template-kit/schema-invalid
The template-kit/schema-invalid authoring rule — what it enforces, why, and how to fix it.
schema.tsandfill-spec.tsare a matched pair. This is every check that makes sure they actually agree.
A section’s schema.ts and fill-spec.ts must, together:
- parse — each is
as const satisfiesits shape (SectionSchemaShape,FillSpecShape); a value that doesn’t satisfy it fails here with the parse error; - cross-reference correctly — every
fill-spec.tsdecision produces a slot that actually exists inschema.ts, everyreadsentry names a real, author-declarable facts key, every option’saffects_decisions/affects_slotsnames a real decision or slot; - satisfy the closed per-type contracts — an
object_listslot’sitem_ordercovers every field, aselectslot’s cases match its transform, a group’s members are slots that exist, and the rest of the per-slot-type rules the schema system documents.
One violation is one diagnostic; a section with several wrong things reports all of them in the same run, not one per fix.
This is the id you also see when a section cannot be built or parsed at all — a
syntax error in schema.ts, a missing export, an import that doesn’t resolve. The
message in that case is the underlying build error, relocated to the file it points at.
Reason
Section titled “Reason”fill-spec.ts is not free-standing — every decision it declares exists to fill a slot
schema.ts declared, and every fact it reads must be one the platform actually exposes.
A decision that produces a slot no schema declares, or reads a fact that doesn’t exist,
is not a style problem: the fill pipeline would either drop the output on the floor or
crash trying to read a fact key that isn’t there. Catching the mismatch here, at author
time, is the difference between a red check and a listing that silently fails to fill.
Read the message: it names the section, the decision or slot in question, and what’s wrong with it. Fix whichever side is actually stale — the schema, or the fill-spec.
Before
Section titled “Before”export const schema = { meta: { displayName: "Facts" }, slots: { year_built: { type: "text", required: false, produced_by: "year_built_text" }, }, options: {},} as const satisfies SectionSchemaShape;export const fillSpec = { reads: [], decisions: [ { id: "year_built_text", type: "text-block", produces: ["year_built_summary"], length_cap: 20 }, // ^ typo — schema.ts declares "year_built" ],} as const satisfies FillSpecShape;Section "facts": fill-spec decision "year_built_text" produces unknown slot "year_built_summary".export const fillSpec = { reads: [], decisions: [ { id: "year_built_text", type: "text-block", produces: ["year_built"], length_cap: 20 }, ],} as const satisfies FillSpecShape;See also
Section titled “See also”- The schema system — the full authoring contract for
schema.tsandfill-spec.ts. fixtures-invalid— the sibling gate on the third contract file,fixtures.ts.manifest-invalid— the same kind of cross-reference check, one level up, on a template composing several sections.bundle-incomplete— reported instead of this id when a contract file is missing outright, rather than present and wrong.