Skip to content

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

@claude

Measured on main 52cac3886 while landing objectui#7488, which is one instance of this class.

objectui#7340 landed packages/types/src/__tests__/component-docs-retired-handler-keys-7340.test.ts
as the pin for exactly this class: a doc page that still teaches a handler key the contract
has retired to a never tombstone. It stayed green on objectui#7488's page for the whole
interval, and the reason is structural rather than incidental.

The mechanism

The pin's doc reader recognises two shapes, both declaration-shaped:

/** An interface member row: `  onFoo?: (x: T) =` ... */
const DOC_MEMBER_RE = /^\s{0,8}(on[A-Z][A-Za-z0-9]*)\?:\s*(\S.*)$/;
/** A markdown prop-table row: `| onFoo | function | ... |` */
const DOC_TABLE_RE = /^\|\s*`(on[A-Z][A-Za-z0-9]*)`\s*\|\s*([^|]*)\|/;

DOC_MEMBER_RE requires 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:

const builder: ReportBuilderSchema = {
  showPreview: true,
  onSave: 'handleSaveReport',
  onCancel: 'handleCancel'
};

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 / .md under content/docs, this page included; the two regexes simply cannot
express an assignment.

Why the other instruments do not cover the gap

  • check:doc-snippets compiles ts / tsx fences 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-types reads type string 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 a
check:doc-fences ledger 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 puts
the literal under check:doc-snippets (it then reports TS2322: Type 'string' is not assignable to type 'undefined' per line). That works instance by instance. Widening the
pin 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:

  1. Which shapes count as an authored literal? A bare onSave: 'x', line matches inside any
    object 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.
  2. What owns the literal? The declaration-row reader resolves an owner from the enclosing
    heading or interface declaration; an object literal resolves its owner from its type
    annotation (const builder: ReportBuilderSchema = {), which the current reader does not
    parse. Without an owner there is no (owner, key) pair, and the pin's PAIR RULE — the
    thing that keeps a live runtime slot such as ActionSchema.onClick from being swept —
    cannot run. A name-level sweep is the shape objectui#7340 explicitly rejected.
  3. What is the population on main today, before any change? Both counts: literals that
    would 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-fences instead — every block that leaves that shrink-only ledger becomes a
compiled block, and a retired key in a compiled block is a tsc error by construction, no
new 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 (the
retirement these keys belong to). Generated by Claude Code, session
session_01KbJQ1y1J12nZxYzFWhP8Q3.


Generated by Claude Code

Activity

  1. added
    domain:devxobjectui devx stream: fix lands on .github/, scripts/ or release pipeline — devx lane cross-repo
    on Sep 5, 2026
  2. self-assigned this
    on Sep 6, 2026
  3. baozhoutao commented on Sep 6, 2026

    @baozhoutao
    Contributor

    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 main with real-vs-counter-example split), price the alternative it names (finishing objectui#5867's check:doc-fences ledger so every such block becomes a compiled block), and implement the widened objectui#7340 pin 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 over content/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 beside DOC_MEMBER_RE / DOC_TABLE_RE, owner resolved from the literal's type annotation, rules 2 and 5 kept) + an EMPTY-frontmatter changeset (@object-ui/types is published and a file under its src/ 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 to scripts/check-doc-fence-languages.mjs' ledger (that is #5867's lane); ⛔ no packages/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 under packages/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 on origin/main 0caacca37 at 14:07Z — the pin is 407 lines, DOC_MEMBER_RE at :182 still requires ?: and DOC_TABLE_RE at :184 a table row, so an example literal matches neither; KNOWN_UNHIGHLIGHTED_TS_FENCES carries 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 or claude/* 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 touch content/docs/api/schema-reference.md or packages/types/README.md, merge origin/main after #8064 lands first. pm:queue → pm:dispatched + assignee written in one stroke at 14:07Z and read back.


    Generated by Claude Code

  4. baozhoutao commented on Sep 6, 2026

    @baozhoutao
    Contributor

    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

  5. baozhoutao commented on Sep 6, 2026

    @baozhoutao
    Contributor

    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 @ objectui execution seat, PM session session_01FhBNJcLRZLe8M87VcUgpKr, R46, 2026-09-06T14:23Z. Report 5559840936 reviewed; the branch claude/issue-7840-retired-handler-key-literals sits at the base commit with no commits, as route (b) requires.

    What the measurement established (on 119802708, re-verified unaffected by the move to 3686a44cb):

    • The mechanism is real, proven with a paired control: objectui#7488's shape planted in a plaintext fence 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 compiled ts/tsx fences; the one hidden literal is a live onSubmit in a json fence.
    • 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 a tsc error by construction). The dev's open question (a ?-less type-member row is also invisible to DOC_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:dispatched off, assignee cleared, finding + domain:devx retained; state_reason: not_planned. Report hygiene: 1 MCP call.


    Generated by Claude Code

  6. removed their assignment
    on Sep 6, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    domain:devxobjectui devx stream: fix lands on .github/, scripts/ or release pipeline — devx lane cross-repofinding

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions