T-OOOE-sdlc-yaml-config-cli-list-explain-get-set-run-apply-init-and
State: closed/done · Impact: high · Complexity: large
sdlc config list|explain|get|set (writing through yaml-splice),
sdlc run, sdlc init, and the sdlc.yaml reference docs generated from
schema plus meta. Everything reads the per-key .meta() T-MU9Z added, so a
new key flows into every surface without an edit to the CLI.
sdlc apply [--dry-run] and drift reporting in doctor were part of this
task’s original scope. They move to the apply framework work tracked under
T-F8NL (Phase 5 brief C2), which builds the appliers those two depend on.
Approach
Section titled “Approach”- Schema introspection (
lib/config/introspect.ts):resolveKeyPathwalks a dotted path through object fields and record values to the field schema, its own description, and its section’s meta;shapeOfrenders a short type string fromz.toJSONSchema;defaultOfis the schema’s own parse ofundefined;nestedFieldslists an object’s children. - Span-preserving edits (
lib/config/edit.ts):setPath/unsetPathreduce a nested path to yaml-splice’s top-level edits by cutting the parent’s block-mapping lines (located with theyamlpackage’s source ranges), dedenting, editing, re-indenting, and splicing back. A flow or null parent re-renders that section alone; a mapping emptied by unset is removed. - Config service core (
lib/services/config/config-file.ts): readssdlc.yamlandsdlc.local.yamlfresh (not throughloadConfig’s memo), reports a key’s source (local/project/default/unset), fails loudly on an invalid config, and writes one layer only after validating the merged result againstSdlcConfigSchema. - Ops (
lib/services/config/ops/):list(grouped by category),explain,get(YAML text,--json,--layer),set(value parsed as YAML, apply hint when the section’s meta saysapply:<x>),unset,init.get-verbs/set-verbsstay:/sdlc:find-verbscalls them. - Reference docs (
lib/config/reference.ts): a markdown page with a key table and one section per key (description, meta table, shape, default, nested field tables, recursing into object fields), registered as thesdlc-yamlartifact inlib/services/docs/generate.ts(default set,docs/sdlc-yaml-reference.md, listed inGENERATED_DOCS_ROOTS, excluded from rumdl like its siblings). sdlc init(config init):configStarterYamlinlib/config/scaffold.tssets only detected verbs —checkfrom an aggregateci/checktask orfmt-check/lint/typecheck/test(@sksizer/detect-runners, root-level tasks),setupfromdetectSetup— and comments out every other key with its description, grouped by category. Refuses an existing file without--force;--dry-runprints.sdlc project setupkeeps writing the fullconfigScaffoldYamlform.sdlc run(workflow run):runWorkflowfrom the step runner with a streaming verb seam (child output to stderr) and a trust-gate wrapper that rethrows a refusal so the command exits 21; the failing step’s exit code becomes the command’s. The step runner gainedStepOutcome.exitCodeand acommandoption for the trust message.--dry-runprints the resolved plan with eachrun:step’s verbs.- Top-level verbs (
cli/sdlc.tsTOP_LEVEL_VERBS):sdlc initandsdlc rundispatch to theconfig init/workflow runregistry entries.
| Area | Note |
|---|---|
solutions/ontological/lib/config/introspect.ts | New: dotted-path resolution, shape, defaults |
solutions/ontological/lib/config/edit.ts | New: span-preserving nested edits over yaml-splice |
solutions/ontological/lib/config/reference.ts | New: generated sdlc.yaml reference |
solutions/ontological/lib/config/scaffold.ts | configStarterYaml for sdlc init |
solutions/ontological/lib/services/config/config-file.ts | New: layer reads, source, validated writes |
solutions/ontological/lib/services/config/ops/ | New ops: list, explain, get, set, unset, init |
solutions/ontological/lib/services/workflow/ops/run.ts | New op: workflow run / sdlc run |
solutions/ontological/lib/services/orchestrator/step-runner.ts | exitCode on outcomes, command option |
solutions/ontological/lib/services/docs/generate.ts | sdlc-yaml artifact |
solutions/ontological/cli/sdlc.ts | Top-level init / run |
docs/sdlc-yaml-reference.md | Generated, committed |
.rumdl.toml | Exclude the generated reference |
Acceptance criteria
Section titled “Acceptance criteria”- AC-1:
config seton a nested key of a commented, oddly spaced fixture changes exactly that value’s line (exact-output tests inlib/config/edit.test.tsandconfig_ops.test.ts);config unsetlikewise removes only that line. - AC-2:
config setwith a value the schema rejects exits SCHEMA_ERROR (14) and leaves the file byte-identical. - AC-3:
config getprints the merged value and its source,--layerone file’s;config listgroups every top-level key by category;config explainworks on top-level and nested (orchestrator.max_implementations) keys with the nested description and inherited meta. - AC-4:
sdlc docs generatewritesdocs/sdlc-yaml-reference.mddeterministically from the live schema, and--checkreports a missing or hand-edited copy as drift. - AC-5:
sdlc initin a bun project detectsbun installas setup and the gate scripts as check, refuses an existing file without--force, and writes nothing under--dry-run. - AC-6:
sdlc run <workflow> --dry-runprints the resolved plan; arun:step executes its verb in a trusted repo; an untrusted repo exits 21 before any verb runs; a failing step’s exit code stops the run.
Out of scope
Section titled “Out of scope”sdlc apply [--dry-run]and doctor drift reporting:T-F8NL(brief C2).- An interactive or host-attached session for
skill:/prompt:steps undersdlc run: they use the step runner’s headlesssession launchpath.
Dependencies
Section titled “Dependencies”T-MU9Z(per-key.meta()).