[issue-2908][slice-5/6] Additive CLI surface: stdin/file prose plum... - #2952
Conversation
…r branch The slice-4 coder branch was created based on main but the slice-4 parent at origin/egg/issue-2908-impl2/slice-4 has the slice-1, slice-2, and slice-3 implementation work that slice-4 builds on. Merge it in before doing task-4-1 / task-4-2. Conflicts resolved in orchestrator/routes/pipelines.py and orchestrator/tests/test_pipeline_prompts.py — both in the BRC preamble dual-role banner. The coder-owns-tests refinement (#2936) that landed on main and the event-pump banner collapse from slice-3 task-3-3 of #2908 both touch the dual-role banner text. Resolution: keep slice-3's event-pump structure (no wait-loop filter allowlists in the preamble — the wrapper drives invocation) and layer in the coder-owns-tests semantics on top: the tester's first invocation does ORIENT/PREPARE only; the wrapper re-invokes it on the coder's CONSENSUS_PROPOSE; it does its producer WORK (review + harden the coder's tests) + PROPOSE + ACK/NACK in that single invocation. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…ORY defaults
Slice-4 task-4-1 makes the event-pump wrapper the production default
by flipping two env-flag defaults:
* ``EGG_BRC_EVENT_PUMP`` flips from unset→OFF (legacy) to unset→ON
(event-pump). Setting ``EGG_BRC_EVENT_PUMP=false`` (or
``0`` / ``no`` / ``off``, case-insensitive) keeps the legacy
capped-restart template available for a one-release rollback
window. Unrecognised tokens fall through to event-pump so a typo
cannot silently downgrade the production path. Slice-4 task-4-2
will delete the legacy template entirely and the env flag with it.
* ``EGG_BRC_MEMORY`` flips from unset→``off`` (slice-1 inert) to
unset→``full`` (event-pump composer reads memory by default).
Setting ``EGG_BRC_MEMORY=off`` is the one-release rollback escape
hatch. Unknown values still fail-safe to ``off`` (the fallback
target stays restrictive — an undocumented value is a
misconfiguration signal, NOT a write-bearing default to mask).
Files touched:
* ``orchestrator/consensus_wrapper.py``:
- ``_event_pump_enabled()`` default flipped; falsy-token allowlist
captures rollback path; docstring + module-level reframe updated.
- Wrapper template's inline ``EGG_BRC_MEMORY:-off`` → ``...:-full``
so the wrapper's invocation of ``event_prompt.py`` inherits the
new default even on shells that don't export the var explicitly.
* ``sandbox/egg_agent_tools/handlers/brc_memory.py``:
- ``get_memory_mode()`` defaults to ``MODE_FULL``; new
``MODE_DEFAULT`` constant pins the contract.
* ``orchestrator/routes/event_prompt.py``:
- CLI ``memory_mode`` default flipped from ``"off"`` to ``"full"``.
* Tests updated to match the new defaults:
- ``orchestrator/tests/test_consensus_wrapper.py``:
``TestEventPumpTemplateSelection`` rewritten — unset-env now pins
event-pump, ``EGG_BRC_EVENT_PUMP=false`` pins legacy.
``TestBuildConsensusWrappedCommand``,
``TestConsensusWrapperBehavior``, ``TestBufferOverflowDetection``,
``TestEventDrivenWait``, ``TestSSESigtermGrace`` gain an autouse
``_force_legacy_template`` fixture that engages the rollback
escape hatch so they continue to drive the legacy template.
Slice-4 task-4-2 deletes the entire fixture + these classes
alongside the legacy template.
- ``tests/sandbox/egg_agent_tools/test_handlers_brc.py``:
renamed ``test_unset_defaults_to_off`` → ``test_unset_defaults_to_full``;
the unset-env pin now asserts the memory file is written.
- ``orchestrator/tests/test_compose_event_prompt.py``: docstring
note that ``write-only`` is the rollback target, not the default.
Verified manually with Python smoke tests that the flag-flip works
for unset, truthy, and the full falsy-token allowlist
(``false`` / ``0`` / ``no`` / ``off`` / case variants), and that
``EGG_BRC_MEMORY=writeonly`` (typo) still fails safe to ``off`` with
a warning while ``EGG_BRC_MEMORY=full`` and unset both enable
writes + reads.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…menter branch # Conflicts: # orchestrator/routes/pipelines.py # orchestrator/tests/test_pipeline_prompts.py
Rewrite docs/architecture/orchestrator.md "BRC Consensus Wrapper" section
(renamed from "BRC Event-Pump Wrapper (slice-2, behind EGG_BRC_EVENT_PUMP)")
to describe the post-deletion steady state. Event-pump is now the only
consensus-wrapper path; the legacy capped-restart template and the
agent-side heartbeat / keep-alive path were removed in slice-4 task-4-2.
Changes:
- docs/architecture/orchestrator.md
- Renamed section to "BRC Consensus Wrapper"; updated anchor link
from #brc-event-pump-wrapper-slice-2-behind-egg_brc_event_pump.
- Replaced the slice-2 caveat blockquote with a four-slice rollout
summary that names the deleted symbols (_CONSENSUS_WRAPPER_TEMPLATE,
_RECOVERY_SYSTEM_PROMPT, SSE consensus.reached, MAX_CONSENSUS_RESTARTS).
- Reframed "Why a new wrapper template" → "Why the wrapper drives the
loop"; rewrote in past tense so the doc reads as if the event-pump
has always been the only model.
- Rewrote "Wrapper-side heartbeat (#2036 migration)" and
"Wrapper-side gateway-session keep-alive (#2451 migration)" with
"completed in slice-4" qualifier; described agent-side deletion.
- Rewrote "Idle / no-progress safety budget" to drop the comparison
table with the legacy 3-restart cap; replaced with a single
behaviour table for EGG_BRC_IDLE_BUDGET_MIN.
- Added new "Rollback plan" subsection documenting git revert of
slice-4 → slice-3 → slice-2 → slice-1 in reverse-merge order, the
integration check operators must run, and the partial-revert
interaction (reverting only slice-4 restores the dual-emission
state).
- Renamed "Slice-2 verification stance — unit-test-only" to
"Verification stance — unit-test-only"; explained that the
snapshot tests pinning the byte-for-byte legacy template emission
were retired in slice-4 task-4-3.
- Renamed "BRC Per-Event Prompt Composer + Preamble Collapse
(slice-3)" to drop the slice marker; reframed "Flag mapping" to
"What's gated by what" since EGG_BRC_EVENT_PUMP no longer gates
anything.
- Updated EGG_BRC_MEMORY table: full is now the slice-4 default;
write-only is the opt-in regression path.
- Updated env vars table: EGG_BRC_EVENT_PUMP is a deprecated no-op
pointing at the rollback plan; EGG_BRC_IDLE_BUDGET_MIN is no
longer gated on EGG_BRC_EVENT_PUMP=true.
- docs/guides/concurrent-execution.md
- Replaced the slice-2 "two emission paths" caveat with a single
post-deletion summary linking to the new orchestrator.md section.
- Rewrote the "Consensus Wrapper" body to describe the deterministic
event-pump loop (steps 1–6) as the only path; removed
MAX_CONSENSUS_RESTARTS-based restart cap, the recovery system
prompt, and the final-consensus-check restart cycle.
- Updated the configuration table: dropped `max_restarts` row;
added EGG_BRC_IDLE_BUDGET_MIN; updated transient-crash recovery
paragraph to reference the idle/no-progress budget instead of
the deleted MAX_CONSENSUS_RESTARTS hard cap.
- docs/architecture/README.md
- Updated the cross-link card to point at the renamed section and
summarise the slice-4 deletion + rollback plan.
Cross-links to docs/architecture/brc-memory.md (slice-1) retained
throughout. The wait-side companion at agent-wait-patterns §10 is
referenced from each cross-link card.
Satisfies contract task-4-4. Acceptance: doc reads as if the event
pump has always been the only model; legacy-path caveats removed;
cross-links present; rollback plan documented; markdown renders
clean (no conflict markers; section anchors resolve).
…nd agent-side heartbeat Slice-4 task-4-2 collapses ``consensus_wrapper.py`` onto the event-pump template that slice-2 introduced and slice-3 wired the per-event composer into. The event-pump is now the only production path; rollback under a regression is a ``git revert`` of slices 1-3 per the PR body, not an env-flag flip. Deleted from ``orchestrator/consensus_wrapper.py``: * ``_CONSENSUS_WRAPPER_TEMPLATE`` (the ~600-line legacy capped-restart bash template). * ``_RECOVERY_SYSTEM_PROMPT`` and ``_RECOVERY_USER_PROMPT`` — the restart-time recovery prompts. * The SSE ``consensus.reached`` curl path (issue #1897) that lived inside the legacy template — the event-pump uses ``egg-orch message wait-loop`` instead. * ``MAX_CONSENSUS_RESTARTS`` (issue #2806) and its companion constants ``MAX_READY_POLL_CYCLES``, ``TRANSIENT_RESTART_BACKOFF_INITIAL``, ``STARTUP_FAILURE_WINDOW_SECONDS``. The idle/no-progress safety budget (env ``EGG_BRC_IDLE_BUDGET_MIN``, default 30 min) is the replacement liveness ceiling. * ``_event_pump_enabled()`` — the ``EGG_BRC_EVENT_PUMP`` env-flag read. The flag is now silently inert; operators with it lingering in k8s manifests can leave it set to either truthy or falsy and still get the event-pump template. * The legacy-template branch in ``build_consensus_wrapped_command``, which is now a thin alias for ``build_event_pump_wrapped_command``. Preserved by relocating into ``_EVENT_PUMP_WRAPPER_TEMPLATE`` (per task-4-2 acceptance, "Keep ``is_buffer_overflow`` / ``is_transient_crash`` / ``is_startup_failure`` classifiers"): * ``is_buffer_overflow()`` — Claude Agent SDK 1 MiB JSON reader overflow detector (#2804). * ``is_transient_crash()`` — signal-based exits (134, 136, 137, 139, 255). * ``is_startup_failure()`` — exit 1 within a 30 s startup window. * ``STARTUP_FAILURE_WINDOW_SECONDS`` — kept as a bash-scope shell variable inside the template (was a Python module constant). The classifiers are not yet wired into the event-pump's ``propose|ack|nack`` agent-invocation failure path (which uses ``AGENT_FAIL_STREAK`` + idle-budget escalation today); they live as named helpers for future revisions. Deleted from ``sandbox/egg_agent_tools/handlers/message.py``: * ``_WAIT_LOOP_HEARTBEAT_INTERVAL_SECS`` — the 60-s cadence constant. * ``_default_emit_wait_loop_heartbeat`` — the agent-side ``WAITING_FOR_EVENT`` / ``WORKING`` heartbeat emitter (#2036). * ``_start_wait_loop_heartbeat`` — the threaded periodic-tick helper. * The per-iteration ``emit_hb`` / ``stop_hb`` calls inside ``message_wait_loop``, including the ``try/finally`` block that drove the final ``WORKING`` beat on wait exit. The event-pump wrapper now owns both heartbeat liveness (#2036) and slice-scoped gateway-session keep-alive (#2451) via the wrapper- owned ``start_background_heartbeat`` subshell. ``message_heartbeat`` (the explicit handler invoked by ``egg-orch message heartbeat``) is unchanged — the wrapper calls it. Test updates: * ``orchestrator/tests/test_consensus_wrapper.py``: deleted the ``TestBuildConsensusWrappedCommand`` / ``TestConsensusWrapperBehavior`` / ``TestBufferOverflowDetection`` / ``TestEventDrivenWait`` / ``TestSSESigtermGrace`` classes (and the ``_force_legacy_template`` fixture that fed them). The buffer-overflow / SSE / capped-restart surfaces they covered no longer exist. The event-pump classes (``TestEventPumpTemplateSelection`` and siblings) cover the new production path; ``TestEventPumpTemplateSelection`` is reworked to pin the post-task-4-2 invariant that ``EGG_BRC_EVENT_PUMP`` is silently inert (any value, including ``false`` / ``0`` / ``no`` / ``off``, emits the event-pump template). * ``orchestrator/tests/test_consensus_wrapper_anchor.py``: deleted in full — every test pinned ``_RECOVERY_SYSTEM_PROMPT`` / ``_CONSENSUS_WRAPPER_TEMPLATE`` symbols that no longer exist. * ``orchestrator/tests/test_brc_nack_iteration.py``: removed ``TestConsensusWrapperNackFeedback`` (4 tests) that pinned the legacy recovery prompt's NACK-feedback placeholder + helper. The equivalent event-pump assertion lives in ``orchestrator/tests/test_compose_event_prompt.py``. * ``tests/sandbox/egg_agent_tools/test_handlers_message.py``: removed ``TestMessageWaitLoopHeartbeat`` (16 tests) that pinned the agent-side heartbeat path. ``TestMessageHeartbeat`` (the explicit handler tests) is unchanged. * ``integration_tests/regression/test_brc_concurrency.py``: updated the slice-2 verification-stance docstring to reflect the slice-4 post-deletion steady state (E2E deferred to #2585 via ``egg_stack``; in-process tracker coverage unchanged). Defensive grep assertions all return zero matches on ``orchestrator/consensus_wrapper.py``: rg 'consensus\.reached|sse_url|_RECOVERY_SYSTEM_PROMPT|MAX_CONSENSUS_RESTARTS' \ orchestrator/consensus_wrapper.py # → 0 hits Smoke-verified that the event-pump template is emitted regardless of ``EGG_BRC_EVENT_PUMP`` value, that the three classifiers survive in the event-pump template, and that the deleted agent-side heartbeat helpers are no longer importable from ``handlers.message``. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Five blocking findings + three non-blockers from reviewer_code's v1 NACK on PR-proposal v1. Address all five blockers; defer the non-blockers (env-var coordination is gated on coder task-4-1 / task-4-2 landing first). Blocker 1+2+3 — restored post-#2936 coder-owns-tests content in docs/guides/concurrent-execution.md (the v1 proposal overwrote the post-#2936 wording when I copied the slice-4 base, which predates the #2936 merge): - §"HANDOFF" table row example: "Coder can't push test files → HANDOFF to tester" → "Tester can't push a .github/ CI fix → HANDOFF to coder with the required end-state" (matches docs/reference/agent-roles.md). - §"Worked Example: Role-Boundary Handoff" rewrite: drop the reinstated pre-#2936 coder→tester test-handoff example, restore the post-#2936 tester→coder .github/-staging example, and keep the explicit lead sentence "the coder→tester test handoff that used to live here is gone: the coder now authors and pushes its own tests". - §"Rebase rarely conflicts" paragraph: "Rebase cannot conflict because agents have mutually exclusive file write permissions" / "role restrictions guarantee non-overlapping file sets" was a doc lie after #2936 — restore the pre-rewrite "rarely conflicts" wording and the follow-up paragraph that names the shared test scope and the serialize-by-time-not-concurrent invariant. Blocker 4+5 — dead anchors and stale §10 / §10.9 framing in docs/reference/agent-wait-patterns.md and docs/architecture/brc-memory.md: - agent-wait-patterns.md §10 retitled from "BRC Event-Pump Wrapper (slice-2, behind EGG_BRC_EVENT_PUMP)" to "BRC Consensus Wrapper (event-pump model)"; intro blockquote rewritten to drop the slice-2 "OFF by default" framing and instead describe the post-deletion steady state + rollback path; §10.8 retitled from "Flag-off as the temporary default — when slice-4 flips it" to "Rollout completed in slice-4" with body rewritten accordingly; §10.9 retitled to drop the (slice-3) suffix and the "Flag mapping" blockquote rewritten to "What's gated by what" since EGG_BRC_EVENT_PUMP no longer gates anything. - All five dead inbound anchor references repointed to the new anchors: agent-wait-patterns.md lines 1178, 1411, 1653, 1654 and brc-memory.md lines 235, 237. - Reverse direction — repointed orchestrator.md, README.md, and concurrent-execution.md cross-links from #10-brc-event-pump-wrapper-slice-2-behind-egg_brc_event_pump to #10-brc-consensus-wrapper-event-pump-model (3 occurrences in orchestrator.md, 1 each in README.md and concurrent-execution.md); same for #109-brc-per-event-prompt-composer--preamble-collapse-slice-3 → #109-brc-per-event-prompt-composer--preamble-collapse. - Verified via grep across docs/ that no remaining link points at the old anchors and no remaining body text carries the "(slice-2, behind EGG_BRC_EVENT_PUMP)" framing. Non-blockers deferred: - Rollback-plan example precision (compose_event_prompt slice-3 vs slice-2 wrapper) — useful tightening but doesn't change the correctness of the doc. - "schema is unchanged" past-tense alignment — minor. - EGG_BRC_EVENT_PUMP "no-op" vs "removed" wording — gated on coder's task-4-1 / task-4-2 final state. Will re-pass once the coder's proposal lands so the doc and code agree.
…r branch Documenter landed task-4-4 (post-deletion consensus-wrapper docs) on the slice-4 branch in parallel with the coder's task-4-1 + task-4-2 work. Their merge resolved the dual-role banner conflict by taking the slice-3 base text (general event-pump description). This commit keeps the coder's resolution (coder-owns-tests refined: tester's first invocation does ORIENT/PREPARE only, wrapper re-invokes on coder's CONSENSUS_PROPOSE carrying proposal in event_payload, tester does producer WORK + PROPOSE + ACK/NACK in that single invocation) since the main-branch coder-owns-tests semantics (#2936) need to be preserved under the event-pump model. The other documenter changes (orchestrator.md, brc-memory.md cross-link, etc.) flow through unchanged. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…to egg/issue-2908-impl2-slice-4-coder/work
v2 cleared mandate 1 (all v1 blockers fixed) but mandate 2 found four new blocking findings in agent-wait-patterns.md §10.3 / §10.4 / §10.5 / §10.7 — subsection bodies still described the flag-off vs flag-on dual-emission world in present tense as if both paths still shipped, contradicting the §10 intro blockquote rewritten in v2. Address all four: - §10.3 (Heartbeat ownership) — dropped the two-row flag-off vs flag-on table; rewrote in past-tense post-migration framing mirroring orchestrator.md §"Wrapper-side heartbeat (#2036 migration completed in slice-4)" — the wrapper owns heartbeating now and the pre-#2908 agent-side path in `message_wait_loop` was deleted in slice-4 task-4-2. - §10.4 (Gateway-session keep-alive) — struck the closing "With the flag off the agent-side keep-alive still runs" sentence and replaced it with the slice-4-deletion qualifier matching §10.3 / orchestrator.md. - §10.5 (Idle / no-progress safety budget) — dropped the parenthetical "(replaces the 3-restart FAIL cap)" from the heading; dropped the two-row flag-off vs flag-on table; replaced with a single-row `EGG_BRC_IDLE_BUDGET_MIN` table mirroring orchestrator.md's steady-state version; rewrote the present-tense "MAX_CONSENSUS_RESTARTS = 3 cap" framing in past tense. - §10.7 (Verification stance) — dropped "Slice-2" from the heading; rewrote the body in past tense matching orchestrator.md's §"Verification stance — unit-test-only"; removed the "snapshot equality for the flag-off path" and "deferred to slice-4" framing (slice-4 is this work; flag-off snapshot tests were retired in slice-4 task-4-3); flipped the integration-tests bullet from "runs with EGG_BRC_EVENT_PUMP=false" to "runs against the event-pump wrapper". Adjacent cleanups for body/header coherence: - §10.1 ASCII diagram: relabelled "LEGACY (flag off, today's default)" → "PRE-#2908 (deleted in slice-4 task-4-2 — kept here for git-blame readers)" and "EVENT-PUMP (flag on)" → "STEADY STATE (event-pump, the only path after slice-4)". - §10.9.4 EGG_BRC_MEMORY mode table: marked `full` as the slice-4 default (mirrors orchestrator.md); dropped the slice-3-rollout "operators opt into full just as they opt into EGG_BRC_EVENT_PUMP=true" paragraph since EGG_BRC_EVENT_PUMP is no longer consulted. - §10.9.5 `_build_brc_preamble` collapse: rewrote the closing paragraph in past tense — the collapse runs unconditionally now because the event-pump wrapper is the only path; flipped "Slice-4 flips the wrapper default" → "Slice-4 flipped the wrapper default" so the doc reads as steady state. - §10.9.6 `mission.md` sandbox-rebuild paragraph: flipped "Slice-4's flag-flip is gated" → past-tense "The slice-4 default flip was gated". - §10.9.7 Composer / preamble verification stance: dropped "Slice-3" from the heading; rewrote in past tense matching the §10.7 rewrite; removed "deferred to slice-4" since slice-4 is this work. - §10.9.8 Architect open-decision resolutions: "resolved across slices 1–3" → "resolved across slices 1–4". - §11 Related Documentation cross-link: updated the Concurrent Execution Wrapper card from "how the wrapper uses SSE + wait-loop" (SSE machinery was deleted in slice-4 task-4-2) to "the deterministic event-pump bash loop driver". The two §10.7 non-blockers (slice-2 contract back-reference at §10.7 tail, architect-corrected-pseudocode parenthetical) survive as audit history — the reviewer marked them non-blocking and the context is still useful for future maintainers tracing the slice-2 design review.
…to egg/issue-2908-impl2-slice-4-documenter/work
… not no-op Reviewer_code v2 non-blocker #3 was deferred awaiting coder task-4-1 / task-4-2 final state. The coder's task-4-2 commit (15664e8) has now landed and the docstring at orchestrator/consensus_wrapper.py:35 confirms the env var itself was deleted ("the EGG_BRC_EVENT_PUMP env flag itself"), not just left as a dead branch. Update the docs to match: - docs/architecture/orchestrator.md env-vars table EGG_BRC_EVENT_PUMP row: "Deprecated no-op after slice-4" → "Removed in slice-4 task-4-2"; default "unset (no-op)" → "n/a (removed)"; added the helm-values / pod-spec drop-row note for operators that referenced it explicitly. - docs/architecture/orchestrator.md §"Operator-facing env vars (cross-link)": "the EGG_BRC_EVENT_PUMP selector is no longer consulted — setting it has no effect because the legacy template it selected to is gone" → "was removed in slice-4 task-4-2 — the env var is no longer read by the orchestrator, so setting it has no effect on a post-slice-4 codebase." - docs/architecture/orchestrator.md §"Rollback plan" partial-revert paragraph: tightened the post-slice-4-revert narrative to say the env var itself comes back when slice-4 is reverted (because task-4-2 is what deleted it), and operators wanting event-pump back set EGG_BRC_EVENT_PUMP=true (not =false — the defaults flip back to off). Also tightened the example of why reverse-merge order matters (slice-2 wrapper template references a composer slice-3 added, not "a composer that no longer exists"). - docs/reference/agent-wait-patterns.md §10.8: same shift — env var was deleted alongside the legacy template, so setting it has no effect; rollback path is reverse-merge order.
Fix the six broken tests and four stale docstrings the holistic
reviewer surfaced on v1 (the gateway-blocked test execution missed
them; the structural issues are all visible from grep alone).
Tests (orchestrator/tests/test_consensus_wrapper.py +
orchestrator/tests/test_brc_nack_iteration.py):
* Restored ``import os`` / ``import shlex`` / ``import subprocess`` —
the surviving event-pump test classes still need them
(``TestEventPumpConfirmFailureRaisesIdleAlert`` uses
``shlex.quote`` for stubbed PATH binaries;
``TestEventPumpHeartbeatSubshellLifecycle`` and the
brc_snapshot tests use ``os.environ``).
* Deleted ``TestEventPumpHeartbeatCadence::test_flag_off_heartbeat_path_unchanged``
— its invariant ("legacy template does not emit
``egg-orch message heartbeat``") no longer applies; the legacy
template is gone. Replaced with an inline comment cross-linking
to the post-deletion positive invariant.
* Deleted ``TestEventPumpKeepAliveCadence::test_flag_off_keep_alive_remains_agent_side``
— same reason.
* Deleted ``TestEventPumpIdleBudgetAlert::test_flag_off_idle_budget_not_used``
— same reason.
* Deleted ``TestEventPumpRoleCompleteConfirm::test_flag_off_legacy_path_does_not_auto_call_consensus_confirmed``
— the legacy template is gone; the event-pump's confirm invocation
is strictly orchestrator-driven via the ``case "$ACTION"`` arms,
not auto-invoked on agent exit, so the symmetry guard is
structurally satisfied.
* Renamed ``TestEventPumpFlagIsolation::test_flag_on_does_not_inherit_legacy_max_restarts``
to ``test_event_pump_relies_on_idle_budget_not_legacy_restart_cap``
and dropped the ``max_restarts=7`` kwarg (the legacy kwarg was
deleted from ``build_consensus_wrapped_command`` by task-4-2).
The remaining assertion — ``EGG_BRC_IDLE_BUDGET_MIN`` is in the
script — is the salient invariant.
* Deleted ``TestEventPumpInvokesComposer::test_flag_off_legacy_template_does_not_reference_event_prompt``
— same legacy-path-only invariant.
* Removed the orphaned ``assert "unresolved_nacks" in _CONSENSUS_WRAPPER_TEMPLATE``
line at the bottom of ``test_brc_nack_iteration.py`` (was left
outside any function by the original ``TestConsensusWrapperNackFeedback``
deletion; this is a pure cleanup of slice-4 v1 commit
15664e8).
Docstrings:
* ``sandbox/egg_agent_tools/handlers/brc_memory.py:546`` —
``record_review_event`` docstring updated to reflect the
slice-4 task-4-1 default flip (``EGG_BRC_MEMORY`` defaults to
``full`` now, not ``off``).
* ``orchestrator/routes/event_prompt.py:787`` — CLI docstring
updated to ``default full``; documents that ``off`` is the
one-release rollback escape hatch and ``write-only`` keeps the
writer warm without consuming the excerpt.
* ``orchestrator/consensus_wrapper.py:81`` — module-level template
comment rewritten: the env-flag predicate is gone, the
event-pump template is the only template path post-task-4-2.
* ``orchestrator/consensus_wrapper.py:723`` —
``build_event_pump_wrapped_command`` docstring rewritten to
describe the post-task-4-2 reality (no env-flag gate; legacy
template deleted; ``compose_event_prompt`` already wired).
Defensive (addresses the non-blocking observation #1):
* ``tests/sandbox/egg_agent_tools/test_handlers_message.py:TestMessageHeartbeat``
gains an autouse ``_isolate_slice_id_env`` fixture that clears
``EGG_SLICE_ID``. ``message_heartbeat`` auto-attaches
``slice_id`` from that env via ``_maybe_attach_slice_id``, so a
developer-machine ``EGG_SLICE_ID`` (e.g. inside the egg sandbox)
would otherwise add an unexpected key to the request body and
fail the strict-equality assertions.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…to egg/issue-2908-impl2-slice-4-coder/work
Blocking finding:
* test_consensus_wrapper.py top-level imports missed ``import sys``;
``test_persistent_confirm_failure_fires_overseer_alert`` (the §1 + §6.2
lock-in test, the most operator-critical assertion in the file)
uses ``sys.executable`` at line ~1092 and would raise NameError on
execution, silently disabling the regression guard. The reviewer
caught it via grep — same shape as the reviewer_code_holistic v1
NACK that surfaced the missing os/shlex/subprocess imports.
Fix: add ``import sys`` alongside os/shlex/subprocess.
Non-blocking findings (all addressed in this v3 since they're cheap):
* TestEventPumpIdleBudgetAlert class docstring rewritten —
``The old template keeps MAX_CONSENSUS_RESTARTS verbatim`` was
present-tense framing for the legacy template that task-4-2 deleted.
Now reads ``The legacy template that owned the historical restart
cap was deleted in slice-4 task-4-2; the idle budget is now the only
liveness ceiling in the wrapper.``
* TestEventPumpFlagIsolation class renamed to TestEventPumpIdleBudgetCeiling
with docstring rewritten — after task-4-2 there is no flag-on /
flag-off partition to police, so the original name and ``cross-cutting
guards`` framing no longer apply. The class retains its single
surviving test (``test_event_pump_relies_on_idle_budget_not_legacy_restart_cap``)
which is correct against the post-deletion state.
* test_persistent_confirm_failure_fires_overseer_alert inline comment
rewritten — ``_event_pump_enabled`` was deleted by task-4-2; the
``monkeypatch.setenv("EGG_BRC_EVENT_PUMP", "true")`` is harmlessly
retained as a defensive guard against a future regression that
re-introduces a flag-gated branch. Comment now reads as such.
The reviewer flagged the docstring drift as non-blocking but I'm
folding it into the same commit because the cost is one edit each
and the docstring↔code mismatch the holistic v1 NACK called out is
the same class of issue. Keeping the surface honest.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…ocker #2 (test_pipeline_prompts fixture) Follow-up to v3 (e093f67 pushed) that addressed the reviewer_code v2 blocker (missing import sys). This commit addresses the reviewer_code_holistic v2 blocker (2): two pre-existing test failures in orchestrator/tests/test_pipeline_prompts.py. Root cause: the slice-4 base-merge in 06c5a6c resolved the conflict on test_pipeline_prompts.py by keeping slice-3's _PLAN_WITH_MISASSIGNED_TASK fixture (``role: coder`` + ``files: integration_tests/conftest.py``). But main's #2936 ("coder authors its own tests; tester reviews-and- hardens") explicitly excluded coder→test-files from the role↔files alignment validator. The fixture no longer trips the reject path, breaking TestPlannerRoleAlignmentValidation::test_rejects_misassigned_plan_at_propose_time and ::test_rejected_proposal_does_not_mutate_tracker. Fix: cherry-pick main's fixture update — switch the misassignment fixture from a test-file path to a docs path (docs/fixtures.md), which IS still a misassignment, since docs remain the documenter's scope. Added an explanatory comment above the fixture citing #2936 and the slice-3 merge-resolution context so future readers do not re-revert under a conflict resolution that "looks like" the slice-3 text. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…x (tester v3 NACK) Tester v3 NACK had two blockers: 1. ``_auto_populate_contract_at_implement_start`` was deleted from ``orchestrator/routes/pipelines.py`` during the slice-4 base merge (commit 06c5a6c). The orphan import in ``orchestrator/tests/test_auto_populate_contract.py`` broke ``pytest --collect-only`` and blocked ``make test`` from running any tests at all (collection aborts on the first ImportError). Verified by the tester via ``git diff origin/main..origin/egg/issue-2908-impl2/slice-4`` that the function was dropped, not renamed. Fix: restored the function body verbatim from ``origin/main`` (the #2915 production implementation) and re-added the call site inside the slice-loop-mode gate where it lived on main. The function: * lives between ``_check_origin_has_plan_draft`` and ``_populate_contract_from_plan_safe`` (matches main's ordering). * is called from the ``_use_slice_loop`` check in ``_run_pipeline`` when ``_slice_count == 0``, exactly as on main. * uses ``_populate_contract_from_plan``, ``PopulateOutcome``, ``ForestValidationError``, ``_commit_statefiles_to_worktree``, and ``_pipeline_identifier`` — all present in the current file (no further imports needed). The function has a slice-4 v4 banner in its docstring explaining the restore so future merge resolutions don't re-drop it. 2. ``orchestrator/consensus_wrapper.py:50`` had a ruff I001 unsorted imports failure — an extra blank line between ``import shlex`` and the next module-level constant. Fix: removed the extra blank line (one-line deletion). Verified locally: * ``pytest --collect-only`` no longer aborts on ``ImportError: cannot import name '_auto_populate_contract_at_implement_start'``. * ``orchestrator/tests/test_auto_populate_contract.py`` imports clean. * ``orchestrator.routes.pipelines`` module imports clean. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Reviewer_code re-reviewed coder v6 and NACKed with 4 blocking ruff failures + 1 ruff-format failure that would block ``make lint`` in CI: 1. ``orchestrator/tests/test_consensus_wrapper.py:13-23`` — I001 unsorted-import-block (resolved as a side-effect of fixes 2 and 3 reducing the import block to a single from-import). 2. ``orchestrator/tests/test_consensus_wrapper.py:18`` — F401 ``pytest`` imported but unused. The two surviving call sites inside function bodies use ``import pytest as _pytest`` so the top-level name was dead after the v2 test deletions. Fix: remove the top-level ``import pytest``. 3. ``orchestrator/tests/test_consensus_wrapper.py:22`` — F401 ``consensus_wrapper.build_event_pump_wrapped_command`` imported but unused (zero references in the file after the test-deletion sweep). Fix: drop the second name from the from-import. 4. ``tests/sandbox/egg_agent_tools/test_handlers_message.py:10`` — F401 ``threading`` imported but unused. Slice-4 task-4-2 (15664e8) deleted the threaded ``message_wait_loop`` heartbeat machinery; the test cases that exercised it were also removed but the top-level ``import threading`` was left behind. Fix: remove the now-dead import. 5. ``orchestrator/tests/test_pipeline_prompts.py:5129-5131`` — ruff format-check failure on a multi-line assertion message. Pre- existing from the slice-3 tester commit 7cff8d1 but surfaced only now that the file is in lint scope. Fix: ``ruff format`` collapses the two-string concatenation into a single line. Verified locally: * ``ruff check .`` → ``All checks passed!`` * ``ruff format --check .`` → ``872 files already formatted`` * ``pytest orchestrator/tests/test_consensus_wrapper.py`` → 33 passed. * ``pytest tests/sandbox/egg_agent_tools/test_handlers_message.py`` → 24 passed. * ``pytest orchestrator/tests/test_pipeline_prompts.py`` → 431 passed. Non-blocking observations from reviewer_code v6 (the _auto_populate_contract restore in routes/pipelines.py and the v4 consensus_wrapper.py I001 deletion) were already verified-clean in the prior review and remain unchanged in v7. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Document the slice-5 additive CLI surface across the four docs that already carry consensus-protocol prose: - docs/reference/orchestrator-cli.md * New "Prose-bearing args: stdin and --*-file channels (#2741)" subsection under ## BRC Consensus Protocol covering --summary-file, --reason-file, --files-reviewed-file, and the stdin sentinel `-`. * New "## BRC verb-level operations (egg-orch brc)" section documenting the next-action / get-state / list-blocking / resolve-obligation / read-peer-artifact subcommands. * Deprecation-warning note on the argv --summary / --reason path. - docs/reference/agent-tools.md * MCP↔CLI table: mcp__brc__get_state, mcp__brc__list_blocking (slice-1), and mcp__brc__read_peer_artifact, mcp__brc__resolve_obligation (slice-5) flipped from "no CLI" to their new egg-orch brc subcommands. * cli_command=None rationale list: drop the four promoted verbs and add a callout summarizing the slice-5 promotion. * Schema-derivation paragraph: shrink the "tools with no CLI" list accordingly. - docs/reference/agent-wait-patterns.md * Update re-propose / stale-version examples to use --summary-file / --reason-file (the canonical idiom for any wrapper-composed CLI). * New "Prose-bearing args use stdin / --*-file, not argv (#2741)" subsection under §1 with channel table, examples, and rationale. * Related Documentation: cross-link to the new orchestrator-cli.md BRC verb-level operations section and to #2741. - docs/guides/concurrent-execution.md * Refresh the worked Consensus Protocol example to use --summary-file for propose, --reason-file for ack, and the stdin sentinel for nack / withdraw. Add a brc resolve-obligation example. * New "egg-orch brc — verb-level read/derive surface" subsection cross-linking the canonical reference in orchestrator-cli.md. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…rface Slice-5 of the BRC event-pump rollout extends the CLI surface for the in-bash wrapper that ships in slice-2. Three coder tasks land here: task-5-1 — Prose-arg channels for consensus propose/ack/nack/withdraw. The wrapper composes CLI invocations via ``bash -c``, so argv-only prose (``--summary "$RAW"``, ``--reason "$RAW"``) gets corrupted by shell metacharacters (``$VAR`` / backticks / ``$()`` / ``;`` / ``&&`` / embedded newlines) — the #2741 failure mode. This slice generalises the mitigation: every prose-bearing arg now offers a paired ``--FOO-file PATH`` flag and accepts ``-`` as the argv sentinel for stdin. Argv prose still works for humans and during transition but emits ``DeprecationWarning`` so a regression to argv-only inside the wrapper surfaces. ``--files-reviewed-file PATH`` carries an array with one path per line (blank lines and ``#`` comments stripped), per architect v2 §verification_strategy.slice_5. Two helpers in orch_cli.py — ``_resolve_prose_arg`` and ``_resolve_files_reviewed_arg`` — handle channel selection (file → stdin → argv), enforce mutual exclusion, and emit the deprecation. task-5-2 — ``egg-orch brc resolve-obligation`` CLI. Verb-level wrapper around ``mcp__brc__resolve_obligation`` (#2338). Slice-6 deletes the agent-side MCP server, so the wrapper bash needs this verb reachable without an MCP round-trip. Args mirror the handler: ``--reviewer-role`` and ``--producer-role`` are required; ``--commit-sha`` and ``--note`` are optional. The ``--note`` flag uses the same prose-arg plumbing as the other reason / summary args. task-5-3 — ``egg-orch brc read-peer-artifact`` CLI. Verb-level wrapper around ``mcp__brc__read_peer_artifact``. Stdout JSON; pagination via ``--limit`` + opaque ``--cursor`` round-trip; ``--message-type`` is ``action="append"`` for repeated use; ``--no-include-unattributed`` opts out of the slice-scoped + cross-cutting merge (default on, per the handler's per-slice-partition contract from #2548). Tests authored by the coder (tester reviews-and-hardens): * ``tests/sandbox/egg_lib/test_orch_cli_prose_args.py`` — #2741 regression-guard. Parametrises seven representative prose payloads (``$VAR`` / backticks / ``$()`` / shell-control / newline+tab / UTF-8 / quotes+escapes) across each delivery channel (file, stdin sentinel, argv) for ``consensus propose``, ``ack``, ``nack``, and ``withdraw``. Asserts byte-equality between the on-disk / stdin input and the request body received by the orchestrator fake. Argv-path tests assert the ``DeprecationWarning`` fires. Mutual- exclusion paths return exit 2 with helpful stderr. ``--files- reviewed-file`` one-path-per-line semantics covered (blank lines + ``#`` comments stripped). The ``consensus propose --file`` JSON payload path (from issue #1738) is explicitly tested to NOT emit the deprecation warning — only the per-arg argv channels are deprecated. * ``tests/sandbox/egg_lib/test_orch_cli_brc.py`` — extends slice-1's test file with ``TestBrcResolveObligation`` (happy path / commit SHA / note via file / note via stdin / help / parser registration) and ``TestBrcReadPeerArtifact`` (happy path / peer-role filter / message-type list / limit+cursor pagination round-trip / no-include-unattributed default flip / phase choices restricted / help / parser registration). All 306 tests pass on the changed paths; existing consensus-push, slice-1 BRC, and CLI parity tests continue to pass unchanged. Files: sandbox/egg_lib/orch_cli.py; tests/sandbox/egg_lib/test_orch_cli_brc.py; tests/sandbox/egg_lib/test_orch_cli_prose_args.py. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Address three blocking findings plus the in-scope non-blocking ones raised by reviewer_code on the v1 documenter proposal. Blocking 1 — `--files-reviewed-file` is one-path-per-line (NOT JSON): The `_resolve_files_reviewed_arg` handler in orch_cli.py:884-922 reads the file as newline-delimited paths, strips blank lines and `#`-prefixed comments, and never calls `json.loads`. Update the example comment in orchestrator-cli.md to say "one path per line; blank lines and `#` comments stripped" and rewrite the heredoc example to demonstrate the comment-stripping behavior. Mirror the clarification in agent-wait-patterns.md. Blocking 2 — schema-derivation claim was wrong: The four BRC tool registrations in sandbox/egg_agent_tools/tools/brc.py (get_state / list_blocking / read_peer_artifact / resolve_obligation) ALL still declare `cli_command=None`. Slice-1 / slice-5 added thin CLI wrappers (`egg-orch brc <verb>`) over the same handlers but deliberately did NOT flip the registrations. The MCP-side schemas continue to be hand-authored in `schemas.py`; the `derive_schema_from_argparse` path is skipped. Restore the four BRC verbs to the `cli_command=None` bullet list with the additional context that a thin CLI wrapper exists; revise the "promoted to CLI" callout to "CLI surface added (registration unchanged)"; revise the schema-derivation paragraph; tag the CLI- counterpart cells with "thin wrapper, registration still cli_command=None — see callout below". Blocking 3 — `brc read-peer-artifact` does NOT use the gateway: The handler reads `.egg-state/brc-history/<identifier>-<phase>.json` files from local disk (verified: no `orchestrator_request(...)` call in `brc_read_peer_artifact`). EGG_ORCHESTRATOR_URL / EGG_LIFECYCLE_SECRET do not apply. Rewrite the "all five subcommands" sentence in orchestrator-cli.md to scope the auth claim to the other four and explain the local-disk semantics so operators don't misdiagnose missing-secret failures. Non-blocking (in-scope to the row I touched): - agent-tools.md: fix the pre-existing handler typo `handlers.brc.read_peer_artifact` → `handlers.brc.brc_read_peer_artifact` (every sibling row uses the brc_ prefix). - agent-tools.md: tighten the read_peer_artifact description to mention `<identifier>-<phase>.json` (not `<pipeline_id>`), the per-slice `<identifier>-implement-<slice_id>.json` partition, the unattributed sibling merge + `include_unattributed=False` toggle, and the `message_type` filter (single value or list). - concurrent-execution.md: author a distinct `reviewer-code-cond-ack.md` for the conditional ACK example so the prose narrative matches the obligation case (instead of re-using the unconditional ACK file). - concurrent-execution.md: show the `cat > /tmp/obligation-resolved.md` heredoc step on the `brc resolve-obligation` example (every other prose-arg example in the same section creates the file inline). Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…ror, return rc=2 Tester v1 NACK on coder v1 (commit 0a8a7f6): `_resolve_prose_arg` caught `OSError` but not `UnicodeDecodeError`, so a binary or non-UTF-8 file passed to `--reason-file` / `--summary-file` / `--note-file` / `--files-reviewed-file` raised a raw traceback to the wrapper bash instead of the actionable `Error: failed to read ...` message. The tester's one-line fix recommendation was to add `UnicodeDecodeError` to the `except` clauses. That's done. While there, also aligned the helpers to the established orch_cli pattern of `return 2` from `cmd_*` (the same pattern `cmd_consensus_ack` already uses for its `--pre-merge-condition-resolved-in-diff` guard): * Added `_ProseArgError` sentinel exception. `_resolve_prose_arg` and `_resolve_files_reviewed_arg` now `raise _ProseArgError` on any CLI-level validation failure (mutual exclusion, missing required arg, file-read failure incl. `UnicodeDecodeError`); the cmd_* functions catch it and return rc=2. The stderr error message is emitted by the helper before the raise — cmd_* only translates the exception to the exit code. * No more `sys.exit(2)` inside the helpers — `sys.exit` from within a cmd_* call raises `SystemExit`, which fails pytest tests that expect a clean returned rc (the tester's bug-finding test, `test_non_utf8_file_surfaces_clean_error_not_traceback`, makes this explicit by checking `assert rc == 2` after the call). Tester's adversarial test file pulled in (tester committed it as `tests/sandbox/egg_lib/test_orch_cli_prose_args_adversarial.py` at 847985f3d8). Two of the tester's tests that used `pytest.raises(SystemExit)` updated to the new `return rc=2` contract: * `TestProseFileReadErrors::test_missing_reason_file_path_surfaces_clean_error` * `TestProseArgEmptyEdges::test_empty_string_argv_treated_as_missing` Both now assert `rc == 2` returned. The `test_invalid_phase_rejected_at_parse_time` test continues to use `pytest.raises(SystemExit)` because argparse's `choices=` rejection is genuinely a parse-time SystemExit, not a cmd_* validation path. Mirror change in `tests/sandbox/egg_lib/test_orch_cli_prose_args.py`: the coder-authored `test_reason_and_reason_file_mutually_exclusive`, `test_missing_reason_fails_cleanly`, and `test_files_reviewed_and_file_mutually_exclusive` likewise switch from `pytest.raises(SystemExit)` to `assert rc == 2` + `capsys` stderr inspection. Verification: * All 142 tests in `tests/sandbox/egg_lib/` pass. * Broader regression: 193 tests across `egg_agent_tools/test_handlers_brc.py`, `test_cli_parity.py`, `test_orch_cli_consensus_push.py`, and `test_orch_cli_slice_id.py` pass unchanged. * ruff check + ruff format clean. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Adds the kubectl-gated integration test
``integration_tests/test_mcp_baseline_capture.py`` that drives a
real-LLM 5-role consensus through the still-live MCP surface
(slice-5 is additive only) and writes per-event wall-clock samples
to ``.egg-state/agent-outputs/latency-mcp-baseline.json``. The
schema (``samples: [{role, event_type, start_ts, end_ts,
duration_seconds, exit_code}]`` plus aggregate p50/p95/max/sum) is
the input slice-6 TASK-6-6 will compare against the CLI-only
baseline it captures after the MCP→CLI collapse lands.
The test skips cleanly when ``_kubectl_available()`` returns False
via the session-scoped ``egg_stack`` fixture, and also skips when
the gateway is unhealthy (dummy GH creds in CI) — mirroring the
guard used by ``test_orchestrator_mcp_contract.py``.
Also commits a synthetic placeholder baseline JSON marked
``_meta.synthetic: true`` so slice-6 has a file to read while the
capture test waits on a real-LLM run; ``_meta.synthetic_reason``
explains exactly how to regenerate.
No ``ScriptedProvider`` import / reference (per the slice-5 plan
re-scope: real LLM route, not in-process provider swap).
This comment has been minimized.
This comment has been minimized.
Autofix tracking{"Lint/Python": 1, "Test/Integration Tests / Integration Tests": 2, "Test/Unit Tests": 3} |
This comment has been minimized.
This comment has been minimized.
…role banner conflicts slice-3's main-merge resolution settled the BRC dual-role banner on the generic event-pump version (dropping main's #2936 wait-loop banner). slice-4 had already reconciled both concerns: its banner carries the event-pump-wrapper framing AND the coder-owns-tests (#2936) tester specialization ('harden the coder's tests', re-invoke on the coder's CONSENSUS_PROPOSE). slice-4's banner is the strict superset, so accepted HEAD for both pipelines.py and test_pipeline_prompts.py — it preserves the coder-owns-tests language while keeping the event-pump framing #2908 requires.
This comment has been minimized.
This comment has been minimized.
… runtime preservation The slice-3 → slice-4 merge resolution accidentally reverted three fixes that landed on main after slice-3 forked. This re-applies them verbatim from origin/main so the unit tests pass: * _slice_agents_alive (#2914): k8s alive guard called from the Layer-C bootstrap resume branch. Without it, a restart_phase that tore down agents but left the contract IN_PROGRESS wedges with no agents. * _resolve_slice_base_branch parent_branch_exists callback (#2928): fresh non-root slices now probe whether the derived parent branch exists on origin via ls_remote_branch_strict, replacing the pre-#2928 merge-base probe that mis-routed every fresh non-root slice onto work whenever work had advanced ahead of the parent. * _merge_preserved_slice_runtime (#2908): _populate_contract_from_plan re-parses the plan into fresh PENDING slices on every restart; the safety-net populator outside the contract_synced guard would otherwise reset COMPLETE slices and strand the pipeline on slice-1. Authored-by: egg
…to egg/egg-exec-20260603-045318-3100/work
Check Failures: Unit Tests & Integration TestsInvestigated CI run Unit Tests — 13 failures, inherited from slice-4
Root cause: those three commits exist in slice-4 (PR #2951) and slice-6 history, but are absent from this branch's Why this PR can't fix it: slice-5's diff is purely additive CLI surface ( Integration Tests — Docker build infrastructure flakeThe integration job failed at This is runner-level (dbus socket / resolv.conf), not code. A re-run should clear it. Recommended action
— Authored by egg |
This comment has been minimized.
This comment has been minimized.
…to egg/issue-2908-impl2/slice-5
Brings slice-3's banner-fix commit 7bdb29d ("Fix dual-role banner contradiction with coder-owns-tests orientation") forward into slice-4, clearing the CONFLICTING state on PR #2951. Conflict was in the dual-role execution-order banner in orchestrator/routes/pipelines.py (_build_brc_preamble). slice-4 had rewritten the whole banner (intro + numbered list); slice-3 had independently rewritten just the numbered list to defer the WORK-vs-gated decision to the role-specific orientation, and added the guard test test_dual_role_banner_does_not_contradict_coder_owns_tests (auto-merged). Resolution: kept slice-4's richer tester-specific intro (won cleanly) and took slice-3's numbered list for the conflicted hunk. slice-3's wording is required for the merged guard test, which asserts the banner contains 'role-specific orientation' + a gating phrase and no 'scaffold'. The two halves are consistent. Full test_pipeline_prompts.py suite green (432).
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
There was a problem hiding this comment.
Review summary
Slice-5 lands the additive CLI surface cleanly. Prose-arg plumbing is symmetric across consensus propose / ack / nack / withdraw and the new brc resolve-obligation, with proper mutual-exclusion, sentinel-vs-argv disambiguation, and explicit UnicodeDecodeError handling (with rationale inline — good — since UnicodeDecodeError is a ValueError subclass, not OSError, so a bare except OSError would leak a raw traceback). The two new brc subcommands wrap their handlers without forwarding pipeline_id from caller args, preserving the R2 cross-pipeline-read hardening. Docs are comprehensive and cross-linked between agent-wait-patterns.md, agent-tools.md, orchestrator-cli.md, and concurrent-execution.md. The argparse required=True removals are correctly paired with post-resolution checks in the cmd_* functions so the "required" semantics are preserved.
Three non-blocking findings below. The first is a code-smell in the new integration-test file that I'd want addressed before merge; the second and third are forward-looking suggestions for the follow-up slices.
Finding 1 (non-blocking, style — please fix) — Python-2-looking except clauses in integration_tests/test_mcp_baseline_capture.py
Three handlers in the new test file use the parenthesisless form:
integration_tests/test_mcp_baseline_capture.py:172—except FileNotFoundError, subprocess.TimeoutExpired:integration_tests/test_mcp_baseline_capture.py:210—except TypeError, ValueError:integration_tests/test_mcp_baseline_capture.py:369—except urllib.error.URLError, TimeoutError, ConnectionError:
These are not bugs: Python 3 parses except E1, E2: as a tuple expression (verified via AST and runtime — both branches catch correctly). But:
- The same file uses the conventional parenthesized form at
integration_tests/test_mcp_baseline_capture.py:307(except (urllib.error.URLError, TimeoutError, ConnectionError, ValueError) as exc:), so the file is internally inconsistent — that's a code-review red flag for any reader. - The form is brittle for future edits:
except A, B as e:is a hardSyntaxErrorin Py3 (Py3 reservesasfor the single-class form), so anyone trying to add exception binding later must first rewrite the clause to the parenthesized form. - Reads like Python 2 to anyone who saw
except E, name:(the Py2 instance-binding form). The semantics here are tuple-multi-catch, not binding, but a future reader has to AST it to be sure.
Convert all three to except (E1, E2[, ...]):. ruff doesn't flag it (verified), so this lands silently if a human doesn't catch it now.
Finding 2 (non-blocking, scope follow-up) — Other prose-bearing flags still take argv only
Slice-5's task-5-1 explicitly scopes the four --summary / --reason flags. But the same bash -c shell-metachar hazard the slice fixes applies to two other free-form prose flags that remain argv-only after this PR:
consensus propose --risk(sandbox/egg_lib/orch_cli.py:3979in the diff —cons_propose.add_argument("--risk", help="Risk considerations")). Risk prose is exactly the kind of content where a reviewer NACK could mention`git reset --hard`or; rm -rf /as a quoted hazard description and have the wrapper bash misinterpret it.consensus ack --pre-merge-conditionand--pre-merge-condition-resolved-in-diff. The docs already say the condition is "validated like--reason" (docs/reference/agent-tools.mdanddocs/guides/concurrent-execution.md), and theconcurrent-execution.mdexample carries a backticked`git mv legacy/auth.py src/auth.py`directly on argv — exactly the shape that breaks under the wrapper bash. The diff atdocs/guides/concurrent-execution.md:649keeps that argv form even though the surrounding--reasonexample was migrated to--reason-file.
If the goal is "slice-5 closes the prose-arg shell-metachar class of bugs," these two should fall in scope. If slice-5 is deliberately scoped to the four BRC verbs and these are a follow-up, please open a tracking issue and link it from the slice-5 narrative — otherwise it's easy for the next slice to assume "all prose-arg flags now have file/stdin channels."
Finding 3 (non-blocking, durability) — Synthetic baseline can silently become slice-6's comparison ground truth
The committed .egg-state/agent-outputs/latency-mcp-baseline.json has "_meta.synthetic": true and a synthetic_reason instructing a human to regenerate before slice-6 TASK-6-6 runs. But integration_tests/test_mcp_baseline_capture.py:81 documents:
slice-6's TASK-6-6 reads only the
sampleslist and theaggregateblock, so additive_metafields are forward-safe.
That sentence is the gap: slice-6 is documented as ignoring _meta, which means a synthetic placeholder can silently become the baseline a real MCP-vs-CLI comparison gates on. The synthetic numbers (p50=150s, p95=270s) are plausible enough that "MCP-vs-CLI within 5%" passes against them by coincidence rather than measurement.
Add a hard gate in slice-6 TASK-6-6: refuse to compare against a baseline whose _meta.synthetic is truthy (skip with a clear "regenerate the baseline first" message, or fail loudly — your call). Slice-5 is fine as-is; this is just naming the trip-wire so slice-6 lands the matching guard. Worth a TODO comment in the test docstring referencing this, so the future implementer is reminded.
Verified non-issues (called out so they don't get re-litigated)
- DeprecationWarning visibility under wrapper bash.
sandbox/bin/egg-orchis a symlink tosandbox/egg_lib/orch_cli.py, so_emit_argv_prose_deprecation(atsandbox/egg_lib/orch_cli.py:812) fires from__main__context, where Python's default warning filter does surfaceDeprecationWarningon stderr (verified via subprocess in a clean interpreter). The test harness usingwarnings.simplefilter("always")is belt-and-suspenders, not a hidden visibility gap. _resolve_prose_argedge case whereargv_value == "-"plus--*-file. Theif file_set and stdin_set:guard catches it before the bare-argv branch fires. Thenot stdin_setqualifier on the file/argv mutual-exclusion check correctly keeps--reason -from being read as an argv string.- CRLF in
--files-reviewed-file.line.strip()normalises both leading and trailing whitespace including\r, so a wrapper that writes the manifest withprintfon a CRLF-defaulting system still works. - Cross-pipeline-read hardening preserved.
cmd_brc_read_peer_artifactdeliberately omitspipeline_idfrom the request body — the handler resolves it fromEGG_PIPELINE_ID/EGG_ISSUE_NUMBERserver-side, defeating an agent-supplied override. The docstring atsandbox/egg_lib/orch_cli.py:3899is explicit about this.
— Authored by egg
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
…s in agent-tools.md and pipelines.py
Conflict Resolution SummaryResolved merge conflicts with
Please review:
— Authored by egg |
This comment has been minimized.
This comment has been minimized.
Finding 1: convert three Python-2-looking ``except E1, E2:`` clauses in integration_tests/test_mcp_baseline_capture.py (lines 172, 210, 369) to parenthesized tuple form. Ruff format actively strips parens off bare ``except (E1, E2):`` (no binding) — pin with ``# fmt: skip`` so the clearer form survives the formatter. Finding 2: extend the slice-5 prose-arg plumbing to the two remaining prose-bearing flags the reviewer flagged. ``consensus propose --risk`` gains ``--risk-file PATH`` and ``--risk -`` stdin sentinel; ``consensus ack --pre-merge-condition`` likewise gains ``--pre-merge-condition-file PATH`` and stdin sentinel. Argv path still works but emits the same DeprecationWarning as ``--summary`` / ``--reason``. Docs and prose-arg test surface updated; ``--pre-merge-condition-resolved-in-diff`` deliberately not exposed (it carries a commit SHA, not prose). Finding 3: add a TODO(slice-6 TASK-6-6) block to the test_mcp_baseline_capture.py module docstring naming the synthetic- baseline trip-wire — slice-6's TASK-6-6 must hard-gate on ``_meta.synthetic`` so the 5% latency budget cannot pass by coincidence against placeholder p50/p95 numbers.
|
Addressed the three review findings from Finding 1 — Finding 2 — additive prose-arg plumbing missed
Argv still works on both but emits the same Finding 3 — synthetic-baseline trip-wire needs an in-source TODO: — Authored by egg |
This comment has been minimized.
This comment has been minimized.
There was a problem hiding this comment.
Re-review — all three previous findings addressed
Reviewed the delta f1fb89b1..629d79db (the actual PR-authored work since the 6db4dd78 baseline; the larger compare range also contains the origin/main merge at f1fb89b1 which isn't PR-authored). All three of my previous findings have been addressed substantively, not superficially. No new blocking issues found.
Finding 1 (Python-2-looking except clauses) — resolved correctly
integration_tests/test_mcp_baseline_capture.py:185,223,382 are now except (E1, E2[, ...]): with # fmt: skip. I verified the # fmt: skip claim is necessary, not paranoid: running ruff format on a minimal repro (def f(): try: ... except (A, B): ...) does strip the parens back to the bare-comma form on the next pass. Without the pin, the formatter would silently revert the fix. The decision to keep the file internally consistent with # fmt: skip rather than ban the strip globally is the right call for a one-file touch.
Finding 2 (additive prose channels for --risk and --pre-merge-condition) — resolved correctly
sandbox/egg_lib/orch_cli.py:2786-2792, 2884-2890 route both flags through _resolve_prose_arg with required=False, gaining the - stdin sentinel and --*-file PATH, with DeprecationWarning on argv. The argparse surface (orch_cli.py:4072-4090, 4171-4196) parallels --summary/--summary-file exactly. Help-text wording is a copy-paste of the --summary template, which is the right consistency choice.
A few code details I checked and want to call out as correct (so they don't get re-litigated):
getattr(args, "pre_merge_condition", None) or Noneatorch_cli.py:2885— this normalises the argparsedefault=""toNonebefore passing to_resolve_prose_arg. Strictly redundant with the helper's ownargv_value != ""check, but it's defensible defensive code and the new regression testtest_default_empty_pre_merge_condition_emits_no_warningpins the no-warning-on-default behavior either way. The asymmetric absence ofor Noneon the--riskcall site (orch_cli.py:2787) is fine because--riskhas no argparse default, so it's alreadyNonewhen not passed.- Reordering of
pre_merge_condition_resolved_in_diffvalidation atorch_cli.py:2897— moved from before the prose resolution to after it. The only behavioral effect is error-ordering when a user supplies both--pre-merge-condition-resolved-in-diffAND omits--reason: they now hit the missing-reason error first instead of the resolved-in-diff error. Both errors are correct; the order is cosmetic. Not a bug. - Empty-file edge case —
--pre-merge-condition-file /dev/null --pre-merge-condition-resolved-in-diff abccorrectly trips the "resolution SHA has nothing to resolve" guard (empty file →pre_merge_condition == ""→ falsy → guard fires). Same behavior as the old--pre-merge-condition ""path. --pre-merge-condition-resolved-in-diffdeliberately NOT exposed through the new channels — correct call. It carries a commit SHA (hex, validated downstream), so it's outside the #2741 threat model. The docs note this explicitly (docs/reference/agent-wait-patterns.md:245-248,docs/reference/orchestrator-cli.md:449).
The new test classes TestConsensusProposeRiskChannels and TestConsensusAckPreMergeConditionChannels round-trip each channel against PROSE_PAYLOADS (shell metachars, UTF-8, embedded newlines, quotes/escapes — tests/sandbox/egg_lib/test_orch_cli_prose_args.py:47-74). Help-advertisement tests at tests/sandbox/egg_lib/test_orch_cli_prose_args.py:752-770 assert the new flag names appear in --help output.
Finding 3 (synthetic-baseline trip-wire TODO) — resolved correctly
integration_tests/test_mcp_baseline_capture.py:50-61 adds the explicit TODO(slice-6 TASK-6-6) block naming the hard-gate requirement on _meta.synthetic. Cross-references this review's Finding 3 for context. The TODO is in the module docstring (top of file), which is where slice-6's implementer will see it first — good placement.
Non-blocking observations (suggestions only — not blocking merge)
-
docs/guides/concurrent-execution.md:661still uses argv form for--pre-merge-conditionwith backticks. My previous Finding 2 explicitly called this line out:--pre-merge-condition "A human must \`git mv legacy/auth.py src/auth.py\` before merging — agents cannot push renames through the gateway"The CLI surface fix landed (Finding 2's primary ask), but the canonical example for conditional ACK in the operator guide still models the argv form the slice is teaching agents not to use. The escaped backticks (
\…`) are exactly the shape that breaks under wrapper-bash composition. Same goes fordocs/reference/orchestrator-cli.md:418, 425. Migrating these examples to--pre-merge-condition-file /tmp/obligation.md(paralleling the--reason-file /tmp/reviewer-code-cond-ack.mdmigration already done inconcurrent-execution.md:642`) would be self-consistent. -
No tracking issue cited for the remaining argv-only prose flags outside
consensus. Slice-5 is now explicitly scoped to theconsensusverbs (docs/reference/agent-wait-patterns.md:239-242anddocs/reference/orchestrator-cli.md:449both enumerate exactly those flags). The other prose-bearing argv flags —signal error --error,signal ready --reason,phase advance/complete --reason,progress emit --detail/--blocker,overseer alert --summary/--detail/--recommend— still suffer the same shell-metachar hazard but are out of scope here. My previous Finding 2 asked for a tracking issue. I don't see one linked from the slice-5 narrative or docs. Worth filing so the next slice-6+ planner doesn't assume "all prose-arg flags now have file/stdin channels." -
No per-flag mutual-exclusion tests for
--risk+--risk-fileor--pre-merge-condition+--pre-merge-condition-file. The shared_resolve_prose_argmutual-exclusion code path is already exercised bytest_reason_and_reason_file_mutually_exclusive(tests/sandbox/egg_lib/test_orch_cli_prose_args.py:244), so this is belt-and-suspenders. If a future refactor splits the helper per-flag, the gap would matter; today it doesn't.
Verified non-issues (called out so they don't get re-litigated)
_resolve_prose_arg's exception ordering atorch_cli.py:862-875correctly catchesfile_set && stdin_set(mutex on-sentinel + file) beforefile_set && argv_set && !stdin_set(mutex on argv literal + file), so a user passing--pre-merge-condition - --pre-merge-condition-file PATHgets the stdin-vs-file error rather than an argv-vs-file error. Both messages are correct; the ordering is the intentional one.tests/sandbox/egg_agent_tools/test_cli_parity.py:227-244and:278-290still constructNamespaces without the new*_fileattributes. The production code reads them viagetattr(args, "*_file", None), so they default toNoneand the tests pass. The deprecation warning fires (becausesummary=…/reason=…/risk=""are still argv) but the assertions only checkrc == 0/ stdout, so no breakage. Not pretty, but not buggy.
— Authored by egg
|
egg review completed. View run logs 15 previous review(s) hidden. |
Context
BRC consensus today depends on the agent re-entering a blocking
egg-orch message wait-loopbetween every event. That re-entry is aseam the model can fall out of by emitting a final assistant
message instead of re-entering the wait. Claude usually re-enters;
qwen3.7-max does not (#2906) — it exits success=True after one
match, the wrapper sees no CONSENSUS_CONFIRMED, the 3-restart cap
trips (#2806), and the pipeline FAILs after ~$1 and ~20 min of
churn. Prompt-only mitigations narrow the seam for one model; the
seam itself exists for every model (lineage: #2323, #2064, #2482,
#2036, #1995, #2451).
Changes
Reframe consensus-agent execution from a long-lived participant
that holds blocking waits into a deterministic wrapper-driven
event pump that invokes the agent one-shot per actionable event,
with continuity carried by a durable per-role memory file. Lands
in six linear slices behind
EGG_BRC_EVENT_PUMP(default falseuntil slice-4):
egg-orch brc next-action,brc get-state,brc list-blocking,phase get-contextCLIsubcommands. Durable BRC memory artifact at
.egg-state/agent-outputs/<role>/brc-memory.mdwithaction-scaffolded writes into
brc_ack/brc_nackhandlers,atomic writes via promoted
_persist_atomic_template,last_reviewed_commit_shaper producer in the schema,fail-closed path construction. Gated by
EGG_BRC_MEMORY=write-only(writes accumulate; reads landin slice-3). Purely additive — zero behavior change.
orchestrator/consensus_wrapper.pyas a deterministic eventpump gated by
EGG_BRC_EVENT_PUMP. Drop the 3-restart cap;replace with idle/no-progress safety budget. Migrate the
heartbeat (Overseer flags BRC reviewers/testers as stalled when they're correctly blocked in mcp__brc__wait_loop (implement-phase false positive) #2036) and gateway-session keep-alive (Orchestrator heartbeat-session lookup fails: container_id missing slice-N segment for non-coder roles #2451) from
the agent-side handler into the wrapper's blocking wait.
Heartbeat payload carries
slice_idfromEGG_SLICE_ID(regression guard). Verification is unit-test-only — no
in-process test double can drive a deployed pod end-to-end
(the pod-injection avenue was ruled out per Expand integration test coverage #2474); true
E2E deferred to slice-4 via the
egg_stackreal-podfixture. Old path retained verbatim alongside.
invocation to hand the agent the memory delta plus the full
git log {last_reviewed_commit_sha}..HEAD --not origin/{base_branch} -pdelta per producer (NOT just orchestrator-side
changed_artifacts— per REVIEWER-SYNC.md the re-review mustaudit the full delta as a fresh review). Strip the
STAY-ALIVE / wait-loop / cursor-threading guidance from
_build_brc_preambleandmission.md; replace with a leanevent-handler contract. Sandbox image rebuilt + agent pod
restarted BEFORE slice-4 flag flip.
EGG_BRC_EVENT_PUMP/EGG_BRC_MEMORYdefaults to on, gated onthe slice-2 / slice-3 unit + BRC in-process regression suites
passing on the new default; delete the capped-restart bash, the
_RECOVERY_SYSTEM_PROMPT, the SSE machinery, and theagent-side wait_loop heartbeat code. Rollback plan: revert
slices 1–3 via
git revertif production traffic regresses. Theqwen3.7-max qwen3.7-max BRC agents end their agentic loop early (success=True) without reaching CONSENSUS_CONFIRMED → consensus-wrapper restart churn #2906 k3s spike that previously validated this
end-to-end was removed (qwen route unavailable in k3s;
Claude-route E2E deferred to Rewrite TestCredentialIsolation as k3s-native (currently skipped under k3s) #2585).
subcommands. Add stdin /
--reason-file/--summary-file/
--files-reviewed-fileplumbing toconsensus propose --summary,consensus ack --reason,consensus nack --reason,consensus withdraw --reason(docs: steer agents to the structured contract tool, not Bash-composed egg-contract #2741 regression guard). Add
egg-orch brc resolve-obligationand
egg-orch brc read-peer-artifactCLI subcommands theslice-6 deletion depends on. Argv kept as fallback during
transition (deprecation warning).
MCP tools (~1,515 LOC across 7 namespace files + the 4
infra files +
server.py), theSYSTEM_PROMPT_NUDGE, and theMCP registration block in
shared/egg_agent/client.py:299-353INCLUDING the
EGG_MCP_TOOLSenv flag at :311 (no orphanflag). Retire
tests/tools/test_mcp_cli_drift.py. Migrate theMCP E2E test so the agent's first action is
consensus ack/nackvia stdin/file (preserves SDK-spawn exercise).Verify per-event wall-clock latency within 5%.
Impact
Operator-facing: the BRC consensus subsystem becomes
model-portable — any agent that exits naturally after handling
one event reaches CONFIRMED, instead of needing prompt nudges to
keep re-entering an in-process wait. Cost-per-phase drops because
restart churn disappears, replaced by short bounded per-event
invocations that hit the prefix cache (≥ 60-min TTL on both
routes per WS7 closure). Net code deletion: the capped-restart
template, the SSE machinery, the recovery system prompt, the 28
MCP tool schemas, the
EGG_MCP_TOOLSflag, the cursor-threadingguidance, and the agent-side heartbeat all go away. The agent
primitive (pod / worktree / SDK / permissions / restrictions) is
untouched.
This slice
Additive CLI surface: stdin/file prose plumbing + new BRC subcommands
Files affected:
sandbox/egg_lib/orch_cli.pydocs/reference/agent-tools.mddocs/reference/agent-wait-patterns.mdtests/sandbox/egg_lib/test_orch_cli_prose_args.pytests/sandbox/egg_lib/test_orch_cli_brc.pyintegration_tests/test_mcp_baseline_capture.pyTasks:
cmd_consensus_propose --summary(parser atsandbox/egg_lib/orch_cli.py:3265),cmd_consensus_ack --reason(parser at orch_cli.py:3485,3523),cmd_consensus_nack --reason(parser at orch_cli.py:3573), andcmd_consensus_withdraw --reason(parser at orch_cli.py:3600). Today these args are argv-only and re-introduce the shell-metachar corruption mitigated in docs: steer agents to the structured contract tool, not Bash-composed egg-contract #2741 when the wrapper bash composes the command. Reuse the--file PATHpattern from existingcmd_consensus_propose(orch_cli.py:2552). New flags:--summary-file PATH(propose),--reason-file PATH(ack / nack / withdraw),--files-reviewed-file PATH(ack / nack — JSON array on disk, one path per line per architect v2 §verification_strategy.slice_5), stdin sentinel--summary -/--reason -. Keep argv--summary/--reasonworking for now (deprecation lives in a later cycle) but emit a deprecation warning when used.--summary-file PATH/--reason-file PATH/--files-reviewed-file PATHround-trip multi-line UTF-8 prose containing shell metacharacters intact ($VAR, backticks,;,&&, newlines); stdin sentinel works forecho … | egg-orch consensus ack --reason -; argv path emits deprecation warning to stderr; existing CLI behavior preserved on argv path (regression test).egg-orch brc resolve-obligationCLI subcommand tosandbox/egg_lib/orch_cli.py. Wraps the existingmcp__brc__resolve_obligationhandler insandbox/egg_agent_tools/handlers/brc.py. Args:--reviewer-role,--producer-role,--commit-sha(optional),--note(optional; via stdin or--note-file PATHper the docs: steer agents to the structured contract tool, not Bash-composed egg-contract #2741 prose-arg rule from TASK-5-1).--noteexercised via stdin and via--note-file PATH.egg-orch brc read-peer-artifactCLI subcommand tosandbox/egg_lib/orch_cli.py. Wraps the existingmcp__brc__read_peer_artifacthandler. Args:--phase(required),--peer-role(optional),--message-type(optional, repeatable),--limit(default 50, max 500),--cursor(opaque token),--include-unattributed(default true). Stdout JSON.--limit+--cursorround-trip.docs/reference/agent-tools.md(or equivalent — locate via Grepdocs/for "consensus propose" / "consensus ack") anddocs/reference/agent-wait-patterns.mdto document the new--summary-file/--reason-file/--files-reviewed-fileflags and stdin sentinel, the two newbrc resolve-obligation/brc read-peer-artifactsubcommands, and the deprecation warning on the argv--summary/--reasonpath. Cross-link to docs: steer agents to the structured contract tool, not Bash-composed egg-contract #2741 for the shell-metachar rationale.tests/sandbox/egg_lib/test_orch_cli_prose_args.py(new file). For each ofconsensus propose --summary,consensus ack --reason,consensus nack --reason,consensus withdraw --reason: round-trip prose containing each of$VAR, single backticks,$(),;,&&, embedded newlines, UTF-8 non-ASCII characters — via stdin sentinel-AND via--*-file PATH— and assert byte-equality between the on-disk input and the request body received by the orchestrator stub. Also test the--files-reviewed-fileone-path-per-line semantics. Argv-path tests verify the deprecation warning lands on stderr.make test; one parametrized test per (CLI command × prose payload × delivery channel) case; deprecation-warning assertion present on the argv-path tests.tests/sandbox/egg_lib/test_orch_cli_brc.py(extending the file added in slice-1 TASK-1-8). Coverbrc resolve-obligationhappy path +--notevia stdin and via--note-file;brc read-peer-artifactpaginated round-trip; lifecycle-secret auth on both.make test; one test per subcommand's happy path plus pagination / prose-channel edge case.integration_tests/test_mcp_baseline_capture.py(directly underintegration_tests/;local_pipeline/does not exist). Drive a real-LLM 5-role consensus on the still-live MCP surface (slice-5 is additive only — MCP tools are still registered) using the session-scopedegg_stackfixture atintegration_tests/conftest.py:340(kubectl-gated; k3s-backed; agents run real Claude / Qwen via the litellm route configured for the test stack — noScriptedProviderreference; that class does not exist per reviewer_plan v2). Record per-event wall-clock samples (event_type, start_ts, end_ts, agent-process exit code as captured from the orchestrator's pipeline-status events, NOT from a non-existent in-process provider) and write to.egg-state/agent-outputs/latency-mcp-baseline.json. The committed JSON file is slice-6's baseline; capturing it in slice-5 sidesteps the vendored-tarball maintenance burden the original TASK-6-6 carried.egg_stackfixture (kubectl-gated; skips if_kubectl_available()returns False); produceslatency-mcp-baseline.jsonwith schema documented in the test file (samples: [{event_type, start_ts, end_ts, exit_code}]plus aggregate p50/p95); JSON file committed at the end of slice-5; slice-6 TASK-6-6 reads this file to derive its baseline. NoScriptedProviderimport or reference.Test Plan
Per-slice automated coverage:
reviewer / dual-role / open-NACK barrier Producer can re-propose after only one reviewer NACK in multi-reviewer BRC, wasting review cycles #2142 /
conditional ACK / stale-version Producer agent calls 'egg-orch message wait-loop --for CONSENSUS_CONFIRMED'; validator rejects #2482), memory-write
side-effects on
brc_ack/brc_nackcovering all sixrequired fields (incl.
last_reviewed_commit_shaperproducer); atomic-write contract test; fail-closed path
constructor test (raise on unset
EGG_AGENT_ROLE); CLIround-trip with lifecycle-secret auth.
wrapper-side heartbeat unit test asserting
slice_idpropagation from
EGG_SLICE_ID; idle-budget overseer-alertthreshold test; in-process
PeerConsensusTrackerregression(
integration_tests/regression/test_brc_*.py) with flag offestablishes zero orchestrator-side regression; E2E deferred
to slice-4 via
egg_stack(no in-process test double candrive a deployed pod end-to-end per Expand integration test coverage #2474).
compose_event_promptunit tests; collapsedpreamble snapshot; full git-log delta in per-event prompt
asserted; per-event prompt envelope (excluding delta) ≤ 10 KB;
sandbox-image rebuild verification (new mission.md reachable
in pod) BEFORE slice-4 flag flip.
spike was removed (qwen route unavailable in k3s; Claude-route
E2E blocked on ScriptedProvider pod injection, deferred to
Rewrite TestCredentialIsolation as k3s-native (currently skipped under k3s) #2585). The flag flip is gated on the slice-2 / slice-3 unit +
BRC in-process regression suites passing on the new default;
the deletions in TASK-4-2 are covered by the updated unit tests
in TASK-4-3.
--reason-file/--summary-file/--files-reviewed-fileround-trip tests for prose containing$VAR/ backticks /;/&&/ embedded newlines (docs: steer agents to the structured contract tool, not Bash-composed egg-contract #2741regression guard); CLI subcommand tests for
brc resolve-obligationandbrc read-peer-artifact; argv--reasondeprecation-warning test.server registered; migrated E2E runs first action as
consensus ack/nackvia stdin/file (preserves SDK-spawnexercise); per-event wall-clock latency within 5% of
pre-slice-6 baseline.
Manual verification:
so the new
mission.mdis reachable in the pod BEFORE slice-4flag flip.
(brc-memory content for reasoning fidelity;
last_reviewed_commit_shaupdated per producer; cost-per-phasedelta vs restart-churn baseline) and
consents to default-on flip via PR review.
mid-run against pre-slice agents; gate deploy on drain or
cancel.
Manual Steps
Pre-merge:
slice-4's flag flip (the new
mission.mdis the slice-4assumption; if pods are still running the old image when the
flag flips, the event-pump path will reference STAY-ALIVE
semantics that have been deleted from the preamble).
last_reviewed_commit_shacorrectness, cost delta)before the
EGG_BRC_EVENT_PUMPdefault flips to true.in-flight pipelines exist before deploy (MCP tools are deleted
so an old wrapper that still injects them starts with no MCP
server registered).
Post-merge:
"Agent exited without BRC consensus" entries; fall back via
EGG_BRC_EVENT_PUMP=falsedeployment env if seen. Rollbackpath for full spike falsification:
git revertslices 1–3 (noproduction traffic touched the new path because the flag
stayed off until slice-4).
wall-clock regression beyond the 5% budget.
Stack
issue-2908-impl2egg/issue-2908-impl2/slice-4Slice slice-5 of pipeline issue-2908-impl2. Stacked on top of
egg/issue-2908-impl2/slice-4.