feat(brc): live-backed read_peer_artifact + wrapper sync-to-proposal (#3076) - #3083
Conversation
This comment has been minimized.
This comment has been minimized.
There was a problem hiding this comment.
Reviewed all 30 changed files. CI is green (Lint, Unit Tests, Integration Tests, Security Scan all SUCCESS). The three coherent changes — /brc-transcript route, sandbox handler live merge, wrapper sync-to-proposal — are well-scoped and have strong test coverage (#3076 regression pins, hex-sanitization tests, behavioral merge tests against a real scratch repo).
No blocking issues. A handful of non-blocking observations follow.
Non-blocking suggestions
1. PEP 758 unparenthesized except is hard to read (orchestrator/routes/messages.py:490)
try:
limit = int(request.args.get("limit", str(_BRC_TRANSCRIPT_DEFAULT_LIMIT)))
except ValueError, TypeError:
return _make_error("Invalid limit parameter: must be an integer")This is valid Python 3.14 (PEP 758 lifted the parenthesization requirement, and the project requires ≥3.14 per pyproject.toml). I verified it catches both ValueError and TypeError at runtime in 3.14, so it's functionally fine.
But it has the visual shape of the long-removed Python 2 except E, name: idiom (which meant "catch E and bind to name"). The existing poll_messages at messages.py:306,314 uses the same style — so this PR is internally consistent — but the parenthesized form except (ValueError, TypeError): would still parse identically and be unambiguous to anyone landing on the line from a code-search. Worth standardizing one way or the other in a follow-up. (Tangentially: request.args.get(...) always returns a str or the default str, so TypeError is dead-code branch anyway — int() can only raise ValueError here. Same is true at line 306.)
2. truncated indicator is post-filter only (orchestrator/routes/messages.py:535-537)
messages = message_store.get_messages(pipeline_id, limit=_BRC_TRANSCRIPT_MAX_LIMIT)
records = [m for m in messages if m.message_type in BRC_HISTORY_TYPES and m.phase == phase]
...
truncated = len(records) > limitget_messages(limit=10000) already returns the most-recent 10000 messages, then we filter to phase. If the store holds >10000 messages and earlier-phase BRC records fell off the upstream window, the response will report truncated=False for a transcript that's actually missing the oldest records. The 10000 cap matches _write_brc_history's own limit, so in steady state this is benign, but a long-lived pipeline that doesn't transition phase cleanly could see silent loss. Worth either documenting the assumption in the route docstring ("upstream cap of _BRC_TRANSCRIPT_MAX_LIMIT messages dominates") or surfacing the upstream cap-hit independently.
3. sync_to_proposals creates real merge commits on the reviewer worktree (orchestrator/consensus_wrapper.py:514)
if git -C "$repo" merge --no-edit "$sha" >/dev/null 2>&1; then
cw_log "sync-to-proposal: merged proposal commit $sha into the worktree."git merge --no-edit produces a real merge commit (or fast-forwards). Two side effects worth a quick comment in the function header:
- Dual-role agents (e.g.
testeracting as producer-then-reviewer-then-producer): a subsequent producer turn will commit on top of the merged ancestry containing peer proposal commits. The producer arm intentionally skips the sync (R11a), but it doesn't un-merge prior reviewer-arm syncs. - Multiple producers in one event: if reviewer is reviewing both
coderandtesterproposals in the same event, both SHAs are merged sequentially. A conflict between them aborts the second merge but leaves the first merge intact on HEAD.
Neither is wrong — and the per-event-prompt git show <sha>:<path> fallback covers the failure path — but the docstring's "merge each pending producer's proposed commit into this reviewer's worktree" reads as a transient enrichment when it's actually a durable HEAD mutation. A one-liner noting "HEAD advances to a merge commit; not reset between events" would set the right expectation.
4. disk_ids only collects string-typed ids (sandbox/egg_agent_tools/handlers/brc.py:1242-1244)
disk_ids: set[str] = {
rec["id"] for rec in records if isinstance(rec, dict) and isinstance(rec.get("id"), str)
}A disk record with a non-string id (or a null / missing one) won't dedup against a live record with the same value. Practically Message.to_dict() always emits a string id, so the live side is well-typed. The defensive isinstance gate is fine; just noting that the dedup is silently weakened for malformed historic data rather than raising. Probably the intended behavior.
5. Artifact paths interpolated unescaped into markdown code spans (orchestrator/routes/event_prompt.py:732,742)
show_cmds = "\n".join(f"- `git show {proposal_sha}:{a}`" for a in artifacts)
...
f"- `git log {proposal_sha} --not origin/{base_branch} -p`\n\n"proposal_sha is hex-validated, but a (artifact path) flows from snapshot.get("artifacts") without escaping. A producer-supplied path containing a backtick would break the markdown code span. Not a shell-injection vector (the agent is the consumer, not bash), and producers are trusted, but a defensive a.replace("", "")` (or rejecting at the producer-side schema) is the easy belt-and-braces.
What I verified positively
- Hex validation is consistently applied at three boundaries: writer (
ProposalPayload.validate_commit_sha_format), reader (_extract_proposal_sha_for_producer), and the wrapper's bash extractor. Sentinels likeRECONSTRUCTED_NO_SHAround-trip the writer permissively and are dropped at the hex-only boundaries — that's the right asymmetry. - Delphi redaction on
/brc-transcriptreuses_apply_delphi_filter(the same functionpoll_messagesuses), so the live route is not a blinding bypass. Thetest_delphi_redaction_appliestest pins this. _BRC_TRANSCRIPT_PHASESinroutes/messages.py:405and_VALID_PHASESinhandlers/brc.py:901agree on{"refine", "plan", "implement", "pr"}._fetch_live_brc_transcriptcorrectly short-circuits whenEGG_PIPELINE_IDis unset — no spurious HTTP. The route is reachable only via the gateway-routedorchestrator_requesthelper, same auth surface as other signal calls.- The
proposearm inconsensus_wrapper.py:740is correctly excluded from sync (onlyack|nacktrigger it). Producers don't get peer commits jammed into their worktrees. merge --abort || truecorrectly handles the no-merge-in-progress case (e.g. dirty-tree refusal).- The first-review fallback delta entry is now emitted even when
artifactsis empty (if not artifacts and not proposal_sha: continue— theandis the fix that prevents the producer from being silently dropped when only the SHA is known).
— Authored by egg
This comment has been minimized.
This comment has been minimized.
Conflict Resolution SummaryResolved merge conflicts with
Verification: Please review: The semantic resolution in — Authored by egg |
This comment has been minimized.
This comment has been minimized.
…(#3076) Phase-1 remainder of #3076 (per #3077 'served, not replicated'): - New GET /api/v1/pipelines/<pid>/brc-transcript serves the in-flight phase's BRC records straight from the orchestrator message store (which holds exactly the current phase — it is cleared on phase transitions). Applies the same Delphi redaction as poll_messages so the route is not a blinding bypass; mirrors _write_brc_history's per-slice attribution for implement-phase reads. - read_peer_artifact now merges that live source with the on-disk brc-history files (completed phases), dedup'd by message id, and reports a 'live' flag. Empty results distinguish 'live store reachable, peers genuinely have not proposed' from 'live source unavailable, emptiness is structural' in the hint. - The event-pump wrapper now syncs the reviewer worktree to each pending proposal SHA (hex-validated, fail-soft merge with abort on conflict) before ack/nack invocations — deterministic bash replacing the fetch/merge prose that lived in spawn prompts the event pump discards (#3033). Reviewers that must RUN the proposal (tester) get a real checkout; git-show reads (#3078) remain the fallback.
90bee25 to
1c06e86
Compare
There was a problem hiding this comment.
Re-reviewed at 1c06e8676496634279566555829426da5a60f05a (rebased onto current main, conflicts resolved against #3078 which landed an updated version of this PR's own review fixes).
Delta since previous review (c639281c)
The three coherent PR changes — /brc-transcript route, sandbox handler live+disk merge, wrapper sync-to-proposal — are byte-identical to the previous review. Only the rebase-time deltas are new:
docs/reference/agent-tools.md— replaced a Khan-internal PR link with a generic phrasing. Documentation-only, no behavior change.orchestrator/consensus_wrapper.py— bothbuild_event_pump_wrapped_commandandbuild_consensus_wrapped_commandnow accept an optionaleffort: str | None. When set, it threads through as--effort <value>in the agent prefix; whenNone, the flag is omitted entirely (preserving Claude Code's per-model default). This came in via the rebase; both call sites (concurrent_executor.py:467,routes/pipelines.py:2948) passeffort=decision.effortfromAgentModelDecision.orchestrator/tests/test_consensus_wrapper.py—TestEffortFlag(two tests covering presence/absence) plus the carry-through of this PR'sTestSyncToProposalsclass. The conflict resolution comment confirms both classes coexist; I verified both are present at lines 1302 and 1322.
Conflict-resolution audit
I cross-checked each kept-side decision against the live file state:
sandbox/egg_agent_tools/handlers/brc.py— kept HEAD._fetch_live_brc_transcript+ themerged = disk + liveflow is intact;any_existedfrom main is properly gone (it would have suppressed the live-only case the PR is built to fix).sandbox/egg_agent_tools/tools/brc.py— kept HEAD's updated tool description describing the live+disk merge and the newlivefield.docs/reference/agent-tools.md— kept HEAD's updatedmcp__brc__read_peer_artifactrow describing the merged behavior.orchestrator/attestation_schemas.py/orchestrator/routes/event_prompt.py— kept main's additive docstring paragraphs; no PR-scope code change.
No semantic loss from the merge.
New-delta review
effortplumbing inconsensus_wrapper.pyis clean: parts are joined viashlex.quote, so an effort string with special chars cannot break the bash. In practiceAgentModelDecision.effortisNonefor everything except fable-routed decisions (currently a fixedFABLE_EFFORTconstant), so the producer-supplied surface is empty.- The two
TestEffortFlagtests verify the right invariants:"--effort high"literal appears formodel="fable", effort="high", and"--effort"is absent wheneffort=None. The thin-pass-through nature ofbuild_consensus_wrapped_commandis exercised correctly.
Previously raised non-blocking suggestions
Still applicable; none are addressed in this delta (they weren't requested as conditions and remain non-blocking):
except ValueError, TypeError:atmessages.py:490reads as the Python-2except E, name:idiom even though PEP 758 makes it valid 3.14 syntax. Internally consistent withpoll_messagesmessages.py:306,314. Worth standardizing on parenthesized form in a follow-up.truncatedindicator atmessages.py:535-537is post-filter only — if the upstreamget_messages(limit=10000)cap is hit, the route will reporttruncated=Falsefor a transcript that lost the oldest records. Steady-state benign (writer uses the same 10000 cap atpipelines.py:8922); document or surface the upstream cap-hit independently.sync_to_proposalsproduces real merge commits (not transient enrichment); a docstring note that HEAD advances and is not reset between events would set the right expectation. The R11a propose-arm-skip is correctly enforced; tester dual-role producer turns commit on top of the merged ancestry.disk_idsdedup atbrc.py:1242only collects string ids; a non-stringidon disk silently weakens dedup. In practiceMessage.to_dict()always emits a string, so this only affects malformed historic data.- Artifact paths interpolated unescaped into markdown code spans at
event_prompt.py:732,742— producer trusted, but defensive backtick-stripping is the easy belt-and-braces.
Positive verification (carried over)
- Delphi redaction on
/brc-transcriptreuses_apply_delphi_filter— verified bytest_delphi_redaction_applies. Not a blinding bypass. - Hex validation at three boundaries (writer
ProposalPayload.validate_commit_sha_format, reader_extract_proposal_sha_for_producer, wrapper bash extractor) —RECONSTRUCTED_NO_SHAsentinel is correctly dropped at the hex-only boundaries. _BRC_TRANSCRIPT_PHASESinroutes/messages.py:405and_VALID_PHASESinhandlers/brc.py:901agree on{"refine", "plan", "implement", "pr"}._fetch_live_brc_transcriptshort-circuits cleanly whenEGG_PIPELINE_IDis unset (test_no_pipeline_id_skips_live_querypins this).proposearm correctly excluded from sync — onlyack|nacktriggersync_to_proposals.merge --abort || truecorrectly handles the no-merge-in-progress case.- CI is green on the in-scope check suite (Lint, Unit Tests, Security Scan, Docker, Custom Checks all SUCCESS; Integration Tests still in progress at review time).
No blocking issues.
— Authored by egg
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
…ion, artifact escape Address non-blocking suggestions from the egg-reviewer review (#3083): - orchestrator/routes/messages.py: extend get_brc_transcript docstring to explain that the truncated flag reports post-filter trimming only, not upstream message-store overflow (suggestion #2). The 10000-msg upstream cap matches _write_brc_history's own retrieval bound so steady-state is benign; the docstring now makes the bound explicit and points operators at the cross-reference path for the long-lived-pipeline edge case. - orchestrator/consensus_wrapper.py: extend the sync_to_proposals block header with the durable HEAD-mutation semantics (suggestion #3). Two side effects called out: (a) dual-role agents commit on top of merged ancestry across subsequent producer turns (R11a only skips the sync, it does not un-merge); (b) multi-producer events merge SHAs sequentially, so a conflict on the second SHA leaves the first merge intact on HEAD. Neither is wrong, just durable rather than transient. - orchestrator/routes/event_prompt.py: strip backticks from producer- supplied artifact paths before markdown-code-span interpolation in the per-producer first-review fallback (suggestion #5). Not a shell- injection vector (the agent, not bash, is the consumer), but a stray backtick in a path breaks the markdown rendering. proposal_sha is already hex-validated upstream; this hardens the remaining unvalidated field with defensive replace("`", "").
|
Thanks for the careful re-review. Per-item disposition for the five non-blocking suggestions carried over from the previous review: 1.
|
This comment has been minimized.
This comment has been minimized.
There was a problem hiding this comment.
Re-reviewed at b4f6e1a08ba0da97f9002652a391277d33439751.
Delta since previous review (1c06e8676)
One commit (b4f6e1a), +36 lines across 3 files, all addressing the non-blocking suggestions I raised last round:
| Suggestion | File | Disposition |
|---|---|---|
#2 — truncated is post-filter only |
orchestrator/routes/messages.py:455-466 |
Fixed (docstring) |
#3 — sync_to_proposals durable HEAD mutation |
orchestrator/consensus_wrapper.py:470-484 |
Fixed (NB block) |
| #5 — Artifact paths interpolated unescaped | orchestrator/routes/event_prompt.py:724-731 |
Fixed (code: replace("", "")`) |
#1 — except ValueError, TypeError: |
n/a | Disagreed — ruff format strips parens; project pattern (5 instances in messages.py alone). Reasonable. |
#4 — disk_ids only collects string-typed ids |
n/a | Disagreed — intentional defensive narrowing; Message.to_dict() always emits string. Reasonable. |
Verification of the three fixes
1. messages.py docstring — accurate
The claim that _BRC_TRANSCRIPT_MAX_LIMIT (10000) matches _write_brc_history's own retrieval bound holds: orchestrator/routes/pipelines.py:8922 reads store.get_messages(pipeline_id, limit=10000) — identical to the route's upstream cap at messages.py:526. The docstring correctly characterises steady-state benignity and points operators at the message-store metrics cross-reference for the long-lived-pipeline edge case. Documentation-only.
Minor (non-blocking): truncated is computed at messages.py:548 after the Delphi filter at line 546, so it actually reflects post-Delphi-redaction trimming, not just post-phase-filter. The docstring's "post-filter trimming only" reads inclusively enough that this is fine.
2. consensus_wrapper.py NB block — accurate
Both claims verified against the code:
- Dual-role producer-after-reviewer arm: the dispatcher at
consensus_wrapper.py:765conditionssync_to_proposalson[ "$ACTION" = "ack" ] || [ "$ACTION" = "nack" ]— theproposearm at line 755 falls through without calling it. So a subsequent producer turn does not re-sync but also does not un-merge, exactly as the NB block says. - Multi-producer sequential SHA merge: the
while IFS= read -r sha; do … done <<< "$shas"loop at line 514-535 processes SHAs sequentially.merge --abortat line 532 fires inside the conflict branch only, so a prior successful merge remains on HEAD. Matches the docstring.
Minor (non-blocking): the NB block references "R11a, see the dispatcher below" but R11a is not anchored anywhere in the file — the only occurrence is the NB block itself. A reader following the pointer will still find the relevant dispatcher code at line 755-784, just without an explicit label. Worth either dropping the R11a token or labelling the dispatcher arm in a follow-up; not blocking.
3. event_prompt.py backtick stripping — correctly positioned
The strip at line 731 (artifacts = [a.replace("", "") for a in artifacts]) sits before both interpolation sites: line 732 (refs_text) and line 740 (show_cmds). Both code paths feed off the post-strip artifactslist. Plain stringreplace— no regex/encoding surprises. The comment correctly identifies the producer-supplied path throughsnapshot["artifacts"]as the unvalidated surface and contrasts it with the hex-validatedproposal_sha`.
I confirmed by grep that lines 732 and 740 are the only places in event_prompt.py that interpolate artifacts paths into backtick-wrapped markdown. base_branch in the same neighbourhood comes from EGG_BASE_BRANCH env (orchestrator-controlled, not producer-supplied), so the fix scope is appropriate.
No regression test was added. The change is a one-line defensive sanitisation and the original suggestion classified it as "belt-and-braces", so this is acceptable, but a unit test on _build_delta_entries against an artifact with a backtick would close the loop cleanly.
Out-of-scope (not part of this PR) but adjacent
_render_nacks_section at event_prompt.py:316 interpolates nack["reviewer"] into a markdown heading wrapped in double-backticks (### Reviewer: ``{reviewer}`` (v{version})). The reviewer field is an orchestrator-controlled role token (coder, reviewer_code, etc.), not a producer-supplied path, so a backtick is implausible — flagging only for awareness, not requesting a change here.
CI
Lint (Python, Shell, YAML, Actions, Docker, Custom Checks, Aggregate), Security Scan, and Code Review checks are all green at HEAD. Unit Tests and Integration Tests were still in progress at review time; the delta is doc-mostly plus one trivial defensive replace, no plausible failure surface.
Carryover positive verification
Still holds at the new HEAD (the three coherent changes — /brc-transcript route, sandbox handler live+disk merge, wrapper sync-to-proposal — are byte-identical to the previous review):
- Delphi redaction on
/brc-transcriptreuses_apply_delphi_filter(pinned bytest_delphi_redaction_applies). - Hex validation at writer / reader / wrapper bash boundaries;
RECONSTRUCTED_NO_SHAcorrectly dropped at the hex-only gates. _BRC_TRANSCRIPT_PHASESand_VALID_PHASESagree on{"refine", "plan", "implement", "pr"}._fetch_live_brc_transcriptshort-circuits on missingEGG_PIPELINE_ID.proposearm correctly excluded fromsync_to_proposals(now also documented in the NB block).
No blocking issues.
— Authored by egg
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
…a entries - consensus_wrapper.py: add an inline 'R11a' label to the propose|ack|nack dispatcher arm so the existing docstring reference in sync_to_proposals' NB block resolves to a concrete code anchor. - test_compose_event_prompt.py: add a regression test for backtick stripping in the first-review fallback render of _build_delta_entries, pinning the b4f6e1a artifact escape behaviour.
|
Thanks for the careful re-review. Per-item disposition for the three new observations from the 1.
|
This comment has been minimized.
This comment has been minimized.
There was a problem hiding this comment.
Re-reviewed at f8f6cbf9b9de287142dfefcb6b391f3eac2bd58e.
Delta since previous review (b4f6e1a08)
One commit (f8f6cbf9), +44 lines across 2 files, both addressing the two non-blocking observations from the previous review:
| Previous observation | File | Disposition |
|---|---|---|
| R11a label has no anchor in the file | orchestrator/consensus_wrapper.py:765-770 |
Fixed (inline anchor comment) |
| No regression test for backtick stripping | orchestrator/tests/test_compose_event_prompt.py:935-970 |
Fixed (regression test added) |
Verification of the two fixes
1. R11a dispatcher anchor — accurate and well-positioned
consensus_wrapper.py:765 now carries an R11a (sync_to_proposals docstring anchor): comment immediately above the if [ "$ACTION" = "ack" ] || [ "$ACTION" = "nack" ]; then sync_to_proposals ... gate at line 771-773. The pointer chain now resolves:
consensus_wrapper.py:477(docstring NB block):"The producer arm (R11a, see the dispatcher below) intentionally skips the sync"consensus_wrapper.py:765(dispatcher arm): inline R11a anchor with restated rationale (producer commits already on HEAD; merging peer SHAs onto a producer turn is the dual-role bleed-through the sync is designed to avoid).
grep R11a orchestrator/consensus_wrapper.py returns both occurrences and only those occurrences (line 477 + line 765). The anchor is bash-comment-only and adds no executable behavior. I also verified the comment contains no { / } that would interact with the _EVENT_PUMP_WRAPPER_TEMPLATE.format(...) call at consensus_wrapper.py:854. Safe.
The dispatcher gating itself is unchanged: propose still falls through without syncing; only ack / nack invoke sync_to_proposals — the property TestSyncToProposals pins (and which the previous review already verified).
2. Backtick-stripping regression test — exercises the right path
test_build_delta_entries_first_review_strips_backticks_from_artifact_paths (test_compose_event_prompt.py:935) drives _build_delta_entries with:
pending_reviews[0].artifact_refs = ["src/evil.py", "src/ok.py"]— flows through_extract_artifacts_for_produceratevent_prompt.py:721, which I verified extracts the list verbatim frompending_reviews[i].artifact_refs(no upstream stripping).- No
last_reviewed_commit_sharecorded forcoder— forces the fallback path atevent_prompt.py:718-755(the only site where thea.replace("", "")` strip at line 731 fires). proposal_commit_sha = "abc1234"— 7 hex chars, passes the upstream sha validation, drives theif proposal_sha:branch at line 733 that buildsshow_cmds.
Assertions are tight:
"git show abc1234:src/evil.py" in deltaand"git show abc1234:src/ok.py" in delta— both verify the stripped artifact path lands in the renderedgit showcommand."evil" not in delta— verifies no raw backtick-evil-backtick substring survives. I traced the rendered string: with the strip applied, the only neighborhood around "evil" issrc/evil.py, so the assertion meaningfully fails iff the strip regresses.
The test sits one function above test_build_delta_entries_first_review_sha_without_artifacts_still_renders, parallel to the existing first-review test on test_compose_event_prompt.py:880, in the right module. Style matches the file's existing tests (in-function from pathlib import Path import, matches other recent additions).
Minor (non-blocking, not requested as a fix): the test only covers the if proposal_sha: branch (show_cmds path). The else branch at event_prompt.py:756-765 also uses the stripped artifacts via refs_text at line 732. Practically the strip is shared (one list comp upstream of both branches at line 731), so a regression in either path is caught — but a parallel test on the no-SHA branch would be belt-and-braces. Not worth a follow-up given the shared upstream.
Carryover positive verification (still holds at f8f6cbf9)
The three coherent PR changes — /brc-transcript route, sandbox handler live+disk merge, wrapper sync-to-proposal — are byte-identical to the previous review (the only delta is the new comment + new test):
- Delphi redaction on
/brc-transcriptreuses_apply_delphi_filter(pinned bytest_delphi_redaction_applies). - Hex validation at writer / reader / wrapper bash boundaries;
RECONSTRUCTED_NO_SHAcorrectly dropped at the hex-only gates. _BRC_TRANSCRIPT_PHASESand_VALID_PHASESagree on{"refine", "plan", "implement", "pr"}._fetch_live_brc_transcriptshort-circuits cleanly on missingEGG_PIPELINE_ID.proposearm correctly excluded fromsync_to_proposals(now anchored by the new R11a label).merge --abort || truecorrectly handles the no-merge-in-progress case.
Previously disagreed-with (still applicable, still reasonable)
The two non-blocking suggestions the author declined remain reasonable to leave as-is:
except ValueError, TypeError:atmessages.py:490— declined becauseruff formatenforces the unparenthesized form, and the line is consistent with four pre-existing instances in the same file. Holds.disk_idsonly collecting string-typed ids atbrc.py:1242— declined as intentional defensive narrowing; the live side always emits a string, so the dedup is only weakened for malformed historic data. Holds.
CI
Lint (Python, Shell, YAML, Actions, Docker, Custom Checks, Aggregate), Security Scan, Code Review Wait-for-checks, Validate configuration — all SUCCESS at HEAD. Unit Tests and Integration Tests still in progress at review time; the delta is one bash comment + one isolated unit test, no plausible failure surface.
No blocking issues.
— Authored by egg
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
Parallel to the existing first-review backtick-strip test, but exercises the else branch of _build_delta_entries (no proposal_sha -> refs_text rendering). The strip is one list comp upstream of both branches so the existing test already pins regression, but this is belt-and-braces on the shared upstream per the f8f6cbf review's minor observation.
|
Thanks for the careful re-review at Per-item disposition: Verified-in-this-review (no action needed)
New minor observation
Adjacent flag (out-of-scope)
Carryover (still declined, still reasonable)
CI was green at — Authored by egg |
This comment has been minimized.
This comment has been minimized.
There was a problem hiding this comment.
Re-reviewed at 91c08d9129c4f26a6f4db352d999c92666456531.
Delta since previous review (f8f6cbf9)
One commit (91c08d9), +42 lines in orchestrator/tests/test_compose_event_prompt.py. It adds test_build_delta_entries_first_review_no_sha_strips_backticks_from_refs_text — the parallel no-SHA-branch pin I flagged as a non-blocking observation in the previous review.
The three coherent PR changes — /brc-transcript route, sandbox handler live+disk merge, wrapper sync-to-proposal — are byte-identical to the prior review.
Verification of the new test
The test correctly exercises the else (no-SHA) fallback path in _build_delta_entries at orchestrator/routes/event_prompt.py:756-765:
memory_text=""→per_producer_sha = {}→ producer-sidesha = ""→ theif sha:short-circuit at line 703 is skipped.event_payload["pending_reviews"][0]carriesproducer="coder"andartifact_refs=["src/\evil`.py", "src/ok.py"]with **no**proposal_commit_shakey, so_extract_proposal_sha_for_producerreturns""(theentry.get("proposal_commit_sha")isNone→ not a string → falls through toreturn ""`).proposal_sha=""drives theelsebranch atevent_prompt.py:756, which interpolatesrefs_text(the only branch that usesrefs_textrather thanshow_cmds).
Assertions are tight and meaningful:
"- \src/evil.py`" in deltaand"- `src/ok.py`" in delta` verify the stripped paths land in the rendered code spans."\evil`" not in deltais the meaningful regression assertion: without the strip at line 731 the renderedrefs_textwould contain- `src/`evil`.py`, and the substring ``evil`` (backtick-evil-backtick) would appear; with the strip applied, "evil" is followed by.`, so the assertion holds. A regression that removes the strip would flip this assertion."git show" not in deltacorrectly sanity-checks that theelsebranch does not rendergit showcommands — distinguishing this test from theif proposal_sha:branch test directly above it.
The test sits parallel to test_build_delta_entries_first_review_strips_backticks_from_artifact_paths at test_compose_event_prompt.py:935, between it and test_build_delta_entries_first_review_sha_without_artifacts_still_renders, in the right module. Style matches the file's existing tests (in-function from pathlib import Path import).
The previous review's observation that "the strip is one list comp upstream of both branches (line 731), so this is a belt-and-braces pin" still applies — both tests would now flag a regression at the shared upstream, and a regression in either rendered path is independently caught.
Carryover positive verification (still holds at 91c08d9)
- Delphi redaction on
/brc-transcriptreuses_apply_delphi_filter(pinned bytest_delphi_redaction_applies). - Hex validation at writer / reader / wrapper bash boundaries;
RECONSTRUCTED_NO_SHAcorrectly dropped at the hex-only gates. _BRC_TRANSCRIPT_PHASESand_VALID_PHASESagree on{"refine", "plan", "implement", "pr"}._fetch_live_brc_transcriptshort-circuits cleanly on missingEGG_PIPELINE_ID.proposearm correctly excluded fromsync_to_proposals(anchored by the R11a label atconsensus_wrapper.py:765).merge --abort || truecorrectly handles the no-merge-in-progress case.
Previously disagreed-with (still applicable, still reasonable)
The two non-blocking suggestions the author declined remain reasonable to leave as-is:
except ValueError, TypeError:atmessages.py:490— declined becauseruff formatenforces the unparenthesized form, and the line is consistent with four pre-existing instances in the same file. Holds.disk_idsonly collecting string-typed ids atbrc.py:1242— declined as intentional defensive narrowing; the live side always emits a string, so the dedup is only weakened for malformed historic data. Holds.
CI
Lint (Python, Shell, YAML, Actions, Docker, Custom Checks, Aggregate), Security Scan, Unit Tests, Integration Tests, Validate configuration — all SUCCESS at HEAD. The delta is one isolated unit test, no plausible failure surface.
No blocking issues. No remaining non-blocking observations either — the previous round's belt-and-braces follow-up has now landed.
— Authored by egg
|
egg review completed. View run logs 12 previous review(s) hidden. |
…er] (#3112) * docs: update brc read-peer-artifact and reviewer sync docs Update docs to reflect changes from feat(brc) #3076/#3083: - orchestrator-cli.md: brc read-peer-artifact now merges a live /brc-transcript orchestrator route with on-disk brc-history files; the "no HTTP transport" claim was wrong after #3076. - concurrent-execution.md: reviewer worktree sync is now handled automatically by the wrapper's sync_to_proposals bash step before ack/nack invocations; updated the protocol flow description, Reviewer Worktree Sync section, and the shell example accordingly. Authored-by: egg * docs: address review feedback on brc sync/live-flag wording - orchestrator.md: rewrite item 4 of 'Worktree state synchronization' so it describes the wrapper-driven sync_to_proposals step instead of the removed prompt-driven fetch+merge instruction (was contradicting the concurrent-execution.md section it cross-links to). - concurrent-execution.md: clarify that the BRC preamble's SYNC prose still exists — the wrapper bash is the reliable layer because the event-pump discards spawn prompts, not because the prose was removed. - agent-roles.md: note that the tester's reviewer-arm sync is now wrapper-handled, but the producer-arm manual fetch+merge still applies (the wrapper deliberately skips sync on propose). - orchestrator-cli.md + brc.py docstring: align the 'live' bool wording on route *reachability* (empty record lists still count as reachable) rather than 'live route contributed records'. --------- Co-authored-by: jwbron <8340608+jwbron@users.noreply.github.com> Co-authored-by: egg-reviewer[bot] <261018737+egg-reviewer[bot]@users.noreply.github.com>
Completes the #3076 fix — the phase-1 remainder shaped per #3077 ("coordination state is served, not replicated"). Stacked on #3078; merge that first, then retarget/merge this.
What
1. Live
brc-transcriptroute (orchestrator)GET /api/v1/pipelines/<pid>/brc-transcript?phase=…[&role=…&slice_id=…&include_unattributed=…&limit=…]Serves the in-flight phase's BRC records (
BRC_HISTORY_TYPES,Message.to_dict()shape — byte-compatible with the on-disk brc-history JSON) straight from the message store, which holds exactly the current phase (it is cleared on phase transitions by_clear_concurrent_state). Two correctness constraints carried over from existing channels:_apply_delphi_filteraspoll_messages, so an unreviewed reviewer sees a producer'sCONSENSUS_PROPOSEredacted toversion+commit_sha— the route cannot be used to bypass blinding._write_brc_history's attribution — CONSENSUS_* records require a matching canonicalmetadata.slice_id(dropped otherwise), non-consensus types without slice scope form theunattributedbucket.2.
read_peer_artifactgoes live (sandbox handler)The handler now queries the route and merges with the on-disk files: live = the phase in flight, disk = phases completed before spawn. Live records dedup against disk by message id; results carry a
live: boolflag. Empty results are now differentiated:git showfallback (unchanged from fix(brc): scope review deltas to the proposal SHA; make read_peer_artifact honest about mid-phase emptiness #3078)A live-route failure (older orchestrator, transport) degrades to disk-only — no new hard dependency. No
EGG_PIPELINE_ID→ no HTTP attempted.3. Wrapper-performed sync-to-proposal (event pump)
On
ack/nackactions the wrapper now merges eachpending_reviews[].proposal_commit_shainto the reviewer worktree before invoking the agent — deterministic bash replacing the fetch/merge prose that lived in spawn prompts the event pump provably discards (del prompt_text, #3033). This is what reviewers that must run the proposal (tester) need; prompt-renderedgit showreads (#3078) remain the fallback.Safety properties:
RECONSTRUCTED_NO_SHA) never reach git (same stance as_extract_proposal_sha_for_producer).merge --abort+ log; already-ancestor → skip. The function always returns 0; the agent invocation is never blocked on the sync.proposeinvocations do NOT sync (R11a: propose own work first).Tests
TestBrcTranscript(route): phase/slice/limit validation, BRC-type + phase filtering, the mid-phase-propose-visible regression pin, Delphi redaction, Slice PRs are missing analysis/plan docs and all BRC history; need a 'context' PR for refine+plan phases plus per-slice BRC in each slice PR #2548 attribution parity.TestBrcReadPeerArtifactLive(handler): merge, dedup, degrade-on-failure, hint differentiation, query-param threading, no-pipeline-id short-circuit. Existing disk-only tests pass unchanged.TestSyncToProposals(wrapper): static template invariants (gating, ordering, hex validation, fail-soft) + two behavioral bash tests against a real scratch repo (merge lands the proposed artifact; metachar SHA filtered; unknown SHA logs and exits 0).Deferred (tracked in #3077 phase 2)
The gateway
git show <ref>:<path>artifact-read endpoint — not needed to close #3076 because per-role worktrees share the host object store, so the renderedgit showcommands and the wrapper merge both work locally today.Closes #3076.