Skip to content

spec: generate declaration-map/ — TS declaration names to spec registry names (docs-audit option D, spec half) - #13939

Merged
os-warren merged 2 commits into
mainfrom
claude/issue-13712-schema-name-mapping
Aug 31, 2026
Merged

spec: generate declaration-map/ — TS declaration names to spec registry names (docs-audit option D, spec half)#13939
os-warren merged 2 commits into
mainfrom
claude/issue-13712-schema-name-mapping

Conversation

@os-warren

@os-warren os-warren commented Aug 31, 2026

Copy link
Copy Markdown
Collaborator

Fixes #13712

What

A new generated artifact, packages/spec/declaration-map/ (14 category shards), mapping TS declaration names of authorable containers to their spec registry names — produced by the spec generation chain, covered by check:generated, never hand-edited. It unblocks docs-audit option D (#13713, which is Blocked-by: the card this PR closes): diff-side tooling holds a changed line's enclosing declaration name (ObjectSchemaBase) and can now ask which authorable container it declares (data/Object).

Phase discipline per the card and triage: the ruled first deliverable was a cost estimate, posted before any code as issue comment 5480770862 (verdict SMALL, with measurements). This PR is the implementation it green-lit.

Clause-②: no — emitting a new generated artifact neither changes an accept/reject verdict nor widens the authorable surface (triage reading, adopted in the claim).

How the mapping is derived (no manual entries — the card's premise holds)

Composition of two committed artifacts plus one bounded syntactic pass, in scripts/build-declaration-map.ts:

  1. Export half: json-schema.manifest/ supplies every def key; export-origins/ supplies which source declaration each entry-point export resolves to. The export-key candidates for a def are the closed inverse of schemaNameFromExportKey (bare name, and name plus the Schema suffix). Measured: all 1,597 def keys reverse-resolve with zero misses.
  2. Base half: module-private shape providers (the ObjectSchemaBase case) are recovered by syntactically unwinding the exported declaration's initializer — lazySchema factories, Object.assign first argument, method-chain receivers, returned identifiers — recording same-file top-level consts so reached. Single ts.createSourceFile, no type checker. Survivors on this tree: ObjectSchemaBase, BaseQuerySchema, FormFieldBaseSchema, MetadataTypeRegistryEntryBaseSchema.
  3. Ambiguity is dropped, never guessed: a name pointing at two def keys is narrowed by the home rule (def key whose category matches the declaring file's src/CATEGORY/ segment), and otherwise recorded in the shard's collisions list (5 names on this tree, e.g. RetryPolicy, declared in src/shared/ and published under both system/ and automation/). A lookup miss therefore means "not known to be an authorable container" — precision over recall, the right trade for the consumer.

Premise nuance recorded on the card: the card's example declaration DatasourceDef does not exist in spec source — the declaration enclosing schemaMode is DatasourceSchema (src/data/datasource.zod.ts), so the second pin is DatasourceSchema resolving to data/Datasource.

Executable criterion (path per implementation)

node -e "console.log(require('./packages/spec/declaration-map/data.json').entries['ObjectSchemaBase'])" prints data/Object — verified on this branch. check:generated covers the artifact via a new GATED ledger row (check:declaration-map / gen:declaration-map), same regime as the other artifacts.

Wiring (every registry has its own reconciliation gate)

  • packages/spec/package.json: gen:declaration-map / check:declaration-map (self-test then byte-compare)
  • packages/spec/scripts/check-generated.ts: GATED row placed after its two input artifacts, so a --fix regenerates inputs first — ledger reconciles (15 gated)
  • .gitattributes + scripts/regen-artifacts.mjs: merge=os-regen routing, reconciled by check:merge-driver
  • packages/spec/scripts/declaration-map.test.ts: pins over the committed bytes — ObjectSchemaBase to data/Object, DatasourceSchema to data/Datasource, a 1,000-entry non-empty floor, a positive control (the known-absent DatasourceDef spelling really misses), manifest cross-consistency (every value is a published def key), and entry/collision disjointness
  • changeset (patch; repo-internal artifact, not added to the npm files whitelist — same posture as export-origins/)

Verification — all at head eee4548 (the final commit; no code changed after these runs)

  • check:declaration-map self-test: every unwinding rule pinned on fixtures (wrapper chains, nested returns, imports and inline shapes stop the walk, precedence, home rule, collision drop) — green
  • Idempotency: regenerate at head rewrote 0 shards, git status clean; check mode green ("declaration-map/ is current: 2978 declaration name(s) across 14 categor(ies), 5 dropped as ambiguous")
  • Red-to-green, both legs: deleting a shard makes the gate print "missing shard declaration-map/data.json" and exit 1; hand-editing an entry makes it print the stale verdict and exit 1; both restored from HEAD, gate green again
  • pnpm --filter @objectstack/spec run check:generated: all 15 gated artifacts green, check:declaration-map among them
  • pnpm --filter @objectstack/spec typecheck (src + scripts + test programs): green
  • Pins: vitest run scripts/declaration-map.test.ts — 6 passed (6)
  • Edited-gate-script suites: check-generated-ledger.test.ts + build-schemas-check-mode.test.ts — 71 passed; liveness/check-liveness.test.ts — 37 passed
  • Derived gate farm (scripts/pm/dispatch-gates.mjs, changeset derived from merge base 9b21037): 55 commands — 50 green, 5 PREREQUISITE NOT MET by the gates' own printed verdicts, none a red: check-dev-prereqs, check:dual-build-cjs-loads, check:type-check-debt re-measure (all three need the whole-workspace build CI performs; the coverage half of the last is green), check-test-completeness (grades a saved CI test log; its own text says record NOT MEASURED locally), check-half-states (needs repo-scoped REST this session's gate refuses, measured 403)

CI convergence review is the PM's per the dispatch contract; gate status as of this report is the local evidence above. Authored in session session_01PBjwYLS6BciTQW3c9xQiD2.

Generated by Claude Code

claude added 2 commits August 31, 2026 16:43
…egistry name

WIP: generator + artifact; wiring (scripts, check:generated row, merge-driver
routing, pins, changeset) follows.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PBjwYLS6BciTQW3c9xQiD2
…pins, changeset

- package.json: gen:declaration-map / check:declaration-map (self-test + --check)
- check-generated.ts: GATED row after its two input artifacts
- .gitattributes + regen-artifacts.mjs: merge=os-regen routing
- scripts/declaration-map.test.ts: pins ObjectSchemaBase→data/Object,
  DatasourceSchema→data/Datasource, non-empty floor, positive control,
  manifest cross-consistency
- changeset (patch)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PBjwYLS6BciTQW3c9xQiD2
@github-actions

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

⚠️ 14 changed file(s) yielded no anchor (packages/spec/declaration-map/ai.json, packages/spec/declaration-map/api.json, packages/spec/declaration-map/automation.json, …), so the pages documenting them are NOT COVERED by this run — this is not a clean bill of health for those files. Nothing else in this diff resolved to a documentable surface (no symbol, route or SDK anchor derived from 1 changed package(s)).

What this run could not see
  • 14 changed file(s) yielded no anchor (packages/spec/declaration-map/ai.json, packages/spec/declaration-map/api.json, packages/spec/declaration-map/automation.json, …) — pages documenting those are invisible to this run
  • a page that states a rule by its inputs shares no identifier with the emitter that implements the rule, so an emitter-only diff cannot list it — not on this run and not on any run. Measured on fix(driver-sql): emit varchar(maxLength) for a text field a declared index keys on #11430: content/docs/protocol/objectql/types.mdx documents the text-family column mapping by the ObjectQL type names it maps FROM (text / textarea / html) while the diff changed createColumn; it went unlisted, and it was the page that diff falsified, in four places. No shared token exists to detect this on, so a rule your change carries has to be re-read by hand in the pages that restate it.

Coarse fallback — 128 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): node scripts/docs-audit/affected-docs.mjs --json 0f63965eaa90a05eb3b9abc153ec39268b20f93cpackageMentionDocs.

@github-actions github-actions Bot added dependencies Pull requests that update a dependency file documentation Improvements or additions to documentation tests tooling labels Aug 31, 2026
@os-warren
os-warren marked this pull request as ready for review August 31, 2026 17:40
@os-warren
os-warren enabled auto-merge August 31, 2026 17:40
@os-warren
os-warren added this pull request to the merge queue Aug 31, 2026
Merged via the queue into main with commit 93809a3 Aug 31, 2026
39 checks passed
@os-warren
os-warren deleted the claude/issue-13712-schema-name-mapping branch August 31, 2026 18:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

dependencies Pull requests that update a dependency file documentation Improvements or additions to documentation size/xl tests tooling

Projects

None yet

Development

Successfully merging this pull request may close these issues.

spec: emit the TS-declaration-name → spec-type-name mapping from gen:schema (unblocks docs-audit option D, #12824)

2 participants