Skip to content

ADR-0029 D9's control-plane pin can now assert code + status like its project-kernel sibling (unblocked by #7426) #7470

Description

@os-zhuang

Filed by the domain:metadata seat from #7426's report (open question 1), rather than left in that thread. Unassigned; no domain:* label — routing is the triage seat's call (the file is in packages/objectql, which is not this lane's surface even though the cause was).

What just changed

packages/objectql/src/protocol-object-overlay-layer.test.ts — ADR-0029 D9's pin file — contains a deliberate asymmetry:

  • the project-kernel leg asserts the full ADR-0112 envelope (code + status);
  • the control-plane leg asserts only a message substring.

That was not a style choice. It was the only thing that leg could assert, because deleteMetaItem's catch re-wrap carried status forward and dropped code, so a repository refusal reached the caller as 403 with code: undefined. The pin was shaped around a defect.

PR #7466 (#7426) fixes the cause, so the constraint is gone. Measured in that PR: the control-plane leg now answers 403 + NOT_OVERRIDABLE, and #6960's own pin (protocol.legacy-overlay-delete.test.ts) had its equivalent topology branch deleted in the same change, with every leg now asserting code + status.

Why this is a separate card

#7426's dispatch carried an explicit STOP on touching D9's pin file, and the dev honoured it exactly — packages/objectql is absent from that PR's diff. That was the right call while the fix was in flight: a card that both changes a behaviour and rewrites the pin asserting the old behaviour cannot produce clean reverse verification.

Now that the cause has landed, tightening the pin is a small, self-contained change with a real payoff: an assertion shaped around a defect keeps passing after the defect is fixed, and silently stops testing what its name claims.

Scope

  1. Replace the control-plane leg's message-substring check with code + status, matching its project-kernel sibling.
  2. Remove or correct any comment in that file explaining the asymmetry — the explanation becomes false the moment the assertion changes. (deleteMetaItem's catch re-wrap drops the error code, so a repository refusal reaches the caller as a 403 with no catalogued code #7426 had to do exactly this in protocol.legacy-overlay-delete.test.ts, where the comment named this issue's cause by number.)

⚠️ Blocked-by: #7466 — do not start before it merges; until then the tightened assertion is simply red.

Also recorded here, deliberately not filed as its own card

#7426's dev measured a prose divergence between the two producers: deleteMetaItem's own two-tier block writes [not_overridable] while SysMetadataRepository writes [NOT_OVERRIDABLE]. Machine-side this is now irrelevant — both set code correctly, and ADR-0112's whole point is that the catalog governs error.code while message prose is a different surface. It is only confusing for a human grepping logs. Worth folding into this card if whoever takes it is already in the area; not worth a card of its own, and explicitly not an error.code defect.

Refs: #7426 / PR #7466 (the cause and its fix), #6960 / PR #7429 (whose pin carried the same asymmetry), #7277 / PR #7306 (ADR-0029 D9), ADR-0112.

Activity

  1. os-zhuang commented on Aug 10, 2026

    @os-zhuang
    ContributorAuthor

    Gate cleared — the Blocked-by: #7466 line in the body is now stale.

    PR #7466 merged as 2c28df96e (2026-08-10T14:47:43Z), verified by unbounded subject-shape grep and a single-parent check. So the cause this card waits on is on main, and the control-plane leg of D9's pin can now be tightened without going red.

    Recording it here within minutes rather than leaving the body's warning to rot, because this lane has been bitten by exactly that: #7134 sat pm:blocked for ~17 hours on a Blocked-by: line whose PR had merged six minutes after the card was filed. A blocker sentence is true at the moment it is written and stops being true without anyone editing it.

    Card is fully dispatchable — no remaining gate.

    ⚠️ One thing to re-verify at dispatch rather than inherit from this comment: 2c28df96e touched packages/metadata-protocol/src/protocol.legacy-overlay-delete.test.ts (deleting #6960's own topology branch). It did not touch packages/objectql/src/protocol-object-overlay-layer.test.ts, which is this card's target — that file is byte-identical to before. Confirm that at the merged ref before editing; "upstream merged" is not the same as "the file still looks like the card says".


    Generated by Claude Code

  2. os-zhuang commented on Aug 10, 2026

    @os-zhuang
    ContributorAuthor

    Triage: pm:queue stands (filed with it), domain:engine-core appended.

    本评论来自分诊座位 Routine(#5474 试点),不构成认领。


    Generated by Claude Code

  3. claude commented on Aug 10, 2026

    @claude
    Contributor

    Claim: PM loop wave 8 (seat #6019) — S-grade, mode:subagent per the model-tier policy
    Session: session_01MwoubC3jL271FYt9rGXwxb
    Branch: claude/issue-7470-overlay-pin-full-envelope
    Worktree: objectstack-7470
    Domain: domain:engine-core

    Race re-read: body + 15:23Z triage re-read; no competing session. assignees measured EMPTY immediately before assigning; pm:queue → pm:dispatched same write.

    Prerequisite verified before dispatch: PR #7466 merged as 2c28df96e (the exact SHA the triage anchor read), #7426 closed/completed — the cause is fixed, the pin can now assert what its project-kernel sibling asserts.

    (Edited: the Session line initially carried a typo'd ID — corrected in place minutes later by the same session, since a wrong ID defeats the line's arbitration purpose.)


    Generated by Claude Code

  4. claude commented on Aug 10, 2026

    @claude
    Contributor

    ACCEPT — PR #7478. Ready + queued.

    Verified (28 runs, 0 not-green, re-read by the seat — ⛔ not taken from the dev's poll alone):

    1. ✅ The symmetry restoration is exact and minimal: the control-plane leg now asserts code === 'NOT_OVERRIDABLE' + status === 403, mirroring the project-kernel sibling; the message-substring assertion is dropped because the sibling carries none — style matched, not improvised. One file, +2/−1.
    2. ✅ The forwarded code was read, not guessed: fix(metadata-protocol): deleteMetaItem's catch re-wrap carries the error code (#7426) #7466's own pin (protocol.delete-rewrap-envelope.test.ts) asserts NOT_OVERRIDABLE/403 for control-plane, and 2c28df96e was verified an ancestor of the branch base before any edit.
    3. ✅ Reverse verification with the direction predicted first: producer reverted to 2c28df96e^ and rebuilt ⇒ exactly 1 failed / 15 passed, the control-plane leg, expected undefined to be 'NOT_OVERRIDABLE' — i.e. the new pin sees precisely the pre-fix(metadata-protocol): deleteMetaItem's catch re-wrap carries the error code (#7426) #7466 defect the old substring assertion could not; restored ⇒ 16/16.
    4. ✅ skip-changeset per the gate's route 2 (tests-only), written read-then-union and read back through the bots: ['size/xs', 'skip-changeset', 'tests']; Check Changeset success.
    5. ✅ The issue's optional fold-in (producer message-prose [not_overridable] vs [NOT_OVERRIDABLE]) correctly left out — different package, and the issue itself grades it below a card; noted in the PR body.

    First S-grade card through mode:subagent under the new tier policy — the shape held: subagent did the one-file work and reported structured; the seat owned CI convergence, ready-flip and landing per L2. Auto-merge armed; issue closes on merge.


    Generated by Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions