T-MU9Z-meta-definition-zod-4-meta-on-every-sdlc-yaml-key-enforced
State: closed/done · Impact: medium · Complexity: large
Every top-level key of SdlcConfigSchema carries a typed Zod 4 .meta()
block (category, consumers, layers, applies_via, runs_in) next to
its .describe(), enforced by a completeness test, so later Phase 5 work
(sdlc config list|explain|get|set, the generated sdlc.yaml reference,
sdlc apply appliers, doctor drift) can read it as data. The sections the
sdlc 1.0 plan names (chain, hooks, harness, sessions, notify,
mcp, knowledge, issues, usage) exist as optional keys. Trust stays
machine-local.
Approach
Section titled “Approach”- New
lib/config/meta.ts: closed enumsCONFIG_CATEGORIES(lifecycle/automation/integration/planning/infrastructure),CONFIG_LAYERS(project/local/machine/subtree),APPLIER_NAMES(hooks/harness/mcp),RUN_CONTEXTS(cli/hook/loop/session/ci);AppliesViaSchema=read|apply:<applier>(template literal); consumers are<path>.ts#<symbol>(relative to the sdlc source root) orplanned:<note>for reserved sections.ConfigKeyMetaSchema(strict) andRegisteredKeyMetaSchema(plus the mergeddescription);keyMeta()types a call site;checkConfigMeta(shape)returns one issue per bad key;readConfigMeta(shape)returns all metas or throws;isReserved,applierOfhelpers. load.ts:.meta(keyMeta({...}))as the last call on every top-level key, with consumers taken from a grep of the real readers. Layers follow the loaders:lease_authorityisprojectonly (read raw fromsdlc.yaml),paths/repos/checkoutaddmachine,verifyaddssubtree. Add the nine new optional sections: strict empty objects for the reserved ones (chain,sessions,notify,knowledge,issues,usage),hooksas arecord(string, unknown)placeholder (apply:hooks),harness: { targets?: string[] }(apply:harness),mcp: { allow: string[] = [], deny: string[] = [] }(apply:mcp). Nested orchestrator fields that lacked a.describe()get one; meta stays top-level only (nested fields inherit their section’s).notify: the working notifier stays underorchestrator.notify(consumed bylib/services/notify/dispatch.ts); top-levelnotifyis a reserved stub Phase 8 fills and absorbs it into.sessionsis a stub:session launchreads onlyhost.defaulttoday.scaffold.ts: an optional section with no default renders commented out, so the scaffold still round-trips toSdlcConfigSchema.parse({}).meta.test.ts: completeness, negative cases, and truthfulness checks.conventions/sdlc-yaml.md: a Key meta section, a reserved-sections table, and stale-prose fixes (orchestrator.review.command,zod-to-json-schema,additionalProperties).
| Area | Note |
|---|---|
solutions/ontological/lib/config/meta.ts | New: meta schema, types, checker |
solutions/ontological/lib/config/meta.test.ts | New: completeness + truthfulness tests |
solutions/ontological/lib/config/load.ts | .meta() on every key; nine new sections; nested describes |
solutions/ontological/lib/config/scaffold.ts | Optional no-default sections render commented |
solutions/ontological/lib/config/index.ts | Re-export the meta surface |
solutions/ontological/conventions/sdlc-yaml.md | Key meta + reserved sections docs |
Acceptance criteria
Section titled “Acceptance criteria”- AC-1: Every top-level
SdlcConfigSchemakey carries a.meta()block with category/consumers/layers/applies_via/runs_in and a description (checkConfigMeta(SdlcConfigSchema.shape)returns[]). - AC-2: A completeness test fails when a key lacks
.meta(), has meta set before a wrapping call, lacks a description, or carries malformed meta (bad enum, empty or duplicate list, bad consumer, unknown applier, unknown field). - AC-3: Every
<path>#<symbol>consumer names an existing file that contains the symbol; themachinelayer is claimed by exactly the keysMachineConfigSchemadeclares; no trust key is inSdlcConfigSchema. - AC-4:
chain,hooks,harness,sessions,notify,mcp,knowledge,issues,usageexist, optional;mcpis exactly{ allow: string[], deny: string[] }defaulting to[]; reserved stubs reject any key. - AC-5: Existing config tests, the scaffold round-trip,
bunx tsc --noEmitand the repo’s ownsdlc.yaml(preflight onconfig get-verbs) stay green.
Out of scope
Section titled “Out of scope”- The
sdlc config list|explain|get|setCLI,sdlc applyand its appliers, the hooks step grammar (T-F8NL), and generated reference docs — later Phase 5 tasks consume this meta.
Dependencies
Section titled “Dependencies”- none