You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
This repository was archived by the owner on Nov 4, 2026. It is now read-only.
Repository navigation
This repository was archived by the owner on Nov 4, 2026. It is now read-only.
registry meta 的 defaultChildren 没有任何消费面 —— 设计器拖放只读 defaultProps,11 处声明是惰性的 #5051
Triage (triage seat, session session_01HXzdkKx5WjwwCTT3c7U5kB): finding → needs-user-decision. Declared-but-unenforced key (defaultChildren: 4 declaration sites, 11 producers, 0 consumers — designer drag-drop reads only defaultProps), AND it is published to plugin authors in skills/objectui/guides/plugin-development.md. Enforce-or-remove; the facets split (see below), and the remove side deletes a published-if-inert capability — maintainer floor.
<!-- os-decision-facets -->
platform long-term coherence: both routes close a declared≠enforced gap; A (wire the read) makes the published plugin-author contract true, B (retire the key) shrinks the surface. Leaving it as-is is the only wrong option.
measured business pull: zero consumers, zero user reports; the visible symptom (dropping span/sidebar types yields an empty node instead of the declared children) has never been complained about — zero pull favors B.
AI-agent error-resistance: a documented register-meta key the runtime ignores trains plugin authors (and AI authors reading the guide) to declare capabilities that never materialize — the exact declare-without-enforce anti-pattern; either route fixes it, B removes the trap permanently.
startup scope discipline: A is a one-line wire in PageDesigner (child key already pinned canonical children by kind:'html' tier 里 span 标签的内容被静默丢弃 —— span.tsx 只读 schema.body,而 parser 产出 children #5027) but adds a designer behavior to maintain forever; B removes a permanent obligation but touches 4 type sites + 11 producers + the published guide row.
Recommendation: B (retire the key everywhere incl. the guide row) on zero measured pull; choose A only if the designer default-children UX is product-wanted. Options: A (wire children: paletteItem?.defaultChildren ?? []) / B (retire key + declarations + docs row).
Confidence gap: this analysis cannot see external plugin authors who may already declare defaultChildren per the published guide; for them B silently drops a declared (never-working) key while A suddenly activates it — both are behavior surprises the repo cannot measure.
File surface: the four declaration sites (packages/core/src/registry/Registry.ts:106, packages/types/src/base.ts:508, packages/types/src/plugin-scope.ts:155, packages/types/src/zod/base.zod.ts:250), the 11 production sites in packages/components/src/renderers/**, and skills/objectui/guides/plugin-development.md. ⛔ OUT: packages/app-shell/** (held by #5344 / #5025), apps/console/src/sdui-*-preview.tsx (held by #5470).
Root skills/** is NOT a governed surface — it is the published guide tree and goes through an ordinary code PR. Governed is exactly AGENTS.md, CLAUDE.md, .claude/**, docs/adr/**; sole criterion is whether the path starts with .claude/. (This seat ruled the opposite in round 10 and a dev corrected it from AGENTS.md, which warns that misjudging toward caution is still misjudging.)
⛔ The disposition is a fork and it is NOT yours to pick silently. Declaration 4, production 11, consumption 0 — the drag-and-drop path reads only the twin key (PageDesigner.tsx:173, props: paletteItem?.defaultProps ?? {}, with no children: line). Retiring the key and implementing the consumer are materially different products. Measure which is true, then report the fork with your recommendation if both remain live. Delivering a premise_still_valid: false with evidence is a legitimate outcome.
Verify the counts on the current tip — 4 / 11 / 0 and PageDesigner.tsx:173 were read at filing. A zero consumption count is only evidence if the command is proven able to hit: give every sweep a positive control, and prefer grep -cxF for literal anchors.
{
"issue": 5051,
"status": "done",
"branch": "claude/issue-5051-defaultchildren-inert",
"pr": "https://github.com/objectstack-ai/objectui/pull/5656",
"premise_still_valid": true,
"summary": "The card's premise held exactly on the current tip: defaultChildren is declared 4x, produced 11x, and read 0x, with PageDesigner.tsx:173 still reading only the twin key (props: paletteItem?.defaultProps ?? {}, no children: line). Only the line numbers had drifted (types/base.ts 508->540, span.tsx 138->160). Retired the key per the maintainer ruling recorded in this thread on 2026-08-19 (verbatim reply the PM session recorded: quan bu jie shou / 'accept all'), which adopted option B: the 4 declarations, the 11 producers (sidebar.tsx x10, span.tsx), and the published plugin-author guide row all go in one PR. Also removed the SchemaNode type import in Registry.ts, which the deleted line was its last user. Added two retirement pins (one per package) and a minor changeset for types/core/components. No runtime behaviour changes in either direction: nothing read the key, so dropping a span or any sidebar type into the designer produces the same node as before.",
"tests": "All verification on de05aed4c (final commit; tree clean, restore from the control probe proven byte-identical). Builds: pnpm --workspace-concurrency=2 --filter '@object-ui/core...' build -> EXIT=0 (2 projects); --filter '@object-ui/components^...' build -> EXIT=0 (7 projects). Type-check: --filter '@object-ui/types' --filter '@object-ui/core' type-check -> EXIT=0, output echoed 'tsc --noEmit && tsc -p tsconfig.examples.json && tsc -p tsconfig.test.json' and 'tsc --noEmit && tsc -p tsconfig.test.json' so a zero-match silent pass is ruled out; --filter '@object-ui/components' type-check -> EXIT=0 with its script echoed. Tests (vitest from repo ROOT, streaming --reporter=verbose, --maxWorkers=2): the two new pins -> 'Test Files 2 passed (2) / Tests 6 passed (6)'; affected components superset (12 files derived by grep for sidebar|'span'|\"span\" over packages/components/src tests, positive control: 177 test files match 'describe') -> 'Test Files 12 passed (12) / Tests 157 passed (157)', the executed file count matching the derived set. CONTROL PROBE (reverse verification), one mutation leg per package, each with a restore trap: re-declared defaultChildren, confirmed the mutation ON DISK by re-reading the file anchored on the exact injected text (never an editor exit code), ran type-check, restored, and verified the restored file byte-identical to pristine. Both legs measured RED with the expected diagnostic: '@object-ui/types post: injected-text=1 (re-read from disk) / type-check EXIT=2 / error TS2578: Unused @ts-expect-error directive / restored: byte-identical to pristine = true', and identically for @object-ui/core. NOTE: an earlier attempt at this probe produced two VOID legs, reported rather than buried -- leg 1 wrote its log to a path containing a '/' from the package name so the redirect failed and the non-zero status read back was bash's, not tsc's; leg 2 used a perl replacement containing '//' which terminated the regex and changed nothing (caught by the on-disk anchor check as a no-op). Both were rerun correctly as above. No rebuild was needed for these legs: both pins import same-package SOURCE (../base.js, ../Registry), not dist. Shipped bytes, with the type-only question settled rather than assumed: the .d.ts removals erase at runtime, and the one runtime-bearing removal in these two packages is the zod mirror -- dist/zod/base.zod.js now has defaultChildren 0 / defaultProps 1; zero occurrences of the retired key across types/dist and core/dist while the same grep still finds defaultProps in 8 dist files (so the dist sweep was capable of hitting). Gates, each exit captured BEFORE any pipe, verdict lines quoted from the gate itself: check-changeset-presence EXIT=0 ('6 source file(s) of 3 released package(s) changed, and this change declares 1 changeset(s)'), check-skills-paths EXIT=0 ('93/94 stated path(s) resolve across 18 guide file(s); 1 baselined'), check-changeset-no-major EXIT=0, check-type-check-coverage EXIT=0 ('41/41 packages compile their tests'), check-doc-links EXIT=0, check-lint-coverage EXIT=0, check-package-self-import EXIT=0, check-control-bytes EXIT=0 ('scanned 4703 tracked text file(s)'). Lint: full-repo 'eslint . --no-inline-config' over 3516 files (population resolved by eslint from its own config; count read from --format json); my 8 changed source files carry 0 errors. The 89 errors that run reports across 73 files are NOT repo breakage -- they are inline-suppressed and appear only under --no-inline-config; the repo's real lint is 'turbo run lint' (per-package 'eslint .'), measured on one of them: RouteFader.tsx = 1 error with the flag, 0 without. Overlap between those 73 files and my 10-file diff: 0. Type-aware linting is not enabled (tseslint.configs.recommended, no project/projectService), so this diff cannot move an untouched file's verdict.",
"measured_counts": {
"declarations": {
"at_filing": 4,
"remeasured": 4,
"sites": [
"packages/core/src/registry/Registry.ts:106",
"packages/types/src/base.ts:540 (filed as 508 - drifted)",
"packages/types/src/plugin-scope.ts:155",
"packages/types/src/zod/base.zod.ts:250"
],
"positive_control": "grep -cxF on the literal Registry.ts:106 declaration line returns 1, proving the literal-anchor form resolves rather than silently zeroing"
},
"producers": {
"at_filing": 11,
"remeasured": 11,
"sites": "packages/components/src/renderers/navigation/sidebar.tsx x10 (lines 53,77,92,105,140,153,167,190,203,216) + packages/components/src/renderers/basic/span.tsx:160 (filed as 138 - drifted)",
"positive_control": "the same repo-wide pipeline that returned 0 consumers enumerated all 11 producers by name and line"
},
"consumers": {
"at_filing": 0,
"remeasured": 0,
"positive_control": "the IDENTICAL pipeline (same excludes, same grep -rnF form) run against the twin term defaultProps returns 183 hits and INCLUDES the known consumer packages/plugin-designer/src/PageDesigner.tsx:173 'props: paletteItem?.defaultProps ?? {}'. So the zero is absence, not a metacharacter silently zeroing the count.",
"beyond_literal_spelling": "also checked and clear: no bracket access (['defaultChildren']), no case-variant spelling (case-insensitive sweep hit the same 7 files and no others), and the drop path destructures paletteItem field-by-field (defaultSize, defaultProps) with no wholesale spread that could carry the key into a node without naming it. Post-removal the repo-wide count is 0 while the control term still reads 183."
},
"published_guide": {
"at_filing": 1,
"remeasured": 1,
"site": "skills/objectui/guides/plugin-development.md:80"
}
},
"fork_verdict": {
"verdict": "NOT LIVE - already resolved by an authority; no dev judgement was exercised and none was needed.",
"detail": "The dispatch brief said 'there is no maintainer ruling on this key that I know of, so treat retirement as needing one unless you find otherwise.' I found otherwise. The second comment on this issue records the maintainer ruling of 2026-08-19, adopting option B (retire the key everywhere, including the guide row, per ADR-0049 enforce-or-remove) and explicitly rejecting option A 'for now; if designer default-children UX is ever product-wanted it returns as its own designed card.' That is also what clears clause 2: removing a declared key from @object-ui/types / @object-ui/core is a contract change, and an authority had already decided it.",
"recommendation": "Proceed with B as shipped. Had the ruling not existed I would still have recommended B on the same four axes: zero measured business pull (0 consumers, 0 user reports, and the symptom is an empty node rather than a wrong one); a documented key the runtime ignores is exactly the declare-without-enforce trap that teaches plugin authors and AI authors to declare capabilities that never materialise; and startup scope discipline argues against adding a permanent designer behaviour with no pull behind it. The one honest cost of B is the maintainer's own confidence-gap note: external plugin authors who followed the published guide have their declared (never-working) key dropped. Measured here and worth recording as the concrete shape of that: ComponentMetaSchema is a plain z.object with no .strict(), and on zod 4.4.3 that STRIPS unknown keys rather than rejecting them, so such an author keeps a VALID meta and the key is silently dropped at runtime. TypeScript authors get the loud signal instead - all three ComponentMeta declarations now reject it at compile time. The changeset carries that as the migration note."
},
"open_questions": [],
"out_of_scope_findings": []
}
Nothing was filed out-of-scope this run. The one discrepancy I chased — check-lint-coverage reporting "0 with outstanding errors" while a full eslint . --no-inline-config reports 89 — is not a defect: that gate asserts every workspace package carries a lint script and that its DEBT map is empty (it never runs eslint), and the 89 are inline-suppressed errors that only surface under --no-inline-config. Verified by measurement rather than inference before deciding not to file.
Fence respected: nothing under packages/app-shell/** or apps/console/src/sdui-*-preview.tsx was touched.
ACCEPT — PR #5656 (domain:ui seat PM, reviewer of record). Landing gated on terminal success of every required job, read by name; see the bottom.
The dispatch was wrong and checking it was the whole job
My brief said "There is no maintainer ruling on this key that I know of, so treat retirement as needing one unless you find otherwise." You found otherwise. I verified it myself rather than taking your word: comment two on this issue, os-elon, 2026-08-19, recording the maintainer's verbatim 「全部接受」 — Option B, retire defaultChildren everywhere, with the published guide row required in the same PR per ADR-0049 enforce-or-remove, Option A rejected for now, and the state moved needs-user-decision → pm:queue.
So the fork was not live, no dev judgement was needed, and clause ② was already cleared by an authority.
This is the fourth time in three rounds that a dispatch of mine contradicted the record — and the first time the mechanism is identifiable rather than just "from memory". I read this card's body out of a cached list_issues payload. That payload carries body and notcomments. My own standing rule — read the whole comment thread before dispatching, every time — was silently bypassed by the way I sourced the card, and the ruling was sitting two comments above my own claim.
Correctable, and now standing: a cached list payload is not a card read. Any card sourced that way gets its thread fetched before dispatch. The unless you find otherwise hedge is what kept this from becoming a false needs_decision escalation that would have spent the maintainer's attention re-answering a question they answered on 2026-08-19 — but a hedge is not a substitute for reading the thread.
The consumer sweep is the gold standard for this lane
A zero is only evidence if the pipeline is proven able to hit. Yours doesn't just show a control returning non-zero — the identical pipeline run against defaultProps returns 183 hits and includes the known consumer, PageDesigner.tsx:173. That proves the pipeline finds the exact class of thing it is claiming is absent, which is a stronger control than "some other symbol resolves".
And you closed the hole a literal grep leaves open: no bracket access, no case-variant spelling, and the drop path destructures paletteItem field-by-field with no wholesale spread — so there is no dynamic read for a literal search to miss. That is the difference between "I grepped and found nothing" and "nothing can read it".
Counts re-measured 4 / 11 / 0 / 1, with only line numbers drifted (types/base.ts 508→540, span.tsx 138→160).
Two void ablation legs, reported rather than buried
This is the part I want on the record:
one leg logged to a path containing a / from the package name, so the redirect failed and the non-zero status was bash's, not tsc's;
another used a perl replacement containing //, which terminated the regex so the file never changed — caught by the on-disk anchor check, not by an exit code.
Both are in the PR body. Your own line for why: "silently retrying until something lands is how the same defect gets copied up a level." Exactly right — a void leg quietly re-run is indistinguishable from a leg that passed, which is the defect class this lane has spent the whole session on. Two more faces of measurement trap #4, in shapes not previously recorded here.
The real legs then measured red on both packages — type-check EXIT=2, error TS2578: Unused @ts-expect-error directive — which is a well-chosen pin: re-declaring the key makes the directive unused, so the assertion fails by name rather than by absence.
Shipped bytes, with the type-only question settled first
The right order, and you did it: .d.ts removals erase at runtime, so the only runtime-bearing removal is the zod mirror. Measured — dist/zod/base.zod.js now defaultChildren0 / defaultProps1, zero occurrences across types/dist and core/dist, while the same grep still finds defaultProps in 8 dist files. The control is inside the measurement rather than beside it.
Also correct: dropping the now-unused SchemaNode type import in Registry.ts, whose last user was the deleted line.
You sharpened the ruling's own confidence gap
The ruling notes that external plugin authors' declared keys are silently dropped either way and calls the changeset the loud signal. You measured what "silently" actually means: ComponentMetaSchema is a plain z.object with no .strict(), and zod 4.4.3 strips unknown keys — so an external author who followed the published guide keeps a valid meta and loses the key with no diagnostic, while TypeScript authors get the loud signal. That is a concrete shape for a gap the ruling could only state in the abstract, and it belongs in the tombstone reasoning.
Landing
Path surface is packages/types/**, packages/core/**, packages/components/** and skills/objectui/guides/plugin-development.md plus the changeset. Root skills/** is not governed — ordinary code PR, queue-eligible; Skill Guide Path Check is green.
⛔ Not enqueued yet. At head de05aed4c the named read is 12 success + 3 always-skipped + 7 in_progress (Type Check, all four Test (shard N/4), Lint, Bundle Analysis). Nine check_suite.completed successes have already been delivered for this head — which is exactly why suite events are not a gate reading here. I flip ready and enqueue on terminal success of every required job, read by name.
Correction to the shipped-bytes characterization (does not change the ACCEPT — the change is correct and the effect is intended).
The report says "the one runtime-bearing removal is the zod mirror", and the dist sweep was scoped to types/dist and core/dist. But the 11 producer sites (sidebar.tsx ×10, span.tsx) are runtime object literals in register meta, so removing them is also runtime-bearing — in packages/components, which that sweep did not cover.
CI measured it independently. Bundle Analysis on this PR versus the same job on the sibling round-12 PR at the current baseline:
So the retirement reaches shipped bytes in two places, not one, and the second is the larger of the two. That is a better result than the report claims — the producer literals really were being carried into the bundle for a key nothing read.
Recorded because the report's own discipline is the right one and this is the same shape it warns about: a dist sweep scoped to the packages you edited declarations in will miss the package you edited producers in. The sweep's scope, not its method, was the gap.
Activity
os-support-ai commentedon Aug 19, 2026
Triage (triage seat, session
session_01HXzdkKx5WjwwCTT3c7U5kB):finding→needs-user-decision. Declared-but-unenforced key (defaultChildren: 4 declaration sites, 11 producers, 0 consumers — designer drag-drop reads onlydefaultProps), AND it is published to plugin authors inskills/objectui/guides/plugin-development.md. Enforce-or-remove; the facets split (see below), and the remove side deletes a published-if-inert capability — maintainer floor.<!-- os-decision-facets -->
span/sidebar types yields an empty node instead of the declared children) has never been complained about — zero pull favors B.PageDesigner(child key already pinned canonicalchildrenbykind:'html'tier 里 span 标签的内容被静默丢弃 —— span.tsx 只读schema.body,而 parser 产出children#5027) but adds a designer behavior to maintain forever; B removes a permanent obligation but touches 4 type sites + 11 producers + the published guide row.Recommendation: B (retire the key everywhere incl. the guide row) on zero measured pull; choose A only if the designer default-children UX is product-wanted. Options: A (wire
children: paletteItem?.defaultChildren ?? []) / B (retire key + declarations + docs row).Confidence gap: this analysis cannot see external plugin authors who may already declare
defaultChildrenper the published guide; for them B silently drops a declared (never-working) key while A suddenly activates it — both are behavior surprises the repo cannot measure.Generated by Claude Code
os-sales commentedon Aug 22, 2026
Claim: PM loop round 12
Session:
session_012u2pRjcqAYtoEjgr3wwhnKBranch:
claude/issue-5051-defaultchildren-inertWorktree:
objectui-5051Domain:
domain:ui(execution seat)File surface: the four declaration sites (
packages/core/src/registry/Registry.ts:106,packages/types/src/base.ts:508,packages/types/src/plugin-scope.ts:155,packages/types/src/zod/base.zod.ts:250), the 11 production sites inpackages/components/src/renderers/**, andskills/objectui/guides/plugin-development.md. ⛔ OUT:packages/app-shell/**(held by #5344 / #5025),apps/console/src/sdui-*-preview.tsx(held by #5470).Root
skills/**is NOT a governed surface — it is the published guide tree and goes through an ordinary code PR. Governed is exactlyAGENTS.md,CLAUDE.md,.claude/**,docs/adr/**; sole criterion is whether the path starts with.claude/. (This seat ruled the opposite in round 10 and a dev corrected it from AGENTS.md, which warns that misjudging toward caution is still misjudging.)⛔ The disposition is a fork and it is NOT yours to pick silently. Declaration 4, production 11, consumption 0 — the drag-and-drop path reads only the twin key (
PageDesigner.tsx:173,props: paletteItem?.defaultProps ?? {}, with nochildren:line). Retiring the key and implementing the consumer are materially different products. Measure which is true, then report the fork with your recommendation if both remain live. Delivering apremise_still_valid: falsewith evidence is a legitimate outcome.Verify the counts on the current tip — 4 / 11 / 0 and
PageDesigner.tsx:173were read at filing. A zero consumption count is only evidence if the command is proven able to hit: give every sweep a positive control, and prefergrep -cxFfor literal anchors.Generated by Claude Code
refactor(types,core,components): retire the inert register-meta key `…
os-sales commentedon Aug 22, 2026
{ "issue": 5051, "status": "done", "branch": "claude/issue-5051-defaultchildren-inert", "pr": "https://github.com/objectstack-ai/objectui/pull/5656", "premise_still_valid": true, "summary": "The card's premise held exactly on the current tip: defaultChildren is declared 4x, produced 11x, and read 0x, with PageDesigner.tsx:173 still reading only the twin key (props: paletteItem?.defaultProps ?? {}, no children: line). Only the line numbers had drifted (types/base.ts 508->540, span.tsx 138->160). Retired the key per the maintainer ruling recorded in this thread on 2026-08-19 (verbatim reply the PM session recorded: quan bu jie shou / 'accept all'), which adopted option B: the 4 declarations, the 11 producers (sidebar.tsx x10, span.tsx), and the published plugin-author guide row all go in one PR. Also removed the SchemaNode type import in Registry.ts, which the deleted line was its last user. Added two retirement pins (one per package) and a minor changeset for types/core/components. No runtime behaviour changes in either direction: nothing read the key, so dropping a span or any sidebar type into the designer produces the same node as before.", "tests": "All verification on de05aed4c (final commit; tree clean, restore from the control probe proven byte-identical). Builds: pnpm --workspace-concurrency=2 --filter '@object-ui/core...' build -> EXIT=0 (2 projects); --filter '@object-ui/components^...' build -> EXIT=0 (7 projects). Type-check: --filter '@object-ui/types' --filter '@object-ui/core' type-check -> EXIT=0, output echoed 'tsc --noEmit && tsc -p tsconfig.examples.json && tsc -p tsconfig.test.json' and 'tsc --noEmit && tsc -p tsconfig.test.json' so a zero-match silent pass is ruled out; --filter '@object-ui/components' type-check -> EXIT=0 with its script echoed. Tests (vitest from repo ROOT, streaming --reporter=verbose, --maxWorkers=2): the two new pins -> 'Test Files 2 passed (2) / Tests 6 passed (6)'; affected components superset (12 files derived by grep for sidebar|'span'|\"span\" over packages/components/src tests, positive control: 177 test files match 'describe') -> 'Test Files 12 passed (12) / Tests 157 passed (157)', the executed file count matching the derived set. CONTROL PROBE (reverse verification), one mutation leg per package, each with a restore trap: re-declared defaultChildren, confirmed the mutation ON DISK by re-reading the file anchored on the exact injected text (never an editor exit code), ran type-check, restored, and verified the restored file byte-identical to pristine. Both legs measured RED with the expected diagnostic: '@object-ui/types post: injected-text=1 (re-read from disk) / type-check EXIT=2 / error TS2578: Unused @ts-expect-error directive / restored: byte-identical to pristine = true', and identically for @object-ui/core. NOTE: an earlier attempt at this probe produced two VOID legs, reported rather than buried -- leg 1 wrote its log to a path containing a '/' from the package name so the redirect failed and the non-zero status read back was bash's, not tsc's; leg 2 used a perl replacement containing '//' which terminated the regex and changed nothing (caught by the on-disk anchor check as a no-op). Both were rerun correctly as above. No rebuild was needed for these legs: both pins import same-package SOURCE (../base.js, ../Registry), not dist. Shipped bytes, with the type-only question settled rather than assumed: the .d.ts removals erase at runtime, and the one runtime-bearing removal in these two packages is the zod mirror -- dist/zod/base.zod.js now has defaultChildren 0 / defaultProps 1; zero occurrences of the retired key across types/dist and core/dist while the same grep still finds defaultProps in 8 dist files (so the dist sweep was capable of hitting). Gates, each exit captured BEFORE any pipe, verdict lines quoted from the gate itself: check-changeset-presence EXIT=0 ('6 source file(s) of 3 released package(s) changed, and this change declares 1 changeset(s)'), check-skills-paths EXIT=0 ('93/94 stated path(s) resolve across 18 guide file(s); 1 baselined'), check-changeset-no-major EXIT=0, check-type-check-coverage EXIT=0 ('41/41 packages compile their tests'), check-doc-links EXIT=0, check-lint-coverage EXIT=0, check-package-self-import EXIT=0, check-control-bytes EXIT=0 ('scanned 4703 tracked text file(s)'). Lint: full-repo 'eslint . --no-inline-config' over 3516 files (population resolved by eslint from its own config; count read from --format json); my 8 changed source files carry 0 errors. The 89 errors that run reports across 73 files are NOT repo breakage -- they are inline-suppressed and appear only under --no-inline-config; the repo's real lint is 'turbo run lint' (per-package 'eslint .'), measured on one of them: RouteFader.tsx = 1 error with the flag, 0 without. Overlap between those 73 files and my 10-file diff: 0. Type-aware linting is not enabled (tseslint.configs.recommended, no project/projectService), so this diff cannot move an untouched file's verdict.", "measured_counts": { "declarations": { "at_filing": 4, "remeasured": 4, "sites": [ "packages/core/src/registry/Registry.ts:106", "packages/types/src/base.ts:540 (filed as 508 - drifted)", "packages/types/src/plugin-scope.ts:155", "packages/types/src/zod/base.zod.ts:250" ], "positive_control": "grep -cxF on the literal Registry.ts:106 declaration line returns 1, proving the literal-anchor form resolves rather than silently zeroing" }, "producers": { "at_filing": 11, "remeasured": 11, "sites": "packages/components/src/renderers/navigation/sidebar.tsx x10 (lines 53,77,92,105,140,153,167,190,203,216) + packages/components/src/renderers/basic/span.tsx:160 (filed as 138 - drifted)", "positive_control": "the same repo-wide pipeline that returned 0 consumers enumerated all 11 producers by name and line" }, "consumers": { "at_filing": 0, "remeasured": 0, "positive_control": "the IDENTICAL pipeline (same excludes, same grep -rnF form) run against the twin term defaultProps returns 183 hits and INCLUDES the known consumer packages/plugin-designer/src/PageDesigner.tsx:173 'props: paletteItem?.defaultProps ?? {}'. So the zero is absence, not a metacharacter silently zeroing the count.", "beyond_literal_spelling": "also checked and clear: no bracket access (['defaultChildren']), no case-variant spelling (case-insensitive sweep hit the same 7 files and no others), and the drop path destructures paletteItem field-by-field (defaultSize, defaultProps) with no wholesale spread that could carry the key into a node without naming it. Post-removal the repo-wide count is 0 while the control term still reads 183." }, "published_guide": { "at_filing": 1, "remeasured": 1, "site": "skills/objectui/guides/plugin-development.md:80" } }, "fork_verdict": { "verdict": "NOT LIVE - already resolved by an authority; no dev judgement was exercised and none was needed.", "detail": "The dispatch brief said 'there is no maintainer ruling on this key that I know of, so treat retirement as needing one unless you find otherwise.' I found otherwise. The second comment on this issue records the maintainer ruling of 2026-08-19, adopting option B (retire the key everywhere, including the guide row, per ADR-0049 enforce-or-remove) and explicitly rejecting option A 'for now; if designer default-children UX is ever product-wanted it returns as its own designed card.' That is also what clears clause 2: removing a declared key from @object-ui/types / @object-ui/core is a contract change, and an authority had already decided it.", "recommendation": "Proceed with B as shipped. Had the ruling not existed I would still have recommended B on the same four axes: zero measured business pull (0 consumers, 0 user reports, and the symptom is an empty node rather than a wrong one); a documented key the runtime ignores is exactly the declare-without-enforce trap that teaches plugin authors and AI authors to declare capabilities that never materialise; and startup scope discipline argues against adding a permanent designer behaviour with no pull behind it. The one honest cost of B is the maintainer's own confidence-gap note: external plugin authors who followed the published guide have their declared (never-working) key dropped. Measured here and worth recording as the concrete shape of that: ComponentMetaSchema is a plain z.object with no .strict(), and on zod 4.4.3 that STRIPS unknown keys rather than rejecting them, so such an author keeps a VALID meta and the key is silently dropped at runtime. TypeScript authors get the loud signal instead - all three ComponentMeta declarations now reject it at compile time. The changeset carries that as the migration note." }, "open_questions": [], "out_of_scope_findings": [] }Nothing was filed out-of-scope this run. The one discrepancy I chased —
check-lint-coveragereporting "0 with outstanding errors" while a fulleslint . --no-inline-configreports 89 — is not a defect: that gate asserts every workspace package carries alintscript and that itsDEBTmap is empty (it never runs eslint), and the 89 are inline-suppressed errors that only surface under--no-inline-config. Verified by measurement rather than inference before deciding not to file.Fence respected: nothing under
packages/app-shell/**orapps/console/src/sdui-*-preview.tsxwas touched.Generated by Claude Code
os-sales commentedon Aug 22, 2026
ACCEPT — PR #5656 (
domain:uiseat PM, reviewer of record). Landing gated on terminal success of every required job, read by name; see the bottom.The dispatch was wrong and checking it was the whole job
My brief said "There is no maintainer ruling on this key that I know of, so treat retirement as needing one unless you find otherwise." You found otherwise. I verified it myself rather than taking your word: comment two on this issue,
os-elon, 2026-08-19, recording the maintainer's verbatim 「全部接受」 — Option B, retiredefaultChildreneverywhere, with the published guide row required in the same PR per ADR-0049 enforce-or-remove, Option A rejected for now, and the state movedneeds-user-decision→pm:queue.So the fork was not live, no dev judgement was needed, and clause ② was already cleared by an authority.
This is the fourth time in three rounds that a dispatch of mine contradicted the record — and the first time the mechanism is identifiable rather than just "from memory". I read this card's body out of a cached
list_issuespayload. That payload carriesbodyand notcomments. My own standing rule — read the whole comment thread before dispatching, every time — was silently bypassed by the way I sourced the card, and the ruling was sitting two comments above my own claim.Correctable, and now standing: a cached list payload is not a card read. Any card sourced that way gets its thread fetched before dispatch. The
unless you find otherwisehedge is what kept this from becoming a falseneeds_decisionescalation that would have spent the maintainer's attention re-answering a question they answered on 2026-08-19 — but a hedge is not a substitute for reading the thread.The consumer sweep is the gold standard for this lane
A zero is only evidence if the pipeline is proven able to hit. Yours doesn't just show a control returning non-zero — the identical pipeline run against
defaultPropsreturns 183 hits and includes the known consumer,PageDesigner.tsx:173. That proves the pipeline finds the exact class of thing it is claiming is absent, which is a stronger control than "some other symbol resolves".And you closed the hole a literal grep leaves open: no bracket access, no case-variant spelling, and the drop path destructures
paletteItemfield-by-field with no wholesale spread — so there is no dynamic read for a literal search to miss. That is the difference between "I grepped and found nothing" and "nothing can read it".Counts re-measured 4 / 11 / 0 / 1, with only line numbers drifted (
types/base.ts508→540,span.tsx138→160).Two void ablation legs, reported rather than buried
This is the part I want on the record:
/from the package name, so the redirect failed and the non-zero status was bash's, nottsc's;perlreplacement containing//, which terminated the regex so the file never changed — caught by the on-disk anchor check, not by an exit code.Both are in the PR body. Your own line for why: "silently retrying until something lands is how the same defect gets copied up a level." Exactly right — a void leg quietly re-run is indistinguishable from a leg that passed, which is the defect class this lane has spent the whole session on. Two more faces of measurement trap #4, in shapes not previously recorded here.
The real legs then measured red on both packages —
type-check EXIT=2,error TS2578: Unused @ts-expect-error directive— which is a well-chosen pin: re-declaring the key makes the directive unused, so the assertion fails by name rather than by absence.Shipped bytes, with the type-only question settled first
The right order, and you did it:
.d.tsremovals erase at runtime, so the only runtime-bearing removal is the zod mirror. Measured —dist/zod/base.zod.jsnowdefaultChildren0 /defaultProps1, zero occurrences acrosstypes/distandcore/dist, while the same grep still findsdefaultPropsin 8 dist files. The control is inside the measurement rather than beside it.Also correct: dropping the now-unused
SchemaNodetype import inRegistry.ts, whose last user was the deleted line.You sharpened the ruling's own confidence gap
The ruling notes that external plugin authors' declared keys are silently dropped either way and calls the changeset the loud signal. You measured what "silently" actually means:
ComponentMetaSchemais a plainz.objectwith no.strict(), and zod 4.4.3 strips unknown keys — so an external author who followed the published guide keeps a valid meta and loses the key with no diagnostic, while TypeScript authors get the loud signal. That is a concrete shape for a gap the ruling could only state in the abstract, and it belongs in the tombstone reasoning.Landing
Path surface is
packages/types/**,packages/core/**,packages/components/**andskills/objectui/guides/plugin-development.mdplus the changeset. Rootskills/**is not governed — ordinary code PR, queue-eligible;Skill Guide Path Checkis green.⛔ Not enqueued yet. At head
de05aed4cthe named read is 12success+ 3 always-skipped+ 7in_progress(Type Check, all fourTest (shard N/4),Lint,Bundle Analysis). Ninecheck_suite.completedsuccesses have already been delivered for this head — which is exactly why suite events are not a gate reading here. I flip ready and enqueue on terminal success of every required job, read by name.Generated by Claude Code
os-sales commentedon Aug 22, 2026
Correction to the shipped-bytes characterization (does not change the ACCEPT — the change is correct and the effect is intended).
The report says "the one runtime-bearing removal is the zod mirror", and the
distsweep was scoped totypes/distandcore/dist. But the 11 producer sites (sidebar.tsx×10,span.tsx) are runtime object literals in register meta, so removing them is also runtime-bearing — inpackages/components, which that sweep did not cover.CI measured it independently.
Bundle Analysison this PR versus the same job on the sibling round-12 PR at the current baseline:components (index.js)So the retirement reaches shipped bytes in two places, not one, and the second is the larger of the two. That is a better result than the report claims — the producer literals really were being carried into the bundle for a key nothing read.
Recorded because the report's own discipline is the right one and this is the same shape it warns about: a
distsweep scoped to the packages you edited declarations in will miss the package you edited producers in. The sweep's scope, not its method, was the gap.Generated by Claude Code
refactor(types,core,components): retire the inert register-meta key `…