Repository navigation
test(types): the objectui#7340 pin cannot see example object literals — its DOC_MEMBER_RE requires a declaration row, so a retired handler key in a const x: Schema = {} example stays green #7840
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-repo
on Sep 5, 2026 Claim: PM loop round R46 — a MEASUREMENT-FIRST card: answer the three questions the card owes (which literal shapes count, how an example literal resolves its owner, and the population on
mainwith real-vs-counter-example split), price the alternative it names (finishing objectui#5867'scheck:doc-fencesledger so every such block becomes a compiled block), and implement the widenedobjectui#7340pin ONLY if the measurement shows the literal reader can keep the PAIR RULE and the PROSE rule with zero false positives on today's corpus; otherwise stop after the measurement and report the fork with both options priced
Session:session_01FhBNJcLRZLe8M87VcUgpKr
Branch:claude/issue-7840-retired-handler-key-literals
Worktree:objectui-issue-7840
Domain:domain:devx
File surface: STEP 1 (always): a measurement overcontent/docs/**on a scratch worktree, no committed change. STEP 2 (conditional):packages/types/src/__tests__/component-docs-retired-handler-keys-7340.test.ts(a third doc-row shape besideDOC_MEMBER_RE/DOC_TABLE_RE, owner resolved from the literal's type annotation, rules 2 and 5 kept) + an EMPTY-frontmatter changeset (@object-ui/typesis published and a file under itssrc/moves) + any doc page whose literal the widened pin reds for a REAL retired pair (fix the page to the contract, ⛔ never allow-list the page). ⛔ No change toscripts/check-doc-fence-languages.mjs' ledger (that is #5867's lane); ⛔ nopackages/types/src/**outside__tests__; ⛔ no third shape (a name-level sweep is what #7340 rejected). Stop on breach; explain in the report
Container & model: M, not mechanical (the card names three open questions and one alternative; the measurement decides the route),mode:subagent,model: opus— no path-derived tier mandate; default judgment tier taken
Clause-②: no (a doc pin underpackages/types/src/__tests__; no published behaviour moves)
Serial constraints cleared: no triage comment on this card (labels from the sweep; filed by the #7488 seat at its triage's request); premise onorigin/main0caacca37at 14:07Z — the pin is 407 lines,DOC_MEMBER_REat:182still requires?:andDOC_TABLE_REat:184a table row, so an example literal matches neither;KNOWN_UNHIGHLIGHTED_TS_FENCEScarries 81 entries (the hidden-fence population the card cross-references at 80 files / 89 blocks); last churn on the pin is #7909 (an eslint-disable deletion); no open PR orclaude/*branch names 7840 or 7340; this seat's in-flight devs (#5174 b23:packages/react-runtime/README.md+ the doc-snippet ledger; #6892 s4: app-shell test files + the vi-mock gate) and queued/converging PRs (#8061, #8063, #8064:packages/types/README.md+content/docs/api/schema-reference.md+ a new scripts test; #8066) are disjoint by file —⚠️ if STEP 2 must touchcontent/docs/api/schema-reference.mdorpackages/types/README.md, mergeorigin/mainafter #8064 lands first.pm:queue→pm:dispatched+ assignee written in one stroke at 14:07Z and read back.
Generated by Claude Code
os-dev-report
{ "issue": 7840, "status": "done", "route": "b", "branch": "claude/issue-7840-retired-handler-key-literals", "pr": null, "head": "119802708", "premise_still_valid": true, "line_budget": "n/a", "files_changed": [], "summary": "Route (b), measurement only, no PR — every one of route (a)'s three gate conditions failed on measurement, and the class the card names is EMPTY on today's corpus. The MECHANISM is real and I proved it with a paired control: planting objectui#7488's exact shape (a ReportBuilderSchema literal assigning the retired onSave in a plaintext fence) leaves the pin GREEN at 25/25, while the same retired pair written in declaration shape turns it RED with 2 failures naming the row — so the control can fail, and the blindness is structural, not incidental. But the yield is zero: of 36 example object literals under content/docs, ZERO attribute to a retired pair and ZERO carry an unambiguously-retired key name, so a widened pin would ship flagging nothing. Meanwhile the false-positive surface is measured and non-empty: a reader without a word boundary produced 4 artifacts (descriptionField yields onField, conversationId yields onId), the one quoted JSON key would break an existing pin counter-probe, 2 literals sit in nested anonymous objects that would be mis-attributed to the outer owner, and 1 prose occurrence sits in a markdown table cell outside any fence. Only 7 of 36 literals attribute to an owner that is actually a shipped interface, so the PAIR RULE cannot judge the other 29 without becoming the name-level sweep objectui#7340 explicitly rejected. The alternative prices out at zero too: the whole objectui#5867 ledger (80 files, 89 hidden blocks) contains exactly ONE on-star key site, and it is a correct live nested member, so finishing that lane removes none of this class.", "measurement": { "corpus": "184 pages under content/docs, base 119802708; shipped surface 28 retired on-star never members, 105 live", "Q1_shapes": { "total_on_star_key_occurrences_excluding_pin_rows": 38, "example_object_literals": 36, "shape_split": { "literal, own-line bare key": 31, "literal, inline mid-line": 4, "literal, quoted JSON-ish key": 1, "NOT a literal — type member with no question mark": 1, "NOT a literal — prose outside any fence": 1 }, "recognisable_without_false_positives": "only the own-line bare-key shape (31). The other four are each a measured false-positive source: inline mid-line needs a word boundary or ordinary camelCase identifiers match; the quoted key is asserted NOT to be a row by the pin's own PROSE counter-probe; the type-member shape is a declaration, not an assignment; the prose occurrence sits in a markdown table cell." }, "Q2_owner_resolution": { "by_mechanism": { "type annotation on the declaration": 19, "preceding interface or type declaration": 7, "preceding heading": 9, "nothing": 1 }, "owner_is_an_actually_shipped_interface": 7, "owner_is_NOT_a_shipped_interface": 29, "nesting_depth_relative_to_the_annotated_declaration": { "direct member (PAIR RULE valid)": 21, "nested anonymous object (PAIR RULE mis-attributes)": 2, "at the declaration line": 1, "no annotation anywhere above": 12 }, "verdict": "route (a) condition 1 FAILS — 12 of 36 literals have no type annotation above them at all, and only 7 of 36 attribute to a shipped interface. Heading fallback yields section names (Overview, Components, Examples, Snippets, Persistence), not schemas." }, "Q3_population": { "literals_that_would_be_flagged": 36, "of_those_real_a_retired_pair": 0, "of_those_counter_examples_or_prose_about_the_retirement": 0, "attributing_to_a_LIVE_pair": 7, "attributing_to_no_shipped_pair_at_all": 29, "carrying_an_unambiguously_retired_key_name": 0, "fence_split": { "tsx": 24, "typescript": 9, "ts": 2, "json": 1 }, "compiled_by_check_doc_snippets": 35, "hidden_from_check_doc_snippets": 1, "the_single_hidden_literal": "content/docs/utilities/vscode-extension.mdx:206 — a quoted onSubmit inside a json fence, owner attributed only to a heading, not a retired pair, and NOT on the objectui#5867 ledger" }, "control": { "planted_literal_shape": "content/docs zz-7840-control-probe.mdx with the objectui#7488 shape, a ReportBuilderSchema literal assigning the retired onSave and onCancel inside a plaintext fence — pin exit 0, 25 passed (25). On-disk proof taken before the run; file removed by trap, git status clean after.", "counter_leg_declaration_shape": "the same retired pair as a declaration row — pin exit 1, 2 failed | 23 passed (25), both failures naming ReportBuilderSchema.onSave. This proves the control is able to fail.", "conclusion": "the pin's blindness to literals is structural and confirmed; the premise of the card stands." }, "alternative_price": { "ledger_at_119802708": "80 files / 89 SYNONYM-mode hidden blocks, all under content/docs", "on_star_key_sites_inside_those_89_hidden_blocks": 1, "that_one_site": "content/docs/components/feedback/toast.mdx:43 — a nested action.onClick declaration that matches the shipped ToastSchema exactly. Correct today, and not a literal.", "literals_removed_by_finishing_objectui_5867": 0, "verdict": "the alternative removes nothing, because the intersection the card names is already empty. It remains the right lane for the hidden-fence debt itself, but it is not a substitute instrument for this class and should not be justified by this card." } }, "route_a_conditions": { "every literal resolves an owner from its annotation": "FAILED — 19 of 36 via annotation; 12 have none at all; only 7 attribute to a shipped interface", "zero false positives on today's corpus": "FAILED — 4 word-boundary artifacts, 1 quoted key that breaks an existing counter-probe, 2 nested mis-attributions, 1 prose-in-table-cell", "PAIR RULE and PROSE rule preserved": "FAILED — 29 of 36 literals have no shipped-interface owner, so judging them at all would be the name-level sweep objectui#7340 rejected" }, "recommendation": "不实施。三条准入条件逐条实测均不成立,且收益为零 —— 今天语料里没有任何一个示例字面量指向已退休的键值对,加宽后的钉子上线即空跑,却带着已测出的误报面(缺词边界的 4 个假命中、会打破现有反例断言的引号键、2 处嵌套误归属、1 处表格散文)。按四轴:【实际业务需求】实测为零 —— 该卡命名的交叉集合(非 ts 围栏里的示例字面量携带已退休键)当前population 为 0,objectui#7488 的那一例已由重新围栏消化,没有第二个真实场景在拉动这个仪表。【项目长远合理性】现有钉子的 PAIR RULE 之所以可信,正因为它只判「能归属到已发布接口的行」;36 个字面量里 29 个归属不到,强行判它们就是 objectui#7340 明确否决的按名字扫,属于用临时补丁换覆盖面的反方向。【防 AI 写错】契约收紧优于消费端加宽:让这类块进入编译(ts 围栏)后,已退休键在 tsc 那里是构造性错误、按行报 TS2322,比一条自造正则更响亮也更难绕过 —— 这正是 objectui#7488 采用的路线,应继续作为逐例处置的标准动作。【创业阶段不扩散】零消费的新仪表不因「类可能复发」获得豁免;真正的债在 objectui#5867 的 89 个隐藏块上,那条 lane 自己会把这类风险一并收敛,不需要在 objectui#7340 上再长一个解析面。建议:本卡按 measurement-only 收口,把结论写回卡上;后续实例继续按 objectui#7488 的重新围栏处置;若将来某次测量真的出现非零 population,再以那次实测重开实施讨论。", "tests": "No diff, so no gates are owed. Evidence captured: pin baseline on 119802708 — pnpm exec vitest run packages/types/src/__tests__/component-docs-retired-handler-keys-7340.test.ts, exit 0, Test Files 1 passed (1), Tests 25 passed (25). Control leg (literal shape planted) exit 0, 25 passed (25). Counter-leg (declaration shape planted) exit 1, 2 failed | 23 passed (25). Both plants were proved on disk before each run and removed by an EXIT/INT/TERM trap; git status porcelain empty and git diff against BASE empty afterwards. Types build prerequisite: pnpm --filter @object-ui/types... build, exit 0, dist completeness 124 emitted files verified. Census scripts lived only in the scratchpad and are not committed.", "mcp_calls": "1 — the report comment on this card. No dedup search was needed: nothing was filed.", "gates": "n/a — route (b) commits nothing, so no gate is owed. The pin itself was run three times as evidence (baseline green, control green, counter-leg red).", "deviations": [ "The objectui#5867 ledger measures 80 files / 89 blocks at 119802708, not the 81 entries the dispatch cited for 0caacca37. Reported as measured.", "origin/main moved from 119802708 to 3686a44cb mid-run. Re-verified the measurement is unaffected: the scoped diff over content/docs, packages/types and the fence gate is empty, with a passing non-empty control leg over the full diff (only packages/layout/README.md and an UNGATED_DOCS entry in check-doc-snippet-types.mjs moved). All readings stay pinned to 119802708.", "The census was widened past the dispatch's line-anchored framing to include inline mid-line and quoted keys, which Q1 cannot be answered honestly without. The first pass omitted a word boundary and produced 4 false positives; they are reported as a Q1 result rather than silently corrected away." ], "open_questions": [ { "question": "An adjacent gap the measurement surfaced, reported for triage rather than filed as a card: DOC_MEMBER_RE requires the question mark, so a TYPE-member row written without one is invisible to the pin too — a different shape from the example literals this card names. The only instance on the corpus is content/docs/components/feedback/toast.mdx:43, and it is correct today (it matches the shipped nested ToastSchema action member). Should this be folded into this card, filed separately, or left alone?", "options": [ "A — leave it; offenders are zero and it shares this card's measurement answer", "B — file it as its own finding card so the shape is on record", "C — fold it into a future widening if a non-zero population ever appears" ], "recommendation": "A, because filing a card whose measured population is zero reproduces exactly the cost this card just measured — a new parse surface with no pull. C is the honest re-entry condition: the shape is recorded here, and a real offender is what should reopen it." } ], "out_of_scope_findings": [] }
Generated by Claude Code
ACCEPT (measurement) — route (b), no PR. The class this card names measures to ZERO on today's corpus, the widened reader's false-positive surface is measured and non-empty, and the alternative removes nothing. Closing as not planned with the measurement as the record; a non-zero population is the re-entry condition.
domain:devx @ objectuiexecution seat, PM sessionsession_01FhBNJcLRZLe8M87VcUgpKr, R46, 2026-09-06T14:23Z. Report5559840936reviewed; the branchclaude/issue-7840-retired-handler-key-literalssits at the base commit with no commits, as route (b) requires.What the measurement established (on
119802708, re-verified unaffected by the move to3686a44cb):- The mechanism is real, proven with a paired control: objectui#7488's shape planted in a
plaintextfence leaves the pin green (25/25); the same retired pair as a declaration row reds it (2 failed) — so the control can fail and the blindness is structural. - The yield is zero: 36 example object literals under
content/docs, 0 attribute to a retired pair, 0 carry an unambiguously retired key; 35 of 36 already sit in compiledts/tsxfences; the one hidden literal is a liveonSubmitin ajsonfence. - Route (a)'s three conditions each fail: 12 of 36 literals have no annotation, only 7 of 36 attribute to a shipped interface (judging the other 29 is the name-level sweep docs: three pages still teach retired handler keys as authorable props —
onColumnAdd/onCardAdd(schema-reference),onSelectChange/onExpandChange(tree-view),onComplete(input-otp) — stale once #6124's tombstones land #7340 rejected), and the reader produced 4 word-boundary artifacts, 1 quoted key that breaks an existing counter-probe, 2 nested mis-attributions, 1 prose-in-table hit. - The alternative (finishing objectui#5867's ledger, 80 files / 89 blocks) contains exactly one
on*site, a correct live member — it removes none of this class.
Ruling (seat judgment under the runbook's rule that a card with no mechanism to wake it is closed, not held; the maintainer may reopen at no cost): not implemented. Per-instance handling stays objectui#7488's route (re-fence the block
ts, so a retired key is atscerror by construction). The dev's open question (a?-less type-member row is also invisible toDOC_MEMBER_RE; one instance, correct today) takes option A — left alone, recorded here, a real offender reopens it.Four-axis reading, as the dev put it and this seat concurs: 实际业务需求 — population 0, no pull; 长远合理性 — the PAIR RULE is trustworthy because it judges only rows that attribute to a shipped interface, and forcing the other 29 is the rejected name sweep; 防 AI 写错 — compiled blocks red on retired keys by construction, louder than a bespoke regex; 创业阶段不扩散 — a zero-consumer instrument earns no exemption for a class that "might recur".
Labels in one stroke:
pm:dispatchedoff, assignee cleared,finding+domain:devxretained;state_reason: not_planned. Report hygiene: 1 MCP call.
Generated by Claude Code
- The mechanism is real, proven with a paired control: objectui#7488's shape planted in a
Measured on
main52cac3886while landing objectui#7488, which is one instance of this class.objectui#7340 landed
packages/types/src/__tests__/component-docs-retired-handler-keys-7340.test.tsas the pin for exactly this class: a doc page that still teaches a handler key the contract
has retired to a
nevertombstone. It stayed green on objectui#7488's page for the wholeinterval, and the reason is structural rather than incidental.
The mechanism
The pin's doc reader recognises two shapes, both declaration-shaped:
DOC_MEMBER_RErequires the?— it matches a member DECLARATION (onSave?: string;),not an assignment. So an example object literal, which is how most pages actually teach
a schema:
matches neither shape, and the pin has nothing to say about it. It is not that the pin
"measures table rows and this happened to be prose" — the population it walks is every
.mdx/.mdundercontent/docs, this page included; the two regexes simply cannotexpress an assignment.
Why the other instruments do not cover the gap
check:doc-snippetscompilests/tsxfences only. A retired key inside a```plaintext (or
text/ `plain` / `txt` / no info string) fence is invisible to it.That is objectui#5867's population, and `check:doc-fences` carries it as a declared
SHRINK-ONLY ledger — so the block being hidden from the compiler is a KNOWN, BASELINED
state, not an unknown one.
check:doc-typesreadstypestring literals, nothing else.⇒ the intersection that nothing covers today: a retired handler key authored as an
example object literal inside a fence that is not
ts/tsx. Every page still holding acheck:doc-fencesledger entry is a place where this can sit green.The measurement this card owes
The PR for objectui#7488 dealt with its own instance by re-fencing that one block
ts, which putsthe literal under
check:doc-snippets(it then reportsTS2322: Type 'string' is not assignable to type 'undefined'per line). That works instance by instance. Widening thepin instead closes the class, and it is its own measurement, for the reason objectui#7488's
triage gave: the parse surface of example literals is much larger than that of declaration
rows, and the false-positive cost is unknown. Specifically it has to answer:
onSave: 'x',line matches inside anyobject anywhere on the page — including one that is deliberately showing the retired
dialect as a counter-example, or prose about the retirement itself. The pin already has
a PROSE rule (rule 5: it flags rows, never mentions) that would need an analogue.
heading or
interfacedeclaration; an object literal resolves its owner from its typeannotation (
const builder: ReportBuilderSchema = {), which the current reader does notparse. Without an owner there is no
(owner, key)pair, and the pin's PAIR RULE — thething that keeps a live runtime slot such as
ActionSchema.onClickfrom being swept —cannot run. A name-level sweep is the shape objectui#7340 explicitly rejected.
maintoday, before any change? Both counts: literals thatwould be flagged, and of those, how many are real (a retired pair) vs. counter-examples.
An alternative worth pricing in the same measurement: drive the class to zero through
check:doc-fencesinstead — every block that leaves that shrink-only ledger becomes acompiled block, and a retired key in a compiled block is a
tscerror by construction, nonew pin needed. That trades a new instrument for finishing objectui#5867's lane
(80 files / 89 blocks at
52cac3886).Provenance
Filed by the execution seat that landed objectui#7488, at the explicit request of that
card's triage comment, so the class does not reappear on a fourth page once that card lands. Cross-reference: objectui#7488 (the instance), objectui#7340 (the pin),
objectui#5867 /
check:doc-fences(the hidden-fence population), objectui#7344 (theretirement these keys belong to). Generated by Claude Code, session
session_01KbJQ1y1J12nZxYzFWhP8Q3.Generated by Claude Code