You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
refactor(types): burn down seven spec-symbol ledger entries, with the triage that decides the rest
objectstack#4115's ledger opened at 156 untriaged collisions. This is the first
tranche: 149 remain. Every symbol removed was proved equivalent to the spec's
before being bound, not assumed equivalent because its doc comment said so —
four of the seven carried exactly such a comment.
Re-exported: BreakpointName, ExportJobStatus, ImportJobStatus, ImportWriteMode,
ValidationError. Derived with z.infer: JoinStrategy, WindowFunction, which the
spec exports as zod enums rather than as types. All seven are structurally
unchanged; full repo type-check passes 76/76.
Mutual assignability is the obvious test for "safe re-export" and it lies three
ways, all present in this repo:
- The SPEC's export resolves to `any` (NavigationItem, JoinNode, FormField).
Binding these replaces a precise local interface with `any`. A naive probe
calls them identical and recommends exactly the wrong edit.
- The LOCAL declaration resolves to `any` — recursive schemas annotated
z.ZodType<any> (FilterConditionSchema, NavigationItemSchema).
- The local declaration carries `[key: string]: any` — the objectstack#4075
mechanism (FormField, AppSchema, PageSchema, ThemeSchema, +12).
And a zod schema needs one question more than a type: FormFieldSchema has an
identical _output and a divergent _input, so re-exporting it would have silently
changed what authoring input parses. All of this is now in the ledger's
burn-down instructions with the detection probe for each case.
spec-derived-unions.test.ts gains an inverted pin asserting the three spec-side
`any` cases are STILL `any`. The day the spec types one properly the assertion
stops compiling, and the failure is the instruction to burn that symbol down.
Guard fix: referencesSpec walked the declaration's own name node, so a symbol
whose name was also bound to a spec import counted as derived from itself.
TypeScript rejects that pair as a duplicate identifier so it was unreachable in
compiling code, but a guard that depends on the compiler having run first has a
hole in it. Clean-tree result unchanged, confirming it masked nothing.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Rvv6qysks2dRLaGfpTdgEy
0 commit comments