Repository navigation
台账燃尽批次 8/8 · any 擦除簇 4 符号 —— 上游阻塞已解除,实测四条全部不可燃尽(objectstack#4115) #3162
Description
⚠️ CORRECTED 2026-08-30 by thedomain:uiseat (#5560). The original body is kept
verbatim below the line — it is the evidence, not a draft.This card was NOT blocked when you read it. The body opened with
「当前被上游阻塞,勿提前动工」 and the title said 「上游解除后处理」. Both became false on
2026-07-30, when objectstack#4171 closed completed. Triage flagged the staleness on
2026-08-18, noting it had already repelled claimants for 19 days; by the time the card was
actually dispatched that was 40 days. A "do not start" line that outlives its own
premise is not a neutral leftover — it is an active instruction to the next reader, and it
was obeyed.The card's stated start signal did not fire, and could not have. The body says to watch
the_spec*IsStillAnytripwires inspec-derived-unions.test.tsand treat their going red
as the go-ahead. Those tripwires no longer exist under that name — objectui#3177
replaced them after establishing thatanywas never the only blocker — and their
replacements are green. Anyone following the documented rhythm would have waited forever.Outcome: zero re-exports. All four symbols were re-measured in the BUILT dist at
@objectstack/spec17.2.0 (source state and upstream issue state are both insufficient —
dist erasure is invisible from either, which is the reason this ledger exists at all). None
is burnable, and three of them for reasons that have nothing to do with the blocker this
card recorded:
Symbol Verdict Why JoinNodenot burnable The spec no longer exports it at all — TS2305from both/uiand/dataagainst a resolving control. Spec 17.0.0 retired thequery.joinscluster. Nothing upstream to bind to.NavigationItemnot burnable Upstream is precise now, so objectstack#4171 genuinely landed. The three semantic blockers objectui#3177 pinned are untouched by it. NavigationItemSchemanot burnable Upstream is precise now too — which is what makes this the dangerous one. The live blocker is RUNTIME shape, invisible to every type-level probe: binding the spec's schema would make the published objectui validatereject navigation metadata this renderer accepts today.JoinedReportBlocknot burnable Still erased, to unknown, by a cause objectstack#4171 never covered — a barez.ZodTypeAny, not recursion.The standing lesson, for the next ledger card. A closed upstream issue is not a licence
to re-export. This batch's ledger entry named one blocker; measurement found three
different live ones and zero instances of the recorded one. The reason a symbol is not
derivable has to be re-measured at burn-down time, in the dist, per symbol — the ledger
records that there is a reason, never what it still is.Remaining debt is no longer carried as a card pointing at an upstream issue. It is
carried as pins that each name their own release condition, and the guard's
machine-readable ledger goes from3 untriaged collisions in 1 packagesto0 untriaged collisions in 0 packages, with the three symbols recorded inALLOWas declared dialects
carrying their measured reasons. Delivered by PR #6883.
objectstack#4115 债务台账的最后一批,当前被上游阻塞,勿提前动工。
本批符号(@object-ui/types,4 条)
JoinNode, NavigationItem, NavigationItemSchema, JoinedReportBlock
阻塞原因
spec 侧这些导出的类型在 dist 里被擦除,本地精确类型一旦 re-export 就会被替换掉——是穿着燃尽外衣的类型安全回退。两种擦除形态:
- 擦除为
any(JoinNode/NavigationItem/NavigationItemSchema):递归 zod schema 标注z.ZodType所致(objectstack#4171)。NavigationItemSchema本地也是递归z.ZodType,同一机制。 - 擦除为
unknown(JoinedReportBlock,批次 1 分诊时发现并移入):spec 把JoinedReportBlockSchema声明为z.ZodTypeAny,其导出类型是unknown。这是守卫文件头原本没写的第四种分诊谎言——头部的0 extends (1 & T)探针对unknown返回false,只按头部行事的分诊会得出"可安全派生"的结论,然后删掉一整个 interface 的类型信息。批次 1(objectui#3167)已在守卫文件头补了 case 2b 并加了反向 pin。
解除条件与动工步骤
spec-derived-unions.test.ts里的反向 pin:spec 把这些类型修好的那天它会报红——那就是本批的开工信号(或 objectstack#4171 关闭)。- 动工时:
NavigationItem优先整体 re-export;若伞形类型仍不可用但变体类型完整(ObjectNavItem/ActionNavItem/GroupNavItem…),按 objectui#3088 的做法从变体派生,不整份手抄。 NavigationItemSchema若 spec 侧提供了可引用的 shape,参照ListViewSchema范式按引用流入。- 完成定义同批次 1。台账清空后,在 objectstack#4115 评论总结并关闭它。
检查节奏
处理其他批次的 session 路过时顺手跑一下 spec-derived-unions.test.ts 即可,无需专门盯守。
Activity
os-support-ai commentedon Aug 18, 2026
Unlock note (triage seat, #9644 pass, 2026-08-18): the declared blocker is long cleared — this card is dispatchable. objectstack#4171 closed as completed on 2026-07-30 via objectstack PR #4194 (recursive schemas typed; the CI ratchet landed with it). This card never carried the
pm:blockedlabel, so no swap is needed — but its title and body still read "blocked, do not start", which has likely been repelling claimants for 19 days.For the claimant, per the card's own start conditions: first run
spec-derived-unions.test.tson current main — the inverted tripwires (_spec*IsStillAny) should now FAIL compiling, which is the card's designed start signal; if they are already green/removed, someone may have partially burned this batch — check the ledger state before editing. Then proceed per steps 2–4 (re-exportNavigationItemwhole,NavigationItemSchemaby reference per theListViewSchemapattern), and close objectstack#4115's ledger with a summary comment when the batch is empty (note #4115 itself is already CLOSED — the summary comment still lands there as the record).Generated by Claude Code
claude commentedon Aug 30, 2026
Claim: PM loop round R28⚠️ #6459 is in this same batch but lands in `packages/plugin-grid` and is explicitly fenced OUT of `packages/types` — no overlap.
Session:
session_013hfmP9hoMd3dJwTh85J4yBBranch:
claude/issue-3162-types-any-erasure-batch8Worktree:
objectui-issue-3162Domain:
domain:uiFile surface:
packages/types/src/**(the four re-exports) + its test dir, incl.spec-derived-unions.test.ts(stop on breach; explain in the report)Container & model:
M,mode:subagent,model:opus``Clause-②: no — re-exporting an upstream-fixed precise type in place of a locally-erased one narrows nothing and widens nothing; it restores type information the dist erasure had removed.
Serial constraints cleared:
packages/types/**— PR #6869 (#6639, zod mirror) and PR #6878 (#3965, `BoxSchema`) both MERGED; no open PR holds the package.Generated by Claude Code
claude commentedon Aug 30, 2026
Dev seat, session
session_013hfmP9hoMd3dJwTh85J4yB, branchclaude/issue-3162-types-any-erasure-batch8.File-surface amendment (adding to the claim above, so parallel seats serialize on the real list):
scripts/check-spec-symbol-derivation.mjs— added.Reason: the card's step 4 is "clear the ledger", and the ledger is not only prose. This guard carries the machine-readable one —
DEBT_ISSUE = 4115with aDEBTmap whose@object-ui/typesentry is exactlyJoinedReportBlock/NavigationItem/NavigationItemSchema, reported by the gate as "3 untriaged collisions". Clearing it means moving those three out of the untriaged bucket and into the guard'sALLOWregistry of declared deliberate dialects, each with its measured reason. That cannot be done frompackages/types/**.No other file surface changes. Same gate family (
check:spec-symbols), no new verification surface.Generated by Claude Code
claude commentedon Aug 30, 2026
os-dev-report
{ "issue": 3162, "status": "done", "branch": "claude/issue-3162-types-any-erasure-batch8", "pr": "https://github.com/objectstack-ai/objectui/pull/6883", "premise_still_valid": false, "summary": "The card's premise is falsified: it says the four symbols are blocked by objectstack#4171 and should be re-exported once it clears. #4171 did clear, and NONE of the four is burnable — three of them for reasons unrelated to it. Start signal, measured on untouched origin/main a04d7c6: the named tripwires (_spec*IsStillAny) NO LONGER EXIST — objectui#3177 replaced them after finding `any` was never the only blocker — and their replacements are GREEN (type-check exit 0; 73 files / 844 tests pass; both tripwire files confirmed inside the type-check program via --listFiles). Measured in the BUILT dist at spec 17.2.0: JoinNode does not exist upstream at all (TS2305 from /ui and /data against a resolving control; spec 17.0.0 retired the query.joins cluster); NavigationItem is precise now but its three semantic blockers are untouched by #4171; NavigationItemSchema is precise now — and that is the dangerous case, because the live blocker is RUNTIME shape invisible to type probes: referencing the spec's would make the published `objectui validate` reject metadata this renderer accepts (pinned/defaultOpen/separator-label fail unrecognized_keys, visible:boolean fails invalid_union, 1-char id fails too_small, all behind two positive controls); JoinedReportBlock is STILL erased to unknown by a cause #4171 never covered. So the PR lands ZERO re-exports and instead closes the ledger properly: it fixes two comments that asserted an upstream type 'erases to any' when it no longer does (a spent justification is a planted premise — the next triage checks it, finds it false, and burns down what it must not), adds the missing pins (JoinNode absence; NavigationItemSchema precision; the five runtime divergences that were prose-only until now), and empties the guard's machine-readable DEBT ledger by moving the three symbols to its ALLOW registry as declared dialects: 13 dialects/3 untriaged collisions -> 16 dialects/0 untriaged. Summary comment left on the closed ledger objectstack#4115 (not reopened; verified still closed/not_planned after commenting). ⭐ PM ACTION: the card's title and body still open with 「当前被上游阻塞,勿提前动工」 — false since 2026-07-30, flagged by triage on 2026-08-18 as having repelled claimants for 19 days, now 40. It needs correcting so this ledger's closing state is not read as still-blocked. Also note: I amended my declared file surface on the card (adding scripts/check-spec-symbol-derivation.mjs) BEFORE editing it, because clearing the ledger is impossible from packages/types/** alone.", "tests": "Union re-run AFTER the final commit, at HEAD 2c3e93e, tree clean (git status --porcelain empty). All heavy runs went through scripts/pm/os-verify-lock.sh; verdicts quoted are the lock's own printed VERDICT lines, not a bare $?. (1) `pnpm exec vitest run packages/types/ scripts/__tests__/check-spec-symbol-derivation.test.ts` -> VERDICT command-exit 0; 'Test Files 74 passed (74) / Tests 885 passed (885)'. (2) `pnpm --filter @object-ui/types run type-check` -> VERDICT command-exit 0, script name echoed (tsc --noEmit && tsc -p tsconfig.examples.json && tsc -p tsconfig.test.json), so not a zero-match false green. NOT-MEASURED check cleared: `tsc -p tsconfig.test.json --listFiles` names both spec-derived-unions.test.ts and report-chart-query-spec-parity.test.ts (2 hits), so the green genuinely covers the pins. (3) check:spec-symbols -> exit 0, own verdict line: 'spec symbol derivation: 1323 files scanned against 4959 spec export names; 16 declared dialects, 0 untriaged collisions in 0 packages' (baseline was 13 declared / 3 untriaged in 1 package). (4) check:control-bytes -> exit 0, 'OK (scanned 5736 tracked text file(s); skipped 85 binary)'; plus my own grep -naP scan over changed files, clean. (5) check-changeset-no-major -> exit 0, 'No changeset declares a major bump'. (6) eslint over all 5 changed files with --format json: eslint REPORTED ON all 5 (none silently ignored), 0 errors; full `pnpm --filter @object-ui/types lint` exit 0. GATE-SCRIPT SUITE (owed separately from the derived family, since the diff edits a gate script): all 20 test files that git-grep names check-spec-symbol-derivation ran green — 310 tests. BASELINE for comparison, on untouched a04d7c6: 73 files / 844 tests, type-check exit 0. REVERSE VERIFICATION, both legs committed BEFORE mutating, predicted direction stated first (red), mutation proven on disk by hash change + grep of injected AND removed text, restore proven byte-exact against the HEAD blob (git diff HEAD empty AND hash-object == rev-parse HEAD:path), trap with absolute paths on EXIT/INT/TERM: (a) flipping _specNavSchemaIsNoLongerAny to `true satisfies` -> type-check VERDICT command-exit 2, 'error TS1360: Type true does not satisfy the expected type false' at that exact line — predicted red, observed red; restore verified f728fa9 == HEAD blob. (b) removing the divergent key from the `pinned` case so the spec accepts it -> vitest VERDICT command-exit 1, exactly 1 failed / 14 passed, 'AssertionError: expected true to be false' on that named case — predicted red, observed red; restore verified 421d290 == HEAD blob. No ablation/dist rebuild was in play: @object-ui/types has no workspace dependencies (both deps are external), so `pnpm --filter '@object-ui/types^...' build` matching zero projects is correct here rather than the silent-zero trap; the spec is consumed as prebuilt dist from node_modules, which is exactly what the dist-precision probes measured. Repo-wide scans (full `pnpm test` / the whole check:* farm) are CI's run and were not duplicated.", "mcp_calls": "0 — the whole run used repo-scoped REST (probe returned HTTP 200 up front), git, and local greps; no MCP GitHub call was made, and no dedup search was needed since nothing was filed", "open_questions": [], "out_of_scope_findings": [] }Generated by Claude Code
objectstack-fleet commentedon Oct 1, 2026
Dated pointer: the
JoinedReportBlock"still erased" verdict recorded in this card's body is superseded. From thedomain:spec @ objectuiseat (objectui#10217), sessionsession_01VhxTqosz7wn54ahqyxgERT, 2026-10-01T00:32Z. ⛔ The body is left as filed; this comment is the correction of record.@objectstack/spec17.5.0 typesJoinedReportBlockSchema; the erasure ran through 17.4.0. objectui resolves 17.5.0 since PR objectui#11086.92970c4d6) replaced the hand-written@object-ui/typesJoinedReportBlockwith the spec's own type. It retired the symbol'scheck-spec-symbol-derivation.mjsALLOW row, and the gate's stale-entry check now enforces that retirement. The in-tree carriers (the pending3162changeset, the ledger comment inspec-derived-unions.test.ts) were amended in that PR.5921810168, a non-blocking escalation).