Repository navigation
Conversation
On the default path a reviewer blocking finding ended the issue immediately: the loop returned FAILED_UNRECOVERABLE and the issue advisor ran in place of a fix iteration. The reviewer uses "blocking" to mean "must be fixed before merge", and the flagged path's synthesizer already treats it as a fix. The default path now does the same, with the blocking findings leading the fix feedback. Block stays reserved for security, crash and data-loss concerns; an issue escalates when the same blocking finding survives the three-iteration stuck window or the iteration budget runs out. Advisor retries no longer share an exhausted iteration counter. Iteration checkpoints are keyed per advisor round (<issue>.r<k>.json; round 0 keeps the bare issue name so in-flight resume is unchanged), a window that runs zero iterations returns FAILED_UNRECOVERABLE instead of a completion, and the last blocking state comes from the recorded iteration history instead of an unbound review variable. Every completed-with-debt outcome records at least one debt item built from the last review's blocking and should-fix findings, and the coding loop's debt is merged with the advisor's rather than overwritten. Split children inherit the parent issue's guidance when the advisor omits it, so a flagged parent's children stay on the flagged path. The same behaviour is mirrored in the Go port, with tests for each case. The two ARCHITECTURE.md sentences that described default-path blocking as a separate terminal outcome now describe the bounded fix pass.
The pipeline already carries per-issue guidance and escalation context, but the prompts dropped most of it. The coder now sees the issue description, the issue advisor's retry context, approach changes and failure diagnosis, upstream debt notes, and needs_new_tests. When needs_new_tests is false it is told to add no test files and to run the build and the existing suite only. The reviewer sees estimated_scope and needs_new_tests. For an issue that needs no new tests it validates that the existing suite still covers the changed behavior and does not require or block on new test coverage. QA sees the sprint planner's testing_guidance. The Go prompt mirrors are updated 1:1 and the coding golden fixtures are regenerated from the Python prompt output. Go tests cover the same rendered fields as the Python tests.
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
What changed
_run_default_pathmapsblocking=truetoaction="fix"instead of"block", and the fix feedback leads with the blocking findings. The default-path stuck window now also counts three fix passes on the same blocking finding.<issue>.r<k>.json; round 0 keeps the bare issue name so in-flight crash resume is unchanged). A window that runs zero iterations returnsFAILED_UNRECOVERABLE. The last blocking state is read from the recorded iteration history instead of an unbound review variable.COMPLETED_WITH_DEBTrecords at least one debt item from the last review's blocking and should-fix findings, and the coding loop's debt is merged with the advisor's instead of overwritten.SplitIssueSpecgets an optionalguidancefield. A child that omits it inherits the parent issue's guidance, so a flagged parent's children stay on the flagged path.description,retry_context,approach_changes,retry_diagnosis,debt_notesandneeds_new_tests. The reviewer prompt rendersestimated_scopeandneeds_new_tests. The QA prompt renderstesting_guidance.go/internal/coding/loop.go,go/internal/coding/artifacts.go, the advisor loop and split gate undergo/internal/dag/,go/internal/schemas/execution.go, and the coder, reviewer and QA builders undergo/internal/prompts/coding/. The coding golden fixtures are regenerated from the Python prompt output.docs/ARCHITECTURE.mdsentences now describe the bounded fix pass and keep the existing meaning of "block": reserved for security, crash and data-loss concerns.Why it changed
blockingas "MUST be fixed before merge", but the default path treated it as a terminal failure after one iteration. In a recorded build, every default-path block was followed by an issue-advisor call in the same iteration, so advisor work stood in for fix passes.COMPLETED_WITH_DEBTwith an empty debt list, while the last review was blocking. The build log hasCoding loop exhausted (non-blocking) ... accepting with debtin the same second as an advisorretry_approach, followed byDebt gate: 1 issues accepted with debt, total debt items: 0.retry_context,approach_changes,retry_diagnosis,debt_notes,estimated_scope,needs_new_testsandtesting_guidance, but the prompts dropped them. That contradicts the architecture document's statement that debt reaches downstream coders and "Nothing is silently dropped".guidance, so a flagged parent's children ran the default path.Validation
make check(pytest pluscompileall) on the branch:2229 passed, 1 skipped.upstream/mainin the same shell:2210 passed, 1 skipped. The branch adds 19 tests and changes no existing test count otherwise.go test ./...undergo/. The changed packages pass. Three unrelated packages fail identically onupstream/mainin the same shell:internal/furrowdisk-budget tests andinternal/roles/planningprovider default, both environment dependent.go test -race ./internal/coding/ ./internal/dag/ ./internal/issue/ ./internal/prompts/coding/ ./internal/schemas/passes.Behavior Impact
This is a default-on bug fix with no flag. The iteration ceiling per issue becomes
(max_advisor_invocations + 1) * max_coding_iterationscoder iterations. With the defaults (max_coding_iterations=5,max_advisor_invocations=2) that is at most 15 coder iterations for one issue, with at most 2 advisor calls. The previous code shared one counter across rounds, so its worst case was 5 coder iterations but a retry could run zero. The new ceiling is still bounded by the two existing config values, and the default-path fix pass makes advisor rounds rarer.Checkpoint names change only for advisor rounds after the first; round 0 keeps the old file name, so crash resume during a run still works.
SplitIssueSpec.guidanceis an optional additive field; no API change.Notes
The prompt text that changed:
Descriptionline; aNew tests neededline forfalse("do NOT create or extend test files for this issue. Run the build and the existing test suite only, and report their results.") and fortrue("add tests only for the behaviors this issue changes."); anUpstream Debt Notesblock; aRetry Context (from Issue Advisor)block with the diagnosis, new approach and approach changes; and the task step "Write or update tests per the Testing Strategy/guidance, unless the issue says no new tests are needed."review_focusand by the issue'sestimated_scope, both provided in the task prompt." plus "When the task prompt says the issue needs no new tests, judge whether the existing suite still covers the behavior this issue changes, and do not require new tests or new test files."Scope and Test Expectations (from sprint planner)block withEstimated scope, andNew tests neededforfalse("do not require new tests and do not block on missing test coverage") andtrue.Testing Guidance (from sprint planner)line.Refs #168, which describes the problem and includes the two reproduction scripts and the production evidence. The alternative of a separate reviewer field for "another coder pass cannot fix this", or keeping a terminal fast-fail for security and data loss, is left for the maintainer to decide. This PR implements the fix pass bounded by the existing stuck window and
max_coding_iterations.The two commits are:
Fix the coding loop's escalation outcomes(loop mapping, stuck window, per-round checkpoints, zero-iteration guard, debt guarantees, split guidance, architecture text).Render carried guidance fields in the coder, reviewer and QA prompts(Python and Go prompt rendering, goldens, tests).