[issue-3200][slice-4/10] Protected root (deterministic, resident... - #3239
Conversation
…k-4-1) Add shared/egg_anchor/protected_root.py: render_protected_root assembles the event-pump agent's protected root in a FIXED four-section order — (a) role contract, (b) task anchor (compose_task_description #3163 output, passed in), (c) the #3189 deterministic anchors (BRCDerivedAnchors from slice-3), (d) non-negotiable directives. Byte-stable for identical input: every keyed anchor collection is sorted (last_reviewed_sha by producer; verdicts/NACKs/obligations by (producer, reviewer)), list counts are bounded by hard caps, each free-form section is char-capped, and no timestamps/sequence numbers/nondeterministic ordering enter the output — so identical (role, contract, task, anchors, directives) renders identical bytes (cacheable prefix for #3186 resume; deterministic reseed source for the #3200 threshold reseed). Role-parameterized via the role header + role_contract arg, so two roles render distinct-but-each-stable roots. The renderer is pure (accepts already-composed strings; egg_anchor takes no new dep) and section (c) is sourced ONLY from the mechanically-derived BRCDerivedAnchors, never agent-authored prose, so the authoritative anchor layer cannot drift. Caps exposed as an overridable RootCaps dataclass (initial knobs). Exported render_protected_root + RootCaps from egg_anchor. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…, task-4-2) Adds shared/egg_anchor/tests/test_protected_root.py asserting the four task-4-2 acceptance properties for the slice-4 protected-root renderer: byte-stability (identical input -> identical bytes), hard per-section-cap truncation (free-text + #3189-anchor sections), sort-stability (output independent of dict-key / list-element input order), and role-parameterization (distinct-but-each-stable roots). Also asserts all four sections render in the fixed a->b->c->d order. Follows the parallel-BRC-producer skip-guard convention (see test_brc_anchor_derivation.py / test_reseed_threshold.py): flexible locators resolve the coder's renderer symbol across plausible spellings and call shapes (model-as-object-or-dict, directives-as-list-or-string, function-or-class) and pytest.skip until task-4-1 merges, keeping the suite green pre-merge and converging at PR assembly. Validated 6/6 PASS against a reference renderer; ruff clean. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…into egg/issue-3200-slice-4-tester/work
This comment has been minimized.
This comment has been minimized.
Autofix tracking{"Lint/Python": 1} |
This comment has been minimized.
This comment has been minimized.
There was a problem hiding this comment.
Contract Verification — PR #3239 (issue-3200, slice-4/10)
Verdict: Approve (posted as a comment — bot self-authored PR). All slice-4 tasks are complete and every task acceptance criterion is objectively met.
Scope checked
Contract slice-4 has two tasks. The contract's top-level acceptance_criteria list is empty and no ac-N criterion IDs exist, so criteria are the per-task prose strings — verified directly below. (The orchestrator was unreachable this run, so egg-contract verify-criterion could not be invoked regardless; there were no ac-N IDs to mark.)
task-4-1 — deterministic protected-root renderer
shared/egg_anchor/protected_root.py (+209), exported from shared/egg_anchor/__init__.py.
- Four sections in fixed order ✅ —
render_protected_rootemits## ROLE CONTRACT→## TASK→## BRC ANCHORS (#3189)→## NON-NEGOTIABLE DIRECTIVES. Verified at runtime: section offsets 38 < 59 < 73 < 125 (a→b→c→d). - Byte-stable across identical renders ✅ — all keyed collections are
sorted()(SHAs by producer; verdicts/NACKs/obligations by(producer, reviewer)), counts bounded by hard caps, free-text sections char-capped, and no timestamps/sequence numbers/random ordering enter the output. Re-render of identical input is byte-identical (confirmed live). - Role-parameterized ✅ —
roleflows into the header (=== PROTECTED ROOT — role: {role} ===) androle_contractinto section (a); two roles render distinct-but-each-stable roots. - Phase-3 layer authoritative for section (c) ✅ —
_render_anchorsconsumes only the mechanically-derivedBRCDerivedAnchors(slice-3); no agent-authored prose is inlined, so the anchor layer cannot drift from the message record.
task-4-2 — tests for deterministic rendering
shared/egg_anchor/tests/test_protected_root.py (+503).
- Byte-stability asserted ✅ —
test_render_is_byte_stable_across_identical_renders+ fixed-order assertion intest_render_contains_all_four_sections_in_fixed_order. - Per-section-cap truncation asserted ✅ —
test_oversized_freetext_section_is_truncated(4 MB role-contract is capped, head preserved) andtest_oversized_anchor_section_is_truncated(5 000-NACK flood bounded bymax_nacks/reason_chars). - Sort-stability asserted ✅ —
test_render_is_stable_regardless_of_input_ordering(reversed dict-key / list-element order → identical bytes). - Role-parameterization asserted ✅ —
test_two_roles_render_distinct_but_each_stable_roots. - Tests pass ✅ —
6 passedlocally (PYTHONPATH=shared pytest shared/egg_anchor/tests/test_protected_root.py). Note: against the stale/opt/egg-runtimeinstall the module fails to importBRCDerivedAnchors; pointing at the working-treeshared/(as CI does) collects and passes cleanly.
Notes (non-blocking)
- The diff includes two files outside slice-4's declared
files_affected—orchestrator/agent_model_resolution.py(−5/+1) andshared/egg_anchor/tests/test_brc_anchor_derivation.py(+6/−2). Both are pure auto-formatter line-reflows from theFix checks: apply automated formatting fixescommit (097ad8b); no behavioral change. Acceptable, just flagged for the human reviewer. - The
__all__insertion ofrender_protected_rootis slightly out of alphabetical order (sits beforeload_anchor). Cosmetic only. - Section (c) bounds its lists by count caps and caps NACK/condition reasons, but does not char-cap producer/SHA identifiers individually. Mechanically-derived inputs make this a non-issue in practice; noting for completeness.
No contract violations found. Phase consistency is fine (tasks implemented + tested, awaiting this verification gate before human merge).
— Authored by egg
This comment has been minimized.
This comment has been minimized.
There was a problem hiding this comment.
Review: Protected-root renderer (slice-4)
Verdict: No blocking issues. The renderer is correct, deterministic, well-documented, and the tests genuinely exercise the production path. I ran the targeted suite (test_protected_root.py → 6 passed, 0 skipped), ruff check, and ruff format --check — all green against the working copy. A few non-blocking notes below.
What I verified
- Field accesses match the models. Every attribute
_render_anchorsreads (last_reviewed_sha,latest_verdicts[].{reviewer,producer,verdict,version,reviewed_sha},open_nacks[].{reviewer,producer,version,reason},conditional_ack_obligations[].{reviewer,producer,version,condition,resolved}) lines up withegg_anchor/models.py.verdict.valueis valid on theReviewVerdictStrEnum. - Determinism holds. Every collection is sorted by a stable key, lists are count-capped with a visible
(+N more elided)marker, free-text sections are char-capped with a visible…[truncated]marker, and no timestamps/sequence numbers/set()iteration enter the output. The byte-stability and sort-stability claims check out. - Tests hit the real code path. Despite the elaborate locator/alias harness (written defensively on the tester branch against an unknown coder API), the first invocation variant passes the real
BRCDerivedAnchorsobjects through the real keyword signature — not a hand-built fixture bypass, not a self-seeded golden. The oversized-section tests exercise the actual caps (role_contract_chars=6000,max_nacks=24/reason_chars=300). - Truncation is signalled, not silent — both markers appear in output, so a pathological contract degrades visibly rather than dropping content silently.
except TypeError, ValueError:(test L200) is valid PEP 758 (project requires Python ≥3.14) and matches established codebase convention (83 existing unparenthesized multi-excepts). Not an issue.- No cross-module dead-end: the renderer has no downstream consumer yet — correct for a building-block slice that explicitly "feeds slices 5, 8, 9." The deliverable here is the deterministic renderer + tests, which is fully functional in isolation.
Non-blocking suggestions
-
Test harness can mask regressions (
test_protected_root.py)._renderer,_finalize, and_render_rawcallpytest.skip(...)on the "present but no call shape worked / non-text result / unmapped required params" paths. A future renderer regression that breaks every call shape would skip rather than fail — a green-looking suite hiding a broken function. Now that the coder API (render_protected_root(*, role, role_contract, task_description, derived, directives, caps)) is merged and known, the alias/variant machinery is dead weight. Consider collapsing to a direct keyword call so regressions fail loudly. -
Sort keys lack a final tiebreaker (
protected_root.py,_render_anchors).latest_verdicts,open_nacks, andconditional_ack_obligationssort by(producer, reviewer). Python'ssortedis stable, so two entries sharing that key render in input order — a latent (currently unreachable, since the derived layer is one-per-edge) nondeterminism. Conditional-ACK obligations are the most plausible place for multiple entries per edge. Addingversion/sha/conditionto the key would make byte-stability robust to that case rather than relying on the upstream deriver. -
_truncateceiling assumesmax_chars ≥ len(marker)(13). If a caller overridesRootCapswith a sub-13 char cap,keepclamps to 0 and the function returns the 13-char marker alone — exceeding the documented "hard ceiling including the marker." Defaults (≥300) never hit this, but a clamp/assert would make the contract hold for custom caps. -
Trivial: a truncated NACK reason embeds the marker's leading
\n, so an over-long reason cosmetically splits its indented anchor line. Harmless. -
Unrelated format-only churn in
orchestrator/agent_model_resolution.pyandtest_brc_anchor_derivation.py(behavior-identical, from the auto-format commit). Fine, just noise in an otherwise tightly-scoped slice.
— Authored by egg
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
1 similar comment
This comment has been minimized.
This comment has been minimized.
- Add version/sha/condition tiebreakers to anchor sort keys so the render stays byte-stable even if the derived layer emits >1 entry per edge - Clamp _truncate so the result never exceeds max_chars for sub-marker caps - Space-prefix the truncation marker so a capped NACK reason no longer splits its inline anchor line - Collapse the defensive locator/alias/variant test harness to a direct keyword call now that the renderer API is merged — regressions fail loudly - Fix __all__ alphabetical ordering in egg_anchor/__init__.py
Review feedback — dispositionsThanks for the thorough review. Both reviews were "no blocking issues"; the actionable non-blocking items are addressed below. All in commit egg-reviewer[bot]:
james-in-a-box[bot] (contract verification):
— 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.
There was a problem hiding this comment.
Re-review: Protected-root renderer (slice-4) — feedback addressed
Verdict: No blocking issues. Every actionable item from my prior review is correctly addressed in 50e2e3a, and the two disagreements are well-reasoned. I re-read the renderer and tests against the merge base, confirmed the model field accesses, and ran the targeted suite (test_protected_root.py → 6 passed). Approving.
Fixes verified
-
Test harness collapse (item 1) —
_rendernow callsrender_protected_root(**inputs)directly; the locator/alias/pytest.skipmachinery is gone (net −248/+65). The fixed-order test (test_render_contains_all_four_sections_in_fixed_order) asserts presence then order unconditionally (L178–181), so a renderer regression fails loudly instead of skipping. Tests genuinely exercise the production path — direct import, realBRCDerivedAnchors, no hand-built fixture bypass, no self-seeded golden. -
Sort tiebreakers (item 2) — all three keyed sorts now carry final tiebreakers: verdicts
(producer, reviewer, version, reviewed_sha or ""), NACKs(…, version, reason or ""), obligations(…, version, condition or "", resolved). I confirmed againstmodels.pythat every tiebreaker field exists and each tuple position is homogeneously comparable (str/int/bool); theor ""guards keep the keys total even thoughreviewed_sha/reasonalready default to"". Byte-stability no longer relies on the deriver being one-per-edge. -
_truncateclamp (item 3) — a sub-marker cap (max_chars <= 13) now hard-trims totext[:max_chars]rather than returning the bare 13-char marker, so the documented "≤max_charsincluding the marker" guarantee holds for any customRootCaps. The==13boundary is handled correctly. -
Space-prefixed marker (item 4) —
" …[truncated]"keeps a capped inline value (e.g. a NACK reason) on its own indented anchor line. -
__all__ordering (item 6) —render_protected_rootmoved afterload_anchor,RootCapsbetweenReviewVerdictandTaskInfo; both alphabetical again.
Disagreements — both reasonable
- Format-only churn (item 5) — the
agent_model_resolution.pyandtest_brc_anchor_derivation.pydiffs are pure ruff line-length reflows; behavior-identical, and reverting would re-fail the Lint check that produced them. Agreed, leave as-is. - No per-identifier char-cap in section (c) (item 7) — section (c) is sourced only from the mechanically-derived
BRCDerivedAnchors, where producer roles and SHAs are bounded by construction and the count caps bound the lists. No unbounded path exists. Agreed.
Non-blocking (optional, not requesting changes)
- The new tiebreaker logic and the
_truncatesub-marker clamp are not directly exercised by a test (no duplicate-edge input, no sub-13 custom cap). Both guard currently-unreachable cases, so this is fine for a building-block slice — but a one-line duplicate-edge fixture and acaps=RootCaps(reason_chars=5)assertion would lock in the robustness you just added.
— Authored by egg
This comment has been minimized.
This comment has been minimized.
There was a problem hiding this comment.
Contract re-verification — PR #3239 (slice-4: deterministic protected-root renderer)
Verdict: Approve. Incremental re-review of the delta since my last review at 097ad8be. The single new commit 50e2e3ae ("Address review feedback") cleanly addresses prior review feedback, strengthens determinism and test coverage, and introduces no regressions to previously-verified acceptance criteria.
Delta reviewed
git show 50e2e3ae — exactly 3 files:
shared/egg_anchor/protected_root.py(+42/−... )shared/egg_anchor/tests/test_protected_root.py(−248 net; harness collapse)shared/egg_anchor/__init__.py(__all__reorder)
Each feedback item verified against the diff
- Sort-key tiebreakers —
verdictsnow sort by(producer, reviewer, version, reviewed_sha),open_nacksby(producer, reviewer, version, reason),obligationsby(producer, reviewer, version, condition, resolved). I confirmed every tiebreaker field exists with a consistent, sortable type on the corresponding model inshared/egg_anchor/models.py(ReviewEdgeVerdict.version:int/reviewed_sha:str,OpenNack.version:int/reason:str,ConditionalAckObligation.version:int/condition:str/resolved:bool). Strengthens the byte-stability guarantee for the case where the derived layer emits >1 entry per edge. ✅ _truncateclamp — the newif max_chars <= len(_SECTION_TRUNCATION_MARKER): return text[:max_chars]branch closes a real bug: previously a sub-marker cap (max_chars < 13) returned the 13-char marker alone, exceeding the documented "hard ceiling including the marker." Now the ceiling holds for any cap. Verified the length arithmetic at the boundaries (max_chars == 13→ 13;== 14→ ≤14 viakeep=1). ✅- Space-prefixed truncation marker (
" …[truncated]"vs"\n…[truncated]") — same length (13 chars), determinism-preserving; prevents a capped NACK reason from splitting its own inline anchor line. ✅ - Test harness collapse — the defensive locator / alias /
_variantsskip-guard machinery was removed in favor of a directrender_protected_root(**inputs)keyword call. This is a net coverage improvement: a renderer regression now fails loudly instead of being masked bypytest.skip. As a side benefit it removes a latentexcept TypeError, ValueError:(Py2 syntax) that lived in the deleted_render_raw. All four acceptance properties (byte-stability, per-section-cap truncation, sort-stability, role-parameterization) plus fixed a→b→c→d ordering remain asserted, now unconditionally. ✅ __all__alphabetical fix —load_anchornow precedesrender_protected_root. Correct. ✅
Acceptance criteria status
- task-4-1 (renderer: four sections in fixed order; byte-stable across identical renders; role-parameterized; section (c) sourced authoritatively from
BRCDerivedAnchors): re-verified — the structure is unchanged and the delta only tightens determinism. Holds. - task-4-2 (byte-stability, per-section-cap truncation, sort-stability, role-parameterization each asserted; tests pass): re-verified — assertions are now unconditional. Ran the targeted suite at HEAD:
pytest shared/egg_anchor/tests/test_protected_root.py→ 6 passed. Holds.
No previously-verified criterion is broken by this delta; no orphaned code or scope creep.
Note: the orchestrator is currently
UNREACHABLE(gateway healthy), soegg-contract verify-criterion --criterion ac-Ncould not be recorded mechanically this run. The verification conclusion above stands; criteria can be marked once the orchestrator recovers.
— Authored by egg
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
Review feedback — dispositions (re-review round)Both re-reviews approved with no blocking issues. The single actionable non-blocking item from the latest round is addressed below. egg-reviewer[bot] (re-review):
james-in-a-box[bot] (contract re-verification): Approve, no new actionable items. Note: — Authored by egg |
This comment has been minimized.
This comment has been minimized.
There was a problem hiding this comment.
Contract re-verification — PR #3239 (issue-3200, slice-4)
Verdict: approve. Incremental re-review since my last verification at 50e2e3a.
Delta reviewed
Excluding .egg-state/ worktree artifacts, the only change since my last review is a single commit:
c0cf38fa— Add tests for tiebreaker determinism and sub-marker truncation clamp
It touches exactly one file: shared/egg_anchor/tests/test_protected_root.py (+94 lines, test-only). No production code changed, so no previously-verified property of the renderer can have regressed.
What the new tests assert (both correct against the implementation)
-
test_duplicate_edge_entries_are_byte_stable_via_tiebreakers— feeds two entries for the same(producer, reviewer)edge into each derived list and permutes input order. This exercises the secondary sort keys inprotected_root.py(render_protected_root's_render_anchors):- verdicts:
key=lambda v: (v.producer, v.reviewer, v.version, v.reviewed_sha or "")(protected_root.py:138) - nacks:
(n.producer, n.reviewer, n.version, n.reason or "")(:154) - obligations:
(o.producer, o.reviewer, o.version, o.condition or "", o.resolved)(:172)
The tiebreakers disambiguate the duplicate edges, so the reversed-input render is byte-identical — locking in sort-stability beyond the primary key. This strengthens task-4-2's sort-stability criterion.
- verdicts:
-
test_sub_marker_cap_hard_trims_without_marker— drives_truncatewithRootCaps(reason_chars=5), below the 13-char_SECTION_TRUNCATION_MARKERlength. Themax_chars <= len(marker)branch (protected_root.py:82-84) hard-trims totext[:5]rather than emitting a longer marker-only string. Assertions ("abcde"present,"abcdef"and"…[truncated]"absent) match this exactly — locking in the documented "hard ceiling including the marker" guarantee for any customRootCaps. This strengthens task-4-2's per-section-cap truncation criterion.
Verification performed
pytest .../test_protected_root.py— 8 passed (the 2 new + 6 prior), confirming the new tests pass and the previously-verified properties (byte-stability, fixed four-section order, per-section caps, sort-stability, role-parameterization) still hold.
Notes for the human reviewer
- Both new tests are robustness guards for cases the docstrings note are currently unreachable via the upstream deriver. They are pure regression locks against a future change dropping a tiebreaker or marker clamp — appropriate and low-risk additions, not dead code masking a gap.
- I could not call
egg-contract verify-criterion: the orchestrator is unreachable from this session, and the contract's top-levelacceptance_criterialist is empty (slice-4's criteria are carried as free-text ontask-4-1/task-4-2). There is noac-Nid to mark. The substance of task-4-2's four acceptance properties is, however, asserted and passing.
No contract violations found. The delta is additive test coverage that tightens slice-4's deterministic-rendering guarantees.
— Authored by egg
This comment has been minimized.
This comment has been minimized.
There was a problem hiding this comment.
Re-review: protected-root renderer (slice-4) — robustness tests added
Verdict: No blocking issues. The only change since my last review (50e2e3a) is the single commit c0cf38f, which adds the two tests I suggested as a non-blocking item last round. Both are correct, exercise the production code path, and have accurate assertions. Approving.
Delta reviewed
c0cf38f touches one file: shared/egg_anchor/tests/test_protected_root.py (+94/−1). No production code changed; the rest of the PR is unchanged from my prior approval.
New tests verified
-
test_duplicate_edge_entries_are_byte_stable_via_tiebreakers— buildsBRCDerivedAnchorswith genuine duplicate(producer, reviewer)edges acrosslatest_verdicts,open_nacks, andconditional_ack_obligations, then asserts_render(forward) == _render(reversed). This calls the realrender_protected_rootthrough_renderwith a real model — no hand-built fixture bypass, no self-seeded golden. Because Python'ssortedis stable, reversing duplicate-edge input would change output order if the discriminating tiebreaker were dropped, so the test fails loudly on regression. ✅ -
test_sub_marker_cap_hard_trims_without_marker— renders a 100-char NACK reason withcaps=RootCaps(reason_chars=5), hitting the_truncatemax_chars <= len(_SECTION_TRUNCATION_MARKER)branch. I traced it:_truncate("abc…"*, 5)→len > 5and5 <= 13→text[:5]="abcde". Assertions"abcde" in text,"abcdef" not in text, and marker-absent are all exactly correct, and the canonical inputs use default caps everywhere else so no spurious truncation can leak the marker into the output. ✅
I confirmed all model fields the tests construct exist with the expected types in shared/egg_anchor/models.py (ReviewEdgeVerdict.version:int/reviewed_sha:str, OpenNack.version:int/reason:str, ConditionalAckObligation.version:int/condition:str/resolved:bool).
Non-blocking (optional)
- In test 1, every duplicate pair carries a distinct
version, so only theversiontiebreaker is actually discriminating — thereviewed_sha/reason/condition/resolvedtiebreakers wouldn't be caught if dropped (they only matter whenversionalso collides). The docstring slightly overstates coverage ("only the version/reason/condition/resolved tiebreakers keep the render byte-stable"). Not a defect: the test locks in the primary tiebreaker and the duplicate-edge case is unreachable in production by construction. A future tightening could add a pair that collides onversionto exercise the secondary keys.
Note: I did not run the full suite per review policy (CI gates this PR). The change is test-only and I verified the logic by reading.
— Authored by egg
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
1 similar comment
This comment has been minimized.
This comment has been minimized.
Cover the case where >1 anchor entry shares (producer, reviewer, version), so byte-stability rests only on the secondary sort key (reviewed_sha for verdicts, reason for NACKs, condition/resolved for obligations). The existing duplicate-edge test only varied version, leaving the secondary tiebreakers unexercised; correct its docstring accordingly.
Review feedback — dispositions (re-review round 2)Both re-reviews at egg-reviewer[bot] (re-review):
james-in-a-box[bot] (contract re-verification): Approve, no new actionable items. — Authored by egg |
This comment has been minimized.
This comment has been minimized.
There was a problem hiding this comment.
Re-review: secondary-tiebreaker test (slice-4) — coverage gap in the obligation case
Verdict: No blocking issues, one non-blocking correction. The only change since my last review (c0cf38f) is c2f0201, which adds test_version_collisions_disambiguated_by_secondary_tiebreakers to address my prior non-blocking note that the existing duplicate-edge test only exercised the version tiebreaker. The new test is real (calls render_protected_root via _render, no hand-built fixture, no self-seeded golden) and passes. But it does not fully deliver on its docstring, and the gap is exactly the class of overstatement this commit was created to close.
What I verified (mutation testing against protected_root.py)
I dropped each secondary key from the production sort keys and reran the new test:
| Mutation | Result | Conclusion |
|---|---|---|
drop reviewed_sha from verdict key (:138) |
FAIL ✅ | reviewed_sha genuinely isolated |
drop reason from NACK key (:154) |
FAIL ✅ | reason genuinely isolated |
drop condition from obligation key (:172), keep resolved |
PASS ❌ | condition not isolated |
drop resolved from obligation key, keep condition |
PASS ❌ | resolved not isolated |
drop both condition and resolved |
FAIL | only the pair is locked |
So the verdict and NACK sections are correct — each secondary key is the sole discriminator. But the two obligation entries differ in both condition ("aaa condition" vs "zzz condition") and resolved (False vs True) simultaneously:
ConditionalAckObligation(..., version=2, condition="aaa condition", resolved=False),
ConditionalAckObligation(..., version=2, condition="zzz condition", resolved=True),Because either key alone disambiguates the pair, a regression that drops condition from the sort key (but keeps resolved) — or vice versa — slips through silently. The docstring asserts the opposite:
...
condition/resolvedfor obligations. Reversing the input must still render identically; dropping any of those secondary keys makes the two renders diverge and this test fail loudly.
That claim is false for condition and resolved individually. This is the same "docstring overstates which secondary keys are independently locked" issue I flagged last round for the original test — fixed for verdicts/NACKs here, but reintroduced for obligations.
Suggested fix (non-blocking)
Split the obligation coverage into two pairs so each key is the sole discriminator, mirroring how the verdict/NACK pairs already work:
conditional_ack_obligations=[
# Pair 1: same resolved -> only `condition` discriminates
ConditionalAckObligation(reviewer="reviewer_security", producer="coder",
version=2, condition="aaa condition", resolved=False),
ConditionalAckObligation(reviewer="reviewer_security", producer="coder",
version=2, condition="zzz condition", resolved=False),
# Pair 2: same condition -> only `resolved` discriminates
ConditionalAckObligation(reviewer="reviewer_docs", producer="coder",
version=2, condition="same condition", resolved=False),
ConditionalAckObligation(reviewer="reviewer_docs", producer="coder",
version=2, condition="same condition", resolved=True),
],With that, dropping either condition or resolved alone fails the test, matching the docstring. (Note resolved is the last sort element, so a pair sharing condition and differing only on resolved exercises it as the sole discriminator.) Alternatively, weaken the docstring to state honestly that only the combined (condition, resolved) ordering is locked.
Why non-blocking
This is test-only; the renderer works and is unchanged. The test still locks reviewed_sha, reason, and the combined obligation ordering, so it strengthens the suite over the prior state. The residual is a precision gap in test coverage plus an inaccurate docstring — worth correcting since the commit's stated purpose was precisely to close this gap, but not a correctness defect in shipping code.
— Authored by egg
This comment has been minimized.
This comment has been minimized.
There was a problem hiding this comment.
Contract Re-verification — PR #3239 (slice-4/10, protected-root renderer)
Incremental re-review of the delta since my last verification at c0cf38fa.
Delta reviewed
git log c0cf38fa..c2f02011 is a single, test-only commit touching shared/egg_anchor/tests/test_protected_root.py (+67/−4):
- Adds
test_version_collisions_disambiguated_by_secondary_tiebreakers— exercises the case where entries collide on(producer, reviewer, version), so byte-stability rests only on the trailing tiebreaker keys. - Tightens the docstring of the existing
test_duplicate_edge_entries_are_byte_stable_via_tiebreakersto scope it to theversiontiebreaker and cross-reference the new test.
Verification
- Keys match the implementation. The new test's distinct fields line up exactly with the renderer's sort keys in
shared/egg_anchor/protected_root.py:reviewed_shafor verdicts (:138),reasonfor NACKs (:154),condition/resolvedfor obligations (:172). Each colliding pair shares(producer, reviewer, version)and differs only on the secondary key, then asserts_render(forward) == _render(reversed). - Non-vacuous. I confirmed via mutation: dropping
reviewed_shafrom the verdicts sort key makestest_version_collisions_disambiguated_by_secondary_tiebreakersfail. Reverted immediately; working tree clean. - Passes. All 9 tests in
test_protected_root.pypass locally (targeted run, not the full suite). - No regression risk. The delta is purely additive test code — no production source changed — so the previously-verified task-4-1 criteria (fixed section order, byte-stability, role-parameterization, phase-3 layer authoritative) are unaffected. The change strengthens task-4-2's sort-stability acceptance criterion ("key ordering stable regardless of input dict order").
Contract state
The orchestrator was unreachable this session (egg-orch health → Orchestrator: UNREACHABLE), so egg-contract show / verify-criterion could not be run and criteria could not be re-marked programmatically. The slice-4 acceptance criteria were already verified in my prior review at c0cf38fa; this delta does not regress them and adds coverage for the secondary-tiebreaker branch.
Verdict
No contract violations. The incremental change is sound and well-targeted. Approving from a contract-verification standpoint.
— Authored by egg
|
egg contract-verification completed. View run logs 19 previous review(s) hidden. |
|
Automated feedback loop has reached the maximum of 5 rounds. Human review is needed to make further progress on this PR. |
Small, byte-stable, role-parameterized resident root rendered from the phase-3 #3189 anchors. Logical dep: slice 3 (the anchors it renders). Feeds slices 5, 8, 9.
Base PR: #3234
What's in this PR
Commits (3):
This slice
Protected root (deterministic, resident, AC-2 part 1)
Files affected:
shared/egg_anchor/shared/egg_agent/shared/egg_anchor/tests/shared/egg_agent/tests/Tasks (2) + acceptance criteria
Stack
issue-3200egg/issue-3200/slice-3