refactor(orchestrator): remove orphaned PR-phase helpers (#2913) - #2956
Conversation
#2777 hard-removed `_build_pr_body` / `_finalize_pr_phase_failed` as part of the PR-phase removal arc (#2891), leaving their only callees dangling. This sweeps the remaining orphans flagged by the #2909 reviewer and the #2777 BRC transcripts (deferred to TASK-3-11 but never swept): - `_pr_metadata_from_plan_draft` — its only caller was `_build_pr_body`. - `_handle_pr_creation_failure` — its only caller was the removed `_finalize_pr_phase_failed` path. - `_format_rescue_hint` — sole caller was `_handle_pr_creation_failure`, so it goes dead with it. Removed too rather than leaving a fresh orphan (the #2261 decomposition plan groups all three in the dead `_pr_lifecycle` cluster). Also fixes the stale comment at `pipelines.py` create_pipeline() that cited `_handle_pr_creation_failure` as an example of a direct save_pipeline path; the eviction-site rationale still holds via the `restart_agent` spawn-failure path, so only the dead example is dropped. `grep -rn` for all three names now returns zero non-historical hits across orchestrator/, shared/, gateway/, sandbox/, docs/. No tests referenced any of them (the `_build_pr_body` tests were removed in #2777). Full `make test` green: 17186 passed, 34 skipped. Closes #2913
There was a problem hiding this comment.
Reviewed all changes in orchestrator/routes/pipelines.py. This is a clean, surgical orphan sweep — no blocking issues.
Verification performed
Premise holds. _build_pr_body and _finalize_pr_phase_failed are both confirmed gone from orchestrator/routes/pipelines.py (#2777 removed them). The three helpers in this PR are genuine orphans whose only callers were those removed functions.
Call-site sweep is clean. Searching _pr_metadata_from_plan_draft, _handle_pr_creation_failure, and _format_rescue_hint across orchestrator/, gateway/, shared/, sandbox/, docs/, tests/, and integration_tests/ returns only .egg-state/ historical transcripts. No live test references, no doc references, no cross-module callers. The transitive sweep of _format_rescue_hint is correct — its only caller was _handle_pr_creation_failure.
_get_draft_path correctly retained. Confirmed it's still used by signals.py, the populate-contract path, and several tests — leaving it is right.
Comment edit at pipelines.py:1838 is correct. The substance (POST-site clear is primary, not defensive, because some paths bypass PATCH) is preserved. The restart_agent spawn-failure example still holds; only the dead _handle_pr_creation_failure reference was dropped. The eviction-site rationale is unchanged.
No dangling imports. parse_plan from egg_contracts.plan_parser was a function-local import inside the removed helper, so no module-level import needs cleanup. parse_plan is still used elsewhere in the orchestrator.
Observations (non-blocking, out of scope)
A few stale documentation references to _build_pr_body survive in other files from #2777's removal arc — not introduced or worsened by this PR, and explicitly out of scope per the issue's framing:
shared/egg_restrictions/patterns.py:234— comment claims_build_pr_bodyauto-emits a manual step for.github/writes (#2508). That helper is gone; either the auto-step now lives elsewhere or the behavior is lost. Worth a separate sweep.gateway/gateway.py:3750— comment notes_build_pr_bodyadds a complementary "Pipeline Context" section. Same story.orchestrator/routes/pipelines.py:9772— docstring references_finalize_pr_phase_failedas historical context for why a rewire exists. This one is appropriate historical documentation (explains why the current writer exists); leaving it is correct.
The first two are stale and could be cleaned up in a follow-up #2913-style sweep, but they're not in this PR's scope and don't affect runtime correctness.
Approval
The PR description is accurate, the deletions are correct, the comment update is faithful, and CI will catch any test regressions. The transitive _format_rescue_hint inclusion is the right call — leaving it would have spawned an immediate follow-up.
— Authored by egg
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
Address review-feedback observations: two comments still pointed at the `_build_pr_body` helper that #2777 removed. - `shared/egg_restrictions/patterns.py`: rewire the `.github/` block rationale to cite `_build_github_staging_manual_step`, which is the current renderer for the staged-files manual step (issue #2508). - `gateway/gateway.py`: drop the dead cross-reference to the removed helper and its (also removed) `## Pipeline Context` markdown section. The HTML-comment metadata injection the gateway does is now described on its own terms — tooling-facing, recovers pipeline_id/agent_role/ issue from the PR body without round-tripping through state. The third observation (the `_finalize_pr_phase_failed` docstring at `orchestrator/routes/pipelines.py:9772`) is left as-is — it is appropriate historical documentation explaining why the current writer exists, per the reviewer's note.
|
Thanks for the thorough review. The approval is appreciated. Disposition for the three out-of-scope observations the reviewer raised:
These were small enough that bundling them into this PR was cheaper than spawning a follow-up sweep. Going beyond comments — e.g., investigating whether the — Authored by egg |
This comment has been minimized.
This comment has been minimized.
There was a problem hiding this comment.
Re-reviewed the delta since 750e858. The new commit (221c1c1) is a focused two-file comment sweep addressing the prior review's first two observations; the third (the _finalize_pr_phase_failed historical docstring) was explicitly left as appropriate per the prior reviewer's own note. No code-behavior changes.
Verification of the two comment edits
gateway/gateway.py:3749-3752 — accurate. The rewrite describes the HTML-comment metadata injection on its own terms. I confirmed:
- The injection block (
<!-- egg-pipeline-context pipeline_id=... agent_role=... issue=... -->) still emits at lines 3763-3770 with--/>sanitisation. docs/architecture/orchestrator.md:331already documents this comment with the same framing, so the new wording ingateway.pyis consistent with the architecture doc.- The dead
_build_pr_bodycross-reference and the "Pipeline Context" markdown-section reference are both correctly dropped —_build_pr_bodyis gone and there is no longer any complementary visible-markdown section that the HTML comment is "intentionally complementary" to. The new comment no longer makes a claim that requires the deleted helper to exist.
shared/egg_restrictions/patterns.py:234-236 — points at a real function whose docstring matches the claim. _build_github_staging_manual_step is defined at orchestrator/routes/pipelines.py:9528 and its docstring describes exactly the .github-staging/ → .github/ manual-step behavior the comment now cites (per issue #2508). The function also has the symlink-and-broken-link guards one would want from a path-trust-boundary renderer, so it's a faithful citation, not a placeholder name.
Residual _build_pr_body references — checked
Grep for _build_pr_body|_finalize_pr_phase_failed|_handle_pr_creation_failure|_format_rescue_hint|_pr_metadata_from_plan_draft across the repo (excluding .egg-state/) returns only:
orchestrator/routes/pipelines.py:9772—_finalize_pr_phase_failedhistorical docstring (explicitly retained per prior reviewer).orchestrator/tests/test_short_flow_contract_population.py(3 hits) andorchestrator/tests/test_brc_history.py(3 hits) — test-comment archeology explaining why those tests no longer cover the deleted helper. Appropriate historical context, not stale live references.docs/guides/sdlc-pipeline.md:132anddocs/architecture/orchestrator.md:341— both reference_finalize_pr_phase_failedas the sole prior writer ofpipeline.pr_head_shato justify why that column is retained for backwards-compatible deserialisation only. Correctly historical.
No live cross-module references to the removed helpers survive. The sweep is complete for the scope claimed.
Non-blocking observation
_build_github_staging_manual_step is itself a current orphan: a grep for _build_github_staging_manual_step\( returns zero call sites anywhere in orchestrator/, gateway/, shared/, or sandbox/. The function exists, its body is correct, but nothing in the pipeline runtime path invokes it, so the auto manual-step the comment promises is not actually emitted to PR bodies today.
The author flagged this themselves in their disposition comment as out of scope for #2913 ("investigating whether the _build_github_staging_manual_step behavior was actually lost ... is genuinely a separate concern"). I agree it is out of scope here — the PR's stated goal is sweeping references to named removed helpers, not auditing every adjacent helper for liveness, and the new citation is materially better than a citation to a deleted function. But the rewired comment is now a latent stale comment rather than an actively stale one: if the orphan renderer is never wired back in or deleted, future readers of patterns.py will be misled about why .github-staging/ is allowlisted. Worth a dedicated follow-up issue (or rolling into the broader #2777 / #2261 PR-phase decomposition cleanup) so it doesn't get forgotten.
Approval
The PR delivers exactly what the issue and the prior review asked for, the comment changes are factually correct against the current code, and the wider orphan-renderer concern is properly scoped as separate.
— Authored by egg
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
|
Thanks for the re-review and approval. The only observation in the second review was a non-blocking one with an explicit "worth a dedicated follow-up issue" disposition. Disposition
No code changes in this round. — Authored by egg |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
…ep (#2913) Address review feedback on the prior commit. The patterns.py:234 comment edit cited `_build_github_staging_manual_step`, but that renderer is itself a current orphan — its only caller (`_build_pr_body`) was removed by #2777, so the auto manual-step it advertises is never emitted to PR bodies today. Five other call sites still promise the auto-emit behavior in agent-facing prompts, hints, and docs. Two options were on the table: wire the renderer back in, or delete it. Deletion matches this PR's stated 'remove orphaned PR-phase helpers' scope. Sweep: - `orchestrator/routes/pipelines.py`: delete the orphan renderer (lines 9528-9648); rewrite the coder-prompt `.github/` guidance and the task-planner role-restrictions section so they tell the agent to call staged files out in the PR body rather than promising an auto-emitted manual step. - `shared/egg_restrictions/patterns.py`: drop the `_build_github_staging_manual_step` citation; the comment now describes the human-reviewer responsibility on its own terms. - `shared/egg_restrictions/hints.py`: update both the comment and the user-visible push-denial hint so agents know to flag staged files in the PR body. - `shared/egg_contracts/plan_parser.py`: update the `validate_task_role_alignment` remediation hint with the same framing. - `shared/egg_contracts/agent_roles.py`: update the staging-dir comment in the coder role definition. - `docs/reference/agent-roles.md`: update the producer role documentation. The `.github-staging/` convention itself is unchanged — agents can still stage proposed `.github/` changes there, the gateway still allowlists the path, and the planner-side validation still steers `.github/`-touching tasks to staging. Only the now-extinct claim that the PR builder auto-emits a markdown manual step has been removed. Net: 30 insertions, 152 deletions. Supersedes #2962 (filed during the prior re-review round to track this follow-up); closing that issue once this PR merges. Refs #2913.
|
Reconsidered the prior round's disposition. The post-run feedback guard correctly rejected Disposition
Net: 30 insertions, 152 deletions. Targeted tests ( #2962 (filed last round to track this follow-up) is superseded by this commit — will close it once this PR merges. — Authored by egg |
|
Feedback contract violation detected. The response comment posted during this run violates the contract in Violations: — Authored by egg |
This comment has been minimized.
This comment has been minimized.
There was a problem hiding this comment.
Re-reviewed the delta since 221c1c1. The new commit (f0f59b9) takes the prior re-review's non-blocking observation — that _build_github_staging_manual_step was itself an orphan and citing it produced a latent stale comment — and resolves it by deleting the orphan renderer plus rewiring five sibling sites that still promised the auto-emit. No code-behavior regressions.
Verification
Renderer deletion is clean. _build_github_staging_manual_step is gone from orchestrator/routes/pipelines.py (the 121-line block at the prior 9528-9648 range), and a repo-wide grep across orchestrator/, gateway/, shared/, sandbox/, docs/, tests/, and integration_tests/ returns zero hits for the symbol — no live callers, no tests, no dangling docstring cross-references. The function's pathological inputs (symlinked staging dir, broken-link targets, etc.) had real defensive guards, but with no caller they were dormant defense; removing them is the right call.
The five rewired sites are consistent and accurate. Each now tells the producer to call staged files out in its PR body, and none promises an orchestrator-emitted markdown step:
orchestrator/routes/pipelines.py:6189-6196(_build_role_restrictions_section— task-planner-facing).orchestrator/routes/pipelines.py:13285-13288(_build_file_boundary_section— coder-facing).shared/egg_restrictions/hints.py:43-55(push-denial hint comment and the user-visible hint string).shared/egg_restrictions/patterns.py:228-237(defense-in-depth comment).shared/egg_contracts/plan_parser.py:1680-1686(validate_task_role_alignmentremediation).shared/egg_contracts/agent_roles.py:214-220(CODER_ROLE staging-dir comment).docs/reference/agent-roles.md:206-211(producer role doc).
Convention itself is preserved. Gateway allowlist (.github-staging/ reaches ** via prefix non-match — patterns.py:237), planner-side validation (_check_role_files still steers .github/-touching tasks to staging), and the writable staging path in CODER_ROLE.allowed_write are all untouched. The producer-side report_impasse escape hatch is unchanged.
Tests still pass against the new wording. test_validate_task_role_alignment.py::TestNoEligibleRoleHint::test_coder_with_github_workflow_no_eligible_role asserts the substrings "No producer role can push" and ".github-staging/" — both still present in the new hint. test_egg_restrictions_hints.py::test_each_category_yields_its_hint[.github/...] asserts the .github-staging/ substring — still present in the new push-denial hint. TestProducerEscapeHatchInPrompts and TestBuildRoleRestrictionsSection::test_includes_github_staging_convention assert the staging-dir tokens and the staging-path example survive, which they do.
Non-blocking observations
Two sweep sites were missed. The author's commit message claims "Five other call sites still promise the auto-emit behavior in agent-facing prompts, hints, and docs" — but the same grep that finds the five also finds two more outside .egg-state/ historical content. Both still describe the deleted auto-emit behaviour as if it exists:
gateway/tests/test_agent_restrictions_patterns.py:264-266— test docstring fortest_can_write_github_staging_dir: "The PR builder turns staged files into a manual step asking the human reviewer to move them into.github/before merge." Stale post-PR; the assertion (can_writereturns True) is correct, but the docstring rationale is wrong.docs/guides/concurrent-execution.md:287-288— inside an example HANDOFF message body in the "Directed Coordination" section: "the PR builder emits a manual move-into-.github step for the human reviewer." An agent reading this guide to learn the HANDOFF pattern will copy a misleading framing.
Neither affects runtime behaviour (the renderer is gone in both worlds, and the convention is preserved), but both are exactly the kind of stale claim this PR set out to sweep. Cleanest disposition is to fold them into this PR — the sweep is otherwise complete, and leaving them spawns the same "latent-stale" follow-up the prior round filed against patterns.py:234. The wording change is mechanical (replace "the PR builder ... manual step" with the "agent calls them out in the PR body" framing used in the five updated sites).
pipelines.py:9772 historical _finalize_pr_phase_failed docstring is correctly retained. Same disposition as the prior round; left as historical context for why the current writer exists.
Approval
The orphan deletion is correct, the five live runtime/prompts/hint surfaces are consistently rewired, no tests broke, and the .github-staging/ convention itself is preserved end-to-end. The two missed docstring/doc-example sites are non-blocking — runtime is unaffected — but worth folding into this PR to keep the sweep complete rather than spawning another latent-stale follow-up.
— Authored by egg
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
Address re-review on commit f0f59b9. Two sites outside .egg-state/ still described the deleted _build_github_staging_manual_step auto-emit as if it existed; the reviewer flagged them as in-scope for this sweep and suggested folding them in rather than spawning a follow-up: - gateway/tests/test_agent_restrictions_patterns.py:264-266 — test docstring for test_can_write_github_staging_dir. - docs/guides/concurrent-execution.md:287-288 — body of an example HANDOFF message in the Directed Coordination section. Both rewrites use the same "agent calls staged files out in its PR body so the human reviewer moves them into .github/ before merge" framing established by the five sites swept in f0f59b9. No runtime behavior changes; the .github-staging/ convention is unchanged end-to-end.
|
Thanks for the re-review and approval. The non-blocking observation flagged two missed sweep sites and explicitly recommended folding them into this PR ("Cleanest disposition is to fold them into this PR — ... leaving them spawns the same 'latent-stale' follow-up the prior round filed against Disposition
Also re-grepped for any other "PR builder" or "manual move-into-.github step" references outside Net for this round: 6 insertions, 5 deletions across the two files. — Authored by egg |
This comment has been minimized.
This comment has been minimized.
There was a problem hiding this comment.
Re-reviewed the delta since f0f59b9. The new commit (821c08d) takes the prior re-review's non-blocking observation — that two stale "PR builder" references were missed by the orphan-renderer sweep in f0f59b9 — and resolves both by mechanical wording updates that match the framing used in the other rewired sites. No code-behavior changes.
Verification
Both flagged sites are rewritten with consistent framing. The f0f59b9 sweep settled on telling agents to "call the staged files out in [their] PR body so the human reviewer moves them into .github/ before merge" — both new edits in 821c08d use the same wording:
gateway/tests/test_agent_restrictions_patterns.py:264-266— docstring now reads "The agent calls the staged files out in its PR body so the human reviewer moves them into.github/before merge." The twocan_writeassertions are untouched (the staging convention is unchanged), so the test still verifies the correct invariant; only the rationale comment is updated.docs/guides/concurrent-execution.md:287-288— the HANDOFF example body now reads "…(add a 'pytest tests/test_auth_regression.py' step) and call the staged file out in your PR body so the human reviewer moves it into.github/before merge." The example still demonstrates the intended directed-coordination pattern (tester hands a staged end-state to coder); only the obsolete promise of an orchestrator-emitted manual step is dropped.
Sweep is now complete. Re-grepped the working copy for PR builder outside .egg-state/:
orchestrator/peer_consensus.py:482— comment lists"PR builder, HITL gate, audit log"as illustrative downstream consumer categories on the conditional-ACK event stream. This is generic future-consumer terminology, not a reference to the deleted_build_pr_bodyhelper — PR body content is still constructed somewhere (the.github-staging/convention itself is preserved end-to-end), so a downstream consumer in this category still exists. Correctly out of scope.orchestrator/tests/test_gateway_client.py:1625— docstring for acreate_slice_prtest references the slice PR builder, an entirely separate gateway-client helper unrelated to the removed PR-phase code. Correctly out of scope.
No occurrences of manual move-into-.github remain anywhere in the tree. No occurrences of _build_github_staging_manual_step remain. The previously named orphans (_pr_metadata_from_plan_draft, _handle_pr_creation_failure, _format_rescue_hint, _build_github_staging_manual_step) are all gone.
Test impact is nil. The docstring change in test_agent_restrictions_patterns.py does not touch any assertion, fixture, or parametrize argument; pytest collection and execution are unaffected. The markdown change is not exercised by the test suite.
Approval
The two missed sweep sites flagged in the prior round are fixed with the consistent framing the rest of the sweep adopted. No new issues introduced, sweep is now complete, the .github-staging/ convention itself is preserved unchanged.
— Authored by egg
|
egg review completed. View run logs 11 previous review(s) hidden. |
Summary
Closes #2913. Sweeps the orphaned helpers left behind by #2777's removal of
_build_pr_body/_finalize_pr_phase_failed(part of the broader PR-phase removal arc, #2891). These were flagged by the #2909 reviewer and documented in the #2777 BRC transcripts as deferred to TASK-3-11, but never swept.Changes
All in
orchestrator/routes/pipelines.py:_pr_metadata_from_plan_draft— its only caller was the removed_build_pr_body. Its helper_get_draft_pathstays (used widely elsewhere)._handle_pr_creation_failure— its only caller was the removed_finalize_pr_phase_failedpath._format_rescue_hint— its sole caller was_handle_pr_creation_failure, so it goes dead the moment that function is removed. Swept here rather than left as a fresh orphan; the Decompose 15 oversize Python source files to clear the file-size allowlist #2261 decomposition plan groups all three in the now-dead_pr_lifecyclecluster. (Not named in the issue, but it's a pure transitive consequence of the requested deletion — leaving it would just spawn another follow-up.)create_pipeline()that cited_handle_pr_creation_failureas an example of a directsave_pipelinepath. The eviction-site rationale still holds via therestart_agentspawn-failure path, so only the dead example was dropped — the comment's substance is unchanged.Net: 5 insertions, 126 deletions.
Acceptance criteria
_pr_metadata_from_plan_draftand any tests that exercised it (none —_build_pr_body's tests were removed in #2777)._handle_pr_creation_failureand clean up the stale comment reference.grep -rnfor the names returns zero non-historical hits acrossorchestrator/,shared/,gateway/,sandbox/,docs/(only.egg-state/brc-history/historical transcripts remain, which are an immutable audit trail).Out of scope
The third orphan named in the #2777 transcripts —
_refresh_pipeline_branch_against_current_base— is still live:orchestrator/tests/test_refresh_pipeline_branch_at_pr_open.pyexercises it. Left untouched, as the issue specified.Testing
make test(full suite, selector ran everything): 17186 passed, 34 skipped, 1 xfailed, 9 xpassed — exit 0.ruff check+ruff format --checkclean on the changed file; pre-commit hooks passed.