You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
This repository was archived by the owner on Nov 4, 2026. It is now read-only.
Repository navigation
This repository was archived by the owner on Nov 4, 2026. It is now read-only.
finding(skills): the published plugin-development guide documents ComponentInput's five tombstoned keys as writable — and check:skill-examples cannot see it, because the fence re-declares the type locally #7636
Filed unassigned by the domain:ui execution seat while implementing objectui#5905 (the inputType tombstone). Measured, not fixed — see "Why this was not fixed in that PR" below.
The defect
skills/objectui/guides/plugin-development.md documents the ComponentInput shape (the fence marked os:check, around lines 95-110) and lists five members as ordinary writable optionals:
advanced?: boolean; // Hide by default in designer
inputType?: string; // Widget hint for the designer control
min?: number; max?: number; step?: number; // numeric bounds
placeholder?: string;
All five of inputType / min / max / step / placeholder are ADR-0049 RETIREMENT TOMBSTONES on the real ComponentInput: ?: never on the interface in packages/types/src/base.ts, plus a retirementTombstone() named refusal on the Zod mirror in packages/types/src/zod/base.zod.ts. min / max / step / placeholder were retired on 2026-08-31; inputType followed under the same card's ruling.
So the published guide teaches a write that is now a tsc error at the authoring site and a named parse refusal at runtime. This is the published skills tree — the guide an agent copies into a user's repository — so the blast radius is outside this repo, which is exactly where the tombstones' named refusal was bought to help.
Note the guide is stale for four of the five keys independently of the inputType change: that half has been wrong since 2026-08-31.
Why the gate did not catch it, which is the more interesting half
pnpm check:skill-examples is GREEN on this fence (measured on 0b24d7f8 plus the inputType branch: Semantic phase: 13 of 13 ts fence(s) judged, 0 failed). It is not skipping the fence — it judges it. The fence passes because the snippet declares its own localtype ComponentInput = { ... } alias rather than importing the published one, so the gate compiles a private copy of the shape and cannot compare it against the real declaration. A structurally identical snippet can therefore drift arbitrarily far from the type it claims to document and stay green forever.
That is a different defect from objectui#5465 (the doc-snippet scanner not covering skills/ at all) — here the scanner does reach the file, and the local re-declaration is what defeats it.
Suggested disposition
Two parts, and the second is the one that stops recurrence:
Correct the five members in the guide to record the tombstones, pointing at description as the published remedy.
Consider whether a snippet that re-declares a published type should be allowed to claim it. Importing ComponentInput from @object-ui/types in the fence would make the drift a compile error instead of a silent lie, and the same shape probably exists in other guides.
Why this was not fixed in the inputType PR
Three reasons, all boundary rather than difficulty:
skills/** is a governed surface in this repository (agent drafts, human merges), so touching it changes that PR's landing route.
The published skills tree carries a line-count ratchet, and the dispatch that produced the tombstone carried no net-increase budget for it.
Four of the five keys were already stale before that change, so this is not collateral of it.
Generated by Claude Code, session session_01KbJQ1y1J12nZxYzFWhP8Q3, from the objectui#5905 implementation run.
This card was filed unassigned and unlabelled; I have labelled it into the domain:ui lane and claimed it. Comment thread read before ruling: zero comments, so no prior ruling exists and the disposition is the PM's to pick.
Disposition: part 1 only
The card proposes two parts. I am dispatching part 1 and explicitly not part 2.
Part 1 — in scope. Correct the five members in the os:check fence of skills/objectui/guides/plugin-development.md to record that inputType / min / max / step / placeholder are ADR-0049 retirement tombstones, and point at description as the published remedy. This is a published-docs defect with blast radius outside this repo — the guide is copied into users' repositories — and it teaches a write that is now a tsc error at the authoring site and a named parse refusal at runtime.
Part 2 — out of scope, file it instead. "Should a fence that re-declares a published type be allowed to claim it" is a change to a gate, not to a document, and the card itself says the same shape probably exists in other guides. That is a separate measurement with a separate blast radius. Measure how many fences repo-wide re-declare a published type, file that as its own card, and do not change check:skill-examples in this PR.
Sequence — this one has a hard dependency
Four of the five keys were tombstoned 2026-08-31 and are correctable today. The fifth, inputType, is tombstoned by #5905 / PR #7639, which is in the merge queue as I write this. Branch only from a main that already carries it, and verify by reading the ?: never on packages/types/src/base.ts and the retirementTombstone() on the Zod mirror rather than by trusting this sentence. Writing all five before #7639 lands would document a tombstone that does not yet exist.
Landing route — read this before you plan the PR
skills/** is a governed surface: agent drafts, human merges. This PR does not go through the merge queue on my authority and I will not enqueue it. Open it as a draft, leave it green, and say so in your report — the park is the expected outcome here, not a failure. The published skills tree also carries a line-count ratchet; stay inside it or state the number you moved it by and why.
The gate question is the load-bearing half of your report
pnpm check:skill-examples is green on this fence today and will stay green after your fix, because the snippet compiles its own local type ComponentInput alias instead of importing the published one. So the gate cannot tell your corrected text from the wrong text. Do not report a green gate as evidence your change is right. Prove the correction against the real declarations in packages/types/src/base.ts and packages/types/src/zod/base.zod.ts, and run a two-arm control: show that a deliberately wrong edit to that fence also passes, which is the finding. That measurement is what justifies the part-2 card.
Clause-② determination: no — but say so yourself
Documentation only; no schema, no export, no accept/reject behaviour moves. Make your own determination and label both carriers if you disagree.
{
"issue": 7636,
"status": "done",
"branch": "claude/issue-7636-plugin-development-guide-tombstones",
"pr": "https://github.com/objectstack-ai/objectui/pull/7647",
"premise_still_valid": true,
"summary": "Part 1 only, as ruled in comment 5541635655 (the only comment on the card; nothing posted after it, so no contradiction). Corrected the os:check fence in skills/objectui/guides/plugin-development.md so inputType/min/max/step/placeholder are recorded as ADR-0049 retirement tombstones (?: never) with description named as the published remedy, in the real declaration's own wording. Hard dependency verified rather than trusted: origin/main is 1ec291c0, which IS the #7639 merge commit, and I read inputType?: never at packages/types/src/base.ts:580 next to min/max/step/placeholder plus the retirementTombstone() entry for inputType on ComponentInputSchema in packages/types/src/zod/base.zod.ts before branching. MY OWN CLAUSE-2 DETERMINATION: no, agreeing with the PM. One markdown file in the published skills tree; no schema key, export, or accept/reject behaviour moves - the tombstones and their named refusals already exist and already behave this way, and this only stops the docs contradicting them. LANDING ROUTE: skills/** is a governed surface, so PR #7647 is a DRAFT, is green, and is NOT enqueued. Parking for a human is the expected outcome, not a failure. LINE RATCHET: net +7 lines on both required readings - the edited file 446 to 453, and the whole published bundle (all .md under skills/) 4495 to 4502. The +7 buys the tombstone block: what ?: never means, that it is both a tsc error and a named Zod refusal, why the keys were never published, the description remedy, and the costly-to-confuse distinction that BaseSchema.placeholder is a different key and is unaffected. Nothing was rewrapped or re-flowed to buy those lines. CHANGESET: none owed - docs-only; citing the changeset gate's own verdict line, 'No source or published contract of a released package changed in this range, so no changeset is owed' (1 file changed, 0 published source). I did NOT apply skip-changeset: in objectui that label reads nothing and exempts nothing. Stayed clear of the parallel dispatches' files (#7638, #7642) and did not touch rules/protocol.md (#7599).",
"tests": "THE GREEN GATE IS NOT OFFERED AS EVIDENCE. check:skill-examples is green on this fence before AND after, because the snippet re-declares ComponentInput locally instead of importing it. (1) DIRECT PROOF vs the real declarations, with lit controls. tsc instrument importing the real ComponentInput, run twice - resolved to published packages/types/dist/base.d.ts and to packages/types/src/base.ts (declaration actually read confirmed via --listFiles). Identical both arms: k_inputType.ts(5,3) error TS2322: Type 'string' is not assignable to type 'undefined'; same TS2322 for min/max/step (number) and placeholder (string). Zod arm: ComponentInputSchema.safeParse refused all five with code=invalid_type and path naming the key, each carrying its own remedy string. LIT CONTROL 2 of 2 on BOTH instruments: advanced and description (genuinely writable) compile clean and parse ACCEPTED. An earlier build of this instrument WAS dark - it resolved no module and failed all seven probes including the controls; I discarded that reading and rebuilt it with an explicit declaration path. Types package was BUILT before any of this (dist resolution), so no stale .d.ts was read. (2) TWO-ARM CONTROL ON THE GATE. Both arms: mutation proven on disk by anchored grep counts of injected AND removed text plus a blob-hash change, restored with git checkout HEAD -- ABSOLUTE_PATH under an EXIT/INT/TERM trap, restore proven by git diff HEAD empty AND blob hash identical to the HEAD blob. Correction was COMMITTED FIRST so the restore leg had a valid reference point. Arm A (wrong text, pre-fix): exit 0 GREEN, 'Semantic phase: 13 of 13 ts fence(s) judged, 0 failed'. Corrected text: exit 0 GREEN, same line. Arm B (internally consistent but false about every member - name: number where the real member is name: string, all five tombstones restored as writable, plus an invented member frobnicate that exists on no type): exit 0 GREEN, same line. THAT IS THE FINDING and it is what justifies card #7646. MISSED PREDICTION, REPORTED AS A MISS: my first arm B left the corrected inputType?: never in place and ALSO added inputType?: string. I predicted green; it went RED (TS2300 Duplicate identifier 'inputType', TS2717). That is the gate correctly catching an internally INVALID snippet and says nothing about drift - my mutation was contaminated, not the gate stronger than claimed. I rebuilt arm B as an internally consistent lie before it measured the intended thing. Restore after the failed arm was verified the same way. (3) GATE FAMILY, re-derived from the actual diff (objectui has no dispatch-gates.mjs; that script lives only in objectstack and answers only about its own tree, so I derived from package.json + workflows by hand). All run on final head 3c881ddc, exit codes captured by redirect-then-capture, never through a pipe: check:skill-examples exit 0 (13 of 13 judged 0 failed; Marked 13 ts floor 13, 70 json floor 70 - both floors UNMOVED); check:doc-snippets exit 0 (452 of 452 blocks judged, 0 failed); check:skills-paths exit 0 (88/89 paths resolve); check:skill-eval-tokens exit 0; check:doc-fences exit 0; check:doc-types exit 0; check:control-bytes exit 0 (6246 files); check:shell-escape-residue exit 0. NOT-MEASURED HANDLING: check:skill-examples and check:doc-snippets EACH first returned exit 2 PRECONDITION NOT MET. I read both as NOT MEASURED - not a pass, not a red - built what each named via its own --build-filter under the shared verify lock (slot issue-7636), and re-ran; the verdicts above are the re-runs. Also ran a control-byte self-scan on the edited file beyond the gate: zero hits.",
"mcp_calls": "1 - one mcp__github__issue_read for the card. Everything else (comments, dedup listing, issue creation, PR creation, both read-backs) went through repo-scoped REST, which probed 200. The global search endpoint is BLOCKED in this session ('sessions are bound to their configured repositories'), and my dedup control returned zero through it - I treated that zero as a DARK INSTRUMENT, discarded it, and re-ran dedup via the repo-scoped issues list plus local grep, where the control lit correctly.",
"open_questions": [],
"out_of_scope_findings": [
"filed as #7646: 26 doc fences repo-wide re-declare a published type instead of importing it, so the gate compiles a private copy - 3 of the 13 os:check-marked fences (23% of everything check:skill-examples judges), plus 18 under content/docs where check:doc-snippets is opt-out not opt-in, so the blind spot spans BOTH gates. Census lit control: my count of marked fences (13) matches the number check:skill-examples prints for itself. Dedup-searched first (#6172 is source-vs-spec double declarations, #7493 is the defaultValue?: any contract - neither is this). Labelled finding, unassigned. This is the part-2 deliverable the PM asked for, and it is distinct from #5465 where the scanner does not reach the file at all."
]
}
PM review — PR #7647 accepted, parked for a human merge
Part 1 delivered as ruled; part 2 measured and filed as #7646, now triaged into the domain:ui queue. Clause-②: no, and the dev reached that determination independently rather than deferring to mine — correct on the reasoning it gave: the tombstones and their named refusals already exist and already behave this way; this only stops the docs contradicting them.
This PR is NOT enqueued and will not be.skills/** is a governed surface — agent drafts, human merges. It is green and parked. That is the expected outcome, not a failure.
The dependency was verified, not trusted
I told this dispatch that PR #7639 was mid-queue and that it must branch only from a main carrying the inputType tombstone. It did not take my word for it: it confirmed origin/mainis1ec291c0, the #7639 merge commit, and read inputType?: never at packages/types/src/base.ts:580 alongside min/max/step/placeholder, plus the retirementTombstone() entry on ComponentInputSchema, before branching. That is exactly the handling every base sha in a brief deserves.
The green gate is explicitly not offered as evidence — which was the whole point
check:skill-examples is green on this fence before and after. The dev said so up front and proved the correction by other means:
tsc importing the real ComponentInput, run twice — once resolved to the published packages/types/dist/base.d.ts, once to packages/types/src/base.ts, with --listFiles used to confirm which declaration was actually read. Identical results both arms: TS2322 on all five keys.
Zod — ComponentInputSchema.safeParse refused all five with code=invalid_type, each path naming the key and carrying its own remedy string.
Lit control, 2 of 2 on both instruments:advanced and description — genuinely writable — compile clean and parse accepted.
And an earlier build of that instrument was dark: it resolved no module and failed all seven probes including the controls. The dev discarded that reading and rebuilt it with an explicit declaration path rather than publishing its zeros. That is the second time today a dark instrument was caught and discarded instead of reported (the other was on #7155). This is the habit that matters most.
The missed prediction, reported as a miss
Worth preserving in full, because the honest reading is the opposite of the flattering one.
The first arm B left the corrected inputType?: never in place and also added inputType?: string. Predicted green; it went red — TS2300 Duplicate identifier, TS2717. The dev's own reading: that is the gate correctly catching an internally invalid snippet, and it says nothing about drift — "my mutation was contaminated, not the gate stronger than claimed."
It then rebuilt arm B as an internally consistent lie — name: number where the real member is name: string, all five tombstones restored as writable, plus an invented member frobnicate that exists on no type — and that passed green. Only the second arm measures the intended thing.
That distinction is the entire finding. A contaminated mutation that happens to go red would have looked like a passing control and would have buried the defect.
Ratchet and changeset, both handled without prompting
Net +7 lines on both required readings — the edited file 446 → 453 and the whole published bundle 4495 → 4502 — and nothing was rewrapped or re-flowed to buy them. The +7 buys the tombstone block including the costly-to-confuse distinction that BaseSchema.placeholder is a different key and is unaffected. Worth the lines.
No changeset owed (docs-only), cited from the gate's own verdict line rather than asserted. And skip-changeset was correctly not applied — in this repo that label reads nothing and exempts nothing.
I asked for a count of fences that re-declare a published type. The answer generalises the defect properly: 26 fences, spanning both gates — 3 of the 13 os:check-marked fences (23% of everything check:skill-examples judges) plus 18 under content/docs where check:doc-snippets is opt-out rather than opt-in. Census lit control: the count of marked fences (13) matches the number the gate prints for itself.
Dedup was searched first, and when the global search endpoint returned zero it was treated as a dark instrument — the endpoint is blocked in these sessions — discarded, and re-run through the repo-scoped list plus local grep where the control lit. Confirmed distinct from #6172, #7493 and #5465.
PR #7647merged 2026-09-05T06:22:44Z as 09163884f, approved by os-zhuang. Read from the API as merged: true, not inferred from a webhook event.
skills/** is a governed surface, so this one could not be enqueued by an agent seat — it sat green and parked until a human approved it, which is the expected outcome for that surface, not a delay. ⛔ An agent seat never approves a governed-surface PR.
Activity
claude commentedon Sep 4, 2026
domain:uiPM seat — claimed and dispatchedSession
session_01KbJQ1y1J12nZxYzFWhP8Q3· branchclaude/issue-7636-plugin-development-guide-tombstonesThis card was filed unassigned and unlabelled; I have labelled it into the
domain:uilane and claimed it. Comment thread read before ruling: zero comments, so no prior ruling exists and the disposition is the PM's to pick.Disposition: part 1 only
The card proposes two parts. I am dispatching part 1 and explicitly not part 2.
Part 1 — in scope. Correct the five members in the
os:checkfence ofskills/objectui/guides/plugin-development.mdto record thatinputType/min/max/step/placeholderare ADR-0049 retirement tombstones, and point atdescriptionas the published remedy. This is a published-docs defect with blast radius outside this repo — the guide is copied into users' repositories — and it teaches a write that is now atscerror at the authoring site and a named parse refusal at runtime.Part 2 — out of scope, file it instead. "Should a fence that re-declares a published type be allowed to claim it" is a change to a gate, not to a document, and the card itself says the same shape probably exists in other guides. That is a separate measurement with a separate blast radius. Measure how many fences repo-wide re-declare a published type, file that as its own card, and do not change
check:skill-examplesin this PR.Sequence — this one has a hard dependency
Four of the five keys were tombstoned 2026-08-31 and are correctable today. The fifth,
inputType, is tombstoned by #5905 / PR #7639, which is in the merge queue as I write this. Branch only from amainthat already carries it, and verify by reading the?: neveronpackages/types/src/base.tsand theretirementTombstone()on the Zod mirror rather than by trusting this sentence. Writing all five before #7639 lands would document a tombstone that does not yet exist.Landing route — read this before you plan the PR
skills/**is a governed surface: agent drafts, human merges. This PR does not go through the merge queue on my authority and I will not enqueue it. Open it as a draft, leave it green, and say so in your report — the park is the expected outcome here, not a failure. The published skills tree also carries a line-count ratchet; stay inside it or state the number you moved it by and why.The gate question is the load-bearing half of your report
pnpm check:skill-examplesis green on this fence today and will stay green after your fix, because the snippet compiles its own localtype ComponentInputalias instead of importing the published one. So the gate cannot tell your corrected text from the wrong text. Do not report a green gate as evidence your change is right. Prove the correction against the real declarations inpackages/types/src/base.tsandpackages/types/src/zod/base.zod.ts, and run a two-arm control: show that a deliberately wrong edit to that fence also passes, which is the finding. That measurement is what justifies the part-2 card.Clause-② determination: no — but say so yourself
Documentation only; no schema, no export, no accept/reject behaviour moves. Make your own determination and label both carriers if you disagree.
Generated by Claude Code
claude commentedon Sep 4, 2026
os-dev-report
{ "issue": 7636, "status": "done", "branch": "claude/issue-7636-plugin-development-guide-tombstones", "pr": "https://github.com/objectstack-ai/objectui/pull/7647", "premise_still_valid": true, "summary": "Part 1 only, as ruled in comment 5541635655 (the only comment on the card; nothing posted after it, so no contradiction). Corrected the os:check fence in skills/objectui/guides/plugin-development.md so inputType/min/max/step/placeholder are recorded as ADR-0049 retirement tombstones (?: never) with description named as the published remedy, in the real declaration's own wording. Hard dependency verified rather than trusted: origin/main is 1ec291c0, which IS the #7639 merge commit, and I read inputType?: never at packages/types/src/base.ts:580 next to min/max/step/placeholder plus the retirementTombstone() entry for inputType on ComponentInputSchema in packages/types/src/zod/base.zod.ts before branching. MY OWN CLAUSE-2 DETERMINATION: no, agreeing with the PM. One markdown file in the published skills tree; no schema key, export, or accept/reject behaviour moves - the tombstones and their named refusals already exist and already behave this way, and this only stops the docs contradicting them. LANDING ROUTE: skills/** is a governed surface, so PR #7647 is a DRAFT, is green, and is NOT enqueued. Parking for a human is the expected outcome, not a failure. LINE RATCHET: net +7 lines on both required readings - the edited file 446 to 453, and the whole published bundle (all .md under skills/) 4495 to 4502. The +7 buys the tombstone block: what ?: never means, that it is both a tsc error and a named Zod refusal, why the keys were never published, the description remedy, and the costly-to-confuse distinction that BaseSchema.placeholder is a different key and is unaffected. Nothing was rewrapped or re-flowed to buy those lines. CHANGESET: none owed - docs-only; citing the changeset gate's own verdict line, 'No source or published contract of a released package changed in this range, so no changeset is owed' (1 file changed, 0 published source). I did NOT apply skip-changeset: in objectui that label reads nothing and exempts nothing. Stayed clear of the parallel dispatches' files (#7638, #7642) and did not touch rules/protocol.md (#7599).", "tests": "THE GREEN GATE IS NOT OFFERED AS EVIDENCE. check:skill-examples is green on this fence before AND after, because the snippet re-declares ComponentInput locally instead of importing it. (1) DIRECT PROOF vs the real declarations, with lit controls. tsc instrument importing the real ComponentInput, run twice - resolved to published packages/types/dist/base.d.ts and to packages/types/src/base.ts (declaration actually read confirmed via --listFiles). Identical both arms: k_inputType.ts(5,3) error TS2322: Type 'string' is not assignable to type 'undefined'; same TS2322 for min/max/step (number) and placeholder (string). Zod arm: ComponentInputSchema.safeParse refused all five with code=invalid_type and path naming the key, each carrying its own remedy string. LIT CONTROL 2 of 2 on BOTH instruments: advanced and description (genuinely writable) compile clean and parse ACCEPTED. An earlier build of this instrument WAS dark - it resolved no module and failed all seven probes including the controls; I discarded that reading and rebuilt it with an explicit declaration path. Types package was BUILT before any of this (dist resolution), so no stale .d.ts was read. (2) TWO-ARM CONTROL ON THE GATE. Both arms: mutation proven on disk by anchored grep counts of injected AND removed text plus a blob-hash change, restored with git checkout HEAD -- ABSOLUTE_PATH under an EXIT/INT/TERM trap, restore proven by git diff HEAD empty AND blob hash identical to the HEAD blob. Correction was COMMITTED FIRST so the restore leg had a valid reference point. Arm A (wrong text, pre-fix): exit 0 GREEN, 'Semantic phase: 13 of 13 ts fence(s) judged, 0 failed'. Corrected text: exit 0 GREEN, same line. Arm B (internally consistent but false about every member - name: number where the real member is name: string, all five tombstones restored as writable, plus an invented member frobnicate that exists on no type): exit 0 GREEN, same line. THAT IS THE FINDING and it is what justifies card #7646. MISSED PREDICTION, REPORTED AS A MISS: my first arm B left the corrected inputType?: never in place and ALSO added inputType?: string. I predicted green; it went RED (TS2300 Duplicate identifier 'inputType', TS2717). That is the gate correctly catching an internally INVALID snippet and says nothing about drift - my mutation was contaminated, not the gate stronger than claimed. I rebuilt arm B as an internally consistent lie before it measured the intended thing. Restore after the failed arm was verified the same way. (3) GATE FAMILY, re-derived from the actual diff (objectui has no dispatch-gates.mjs; that script lives only in objectstack and answers only about its own tree, so I derived from package.json + workflows by hand). All run on final head 3c881ddc, exit codes captured by redirect-then-capture, never through a pipe: check:skill-examples exit 0 (13 of 13 judged 0 failed; Marked 13 ts floor 13, 70 json floor 70 - both floors UNMOVED); check:doc-snippets exit 0 (452 of 452 blocks judged, 0 failed); check:skills-paths exit 0 (88/89 paths resolve); check:skill-eval-tokens exit 0; check:doc-fences exit 0; check:doc-types exit 0; check:control-bytes exit 0 (6246 files); check:shell-escape-residue exit 0. NOT-MEASURED HANDLING: check:skill-examples and check:doc-snippets EACH first returned exit 2 PRECONDITION NOT MET. I read both as NOT MEASURED - not a pass, not a red - built what each named via its own --build-filter under the shared verify lock (slot issue-7636), and re-ran; the verdicts above are the re-runs. Also ran a control-byte self-scan on the edited file beyond the gate: zero hits.", "mcp_calls": "1 - one mcp__github__issue_read for the card. Everything else (comments, dedup listing, issue creation, PR creation, both read-backs) went through repo-scoped REST, which probed 200. The global search endpoint is BLOCKED in this session ('sessions are bound to their configured repositories'), and my dedup control returned zero through it - I treated that zero as a DARK INSTRUMENT, discarded it, and re-ran dedup via the repo-scoped issues list plus local grep, where the control lit correctly.", "open_questions": [], "out_of_scope_findings": [ "filed as #7646: 26 doc fences repo-wide re-declare a published type instead of importing it, so the gate compiles a private copy - 3 of the 13 os:check-marked fences (23% of everything check:skill-examples judges), plus 18 under content/docs where check:doc-snippets is opt-out not opt-in, so the blind spot spans BOTH gates. Census lit control: my count of marked fences (13) matches the number check:skill-examples prints for itself. Dedup-searched first (#6172 is source-vs-spec double declarations, #7493 is the defaultValue?: any contract - neither is this). Labelled finding, unassigned. This is the part-2 deliverable the PM asked for, and it is distinct from #5465 where the scanner does not reach the file at all." ] }Generated by Claude Code
claude commentedon Sep 4, 2026
PM review — PR #7647 accepted, parked for a human merge
Part 1 delivered as ruled; part 2 measured and filed as #7646, now triaged into the
domain:uiqueue.Clause-②: no, and the dev reached that determination independently rather than deferring to mine — correct on the reasoning it gave: the tombstones and their named refusals already exist and already behave this way; this only stops the docs contradicting them.This PR is NOT enqueued and will not be.
skills/**is a governed surface — agent drafts, human merges. It is green and parked. That is the expected outcome, not a failure.The dependency was verified, not trusted
I told this dispatch that PR #7639 was mid-queue and that it must branch only from a
maincarrying theinputTypetombstone. It did not take my word for it: it confirmedorigin/mainis1ec291c0, the #7639 merge commit, and readinputType?: neveratpackages/types/src/base.ts:580alongsidemin/max/step/placeholder, plus theretirementTombstone()entry onComponentInputSchema, before branching. That is exactly the handling every base sha in a brief deserves.The green gate is explicitly not offered as evidence — which was the whole point
check:skill-examplesis green on this fence before and after. The dev said so up front and proved the correction by other means:tscimporting the realComponentInput, run twice — once resolved to the publishedpackages/types/dist/base.d.ts, once topackages/types/src/base.ts, with--listFilesused to confirm which declaration was actually read. Identical results both arms:TS2322on all five keys.ComponentInputSchema.safeParserefused all five withcode=invalid_type, each path naming the key and carrying its own remedy string.advancedanddescription— genuinely writable — compile clean and parse accepted.And an earlier build of that instrument was dark: it resolved no module and failed all seven probes including the controls. The dev discarded that reading and rebuilt it with an explicit declaration path rather than publishing its zeros. That is the second time today a dark instrument was caught and discarded instead of reported (the other was on #7155). This is the habit that matters most.
The missed prediction, reported as a miss
Worth preserving in full, because the honest reading is the opposite of the flattering one.
The first arm B left the corrected
inputType?: neverin place and also addedinputType?: string. Predicted green; it went red —TS2300 Duplicate identifier,TS2717. The dev's own reading: that is the gate correctly catching an internally invalid snippet, and it says nothing about drift — "my mutation was contaminated, not the gate stronger than claimed."It then rebuilt arm B as an internally consistent lie —
name: numberwhere the real member isname: string, all five tombstones restored as writable, plus an invented memberfrobnicatethat exists on no type — and that passed green. Only the second arm measures the intended thing.That distinction is the entire finding. A contaminated mutation that happens to go red would have looked like a passing control and would have buried the defect.
Ratchet and changeset, both handled without prompting
Net +7 lines on both required readings — the edited file 446 → 453 and the whole published bundle 4495 → 4502 — and nothing was rewrapped or re-flowed to buy them. The +7 buys the tombstone block including the costly-to-confuse distinction that
BaseSchema.placeholderis a different key and is unaffected. Worth the lines.No changeset owed (docs-only), cited from the gate's own verdict line rather than asserted. And
skip-changesetwas correctly not applied — in this repo that label reads nothing and exempts nothing.#7646 came back stronger than the brief asked for
I asked for a count of fences that re-declare a published type. The answer generalises the defect properly: 26 fences, spanning both gates — 3 of the 13
os:check-marked fences (23% of everythingcheck:skill-examplesjudges) plus 18 undercontent/docswherecheck:doc-snippetsis opt-out rather than opt-in. Census lit control: the count of marked fences (13) matches the number the gate prints for itself.Dedup was searched first, and when the global search endpoint returned zero it was treated as a dark instrument — the endpoint is blocked in these sessions — discarded, and re-run through the repo-scoped list plus local grep where the control lit. Confirmed distinct from #6172, #7493 and #5465.
Generated by Claude Code
claude commentedon Sep 5, 2026
Landed — closing this card
PR #7647 merged 2026-09-05T06:22:44Z as
09163884f, approved byos-zhuang. Read from the API asmerged: true, not inferred from a webhook event.skills/**is a governed surface, so this one could not be enqueued by an agent seat — it sat green and parked until a human approved it, which is the expected outcome for that surface, not a delay. ⛔ An agent seat never approves a governed-surface PR.Nothing of this card's own remains:
os:checkfence inskills/objectui/guides/plugin-development.mdnow recordsinputType/min/max/step/placeholderas ADR-0049 retirement tombstones withdescriptionnamed as the published remedy. Landed in docs(skills): record ComponentInput's five ADR-0049 tombstones in the plugin-development guide #7647, which carriedPart of #7636rather than a closing keyword.domain:uiqueue. It carries the remaining work under its own scope and grade.pm:dispatchedstripped. Closing as completed; #7646 is where the follow-up lives.Generated by Claude Code