Repository navigation
fix(plugin-dashboard,cli): converge the bare dashboard key on plugin-dashboard, retire view:dashboard with a by-name tombstone - #9803
Conversation
…in-dashboard`
The console declares its lazy stubs for bare `dashboard` under
`plugin-dashboard` (twice), while this package registered the renderer as
`view:dashboard`. Neither site passed `skipFallback`, so both claimed the bare
key and `registerLazy` has no collision check, so nothing warned.
Reproduced against a real `Registry` before acting: after the package loads,
`hasLazy('dashboard', 'plugin-dashboard')` reads `true` and
`get('dashboard', 'plugin-dashboard')` reads `undefined` — the stub is never
cleared, because `register()` clears the stub of the type it registers and that
type was `view:dashboard`. The generated CLI whitelist advertised that spelling
as renderable.
The renderer now registers as `plugin-dashboard:dashboard`, so all three
claimants of the bare key name one full type. `view:dashboard` is retired with a
tombstone that refuses by name and names its replacement, registered with
`skipFallback: true`; its spelling is withheld from the derived key universe by
declaration, so `objectui check` reports it rather than blessing it. The
objectui#9264 shrink-only collision ledger loses its only row.
Ownership is pinned in both registration orders, with `hasLazy` false after the
load and the refusal asserted together with the tombstone's own text.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012EpHzwH4wTy5sd7ibkD2yq
…board` `dashboardAuthoredInputs.test.tsx` looked the `inputs` list up under the `view` namespace. That key now answers the retirement tombstone, which publishes no `inputs` at all, so the "publishes neither" half would have read an empty list and passed while measuring nothing — caught by its own `label` / `widgets` controls. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012EpHzwH4wTy5sd7ibkD2yq
|
changeset-claim-re-read
|
✅ Console Performance Budget
The eager closure is every chunk the entry reaches through static imports — what the browser fetches and parses before the app renders. The entry chunk on its own is a small fraction of it. 📦 Bundle Size Report
Size Limits
|
…red spelling `check-doc-component-types.mjs`'s header ran its namespace-blindness example over the literal pair `view:dashboard` / `plugin-dashboard:dashboard` and told the reader to flip `namespace: 'view'` on the dashboard registration. This branch made that false: there is no `namespace: 'view'` on that registration any more. The example is kept and re-pointed, with a note saying what moved. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012EpHzwH4wTy5sd7ibkD2yq
✅ Console Performance Budget
The eager closure is every chunk the entry reaches through static imports — what the browser fetches and parses before the app renders. The entry chunk on its own is a small fraction of it. 📦 Bundle Size Report
Size Limits
|
`no-console` is not enabled for this package, so the directive was never suppressing anything and `reportUnusedDisableDirectives` failed the package's own `eslint .` as an error. I did not see it locally because I verified with `eslint . --no-inline-config`, which makes eslint skip inline configuration comments entirely — an unused directive cannot be reported when directives are not read at all. That flag belongs to the sibling repository; this one's lint script takes no flags. Re-verified with `pnpm --filter @object-ui/plugin-dashboard lint`: exit 0, 0 errors. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012EpHzwH4wTy5sd7ibkD2yq
✅ Console Performance Budget
The eager closure is every chunk the entry reaches through static imports — what the browser fetches and parses before the app renders. The entry chunk on its own is a small fraction of it. 📦 Bundle Size Report
Size Limits
|
Clause-② review — IN-SEAT, at the default tier · ⛔ this is NOT an at-tier record
⛔ Read the label before the verdict. This is the lane's own default-tier review plus the gates. It is ⛔ not a Why this route, and the authority for itThis card's own maintainer-approved ruling says no at-tier review is owed here. Comment
⛔ ① Derived judgments1. The published full name moves — 2. The refusal is BY NAME, with the migration in its own text. A loop registers each retired spelling with 3. 4. The generated CLI whitelist loses exactly one line. ⛔ Nothing narrows beyond what the ruling authorised, and nothing widens except item 3. ② Semver level
③ Boundary flags
VERDICT: PASS — at the default tier, in-seat, on the authority named at the top. Both Generated by Claude Code |
⛔ CORRECTION — I cleared the carriers without a legible record. Re-hung, and this PR is parked.
What happenedI performed the clause-② review in-seat at the default tier — on the authority of this card's own maintainer-approved ruling (「
My comment is prose. It has no ⛔ And the remedy the gate names is not reachable at the default tierThis is the part that matters beyond this PR, so I am stating it as a measurement rather than a complaint.
⇒ the record format requires the value ⛔ I will not write Where that leaves this PRParked, outside the queue, carriers hung — which
What the ruling needs to settleobjectstack#18885 already holds 「who reviews a clause-② card in a non-spec lane」. This adds a second, sharper instance, and I am carrying it there:
⭐ The findings of the review I did perform are on the record above and do not depend on the label: the published full name moves as ruled, the refusal is by name with the migration in its own text, Generated by Claude Code |
Park update — the deadlock was ruled at 2026-09-18T08:10Z, and I did not read the ruling before writing the two comments above
What the ruling says, and what it does to this PRTwo limbs, both against the premise of the review I performed:
Control on this PR, against limb 2. Files changed: 15. Counting rule — path prefix, on the PR's own file list at head Zero on all three. This PR's whole diff sits in Why it is still parked, and what un-parks itThe ruling's execution段 is explicit: 「⛔ No carrier is stripped by the director; after PR #18903 lands, each lane seat re-reads the So both carriers stay hung and this PR stays parked. ⛔ I am not stripping them on the strength of a text that is still a draft; anticipating an unlanded rule is the same error as the one this comment opens by admitting. What changed is the park's reason, and it is worth stating plainly because it changes who acts next:
⛔ Still not spending the contract-review tier on this PR. Under limb 1 there is nothing here for it to do. Reading time: 2026-09-18T12:24Z Generated by Claude Code |
|
Clause-② contract review ADOPTED — the record follows in the next comment, verbatim. Why this seat, on a
|
| transcript | assistant records | served model |
|---|---|---|
| the reviewer | 96 | 96 / 96 claude-fable-5-1 — the CONTRACT_REVIEW_TIER constant, zero fallback |
| ⭐ FIRING CONTROL — this round's dev on objectui#8071 | 130 | 130 / 130 claude-opus-5 |
| ⭐ FIRING CONTROL — this round's dev on objectui#9870 | 105 | 105 / 105 claude-opus-5 |
| ⭐ FIRING CONTROL — this round's dev on objectui#9875 | 104 | 104 / 104 claude-opus-5 |
⇒ three independent subagents in the same session read the other value, so the field discriminates and the at-tier reading is a reading, ⛔ not a constant the harness prints regardless.
claude-opus-5, which is ⛔ not at tier — so ⛔ it may not judge this contract itself, and it has not. Its only acts are: commission, verify the tier, and adopt verbatim or void entirely. ⭐ There is no third option, and ⛔ the record is never rewritten, trimmed or polished — including the parts that read as criticism of the diff.
⚠️ What the record itself declares unmeasured
The reviewer names its own gaps rather than letting them pass as green: vitest, the CLI check run, the live-Registry reproduction, the lint split, the html-tier manifest, and behaviour after merging today's main — all ⛔ NOT measured by it, because the shared checkout carries no node_modules and it correctly refused to install into a checkout other agents are using. It reconstructed the head tree in scratch and blob-checked all six changed files against the diff's own index lines before running the three node-only gates. ⇒ read its verdict as resting on the gates it names, ⛔ not on a full suite.
Generated by Claude Code
Contract reviewServed-tier: Instrument note, first. The shared checkout's copy of the branch stops at ① Derived judgments
Letter 1, clause by clause: package registers PR-body claims, verified at head: whitelist loses one line ✓; ledger empty ✓; gate figures ✓ (measured identically); leg 1 ② Semver level
③ Boundary flags
Owed before merge, none verdict-flipping: amend the PR body (head sha, floor count 5, "published" not "internal"), add the four exports and the Implemented-by: VERDICT: PASS Generated by Claude Code |
|
The authorisation, quoted verbatimTwo instructions, in order, both from the maintainer in session:
⛔ Nothing else about card objectui#9533 moves. It keeps
|
Exactly the three items the at-tier contract review listed as owed before merge on this PR, nothing wider. 1. The INDIRECT_REGISTRATIONS entry for RETIRED_DASHBOARD_NODE_TYPES claimed that dropping its `excluded` line re-admits `view:dashboard` to the derived universe, that KNOWN_SCHEMA_TYPES regains it, and that a document teaching it turns green again. Re-measured on this head, dropping that line makes the entry report `stale-indirect-registration` instead: without the exclusion the derivation has to read the collection literal in the site file, and RETIRED_DASHBOARD_NODE_TYPES is IMPORTED there from `./retired-node-types`, so it resolves to no literal keys at all. check-doc-component-types.mjs and regenerate-known-schema-types.mjs --check both exit non-zero and write nothing; the spelling does not re-enter, and a document teaching it stays red for a different reason. The sentence now says that, and points at the two commands that re-derive it. 2. The changeset body now declares what it was missing: the four symbols this branch adds to the package entry's exports["."] (RETIRED_DASHBOARD_NODE_TYPES, RetiredDashboardNodeTombstone, reportRetiredDashboardNodeType, resetRetiredDashboardNodeTypeReports) and the data-obj-type value change on a dashboard grid. The semver LEVEL does not move -- `minor` was already correct; only the declaration was incomplete. Frontmatter untouched. The third owed item, the PR body's stale head reference / export floor count / "internal surface" wording, is a body edit rather than a commit. Deliberately NOT folded in: the index.tsx "LAST" rationale comment the review measured as going stale once objectui#9838 / objectui#9851 are in the base. The review put it under boundary flags and kept it off the owed list. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UanLVj6xvbS6puBCewLr8L
✅ Console Performance Budget
The eager closure is every chunk the entry reaches through static imports — what the browser fetches and parses before the app renders. The entry chunk on its own is a small fraction of it. 📦 Bundle Size Report
Size Limits
|
|
os-dev-report { Generated by Claude Code |
|
Clause-② contract review RE-RUN at the new head and ADOPTED — the record follows in the next comment, verbatim. Why a second recordThe prior record (comment ⭐ That is the head-binding doing its job, ⛔ not a formality: a record is a statement about a tree, and the tree moved. ⛔ This seat did not judge whether the delta preserved the verdict. That judgement is itself a clause-② judgement, and this seat serves The tier reading — from the subagent's OWN transcript, ⛔ never
|
| transcript | assistant records | served model |
|---|---|---|
| this re-review | 59 | 59 / 59 claude-fable-5-1 — the CONTRACT_REVIEW_TIER constant, zero fallback |
| ⭐ FIRING CONTROL — the dev that produced this very delta | 99 | 99 / 99 claude-opus-5 |
| the prior at-tier record, for comparison | 96 | 96 / 96 claude-fable-5-1 |
⇒ the control reads the other value, so the field discriminates and the at-tier reading is a reading. ⭐ Note what the control is here: the author of the diff under review — different tier, different transcript, measurably not the same agent.
⚠️ ⚠️ The record escalates something to the maintainer, and this seat is NOT ruling on it
Under ③ the reviewer names, unprompted, that commit 96b6ee2820's Claude-Session: trailer is this same session — the session that commissioned both records and adopts them. Its words: 「the isolation is the subagent's … not the session's」, and it asks whether a record whose Reviewed-by session equals the reviewed commit's Claude-Session satisfies the independence pair.
⛔ This seat does not answer that, and ⛔ it does not answer it by landing. Three things are true and are stated rather than blended:
- Mechanically the pair is satisfied as designed.
references/contract-review.mdreads 「Implemented-by:…mode:subagent记分支」 and 「mode:subagent席内审是设计」 — under subagent mode the implementer is recorded as a branch, so the SELF-REVIEW condition (both fields naming the same session) cannot arise by construction, and in-seat review is the ruled route, selected by the maintainer in session. ⚠️ The reviewer's point is sharper than the mechanism, and it is right: for this delta one session commissioned the dev, commissioned the review, and adopts it. What is isolated is the reviewing subagent, ⛔ not the session.- ⭐ It is therefore a question about the ROUTE, ⛔ not about this pull request — it holds identically for every card this seat has landed through the ruled route. ⇒ singling this PR out would be arbitrary, and ⛔ withholding it would not answer the question either.
⇒ Raised to the maintainer as a standing-route question, quoted above so it is not discovered later. ⛔ Not filed as a card: this seat's REST issue-creation channel is currently refused by the session's write classifier, and ⛔ routing it through another agent would launder that refusal.
⚠️ One flag the record names and this seat is deliberately NOT acting on
The body sentence 「Registry.registerLazy has no collision check」 is true of the tree under review and stale on today's main (objectui#9838 landed since). The reviewer classifies it 「Stale on main, true of this tree」, keeps it off the owed list — as the prior record did — and observes that a one-clause repair is cheap.
⛔ This seat is not taking it, and the reason is the one this round already paid for: the body was just verified by this record, and editing verified content after the record without a further review is exactly how a record stops describing what it names. ⇒ recorded here instead, so the successor sees it and the history shows the choice.
What happens next, and its red lines
Both needs:contract-review carriers are stripped in one act, then ready → enqueue with squash → follow to MERGED.
- ⛔ No approval review of any kind — this seat's write identity resolves to
hotlong, one of the twoGOVERNED_APPROVERS. - ⛔ Never merged directly: this repository answers
PUT /pulls/N/mergewith 405Changes must be made through the merge queue. ⚠️ The record's own CI reading was taken with 4Testshards still in progress. ⛔ Never enqueue while a required check runs — the enqueue below is gated on a fresh complete enumeration, ⛔ not on the record's snapshot.- Landing is verified on
origin/mainby symbol with a lit control, ⛔ never from themergedfield.
Generated by Claude Code
Contract reviewServed-tier: Instrument note, first. The shared checkout now holds all three objects ( The delta ① Derived judgments
PR body as it now stands — verified: floor 5 at both heads ✓; merge-base Prior-record judgments re-verified at head: 1, 3, 4, 5, 6, 8 and the gate figures. Carried without re-running: 2, 7, 9, the ablation leg counts, and every vitest-backed claim. ② Semver level
③ Boundary flags
Implemented-by: VERDICT: PASS Generated by Claude Code |
|
Clause-② gate CLEARED — both carriers stripped in this act.
⛔ ⛔ What clearing the gate does NOT mean
Route from here: ready → enqueue with squash → follow to MERGED via the queue, ⛔ never a direct merge (this repository answers Generated by Claude Code |
|
LANDED — and this seat's follow-through ends here. Merged through the queue; squash on Verified on
|
| probe | reading |
|---|---|
SUBJECT — namespace: 'plugin-dashboard' in packages/plugin-dashboard/src/index.tsx |
8 (the base carried 7 — the one-token move the ruling asked for) |
SUBJECT — the tombstone module retired-node-types |
present |
SUBJECT — 'view:dashboard' in packages/cli/src/utils/known-schema-types.ts |
empty cell |
⭐ LIT CONTROL — 'plugin-dashboard:dashboard' in the same whitelist |
1 |
⭐ LIT CONTROL — 'view:chart' in the same whitelist |
1 |
view:dashboard row is deliberately not written as a 0: grep -c with no match exits non-zero and returns nothing. ⭐ The two lit controls are what make that empty cell a reading — the matcher still finds both the converged key and an unrelated namespaced key in the same file, so the whitelist genuinely lost the retired spelling.
The maintainer instruction this discharges, quoted verbatim
- 「9803 帮我契约复审」 → the at-tier record at comment
5731438175(head588e45950f). - 「9803 你负责跟进到合并」 → the owed repairs, the re-review at comment
5731997344(head96b6ee2820), the carrier clear, the enqueue, and this landing record.
⭐ Why there are two records, and why the second was not optional: closing the first record's owed list moved the head, and check-clause2-carriers --pair 9803 then reported no review of record at all. A record is a statement about a tree, and the tree had moved. main's permanent history, so a sentence added to discharge a finding can itself become a durable false claim. ⛔ And judging whether the delta preserved the verdict is itself a clause-② judgement, which this seat (serving below CONTRACT_REVIEW_TIER) ⛔ may not make.
⛔ What this seat did NOT do
- ⛔ No approval review of any kind, at any point — this seat's write identity resolves to
hotlong, one of the twoGOVERNED_APPROVERS. - ⛔ Card objectui#9533 was not re-graded, re-routed or closed by this seat. It is
domain:ui, assigned toos-justin; whateverFixes #9533did on merge is the platform's act, ⛔ not this seat's. Its lane owns everything after this. - ⛔ The
index.tsx「LAST」 rationale comment — which both records measured as going stale once objectui#9838 / objectui#9851 are in the base — was left untouched, because both records deliberately kept it off the owed list. - ⛔ The stale body clause 「
Registry.registerLazyhas no collision check」 was not repaired, and that was a decision rather than an oversight: it is true of the tree under review, both records kept it off the owed list, and the body had just been verified by the second record — editing verified content afterwards without a further review is precisely how a record stops describing what it names.
⚠️ ⚠️ Two things the second record escalated, both still OPEN and neither answered by this landing
- ⭐⭐ The self-review chain. Commit
96b6ee2820'sClaude-Session:trailer is this same session — the one that commissioned both records and adopts them. Mechanically the independence pair is satisfied as designed (Implemented-by:records a branch undermode:subagent, and 「mode:subagent席内审是设计」), but the reviewer's sharper reading stands: the isolation is the subagent's, ⛔ not the session's. ⇒ this is a question about the ROUTE, ⛔ not about this pull request — it holds identically for every card landed through it. Raised to the maintainer; ⛔ not answered by landing, and ⛔ not answerable by this seat. - The sibling born-false sentence.
RETIRED_FIELD_TYPES' entry inscripts/check-doc-component-types.mjscarries the identical false claim this PR just corrected forRETIRED_DASHBOARD_NODE_TYPES— measured by the dev with the same ablation. ⛔ Out of scope here by instruction; owed its own card, which this seat ⛔ cannot file (REST issue creation refused by the session's write classifier, and ⛔ routing it through another agent would launder that refusal). Successor named by the record: whoever settles objectui#9717, which now owns two entries.
Generated by Claude Code
Fixes #9533
Ruled shape, executed: director seat summon #24, batch #152 item 5, letter 1, maintainer 「其他同意」 2026-09-18 (issue comment 5724939774). Routes 2 and 3 were rejected on the record and are not reopened here.
The reproduction came first, and it confirmed the card
The card and the ruling both required the never-cleared stub to be reproduced against a real
Registrybefore acting, because it had been read offRegistry.register's clearing lines rather than executed. It was, on a freshRegistryfed this package's REAL declared metadata read back out of the registry:Both consequences reproduce. The stub is never cleared (
register()clears the stub of the type IT registers, and that type wasview:dashboard), the whitelisted key resolves toundefinedforever, and the bare key's declared namespace flips mid-sequence. The zero collision warnings are the triage seat's point measured: this shape came in throughregisterLazy, which takes the same fallback branch with no collision check at all.Nothing falsified the ruling.
What letter 1 required, and where each clause landed
plugin-dashboard:dashboard; theviewnamespace registration goespackages/plugin-dashboard/src/index.tsxview:dashboardrefused BY NAME with a tombstone pointing atplugin-dashboard:dashboardpackages/plugin-dashboard/src/retired-node-types.tsx, registered last withskipFallback: truecontent/docs/plugins/plugin-dashboard.mdxrow regeneratespackages/cli/src/utils/known-schema-types.ts, one line:view:dashboardleavescheck-registry-bare-name-collisions.mjs's row for this pair goeshasLazyfalse after loadpackages/plugin-dashboard/src/__tests__/dashboardBareKeyOwnership.test.tsxThe ledger row was deleted, not reworded — the gate now prints
0 contested; ledger holds 0.Why the tombstone spelling is withheld from the key universe
A literal
register('dashboard', Tombstone, { namespace: 'view' })would have putview:dashboardstraight back intoderiveRegistryKeys' universe and therefore back intoKNOWN_SCHEMA_TYPES— and objectui#8760 graded exactly that as the wrong side of the line: "an unknown key is refused loudly at authoring time; a registered-but-unfulfilled key passes every check, is taught by the documentation, and fails only at render in front of a user." Blessing the retired spelling in the CLI would have rebuilt the defect this card removes, one spelling over.So the tombstone registrar is collection-keyed and declared
excludedinINDIRECT_REGISTRATIONS, the same dispositionRETIRED_FIELD_TYPES' tombstones already take (objectui#9717 holds the open question; both are answered the same way so they cannot drift apart). Net effect: the runtime points the author at the replacement, andobjectui checknames the retired spelling instead of blessing it.The pin, and the reverse verification that proves it can fail
Both ablation legs ran against the COMMITTED fix, each with an on-disk mutation proof and a restore proven by
git diff HEADbeing empty:view(occurrences of the new spelling 8 to 7, blobcf38965toee4c498): the pin goes 7 of 10 red;check:registry-bare-namesexits 1 and reprints the card's own finding verbatim, naming all three claimants;regenerate-known-schema-types.mjs --checkexits 1.cf38965to36f5964): 5 of 10 red, includingview:dashboardresolves to the TOMBSTONE, not to the renderer and renders the tombstone, carrying the migration text the table declares.Leg 2 exists because the refusal is the assertion most easily faked. The pin asserts the refusal and the tombstone's own text (read from the table the component reads, never restated), the
role="alert"element, thedata-retired-node-typeattribute and theconsole.errorcarrying the same string — plus a control that baredashboardandplugin-dashboard:dashboardstill paint the real grid, so "nothing rendered" cannot pass for a refusal.Clause-②: yes — and what the mechanical floor does NOT prove
Declared by the ruling: the published full name moves. The shape is unusual and worth stating so it does not confuse a reviewer's measurement — the accept set narrows (an authored
view:dashboardstops resolving) and the clause isyesanyway, on the published-name move rather than on a widened surface.⇒ the⚠️ An earlier revision of this paragraph said 2, and named only two of the symbols — that was wrong; the at-tier contract review measured the floor at 5 off the head diff, and re-measuring it here reproduces 5 (same number at
^\+exportfloor is useless here in both directions. Counted against this branch's merge-base42234b1a: it adds 5^\+exportlines — four in the newretired-node-types.tsx(RETIRED_DASHBOARD_NODE_TYPES,reportRetiredDashboardNodeType,resetRetiredDashboardNodeTypeReports,RetiredDashboardNodeTombstone) and oneexport { … } from './retired-node-types'block inindex.tsx.588e45950fand at head). That count proves neither half of the clause. It does not proveyes, because those five lines are a NEW surface rather than the moved published name the clause is actually about — and to be exact about what kind of surface: the four symbols are published, not internal.src/index.tsxis the file this package'sexports["."]publishes, so anything that resolves@object-ui/plugin-dashboardcan import them, and dropping one later is a breaking change like any other export. (They are declared in the changeset as of96b6ee2820.) It could not have provennoeither, because the thing that moved — the stringplugin-dashboard:dashboardreplacingview:dashboardinside aregister(...)call — adds no export line at all and would score 0 on a floor that only counts them. The clause rests on the registry key, which is a runtime string, and the instrument that re-derives it isdashboardBareKeyOwnership.test.tsxplus the regenerated whitelist, not a diff-line count.Changeset marked
minorper AGENTS.md's 版本号策略 (objectui's own breaking changes takeminor, with the breaking semantics written out), naming the tombstone under 「Breaking for authored metadata」.Verification
Ordinary-direction result throughout; nothing reversed or fanned out.
pnpm exec vitest run packages/plugin-dashboard/ packages/cli/ packages/app-shell/src/__tests__/widget-dom-leak-sweep.test.tsxplus the four affectedscripts/__tests__/files — 143 files, 1806 tests, all passing after the one collateral repair below (first run caught it: 1 failed / 1805 passed).pnpm --filter @object-ui/plugin-dashboard type-check,pnpm --filter @object-ui/cli type-check,tsc -p tsconfig.test.jsonin@object-ui/app-shell— all exit 0, each on a tree whose dependency closure was built first (an unbuilt closure answersTS2307for every workspace import, which is a missing prerequisite and not a verdict).check:registry-bare-names,check:doc-types,check:side-effects-array,check:changeset-claims,check:changeset-presence,check:changeset-no-major,check:control-bytes,check:new-line-citations,check:entry-guard,check:prompt-keys,check:doc-fences,check:doc-example-ids,check:component-surface-parity,check:test-path-roots,check:unreferenced-sources,check:pending-changeset-literals.Collateral repair, in scope because this branch caused it.
dashboardAuthoredInputs.test.tsxlooked theinputslist up under theviewnamespace. That key now answers the tombstone, which publishes noinputsat all — so the objectui#5742 "publishes neither" half would have read an empty list and passed while measuring nothing. Its ownlabel/widgetscontrols caught it; the row moved toplugin-dashboardrather than being dropped.Other call sites updated to the new full type:
DashboardRenderer.domProps.test.tsx(the canary node and itsdata-obj-typeassertion),widget-dom-leak-sweep.test.tsx(the sweep target moved under theplugin-dashboard:prefix case; itsOWNED_VIEW_ALIASESentry is now empty, with the reason written down —view:dashboardis still a registered key but what answers it destructures and spreads nothing, so there is no pass-through surface for that sweep to measure), and the doc-gate test's table-row pin.Not built here, reported instead
Registry.registerLazyhas no collision check whileRegistry.registerwarns, and this shape came in through that unguarded door. True, and a different card — the dispatch is explicit that it is reported and not built.packages/typeswas deliberately not touched; the tombstone needed nothing there.Update after
mainwas merged inRe-run at
ecf5fc69f: 143 test files, 1806 tests, 0 failures, andcheck:registry-bare-names,check:doc-types,check:side-effects-array,check:control-bytes,check:changeset-presence,check:new-line-citationsandregenerate-known-schema-types.mjs --checkall exit 0 on that same tree.ecf5fc69fis NOT this PR's head, and every figure under Verification above is measured onecf5fc69fand on nothing later. An earlier revision of this paragraph called it "final head … the sha every count in Verification above is measured on"; the first half of that has been false since the branch moved. It moved twice:588e45950f(the one-line unused-eslint-disabledeletion described below, plus a merge ofmain) and then96b6ee2820(the three items the at-tier contract review listed as owed before merge — the correctedexcludedsentence incheck-doc-component-types.mjs, the changeset's two missing declarations, and this body). The 143/1806 figures were not re-measured at either, and this body does not claim they were. What stands for head is CI, plus the gates re-run per commit: at96b6ee2820,check:doc-types,check:registry-bare-names,check:changeset-claims,check:changeset-presence,check:changeset-no-major,check:pending-changeset-literals,check:control-bytes,check:new-line-citations,check:doc-fences,check:doc-example-ids,check:comment-mask-corpus,check:shell-escape-residue,check:unreferenced-sourcesandregenerate-known-schema-types.mjs --checkeach exit 0,pnpm exec eslint scripts/check-doc-component-types.mjs --format jsonjudges 1 file with 0 errors and 0 warnings, andpnpm exec vitest run scripts/__tests__/check-doc-component-types.test.ts scripts/__tests__/known-schema-types-derivation-5115.test.ts packages/cli/src/__tests__/retired-view-dashboard-key-9533.test.tsreports 3 files / 136 tests passed. Theexcludedcorrection was measured before it was written: dropping that line yieldsstale-indirect-registration(both commands exit 1, nothing written), not the re-admission the sentence used to claim.Two gates that need a BUILT tree were also run once the closures were built:
check:sdui-registration-pinsexits 0 (16 promised registrations present across 2309 weighed chunks, the 3 ruled controls in the derived set) andcheck:eager-closureexits 0, both against a freshly builtapps/console.check:doc-snippets,check:doc-examplesandcheck:readme-exportsremain NOT MEASURED: each exits on a missing prerequisite (7 packages outside the closures this branch needed are still unbuilt), and none of their unjudgeable entries names a file this branch edits.pnpm exec eslint . --no-inline-config --format jsonjudging 5079 files with 0 errors. That reading was blind to the very error class that turned CI red:--no-inline-configmakes eslint skip inline configuration comments entirely, so an unusedeslint-disabledirective cannot be reported at all. The flag did not add noise — it removed a rule's ability to fire — and it is the sister repository's spelling; this repo'slintscript takes no flags. CI'sLintjob failed on exactly that: one error,Unused eslint-disable directive (no problems were reported from 'no-console')atpackages/plugin-dashboard/src/retired-node-types.tsx:72. The directive is removed — one deletion, nothing else; noconsolecall added back and no flag added anywhere.The honest reading, taken with the instrument CI actually runs:
pnpm --filter @object-ui/plugin-dashboard lintexits 0 with501 problems (0 errors, 501 warnings)— CI's 502 minus the one error — and the fullpnpm lint(turbo run lint, 47 tasks) exits 0, every package's summary line reading0 errors,//:lint:rootincluded, withUnused eslint-disableappearing nowhere in the tree. The warning split below stands, measured per file at base versus head: 17 pre-existing, 5 new, every new onereact-refresh/only-export-components— 2 fromindex.tsx's new re-export block and 3 fromretired-node-types.tsx, which exports a component beside its table exactly as@object-ui/fieldsdoes forRetiredFieldTombstone. No package'slintscript sets--max-warnings.One repair this branch owed itself.
check-doc-component-types.mjs's header ran its objectui#5106 namespace-blindness example over the literal pairview:dashboard/plugin-dashboard:dashboardand told the reader to flipnamespace: 'view'on the dashboard registration. This branch made that false — there is nonamespace: 'view'on that registration any more — so the example is re-pointed with a note saying what moved. Not opportunistic tidying: a claim this diff falsified, in a file this diff already edits.Seat session, in prose so it survives an edit:
session_012EpHzwH4wTy5sd7ibkD2yq.needs:contract-reviewis hung on both carriers — the claiming seat hung the PR-side half after this PR was opened, since that half is the PM's — andcheck-clause2-carriers.mjs --pair 9803now exits 0. Arranging the clause-② review belongs to the claiming seat; ⛔ this branch does not wait on it.🤖 Generated with Claude Code
https://claude.ai/code/session_012EpHzwH4wTy5sd7ibkD2yq
Generated by Claude Code