Skip to content

Commit 82668e4

Browse files
author
Test User
committed
feat(loop): GitHub issue lifecycle (#73) + optional fix_plan sections (#239)
Issue #73 — GitHub issue lifecycle management (lib/github_lifecycle.sh): - New `ralph --github-issue <ref>` tracking with opt-in lifecycle actions: progress comments (--comment-progress/--comment-interval), completion summary (--close-summary), PR creation linked with "Closes #N" (--create-pr/--link-issue/--draft-pr), grouped follow-up issue from TODO/FIXME markers (--create-followups/--followup-label), and issue close with labels (--auto-close/--add-label). - Uses the `gh` CLI exclusively (not raw REST/GITHUB_TOKEN); state at .ralph/.github_lifecycle_state (atomic temp+mv). Every gh op degrades gracefully — a permission failure is logged and the loop continues. - Wired into ralph_loop.sh: init at startup, progress hook in the loop body, completion workflow on graceful exit. Config via flags or .ralphrc. Issue #239 — Optional/Future sections in fix_plan.md: - `_count_blocking_unchecked()` (awk, section-aware) excludes unchecked items under OPTIONAL_SECTIONS (default "Optional,Future,Future Enhancements,Nice to Have", case-insensitive, configurable) from the plan-complete exit check. Resolves the deadlock where Claude skips low-priority items while Ralph waits. Backward compatible when no optional sections are present. Tests: +29 unit (test_github_lifecycle.bats), +9 (test_exit_detection.bats), +3 (test_cli_modern.bats). Full suite green: 769 unit + 250 integration + 13 e2e. Docs: CLAUDE.md, README.md, templates/fix_plan.md.
1 parent 5dcba17 commit 82668e4

8 files changed

Lines changed: 1246 additions & 5 deletions

File tree

CLAUDE.md

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ Ralph for Claude Code — an autonomous AI development loop system enabling cont
2323
- `--select first|interactive|priority` picks among multiple matches: priority understands bare `P0``P9` and `priority: PN` labels (ties → oldest, none → first); interactive falls back to first on non-TTY/EOF. `--dry-run` previews the match table + would-be selection without importing
2424
- Completeness assessment + plan generation (Issue #70): issues are scored 0–100 via `lib/issue_analyzer.sh`; below `--completeness-threshold` (default 60) an implementation plan is generated via Claude CLI (`--plan-model` passthrough) and appended to the PRD before conversion, plus saved to `.ralph/specs/implementation-plan.md`. Flags: `--generate-plan` (force), `--no-generate-plan` (fail if below threshold), `--plan-model <model>`, `--completeness-threshold <0-100>`, `--auto-approve` (skip the approval prompt; non-TTY sessions auto-accept)
2525
- **ralph_queue.sh**`ralph-queue` command: batch processing and issue queue management (Issue #72). Builds a persistent queue at `.ralph/queue.json` of GitHub issues (reuses `ralph_import.sh`'s `gh` machinery: `resolve_github_issue_candidates`, `fetch_github_issue`, `format_issue_as_prd`) or local PRD specs. Subcommands: `add` (`--github-issues N,N` | filter flags | `--prd <file>`), `status [--json]`, `next`, `remove`, `clear`, `reorder`, `validate`, `process [--halt-on-failure]`, `resume`. The sequential processor stages `.ralph/` from each ready item (priority + dependency order), runs the loop via `RALPH_LOOP_CMD` (default `ralph_loop.sh`; overridable for tests), commits `Fix #N: <title>` per issue, skips failures (or halts), and writes `.ralph/logs/queue_processing.log`. Single branch, no concurrency. See [docs/QUEUE_MANAGEMENT.md](docs/QUEUE_MANAGEMENT.md)
26+
- **GitHub issue lifecycle** (Issue #73): when `ralph` is run with `--github-issue <ref>`, it tracks the issue across the loop via `lib/github_lifecycle.sh`. During development it can post progress comments every N loops (`--comment-progress`, `--comment-interval`); on graceful completion it runs a completion workflow — summary comment (`--close-summary`), PR creation linked with `Closes #N` (`--create-pr --link-issue`, optional `--draft-pr`), grouped follow-up issue from TODO/FIXME markers added during dev (`--create-followups --followup-label`), and issue close with optional labels (`--auto-close --add-label`). All steps are opt-in and degrade gracefully (a gh permission failure is logged and the loop continues). State lives in `.ralph/.github_lifecycle_state`. Uses the `gh` CLI exclusively (not raw REST/`GITHUB_TOKEN`)
2627
- **ralph_enable.sh** — interactive wizard enabling Ralph in existing projects (environment detection, task source selection, generates `.ralphrc`)
2728
- **ralph_enable_ci.sh** — non-interactive version for CI/automation; `--json` output mode; exit codes: 0 (success), 1 (error), 2 (already enabled)
2829

@@ -38,6 +39,7 @@ Ralph for Claude Code — an autonomous AI development loop system enabling cont
3839
- **issue_analyzer.sh**`assess_issue_completeness()`: deterministic 0–100 heuristic scoring of issue PRDs (acceptance criteria +25, checklists/code blocks/sections/keywords/length +15 each); JSON output with `confidence_score`, `completeness_level`, `missing_elements`, `recommendation`; `log_issue_analysis()` for summaries
3940
- **file_protection.sh**`validate_ralph_integrity()` checks `RALPH_REQUIRED_PATHS` exist; runs every loop iteration; `get_integrity_report()` for recovery instructions
4041
- **log_utils.sh**`rotate_logs()` rotates `$LOG_DIR/ralph.log` at 10MB, keeping 4 archives (`.log.1``.log.4`); GNU `stat -c%s` with BSD `stat -f%z` fallback
42+
- **github_lifecycle.sh** — GitHub issue lifecycle management backing `ralph --github-issue` (Issue #73). `parse_issue_reference` (N | #N | owner/repo#N | URL → number+repo); gh wrappers `gh_issue_comment`/`gh_close_issue`/`gh_add_labels`/`gh_create_pr`/`gh_create_issue` (each logs + returns non-zero on failure, never exits); state primitives `init_github_lifecycle`/`lifecycle_get`/`_lifecycle_apply` (atomic temp+`mv` at `.ralph/.github_lifecycle_state`, program-first signature like `_queue_apply`); generators `generate_progress_comment`/`generate_completion_summary`/`scan_for_todos`; orchestration `lifecycle_post_progress <loop>` (interval-gated) and `lifecycle_on_completion` (summary → PR → followups → close, each flag-guarded, always returns 0). Reuses `lib/date_utils.sh` timestamps
4143
- **queue_manager.sh** — queue state primitives backing `ralph-queue` (Issue #72). State at `.ralph/queue.json` (`{version, created_at, updated_at, repository, queue:[…]}`); entries carry `id`/`source` (`github`|`prd`)/`issue_number`/`path`/`title`/`priority`/`labels`/`milestone`/`dependencies`/`status`/timestamps. Functions: `init_queue`, `add_to_queue` (dedupe by id, fills defaults; rc 0/1/2), `remove_from_queue`, `clear_queue`, `mark_issue_status` (validates status, stamps started/completed), `get_queue_status` (counts JSON), `sort_queue_by_priority` (rank then FIFO), `get_priority_from_labels` (reuses the P0–P9 / `priority: PN` parser), `parse_issue_dependencies` (`depends on/blocked by/requires #N`), `is_dependency_satisfied`, `get_next_issue` (ready+priority+FIFO), `validate_dependencies` (jq cycle detection). All mutations are atomic temp-file+`mv` via `_queue_apply`
4244

4345
## Key Commands
@@ -83,6 +85,24 @@ ralph --rollback # List available backup branches
8385
ralph --rollback ralph-backup-loop-3-1775155286 # Roll back to a specific backup
8486
```
8587

88+
### GitHub Issue Lifecycle (Issue #73)
89+
```bash
90+
# Track an issue and post progress comments every 5 loops
91+
ralph --github-issue 69 --comment-progress --comment-interval 5
92+
93+
# On completion: open a PR that closes the issue, then close it with a summary
94+
ralph --github-issue 69 --create-pr --link-issue --close-summary --auto-close
95+
96+
# Add labels on close and open a follow-up issue for any TODO/FIXME left behind
97+
ralph --github-issue owner/repo#69 --auto-close --add-label completed \
98+
--create-followups --followup-label tech-debt
99+
100+
# Draft PR for manual review before merge
101+
ralph --github-issue 69 --create-pr --draft-pr
102+
```
103+
All lifecycle flags are opt-in and require `--github-issue`. Each GitHub operation
104+
degrades gracefully — a permission failure is logged and the loop continues.
105+
86106
### Batch Processing / Issue Queue (Issue #72)
87107
```bash
88108
# Build a queue (GitHub issues or local PRDs)
@@ -178,7 +198,7 @@ Exit requires BOTH conditions (dual-condition check prevents premature exits):
178198
- `MAX_CONSECUTIVE_DONE_SIGNALS=2` — repeated "done" signals from Claude
179199
- `MAX_CONSECUTIVE_TEST_LOOPS=3` — too many test-only iterations (feature completeness)
180200
- `TEST_PERCENTAGE_THRESHOLD=30%` — flag if testing dominates recent loops
181-
- All items in `.ralph/fix_plan.md` marked complete
201+
- All items in `.ralph/fix_plan.md` marked complete — but unchecked items under **optional sections** are excluded (Issue #239). `_count_blocking_unchecked()` (awk, section-aware) counts only unchecked `- [ ]` items NOT under a heading whose title matches `OPTIONAL_SECTIONS` (default `"Optional,Future,Future Enhancements,Nice to Have"`, case-insensitive, comma-separated, configurable in `.ralphrc`). Optional context persists into deeper subsections and closes at the next same-or-higher-level heading. This resolves the deadlock where Claude treats "Low Priority"/optional items as skippable while Ralph keeps looping for them. With no optional sections present, behavior is identical to the prior full-file count (backward compatible)
182202

183203
**Startup state reset (Issue #194)**: every `ralph` invocation unconditionally resets `.exit_signals` and removes `.response_analysis` before the main loop, so stale completion signals from a prior run (crash, SIGKILL, API-limit exit) can't trigger `should_exit_gracefully()` on the first iteration. The API-limit "user chose exit" path also calls `reset_session()`.
184204

README.md

Lines changed: 60 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -321,11 +321,30 @@ Loop 8: Claude outputs "All tasks complete, project ready"
321321
```
322322

323323
**Other exit conditions:**
324-
- All tasks in `.ralph/fix_plan.md` marked complete
324+
- All tasks in `.ralph/fix_plan.md` marked complete — except unchecked items under **optional sections**
325325
- Multiple consecutive "done" signals from Claude Code
326326
- Too many test-focused loops (indicating feature completeness)
327327
- Claude API 5-hour usage limit reached (with user prompt to wait or exit)
328328

329+
#### Optional / Future sections in fix_plan.md
330+
331+
By default, Ralph keeps looping until **every** `- [ ]` item is checked. To mark work as
332+
genuinely optional so it does not block completion, put it under an optional section:
333+
334+
```markdown
335+
## High Priority
336+
- [x] Core feature
337+
338+
## Optional
339+
- [ ] Frontend integration # does NOT block exit
340+
- [ ] SMS notifications # does NOT block exit
341+
```
342+
343+
Unchecked items under `Optional`, `Future`, `Future Enhancements`, or `Nice to Have` headings
344+
(and their subsections) are ignored by the completion check. Customize the section names with
345+
`OPTIONAL_SECTIONS` in `.ralphrc` (comma-separated, case-insensitive). This resolves the
346+
deadlock where Claude treats low-priority items as skippable while Ralph waits for them.
347+
329348
## Enabling Ralph in Existing Projects
330349

331350
The `ralph-enable` command provides an interactive wizard for adding Ralph to existing projects:
@@ -486,6 +505,46 @@ Generated plans are shown for approval before conversion. Non-interactive sessio
486505
- **"GitHub CLI (gh) is not installed"** — install it from https://cli.github.com
487506
- **"GitHub CLI is not authenticated"** — run `gh auth login`
488507

508+
## GitHub Issue Lifecycle
509+
510+
Once development is underway, Ralph can close the loop on the whole GitHub workflow. Pass
511+
`--github-issue <ref>` (a number `69`, `#69`, `owner/repo#69`, or a full issue URL) to `ralph`
512+
and opt into any of the lifecycle actions below. They all use the `gh` CLI (so the same
513+
`gh auth login` prerequisite applies), and every GitHub operation degrades gracefully — if a
514+
call is denied, Ralph logs a warning and keeps developing rather than crashing the loop.
515+
516+
```bash
517+
# Post a progress comment to the issue every 5 loops while developing
518+
ralph --github-issue 69 --comment-progress --comment-interval 5
519+
520+
# On completion: open a PR linked to the issue, comment a summary, and close it
521+
ralph --github-issue 69 --create-pr --link-issue --close-summary --auto-close
522+
523+
# Add labels when closing, and open a follow-up issue for any TODO/FIXME left in the diff
524+
ralph --github-issue 69 --auto-close --add-label completed \
525+
--create-followups --followup-label tech-debt
526+
527+
# Open the PR as a draft for manual review before merge
528+
ralph --github-issue 69 --create-pr --draft-pr
529+
```
530+
531+
| Flag | Effect |
532+
|------|--------|
533+
| `--github-issue REF` | Track the issue (required for all lifecycle features) |
534+
| `--comment-progress` | Post progress comments during development |
535+
| `--comment-interval N` | Comment every N loops (default: 5) |
536+
| `--auto-close` | Close the issue on graceful completion |
537+
| `--close-summary` | Post a completion summary comment |
538+
| `--create-pr` | Create a pull request on completion |
539+
| `--link-issue` | Add `Closes #N` to the PR body |
540+
| `--draft-pr` | Create the PR as a draft |
541+
| `--create-followups` | Open a grouped follow-up issue for TODO/FIXME markers added during dev |
542+
| `--followup-label LABEL` | Label for follow-up issues (default: `tech-debt`) |
543+
| `--add-label LABEL` | Label to add on close (repeatable) |
544+
545+
These can also be set in `.ralphrc` (`COMMENT_PROGRESS`, `AUTO_CLOSE`, `CREATE_PR`, etc.).
546+
Lifecycle state is tracked in `.ralph/.github_lifecycle_state`.
547+
489548
## Batch Processing and Issue Queue
490549

491550
For larger efforts, the `ralph-queue` command builds a persistent queue of work items (GitHub issues or local PRD specs) and processes them sequentially, respecting priority and dependencies. The queue is stored at `.ralph/queue.json` and survives restarts, so an interrupted run can be resumed. See [docs/QUEUE_MANAGEMENT.md](docs/QUEUE_MANAGEMENT.md) for the full guide.

0 commit comments

Comments
 (0)