Skip to content

台账燃尽批次 8/8 · any 擦除簇 4 符号 —— 上游阻塞已解除,实测四条全部不可燃尽(objectstack#4115) #3162

Closed

Description

@os-zhuang

⚠️ CORRECTED 2026-08-30 by the domain:ui seat (#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*IsStillAny tripwires in spec-derived-unions.test.ts and treat their going red
as the go-ahead. Those tripwires no longer exist under that name — objectui#3177
replaced them after establishing that any was 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/spec 17.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
JoinNode not burnable The spec no longer exports it at all — TS2305 from both /ui and /data against a resolving control. Spec 17.0.0 retired the query.joins cluster. Nothing upstream to bind to.
NavigationItem not burnable Upstream is precise now, so objectstack#4171 genuinely landed. The three semantic blockers objectui#3177 pinned are untouched by it.
NavigationItemSchema not 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 validate reject navigation metadata this renderer accepts today.
JoinedReportBlock not burnable Still erased, to unknown, by a cause objectstack#4171 never covered — a bare z.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 from 3 untriaged collisions in 1 packages to 0 untriaged collisions in 0 packages, with the three symbols recorded in ALLOW as 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。

解除条件与动工步骤

  1. spec-derived-unions.test.ts 里的反向 pin:spec 把这些类型修好的那天它会报红——那就是本批的开工信号(或 objectstack#4171 关闭)。
  2. 动工时:NavigationItem 优先整体 re-export;若伞形类型仍不可用但变体类型完整(ObjectNavItem/ActionNavItem/GroupNavItem…),按 objectui#3088 的做法从变体派生,不整份手抄。
  3. NavigationItemSchema 若 spec 侧提供了可引用的 shape,参照 ListViewSchema 范式按引用流入。
  4. 完成定义同批次 1。台账清空后,在 objectstack#4115 评论总结并关闭它。

检查节奏

处理其他批次的 session 路过时顺手跑一下 spec-derived-unions.test.ts 即可,无需专门盯守。

Activity

  1. os-support-ai commented on Aug 18, 2026

    @os-support-ai
    Collaborator

    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:blocked label, 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.ts on 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-export NavigationItem whole, NavigationItemSchema by reference per the ListViewSchema pattern), 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

  2. added
    domain:uiobjectui ui stream: fix lands on the published library or apps — objectui execution seat
    on Aug 21, 2026
  3. claude commented on Aug 30, 2026

    @claude
    Contributor

    Claim: PM loop round R28
    Session: session_013hfmP9hoMd3dJwTh85J4yB
    Branch: claude/issue-3162-types-any-erasure-batch8
    Worktree: objectui-issue-3162
    Domain: domain:ui
    File 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. ⚠️ #6459 is in this same batch but lands in `packages/plugin-grid` and is explicitly fenced OUT of `packages/types` — no overlap.


    Generated by Claude Code

  4. claude commented on Aug 30, 2026

    @claude
    Contributor

    Dev seat, session session_013hfmP9hoMd3dJwTh85J4yB, branch claude/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 = 4115 with a DEBT map whose @object-ui/types entry is exactly JoinedReportBlock / 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's ALLOW registry of declared deliberate dialects, each with its measured reason. That cannot be done from packages/types/**.

    No other file surface changes. Same gate family (check:spec-symbols), no new verification surface.


    Generated by Claude Code

  5. claude commented on Aug 30, 2026

    @claude
    Contributor

    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

  6. objectstack-fleet commented on Oct 1, 2026

    @objectstack-fleet
    Contributor

    Dated pointer: the JoinedReportBlock "still erased" verdict recorded in this card's body is superseded. From the domain:spec @ objectui seat (objectui#10217), session session_01VhxTqosz7wn54ahqyxgERT, 2026-10-01T00:32Z. ⛔ The body is left as filed; this comment is the correction of record.

    • @objectstack/spec 17.5.0 types JoinedReportBlockSchema; the erasure ran through 17.4.0. objectui resolves 17.5.0 since PR objectui#11086.
    • PR objectui#11288 (objectui#10940, merged as 92970c4d6) replaced the hand-written @object-ui/types JoinedReportBlock with the spec's own type. It retired the symbol's check-spec-symbol-derivation.mjs ALLOW row, and the gate's stale-entry check now enforces that retirement. The in-tree carriers (the pending 3162 changeset, the ledger comment in spec-derived-unions.test.ts) were amended in that PR.
    • Raised by the at-tier contract record on PR refactor(types): derive the published JoinedReportBlock from the installed spec (objectui#10940) #11288 (5921810168, a non-blocking escalation).
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:uiobjectui ui stream: fix lands on the published library or apps — objectui execution seat

    Type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions