Skip to content

feat(#2306): plan-review-convergence v2 — CYCLE_SUMMARY contract, config gate, local model reviewers#2718

Merged
trek-e merged 4 commits intomainfrom
feat/2306-plan-review-convergence-v2
Apr 25, 2026
Merged

feat(#2306): plan-review-convergence v2 — CYCLE_SUMMARY contract, config gate, local model reviewers#2718
trek-e merged 4 commits intomainfrom
feat/2306-plan-review-convergence-v2

Conversation

@trek-e
Copy link
Copy Markdown
Collaborator

@trek-e trek-e commented Apr 25, 2026

Fix PR

Using the wrong template?
— Enhancement: use enhancement.md
— Feature: use feature.md


Linked Issue

Required. This PR will be auto-closed if no valid issue link is found.

Fixes #2306
Closes #2339

The linked issue must have the confirmed-bug label. If it doesn't, ask a maintainer to confirm the bug before continuing.


What was broken

The plan→review→replan convergence loop had a false-stall detection bug: REVIEWS.md accumulates history across cycles, so a raw grep for HIGH count on cycle 2+ would find resolved HIGHs from prior cycles, inflating the count and triggering spurious stall warnings even when the plan was converging correctly.

Additionally, the workflow.plan_review_convergence feature had no opt-in config gate (it ran unconditionally), and there was no support for local model reviewers (Ollama, LM Studio, llama.cpp).

What this fix does

  • CYCLE_SUMMARY contract: The review agent now emits CYCLE_SUMMARY: current_high=<N> in its return message. The orchestrator parses this per-cycle value instead of grepping the accumulated REVIEWS.md file, eliminating the false-stall inflation.
  • Config gate: Adds workflow.plan_review_convergence (disabled by default, same pattern as workflow.code_review). Command exits with enable instructions when the key is false.
  • Local model reviewers: Adds --ollama, --lm-studio, --llama-cpp flags. All three use the OpenAI-compatible /v1/chat/completions endpoint. Host and model are configurable; host defaults to localhost:11434/1234/8080 respectively.

Root cause

The orchestrator read HIGH count by grepping the REVIEWS.md artifact file rather than receiving it from the review agent directly. Because REVIEWS.md is append-only (prior cycle findings remain as audit trail), the grep count was cumulative across cycles rather than reflecting only the current cycle's unresolved issues.

Testing

How I verified the fix

  • node --test tests/plan-review-convergence.test.cjs — 58/58 pass
  • node --test tests/config-schema-sdk-parity.test.cjs — 2/2 pass
  • node --test tests/config-schema-docs-parity.test.cjs — 1/1 pass (all new schema keys documented)

Regression test added?

  • Yes — added a test that would have caught this bug: "workflow extracts HIGH count from CYCLE_SUMMARY contract, NOT from grepping REVIEWS.md" with inline comment explaining the false-stall mechanism

Platforms tested

  • macOS
  • Windows (including backslash path handling)
  • Linux
  • N/A (workflow markdown + config schema — not platform-specific)

Runtimes tested

  • Claude Code
  • Gemini CLI
  • OpenCode
  • Other: ___
  • N/A (orchestrator/workflow layer — runtime-agnostic)

Checklist

  • Issue linked above with Fixes #NNNPR will be auto-closed if missing
  • Linked issue has the confirmed-bug label
  • Fix is scoped to the reported bug — no unrelated changes included
  • Regression test added (or explained why not)
  • All existing tests pass (npm test)
  • CHANGELOG.md updated if this is a user-facing fix
  • No unnecessary dependencies added

Breaking changes

None — the feature was not previously enabled by default. Users who had manually invoked /gsd-plan-review-convergence will now need to set workflow.plan_review_convergence=true first; the command exits with clear instructions if the gate is not enabled.


Additional scope: local model reviewer support

The local model flags (--ollama, --lm-studio, --llama-cpp) and config keys (review.ollama_host, review.lm_studio_host, review.llama_cpp_host, review.models.ollama, review.models.lm_studio, review.models.llama_cpp) were added as part of the same fix cycle per the issue thread. All three backends use jq --rawfile to safely encode multi-line prompts as JSON before posting to the OpenAI-compatible endpoint.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features
    • Added support for local OpenAI-compatible review backends (Ollama, LM Studio, llama.cpp) alongside existing review options
    • Introduced iterative plan-review-convergence workflow to refine plans through repeated review cycles until HIGH-severity concerns are resolved
    • Added configuration keys for local reviewer host addresses and model selection settings

…fig gate, local model reviewers

Fixes the false-stall detection bug in the plan→review→replan convergence
loop. REVIEWS.md accumulates history across cycles so raw grep inflated
HIGH counts; HIGH count now comes from a per-cycle CYCLE_SUMMARY contract
emitted in the review agent's return message.

Key changes:
- workflow.plan_review_convergence config gate (disabled by default, same
  pattern as workflow.code_review / workflow.nyquist_validation)
- Review agent prompt defines CYCLE_SUMMARY: current_high=<N> contract with
  PARTIALLY RESOLVED / FULLY RESOLVED counting rules
- Orchestrator aborts on absent/malformed CYCLE_SUMMARY (distinguishes both)
- Warns when HIGH_COUNT > 0 but ## Current HIGH Concerns section is missing
- Stall detection and --ws forwarding preserved and tested
- Local model reviewers: --ollama, --lm-studio, --llama-cpp flags added to
  convergence workflow and review workflow; all three use OpenAI-compatible
  /v1/chat/completions endpoint with jq --rawfile for safe JSON encoding
- review.ollama_host / review.lm_studio_host / review.llama_cpp_host config
  keys registered and documented (default to localhost:11434/1234/8080)
- review.models.ollama / .lm_studio / .llama_cpp model-name config support
- 58 tests (up from 29 in PR #2339), all passing

Closes #2306
Closes #2339
Co-authored-by: Tom Boucher <trekkie@nomorestars.com>

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 25, 2026

Warning

Rate limit exceeded

@trek-e has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 5 minutes and 46 seconds before requesting another review.

Your organization is not enrolled in usage-based pricing. Contact your admin to enable usage-based pricing to continue reviews beyond the rate limit, or try again in 5 minutes and 46 seconds.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 92ff35d3-c998-47cb-a1ee-d653b133435a

📥 Commits

Reviewing files that changed from the base of the PR and between 88cd0bc and 4d642bd.

📒 Files selected for processing (1)
  • get-shit-done/workflows/review.md
📝 Walkthrough

Walkthrough

Adds local OpenAI-compatible reviewer backends (Ollama, LM Studio, llama.cpp) to the plan-review-convergence flow, adds a config gate workflow.plan_review_convergence, extends config keys/validation for reviewer hosts/models, replaces grepped HIGH detection with a CYCLE_SUMMARY contract, and updates docs/tests accordingly.

Changes

Cohort / File(s) Summary
Configuration & Schema
get-shit-done/bin/lib/config-schema.cjs, sdk/src/query/config-schema.ts, docs/CONFIGURATION.md
Extended VALID_CONFIG_KEYS and docs with workflow.plan_review_convergence and host keys review.ollama_host, review.lm_studio_host, review.llama_cpp_host; documented local defaults and model config paths.
Workflow Logic
get-shit-done/workflows/plan-review-convergence.md, get-shit-done/workflows/review.md
Convergence workflow now requires/parses a CYCLE_SUMMARY: current_high=<N> contract and ## Current HIGH Concerns; orchestrator enforces/gates on workflow.plan_review_convergence, probes local servers via /v1/models, selects models, posts prompts to /v1/chat/completions, and handles missing/malformed contract cases and warnings.
Command Documentation
commands/gsd/plan-review-convergence.md
Added reviewer selector flags --ollama, --lm-studio, --llama-cpp, documented defaults, model config keys, updated --all semantics, and provided gsd config-set workflow.plan_review_convergence=true enablement example.
Tests
tests/plan-review-convergence.test.cjs
Expanded tests to assert CYCLE_SUMMARY parsing, gate behavior, local-reviewer flag handling, forwarding of {GSD_WS}, warnings for missing sections, and config/docs parity; added negative/malformed-contract cases.

Sequence Diagram(s)

sequenceDiagram
    participant Orchestrator as Orchestrator<br/>(plan-review-convergence)
    participant Config as Config<br/>Store
    participant LocalServer as Local Server<br/>(Ollama/LM Studio/llama.cpp)
    participant ReviewAgent as Review Agent
    participant Output as REVIEWS.md

    Orchestrator->>Config: Read `review.*_host` and model keys
    Config-->>Orchestrator: Host URL(s) & model path(s)
    Orchestrator->>LocalServer: GET /v1/models (probe)
    alt server responds
        LocalServer-->>Orchestrator: Models list
        Orchestrator->>ReviewAgent: Spawn gsd-review with chosen backend & model
        ReviewAgent->>LocalServer: POST /v1/chat/completions (jq-embedded prompt)
        LocalServer-->>ReviewAgent: Completion (includes CYCLE_SUMMARY)
        ReviewAgent->>Output: Write review sections + CYCLE_SUMMARY
        Output-->>Orchestrator: Parsed current_high & concerns
    else server unreachable
        LocalServer-->>Orchestrator: error
        Orchestrator->>Orchestrator: Skip reviewer / emit warning
    end
    Orchestrator->>Orchestrator: Loop/replan until current_high == 0 or max cycles reached
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

  • gsd-build/get-shit-done#2479 — Prior changes to the config-schema allowlist; touches the same VALID_CONFIG_KEYS surface.
  • gsd-build/get-shit-done#2696 — Related config-schema/testing patterns validating runtime acceptance of new config keys.

Suggested labels

size/M, needs-maintainer-review, area: config

Suggested reviewers

  • glittercowboy

Poem

🐰 Whiskers twitch at convergence night,

Ollama, Studio, llama join the fight;
Models probed and CYCLE_SUMMARY sung,
HIGHs counted until no more rung,
Hops of joy — the plans converge right! 🎉

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The PR title 'feat(#2306): plan-review-convergence v2 — CYCLE_SUMMARY contract, config gate, local model reviewers' clearly and specifically summarizes the main changes: fixing the convergence loop via a new contract, adding a config gate, and enabling local model support.
Description check ✅ Passed The PR description uses the correct Fix template, includes all required sections (linked issues, what was broken, what the fix does, root cause, testing, and checklist), with detailed explanations of the bug and its resolution.
Linked Issues check ✅ Passed All coding requirements from #2306 and #2339 are met: CYCLE_SUMMARY contract parsing implemented, config gate added, local model reviewer flags (--ollama, --lm-studio, --llama-cpp) supported, workflows updated, tests pass (58/58), and schema parity verified.
Out of Scope Changes check ✅ Passed All changes directly address the approved scope: fix the false-stall detection bug via contract parsing, add feature gate, enable local model reviewers. No unrelated modifications detected across workflow, schema, config, and test files.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/2306-plan-review-convergence-v2

Comment @coderabbitai help to get the list of available commands and usage tips.

Add workflow.plan_review_convergence, review.ollama_host,
review.lm_studio_host, and review.llama_cpp_host to the SDK-side
TypeScript mirror — required by the CJS↔SDK parity test (#2653).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@github-actions github-actions Bot added size/XL and removed size/XL labels Apr 25, 2026
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (1)
docs/CONFIGURATION.md (1)

198-198: Broaden the convergence description to include local reviewers.

Line 198 currently names only Codex/Gemini/Claude/OpenCode, but this PR also supports Ollama/LM Studio/llama.cpp in the same loop. Updating that sentence would keep behavior docs fully consistent.

📝 Suggested wording tweak
-| `workflow.plan_review_convergence` | boolean | `false` | Enable the `/gsd-plan-review-convergence` command. Disabled by default — the command exits with an enable instruction when this key is `false`. The command automates the manual plan→review→replan loop: it spawns external AI reviewers (Codex, Gemini, Claude, OpenCode), counts unresolved HIGH concerns via the CYCLE_SUMMARY contract, replans with `--reviews` feedback, and repeats until converged or max cycles reached. Enable with `gsd config-set workflow.plan_review_convergence true`. Added in v1.39 |
+| `workflow.plan_review_convergence` | boolean | `false` | Enable the `/gsd-plan-review-convergence` command. Disabled by default — the command exits with an enable instruction when this key is `false`. The command automates the manual plan→review→replan loop: it spawns configured reviewers (Codex, Gemini, Claude, OpenCode, Ollama, LM Studio, llama.cpp), counts unresolved HIGH concerns via the CYCLE_SUMMARY contract, replans with `--reviews` feedback, and repeats until converged or max cycles reached. Enable with `gsd config-set workflow.plan_review_convergence true`. Added in v1.39 |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/CONFIGURATION.md` at line 198, The docs entry for the configuration key
`workflow.plan_review_convergence` lists only external AI reviewers (Codex,
Gemini, Claude, OpenCode) but omits local/embedded reviewers; update the
sentence to also mention Ollama, LM Studio, and llama.cpp (or more generally
"local reviewers") so the description reflects that the convergence loop spawns
both external AI reviewers and local reviewers (Ollama/LM Studio/llama.cpp) when
counting HIGH concerns via the CYCLE_SUMMARY contract and replanning until
convergence or max cycles.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@get-shit-done/workflows/plan-review-convergence.md`:
- Around line 193-194: The HIGH_COUNT extraction can return multiple numbers;
update the extraction of HIGH_COUNT from REVIEW_AGENT_RETURN to perform a single
anchored match (start-of-line) and return only one numeric value (e.g., use a
regex anchored with ^ and a single-match option like grep -m1 or use a PCRE \K
to capture only the digits) so HIGH_COUNT is always a single integer; apply the
same anchored single-match fix to the other occurrences that parse current_high
in this file (the other extraction sites referencing
REVIEW_AGENT_RETURN/current_high).

In `@get-shit-done/workflows/review.md`:
- Line 324: The frontmatter line "reviewers:" currently hardcodes all possible
reviewers but should reflect the actual set used at runtime; update the code
that builds the workflow frontmatter to derive the reviewers list from the same
selected/available reviewer set used by invoke_reviewers (reuse the same
variable/logic instead of a static array), ensuring the generated frontmatter is
populated programmatically with that set so it matches which reviewers (e.g.,
codex, ollama, etc.) are actually enabled for the run.

---

Nitpick comments:
In `@docs/CONFIGURATION.md`:
- Line 198: The docs entry for the configuration key
`workflow.plan_review_convergence` lists only external AI reviewers (Codex,
Gemini, Claude, OpenCode) but omits local/embedded reviewers; update the
sentence to also mention Ollama, LM Studio, and llama.cpp (or more generally
"local reviewers") so the description reflects that the convergence loop spawns
both external AI reviewers and local reviewers (Ollama/LM Studio/llama.cpp) when
counting HIGH concerns via the CYCLE_SUMMARY contract and replanning until
convergence or max cycles.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 40aa6ad9-bbf0-4941-a1f6-f7c42b2ef898

📥 Commits

Reviewing files that changed from the base of the PR and between 3da9420 and 7e427f8.

📒 Files selected for processing (6)
  • commands/gsd/plan-review-convergence.md
  • docs/CONFIGURATION.md
  • get-shit-done/bin/lib/config-schema.cjs
  • get-shit-done/workflows/plan-review-convergence.md
  • get-shit-done/workflows/review.md
  • tests/plan-review-convergence.test.cjs

Comment thread get-shit-done/workflows/plan-review-convergence.md Outdated
Comment thread get-shit-done/workflows/review.md Outdated
- Anchor HIGH_COUNT extraction with head -1 to prevent multi-match when
  agent return message contains multiple CYCLE_SUMMARY lines (e.g. quoted
  back from prompt context)
- Replace hardcoded reviewers list in REVIEWS.md frontmatter template with
  runtime-derived placeholder — the static list did not reflect which
  reviewers were actually invoked
- Broaden workflow.plan_review_convergence docs to include local reviewers
  (Ollama, LM Studio, llama.cpp) alongside cloud reviewers

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@github-actions github-actions Bot added size/XL and removed size/XL labels Apr 25, 2026
The cursor-reviewer.test.cjs (and equivalent per-reviewer tests) assert
that each supported reviewer appears on the reviewers: line — these are
wiring tests that catch when a new reviewer is added to invocation but
not to the REVIEWS.md template. Replacing the list with a placeholder
broke those tests.

Restore the full static list and add an inline comment clarifying that
the actual committed frontmatter should be filtered to only the reviewers
invoked that run — satisfying both the per-reviewer tests and the
CodeRabbit correctness note.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@github-actions github-actions Bot added size/XL and removed size/XL labels Apr 25, 2026
@trek-e trek-e merged commit b401101 into main Apr 25, 2026
12 checks passed
@github-actions github-actions Bot deleted the feat/2306-plan-review-convergence-v2 branch April 25, 2026 18:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat: add gsd:plan-review-convergence command — cross-AI plan convergence loop

1 participant