Skip to content

T-DPG3-default-check-composition-skip-writes-doctor

State: closed/done · Impact: medium · Complexity: medium

Ship check’s fixed default composition, the skip-and-report/--strict behavior for an unresolved leaf inside any composition, the revised “vocabulary name resolves to nothing → error” CLI behavior, and doctor’s new warning for a write-capable verb used where read-only is expected.

check has no built-in composition today (its old self-referential [{run: 'check'}] became [] in T-4OUZ). There is no skip-and-report behavior for an unresolved {run: <name>} step reached via splicing — it silently contributes zero steps. sdlc run <vocabulary-name> with nothing configured or detected has no distinct “not configured, nothing detected” message. doctor has no check for a hooks: reference to a write-capable verb.

check’s built-in entry becomes [{run: 'fmt-check'}, {run: 'lint'}, {run: 'typecheck'}, {run: 'test'}] (layer: 'builtin', never 'detected' — see decision.md’s “Default check composition”). A non-top-level unresolved {run: <name>} step is recorded {status: 'skipped', reason: 'not configured'} instead of silently vanishing; --strict turns a skip into a failure. sdlc run <vocabulary-name> with nothing configured or detected prints “not configured, nothing detected” (exit non-zero), distinct from “no workflow named ''” for a genuinely unrecognized name. doctor warns when a hooks:/documented-CI reference names a writes: true vocabulary name.

  1. lib/config/workflows.ts: check’s built-in entry becomes [{run: 'fmt-check'}, {run: 'lint'}, {run: 'typecheck'}, {run: 'test'}] (layer: 'builtin', not 'detected' — check is excluded from T-VE84’s detectVocabulary entirely: never resolved by searching for a runner task literally named check). test-int/test-e2e are deliberately not part of the default — a project adds them via prepend/append or a full workflows.check override.
  2. step-runner.ts’s runWorkflow (or wherever T-4OUZ put run: splicing): when a non-top-level {run: <name>} step (reached via splicing, not the name the caller originally asked to run) resolves to layer: 'none', record {status: 'skipped', reason: 'not configured'} for that step instead of contributing zero steps silently. Add a strict option (CLI --strict on sdlc run/workflow run, and an optional workflows.<name>.strict schema field as a per-project default) that turns a 'skipped' outcome into a failure for that run.
  3. lib/services/workflow/ops/run.ts: the layer === 'none' check (T-4OUZ) gets two message variants: name ∈ VOCABULARY_NAMES → “not configured, nothing detected” (exit non-zero); otherwise → “no workflow named ''” (exit non-zero, unchanged wording).
  4. lib/services/project/ops/doctor.ts: new check — for every hooks: step and every documented CI-context reference whose run: target is a vocabulary name with VOCABULARY_METADATA[name].writes === true, emit a warning naming the hook and the write-capable verb, suggesting the read-only counterpart (fmt → fmt-check, lint-fix → lint).
  5. lib/services/config/ops/explain.ts (T-MVK5’s rendering): a 'detected' layer’s detectedVia prints as e.g. “detected via cargo (synthesized cargo clippy)” / “detected via node-scripts (declared script lint).”
AreaNote
solutions/ontological/lib/config/workflows.tscheck’s builtin composition; strict schema field
solutions/ontological/lib/services/orchestrator/step-runner.tsSkip-and-report for a non-top-level unresolved run:; --strict
solutions/ontological/lib/services/workflow/ops/run.ts--strict flag; two-variant 'none' message
solutions/ontological/lib/services/project/ops/doctor.tsNew writes-in-read-only-context warning
solutions/ontological/lib/services/config/ops/explain.tsRender detectedVia
solutions/ontological/lib/config/workflows.test.ts, step-runner.test.ts, doctor.test.tsNew cases
  • AC-1: A Rust-only crate (no package.json/tsconfig.json) running sdlc run check succeeds, with typecheck reported skipped: not configured and fmt-check/lint/test actually running via their cargo-detected commands.
  • AC-2: The same run with --strict fails, naming typecheck as the reason.
  • AC-3: sdlc run build in a directory with no Cargo.toml, package.json, moon/just/mise task, prints “not configured, nothing detected” and exits non-zero; sdlc run banana (never a real name) prints “no workflow named ‘banana’” and exits non-zero — different message, same exit behavior.
  • AC-4: sdlc run judge in a project that never configured it still exits 0 with zero steps (lifecycle name, unchanged).
  • AC-5: hooks.pre-commit: [{run: 'fmt'}] makes sdlc project doctor warn that pre-commit runs a write-capable verb; hooks.pre-commit: [{run: 'fmt-check'}] does not.
  • AC-6: sdlc config explain workflows.lint in a project with no workflows.lint entry but a detected package.json lint script prints the detectedVia line, not a bare command with no source.
  • Detecting test-int/test-e2e defaults automatically (they are project-declared only — no synthesized convention exists for “the integration tier” the way cargo test does for the fast tier).

T-VE84 (needs detectVocabulary/VOCABULARY_METADATA to exist); T-4KYN (hooks resolution, for the doctor warning to inspect a hook’s run: targets); T-MVK5 (config-explain/doctor plumbing this extends rather than duplicates).

Drawn from D-LSLH-collapse-verbs-workflows-chain-hooks’s “Default check composition” and “Skip semantics” sections.

T-VE84, T-4KYN, T-MVK5


← Back to Tasks