Skip to content

T-DHUF-entity-docs-migration-cleanup-ajv-removal

Status: closed/done · Impact: high · Complexity: large

Complete the entity-surface Zod migration: move the docs generator and every remaining schema.json consumer onto the in-memory Zod schema, delete the 11 schema.json files + _common.json, drop the vestigial Python-style error-parity goldens, amend the standards/decisions/conventions, and — the shared final gate across both surfaces — remove ajv + ajv-formats from package.json. This is child 3 of the three-way split of T-QFTI-migrate-entity-schemas-to-zod-first (the epic) and lands last: it depends on T-KESH-config-surface-sdlc-yaml-zod-safeparse (config off AJV, so the shared package.json removal is safe) and T-JO4I-entity-zod-schemas-validation-ops-swap (entity validation already on Zod, so deleting schema.json and dropping the goldens leaves nothing broken).

After child 2 lands, entity validation and ops read Zod, but the docs generator, entity discovery, and several JSON consumers still read the on-disk schema.json / _common.json; the Python-style error-parity goldens still exist; the standards/decisions/conventions still assert JSON-schema-of-record + AJV; and ajv + ajv-formats are still in package.json (the config surface, child 1, removed its AJV imports but the dependency line stays until both surfaces are clean).

LocationRole today
plugin/lib/model/entities/<type>/schema.json (11 files) + plugin/lib/model/entities/_common.jsonStill on disk after child 2 — read by the docs generator, entity discovery, and the JSON consumers below. To be deleted here
plugin/lib/services/docs/data_model.tsReads each schema.json + _common.json directly (readJson) to derive entity type list, id-pattern prefix, and key-fields (props minus common) for the data-model page
plugin/lib/services/docs/site.tsJoins <type>/schema.json for per-entity reference pages (sourceRel, key-fields)
plugin/lib/services/docs/site/projections.tsGates “is this an entity type” on existsSync(<type>/schema.json)
plugin/lib/services/docs/site_data_model_template.eta, plugin/lib/services/docs/site_entity_template.eta, plugin/lib/services/docs/site_ref_index_template.etaProse/header references to schema.json as the frontmatter contract
plugin/lib/model/entities/*/body-template.etaHeader-comment references to schema.json
plugin/lib/configuration.tsentity.schemaFile: "schema.json" — the surface filename constant every loader joins on
plugin/lib/services/project/ops/setup.tsglobOneLevel(entitiesDir, "schema.json") to discover entity types during sdlc project setup
plugin/cli/backlog_cli/create.ts, plugin/cli/backlog_cli/_common.tsJoin entities/backlog/schema.json to read the backlog contract
.claude/skills/project-check/check_entities.ts/project-check gate: loads each schema.json, asserts it’s valid Draft 2020-12, checks prose field/enum references against properties / status.enum
tests/parity/validators/ (367 *.fixture.json) + tests/parity/validators.golden.test.ts + tests/parity/regen_validators.tsPython-style error-parity goldens that lock the AJV 5-line failure-output format. The Python validators they mirrored are retired — vestigial
plugin/lib/tests/validate_absorb_parity.test.ts + plugin/lib/tests/fixtures/validate-absorb/goldens/Validator-absorb goldens asserting the same Python-style failure format through sdlc entities validate
docs/planning/standards/S-0005-entity-definition-contract.mdThe standard. Rule table lists schema.json as “JSON-Schema frontmatter contract”; Deterministic-checks table names validate_frontmatter.ts (AJV)
docs/planning/decisions/D-0004-entity-definition-architecture.mdADR asserting schema.json as the validation+scaffolding source and JSON-Schema default keywords as the defaults home; describes the _common.json $ref architecture
plugin/conventions/typescript-runtime.mdLists ajv + ajv-formats as available runtime dependencies
package.json"ajv": "^8.17.1", "ajv-formats": "^3.0.1" dependencies. Removing them is gated on BOTH surfaces being off AJV (config via child 1, entity validation via child 2)
  1. Change data_model.ts, site.ts, and projections.ts to derive their entity inventory and per-entity facts from zodToJsonSchema(EntitySchema) in memory (id-pattern prefix, key-fields = props minus common, status enum), instead of reading schema.json / _common.json off disk. Update entity discovery (which today gates on schema.json presence) to enumerate the schema registry from child 2. The existing rendering logic survives almost unchanged — it never hand-walks Zod’s _def internals.
  2. Repoint the remaining schema.json consumers: configuration.ts (entity.schemaFile), backlog_cli/{create,_common}.ts, project/ops/setup.ts, and .claude/skills/project-check/check_entities.ts (validate field/enum prose references against the Zod schema instead of the JSON).
  3. Update the .eta templates (site_data_model_template, site_entity_template, site_ref_index_template) and the per-entity body-template.eta header comments so their schema.json references point at the Zod schema.
  4. Delete the 11 schema.json files and _common.json. Optionally add an on-demand sdlc-verb / script that writes a generated schema.json export for autocomplete, off by default (not a checked-in artifact).
  5. Drop the Python-style error-parity goldens (tests/parity/validators/**, validators.golden.test.ts, regen_validators.ts, the validate-absorb goldens validate_absorb_parity.test.ts + its goldens/). The Zod-error assertions added in child 2’s entity.test.ts already cover the failure cases.
  6. Amend S-0005 in place (Rule + Deterministic-checks tables read Zod-first); update D-0004’s schema.json/_common.json/AJV assertions to Zod-first; drop ajv/ajv-formats from plugin/conventions/typescript-runtime.md.
  7. Remove ajv + ajv-formats from package.json. This is the shared gate — safe only because child 1 took config off AJV and child 2 took entity validation off AJV.
  8. Regenerate the docs site (sdlc docs generate site) so the data-model and per-entity reference pages reflect the in-memory Zod derivation, and confirm sdlc docs generate --check exits clean.
LocationKindChange
plugin/lib/services/docs/data_model.tsmodifyDerive from zodToJsonSchema(EntitySchema) in memory, not readJson
plugin/lib/services/docs/site.tsmodifyPer-entity facts from the in-memory schema; drop <type>/schema.json joins
plugin/lib/services/docs/site/projections.tsmodifyEntity-type gate off the schema registry, not schema.json presence
plugin/lib/services/docs/site_data_model_template.etamodifyProse references to schema.json → Zod
plugin/lib/services/docs/site_entity_template.etamodifyProse references to schema.json → Zod
plugin/lib/services/docs/site_ref_index_template.etamodifyProse references to schema.json → Zod
plugin/lib/model/entities/*/body-template.etamodifyHeader-comment references to schema.json → Zod
plugin/lib/configuration.tsmodifyRetire/repoint entity.schemaFile: "schema.json"
plugin/lib/services/project/ops/setup.tsmodifyDiscover entity types via the registry, not globOneLevel(..., "schema.json")
plugin/cli/backlog_cli/create.tsmodifyResolve the backlog contract from the Zod schema
plugin/cli/backlog_cli/_common.tsmodifyResolve the backlog contract from the Zod schema
.claude/skills/project-check/check_entities.tsmodifyValidate field/enum prose references against the Zod schema
plugin/lib/model/entities/_common.jsondeleteReplaced by the Zod base (child 2’s _common.ts)
plugin/lib/model/entities/backlog/schema.jsondeleteReplaced by the Zod schema
plugin/lib/model/entities/capability/schema.jsondeleteReplaced by the Zod schema
plugin/lib/model/entities/decision/schema.jsondeleteReplaced by the Zod schema
plugin/lib/model/entities/driver/schema.jsondeleteReplaced by the Zod schema
plugin/lib/model/entities/milestone/schema.jsondeleteReplaced by the Zod schema
plugin/lib/model/entities/principle/schema.jsondeleteReplaced by the Zod schema
plugin/lib/model/entities/product/schema.jsondeleteReplaced by the Zod schema
plugin/lib/model/entities/reference/schema.jsondeleteReplaced by the Zod schema
plugin/lib/model/entities/standard/schema.jsondeleteReplaced by the Zod schema
plugin/lib/model/entities/task/schema.jsondeleteReplaced by the Zod schema
plugin/lib/model/entities/term/schema.jsondeleteReplaced by the Zod schema
tests/parity/validators/deleteVestigial Python-style error-parity fixtures (367 files)
tests/parity/validators.golden.test.tsdeleteVestigial Python-style error-parity goldens
tests/parity/regen_validators.tsdeleteRegenerator for the vestigial goldens
plugin/lib/tests/validate_absorb_parity.test.tsdeletePython-style format goldens through the op
plugin/lib/tests/fixtures/validate-absorb/goldens/deleteGolden fixtures for the validate-absorb parity test
docs/planning/standards/S-0005-entity-definition-contract.mdmodifyAmend in place: every entity ships a Zod schema; validation + docs derive from it
docs/planning/decisions/D-0004-entity-definition-architecture.mdmodifyUpdate schema.json/_common.json/AJV assertions to Zod-first
plugin/conventions/typescript-runtime.mdmodifyDrop ajv/ajv-formats from the available-deps list
package.jsonmodifyDrop ajv + ajv-formats (shared gate: both surfaces now off AJV)
site/src/content/docs/planning/modifyRegenerated data-model + per-entity reference pages (via sdlc docs generate site)
  • AC-1: No remaining schema.json / _common.json files under plugin/lib/model/entities/, and no ajv / Ajv / ajv-formats import anywhere in the runtime except, at most, the optional on-demand JSON-export path.
  • AC-2: ajv and ajv-formats are removed from package.json — the shared gate, now satisfiable because both the config surface (T-KESH-config-surface-sdlc-yaml-zod-safeparse) and entity validation (T-JO4I-entity-zod-schemas-validation-ops-swap) are off AJV.
  • AC-3: The docs site still renders the data-model page and per-entity reference pages, deriving all entity facts from zodToJsonSchema(EntitySchema) in memory — sdlc docs generate site --check exits clean.
  • AC-4: S-0005-entity-definition-contract.md reads Zod-first (Rule + Deterministic-checks tables name the Zod schema and .safeParse path, not schema.json + AJV validate_frontmatter.ts); D-0004, the entity conventions doc, and the .eta/template references no longer assert JSON-schema-of-record or AJV.
  • AC-5: /project-check check_entities.ts passes, validating prose field/enum references against the Zod schemas; and the Python-style error-parity goldens (tests/parity/validators/**, the validate-absorb goldens) are gone.
  • AC-6: bun test is green and bunx tsc --noEmit is clean after the JSON deletes, the goldens drop, and the ajv removal.
  • The entity Zod schemas themselves, the CommonFrontmatter base, the registry, and the entity.ts / validate.ts / audit.ts / migrate.ts / authoring.ts / schema_patterns.ts validation+ops swap — all delivered by T-JO4I-entity-zod-schemas-validation-ops-swap (child 2), which this task depends on.
  • The config surface (sdlc.yaml) AJV retirement — delivered by T-KESH-config-surface-sdlc-yaml-zod-safeparse (child 1), which this task depends on. This task only removes the shared ajv/ajv-formats dependency line from package.json once both surfaces are clean.
  • Persisting any generated JSON schema by default. The optional on-demand export (editor/YAML-LS autocomplete) is a stub left for if/when wanted; not a checked-in artifact, no drift test.
  • A separate ADR for the decision. D-0004 is amended in place (the epic’s settled rationale); no new ADR is minted.
  • The schema_version numbering and any instance migration — an /sdlc:entities-migrate concern after the epic lands.
  • T-KESH-config-surface-sdlc-yaml-zod-safeparse — must land first. The shared package.json removal of ajv / ajv-formats is only safe once the config surface has no AJV imports.
  • T-JO4I-entity-zod-schemas-validation-ops-swap — must land first. Entity validation must already run on Zod before the 11 schema.json + _common.json can be deleted and the Python-style error-parity goldens dropped; this task migrates the docs/discovery/JSON-consumer half that child 2 deliberately left on the JSON path.

This task is child 3 of the three-way delivery split of T-QFTI-migrate-entity-schemas-to-zod-first and is the shared final gate. Scope maps to the epic’s Approach steps 7–11 (docs generator + remaining JSON consumers onto the in-memory Zod schema, the schema.json / _common.json deletes, dropping the Python-style error-parity goldens, the standards/decisions/conventions amendments) plus the shared ajv / ajv-formats removal from package.json. It is gated on both sibling children because the dependency removal needs config off AJV (child 1) and the JSON-deletion + goldens-drop needs entity validation already on Zod (child 2). The full decision rationale — full-Zod cut, no bridge, JSON as optional export only, D-0004 amended in place — lives in the epic.

Captured by /sdlc:task-work on 2026-06-13. PR: pending.

  • AC-1: auto — grep -rn 'ajv|Ajv' plugin/ --include='*.ts' returns only T-DHUF-… provenance comments documenting the removal; no live import remains, and bunx tsc --noEmit is clean against the Zod-only tree.
  • AC-2: auto — grep -c ajv package.json returns 0; the shared dependency line is gone now that both sibling children are off AJV.
  • AC-3: auto — sdlc docs generate site --check (worktree CLI) reports clean (no drift); the data-model and per-entity reference pages derive from zodToJsonSchema(EntitySchema) in memory.
  • AC-4: agent-manual — inspected S-0005-entity-definition-contract.md, D-0004, the entity conventions doc, and the .eta/body-template.eta headers; Rule + Deterministic-checks tables now name the Zod schema and the .safeParse path, and no doc/template asserts JSON-schema-of-record or AJV.
  • AC-5: auto — /project-check check_entities.ts passes against the Zod schemas, and tests/parity/validators/ no longer exists (the Python-style error-parity goldens are deleted).
  • AC-6: auto — bun test is green (the lone failure is the pre-existing site_roadmap idempotency case already failing on origin/main, unrelated to this task) and bunx tsc --noEmit is clean after the JSON deletes, the goldens drop, and the ajv removal.
  • The three-way split landed the dependency removal cleanly: with config (child 1) and entity validation (child 2) already off AJV, deleting the 11 schema.json files + _common.json and dropping ajv/ajv-formats left nothing broken — tsc --noEmit and entities audit were clean first try.
  • The worktree CLI’s regenerated site matched the deterministic --check gate exactly, so AC-3 verification was a single command.
  • The runner stalled on the watchdog at the Wave-3 finalize commit due to a rumdl-reflow ↔ docs-drift race: editing the task file reflows the source (markdown-fmt hook) while also staling the derived site page (project-check-docs-drift), and the two hooks fought across the commit boundary — the working sequence is reflow source → regenerate site (worktree CLI) → stage task file + regenerated page together → commit. Already tracked upstream by the auto-regen fix T-PA51/#443; no new follow-up spawned.
  • Debugging gotcha: running the main checkout’s sdlc.ts docs generate site against this worktree’s data falsely reports a mass page deletion (~471 pages) because the main generator is still the old schema.json-based one and the worktree’s schema.json files are deleted — always run the worktree CLI for docs commands during this migration. A documentation/ergonomics gap, not a code bug; folded into the T-PA51 thread rather than spawned separately.
  • Baseline quality-check run is slow on this repo (full corpus audit + test suite), adding latency to each gate pass — already tracked as B-6AHH; no new follow-up spawned.

T-KESH-config-surface-sdlc-yaml-zod-safeparse, T-JO4I-entity-zod-schemas-validation-ops-swap


← Back to Tasks