4.4 KiB
CT.M1 — ContentValidationPipeline
Summary
| Field | Value |
|---|---|
| Module ID | CT.M1 |
| Track | Content tooling — internal authoring (cross-cutting; not E1–E9) |
| Stage target | Prototype |
| Status | Planned (see dependency register) |
Purpose
Own content schema artifacts, automated validation in CI and locally, and (when wired) server-side smoke loading so file-backed catalogs cannot drift from enforced contracts.
Responsibilities
- Publish and version JSON Schema (or agreed equivalent) for catalogs consumed by E2.M1, E3.M2–M3, E4.M1, E7.M1.
- Run structural and cross-reference validation before merge; expose the same rules to CT.M2.
- Optional: C# deserialize test or boot check aligned with
ContentCatalogRegistry(or successor).
Key contracts
| Contract | Role |
|---|---|
| Content schema files | $id + versioning per contracts.md |
| Validation CLI | Stable exit codes and machine-readable errors for CI and studio |
Module dependencies
- Soft: Gameplay modules above must define or stabilize the shapes being validated; pipeline can ship minimal schemas first.
Dependents (by design)
- CT.M2 — AuthoringStudioApplication
- CT.M3 — ContentReferenceAndBundleWorkflows
Related implementation slices
Content tooling Slice 1 — schemas + CI; Slice 4 — server parity hardening.
CI (prototype)
Skill catalogs: the repo PR gate workflow (.github/workflows/pr-gate.yml) runs scripts/validate_content.py on every push and pull request. It validates each object in content/skills/*.json under the top-level skills array against content/schemas/skill-def.schema.json (Python jsonschema, Draft 2020-12), rejects duplicate id across files, and (Slice 1 / NEO-33) enforces the frozen prototype trio ids plus gather + tech + (process or make) category coverage.
Mastery catalogs (NEO-45): the same script validates content/mastery/*_mastery.json against content/schemas/mastery-catalog.schema.json, cross-checks track skillId against loaded SkillDef ids, rejects duplicate perkId, enforces branch integrity (tier branch sets match; perkIds reference defined perks), and (Slice 4) requires exactly one track for salvage only.
Item catalogs (NEO-50): the same script validates each row in content/items/*_items.json against content/schemas/item-def.schema.json, rejects duplicate id across files, and (Slice 1) enforces the frozen six-item id set plus exactly one row per prototypeRole (material through equip_stub).
Resource node catalogs (NEO-57): the same script validates content/resource-nodes/*_resource_nodes.json rows against content/schemas/resource-node-def.schema.json and *_resource_yields.json rows against content/schemas/resource-yield-row.schema.json; rejects duplicate nodeDefId; (Slice 2) enforces the frozen four-node id set, one row per gatherLens, exactly one yield row per node, yield itemId cross-check against item catalogs, and only scrap_metal_bulk as yield item in prototype. Extend the script when additional catalogs and schemas ship.
Decomposition vocabulary: the same workflow runs scripts/check_decomposition_language.py (stdlib only) over docs/decomposition/**/*.md to catch wording that treats combat as a leveled SkillDef line instead of gig progression (see script docstring for patterns). Adjust the script if a future doc needs a documented exception.