Skip to content

feat(platform-checklist): carry implementation STATUS in the ledger — status: planned for capabilities the definition requires and the platform does not yet verify - #19161

Merged
os-steve merged 5 commits into
mainfrom
claude/issue-19157-checklist-planned-status
Sep 19, 2026
Merged

os-steve merged 5 commits into
mainfrom
claude/issue-19157-checklist-planned-status

Conversation

@os-steve

@os-steve os-steve commented Sep 19, 2026

Copy link
Copy Markdown
Collaborator

Part of #19157 — the ledger half (scope items 1–6).

Clause-②: yes (widening)

⛔ Merging this PR is deliberately not a close of that card. Scope item 7 — the scheduled workflow that publishes the human reading entry — is a separate draft on claude/issue-19157-checklist-status-workflow, human-merged because the seat token lacks the workflow scope. That half is what is left open here.

The problem

docs/qa/platform-checklist/areas/*.json held 264 items, every one status: active: the ledger recorded only capabilities that already work. So a missing piece of a listed capability had nowhere to live — the backlog sweep had nothing to point a Path: at, and the platform's implementation status lived in nobody's head. The North Star's definition line (「做出来的是什么」…「缺任何一样就不是这个应用」) makes such a piece a requirement, which is why it belongs on this ledger rather than in a second document that would drift against it with no gate able to say which is wrong.

One ledger, one id space, one more status.

What changed

status: "planned" — the definition requires the capability and the platform does not yet implement or verify it. It relaxes exactly the three fields that cannot honestly exist before the capability does, and adds one that can:

field on a planned item
since null (no target release chosen) or a TARGET release. ⛔ Only the SHAPE is checked — this ledger holds no release timeline, so naming a release that already shipped is an authoring error no gate here can see. ⭐ Corrected by the seat: an earlier revision of this row promised 「never one that already shipped without it」, which described a check the code does not perform (PD #10 — keep the claim as narrow as the enforcement).
steps none. Steps arrive in the PR that implements the capability, in the same edit that promotes the item
acceptance not required — no oracle can be consulted yet. Clauses drafted early are still validated
personas required — knowable the day the gap is found, and what makes the gap readable to the next sweep

Everything else (id, title, priority, surface, revision, history) is judged exactly as before, and the 264 live items are untouched.

A planned item never runs. scripts/checklist-select.mjs now resolves one selector against two pools. The runnable pool is unchanged; the planned pool is reported beside it and handed to no runner. Dropping planned items silently was the alternative and is wrong in the other direction — a selector would answer "nothing here" about an area whose gap the ledger is deliberately carrying.

A planned item is not coverage — this is the load-bearing half. It is a legal coverage.json map target, which is where a capability-gap card points, and it contributes zero: a kind whose only items are planned is reported UNMAPPED. Otherwise planned becomes the cheapest way to green an untested kind, and 「凡是有的能力, 都要测试」 quietly becomes 「都要打算测试」.

pnpm gen:checklist-status is the 「平台功能清单 + 实现状态」 view: per-area active/planned counts, every planned id, and — with --out DIR — the wiki page set (one index, one page per area, planned first). Nothing downstream types a number; the pages carry them because the command produces them.

RUNNER.md, README.md and the two internal skills carry the same three rules, each in the place its reader is already looking.

Measured, not asserted

Both coverage directions were driven end to end against a real fixture area file (a temporary i18n.rtl-mirroring planned item plus a coverage.json edit, restored afterwards — git diff HEAD empty and both blob hashes equal to HEAD's):

Direction A — the kind is still mapped by active items, planned listed beside them: GREEN

check-platform-checklist: OK — 15 areas, 265 items (264 active, 1 planned); coverage: 38 kinds mapped, 1 waived; …
EXIT=0

Direction B — the kind's ONLY item is planned: RED

✗ coverage.json · translation: UNMAPPED — nothing here CARRIES coverage: every item mapped to this kind
  is `planned` (or does not resolve). A planned item records that the definition requires the capability
  and that nothing verifies it yet — it is a promise, not a test, and counting it would let any kind go
  green by promising to cover it. Add an item that RUNS, or waive the kind with a reason.
EXIT=1

The selector on that area — reported as planned, runs nothing for it

selector: area:i18n → 5 runnable item(s)
  …
  1 PLANNED item(s) matched this selector — not run, and not runnable: the definition requires the
  capability and the platform does not verify it yet.
  Record each as `planned` in the run record (⛔ never pass/fail/blocked — no oracle was consulted),
  and do not drive any of them.
    P1  browser   i18n.rtl-mirroring

The runnable JSON that a runner fans out over carried the five active ids and not the planned one.

The status command on the current tree

264 active · 0 planned across 15 areas
wrote 16 page(s): Platform-Checklist + 15 area page(s)

Both numbers are read off the command. Index counts equal each area page's own (P12 in the generator's battery pins that equality rather than a second count of the same thing).

Both directions are pinned on fixtures, in a battery declared in the roster with its floor — the live ledger carries zero planned items and is expected to for a while, so the real data cannot distinguish a working ratchet rule from a deleted one.

⚠️And a pure function's battery says nothing about whether anything CALLS it. An at-tier review proved that: severing either call site left --self-test at 207/207 green, the live gate green, and even a planned-only fixture kind green. statusBindingProblems now pins both call sites by reading this file's own source, driven ON and OFF — the pattern the line-citation limb beside it already uses. All four severings now exit 1 on both instruments; two of the four were double-green before this pin existed.

And that pin has a limit which is stated rather than implied (## ⛔ WHAT THIS PIN CANNOT SEE): it reads comment-masked source, so it catches the text-visible severings — deletion, comment-out, a decoy copy — and ⛔ cannot see shadowing, a dead helper or a dead branch, which are semantic. ⭐ It is not proof the call executes. The behavioural tier that would be — driving the real walk over a fixture ledger — was deliberately not built here: it needs a root knob for AREAS_DIR or the walk factored into a callable, and the seat scoped that out rather than widen this PR at its third review.

Gates

Derived with node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commands and reconciled with --ran: 43 derived families, 43 accounted for, 0 UNRUN.

⚠️「0 UNRUN」 is true of that INSTRUMENT and is not 「green」. check:adr-anchors sits among dispatch-gates's 43 UNDETERMINED families — outside the 43 this derivation covers — and an earlier head of this PR reddened it while the reconciliation above read clean. ⭐ The green asserted here is read from the PR's actual check runs: at 2026-09-19T04:18:24Z, 34 runs — 30 success, 4 skipped, 0 not-green, all seven required contexts success. ⚠️ That count drifts upward by skipped runs, which is why it carries its reading time.

And one more reach fact that changes what CI green MEANS here: lint.yml records that check:platform-checklist is by maintainer decision NOT wired into CI — PR CI runs only a static watchdog-workflow pin, and the gate itself runs on main daily. ⇒ Lint & Repo Gates success says nothing about this PR's self-test, here or on any future head. The local runs above are its only reading.

  • green (38): check:platform-checklist (207-assertion self-test + the live gate), check:doc-authoring, check:pm-skill-ratchet, check:pm-skill-id-lint, check:skill-frame-sync, check:merge-driver, check:pm-dispatch-gates (1866 cases), check:self-test-wired, check:declared-population-live, check:nul-bytes, check:pm-governed-merges, check:cross-package-test-inputs, check:parse-guard, check:turbo-task-graph and the rest of the derived set.
  • Two gates found real gaps in this change and were fixed rather than routed around: check:merge-driver (the new generator owed a merge disposition) and check:pm-dispatch-gates (the new battery owed a COMPOUND_ANCHOR_LEDGER row).
  • NOT MEASURED (5) — each exited 3, PREREQUISITE NOT MET, which is that gate's own distinct code for "nothing was swept": no closure build exists in this worktree, and this diff touches no package source at all, so there was nothing for a build to produce. check:dts-closure, check:dual-build-cjs-loads, check:lean-entry-closure, check:sourcemap-no-sources-content, @objectstack/lint check:doc-formula-expressions. ⛔ Read as neither a pass nor a finding; CI builds fresh and measures them there. Every exit code above was captured before any pipe.

Skill budgets, both at their ceilings with the added rules paid for in the same edit: checklist-test 234 → 238 (ceiling 238), checklist-author 53 → 62 (ceiling 62). No ceiling raised, no line bought by re-wrapping.

⛔ Landing — Tier S, and the record comes first

.claude/** is on the governed register and is Tier S: this PR lands on a contract-tier review of record on this thread (Served-tier: CONTRACT_REVIEW_TIER plus a PASS verdict) and then the merge queue. ⛔ Not a human merge, and ⛔ never the queue without that record.

docs/qa/** and scripts/** are not governed, and no hunk lands on a Tier H pathAGENTS.md, CLAUDE.md, docs/adr/**, docs/NORTH-STAR.md and published skills/** are all untouched. Scope item 6 anticipated the one way that could change: the North Star's 「账本」 sentence stands as written, and nothing here required a pointer in AGENTS.md to name the status axis, so the tier is S and not H.

skip-changeset: this diff publishes nothing. Measured rather than assumed — the ten changed paths are .claude/**, docs/qa/**, scripts/** and the private root package.json, none of which lives under any workspace package directory, so none can appear in any package's files[]. Positive control: the same method finds 70 published packages that DO declare files[].

Acceptance notes

  • scripts/pm/dispatch-gates.mjs's anchor-census docblock carried two unpinned corpus totals that were already stale on origin/main: it claimed 253 matches / 223 bare against a measured 273 / 243. They are unpinned, so nothing reddened. This PR restates them to the freshly measured 275 / 244 because its own new row moves the pinned third number (30 → 31) and 244 + 31 = 275 has to stay true; leaving them would have broken the paragraph's arithmetic. Disclosed rather than folded in silently.
  • The run-record TITLE grammar is deliberately untouched: planned items appear neither in (judged/total) nor as a sixth counts bucket, because scripts/qa/qa-rollup.mjs parses that vocabulary strictly and a planned item was never a judgeable unit of a run. RUNNER.md now says so where a runner would otherwise guess.

维护者速读(草稿)

改了什么 —— 测试清单账本多了一个状态 planned:平台「按定义应该有、但还没做出来或还没验证」的能力,从此在账本里有地方放,有 id 可指。配套一条命令 pnpm gen:checklist-status 打印每个区的 active / planned 数字。

为什么改 —— 之前账本只记已经能用的东西,于是 backlog 扫出来的「能力缺口」卡无处可指,只能靠人记着;平台实现到哪一步这件事没有任何地方写着。另立一份功能清单会和账本互相漂移,而且没有任何闸门能说哪份是错的 —— 所以加在同一份账本上,不新开文档。

风险与代价(含回滚) —— 最大的风险是 planned 被当成覆盖用:只要有人把「打算测」算成「测了」,整个覆盖棘轮就从「有的能力都测了」变成「有的能力都打算测」。这条被钉死在两个方向上(只有 planned 项的种类仍报 UNMAPPED),并且是在夹具上钉的,因为真实账本现在一个 planned 项都没有。回滚代价很低:整个改动是新增状态 + 新增命令,现有 264 项的判定一字未动,撤回即回到今天的行为。

席位意见 ——

你要做的 —— 这是 Tier S:需要本 PR 线程上一条契约档复核记录(Served-tier: CONTRACT_REVIEW_TIER + PASS),然后才走合并队列,⛔ 不是人工直接合。另外,item 7 的工作流是另一张单独的 draft,要你手动合(座位令牌没有 workflow 权限),建议先合这一张、再合那一张。


Generated by Claude Code


Generated by Claude Code

… `status: planned`

An area item gains `status: planned` — a capability the North Star's definition
requires that the platform does not yet verify. The ledger could record only
what already works, so a capability gap had nowhere to live: the backlog sweep
had nothing to point a `Path:` at, and the platform's implementation status
lived in nobody's head.

`planned` relaxes exactly the three fields that cannot honestly exist before
the capability does — `since` (null, or the TARGET release), `steps` (none
until it is implementable) and `acceptance` (no oracle to consult) — and adds
one: `personas`, which is knowable the day the gap is found and is what makes
the gap readable to the next sweep.

The load-bearing half is the capability-coverage ratchet: a planned item is a
legal map target and carries ZERO coverage, so a kind whose only items are
planned is UNMAPPED. Otherwise `planned` would be the cheapest way to green an
untested kind and the ratchet would measure intentions instead of tests. Both
directions are pinned on fixtures in a new self-test battery, because the live
ledger carries zero planned items and cannot tell a working rule from a
deleted one.

Claude-Session: https://claude.ai/code/session_01AmH9bKvGoLjiY86Q4Z3og2
Co-authored-by: Claude <noreply@anthropic.com>
…UNNER/README/skills

The selector resolves one selector against two pools: the runnable one it has
always returned, and the planned one it now reports beside it. A planned id
must never reach a runner (whatever verdict came back would be about nothing),
but dropping it silently would answer 'nothing here' about an area whose gap
the ledger is deliberately carrying.

`pnpm gen:checklist-status` is the 平台功能清单 + 实现状态 view: per-area
active/planned counts and every planned id, plus `--out <dir>` rendering the
wiki page set — one index and one page per area, planned first. Published on a
schedule to the wiki, never committed: a generated page in the tree is a third
artifact to keep fresh whose stale copy reads exactly as authoritative as a
current one.

Claude-Session: https://claude.ai/code/session_01AmH9bKvGoLjiY86Q4Z3og2
Co-authored-by: Claude <noreply@anthropic.com>
…isposition and classify its battery

Two ledgers the new generator and its self-test battery owe a row in, each
found by its own gate rather than by inspection:

- `scripts/regen-artifacts.mjs`: `gen:checklist-status` writes NOTHING into
  this repository, so 'discard both sides and re-run the generator' is not a
  question that arises. Recorded as NOT_DRIVER_MANAGED with `untracked: true`
  rather than omitted, because the refused alternative — a committed STATUS.md
  paired with a check — is exactly the routed-artifact shape a reader assumes.
  Owner is the ROOT manifest: the accounting is keyed per (owner, script).

- `scripts/pm/dispatch-gates.mjs`: `selfTestPlannedStatus` is a genuine
  battery, so its fixtures SHOULD be masked away from watch-hint extraction.
  The docblock's TOTAL / GENUINE / distinct-spelling counts are pinned against
  the table and move with the row. Its two UNPINNED neighbours (the corpus
  totals) were already stale on origin/main at 253/223 against a measured
  273/243; restated to the freshly measured 275/244 so the paragraph's own
  arithmetic (244 + 31 = 275) stays true rather than being broken by this row.

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

Copy link
Copy Markdown
Collaborator Author

Contract review — Tier S landing credential

Served-tier: CONTRACT_REVIEW_TIER
Head-sha: 22453417e1e9cf0b5373d4fb566ecd71ccef23de

Isolated at-tier reviewer, own worktrees, shared checkout untouched. Tier re-derived independently and agrees with the seat: check-governed-merges --pr 19161 exit 3, 2 of 10 paths on the register, Tier S, no Tier H hit; check-clause2-carriers --pair 19161 exit 0. Diff vs merge-base e872ef44b6: 10 files, +865/−36, 3 commits.

VERDICT: FAIL

One blocking finding, and it is one line of prose. Everything substantive measured PASS-grade — the relaxation not leaking to active, the coverage rule in both directions and under twelve adversarial fixtures, the selector in thirteen forms, the status command, both Tier S skill files agreeing with the code, the budgets at their ceilings with zero deletions, the docblock arithmetic, the two fixed gates, and the widening declaration.

⛔ F1 — BLOCKING — a dangling ADR-0136 citation reds a REQUIRED CI context

docs/qa/platform-checklist/README.md:308 (a new line in this PR) reads 「which is wrong (the ADR-0136 lesson)」. There is no ADR-0136 in this registry.

probe result
pnpm check:adr-anchors at head exit 1 — 2 failures of 106: 「ADR-0136 is cited by 1 file(s) but names no record under docs/adr/
same on origin/main 8b8258d910 exit 0
git grep ADR-0136 on origin/main 0 hits — the line is this PR's
highest record under docs/adr/ 0135-identity-and-access-architecture.md
CI Lint & Repo Gates (job 105819264481) FAILURE, step 10 pnpm check:adr-anchors exit 1 · never_ran=169 failed=1 ran=8 declared=179

Lint & Repo Gates is one of the seven required contexts. A ## Contract review record is a credential for the CURRENT head, and this head cannot land, so a PASS here would be a credential for nothing.

Provenance, and it is not the dev's invention: the CARD ITSELF carries the citation. #19157's body says 「(the ADR-0136 lesson; …)」 and the dev copied it. A bare ADR-NNNN resolves against this repo's registry; if a sibling repo's decision is meant, the gate's own remedy text names the cloud ADR-0136 / ObjectUI ADR-0136 spelling. Whether such a record exists in objectstack-ai/cloud is NOT MEASURED — no cloud checkout here.

⚠️ Why the dev's gate accounting missed it, stated precisely because it is NOT a false claim. check:adr-anchors sits among dispatch-gates's 「43 undetermined (their sources name no path at all)」 families — outside the 43 it DERIVES for these paths. The dev's 「43 derived / 43 accounted / 0 UNRUN」 was reproduced exactly and is true of that instrument. ⇒ this is an instrument-reach fact, not dishonesty. But 「every check is green」 is a landing precondition the PR body itself states, and it is false at this head.

F3 — noted by the reviewer; ⭐ the seat is CARRYING it into the same push

The reviewer ran the ablations the PR said were not owed, and the answer is two-sided:

  • The dev is RIGHT that no ablation was needed to prove the SHIPPED behaviour — the fixture-driven live runs prove the binding works today, in both directions and in the leak direction.
  • The dev is WRONG as a DURABILITY claim. The PR body says 「the real data cannot distinguish a working ratchet rule from a deleted one … pinned on fixtures in the self-test」. That holds for the function, ⛔ not for its binding into the walk:
ablation result
A2 — coverage call site reverted to the pre-PR loop, coverageEntryProblems never called --self-test exit 0, 207 assertions; live gate on a planned-only kind exit 0
A3 — the statusFieldProblems(item) call dropped from the item walk --self-test exit 0, 207; live gate on an ACTIVE item with since: null and no steps exit 0
A1 guard · A4 selector · A5/A6 gen · A7 floor all exit 1 ✓ — the function-level pins do fire

a severed call site leaves the self-test 207/207 green, the live ledger green, and even a planned-only fixture green. ⛔ The seat is not letting that ship as a noted item: this PR's whole subject is a ratchet, and a ratchet whose binding nothing pins is the shape this lane refuses. The remedy pattern already lives in this file — the line-citation limb pins its binding by a source read driven on and off. Carry it in the same push; the file is already open and this is not widening.

Other noted findings, all to carry

  • F2 — a planned item whose since names a PAST release passes silently (fixture since: "v1" → exit 0). RELEASE_RE is shape-only and the ledger holds no release timeline, so the README/PR-body phrase 「never a release that already shipped without it」 is authoring guidance the code cannot enforce, and nothing pins it either way. ⇒ per PD chore: version packages #10 「keep the claim as narrow as the enforcement」: narrow the wording, or add a floor. Not coverage-defeating (bearing stays 0).
  • F4 — a hand-typed 264 in the new self-test prose (assertion label and success line). Prose only, no output derives from it, ⛔ but it reads false on the 265th item and nothing pins it — the same rot dispatch-gates.mjs's own docblock warns about. The status command's numbers are derived (with the fixture on the tree it printed 「264 active · 1 planned」).
  • F5 — the docblock arithmetic is right and the edit was forced, not creep: census re-derived at three trees, head reads 275 / 244 / 31 / 28, and 275 = 244 + 31 ✓, with 「the remaining 31」 pinned in the same sentence as the unpinned 253/223 where 253 − 223 = 30 ≠ 31. ⚠️ On the untouched sentence the reviewer corrects both the author and itself: accidental rows are 11 over SIX files — so 「in any of the six files」 is correct, 「Neutralising each of the ten」 is stale, and the dev's own report saying 「eleven rows across SEVEN files」 has the seven wrong. All of it was already stale at the merge base and none is pinned ⇒ ⛔ leaving it untouched here is right; the next accidental row is the carrier.
  • F6 — the README links the workflow file (absent on PR A's tree) and the wiki page (absent until PR B's first run): dangling between the two landings by the declared ordering. Check Documentation Links is success, so no gate reds.
  • F7 — PR B's own pull_request trigger runs pnpm gen:checklist-status on PR B's tree, where the script is absent ⇒ that check fails until PR A lands or PR B rebases onto it.

⭐ Ordering CONFIRMED from four independent sources

PR B's body 「land the ledger PR first」 · PR A's body 「deliberately not a close」 · the card's closed_by_pull_requests listing only #19162 · the workflow's own lines. And measured rather than argued: on the base tree without PR A, pnpm gen:checklist-status exits 254 (Command "gen:checklist-status" not found), and the workflow captures code=$? with no pipe and re-exits it ⇒ PR B landed first fails loudly, exactly as its body claims.

NOT MEASURED, declared

  • The final exit code of the ledger-row ablation battery — its decisive assertion had already gone red and was captured (case 194, unlisted: …::selfTestPlannedStatus), but the 1866-case / ~700 s battery was still running at handback. ⇒ it will exit non-zero; the exit code itself is not a reading I hold.
  • check:dts-closure, check:dual-build-cjs-loads, check:lean-entry-closure, check:sourcemap-no-sources-content, @objectstack/lint check:doc-formula-expressions — exit 3, no closure build in the worktree, and the diff touches no package source.
  • The 169 CI gates that never ran on this head, because CI stopped at F1.
  • PR B's workflow_dispatch / wiki publish (environmental — the wiki must exist; ⭐ the file refuses rather than skips, which is checkable from the workflow source without running it) and PR B's check runs.
  • Whether ADR-0136 exists in objectstack-ai/cloud.

Zeros, each with its reach

0 leak (one item, five mutations; the walk applies the same status-keyed predicate to all 264, so it generalises by construction — outside: fields this PR does not touch) · 0 derivation drift (38 of 8988 tracked paths, 178 families identical at both trees — outside: the other 8950) · 0 bin/exports escapes (70 published manifests — outside: a build script copying a root file into a package's dist) · 0 UNRUN (the 43 DERIVED families only — ⛔ check:adr-anchors sits outside that reach, and it is RED).

⛔ The PR stays a draft and ⛔ does not enter the queue. ⛔ needs:contract-review comes off all three carriers (#19157, #19161, #19162) in one stroke, as a concluded review does whether it passed or failed — ⛔ this is NOT a strip and NOT a green light; this record is what blocks the landing. It is re-hung when the new head arrives.

Implemented-by: claude/issue-19157-checklist-planned-status
Reviewed-by: session_01AmH9bKvGoLjiY86Q4Z3og2


Generated by Claude Code

…l sites, narrow the `since` claim

Four findings from the Tier S contract review, carried in one push.

F1 (BLOCKING) — `docs/qa/platform-checklist/README.md` cited `ADR-0136`, which
names no record under `docs/adr/` (the registry stops at 0135). A bare
`ADR-NNNN` resolves against THIS repo, so `check:adr-anchors` exited 1 and took
the required `Lint & Repo Gates` context with it, leaving 169 gates never run.
The citation came from the card body and was copied; the fix is still owed
here. ⛔ No number is invented and nothing is allowlisted: the lesson is stated
self-containedly instead, which is what a rule in this tree owes anyway.

F3 — the two rules ride on two call sites that nothing pinned. Both were
severed and measured: `--self-test` stayed at 207/207 green, the live gate
stayed green, and a fixture kind whose ONLY item is planned stayed green. A
pure function's battery cannot see whether anything calls it, and the subject
here IS a ratchet, so an unpinned binding is a ratchet that switches off
without a number moving. `statusBindingProblems` reads this file's own source
and is driven ON and OFF over one text, the way the line-citation limb below
already pins its binding. The first draft of it shipped a decoy — its severing
needles were plain string literals the predicate matched instead of the real
call sites, so both OFF legs read as passes. The OFF legs caught it; the
predicate now demands EXACTLY ONE occurrence and the needles arrive in halves.

F2 — `since` is checked for SHAPE only. This ledger holds no release timeline,
so a planned item targeting an already-shipped release passes. The README, the
refusal message and the docblock now say that, and two rows pin the limit in
the direction it deliberately does not go.

F4 — the hand-typed `264` in the self-test prose is derived from the ledger.

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

Copy link
Copy Markdown
Collaborator Author

Contract review — Tier S landing credential, scoped re-review

Served-tier: CONTRACT_REVIEW_TIER
Head-sha: b835196bc1a32805df1974b4d8651f3e89d41bca — prior head 22453417e1 confirmed an ancestor. Delta 22453417e1..b835196bc1: 1 commit, 2 files, +183/−21. Isolated reviewer, two detached worktrees, shared checkout untouched before and after. Exit codes captured before any pipe.

VERDICT: FAIL — one blocking finding. F1, F2, F4 and the whole regression surface measured PASS-grade.

⛔ F3 — BLOCKING — it is a SPELLING pin, ⛔ not a BINDING pin

What is genuinely real. statusBindingProblems(source) demands exactly one occurrence of each of four spellings, and the OFF legs assemble their needles in halves broken inside an identifier, so no contiguous copy exists at rest (grep -c of each pinned spelling reads 1, 1, 1, 1). The live path runs the battery as a control on every invocation, so the pin reaches both instruments. All four required severings now red both:

leg --self-test live gate
sever statusFieldProblems(item) from the item walk 1 1
sever the coverageEntryProblems call 1 1
compute the coverage problems and never report them 1 1
ungate mappedCount on bearing 1 1
identity control 0 (217) 0 (264 items)

And it is defeated by the most ordinary severing gesture there is. Every row below left --self-test at exit 0 / 217 and the live gate at exit 0 / 264 active:

attack
A1 — comment the walk call out IN PLACE GREEN / GREEN — defeated. The commented line is the one occurrence; the predicate reads raw source, never comment-masked
A1c — comment out if (bearing > 0) mappedCount++; and add mappedCount++; below GREEN / GREEN. A planned-only kind would then count as mapped on the OK line
A9 dead branch · A7 call moved into a never-called helper · A6 shadowing const statusFieldProblems = () => [] GREEN / GREEN

The dev's own docblock names 「a commented-out draft」 as the decoy threat — and the comment-out IS that draft, at count 1. ⚠️ maskComments from ./js-comment-mask.mjs is already imported at line 96 of this same file and already used at lines 841 and 2736.

What it refuses, correctly (fails closed — brittle but documented): a double space, a line break inside the for, a /* row */ inside the call, a renamed binding — all exit 1 / exit 1 with the binding intact. And a decoy copy added in a comment while the real call standsexit 1 「occurs 2 times … DECOY」 ⇒ the exactly-one rule works in the direction it was written for.

⭐ The seat's call on which tier to demand — stated rather than left open

The reviewer measured two tiers and handed the choice to the seat. Take the MINIMUM tier, and make the residual DISCLOSED rather than implied.

  • Demanded: mask comments before counting — the measured one-line remedy, using an import this file already has. Verified by the reviewer: R0 (mask alone) leaves everything green; R1 (+A1) → exit 1; R2 (+A1c) → exit 1; R3 (+ decoy-in-comment) → exit 1.
  • Not demanded: the behavioural tier. Driving the real walk over a fixture ledger needs a root knob (AREAS_DIR is fixed from import.meta.url) or the walk factored into a callable. That is real scope on a PR already through two reviews, and ⛔ I am not widening it at the third.
  • But the claim must become as narrow as the enforcement (PD chore: version packages #10, the same principle F2 was fixed under). Masking closes the three text-visible severings and leaves shadowing, the dead helper and the dead branch open — the reviewer states plainly that those are semantic and no text pin can see them. ⇒ the docblock must say what this pin can and cannot see. ⛔ A pin that calls itself a binding pin while three ordinary severings walk past it is the same over-claim this PR already corrected twice.
  • ⚠️ One more the reviewer surfaced: the OFF legs' anchoring is order-sensitivesever() uses first-occurrence String.replace, so a decoy placed above the real call absorbs the cut (it still reds, via a different row). ⇒ say so where the legs are written.

VERIFIED

F1 — PASS. git grep ADR-0136 at head: 0 hits (control at the prior head: 1, README.md:308); check-adr-anchors exit 0 at head, exit 1 at the prior head; highest record is still 0135. ⭐ And the replacement prose states the lesson instead of gesturing at a citation — drift between two hand-maintained documents, no arbiter between them, therefore one ledger. ⛔ No number invented, nothing allowlisted.

F2 — PASS on the tree. A five-spelling whole-tree sweep finds the only in-surface hits now reading 「Only the SHAPE is checked … no release timeline … an authoring error no gate here can see」. ⚠️ NOTED, and it is the seat's to fix: the PR BODY's field table still carries the old over-promise 「never one that already shipped without it」. Off the tree, not landed by the merge — ⛔ but it describes a check the code does not perform, and the body is the seat's. It is corrected in the rewrite that accompanies the next head.

F4 — PASS, one noted: the literal readings that remain (207/207, 28 → 38) name no tree or commit — per AGENTS.md 「a count plus the tree it was taken against … or it is not a reading」.

F5 — PASS. ⭐ No assertion was weakened or deleted, established by predicate-level extraction at both heads: the 19 rows the extractor parses are byte-identical, and the diff is additions only. The one touched pre-existing row had its label string become a template literal with the predicate unchanged. 217 − 207 = 10 = the ten new rows. Skill budgets did not move (the delta touches no .claude/ path); all four skill gates exit 0 on both halves.

⚠️ Two corrections to readings I reported

  1. My CI count was stale. I reported 34 runs / 30 success / 4 skipped; the reviewer reads 38 / 30 / 8 — four more skipped runs arrived after my read. ⇒ the delta is skips only, 0 not-green either way, and all seven required contexts success. ⛔ But my number was a snapshot presented without its time, which is the defect this lane names.
  2. An instrument-reach fact that changes what CI green MEANS here. lint.yml records that check:platform-checklist is 「by MAINTAINER DECISION … NOT wired into CI」 — PR CI runs only a static watchdog-workflow pin, and the gate itself runs on main daily. ⇒ Lint & Repo Gates success says NOTHING about this PR's self-test. The local runs are the only reading of it, on this PR and on every future one.

NOT MEASURED, declared

The five exit 3 PREREQUISITE-NOT-MET gates (no dist/ in a worktree; CI's Build Core and TypeScript Type Check are success on this head) · check:pm-dispatch-gates' 1866-case battery (~700 s) · the planned-only and active-since:null fixture legs under severing (the prior review took them; the delta moves nothing that could change them) · whether ADR-0136 exists in objectstack-ai/cloud.

Zeros, each with its reach

0 ADR-0136 hits (every tracked path at head — outside: the sibling cloud registry) · 0 over-promising sentences (five spellings, whole tree — outside: the PR body, where one survives, and the card body) · 0 weakened assertions (predicate extraction of one function at two heads — outside: three multi-line-label rows read by eye, and the six untouched batteries) · 0 not-green check runs (the 38 GitHub attaches — outside: the job's 169 sub-steps individually, and check:platform-checklist, which PR CI does not run at all) · 0 defeats of the four REQUIRED severings — the DELETION form only; the comment-out, dead-branch, dead-helper and shadow forms were measured red-handed and are F3.

⛔ The PR stays a draft, ⛔ does not enter the queue, and needs:contract-review comes off all three carriers in one stroke as a concluded review does — ⛔ that is not a green light; this record is what blocks the landing, and it is re-hung on the next head.

Implemented-by: claude/issue-19157-checklist-planned-status
Reviewed-by: session_01AmH9bKvGoLjiY86Q4Z3og2


Generated by Claude Code

…urce, and disclose what it still cannot see

F3, third pass. The pin demanded exactly one occurrence of each call site and
counted RAW source, so the most ordinary severing gesture there is walked
straight past it: commenting the call out IN PLACE left the commented line as
the one occurrence, and `--self-test` stayed at 217/217 with the live gate at
264 active. The nastier variant did the same while inverting behaviour —
comment the `mappedCount` gate out, add an ungated increment below it, and a
kind mapped only to planned items is counted as covered on the OK line.

The remedy is one line: `maskComments`, already imported in this file and
already used twice in it, applied before counting. Masking also settles the
decoy rule in the only consistent direction — a copy inside a comment is
neither a call site nor a decoy, so it must neither satisfy the count nor
inflate it.

⛔ And the claim is narrowed to the enforcement, which is the part that is not
optional. This is a TEXT pin. It answers "is this call site still written, in
live code, exactly once?" and it is NOT proof the call executes: shadowing, a
call moved into a never-called helper, and a call left under a dead branch all
keep the spelling intact and this pin reports nothing. The docblock says so and
G12 asserts it, so nobody reads a green G1 as more than it is. Closing those
needs the walk driven over a fixture ledger — a root knob or the walk factored
into a callable — which is not built here by the seat's scope call.

G9–G11 keep the mask: reverting it to a raw count reds those three rows and
nothing else. The OFF legs' first-occurrence anchoring is noted where they are
written.

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

Copy link
Copy Markdown
Collaborator Author

Contract review — Tier S landing credential

Served-tier: CONTRACT_REVIEW_TIER
Head-sha: 51792f85d201… (51792f85d2)

VERDICT: PASS

Blocking findings: none. Six noted prose/citation imprecisions, ⛔ none of which makes a docblock claim false on the tree. Scope: the delta b835196bc1..51792f85d2 only — ONE file, scripts/check-platform-checklist.mjs, +123/−17, verified by --numstat. Append-only confirmed. Shared checkout untouched (git status --porcelain 0 lines before and after, HEAD unchanged, none of the reviewer's worktrees registered in it); all runs in git clone --shared copies. Every mutation asserts its needle occurs exactly once before replacing (exit 9 otherwise), and failing rows were read from the failure TEXT, ⛔ not inferred from exit codes.

⭐ The mask is the whole difference — identical attacks, green at base, red at head

mutant self-test live gate rows
A — comment the walk call out in place 1 1 G1 「the item walk does not consume statusFieldProblems(item)」, G11, G12
B — comment the gate out + an ungated mappedCount++; below 1 1 G1 「does not gate mappedCount on bearing」, G11, G12
the four deletion severings 1 1 G1 plus each leg's own row
A on BASE b835196bc1 0, 217 0, 264 none — the prior F3 hole reproduced
B on BASE 0, 217 0, 264 ⛔ none

⇒ the two attacks that defeated the previous head are closed, and the base control proves it is the mask that closed them.

⭐ META-ABLATION — the rows are the mask's pins, ⛔ not decoration

Reverting maskComments to a raw count → --self-test exit 1, exactly 3 failures: G9, G10, G11 and nothing else; live gate the same three. Claim confirmed exactly.

⭐ The disclosure is ACCURATE in both directions

## ⛔ WHAT THIS PIN CANNOT SEE — read this before trusting it states 「⛔ it is not a proof that the call EXECUTES」. Each named item measured at head:

semantic severing self-test live
shadow scoped to the walk alone 0, 221 0
dead branch 0, 221 0
dead helper 0, 221 0

⇒ all three named forms are genuinely unseeable, and ⛔ nothing the list names is in fact seen — the disclosure neither under- nor over-claims on its own members.

G12 is something a test can fail on, ⛔ not prose: adding a row that claims to see shadowing reds exactly G12 (1 failure) on both instruments. And the floor bites — dropping G12 reds with 「reported 41 assertions but its floor is 42」.

⭐ Both of the dev's self-reports against itself — CONFIRMED

  • (i) shadowing. A walk-scoped shadow is invisible to both instruments ⇒ the prior reviewer's A6 result stands, exactly as the dev said. Its module-global shadow reds 9 FIXTURE rows and ⛔ no G-row, matching its account. grep -i shadow over the file finds no row or docblock claiming the pin catches it. ⇒ ⭐ the dev's refusal to claim credit for an accidental red was correct.
  • (ii) G10. Contiguous if (bearing > 0) mappedCount++; occurs once (the real gate); every harness needle is split, so first-occurrence replace cannot land on a helper literal. Conjunct 3 measured directly: shipped mutant → true true true, masked hits 0 (fires); the variant without the ungated line → conjunct 3 false; raw unmasked hits = 1, ⇒ a raw pin would have stayed silent — the very mechanism the meta-ablation exposes. ⛔ Not vacuous.

Regression on the delta

217 → 221 assertions, battery 38 → 42, floor raised to 42 and it bites. ⛔ No assertion weakened or deleted: the t() label roster base-vs-head diffs as 36a37,40four added, zero removed — and the function-to-EOF region shows exactly one < line, the old success string. None of the four new rows is vacuous — each reds under multiple independent mutants. All four skill gates exit 0 on both halves.

⚠️ Six NOTED, none blocking, and each recorded rather than smoothed over

  1. H3 — a FOURTH semantic severing the list does not name: a neutered sink (const where = () => {};) → 0, 221 / 0. ⛔ It sits inside the disclosed class (「SEMANTIC … no text pin can reach them」) and the list is introduced as 「Three ordinary severings」, claiming no exhaustiveness — so it is not a false claim. ⭐ The reviewer's own disposition: add 「a swallowed sink」 in a follow-up.
  2. G12's success line overstates by two — 「G12 records the three semantic severings」, while G12's assertion drives shadowing only; the dead helper and the dead branch are prose.
  3. H4 — a string-literal stand-in (void '…the call…';) is a text-visible non-comment severing the pin does not close (a literal counts as live, as the docblock says). It reds only fail-closed, by harness accident (the // lands inside the literal). ⛔ Not a green blind spot at this head; recorded as harness-accidental.
  4. Order-sensitivity prose — the new note says a decoy-above leg reds 「through the exactly-one row」; true for a LIVE duplicate, but a COMMENTED decoy above reds through the OFF-leg rows with G1 green. The operative instruction (read the failure text) holds.
  5. A citation nit — the meta-ablation reading is cited as 「measured on this branch at b835196bc1」, a tree that has no mask to revert; the reading is of this diff over that parent.
  6. The shadow example and G12's fixture prepend the const at module top, where it would be a SyntaxError if executed; legitimate as a text stand-in, and a real shadow lives in an inner block.

⭐ The instrument-reach fact, confirmed FROM THE WORKFLOW FILES

lint.yml's Lint & Repo Gates job: grep -c check-platform-checklist.mjs0; check-platform-checklist-watchdog.mjs2, both inside the single step 「Platform-checklist watchdog workflow pin」. ci.yml → 0 mentions. The only run: invoking the gate anywhere is in platform-checklist-watchdog.yml, whose triggers are a nightly schedule, workflow_dispatch, and a pull_request filter to itself — ⛔ it does not run on this PR. README.md:422 records the maintainer decision.

⇒ ⛔ Lint & Repo Gates success says NOTHING about this PR's self-test, here or on any future head. The local runs above are its only reading.

CI, with its reading time

Read at 2026-09-19T04:36:03Z: total_count 45 (machine-provided), hand tally 34 success / 11 skipped / 0 not-green; Lint & Repo Gates success. ⚠️ NOT MEASURED: a programmatic split — gh is absent, so the 34/11/0 is a hand tally of the returned JSON, ⛔ not a machine count. ⚠️ Drift from the seat's 34 / 30 / 4 at 04:18:24Z is +11 re-triggered runs at 04:18:46Z and 04:20:29Z — skips plus four claim-guard successes. ⇒ this count carries its timestamp because it moves.

NOT MEASURED, declared

The five exit 3 PREREQUISITE-NOT-MET gates (no dist/ locally) · the programmatic check-run split (above) · the pre-mask readings of the three semantic severings at b835196bc1 — the reviewer took its own at head, all green there too, which is consistent with the claim.

Zeros, each with its reach

0 porcelain (tracked + untracked; ignored files outside) · 0 gate invocations in lint.yml (literal spellings in that file — ⭐ and the same grep DOES find the spelling in the watchdog workflow, so the instrument is lit) · 0 removed t() rows (textual removal in the function-to-EOF diff; a predicate weakened via a helper defined above the function is outside it, covered separately by the delta hunk list) · no claim the pin sees shadowing (grep -i shadow; a claim phrased without the word is outside) · 0 not-green check runs (runs on this head; legacy statuses and earlier heads outside) · mutant 0-failures (the batteries these instruments run; a behavioural change on a ledger with 0 planned items is outside — which is precisely the disclosed limit).

Implemented-by: claude/issue-19157-checklist-planned-status
Reviewed-by: session_01AmH9bKvGoLjiY86Q4Z3og2

needs:contract-review comes off all three carriers in one stroke, as a concluded review does. ⭐ This record is the Tier S landing credential for head 51792f85d2 — and it covers that head only. The six noted items are filed as a bare follow-up rather than held against this landing; ⛔ none of them makes a claim that is false on the tree.


Generated by Claude Code

@os-steve
os-steve marked this pull request as ready for review September 19, 2026 04:42
@os-steve
os-steve enabled auto-merge September 19, 2026 04:42
@os-steve
os-steve disabled auto-merge September 19, 2026 04:43
@os-steve
os-steve added this pull request to the merge queue Sep 19, 2026
Merged via the queue into main with commit 57cfedd Sep 19, 2026
50 checks passed
@os-steve
os-steve deleted the claude/issue-19157-checklist-planned-status branch September 19, 2026 05:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

dependencies Pull requests that update a dependency file documentation Improvements or additions to documentation size/xl skip-changeset PR has no user-facing published change; bypasses the changeset gate

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants