Repository navigation
gate(doc-types): rule the 25 non-component type vocabularies the package-README census found and write their DOC_TYPE_EXEMPTIONS entries — the precondition for objectui#7896's fourth leg #8115
Description
Activity
- addeddomain:devxobjectui devx stream: fix lands on .github/, scripts/ or release pipeline — devx lane cross-repoobjectui devx stream: fix lands on .github/, scripts/ or release pipeline — devx lane cross-repoand removed
on Sep 7, 2026 Triage: lands in
domain:devx(scripts/check-doc-component-types.mjs'sDOC_TYPE_EXEMPTIONS);Task,priority:p3,pm:queue.Admission basis, stated because it is not one of the three classes. This card records no defect — the 25 are "genuine non-component vocabularies, each with a declaration site in source", and the one real defect the census found is carded separately. It is admitted because ⭐ objectui#7896 carries
Blocked-by:this card and ispm:blockedon it today. Closing it would orphan a live blocker and strand that card's fourth leg with no owner — the same reasoning applied to objectui#8281 (the exemption ledger for the then-dispatched #8216) earlier today.⭐ And the split is not a preference — it is required by a binding ruling. The
domain:uiPM's ruling on #7896 (comment5556586208) is that ⛔ the table records ruled exceptions; it is not a switch for turning a first run green, and an entry that only says "not a component" teaches nothing. ⇒ Writing 25 entries in the same PR that switches the leg on makes "make it green" and "record the ruling" the same act, which is exactly what that ruling forbids. Keeping them apart is what keeps each entry reviewable as a ruling.priority:p3, matching #7896's own grade: nothing is red, nothing is unenforced today — the leg is not on. This is preparatory work for a coverage widening.⭐ The census is trustworthy and ⛔ should not be re-derived: PR #8111 walked all 39
packages/NAME/README.mdwithcheck:doc-types' own extractor and registry — 385 blocks, 237typeliterals, 26 unregistered across 12 files.⚠️ And the 4 blind spots are declared rather than hidden (unquoted YAML field-type scalars atdata-objectstack/README.md:603-606, which the extractor never sites and so owe no entry) — ⛔ do not write exemptions for them.⚠️ The acceptance is binary per site and ⛔ must not be softened: each of the 25 either gets aDOC_TYPE_EXEMPTIONSentry naming the vocabulary and its declaration site — so the next reader can re-check it — or is re-classified as a defect and carded. ⛔ There is no third bucket, and ⛔ "not a component" is not a reason.Scope fences, all from the card and all holding: ⛔ no package README content edits here; ⛔ the leg itself does not land here (that is #7896's, after this card and the plugin-detail defect card close). ⇒ Whoever takes this should confirm both blockers before #7896 is unblocked, not just this one.
⭐ Dedup discipline noted: the semantic search returned zero and the sibling search filed alongside returned three cards, so the channel answers — a reading, not a dead instrument.
⛔ This seat grades and routes only: not claimed, not dispatched, no code, and ⛔ it does not pre-rule any of the 25.
Generated by Claude Code
Claim: PM loop round R46 —
domain:devx @ objectuiexecution seat.
Session:session_01FhBNJcLRZLe8M87VcUgpKr
Branch:claude/issue-8115-doc-type-exemptions
Worktree:/home/user/objectui-issue-8115
Domain:domain:devx
Dispatch: oneos-devsubagent of this session (mode:subagent,model: opus); the dispatch note with the brief follows. Labelspm:queue→pm:dispatchedand assignee set in one write, read back and diffed against the union at 2026-09-08T01:55Z.⚠️ ⚠️ This seat put FOUR false premises into dispatch briefs today —660 judged(tree: 663),1309fences (read in the shared checkout;origin/mainreads 1310),UNGATED_DOCS = {}(it holds 4), and "objectui#8045 is open" (closed 2026-09-07T19:09:04Z). ⭐ The last brief instructed the dev to re-read every referenced card on GitHub while this seat took that card's status from the card's own record table. ⇒ Every fence, number and card status below is a PREDICTION. Re-derive before you act on it, and a corrected brief with zero implementation is a good outcome.⚠️ SIX cards this shift carried a false premise in the card face itself — #8006 #8029 #8113 #8117 #8122 #7925, three of them repeated verbatim in the triage comment.⛔ A zero-hit reading means nothing without a control term you know is present, in the same run. ⛔
origin/mainis verified on a clean extract or a detached worktree, ⛔ NEVER on/home/user/objectui's working tree. ⛔ A grep over a whole file cannot answer a question about one region of it — three probes did exactly that today and hit a docblock, a different schema, and a deliberately dated historical sentence.
Generated by Claude Code
Dispatched —
domain:devx @ objectuiexecution seat, PM sessionsession_01FhBNJcLRZLe8M87VcUgpKr, R46, 2026-09-08T01:57Z. One of three slots (with #8125 and #8366); the previous batch drained — #8461 #8462 #8467 #8470 all merged, #8480 is in the queue.Dev. One
os-devsubagent of this session on branchclaude/issue-8115-doc-type-exemptions, worktree/home/user/objectui-issue-8115, fromorigin/mainated17be480or later. Race re-read at 01:55Z: the newestClaim:is5577907812, naming that branch — and it is the only one. ⛔ The dev posts no second claim and ⛔ never writes the assignee.⭐ The binding ruling is the whole shape of this card, and the brief leads with it. Triage quotes the
domain:uiPM's #7896 ruling (5556586208) verbatim: ⛔ the table records ruled exceptions; it is not a switch for turning a first run green, and an entry that only says "not a component" teaches nothing. ⇒ The brief makes that operational: an entry whose reason is "not a component" is a FAILED entry, not a terse one — each must name the vocabulary and its declaration site so the next reader can re-check the ruling rather than take it. It is also why this card exists separately at all: writing the 25 entries in the same PR that switches #7896's fourth leg on would make "make it green" and "record the ruling" the same act.⛔ Two things triage says NOT to do, both carried. ⛔ Do not re-derive the census — PR #8111 walked all 39 package READMEs with
check:doc-types' own extractor and registry (385 blocks, 237typeliterals, 26 unregistered across 12 files), and triage calls it trustworthy. ⛔ Do not write exemptions for the 4 declared blind spots (unquoted YAML field-type scalars atdata-objectstack/README.md:603-606) — the extractor never sites them, so they owe no entry, and an exemption there would be a ruling about something the gate cannot see.⚠️ One of the 26 is a real defect carded separately; the dev must identify which and ⛔ neither fix nor exempt it.⚠️ The non-vacuity requirement is aimed at the table itself. A waiver table is where "declared but not enforced" hides. The brief requires each entry shown to key a site the extractor actually reaches — an entry keyed to a site never visited is a stale row by construction — and the unregistered count to move by exactly the number of entries written. ⛔ #7896's fourth leg stays off; ⛔ no existing check weakened to accommodate an entry. The third axis is pointed at the dev's own output: which of your 25 entries could a future reader re-check, and how?⚠️ ⚠️ The brief warns the dev about this seat before it warns it about anything else. Four false premises reached dispatch briefs today —660 judged(tree: 663),1309fences (read in the shared checkout;origin/mainreads 1310),UNGATED_DOCS = {}(it holds 4), and "objectui#8045 is open" (closed 2026-09-07). ⭐ That last brief instructed its dev to re-read every referenced card on GitHub while this seat took the status from the card's own record table. ⇒ Every fence, number and card status in the brief is labelled a prediction, and a corrected brief with zero implementation is stated as a good outcome.
Generated by Claude Code
os-dev-report
{ "issue": 8115, "status": "needs_decision", "branch": "claude/issue-8115-doc-type-exemptions", "pr": null, "pr_number": null, "head_sha": "c1ae1af0b14363a64e7a166b3027110559269ff1", "base": "c1ae1af0b14363a64e7a166b3027110559269ff1", "premise_still_valid": false, "premise_notes": "FOUR premises hold, FOUR fail. HOLD: (1) DOC_TYPE_EXEMPTIONS exists in the described shape at check-doc-component-types.mjs:470, keyed file -> value -> reason. (2) objectui#7896 is open, pm:blocked, and its body carries both 'Blocked-by: #8114' and 'Blocked-by: #8115'; #8114 is still open too, so the leg stays blocked on two cards. (3) All 26 census sites still reproduce on c1ae1af0b, file:line:value identical to PR #8111's per-file table, using the gate's own deriveRegistryKeys + its own fence walker + its own type-literal matcher (39 READMEs, 382 blocks, 240 type literals, 656 registry keys). (4) The 4 blind spots are at packages/data-objectstack/README.md:603-606 exactly, four unquoted YAML scalars (lookup(sys_user), string, json, datetime) the quoted-literal matcher cannot see; they owe no entry, confirmed, and none was written. FAIL: (A) THE CARD'S CENTRAL PREMISE — that the 25 entries can be written before objectui#7896's fourth leg lands — is false and this is the blocker; see open_questions. (B) '26 across 12 files' is wrong: it is 8 files, and PR #8111's OWN per-file table already listed 8 while its TOTAL row and prose said 12; the wrong number is now merged into the gate header at check-doc-component-types.mjs:287 and was propagated into this card's body and its triage comment. Filed as objectui#8484. (C) '25 entries' is a site count, not an entry count: 25 sites map to 22 distinct (file,value) keys, because plugin-grid 'multiple' occupies 3 sites (177/380/551) and plugin-dashboard 'line' occupies 2 (226/344). Any acceptance that counts 25 table rows cannot be met. (D) 'each a genuine non-component vocabulary with a declaration site' is false for at least one of the 25: packages/app-shell/README.md:395 teaches flow node type 'action', which is absent from FlowNodeAction (objectstack packages/spec/src/automation/flow.zod.ts:27-51, 20 members), absent from NODE_PALETTE (flow-canvas-parts.tsx:333-355, 18 kinds) and handled nowhere in the flow canvas/layout/inspector/simulator. Re-classified as a defect and filed as objectui#8483, which is what the card's acceptance prescribes for this case.", "summary": "No code written and no PR opened, deliberately. The card asks for DOC_TYPE_EXEMPTIONS entries keyed to packages/NAME/README.md while forbidding the fourth leg that would put those files in the walk. The gate makes that combination impossible: analyze() populates exemptionHits ONLY from docs.sites, and any entry with no hit is reported as stale-exemption (lines 1292-1301). Measured with a control in the same run: an entry keyed to content/docs/blocks/dashboard.mdx -> navigate is exempted (counter 1, no finding), while packages/app-shell/README.md -> start comes back 'stale-exemption: no code block in that file spells this type any more'. So the 22 entries would produce 22 stale-exemption findings and a RED gate. The card's own non-vacuity criterion is independently unsatisfiable for the same reason: 'the count of unregistered values moves by exactly the number of entries written' requires the sites to be IN the scan, and today they contribute 0 to that count. The three escapes are each closed by an explicit fence: land the leg (forbidden), weaken stale-exemption (forbidden), or invent a pending-rulings surface (a declared-but-not-enforced table with no staleness detector). This is a sequencing decision above the seat, so the card stops here with the measurement, the corrected arithmetic, the two re-classifications, and better declaration sites than the census named. Ruling work that survives, for whoever lands it: gestures are declared at packages/types/src/mobile.ts:278 (export type GestureType), not at the useGesture.ts / useSpecGesture.ts pair the census cited; report kinds matrix/joined at packages/types/src/spec-report.ts:82 (SpecReportTypeName); and plugin-report's 'bar' at README:247 is a CHART SERIES kind under chart.type (dispatched at DatasetReportRenderer.tsx:696), a different vocabulary from matrix/joined, which the census table lumps with them.", "files_changed": [], "tests": "check:doc-types BEFORE, on c1ae1af0b, worktree /home/user/objectui-issue-8115: EXIT=0, verdict line 'Scanned 188 doc file(s) (.mdx + .md), 1106 code block(s), 891 `type` literal(s) against 656 registered key(s) derived from 144 source file(s) (240 resolved call site(s), 132 indirect, 2 open): 774 registered, 117 exempted; 4 key table(s), 24 row(s), 45 table key(s) judged (namespaced + bare), 45 registered.' + 'Every documented component type is registered.' AFTER: byte-identical (diff of the two captures is empty), EXIT=0 — no file was edited, git status --porcelain is empty. REACHABILITY PROBE, via the gate's exported analyze(root, {exemptions}) so no file was mutated: exemptions = { 'content/docs/blocks/dashboard.mdx': { navigate: CONTROL }, 'packages/app-shell/README.md': { start: PROBE } }. Result: 'exempted counter: 1' and exactly one stale-exemption finding — 'packages/app-shell/README.md -> start | no code block in that file spells this type any more.' The CONTROL entry produced no stale finding in the same run, so the probe measured reachability rather than a broken harness. CENSUS RE-RUN with the gate's own deriveRegistryKeys + fence walker + type matcher over all 39 packages/NAME/README.md: 'README files: 39 | blocks: 382 | type literals: 240 | registry keys: 656 / unregistered sites: 26 across 8 file(s) / distinct (file,value) pairs: 23' (23 minus the objectui#8114 activity-timeline defect = 22 candidate entries covering 25 sites). node scripts/check-changeset-presence.mjs: EXIT=0, '0 file(s) changed, 0 of them published source ... no changeset is owed.' node scripts/check-governed-queue-guard.mjs --test scripts/check-doc-component-types.mjs: EXIT=0, 'NOT GOVERNED — 1 path(s) checked against 5 governed surface(s); none matched.' Every exit code was captured by redirecting to a file first and reading $? on the next statement, never across a pipe. No ablation was owed: nothing was implemented, so there is nothing to ablate; the reachability probe above is the equivalent falsifiability evidence and it carries its own positive control.", "four_axis_analysis": { "option_A_atomic_leg_plus_entries_in_7896": { "shape": "This card produces and reviews the ruled set (22 entries, each naming vocabulary + declaration site); objectui#7896's PR lands the leg AND those entries in one commit, because the gate admits no other order. The ruling's separation is preserved as a REVIEW separation, not a commit separation.", "real_business_need": "Highest. The measured need is that packages/NAME/README.md ships to npm inside each package's files list and its type literals are read twice by sibling gates and judged by none — objectui#7896's actual defect. This is the only option that ends with that surface guarded. The other two end with rulings written down and the surface still unguarded.", "long_term_soundness": "Sound, and it is contract-first: the entries and the surface they describe enter the tree together, so the table is never describing files nobody walks. It costs one reviewable-as-a-ruling artifact separate from the commit, which is a review-process cost, not an architectural one.", "ai_error_resistance": "Strongest. Every entry is enforced the moment it exists: a wrong or outdated entry fails as stale-exemption on the next run. Nothing is declared that the runtime does not honour, which is the third axis stated exactly. The failure the axis warns about — a waiver table becoming a place to put things — is structurally impossible when each row is checked on every run.", "startup_focus": "Cheapest of the three: no new mechanism, no new surface, no transitional window. It adds nothing to the tree that has to be retired later.", "tension": "It reads against the triage seat's gloss that leg-plus-entries in one PR is what the domain:ui ruling forbids. But the ruling's words forbid an entry that only says 'not a component' and forbid using the table as a switch for turning a first run green — not co-landing well-ruled entries. And the seat's own measurement (objectui#8483) shows the entries cannot be transcribed as a group anyway, which is the substance the ruling was protecting." }, "option_B_relax_stale_exemption_for_a_declared_pending_surface": { "shape": "Teach the gate that an exemption may name a file on a declared-pending scan surface, so entries can land ahead of the walk.", "real_business_need": "None measured. No second consumer wants this; it exists only to make this card's stated order possible.", "long_term_soundness": "Poor. It adds a second, weaker class of exemption whose evidence is a promise about a future walk. The gate's header states the opposite as its design: an exemption is worth what its evidence is worth.", "ai_error_resistance": "Worst on this axis. It converts the one detector that keeps this table honest into a detector with a hole, and the hole is exactly the shape a future agent reaches for when a first run is red. This is also the card's own explicit fence: do not weaken any existing check to accommodate an entry.", "startup_focus": "A new mechanism with one caller and a retirement obligation nobody will schedule. Rejected on this axis alone.", "verdict": "Rejected." }, "option_C_pending_rulings_as_a_comment_block": { "shape": "Write the 22 rulings as a comment beside DOC_TYPE_EXEMPTIONS now, to be lifted verbatim into the table when the leg lands. PR #8111 set this precedent for the census itself.", "real_business_need": "Partial. It records the rulings and closes this card, but guards nothing and leaves objectui#7896 blocked on the same decision one round later.", "long_term_soundness": "Weak. It creates a second copy of the table's content in a form the gate does not read, and the transcription step is unverified — the very drift the (file,value) keying exists to prevent.", "ai_error_resistance": "Weak, and it fails the axis on its own terms: 22 rulings in a comment are declared and not enforced, with no staleness detector, so they rot exactly like a stale exemption but silently. Answering the brief's question directly — a future reader could re-check each reason by grep against the named declaration site, but nothing would tell them WHEN one went stale, which is the property the live table has and the comment does not.", "startup_focus": "Adds a transitional artifact with a hand-off step, in a repo whose standing ruling is that transitions are immediate and no staged window is set up without named external evidence.", "verdict": "Viable but dominated by A." }, "recommendation": "Option A. It is the only option that ends with the surface guarded, the only one where every written entry is enforced from the moment it exists, and the only one that adds no mechanism the tree has to carry. The maintainer or the domain:ui PM should confirm that co-landing well-ruled entries with the leg is consistent with the comment-5556586208 ruling; the seat will not read that ruling in its own favour without a decision." }, "open_questions": [ { "question": "The gate reports stale-exemption for any DOC_TYPE_EXEMPTIONS entry whose (file,value) is not hit by the walk, and packages/NAME/README.md is not in the walk until objectui#7896's fourth leg lands. Measured with a control. So this card cannot write its entries without either landing the leg (its own fence forbids) or weakening the check (its own fence forbids). Which order does the project want?", "options": [ "A — this card produces and reviews the 22 ruled entries as a reviewable artifact, and objectui#7896's PR lands the leg and the entries atomically, since the gate admits no other order", "B — teach the gate a declared-pending scan surface so an exemption may name a file the walk does not yet reach", "C — record the 22 rulings as a comment beside the table now, lifted into the table when the leg lands" ], "recommendation": "A, because it is the only order in which every entry is enforced from the moment it exists (axis 3), the only one that ends with the README surface actually guarded (axis 1), and the only one that adds no mechanism the tree must later retire (axis 4). It needs one confirmation: that the comment-5556586208 ruling forbids UNRULED entries used as a green switch, not well-ruled entries co-landing with the leg." }, { "question": "The card's acceptance counts 25 entries; the table is keyed by (file,value) and 25 sites collapse to 22 keys (plugin-grid 'multiple' spans 3 sites, plugin-dashboard 'line' spans 2). Should the acceptance be restated as 22 entries covering 25 sites?", "options": [ "restate the acceptance as 22 (file,value) entries covering 25 sites", "leave 25 as a site count and say so in the card" ], "recommendation": "Restate as 22 entries / 25 sites. A reviewer counting 25 rows against 22 correct entries reads correct work as incomplete, and the (file,value) keying is deliberate and load-bearing per the gate header." }, { "question": "Instruction conflict, reported rather than resolved silently: the dispatch brief says any card this seat files carries the `finding` label ONLY, while the seat's standing rules say a concrete defect carries NO label and is left for triage to grade, with `finding` reserved for observations. Acting on the stricter reading, objectui#8483 (a concrete defect) was filed unlabelled and objectui#8484 (a drift observation) was filed `finding`. Neither carries a domain:* or an assignee. Confirm or correct.", "options": [ "confirm: concrete defect unlabelled, observation `finding`", "correct: label both `finding`" ], "recommendation": "Confirm. `finding` on a concrete defect pre-grades it, and both readings agree that no domain:* and no assignee is right." } ], "out_of_scope_findings": [ "filed as objectui#8483 (no labels, unassigned): packages/app-shell/README.md:395 teaches flow node type 'action', absent from FlowNodeAction (objectstack packages/spec/src/automation/flow.zod.ts:27-51) and from NODE_PALETTE (flow-canvas-parts.tsx:333-355) and handled nowhere in the flow code — the SECOND re-classification out of the 26, alongside objectui#8114's activity-timeline. Not exempted, not repaired, as the card requires.", "filed as objectui#8484 (`finding`, unassigned): the gate's merged header at check-doc-component-types.mjs:287 records the census as '26 across 12 files'; PR #8111's own per-file table lists 8 and a re-run on c1ae1af0b reads 8. The wrong number was propagated into this card's body and into its triage comment, which forbids re-deriving the census — so it is designed to be taken rather than checked.", "NOT filed, reported here because it is inside this card's own subject: the census table's vocabulary column is wrong for plugin-report:247 'bar' (a chart series kind under chart.type, dispatched at DatasetReportRenderer.tsx:696, NOT a report schema kind like matrix/joined at packages/types/src/spec-report.ts:82), and it cites weaker declaration sites than exist for two more groups (gestures are declared at packages/types/src/mobile.ts:278 as export type GestureType, not at useGesture.ts / useSpecGesture.ts). This is the concrete evidence that the 25 cannot be transcribed from PR #8111's table and must be ruled one at a time, which is what the domain:ui ruling asked for." ], "mcp_calls": "2 — both mcp__github__issue_write (filing objectui#8483 and objectui#8484). Every card and comment READ went through the zero-quota channels: the issue page's embedded JSON payload for objectui#8115 (frontTimelineItems hasNextPage: false, 15 items, so the comment list is complete) and repo-scoped REST for objectui#7896, objectui#8114 and PR #8111. Dedupe before filing used repo-scoped REST label listings (finding: 154 rows over 2 pages; documentation: 31 rows) plus local grep, with objectui#7896 as the known-present positive control in the same scan." }
Generated by Claude Code
ACCEPT — and the deliverable is that the card cannot be done as written.
domain:devx @ objectuiexecution seat, PM sessionsession_01FhBNJcLRZLe8M87VcUgpKr, R46, reviewed 2026-09-08T02:20Z against GitHub and the tree, ⛔ never against the report's narrative. Zero code, no PR, and that is the right outcome.pm:retriagegoes on with this comment;pm:dispatchedstays.⭐ The blocker, and it is the gate's own header that says so
The card asks for
DOC_TYPE_EXEMPTIONSentries keyed topackages/NAME/README.mdwhile forbidding the fourth leg that would put those files in the walk. Those two cannot both hold. Verified by this seat on a cleanorigin/mainextract:scripts/check-doc-component-types.mjs:267 * `packages/NAME/README.md` — MEASURED, DELIBERATELY NOT WALKED (objectui#7896). scripts/check-doc-component-types.mjs:132 * … that value, or that carries no reason, fails as `stale-exemption` — an …⇒ An entry whose (file, value) the walk never hits fails. The 22 entries would produce 22
stale-exemptionfindings and a red gate.⭐ And the dev measured it with a control in the same run rather than arguing it, through the gate's exported
analyze(root, {exemptions})so no file was mutated:entry result content/docs/blocks/dashboard.mdx → navigate(control, a file in the walk)exempted, counter 1, no finding packages/app-shell/README.md → start(the probe)stale-exemption: no code block in that file spells this type any more⇒ The probe measured reachability, not a broken harness. ⭐ And the card's own non-vacuity criterion is unsatisfiable for the same reason: "the count of unregistered values moves by exactly the number of entries written" requires those sites to be in the scan, and today they contribute 0 to it. The acceptance criterion and the fence contradict each other.
The three escapes are each closed by an explicit fence — land the leg (⛔ forbidden by this card), weaken
stale-exemption(⛔ forbidden by the brief), or invent a pending-rulings surface (a declared-but-not-enforced table with no staleness detector, which the third axis bans). ⇒ This is a sequencing decision above the seat, and stopping was correct.⚠️ Three corrections to the card face, and one of them is inside the instruction not to check- "26 across 12 files" is wrong — it is 8. Confirmed here at
scripts/check-doc-component-types.mjs:287, where the merged gate header reads "26 unregisteredtypeliterals across 12 files". PR docs(gates): record the package-README census and defer check:doc-types' fourth leg (objectui#7896) #8111's own per-file table already listed 8 while its total row and prose said 12; the wrong figure was then propagated into this card's body and into its triage comment. ⭐ That comment is the one that says ⛔ do not re-derive the census — so the number was designed to be taken rather than checked, and it is wrong. ⇒ Two instructions conflicted (triage's "don't re-derive" against the brief's "re-derive before you act"); the dev took the stricter one and was right. Filed as finding(gate):check-doc-component-types' header records the package-README census as "26 across 12 files" — PR #8111's own per-file table lists 8, and a re-run on today's tree reads 8 #8484. - "25 entries" is a site count, not an entry count. The table is keyed by (file, value), and 25 sites collapse to 22 distinct keys —
plugin-grid'smultipleoccupies 3 sites,plugin-dashboard'slineoccupies 2. ⇒ A reviewer counting 25 rows against 22 correct entries would read correct work as incomplete. The acceptance is hereby restated as 22 entries covering 25 sites, and that is a bookkeeping correction this seat can make. - At least one of the 25 is not a non-component vocabulary at all.
packages/app-shell/README.md:395teaches flow node typeaction, absent fromFlowNodeAction, absent fromNODE_PALETTE, and handled nowhere in the flow canvas/layout/inspector/simulator. ⇒ The second re-classification out of the 26, after docs(plugin-detail): README teaches a detail tab whosecontent.typeisactivity-timeline, which nothing registers — a reader gets the OBJUI-001 panel #8114's. Filed as docs(app-shell): the README's flow draft teaches node typeaction, whichFlowNodeActiondoes not contain and nothing in the flow canvas handles — a second re-classification out of the #8111 census #8483, ⛔ not exempted and ⛔ not repaired — which is what the card's own acceptance prescribes for this case.
⭐ This is also the concrete proof that the 25 cannot be transcribed from PR #8111's table. The census's vocabulary column is wrong for
plugin-report:247'sbar(a chart series kind underchart.type, dispatched atDatasetReportRenderer.tsx:696, not a report schema kind likematrix/joinedatspec-report.ts:82), and it cites weaker declaration sites than exist — gestures are declared atpackages/types/src/mobile.ts:278asexport type GestureType, not at theuseGesture.ts/useSpecGesture.tspair the census named. ⇒ Each of the 22 has to be ruled one at a time, which is exactly what thedomain:uiruling asked for. That ruling work survives this card and is recorded above.⛔ What is being asked of triage, ⛔ not answered here
The sequencing fork, with the dev's recommendation and this seat's agreement that it is not the seat's to take:
- A — this card produces and reviews the 22 ruled entries as a reviewable artifact, and finding(gate):
check:doc-typesdoes not walkpackages/NAME/README.md— a package README'stypeliterals are judged by nothing, and objectui#7856's enumeration says otherwise #7896's PR lands the leg and the entries atomically, because the gate admits no other order. The ruling's separation is preserved as a review separation rather than a commit separation. - B — teach the gate a declared-pending scan surface. ⛔ Rejected by the dev on the third and fourth axes, and this seat agrees: it puts a hole in the one detector that keeps the table honest, and the hole is the exact shape a future agent reaches for when a first run is red.
- C — record the 22 rulings as a comment now, lifted into the table when the leg lands. Viable but dominated: 22 declared-and-unenforced rulings with no staleness detector, which is the property the live table has and a comment does not.
⇒ Recommendation A, and it needs exactly one confirmation: that comment
5556586208forbids unruled entries used as a green switch, ⛔ not well-ruled entries co-landing with the leg. ⛔ This seat will not read that ruling in its own favour.⚠️ Note for whoever routes this: #7896 is blocked on two cards, and one is another lane's — verified here, its body carriesBlocked-by: #8114andBlocked-by: #8115, and #8114 is open,pm:queue,domain:ui. So answering this fork unblocks only half of it.⭐ The dev's third open question is answered here, and it corrects THIS SEAT's brief
The dispatch said "any card you file carries the
findinglabel only". The dev flagged that against the standing rule thatfindingmeans an observation awaiting first grading, and that a concrete defect should carry no label so triage grades it. It acted on the stricter reading — #8483 unlabelled (a defect), #8484finding(a drift observation), neither with adomain:*or an assignee — and asked for confirmation.Confirmed. The dev is right and the brief was wrong. Putting
findingon a concrete defect pre-grades it, which is the precise thing this seat has spent the shift telling devs not to do. The brief's blanket wording was over-broad; it is corrected from here, and the two devs still in flight have been told. ⇒ ⭐ A dev catching a PM instruction that contradicts the protocol it is quoting is the rule working exactly as intended.⚠️ Verified independently: #8483 carries no labels and #8484 carriesfindingonly, both unassigned. ⛔ No half-state for this seat to repair.
Generated by Claude Code
- "26 across 12 files" is wrong — it is 8. Confirmed here at
12 remaining items
Claim withdrawn at shift close —
pm:dispatched→pm:queue, assignee cleared. Consolidated seatsession_018rzQyhLGC5iVs11V3TzRs5, 2026-09-09T06:32Z, on the maintainer's instruction in this session's chat at 02:59Z, verbatim: 「当前任务处理完就下班」.The pre-claim (5594703484) waited on objectui#8114 and a free slot; neither came, so no dev was started and nothing is on any branch from this shift. Its content stands: the
pm:retriagewas answered A₁ and the ruled-execution brief under option A remains the dispatch shape. Thedomain:devx @ objectuiseat is vacant (objectui#5748); the next sitter re-claims, re-checks the serial order against #8114, and dispatches.
Generated by Claude Code
pm:blockedon objectui#8114 — the serial order the previous seat measured is real, and #8114 is another lane'sdomain:devx @ objectuiexecution seat, sessionsession_01FhBNJcLRZLe8M87VcUgpKr, R51, 2026-09-09T12:56Z. Picked up from the shift-close brief on objectui#5748, which released this card back topm:queueand told the next sitter to re-check the serial order against #8114 before dispatching. I did, and it does not clear.The blocker, verified rather than inherited
The withdrawn pre-claim (
5594703484) recorded the constraint:#8115's PR stays draft until #8114 merges, because the fourth leg would red on that README's unregistered type
⇒ this card's deliverable is the fourth leg (walking
packages/NAME/README.md), so it cannot land green while a README in that walk teaches acontent.typenothing registers. Read on GitHub just now: objectui#8114 is open,pm:queue, unassigned.⛔ Why I am not simply taking #8114 over to unblock myself
The cross-lane rule lets a blocked seat take a blocker over directly, but only when it is mechanical, clearly specified and S-sized — and ⛔ explicitly not when it carries design judgement, which stays with the owning lane.
#8114 is labelled
domain:ui, and its substance is a choice, not a transcription: a README teaches a detail tab whosecontent.typeisactivity-timelineand nothing registers it. Fixing that is either register the component or correct the docs, and picking between them is a product-surface judgement about whether that capability is meant to exist. ⇒ ⛔ not mine, and taking it would be the cross-lane exception used as a convenience rather than as written.Disposition
pm:queue→pm:blockedin one label write, andBlocked-by: objectui#8114prepended to the body so the unlock sweep can grep it. ⛔ The assignee stays clear — this card is not claimed by anyone and should not read as in-flight.⭐ Everything the previous seat measured stands and is not re-derived: the
pm:retriagewas answered A₁, and the ruled-execution brief under option A in5594703484remains the dispatch shape. ⇒ whoever takes it when #8114 lands re-claims and dispatches that brief; ⛔ there is no need to re-open the A/A₁ question.
Generated by Claude Code
Reconciliation under ruling 5725370464 item 2 (objectstack#18862 b — the twelve cross-author claim pairs) — skills seat,
session_01W5y9kRg1YtYaMQYExVLRc2· 2026-09-19T03:31Z.
⛔ No label, assignee or state change by this comment; the card stayspm:queuewith no assignee.Pair read:
claude[bot](5577907812 at 2026-09-08T01:54Z, no PR) +yinlianghui(5594703484, the maintainer-ordered takeover; withdrawn in prose at shift close, 5597122416). The earlier claimant is the retired identity:Release: session
session_01FhBNJcLRZLe8M87VcUgpKr— 因 claim 5577907812 by the retiredclaude[bot]identity opened no PR; superseded by the maintainer-ordered takeover (5594703484) — 去向pm:queue
Release: sessionsession_018rzQyhLGC5iVs11V3TzRs5— 因 the takeover's own withdrawal at shift close (5597122416:pm:dispatched→pm:queue, assignee cleared), written as prose — 去向pm:queue
Generated by Claude Code
os-try-charles commented
on Sep 19, 2026 CollaboratorMore actionsClaim: PM loop round 85
Session:session_015h79niBMyoB1xcaQje3uiz
Branch:claude/issue-8115-doc-type-exemptions-package-readmes
Worktree:objectui-issue-8115
Domain:domain:devx
File surface:scripts/**,scripts/__tests__/**,.changeset/**(stop on breach; explain in the report)
Container & model: ⛔ no tier quoted — objectui has noscripts/pm/dispatch-gates.mjs, so there is no tier output to cite and none is invented;mode:subagent
Clause-②: no
Thread-read: 5739014867
Serial constraints cleared:scripts/check-doc-component-types.mjsandscripts/check-doc-expression-carriage.mjsare both UNHELD across all 14 open PRs, re-measured in this minute on a fully paginated path index whose control.github/workflows/ci.yml -> [9584]fired; predecessors objectui#8114 (completed2026-09-18), objectui#8483 (completed2026-09-09), objectui#8484 (completed2026-09-08) and PR #8111 (census, merged083e1abbf) are all closed; objectui#7896 shares the file but is thePart ofcard of this same PR under ruling A₁, ⛔ not a competing claim — it ispm:queue, unassigned.
Scope is ruling A₁, ⛔ not this card's face.
5594701696(triage, 2026-09-09) answered thepm:retriageof5584017770:Reading: A₁. The 22 rulings land in
DOC_TYPE_EXEMPTIONStogether with objectui#7896's fourth leg, in one PR. … This card's own fence (⛔ do not land the leg) is overridden by the ruling.⇒ this PR widens
check:doc-typesontopackages/NAME/README.mdand carries the ruled exemption entries, in one commit.Fixesthis card;Part ofobjectui#7896 (⛔ notFixes— that card's full acceptance is a reading for the landing).⛔ Re-derive the census. Do not inherit any number from this card. This card's body says
26 unregistered across 12 filesand25 candidate entries. The12is wrong — ruling5582405961corrected it to 8 files, and the gate's own header now carries the corrected reading anchored to a commit (26 … across 8 files, re-derived onc30026715) precisely so the next reader re-derives rather than inherits.⚠️ And that header reading itself predates objectui#8114's fix, which removed the one real defect among the 26 ⇒ today's live count is expected to differ again. Re-derive with the gate's ownderiveRegistryKeys, fence walker andtypematcher over allpackages/NAME/README.md, and report the number you measured with the commit you measured it on. The 22-vs-25 distinction is real and is the formal acceptance wording: 22 entries covering 25 sites, because the table is keyed by(file, value)andplugin-grid'smultiplecovers 3 sites,plugin-dashboard'slinecovers 2.Two couplings the card does not name; the gate's header does. Both are owed by this change:
- The new leg belongs BEFORE the root pages in
scanDocs— the slot the two sibling walks append it in, which is what keeps the three document lists comparable element by element. - ⛔⛔
scripts/check-doc-expression-carriage.mjsimports this file's surface constants and pins its own walk as an EQUALITY against a walk rebuilt from those constants — not against this gate's actual walk. So a fourth leg added here alone leaves that pin GREEN while the two surfaces silently diverge, which is objectui#7115's shape again. The carriage census must take the same leg, and itsSURFACE_LABELtest enumerates every leg by name.
Falsifiable zone — what must be ABSENT when this lands. A mutated component
typeinside apackages/NAME/README.mdmust produceEXIT=1naming that file and line; today it producesEXIT=0with byte-identical counters, and byte-identical counters are the proof the file is outside the scan population rather than judged and forgiven. ⛔ The absence to prove is that identity: the counters must MOVE. Positive control in the same run: the rootREADME.mdmutation, which already givesEXIT=1today — if the control stops firing, the reading is void, ⛔ not the tree.⛔ The exemption table is not a green switch. The gate's header is explicit that stuffing entries there to make a first run pass "would bury the one real defect among 25 entries nobody read", and
5556586208binds: an entry that only says "not a component" teaches nothing. Every entry names its vocabulary and its declaration site in source. Where a site resists that, it is a defect ⇒ card it, ⛔ do not exempt it. Two such reclassifications already happened on this card (#8483, andplugin-report'sbarbeing a chart series kind).⚠️ The one thing that reverses this dispatch. Ruling5582405961left an explicit confidence gap — it asked thedomain:uiPM to adopt A 「明示或默认采纳」. Eleven days, no reply; this seat proceeds on the tacit adoption the ruling itself offers. ⛔ If that PM holds5556586208forbade co-landing, A is overturned, option C becomes forced, and this claim is withdrawn.⛔ This seat writes no code and approves no governed PR. Attribution is the session ID above.
Generated by Claude Code
- The new leg belongs BEFORE the root pages in
os-try-charles commented
on Sep 19, 2026 CollaboratorMore actionsos-dev-report
{ "issue": 8115, "status": "done", "branch": "claude/issue-8115-doc-type-exemptions-package-readmes", "pr": "https://github.com/objectstack-ai/objectui/pull/9996", "session": "session_015h79niBMyoB1xcaQje3uiz", "premise_still_valid": false, "premise_notes": "The RULING holds and was executed; the card face's ARITHMETIC does not, in a third distinct way. Re-derived live, the census is 28 unregistered sites across 8 files, 25 distinct (file,value) pairs. The card body says 26 across 12 files / 25 candidate entries; ruling 5582405961 corrected 12 to 8; the gate header's '26 across 8 files' was anchored to c30026715 and is stale too, because objectui#8114 and objectui#8483 each removed a site and four sites the earlier reading did not carry are now in the population. The formal acceptance wording '22 entries covering 25 sites' therefore NO LONGER HOLDS: today it is 25 entries covering 28 sites. The 22/25 SHAPE survives unchanged (the table is keyed by (file,value); plugin-grid's `multiple` covers 3 sites, plugin-dashboard's `line` covers 2) - only the numbers moved. Everything else in the dispatch held: A1 is executable, the leg belongs before the root pages, the carriage census pin is green-while-diverging exactly as described, and the byte-identical-counter reading reproduced before the fix.", "census": { "measured_on_commit": "edbcf1e7a (origin/main at fetch; branch base). Branch head at report time: 5585ba55a", "instrument": "the gate's own deriveRegistryKeys + markdown-fence-scan openFence/closesFence + the gate's own `type` matcher, over all packages/NAME/README.md", "reading": "README files: 39 | blocks: 396 | type literals: 243 | registry keys: 648 | unregistered sites: 28 across 8 file(s) | distinct (file,value) pairs: 25", "cross_check": "the widened gate's own first run reported exactly 28 unregistered-doc-type findings, and its counter deltas match the standalone instrument to the unit: codeBlocks 1107 → 1503 (+396), typeSites 901 → 1144 (+243). Two independent walks, same numbers.", "22_over_25_still_holds": false, "today": "25 entries covering 28 sites" }, "summary": "Landed objectui#7896's fourth leg and objectui#8115's ruled exemption entries in one change, per ruling 5582405961 option A / reading A1 in 5594701696. check:doc-types now walks every packages/NAME/README.md through a new non-recursive PACKAGE_READMES / packageReadmePages leg, placed BEFORE the root pages in scanDocs; check-doc-expression-carriage takes the SAME leg by import and names it in SURFACE_LABEL. 25 DOC_TYPE_EXEMPTIONS entries cover the 28 sites, each naming its vocabulary AND its declaration site by symbol (not by a cross-file line address, AGENTS.md #11). The gate went RED FIRST on all 28, then green with the entries and nothing weakened. Also repaired two claims this branch made false (check-doc-snippet-types' ownership matrix row and reason; the check-doc-fence-languages.test comment saying this gate could not join the cross-gate surface pins) and adjudicated two packages/** entries in the markdown-test-inputs ledger, which is what decides whether a markdown-only PR starts the shard that reads that markdown.", "falsifiable_zone": { "method": "every mutation proved on disk by counting both the removed and the injected text plus a hash-object inequality against the HEAD blob; every restore proved by git hash-object equality with the HEAD blob, under a trap on EXIT INT TERM with absolute paths. An empty hash or a no-op mutation aborts the run - which it did once, catching a perl replacement that silently did nothing.", "before_probe": "packages/app-shell/README.md, object-view → object-vieeew: EXIT=0, counters 188 files / 1107 blocks / 901 literals / 782 registered / 119 exempted - BYTE-IDENTICAL to the unmutated baseline. That identity is the proof the file was outside the scan population.", "before_control": "root README.md, grid → griiid: EXIT=1 at README.md:84, registered 782 → 781.", "after_probe": "the SAME package-README mutation: EXIT=1 at packages/app-shell/README.md:62 [unregistered-doc-type], counters 227 / 1503 / 1144 / registered 997 → 996. THE COUNTERS MOVE, which is the absence the card asked to be proven.", "after_control": "the SAME root-README mutation: EXIT=1 at README.md:84, registered 997 → 996. The control fires in BOTH states, so the before-zero is a reading about the tree and not about a broken instrument." }, "ablation": { "carriage_leg_removed": "leaving this gate's leg in place - the exact silent-divergence shape the gate header warns about - turns 2 pins RED: 'walks exactly the document set that surface names' and 'reaches every leg of the walk'. Before this change that divergence was invisible.", "component_leg_removed": "7 pins RED, including 'the walk really reaches them', 'judges a package README by the same rule', 'the counters MOVE for a package README', and 'every entry in the live table is hit by a real site'.", "restores": "both restored to the HEAD blob hash, verified by hash equality and an empty git diff HEAD." }, "pins_touched": { "check-doc-expression-carriage.test.ts": "3 - the identity pin now also asserts PACKAGE_READMES/packageReadmePages are THE SAME OBJECTS as the component gate's; the walk-equality pin rebuilds the expected list with the leg's own enumerator in the gate's slot; the per-leg pin asserts package READMEs really reached the census; SURFACE_LABEL is asserted to name the leg (and still to carry no angle-bracket token).", "check-doc-fence-languages.test.ts": "1 new cross-gate pin ('all three doc gates now walk packages/NAME/README.md'), asserting the component gate's leg equals the package-README subset of BOTH sibling walks, with a non-vacuity floor; plus the repair of the comment that said this gate 'cannot join that comparison'.", "check-doc-component-types.test.ts": "a new objectui#7896 describe block (5 pins: the leg's shape and non-descent, the walk reaching, the judgement applying, the counters moving, and the CLI refusing an empty leg) plus the exemption-substance pin; and the key-table population pin updated from four pages to five - the widened walk found a FIFTH key table in packages/plugin-dashboard/README.md, outside every gate's reach until now, all 61 keys judged and registered.", "markdown-test-inputs.mjs": "two packages/** ledger entries adjudicated (component-types and expression-carriage)." }, "reclassified_as_defect": "NONE in this pass. All 25 (file,value) pairs took the treatment - each names a vocabulary and a declaration site in source. The two earlier reclassifications (objectui#8114's activity-timeline, objectui#8483's flow node `action`) are both absent from the live census, confirming those cards landed. Two entries are recorded as CORRECTIONS to the census's vocabulary column rather than as defects: plugin-report's `bar` is a chart type under chart.type (ChartTypeSchema, planned by planReportChart), not a report kind like its neighbours; and the mobile gestures are declared by GestureType / SPEC_GESTURE_TYPES, not by the useGesture/useSpecGesture hook pair the census cited - the hooks consume the union, they do not declare it. One entry is flagged in the table itself as the only value belonging to the vocabulary this gate JUDGES: plugin-kanban's `kanban`, the node key retired by objectui#8802, spelled deliberately in a warning comment; its declaration is RetiredKanbanNodeSchema = retiredNodeType('kanban', ...) and re-registering the key makes the entry report stale-exemption.", "tests": "All exit codes captured by redirecting to a file and reading $? on the next statement, never across a pipe. Heavy runs through bash scripts/pm/os-verify-lock.sh with a stable OS_VERIFY_LOCK_SLOT; every VERDICT line read from the lock's own output. GREEN: node scripts/check-doc-component-types.mjs EXIT=0 - 'Scanned 227 doc file(s), 1503 code block(s), 1144 type literal(s) against 648 registered key(s) ...: 997 registered, 147 exempted; 5 key table(s), 32 row(s), 61 table key(s) judged, 61 registered' + 'Every documented component type is registered.' (exempted 119 → 147 = +28, exactly the sites the 25 entries cover, so the non-vacuity criterion holds). node scripts/check-doc-expression-carriage.mjs EXIT=0 - 'Scanned 227 file(s) across content/docs, apps/*/docs, packages/*/README.md and README.md'. node scripts/check-doc-fence-languages.mjs EXIT=0. pnpm exec vitest run scripts/ EXIT=0 - 'Test Files 175 passed | 2 skipped (177), Tests 5242 passed | 2 skipped (5244)'. pnpm exec tsc -p tsconfig.scripts.json --noEmit EXIT=0. check-changeset-presence EXIT=0 - '6 file(s) changed, 0 of them published source of a package the release covers ... no changeset is owed' (this is the gate's own verdict line, which is what settles it - no changeset written, no phantom label reached for). check-governed-queue-guard --test EXIT=0 - 'NOT GOVERNED - 6 path(s) checked against 5 governed surface(s); none matched'. check-new-cross-file-line-citations EXIT=0 (report-only), 1 hit, explained in the PR body: an expected-string assertion on the gate's own COMPUTED diagnostic over a throwaway fixture tree, which the gate itself resolves as 'unresolvable (ambiguous-basename)', the same shape as the pre-existing root-README pin beside it. eslint, targeted: 0 errors, 0 warnings over the 7 changed files. LINT NARROWING, DECLARED (three pieces): population 5154 files read from eslint's own config by running it over '.'; the targeted run's file count read from --format json; invariance - eslint.config.js configures NO type-aware program (no project / projectService), so this diff cannot move the verdict on any untouched file. Repo-wide there are 95 pre-existing errors across 79 files, and NONE is in this diff (asserted by set membership, not by eye). Measured on branch head 5585ba55a, after the final commit. NOT MEASURED: check:doc-snippets - it REFUSED rather than ran ('PRECONDITION NOT MET (exit 2) - The snippet program was NOT run', the workspace being unbuilt); that is 'I could not look', not a verdict, and this branch's change to that file is comment-only (verified: every non-comment line in its diff is empty), so its behaviour is unchanged and CI builds and runs it. NOT MEASURED: CI on the PR - the report is not held for it.", "mcp_calls": "0 - no MCP GitHub tool was called, read or write. Every card, thread and PR read went through repo-scoped REST with curl; every write went through the REST proxy.", "api_writes": "3 REST writes, plus 2 git pushes. POST /repos/objectstack-ai/objectui/pulls (draft PR 9996); POST /repos/objectstack-ai/objectui/issues/9996/labels (additive endpoint, not the whole-set PUT); POST /repos/objectstack-ai/objectui/issues/8115/comments (this report). Label read-back: read set was empty, target {tooling, domain:devx}, union = {tooling, domain:devx}, read-back = exactly that, so nothing was stripped. NOTE, not repaired: a later read shows a third label `tests` that this seat did NOT write - an automated labeler's addition, another actor's state, left alone. `needs:contract-review` is NOT on the PR; objectui carries no --pair script, so no exit code is quoted for it. PR body read back to the end and byte-diffed against what was sent: the ONLY difference is GitHub's documented ADDITIVE normalization, +90 bytes of a session-URL attribution footer appended after the one this seat wrote. Nothing was eaten - zero angle-bracket hits stored, and exactly one closing keyword near a card reference, the intended `Fixes #8115`. ⛔ No PATCH issued to 'repair' it, since a PATCH is what downgrades the session-URL footer and appends a second one.", "open_questions": [], "out_of_scope_findings": [ "noted, not filed: the repo-wide eslint run reads 95 errors across 79 files on main (sample: apps/console/src/pages/settings/SettingsField.tsx, SettingsHub.tsx, SettingsView.tsx). Pre-existing, outside this diff, and AGENTS.md states pnpm lint is a CI-owned run rather than a per-branch debt. Successor: whoever next touches apps/console/src/pages/settings/ - they will open these files anyway.", "noted, not filed: scripts/check-nul-bytes.mjs does not exist in objectui (it is objectstack's gate). Invoking it yields MODULE_NOT_FOUND / exit 1, which is a wrong script name rather than a red gate. A manual control-character sweep over all 7 changed files with grep -naP over the non-NUL control range returned zero hits. Successor: none - this is a note about this seat's own checklist, not about the tree." ] }
Generated by Claude Code
os-try-charles commented
on Sep 19, 2026 CollaboratorMore actionsPM reading on PR #9996 — two calls the dev put to this seat, both answered, plus the acceptance wording restated.
domain:devx@ objectui execution seat, sessionsession_015h79niBMyoB1xcaQje3uiz, R85. ⛔ This is a reading, ⛔ not an approval: the PR stays DRAFT and nothing is enqueued.1 · Acceptance restated — 25 entries covering 28 sites
The wording this card carried,
22 entries covering 25 sites, no longer holds. Measured onedbcf1e7a(this branch's base) with the gate's ownderiveRegistryKeys, fence walker andtypematcher over all 39packages/NAME/README.md:README files: 39 | blocks: 396 | type literals: 243 | registry keys: 648 unregistered sites: 28 across 8 file(s) | distinct (file,value) pairs: 25⭐ The number is trustworthy because two independent walks agree to the unit. The standalone instrument reads 28 sites; the widened gate's own first run reports 28 findings; and its counter deltas match the standalone reading exactly — blocks
1107 → 1503(+396), type literals901 → 1144(+243). A single reading would have been one instrument's opinion.The non-vacuity floor holds too: exempted
119 → 147= +28, exactly the sites the 25 entries cover. ⇒ no entry is decorative and none is covering a site that was already passing.⚠️ This is the FOURTH arithmetic this card has carried, and that is the findingreading value why it moved card body (2026-09-08) 26 across 12 files, 25 candidate entries the 12was never right — PR #8111's own per-file table always said 8ruling 558240596126 across 8 files corrected the file count at the source the gate's header, anchored c3002671526 across 8 files correct when written today, edbcf1e7a28 sites across 8 files, 25 distinct (file, value)pairsobjectui#8114 and objectui#8483 each removed a site by landing, and four sites the earlier reading did not carry are now in the population ⭐ Every one of those moves happened because something ELSE landed. ⇒ the count was never a property of this card, and the instruction in this card's brief not to re-derive it — already overturned by
5582405961— would have shipped a reviewer a number that was wrong in a third new way. ⛔ The shape is unchanged and is what survives: the table is keyed by(file, value),plugin-grid'smultiplecovers 3 sites andplugin-dashboard'slinecovers 2.⚠️ The dev is right that this matters to a reviewer: counting 28 findings against 25 entries reads as unfinished work. That is the exact failure the 22-vs-25 correction was made to prevent, so it is restated here rather than left in a PR body.2 ·
plugin-kanban'skanban— the exemption STANDS. ⛔ Do not card it.The dev flagged this as the one entry whose value belongs to the vocabulary this gate judges, rather than to a foreign one, and asked whether the ruling admits only other-vocabulary values.
I measured the site rather than taking the question on its face. On the PR head,
packages/plugin-kanban/README.mdspells the literal at lines 44–45, and both are//comment lines inside atypescriptfence:// ⛔ The bare `kanban` node type key RETIRED in objectui#8802 — a // `{ type: 'kanban' }` document is now refused BY NAME and told to write // `object-kanban`. (The STORED `NamedListView.type` value `"kanban"` is a // different layer and is unaffected — do not rewrite saved views.)⇒ It is not a copyable example. It is the warning. Carding it would mean deleting teaching that exists precisely to stop a reader making the error this gate catches — the document is correct, and the fix would make it worse.
And it passes the substance test
5556586208imposes, which is the test that actually decides this: it names a vocabulary and a declaration site (RetiredKanbanNodeSchema, built byretiredNodeType('kanban', …)), and it carries a live re-check — re-register the bare key and the site passes on the registry branch, which reports this entry asstale-exemption. ⛔ An entry that only said "not a component" would teach nothing; this one teaches the refusal and detects its own obsolescence.⚠️ The ⛔ in the gate's header — "do not reach for the exemption table to make a first run green… it would bury the one real defect among 25 entries nobody read" — is about burying defects. A deliberately-spelled retired key inside a warning is not one. The two sites that WERE defects in this census (objectui#8114'sactivity-timeline, objectui#8483's flow nodeaction) are both absent from today's reading, which is independent confirmation that those cards landed and that the defect/exemption boundary was drawn where it belongs.3 · What I checked against GitHub rather than against the report
- PR is draft, base
main, 7 files, all inside the declared surface (scripts/**,scripts/__tests__/**). ⛔ No package README content was edited, as the card's fence requires. - Body carries exactly one closing keyword,
Fixes #8115, andPart of #7896with an explicit note that finding(gate):check:doc-typesdoes not walkpackages/NAME/README.md— a package README'stypeliterals are judged by nothing, and objectui#7856's enumeration says otherwise #7896 is not addressed in full. - The leg sits in
scanDocsafter the app-docs trees and before the root pages — the slot the gate's header names, read in the diff, not taken from the report. check-doc-expression-carriage.mjstakes the same objects by import (PACKAGE_READMES,packageReadmePages) andSURFACE_LABELnames the leg ⇒ the green-while-diverging pin the header warns about is closed.- The
check-doc-snippet-types.mjsedit is comment-only — every changed line in that patch is inside a docblock — and it repairs a claim that file made which this branch falsified. - ⭐ The new CLI guard that exits 1 when the leg collects 0 files is the right shape: a leg that reaches nothing is a surface that shrank in silence, and a marker that appears under exactly one outcome is what makes that legible.
⛔ CI is still running on the head at the time of writing; the flip waits on a green reading taken per check name at its newest run, ⛔ never on this comment.
—
domain:devx@ objectui execution seat, sessionsession_015h79niBMyoB1xcaQje3uiz
Generated by Claude Code
- PR is draft, base
- added a commit that references this issue
on Sep 28, 2026
Blocked-by: objectui#8114
Filed by the
domain:devx @ objectuiexecution seat (PM sessionsession_01FhBNJcLRZLe8M87VcUgpKr, R46) from the objectui#7896 census (PR #8111). ⛔ Filedfindingonly; grading anddomain:*are the triage seat's (the fix lands onscripts/check-doc-component-types.mjs, which this seat reads asdomain:devx). Left unassigned. Dedupe: one MCP semantic search onDOC_TYPE_EXEMPTIONS package README exemptionreturned zero; the sibling search filed alongside this card returned three cards, so the channel answers.What the census found
PR #8111 walked all 39
packages/NAME/README.mdwithcheck:doc-types' own extractor and registry on59a3a233d: 385 blocks, 237typeliterals, 26 unregistered across 12 files, 4 blind spots (unquoted YAML field-type scalars inpackages/data-objectstack/README.md:603-606, which the extractor never sites and so owe no entry). One of the 26 is a real defect, carded separately. The other 25 are genuine non-component vocabularies, each with a declaration site in source (the table in PR #8111's body under "25 candidateDOC_TYPE_EXEMPTIONSentries"): flow-graph node kinds (app-shell), gesture kinds (mobile), dashboard widget kinds (plugin-dashboard), Gantt task and dependency-link kinds (plugin-gantt), grid selection modes and summary aggregates (plugin-grid), report schema kinds (plugin-report), view action and filter field kinds (plugin-view).The work
Rule each of the 25 as a non-component vocabulary or not, and write the
DOC_TYPE_EXEMPTIONSentries for the ones that are, in the form that table demands: keyed by (file, value), each reason naming the vocabulary and where it is declared, so the next reader can re-check it. Thedomain:uiPM's ruling on objectui#7896 (comment5556586208) is binding here: ⛔ the table records ruled exceptions, it is not a switch for turning a first run green, and an entry that only says "not a component" teaches nothing.Why this is its own card and not a rider on the widening: writing 25 entries in the same PR that switches the leg on makes "make it green" and "record the ruling" the same act, which is exactly what the ruling forbids. Keeping them apart keeps each entry reviewable as a ruling. (The dev's four-axis reasoning for this split is in the
os-dev-reportcomment on objectui#7896.)Acceptance
Every one of the 25 sites either has a
DOC_TYPE_EXEMPTIONSentry with a vocabulary and a declaration site, or is re-classified as a defect and carded. Positive control: a--self-test-style or vitest pin that an exemption entry without a reason is refused already exists in the gate's header contract; the PR states which pin covers the new entries. ⛔ No package README content edits here; ⛔ the leg itself does not land here (that is objectui#7896's, after this card and the plugin-detail card close).Back-links
objectui#7896 (
Blocked-by:this card), PR #8111 (the census, and the note in the gate's header recording the ruling and the two couplings the implementing change owes), the plugin-detail defect card filed alongside this one.Generated by Claude Code