Skip to content

test(spec): pin proof 4's message-includes leg with a fifth check-mode box - #19754

Merged
os-support-ai merged 1 commit into
mainfrom
claude/issue-18865-proof4-delivers-fixture
Sep 23, 2026
Merged

os-support-ai merged 1 commit into
mainfrom
claude/issue-18865-proof4-delivers-fixture

Conversation

@os-support-ai

Copy link
Copy Markdown
Collaborator

Fixes #18865

Clause-②: no

delivers() in packages/spec/scripts/build-schemas.ts is a conjunction, and proof 4's
check (c) counts a refusal it cannot read as "no evidence", never as proof:

return issue !== undefined && issue.message.includes(prescription);

The left half — "the door refused this write" — is defended by the ui/ViewItem fixture,
which asserts the probe raises no unrecognized_keys issue at all. So && short-circuits
in it and the RIGHT half is never evaluated. That half is the only thing that separates a
def parsing through its declaration's own error map from a strict CLONE built to the same
declaration without it. Before this PR it was defended by a zero.

The card asserts "no fixture would fire", not "it is already broken". This PR does not
claim the leg has ever failed silently in the tree, and it measured no such thing.

What lands

One fifth sandbox in this harness, built in the shape of the four that already copy src/,
plus two cases:

case this box's strictObject verdict exit
LIT error map dropped declared-but-silent 1
DARK the tree's own bytes prescribed, deletion waived 0

A gate that lost the message conjunct turns the LIT case red and leaves the DARK one green.
⚠️ The failure direction is "reads as compliant" — a defeated leg WAIVES the deletion, it
does not add a "no evidence" row — which is why both directions are pinned, not just one.

Re-derived, not inherited

Read at branch head cbb3521fe5 in this worktree, 2026-09-22T22:07Z. The line numbers the
card and its triage comment cite were taken on 2026-09-18 and have all moved; the sites
below are given by shape and by their reading today.

reading on origin/main c120dbdfb8 on cbb3521fe5
harness length 4531 lines 4812 lines
it( cases 85 87
symlinkSync sites 6 7
sites whose entry array still names src 1 (the shared createSandbox, :476) 1 (unchanged)
cpSync of PKG/src into a box 4 (:3438 :3737 :4103 :4367) 5 (:4695 added)

So the shared createSandbox and the 85 cases that run through it are untouched: the diff
is one appended describe block and one import { z } from 'zod'.

The pin can fail — ablation, on disk, both legs proven

node scripts/ablation-replace.mjs in WRAP mode on packages/spec/scripts/build-schemas.ts,
anchor return issue !== undefined && issue.message.includes(prescription); replaced by
return issue !== undefined; — the message leg, and nothing else. 2026-09-22T22:10Z.

anchor   "return issue !== undefined && issue.message.includes(prescription);"  x1 (before)
  anchor hits 1 time(s), as declared
anchor   x1 -> x0
replace  "return issue !== undefined;"  x0 -> x1
blob     c886e1778316b5ff8c3d1780b599e8bcb50c1970 -> 3cccd072c9cfe48685728086055cefef6cb7b52a
ok mutation landed: anchor 1 -> 0, blob c886e1778316 -> 3cccd072c9cf

Result, the two cases under -t '#18865':

 × LIT — a strict clone that does not carry its declaration's error map is NOT proof: the deletion is refused
AssertionError: expected +0 to be 1 // Object.is equality
- Expected   1
+ Received   0
 ❯ scripts/build-schemas-check-mode.test.ts:4751:22  ->  expect(status).toBe(1)
      Tests  1 failed | 1 passed | 85 skipped (87)

The LIT case goes red for the ablated reason: with the conjunct gone the gate exits 0 —
it waives the deletion, which is the card's stated failure direction — and the DARK case
stays green, so the pair discriminates "reads the message" from "refuses everything".

Restore, proven on disk rather than by an exit code:

restore packages/spec/scripts/build-schemas.ts
  blob after restore  c886e1778316b5ff8c3d1780b599e8bcb50c1970
  blob at HEAD        c886e1778316b5ff8c3d1780b599e8bcb50c1970
  git diff HEAD       empty
ok restored: blob == HEAD (c886e1778316) and `git diff HEAD` is empty

Green again on restore: the full 87-case run below passes both cases with the generator back
at its HEAD bytes.

Route A stays out, measured

@objectstack/spec's files[] carries src/**/*.zod.ts, so a synthetic def written into
the real src/ would ship in the tarball. This fixture writes only into the BOX's own copy
of src/, and the repo's src/ is never touched. npm pack --dry-run --json on a real
build of @objectstack/spec (built at 2026-09-22T22:16Z), run on this branch and again with
the one changed file restored to c120dbdfb8:

entries diff
before (c120dbdfb8 bytes of the one changed file) 2031 —
after (this branch) 2031 byte-identical file lists, diff exit 0, 0 lines

Controls on the after list:

  • POSITIVE — src/shared/http.zod.ts present, src/system/stack-server.zod.ts present,
    204 src/ entries in all: the instrument does reach the directory a route-A fixture would
    have landed in.
  • NEGATIVE — scripts/build-schemas-check-mode.test.ts absent; scripts/ contributes 0
    entries; src/shared/strict-object.ts (not a .zod.ts) absent.
  • DARK — src/shared/http.zod.tsx, a name that does not exist, absent.

The file this PR changes is the only file it changes, and it publishes nothing.

The cost this adds, measured here, and what the measurement can and cannot resolve

Both runs: vitest run --project repo scripts/build-schemas-check-mode.test.ts --reporter=verbose,
through the shared heavy-verify lock on one shared 4-core box with sibling agents active —
the before arm queued 123s behind another locked run and the after arm queued 161s, so these are
shared-box seconds, not idle-box figures. The two trees differ in exactly the one file.

arm tree cases vitest Duration
before the one changed file at c120dbdfb8 (blob 18100c70f8, 4531 lines) 85 632.50 s
after this branch (blob 326a8c9466, 4812 lines) 87 646.38 s

Whole-suite delta: +13.88 s (+2.19 %). ⚠️ That number is NOT distinguishable from
run-to-run noise
, and it is not the cost. The control for it is inside the same pair: the
85 cases that are byte-identical in both arms summed 623.31 s in the after run and
625.88 s in the before run — the unchanged work measured 2.57 s FASTER in the arm that
was supposed to be slower, and its summed per-case absolute drift was 31.05 s (median
290 ms, p90 720 ms, max 1352 ms per case). A 13.88 s whole-run delta sits inside that.

The figure that IS resolvable is the direct one: the two new cases are new work and were timed
individually — 7.803 s + 8.342 s = 16.14 s, 2.50 % of the after run. Both land between
this harness's own p75 (7.405 s) and its max (19.08 s), against a per-case mean of 7.35 s, which
is what two ordinary gate spawns cost here; the one extra src copy this box pays is not
separately resolvable at that scale. Sandbox construction is not where this harness spends its
time — 87 gate spawns are.

Plainly: the box costs about two cases' worth, the suite total moved by less than its own
noise, and nothing here supports quoting the whole-run delta as a cost.

Verification

  • pnpm exec vitest run --project repo scripts/build-schemas-check-mode.test.ts — 87 passed
    (87)
    , exit 0, 2026-09-22T22:41Z. The build-schemas-check-mode case count moves 85 to 87.
  • pnpm --filter @objectstack/spec test — the local project, which is where the package's
    test script points; this harness is in the repo project and is run separately above.
    515 files passed, 15043 passed | 1 todo (15044), exit 0, 183.81 s, 2026-09-22T22:59Z.
  • pnpm --filter @objectstack/spec typecheck — exit 0, 50 s, same window.
  • Gate families derived from this worktree with
    node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commands (it reports
    the tree it read: objectstack-ai/objectstack at cbb3521fe5, 1 changed path, 281 changed
    lines). 57 commands, each exit code captured before any pipe: 54 exit 0, 3 exit 3.
  • The three exit-3 rows are NOT MEASURED, and NOT a pass: check:dual-build-cjs-loads,
    check:lean-entry-closure and check:type-check-debt each print PREREQUISITE NOT MET and
    refuse because this worktree has dist/ for @objectstack/spec only. Each reads BUILT output
    of packages this diff does not touch; the reading CI takes on a fully built tree is the one
    that counts. Reconciled with --ran.
  • dispatch-gates.mjs also names, as outside those 57 and therefore unmeasured here: 58
    artifact-roster families whose silent verdict is a fact about a list, 11 wide-population
    families, 9 that apply once a changeset exists, 7 that take a value from the workflow, 5
    path-scheduled CI jobs and 4 type-check lanes. Its own words: that silence is not a clearance.

Changeset

This diff changes one file, packages/spec/scripts/build-schemas-check-mode.test.ts, and it
publishes nothing: measured, not argued — npm pack --dry-run lists 2031 entries and 0 under
scripts/
, and the list is byte-identical to the one taken with that file restored to
c120dbdfb8.

The changeset gate's own route 0 discriminator,
git diff --name-status c120dbdfb8...HEAD -- '.changeset/*.md', returns nothing — this PR
neither adds nor corrects a changeset — so route 0 does not match and the gate's prescription is
its route 2, quoted from .github/workflows/pr-automation.yml:

  2. It releases nothing (.github/, .claude/, skills/, docs/, content/,
     examples/, tests-only, and the like)
     -> apply the 'skip-changeset' label.

(the workflow marks that last line PREFERRED; the marker is dropped from the quote above
only because its arrow characters do not survive a GitHub body intact.)

⛔ This round applies no label. The prescription is reported here for the owning seat to act on.

Acceptance notes

Observations, none of them filed and none of them fixed here — this PR's scope is this card:

  • Every line number the card body and its triage comment cite has moved (the harness is 4531
    lines on origin/main, not the 4466 the card cites), which is why every site above is given
    by shape and re-derived. Nothing in the tree is wrong; a line number is simply not an anchor.
  • The card's stated route-B blocker ("the fixture def can only be written into the real src")
    is false for four of the five sandboxes, which already copy src/ privately. That is what
    made a fifth box possible without touching createSandbox.
  • ⛔ Still unmeasured, exactly as the card left it: how many OTHER fail-closed legs of proof 4
    are in the same undefended state, and whether this leg has ever actually failed silently in
    the tree. This PR pins one leg and claims nothing about a population.

Generated by Claude Code

…e box

`delivers()` is a conjunction and check (c) reads a refusal it cannot
parse as "no evidence", never as proof. The left half (an
`unrecognized_keys` issue exists) is defended by the `ui/ViewItem`
fixture; that fixture asserts the probe raises no such issue at all, so
`&&` short-circuits in it and the RIGHT half — the refusal carries the
declaration's own prescription — was defended by a zero.

Adds a fifth sandbox in the shape of the four that already copy `src/`,
substitutes `strictObject` in the box's own copy so every closed shape
becomes a strict clone built to its declaration WITHOUT the
declaration's error map, and pins both directions on one key:

  LIT   map dropped  -> `declared-but-silent`, exit 1
  DARK  map intact   -> `prescribed`, the deletion waived, exit 0

A gate that lost the message conjunct turns the LIT case red and leaves
the DARK one green.

Claude-Session: https://claude.ai/code/session_013RDBh5DqXd2xnLwvHLgLFr
Co-authored-by: Claude <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

Nothing in this diff resolved to a documentable surface (no symbol, route or SDK anchor derived from 0 changed package(s)), so this run has no opinion about the docs.

What this run could not see

Coarse fallback — 0 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): node scripts/docs-audit/affected-docs.mjs --json c120dbdfb81743a172622b7aec6d81bb9f2ed9bf → packageMentionDocs.

Copy link
Copy Markdown
Collaborator Author

Seat read — and ⛔ NO at-tier subagent is owed here, by the rule's own words

Written by the domain:spec execution seat 1 (session_013RDBh5DqXd2xnLwvHLgLFr) at 2026-09-22T23:03Z, on head cbb3521fe5.

Why there is no isolated review on this PR, ⛔ and why that is not a skipped step

origin/main:.claude/skills/pm-dispatch/references/contract-review.md decides it, and it decides it by surface, not by lane — its own words:

欠不欠按面判 ⛔ 不按车道:diff 碰下列任一面即欠达档复核 … 复核面 = 出货给用户或 agent 的五处:content/docs/**、apps/docs/**、CHANGELOG/.changeset 散文 … 加已发布 schema(packages/spec/src/** 非测试)与 governed 规则文本 … 五面皆不碰 ⇒ CI 加席位自读 ⛔ 不起第二个 agent

This diff is one file, packages/spec/scripts/build-schemas-check-mode.test.ts, +281/−0. Against the five:

surface this diff
content/docs/** no
apps/docs/** no
CHANGELOG / .changeset prose no
published schema — packages/spec/src/**, non-test no: the path is packages/spec/scripts/, ⛔ not src/, and it is a .test.ts
governed rule text no

⇒ 五面皆不碰 ⇒ CI plus a seat read, and ⛔ not a second agent. Spawning one here would be the seat ignoring a rule to look thorough.

⚠️ A correction this seat owes on its own record: two earlier notes on sibling PRs described a review as owed 「by the lane rule (C6)」. The governing text says ⛔ 不按车道 in as many words. Those reviews were still owed — each of those diffs touched a listed surface (.changeset prose, or packages/spec/src/** non-test, or content/docs/**) — so ⛔ nothing was over-dispatched; what was wrong was the stated basis, and it is corrected here rather than left standing.

The seat read — structure, ⛔ not a verdict on behaviour

Read at head at 2026-09-22T23:03Z:

  • Scope holds exactly. One file, +281/−0, no other path in the diff.
  • ⭐ The fifth box copies src, it does not link it. fs.cpSync(PKG/src → box/src, { recursive: true }), with symlinkSync left for the other entries only — the shape of the four boxes that already do this. ⇒ the fixture's synthetic strictObject lives in the box's private copy, so route A (a synthetic schema written into the real src, which files[] would ship to consumers via src/**/*.zod.ts) is avoided by construction, ⛔ not by care.
  • ⭐ The substitution is anchored, and the anchor is guarded. A regex pins strictObject as one function declaration, and the fixture asserts it matches before substituting, with a message that says the declaration has moved. ⇒ if the anchor drifts the fixture goes red loudly, ⛔ it does not silently substitute nothing and pass.
  • Both directions are pinned. Alongside the positive assertions the case carries negative ones — the output must not contain the compliant-looking prescription line. ⚠️ That is the point of this card: the failure direction is 「reads as compliant」, a defeated leg waives the deletion rather than adding a 「no evidence」 row, so a one-directional pin would not have caught it.

⛔ This is a reading of the diff's shape. It is ⛔ not a claim that the pin fires — that is what the round's own ablation evidence and CI have to show, and neither is in yet.

What is still outstanding on this PR

  • The round's os-dev-report has not arrived; ⛔ nothing here is taken as verified until it does and is checked against GitHub.
  • CI at 2026-09-22T23:03Z: 32 check names — 8 success, 3 skipped, 0 failure, 21 still running. ⚠️ Running is NOT MEASURED, ⛔ not a pass.
  • The changeset route is the seat's to settle once the gate reports: this diff touches one test file and no package's files[] surface, but ⛔ the seat applies no label on a guess — it reads the gate's own job log first, as it did on the sibling PR.

Generated by Claude Code

@os-support-ai os-support-ai added the skip-changeset PR has no user-facing published change; bypasses the changeset gate label Sep 22, 2026 — with Claude

Copy link
Copy Markdown
Collaborator Author

⛔ Correcting this seat's own note 5785719474 — an at-tier review IS owed here, and it is being arranged

Written by the domain:spec execution seat 1 (session_013RDBh5DqXd2xnLwvHLgLFr) at 2026-09-22T23:06Z. The earlier note said ⛔ no isolated review was owed on this PR. That was wrong. ⛔ Nothing in the diff changed; what was wrong was the rule this seat read.

What the earlier note got wrong

It applied references/contract-review.md's five-surface test — 「欠不欠按面判 ⛔ 不按车道 … 五面皆不碰 ⇒ CI 加席位自读 ⛔ 不起第二个 agent」 — and stopped there. The surface reading itself is right: this diff is one .test.ts under packages/spec/scripts/, so it touches none of the five.

⭐ But that clause is the OTHER-lane case, and the file it points at says so in as many words. origin/main:scripts/pm/check-clause2-carriers.mjs, the C6 block, quoting the maintainer's own rule as restated on #18536:

The lane rule (the maintainer's …) owes the contract review at CONTRACT_REVIEW_TIER in the spec and skills lanes on EVERY delivered round, Clause-②: yes or no, and in no other lane: there the three landing pre-checks and the gates are the whole bar, ⛔ no default-tier "self-review" record is demanded and ⛔ no at-tier subagent is spawned.

⇒ 「⛔ 不起第二个 agent」 is what applies outside spec and skills. Inside them the review is owed every round, whatever the surface and whatever the declaration says.

C6's machine half reads it off the card: 「on a Clause-②: no pair whose CARD sits in a lane that owes the review on every round (laneOwesReview, read off the card's domain:* labels)」. Measured at 2026-09-22T23:06Z: card #18865 carries domain:spec. Absent record ⇒ C6 renders a FINDING row and exit 4, ⛔ not an advisory.

How this seat got it wrong, recorded rather than smoothed over

Two messages ago this seat "corrected" itself in the wrong direction: it had described a sibling PR's review as owed 「by the lane rule (C6)」, then read contract-review.md alone and declared that wording mistaken because that file says ⛔ 不按车道. The lane rule was the right citation all along — it is a maintainer ruling, which outranks a 细则 in the priority order, and C6 is its machine half.

⇒ the error was reading one reference and not the rule it points at, then being confident about the result. ⛔ Neither the first statement nor its "correction" was measured against check-clause2-carriers.mjs until now.

⚠️ Nothing landed on that mistake: the sibling PRs each touched a listed surface too, so every review this seat dispatched was owed on both readings. The only PR where the two readings differ is this one, and it is being fixed before it could cost anything.

What happens now

An isolated at-tier subagent is being dispatched against head cbb3521fe5, and the record it renders will be posted here in the required shape. ⛔ This seat does not self-review: it is below CONTRACT_REVIEW_TIER, and 未达档 ⛔ 不自审 stands.

The seat read in 5785719474 stays on the thread as what it is — a reading of the diff's shape, useful and ⛔ not a ruling. Its five-surface table is accurate; only its conclusion was wrong.


Generated by Claude Code

Copy link
Copy Markdown
Collaborator Author

Served-tier: 117/117 CONTRACT_REVIEW_TIER (seat-measured, 2026-09-22T23:30Z)
Head-sha: cbb3521

Contract review — PR #19754, head cbb3521fe5eb5921277107d81c28d2e343f5792e

Isolated at-tier contract review for the domain:spec lane (seat domain:spec#1, PM session session_013RDBh5DqXd2xnLwvHLgLFr). Subject: objectstack-ai/objectstack PR #19754, branch claude/issue-18865-proof4-delivers-fixture, head cbb3521fe5eb5921277107d81c28d2e343f5792e, base main at c120dbdfb81743a172622b7aec6d81bb9f2ed9bf (merge-base re-derived, identical: git merge-base origin/main <head> → c120dbdfb8…, 2026-09-22T23:07:05Z). Diff: one file, packages/spec/scripts/build-schemas-check-mode.test.ts, numstat 281 0, zero removed lines (2026-09-22T23:15:23Z). Fixes #18865.

Tier control. The tier served to this review is the SEAT's reading, taken from the transcript's per-request harness model stamps; this record's own self-report of its model is not admissible and is not offered. No fallback or overload notice was received by this review during its run. The first line's counts are left TBD/TBD for the seat to fill.

Why this review exists (the lane rule, read at source)

The surface test does not fire: the diff touches none of content/docs/**, apps/docs/**, CHANGELOG/.changeset prose, published schema (packages/spec/src/** non-test) or governed rule text — the one path is under packages/spec/scripts/ and is a .test.ts.

The review is owed by the lane rule. Read at origin/main:scripts/pm/check-clause2-carriers.mjs (2026-09-22T23:07:16Z), the C6 header block says, verbatim:

## C6 — a record owed on this head, and none behind it (#17302; lane-keyed by #18536) … The lane rule (the maintainer's, restated on #18536 — 「曾经要求只有 spec 和 skills 需要 fable,其他 opus 就够了,理论上其他车道不需要契约复审」) owes the contract review at CONTRACT_REVIEW_TIERin the spec and skills lanes on EVERY delivered round,Clause-②: yesorno, and in no other lane

and, in the same file:

export const LANES_OWING_REVIEW = Object.freeze(['domain:spec', 'domain:skills']);
export function laneOwesReview(pair) { const labels = pair?.cardLabels; if (!Array.isArray(labels)) return null; return labels.some((name) => LANES_OWING_REVIEW.includes(name)); }

with its docblock: Read off the CARD's labels: domain:* is produced by triage and lives on the card, never on the PR. Card #18865's labels, read live (2026-09-22T23:08:41Z): priority:p2, pm:dispatched, domain:spec ⇒ laneOwesReview is true and the record is owed on this round whatever the clause-② value.

CONTRACT_REVIEW_TIER, read at origin/main:scripts/pm/dispatch-gates.mjs:12282 (2026-09-22T23:07:17Z): export const CONTRACT_REVIEW_TIER = 'claude-fable-5-1';. Its docblock carries the maintainer's 2026-09-22 ruling verbatim: 「复核档应该就是 fable 啊」 · 「某个agent临时没有fable给的特殊授权,不应该改变skills」 · 「fable 撤回卡 你来创建」, and the rule that a 429 or a missing authorization on one session is never a retirement, and that a seat not served this tier renders the review through an isolated at-tier subagent — which is what this record is.

C6 reads this record for a level-2 heading beginning ## Contract review, the head sha as a code span (H51_SHA_SPAN = /([0-9a-fA-F]{7,40})/g in check-half-states.mjs:12523; CONTRACT_REVIEW_HEADING_MARKER = /^\s*>?\s*## Contract review\b/m at :12511) and a Reviewed-by: line (AUTHORSHIP_KEYS = ['Implemented-by', 'Reviewed-by'], check-clause2-carriers.mjs:3105). All three are present below.

Method

  • Head fetched into an owned ref refs/review/pr-19754-head (2026-09-22T23:06:56Z); a private detached worktree at <scratchpad>/pr-19754/wt, offline pnpm install --frozen-lockfile --ignore-scripts (exit 0, 3.8 s from the store). The shared checkout was neither edited nor read for tree facts; every main reading is git show origin/main:PATH / git grep … origin/main.
  • Gate conclusions are read from this head's GitHub check-runs only; no derived family was re-run locally. The only local executions are the harness's two new cases and the ablations of delivers() needed to judge the pin, in the private worktree, each restore proven by blob id.
  • Nothing was posted to GitHub; no label, comment, review or ref on the remote was written.

① Derived judgments

1. The fifth sandbox is in the shape of the four that already work — VERIFIED

Base vs head, same file, re-derived (2026-09-22T23:15:23Z):

reading origin/main c120dbdfb8 head cbb3521fe5
lines (wc -l) 4531 4812
it(/test( cases 85 87
symlinkSync sites 6 7
entry arrays ['src', 'node_modules', 'package.json'] 1 1
cpSync(path.join(PKG, 'src') sites 4 5

The new block (head :4695–:4699): fs.cpSync(path.join(PKG, 'scripts'), …), fs.cpSync(path.join(PKG, 'src'), …, { recursive: true }), then for (const entry of ['node_modules', 'package.json']) fs.symlinkSync(…) — src absent from the entry array, byte-for-byte the shape of the #4659 / #4725 / #5898 / #17969 boxes (origin/main :3436–3439, :3735–3738, :4101–4104, :4365–4368). The shared createSandbox (origin/main:462–500) is untouched: the diff removes zero lines, and the only change above line 4530 is import { z } from 'zod'; at :51. The 85 pre-existing cases are untouched.

2. Route A is excluded by construction — VERIFIED, with controls

origin/main:packages/spec/package.json files[] carries "src/**/*.zod.ts" (2026-09-22T23:07:28Z), so a synthetic def in the REAL src would ship. The fixture's write target is boxStrictObject = path.join(box, 'src', 'shared', 'strict-object.ts') where box = fixtureTree(…) = fs.mkdtempSync(os.tmpdir()…)/packages/spec and that src is the cpSync copy, not a symlink. The copied scripts/build-schemas.ts reaches schemas only through relative ../src/* imports (origin/main:build-schemas.ts:116–147), never through the symlinked node_modules, so the substitution is read from the copy.

Runtime negative control, my worktree, after the intact run and after every ablation run: git status --porcelain → 0 lines; packages/spec/src/shared/strict-object.ts blob 24c9e672f39d… == HEAD: blob (2026-09-22T23:13:27Z, again 23:15:19Z). Firing control on the same subject: the LIT case exits 1 on the intact tree, which is only possible if the substituted strictObject WAS read by the gate — from the box copy, since the worktree copy is unchanged.

npm pack --dry-run --json --ignore-scripts in the private worktree (no dist/ built here, so the absolute count is 277, not the round's 2031 on a built tree; the discriminating readings do not depend on dist/), 2026-09-22T23:13:16Z: POSITIVE — 204 src/ entries, src/shared/http.zod.ts and src/system/stack-server.zod.ts present (the round's 204 is reproduced exactly). NEGATIVE — 0 entries under scripts/, scripts/build-schemas-check-mode.test.ts absent, src/shared/strict-object.ts (not a .zod.ts) absent. DARK — src/shared/http.zod.tsx absent. With the one changed file put back to base bytes (blob 18100c70f8… proven on disk) the sorted list is byte-identical (diff exit 0), then restored to 326a8c9466…. The round's reading holds.

3. The pin can fail and it discriminates — VERIFIED by my own ablations

delivers() at origin/main:build-schemas.ts:1695–1709: return issue !== undefined && issue.message.includes(prescription); — blob c886e1778316b5ff8c3d1780b599e8bcb50c1970, identical on head and main.

Intact (2026-09-22T23:13:06Z, -t '#18865'): 2 passed | 85 skipped (87), LIT 7.6 s, DARK 9.2 s.

Ablation A (message leg removed → return issue !== undefined;), anchor x1→x0, replacement x0→x1, blob c886e177… → 3cccd072c9cfe48685728086055cefef6cb7b52a (the same mutated blob the round reported), 2026-09-22T23:14:11Z: LIT red, DARK green — × LIT … AssertionError: expected +0 to be 1 at build-schemas-check-mode.test.ts:4751:22, which is expect(status).toBe(1): the gate exited 0 and WAIVED the seeded deletion. That is the card's failure direction, 「reads as compliant」. Restore: blob c886e177… == HEAD, git diff HEAD empty (MATCH).

Ablation B (refuses everything → return false; // ablation-B): anchor x1→x0, replacement x0→x1, blob c886e177… → b67031b7f25fdbcfe3998d36461c2558964e3c9d, 2026-09-22T23:15:59Z: LIT green, DARK red — × DARK … AssertionError: expected '…' to contain 'carry their own proof (#4650)' at :4798, i.e. the tree's own door, which does deliver its prescription, was refused anyway and the gate exited 1. Restore: blob c886e177… == HEAD, git diff HEAD empty (MATCH). (The round did not run this arm; it inferred DARK's role from A. The inference was right, and it is now measured.)

Together: A shows the LIT case is red for exactly the waiver a lost message leg grants (and the DARK case, same box, same key, differing only in whether strictObject hands over its error map, stays green — so the box construction and the seeded key are sound and the red is not a fixture artefact); B shows the DARK case catches a gate that refuses everything. The pair separates 「reads the message」 from 「refuses everything」.

Could LIT go red for another reason? Its assertions after status also exclude the not reachable from the and was LIVE (never tombstoned) verdicts and the prescribed text, all of which exist as the gate's own strings at origin/main:build-schemas.ts:2744–2759 (checked: the DARK string carries the prescription its strictObject declaration owes is on :2745, the LIT string a strictObject declaration NAMES '…', but writing it on :2759). A beforeAll failure would redden both cases; DARK's green under A rules that out.

Full-harness ablation A (the reading the card's acceptance 5737129694 said must be taken before landing, and which the round's 85 skipped did not take): the whole harness, no -t filter, with delivers() at blob 3cccd072… (message leg removed), 2026-09-22T23:16:20Z → 23:28:18Z, 716.94 s on my shared box: Tests 1 failed | 86 passed (87), exit 1 — the single red is the new LIT case at :4751:22 and every one of the 85 pre-existing cases stayed green. Restore proven: blob c886e177… == HEAD, git diff HEAD empty, git status --porcelain 0 lines; final intact re-run (23:14:58Z) 2 passed | 85 skipped, exit 0.

4. The fixture-validity assertions — the argument holds

beforeAll carries, before any box is built: (i) pristineSurface does not contain system/ServerRateLimitConfig:keyBy (re-derived on origin/main: 0 hits in packages/spec/authorable-surface/, firing control: …:enabled, …:maxRequests, …:windowMs present); (ii) the manifest still emits system/ServerRateLimitConfig; (iii) keyBy is not on RateLimitConfigSchema.shape; (iv) the real ServerRateLimitConfigSchema refuses keyBy AND its message carries PRESCRIPTION_BULLET (the DARK leg's tree fact); (v) z.object(RateLimitConfigSchema.shape).strict() refuses keyBy with an unrecognized_keys issue whose message does NOT carry the bullet. Assertion (v) is what makes this a pin on the MESSAGE half: it proves in-process that the probe DOES get an unrecognized_keys issue for the clone, so && does not short-circuit and only issue.message.includes(prescription) can separate LIT from DARK. The existing ui/ViewItem pin (origin/main:1123–1140, :1276–1290) asserts the opposite — not.toContain('unrecognized_keys') — so it defends the left half only. The two pins are disjoint by their own assertions.

The substitution keeps strictObjectError(options, shape) and drops only the map: strictObjectError performs declarationStore().push({ options, shape }) (origin/main:strict-object.ts:346) and strictObject is exactly z.object(shape, { error: strictObjectError(options, shape) }).strict() (:357–359, one 3-line declaration, so STRICT_OBJECT_ANCHOR's lazy [\s\S]*?\n\}\n matches it and nothing else). Proof 4's promisesFor therefore still finds the promise, the door is still closed, and only the refusal text changes — the card's exact shape.

5. Cost — the reasoning is sound and the honest number is the one quoted

Arithmetic re-checked from the round's own figures: 646.38 − 632.50 = 13.88 s = 2.19 % of 632.50; 7.803 + 8.342 = 16.145 s = 2.50 % of 646.38; 625.88 − 623.31 = 2.57 s. The whole-run delta (13.88) is what the direct cost (16.14) minus the unchanged cases' negative drift (−2.57) predicts (13.57; the ~0.3 s remainder is hook time, consistent with the measured 351 ms src copy), so the two numbers agree rather than compete. The seat's argument that a single whole-run pair cannot RESOLVE a ~14 s effect is right on its own evidence (summed per-case absolute drift 31.05 s within the pair; the earlier measurement round saw 59.29 s between two byte-identical runs). The cost this review quotes is the resolvable one: about two gate spawns, 16.1 s, ≈2.5 % of a harness run. My own timings on the same two cases (7.6–10.1 s LIT, 7.1–9.3 s DARK across five runs on a shared box) sit in the same band. No fabricated percentage found; the whole-run delta is not quoted as the cost.

6. Clause-② and the changeset — declared no, and right

The declaration reads no on the card's live claim comment 5784429035 and on the PR body, both by os-support-ai. The path limb (packages/spec/src/** non-test) does not fire: the one path is packages/spec/scripts/build-schemas-check-mode.test.ts. The content limb: the diff adds no key to any published payload, touches no .zod.ts, and the pack list is byte-identical to base (§2). The clause-② value no is correct for this diff.

skip-changeset was applied at 2026-09-22T23:04:33Z by os-support-ai (timeline event; the round's dev report says it applied no label, which is consistent). Route 0 discriminator re-run: git diff --name-status c120dbdfb8 <head> -- '.changeset/*.md' → 0 rows (firing control: the same instrument over c120dbdfb8~30..c120dbdfb8 → 5 A rows; dark control on .changesett/*.md → 0). The gate's own job log (run 35795377021, job 106973341647, 23:03:33Z) prints route 2 as 2. It releases nothing (.github/, .claude/, skills/, docs/, content/, examples/, tests-only, and the like) -> apply the 'skip-changeset' label. <<< PREFERRED and NOT this route if route 0 matched. Route 0 did not match; the diff is tests-only and publishes nothing. The label is the right call. The newer Check Changeset run (106974113468, 23:04:36Z) concluded skipped on the label, as the workflow designs (pr-automation.yml:290, :344–345); the earlier failure (106973341647, 23:03:35Z) is the pre-label first run the workflow itself describes as the common case.

7. Gates — read from this head's check-runs, not re-run

Read from the head's check-runs (GET /commits/cbb3521fe5eb…/check-runs, polled until no run was pending; final read 2026-09-22T23:24:51Z): 39 check-runs, 0 pending. Newest run per check name:

conclusion check name (newest run id, completed)
success Build Core (106973409959, 23:10:25Z) · Test Core (106978463090, 23:21:31Z) · Test Core 1/6–6/6 (106973410206 23:19:05Z, 106973410101 23:13:43Z, 106973410102 23:17:36Z, 106973410203 23:15:10Z, 106973410241 23:21:08Z, 106973410197 23:14:38Z) · Lint & Repo Gates (106973341999, 23:24:30Z) · Type Check · source gates / debt ledger / workspace / consumer gates (106973342113 23:04:10Z, 106973342055 23:09:38Z, 106973342048 23:17:34Z, 106973341955 23:12:54Z) · TypeScript Type Check (106977551127, 23:17:39Z) · Temporal Conformance (live PG + MySQL) (106973410014, 23:10:48Z) · Dogfood Regression Gate + 1/3–3/3 · Dogfood Verify CLI · Spec property liveness (106973341781) · Governed Surface Queue Guard · Flag docs affected by code changes · Check Documentation Links · Part-of PR must not also close its card · The card this PR closes must claim this branch · No other open PR may claim the same issue · No other open PR may claim the same single-writer path · filter · Auto Label (first run 106973422242) · Check PR Size (first run 106973341902)
skipped Check Changeset (106974113468, 23:04:36Z — exempt on the skip-changeset label, the workflow's designed exit; its superseded first run 106973341647 concluded failure at 23:03:35Z, before the label) · Build Docs · Console Pin Gate · Packed-tarball smoke (opt-in) · the label-triggered re-runs of Auto Label and Check PR Size
failure / cancelled / in_progress none at the final read

No run is in_progress or cancelled; no aggregator reports failure. The one failure on the head is the superseded first Check Changeset run, whose own log (§6) prescribes exactly the label that was then applied.

The three families the round declared exit 3 (PREREQUISITE NOT MET, NOT MEASURED locally): check:dual-build-cjs-loads and check:lean-entry-closure are steps of Build Core (ci.yml:2116, :2140); check:type-check-debt is the Type Check · debt ledger job (lint.yml:6059–6060, :6279). Declaring them NOT MEASURED was right — each reads built output of packages this diff does not touch — and none was owed locally for a tests-only diff whose own package typecheck ran green; CI has now measured them: Build Core 106973409959 → success, completed 2026-09-22T23:10:25Z (so check:dual-build-cjs-loads and check:lean-entry-closure ran on a built tree and passed); Type Check · debt ledger 106973342055 → success, completed 2026-09-22T23:09:38Z (check:type-check-debt). Read 2026-09-22T23:17:57Z from this head's check-runs.

Who executes the new pin: packages/spec/vitest.repo-tests.json:2 lists scripts/build-schemas-check-mode.test.ts; packages/spec/package.json:283 "test:repo": "vitest run --project repo"; ci.yml:725 runs pnpm turbo run test test:repo in Test Core. So the harness runs in CI's Test Core shards, and the pin is live there. The shard the run-time planner (scripts/ci/select-shard-packages.sh + partition-test-shards.mjs over turbo ls --affected, ci.yml:551–555) assigned @objectstack/spec to is not readable from here — the job-log download is refused by the egress proxy on the redirect host and the MCP tail of shard 6/6 (12 packages, check-test-completeness: OK (12 of 12 …)) ends in @objectstack/cli:test — so this record names no shard and reads all six Test Core conclusions instead (§7 table). The @objectstack/spec#test:repo turbo input hash includes the changed file ($TURBO_DEFAULT$, turbo.json:532–536), so a main-seeded cache cannot have served it.

The card's distinction, held

The card claims 「no fixture would fire」, not 「it is already broken」. Nothing in this review, in the round, or in the PR measures whether the leg has ever failed silently in the tree; the intact DARK case shows the tree's real door delivers its prescription today. The PR's in-file comment says Measured before this block was written: the leg was defended by a zero — that sentence is now a measured fact rather than a structural reading. The full-harness ablation above is the instrument: with the message leg gone, 85 of 85 pre-existing cases stay green and only the new LIT case fires. So before this PR no fixture would have fired — exactly the card's claim, and nothing more.

② Semver level

None / no release. Tests-only diff under packages/spec/scripts/; no published file changes (pack list byte-identical to base); skip-changeset correctly applied. Were a level ever demanded for this file it would be patch at most, but no changeset is owed.

③ Boundary flags

Findings

None that would change whether this PR should land. Observations, none blocking:

  1. The round reported the ablation with the 85 other cases skipped (1 failed | 1 passed | 85 skipped); the card's acceptance 5737129694 had named the full-harness ablation as the reading to take before landing. This review took it (§3): 1 failed | 86 passed (87). The round's structural reading was correct; it is now also measured.
  2. The round inferred the DARK case's discriminating role from Ablation A alone; this review ran the 「refuses everything」 arm (Ablation B) and the DARK case caught it at :4798. The inference was correct; it is now also measured.
  3. The absolute npm pack entry count differs between a built tree (the round's 2031) and this review's unbuilt worktree (277); the discriminating readings — 204 src/ entries, 0 scripts/ entries, byte-identical lists before/after — agree exactly and do not depend on dist/.
  4. The one failure check-run on the head (Check Changeset 106973341647) is the pre-label first run the workflow itself documents as the common case; its newest run is skipped on the label. Nothing on the head is red at the final read.
  5. The Served-tier counts on line 1 are the seat's to fill from the transcript's harness model stamps; this record does not self-report.

Implemented-by: claude/issue-18865-proof4-delivers-fixture
Reviewed-by: session_013RDBh5DqXd2xnLwvHLgLFr

VERDICT: PASS — the pin is measured to fail in both directions for exactly the message leg (LIT red under a lost conjunct, DARK red under a blanket refusal, 85 pre-existing cases untouched either way), the diff publishes nothing and touches no source, and every check on the head is green or designed-skipped.


Tier control — measured by the SEAT from the reviewer's transcript

  • 117 assistant requests, 117 stamped claude-fable-5-1 — every per-request "message":{"model":…}.
  • 260/260 on the superset: 143 "model" plus 117 "advisorModel", all the same value.
  • Dark control: empty.
  • Fallback / overload sweep: 21 keyword hits, ⛔ none a notice — tool-schema prose, the dispatch order's own sentence, and the reviewer's own "none received".
  • CONTRACT_REVIEW_TIER re-read at source: origin/main:scripts/pm/dispatch-gates.mjs — export const CONTRACT_REVIEW_TIER = 'claude-fable-5-1';

⚠️ This record is adopted verbatim. ⛔ A seat does not rewrite or re-verdict a subagent's ruling.

⭐ Two things this review did that the round did not, and they are the reason the verdict is worth having

  1. It ran the ablation the round skipped. The round proved the pin reds when the message conjunct is removed. The reviewer additionally replaced the whole predicate with return false; — LIT green, DARK red — so the two ablations move the two cases in opposite directions. ⇒ the pair genuinely separates 「reads the refusal text」 from 「refuses everything」, ⛔ it is not two spellings of one assertion.
  2. It ran the FULL 87-case harness under ablation, where the round had only the narrowed run (85 skipped). Result: 1 failed | 86 passed (87) — ⭐ only the new LIT case fires. That is the card's own acceptance condition (「defended by a zero」) turned from a claim into a measurement, and it is what the card said had to exist before landing.

⇒ this seat notes it because the round's evidence was sound but incomplete in exactly the place the card cared about, and the review closed that gap rather than restating it.

Seat's own note on this record's basis

⚠️ Earlier on this PR the seat posted that ⛔ no at-tier review was owed here, reading contract-review.md's five-surface test alone. That was wrong and was corrected in 5785745857. This record confirms the correction at source: LANES_OWING_REVIEW = ['domain:spec','domain:skills'] with laneOwesReview reading the card's domain:* labels, and card #18865 carries domain:spec — so the review is owed on every delivered round, surface or no surface.


Generated by Claude Code

@os-support-ai
os-support-ai marked this pull request as ready for review September 22, 2026 23:32
@os-support-ai
os-support-ai added this pull request to the merge queue Sep 22, 2026
Merged via the queue into main with commit 544767d Sep 23, 2026
40 of 41 checks passed
@os-support-ai
os-support-ai deleted the claude/issue-18865-proof4-delivers-fixture branch September 23, 2026 00:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size/m skip-changeset PR has no user-facing published change; bypasses the changeset gate tests tooling

Projects

None yet

2 participants