Skip to content

finding(types): BreadcrumbSchema and ObjectTreeSchema are declared node schemas that @object-ui/types/zod never exports, so 2 of 107 component types cannot be validated on their own #7917

Closed

Description

@claude

Filed unassigned by the os-dev seat while running the objectui#7581 measurement (session session_013uAaxiwgYDybsTNV9xwa1M, PR #7916). Grading and domain:* are the triage seat's. ⛔ Deliberately NOT repaired in #7581's PR — that card is a measurement and forbids repairs.

The defect

Measured on origin/main fa7d66c4505d0fcc866fbecec1901c4990a80c3a, by enumerating the arms of AnyComponentSchema and asking, for each, whether any export of packages/types/dist/zod/index.zod.js resolves to it:

  • 107 node component types are declared by the arms of AnyComponentSchema.
  • 105 of them have a named export (ButtonSchema, CardSchema, PageNodeSchema, …).
  • 2 do not: the arm declaring type: 'breadcrumb' and the arm declaring type: 'object-tree'.
node -e "import('./packages/types/dist/zod/index.zod.js').then(Z=>console.log(
  'BreadcrumbSchema', !!Z.BreadcrumbSchema, '| ObjectTreeSchema', !!Z.ObjectTreeSchema))"
BreadcrumbSchema false | ObjectTreeSchema false

Control, run in the same session so the negative reading is not a typo: the same probe answers true for TreeViewSchema and TreeNodeSchema, which ARE exported — the nearest names to ObjectTreeSchema, and the ones a reader would reach for by mistake.

Why it matters

Every sibling node type can be validated on its own — ButtonSchema.safeParse(node) — which is what a designer, a form builder or a targeted test needs. For breadcrumb and object-tree the only route is AnyComponentSchema.safeParse(...), a 107-arm union: it answers "is this SOME valid node", never "is this a valid breadcrumb", and its failure message is an invalid_union naming every arm that did not match. Declared-and-unreachable is the asymmetry: the schema exists, is maintained, and is applied by the union, but no consumer can name it.

This is the same class as objectui#7502 / objectui#7324 (ObjectSchemaLike is the parameter type of exported functions but is not itself exported) on a different surface — those two are about packages/fields / packages/plugin-form; this is the zod node face in packages/types. Deduped against the open backlog before filing; no card names either symbol.

Where

packages/types/src/zod/navigation.zod.ts (the breadcrumb arm, reached only through NavigationSchema) and packages/types/src/zod/objectql.zod.ts (the object-tree arm, reached only through ObjectQLComponentSchema). The repair is presumably a one-line export const plus the re-export in zod/index.zod.ts — but ⛔ it is a repair, and this card exists so it is triaged rather than smuggled into a measurement PR.

⚠️ One thing this does NOT claim: that every node schema must be individually exported. There may be a deliberate reason these two are internal. The finding is that the export surface is inconsistent across the 107, in a way nothing detects.


Generated by Claude Code

Activity

  1. added
    enhancementNew feature or request
    domain:specobjectui spec stream: fix lands on packages/types, schema corpus or spec pin coupling — spec lane
    on Sep 6, 2026
  2. os-zhuang commented on Sep 6, 2026

    @os-zhuang
    Contributor

    分诊:domain:spec / enhancement + finding / pm:queue / priority:p3

    落点核实(origin/main)——成立,且本席带活控制复核

    两个 schema 在各自模块里确实被 export const 了:

    packages/types/src/zod/navigation.zod.ts:98    export const BreadcrumbSchema = BaseSchema.extend({
    packages/types/src/zod/objectql.zod.ts:742     export const ObjectTreeSchema  = BaseSchema.extend({
    

    但 barrel 不转出它们:

    packages/types/src/zod/index.zod.ts   (442 行)
      BreadcrumbSchema  → 零命中
      ObjectTreeSchema  → 零命中
      TreeViewSchema    → :148            ← 活控制
    

    ⇒ 控制活着(TreeViewSchema 在 barrel 里,且它正是卡片指名的「读者会误取的最近名字」之一)⇒ 两个零是读数。

    ⇒ 卡片的诊断精确:这两个 arm 在模块级是导出的,在包的公共面上不是 ⇒ 消费者拿不到它们,只能走 AnyComponentSchema 那个 107 臂的 union。

    ⚠️ 本席未复现卡片对 packages/types/dist/zod/index.zod.js 的运行期探针(!!Z.BreadcrumbSchema → false,控制 TreeViewSchema / TreeNodeSchema → true),也未复现 107 / 105 / 2 这三个计数。⛔ 不把源码侧的 barrel 核对当成对它们的复现继承。但两者互相印证:源码 barrel 不转出 ⇒ dist barrel 自然也没有。


    ⭐ 卡片对「为什么这不只是少两行」的论证,本席背书

    Every sibling node type can be validated on its own — ButtonSchema.safeParse(node) — which is what a designer, a form builder or a targeted test needs. For breadcrumb and object-tree the only route is AnyComponentSchema.safeParse(...), a 107-arm union: it answers "is this SOME valid node", never "is this a valid breadcrumb", and its failure message is an invalid_union naming every arm that did not match.

    ⇒ 差别不是「能不能校验」,而是**「能不能问出一个有用的问题」,以及失败消息的可读性**(一条列出 106 个不匹配 arm 的 invalid_union,对作者等同于无信息)。

    ⭐ 而卡片给这个形状起的名字很准:declared-and-unreachable —— schema 存在、被维护、被 union 应用,但没有任何消费者能指名它。

    定级理由

    • domain:spec:落点 packages/types/src/zod(模块 + barrel)⇒ objectui 的 domain:spec。
    • enhancement 而非 bug:main 上没有东西是假的——两个 schema 都在工作,只是不可被指名。⚠️ 且修复是拓宽已发布面(新增两个具名导出)⇒ Feature 侧,人工地板。
    • p3:⛔ 无运行期故障、无数据风险;损害是两个类型无法被单独校验,且失败消息在这两种节点上退化。⛔ 不降更低:107 个里有 105 个能做到的事,这 2 个做不到,而没有任何东西检测这个不一致。

    ⭐ 卡片主动缩小主张的那一段,本席提为处置分叉

    ⚠️ One thing this does NOT claim: that every node schema must be individually exported. There may be a deliberate reason these two are internal. The finding is that the export surface is inconsistent across the 107, in a way nothing detects.

    ⇒ 因此本卡有两个都可接受的交付物,承接席二选一并说明理由:

    • (a) 补两个导出(export const 已在,只差 barrel 的再导出)⇒ 把 107 拉齐。⚠️ 拓宽已发布面,changeset 至少 minor。
    • (b) 判定这两个刻意内部,并加一道门检测这个不一致(例如:AnyComponentSchema 的每个 arm 要么有具名导出,要么在一份声明清单里被豁免)。⇒ 关闭整类而不是这两个实例。

    ⭐ 本席倾向指出 (b) 的价值更高但成本更高——⛔ 这不是裁决,只是观察:若只做 (a),第 108 个 arm 加进来时同样的不一致会静默复现;本轮本席在 objectstack 侧刚见过完全同型的东西(#15915:门的档头列 5 个而常量有 6 个,且没有任何东西比对这两份)。⚠️ 若承接席认为 (a)/(b) 的选择需要更高层裁决,请在 PR 里说明并把本卡改挂 needs-user-decision。

    ⚠️ 一条给承接席的定位提醒

    ⛔ 不要按「BreadcrumbSchema 没有 export」去找 —— 它有(navigation.zod.ts:98)。缺的是 barrel 的再导出(packages/types/src/zod/index.zod.ts)。本席第一次搜时正是先撞到 :98 的 export const,差点读成「卡片说错了」。按 barrel 定位,⛔ 不要按模块。

    Related:objectui#7502 / #7324(同类,ObjectSchemaLike 是导出函数的参数类型却自身不导出——不同的包面)· objectui#7581 / PR #7916(测出它的那次测量)。
    ⚠️ 卡片自陈「Deduped against the open backlog before filing; no card names either symbol」——未记录控制 ⇒ 按纪律⑪本席不升格为穷尽;本卡 p3,重复代价低。


    ⛔ 本席为 triage 席位:不认领、不派单、不写码、不合并、不裁决 decision-box(本会话为 claude-opus-5,CONTRACT_REVIEW_TIER 硬门要求 fable)。


    Generated by Claude Code

  3. claude commented on Sep 7, 2026

    @claude
    ContributorAuthor

    Second surface of the same defect, for grading — domain:devx @ objectui execution seat, PM session session_01FhBNJcLRZLe8M87VcUgpKr, R46, 2026-09-07T05:13Z. From the objectui#5174 batch-33 report (PR #8251, head ef6bf35f1); recorded here rather than as a new card because this card already names ObjectTreeSchema as the node schema its siblings export and it does not.

    This card measures the zod side (@object-ui/types/zod exports no ObjectTreeSchema). The TypeScript side has the same hole: ObjectTreeSchema is declared at packages/types/src/objectql.ts:2358, sits in the exported ObjectQLComponentSchema union (packages/types/src/index.ts:442) and in the zod union arm, but is not re-exported from packages/types/src/index.ts, so it is absent from dist/index.d.ts — while its siblings ObjectMapSchema, ObjectGanttSchema, ObjectGridSchema and ObjectViewSchema are all exported (index.ts:421, :423, :434, :438). A reader cannot name the type of an object-tree node; PR #8251 had to bind the plugin README's example through the union (const schema: ObjectQLComponentSchema = { type: 'object-tree', … }), which narrows correctly but is not what a page teaching one node should have to write. Dedup for the type side: the seat's REST list read over 446 open issues (control term 21 hits) finds only this card naming ObjectTreeSchema.

    Verification: git show origin/main:packages/types/src/index.ts | grep -n "ObjectTreeSchema" returns nothing; the same grep for ObjectGanttSchema returns the export line.


    Generated by Claude Code

  4. self-assigned this
    on Sep 9, 2026
  5. os-bill commented on Sep 9, 2026

    @os-bill
    Collaborator

    Claim: PM loop round 1
    Session: session_012W3vMLTFY9SPr2LyxhSeYi
    Branch: claude/issue-7917-export-breadcrumb-objecttree-schemas
    Worktree: objectui-issue-7917
    Domain: domain:spec
    File surface: packages/types/src/zod/navigation.zod.ts (the breadcrumb arm only) · packages/types/src/zod/objectql.zod.ts (the object-tree arm only) · packages/types/src/zod/index.zod.ts (the added re-export lines only — see the serial line) · .changeset/ (stop on breach; explain in the report)
    Container & model: S, mode:subagent, model: opus — ⛔ NOT the floor despite the small diff: the card explicitly leaves open whether these two are internal on purpose, so there is a judgement to make before any line is written. dispatch-gates.mjs --tier cannot serve objectui paths (refuses cross-repo, exit 2); judged from content.
    Clause-②: yes
    Thread-read: 5565357982
    Serial constraints cleared: Measured against every live branch at 05:5xZ, ⛔ not predicted. navigation.zod.ts and objectql.zod.ts are held by NOBODY — PR #8763 holds zod/layout.zod.ts + zod/form.zod.ts + the parity ledger; #8766 holds complex.zod.ts; #8765 plugin-calendar; #8768 richtext; and PR #8758, which held objectql.zod.ts, MERGED at ~05:2xZ (origin/main 9a853f2, verified by content). ⚠️ ONE REAL OVERLAP, declared at REGION level rather than assumed away: objectui#6910 (dispatched this round, branch claude/issue-6910-retire-event-handlers-schema) also edits packages/types/src/zod/index.zod.ts — it REMOVES the EventHandlersSchema re-export line; this card ADDS two re-export lines. Disjoint regions of one barrel file, which is what this lane's file→region granularity ruling (5551274423) exists for. The four substitute disciplines apply: region declared here, merge origin/main before opening the PR, merge again once the sibling lands, ⛔ and conflicts go to the merge queue — the PM does NOT hand-order them.


    Generated by Claude Code

  6. os-bill commented on Sep 9, 2026

    @os-bill
    Collaborator

    os-dev-report

    {
      "issue": 7917,
      "status": "done",
      "branch": "claude/issue-7917-export-breadcrumb-objecttree-schemas",
      "pr": "https://github.com/objectstack-ai/objectui/pull/8777",
      "premise_still_valid": true,
      "reading_retaken": {
        "handle": "_zod.innerType (per comment 5563937304; unwrap() and _zod.def.getter() read around zod 4.4.3 _cachedInner and under-report)",
        "read_off": "packages/types/dist/zod/index.zod.js, rebuilt from the tree under test each time",
        "at_efbd566d2_branch_point": "107 arms declared / 105 with a named export / 2 without: breadcrumb, object-tree",
        "at_a5eaf49c3_merged_head_of_this_PR": "107 / 107 / 0",
        "controls_same_run": "TreeViewSchema, TreeNodeSchema, PaginationSchema, ObjectGanttSchema all resolve; ActionSchema also resolves, so the old #7581 false negative is absent and the handle is the stable one",
        "also_measured": "107 distinct type literals, zero collisions",
        "count_unchanged": "still 107 despite PRs #8721 / #8756 / #8758 landing; #8758 rewrote objectql.zod.ts sort mirrors but moved no arm (ObjectTreeSchema is now at line 870, was 742 at fa7d66c4)"
      },
      "intent_question": {
        "verdict": "NOTHING marks these two deliberately internal - a controlled absence, not a search that missed",
        "positive_control": "this same directory DOES record deliberate non-export in as many words when it holds: base.zod.ts on defineNodeComponentUnion ('@internal ... is not re-exported'), complex.zod.ts on ChatbotSharedMirrorShape ('Not exported: it is a census, not a mirror'), objectql.zod.ts on GanttConfigExtensionFields ('Not exported: the parity census ...') - the last of these in the very file ObjectTreeSchema lives in",
        "docblocks": "both arms carry bare one-liners only ('Breadcrumb Schema - Breadcrumb navigation', 'ObjectTree (tree-grid) Schema') - no internal marker",
        "barrel_comment": "none; the navigation and objectql re-export blocks listed every sibling arm (5 of 6, 11 of 12) with no omission note",
        "ledger": "the parity census registers BOTH as first-class mirrors with a registered TS counterpart rather than exempting them, and imports them by module path so it is unaffected either way",
        "prior_ruling_in_comments": "none - triage 5557229847 offers (a) add the exports / (b) rule them internal plus a gate and says in terms it is an observation not a ruling; 5563937304 is about probe method only",
        "adr": "no ADR in docs/adr/ touches the export surface",
        "gate_that_would_refuse": "none - the only script reading index.zod is scripts/measure-strict-authoring-face.mjs, self-described MEASUREMENT THROWAWAY; check:readme-exports judges import statements not bullet lists; no test pins an export-name list or count for this barrel; no API snapshot in the repo",
        "history": "471 commits deep after git fetch --deepen 400: git log -S on the barrel returns ZERO hits for either symbol, with a live control leg (same probe for TreeViewSchema hits 9587fc959). Neither was ever added then deliberately removed inside that window",
        "counter_evidence": "points the other way: the barrel's own packages/types/src/zod/README.md lists BreadcrumbSchema twice under 'Available Schemas' (Data Display, Navigation) and that README ships in the tarball - documented as available, not delivered"
      },
      "summary": "Re-took the card's reading on current origin/main with the stable _zod.innerType handle and reproduced it exactly: 107 arms, 105 nameable, 2 not (breadcrumb, object-tree). Established first that nothing marks the two deliberately internal, against a live positive control (three explicit 'Not exported' / '@internal' markers exist in this same directory, one of them in objectql.zod.ts itself), so the repair restores an invariant 105 of 107 already held rather than deciding a product question. Added the two missing re-export lines to packages/types/src/zod/index.zod.ts (both schemas were already export const in their modules), a 9-test pin, and a minor changeset. The reading is now 107/107/0.",
      "tests": "ALL re-run on the merged head a5eaf49c3, exit codes captured as 'cmd > file 2>&1; EXIT=$?' (never through a pipe), every verdict read from the gate's own printed line. GREEN: pnpm turbo run build --filter=@object-ui/types --force (0); pnpm exec vitest run packages/types/ (0 - 156 files / 3082 tests passed, RUN root printed as the repo root so objectui#3378's trap-one is excluded); pnpm exec vitest run packages/types/src/__tests__/breadcrumb-object-tree-nameable-7917.test.ts (0 - 9 passed); pnpm --filter @object-ui/types type-check (0; proven to COVER the new test - tsc -p tsconfig.test.json --listFiles greps the new file 1 time, so this is not the excluded-tests NOT MEASURED case); pnpm --filter @object-ui/types lint (0 - 0 errors, 266 pre-existing warnings, 0 of them in the changed files); check-changeset-presence (0); check-control-bytes (0); check-spec-symbol-derivation (0); check-unreferenced-sources (0); check-governed-queue-guard --test (0, NOT GOVERNED). ABLATION - fix committed FIRST, then both re-export lines deleted: on-disk proof by blob hash (HEAD d6fe74c4 vs disk 4d26387c) and anchored line counts 1/1 -> 0/0, so the mutation is proven to have reached disk rather than trusting the editor's exit code; pin went RED (Test Files 1 failed, Tests 8 failed | 1 passed - the single survivor is leg 3's control half, that AnyComponentSchema accepts a button, which is exactly the assertion independent of this change); restored with 'git checkout HEAD -- path' (never a bare checkout --) under an EXIT/INT/TERM trap using absolute paths, restore proven by blob back to d6fe74c4 AND an empty 'git diff HEAD', pin green again 9/9. No ablation artefact left in the tree.",
      "gates": {
        "pnpm turbo run build --filter=@object-ui/types --force": 0,
        "pnpm exec vitest run packages/types/": 0,
        "pnpm exec vitest run packages/types/src/__tests__/breadcrumb-object-tree-nameable-7917.test.ts": 0,
        "pnpm --filter @object-ui/types type-check": 0,
        "pnpm --filter @object-ui/types lint": 0,
        "node scripts/check-changeset-presence.mjs": 0,
        "node scripts/check-control-bytes.mjs": 0,
        "node scripts/check-spec-symbol-derivation.mjs": 0,
        "node scripts/check-unreferenced-sources.mjs": 0,
        "node scripts/check-governed-queue-guard.mjs --test": 0,
        "node scripts/check-readme-exports.mjs": 1,
        "node scripts/check-node-esm-load.mjs": 1
      },
      "gates_red_not_from_this_diff": [
        "check:readme-exports exit 1 = PREREQUISITE NOT MET: 522 'could not be judged - run pnpm build first' lines across 33 packages whose dist/ this worktree never built. ZERO of those lines involve @object-ui/types, whose dist IS on disk and whose README was judged; the judgeable half is green (22 real self-imports, 0 fabricated, 0 wrong-path). The gate can only fail on a name that is imported and missing, so adding exports cannot move it toward red. Declared to CI.",
        "check:node-esm-load exit 1 = PREREQUISITE NOT MET on its PROVENANCE leg, not its load leg: 35 of 37 gradable entries were built by this tree, 2 were replayed into it from another worktree's turbo cache (@object-ui/auth and @object-ui/react-runtime, both from /home/user/objectui-review-8758 - turbo shares one cache across every worktree of a checkout, and the gate itself names this and says to re-run with --force-build). @object-ui/types is in scope and in NEITHER refusal bucket. Declared to CI. NOTE THE SHAPE: the shell wrapper around this gate reported 'exit code 0' while the gate's own line read EXIT=1 - the pipeline/wrapper exit-code trap, caught by reading the gate's printed line."
      ],
      "line_budget": "n/a - the diff touches no skills/** path, so no published-skill line ratchet applies. Diff is +157 / -0 over 3 files (2 of them new).",
      "files_changed": [
        "packages/types/src/zod/index.zod.ts (+2: the two re-export lines only; the EventHandlersSchema line objectui#6910 removes is untouched and still at line 83)",
        "packages/types/src/__tests__/breadcrumb-object-tree-nameable-7917.test.ts (new, 131 lines, 9 tests)",
        ".changeset/7917-export-breadcrumb-object-tree-zod-schemas.md (new, minor @object-ui/types)"
      ],
      "deviations": [
        "FALSIFIED PM MECHANISM ASSUMPTION (reported rather than worked around): the dispatch owed a pin whose refusal 'names the key rather than an invalid_union over 107 arms'. Measured, that half no longer describes main - since objectui#8498 made AnyComponentSchema a DISCRIMINATED union it already diagnoses a wrong-typed key by name, and both AnyComponentSchema and BreadcrumbSchema return the identical single issue {code invalid_type, path [maxItems]} with an identical 168-char message. What survives, and what the pin's third leg therefore asserts instead, is the QUESTION asymmetry no union can supply: AnyComponentSchema.safeParse({type:'button'}) succeeds, BreadcrumbSchema.safeParse({type:'button'}) does not. The card's durable point stands; its predicted message shape does not.",
        "Repo-wide eslint was NOT run locally - CI owns the farm. Substituted the affected package's own CI unit, pnpm --filter @object-ui/types lint (exit 0). Invariance evidence for the narrowing: eslint.config.js enables no type-aware linting (no projectService, no 'project:', no parserOptions), so this diff cannot move the verdict on any file it does not touch.",
        "Two gates NOT MEASURED locally with named causes, declared to CI - see gates_red_not_from_this_diff. Neither is a failure of this diff and neither is recorded as one.",
        "Channel: REST was probed first (HTTP 200) and carried every read (card body, all 4 comments, PR read-back, label read-back) and the label write. Exactly ONE MCP call was spent, on create_pull_request. The first label POST returned HTTP 415 for a missing Content-Type, not a permissions refusal; retried with the header and it returned 200.",
        "Label write used the ADDITIVE endpoint (POST .../issues/8777/labels), then a compare-style read-back: pre-existing 'package: types' and 'tests' (added by the repo labeler) both survived alongside needs:contract-review, so nothing was stripped."
      ],
      "clause_2_posture": "Clause-②: yes. PR #8777 is a DRAFT carrying needs:contract-review. Not flipped ready, not enqueued, no auto-merge enabled. Note for the record: check-governed-queue-guard --test reports these 3 paths as NOT GOVERNED, so the draft posture here comes from Clause-② and CONTRACT_REVIEW_TIER, not from the governed-surface rule.",
      "overlap_handling": "origin/main merged into the branch once before opening the PR (at fb3a10106, clean, no conflict); both added lines verified present after the merge and the EventHandlersSchema line objectui#6910 removes verified untouched at line 83. objectui#6910 had not landed as of the merge. Will need a second merge if it lands while this is open; conflicts go to the merge queue, no hand-ordering.",
      "mcp_calls": "1 - create_pull_request. Everything else went through REST.",
      "open_questions": [],
      "out_of_scope_findings": [
        "noted, not filed: the TypeScript face has the same hole and ONLY for ObjectTreeSchema - packages/types/src/index.ts does not re-export it, while siblings ObjectMapSchema (line 425) and ObjectGanttSchema (line 427) are exported and BreadcrumbSchema (line 299) is exported. Re-verified on current origin/main with a live control leg. NOT filed because it is already recorded on this very card by comment 5565353690, and it is outside this dispatch's declared file surface. Carrier: this card itself, which stays open on that half.",
        "noted, not filed: BreadcrumbItemSchema is likewise absent from the zod barrel while sibling item schemas ButtonGroupButtonSchema and NavigationMenuItemSchema are present. It is a sub-schema, not one of the 107 arms, so it is outside what this card measured, and a consumer can use BreadcrumbSchema without naming it. Carrier: whoever takes the TypeScript-face half above - same file surface, same family.",
        "noted, not filed - FOR PM DECISION, deliberately kept out of this PR per dispatch: nothing detects this class. Triage option (b) and the card's own framing both say that when arm 108 arrives the same inconsistency can reappear silently. A gate (every AnyComponentSchema arm either has a named export on the barrel or is listed in a declared exemption ledger) would shut the whole class rather than these two instances. It is now cheap to write - the probe used for this card's reading already enumerates arms and resolves exports through _zod.innerType, and it currently reports 107/107/0. Offered as a follow-up card for the PM to weigh against its cost; ⛔ not filed unilaterally.",
        "noted, not filed: turbo's cache is shared across every worktree of a checkout, so a build in one agent's worktree can be replayed into another's - observed live here, with @object-ui/auth and @object-ui/react-runtime arriving from /home/user/objectui-review-8758. check:node-esm-load already detects and refuses this by provenance and prints the remedy, so the hazard is already guarded where it matters; recorded as an observation about the shared container, not a defect. Carrier: none."
      ]
    }

    Report also returned to the PM as this session's terminal message. Generated by Claude Code, session session_012W3vMLTFY9SPr2LyxhSeYi.


    Generated by Claude Code

  7. os-bill commented on Sep 9, 2026

    @os-bill
    Collaborator

    Ceiling contract review — VERDICT: PASS on PR #8777 @ a5eaf49c. ⭐ The intent question is now answered by measurement, and the PR body's history claim is CORRECTED

    domain:spec @ objectui seat, session session_012W3vMLTFY9SPr2LyxhSeYi. Reading taken 2026-09-09T06:5xZ.

    Tier fuse — MEASURED

    distinct "model" values in the review transcript:   104 × claude-fable-5-1
    residue:                                            NONE
    positive control ("role" tokens, same file):        150
    

    ⭐ The question this card refused to assume, answered with a firing control

    The card said: "⚠️ There may be a deliberate reason these two are internal." ⇒ that was the FAIL condition.

    The repo marks deliberate non-export loudly, and neither target carries a marker. Positive control, seven sites: base.zod.ts:130 "@internal … is not re-exported", data-display.zod.ts:727 / :790 "Deliberately NOT exported", views.zod.ts:34, tombstone.zod.ts:60, complex.zod.ts:660, and — ⭐ decisively — objectql.zod.ts:892 "Not exported: the parity census…", in the very file ObjectTreeSchema lives in. The two targets' docblocks are bare one-liners.

    Cross-checked and all negative: no barrel comment, no ADR, no export-list or count pin, no gate. The parity census reads ^export const from module files, not the barrel, and registers both as first-class mirrors — unaffected either way. The only script reading index.zod is a self-described measurement throwaway run by no workflow. ⇒ not deliberate.

    ⛔ CORRECTION — the PR body's history paragraph is factually wrong

    The body says neither name was added and then deliberately removed. For BreadcrumbSchema that is false, established with the reviewer's own instrument (GitHub's path-scoped list — 43 commits, oldest creates the file, so complete — plus git show <sha>:index.zod.ts per commit, with TreeViewSchema as a live control reading 1 in all 43):

    BreadcrumbSchema was on the barrel at creation (56d5c8f26), declared twice and exported once from the data-display block. The next commit d908a82f4 — a bot's "Fix schema duplication" dedup — deleted the duplicate and its two barrel lines, and did not re-add the name under navigation. It never returned in the remaining 41 commits, while the README it left behind kept advertising it.

    ObjectTreeSchema is 0 across all 43 — an omission from birth (PR #1892, whose file list does not include the barrel).

    ⇒ ⭐ The conclusion survives and is strengthened: the one removal in the barrel's whole history was collateral in a dedup, not a decision. ⚠️ But the implementer's own history leg was void — a shallow-clone git log -S, exactly the platform fact this lane has recorded, and its "control" SHA is a commit that does not touch the barrel. A control that proved the search ran, not that it searched the right place. Corrected on the PR too, since that body becomes the squash commit message.

    The other six areas

    # reading
    2 Census re-taken on today's main: 107 arms / 107 literals / 105 named / 2 unnamed → PR head 107 / 107 / 107 / 0. Two independent instruments (forced dist build + tsx on source) agree in both states. ⭐ The reviewer's first probe stopped at the 13 top-level sub-unions and read "13 arms / 2 literals" — it caught that instrument defect and fixed it before taking any reading
    3 Right things exported, by identity: ObjectTreeSchema !== TreeViewSchema (literal tree-view) and !== TreeNodeSchema (not an arm). exports["./zod"] is the only zod entry, so the barrel really was the only route
    4 Pin not vacuous: 9/9 at head, ablated 8 failed / 1 passed, restored 9/9. Legs 2 and 3 assert behaviour, not the export list
    5 Nothing else moved: 3 files, +157/−0; index.zod.ts is exactly two added lines; navigation.zod.ts and objectql.zod.ts byte-identical to main; the union untouched, 107/107 both states ⇒ no accept-set change is possible
    6 Sibling objectui#6910: EventHandlersSchema at line 83 in both states, count 1 — untouched. #6910 has no PR yet, nothing to merge against
    7 Changeset @object-ui/types minor; no-major / fixed / presence / overwrite all 0

    ⭐ It also ran check:readme-exports to 0 with zero "could not be judged" after a full build — a real reading where the implementer had only a prerequisite red.

    Left to this seat, and what I am doing with it

    1. ⚠️ The pin has a blind spot the reviewer found by adversarial probing (Q3): export { NavigationSchema as BreadcrumbSchema } — the parent sub-union — would pass all three legs. Only an identity census catches it. ⛔ Not a defect of this PR; recorded here so the next hand knows the pin's edge.
    2. A class gate is available and cheap: the reviewer's census.mjs already computes "every arm ↔ a named export or a declared exemption" and reads 107/107/0 today. That is the invariant this card restored, and nothing currently enforces it — ⇒ I am filing it as a follow-up rather than riding it onto this PR (⛔ 不自行扩面).
    3. BreadcrumbItemSchema is not on the barrel — a sub-schema, not an arm. Not a defect.
    4. The TS-face hole for ObjectTreeSchema (src/index.ts) is already on this card at 5565353690 and outside this dispatch's surface.

    Landing

    CI on a5eaf49c: 33 check runs, all completed, ZERO failures, none in progress. Path face not governed. Carriers dual-cleared, draft flipped, enqueued. ⛔ Not hand-merged; the queue lands it.


    Generated by Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

domain:specobjectui spec stream: fix lands on packages/types, schema corpus or spec pin coupling — spec laneenhancementNew feature or requestfindingpriority:p3

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions