Fold 51 issue-named CLI black-box + scripts-tooling regression files into their canonical module suites (runtime-launcher-parity, worktree-safety, install-*, managed-hooks, read-guard, capability-registry, etc.), plus a NEW slash-command-namespace.test.cjs grouping the 4 slash/colon-namespace-leak invariant suites that had no canonical owner. Verbatim block-scoped describe wrappers; 427 subtests conserved 1:1. Host-env pre-check (per B2): no CLI-receiving host sets a redirecting GSD_WORKSTREAM/GSD_PROJECT value. One folded suite (bug-3668 runtime resolver) creates an extension-less PATH gsd-tools stub + bash -c; co-locating it with the host's chmodSync tripped local/no-unguarded-nonportable-exec, so it's now Windows-guarded (skip on win32) matching the host suite's own bash -c guard. Regenerates regression-name allowlist (222->182), ratchets file-count allowlist (graphify 7->6, docs entry removed), makes 26 relocated allow-test-rule exemptions issue-ref-compliant (ADR-456; prunes stale ids). Repoints 13 tests/ references across CONTEXT.md, COMMANDS.md/FEATURES.md (EN + ja/ko/pt/zh) and ADR-0002. lint:ci green. Part of epic #1969. Closes #1975. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
3.2 KiB
Command Contract Validation Module
- Status: Accepted
- Date: 2026-05-05
We decided to centralize the commands/gsd/*.md file contract into a single validation seam enforced at two layers: a fast lint script (scripts/lint-command-contract.cjs) that runs as a pre-test CI step, and a behavioral regression test (tests/command-contract.test.cjs) that validates the full contract against the live filesystem.
Decision
The command file contract defines what makes a valid commands/gsd/*.md:
name:field present, non-empty, matchesgsd:*orgsd-*(ns- commands usegsd-)description:field present and non-emptyallowed-tools:block present and non-empty, all entries from the canonical tool set- Every
@-reference inside<execution_context>blocks resolves to an existing file on disk @-references inside<execution_context>blocks appear on their own line (no trailing prose)
Context
Before this ADR, the command contract was enforced inconsistently:
tests/skill-frontmatter-contract.test.cjs(folds formerenh-2790-skill-consolidation, consolidation epic #1969) checked existence and frontmatter of specific post-consolidation commandstests/docs-update.test.cjs(folds formerbug-3135-capture-backlog-workflow, consolidation epic #1969) checkedexecution_context@-ref resolution (added 2026-05-05)- No test checked
allowed-toolsvalidity,name:convention, ordescription:non-emptiness across all commands simultaneously
This meant any PR touching a command file could break the contract without a single test catching it. The add-backlog.md gap (#3135) is a concrete example: the workflow file was missing for the full consolidation cycle before a targeted regression test was written.
Additionally, 40 of 65 command files contained redundant prose @-references — the same path appearing once in <execution_context> (which loads the file) and again in <process> body text (inert). This added ~900 tokens of dead weight per invocation and created a drift seam where prose refs could go stale independently of the executable execution_context ref.
The two largest commands (debug.md, thread.md) embedded their full implementation inline rather than delegating to workflow files, causing ~4,400 tokens of implementation detail to load as part of the skills index description on every session regardless of whether those commands are used.
Consequences
- A single
lint-command-contract.cjsscript enforces frontmatter invariants across all 65 commands in milliseconds, runs before the test suite in CI tests/command-contract.test.cjsreplaces the scattered contract coverage inenh-2790andbug-3135, becoming the authoritative behavioral contract test for the entire command surface- Redundant prose @-refs removed from 40 command files (~900 tokens/invocation recovered)
debug.mdandthread.mdrefactored to the workflow-delegation pattern (~4,400 tokens removed from eager system-prompt load)workflows/extract_learnings.mdrenamed toworkflows/extract-learnings.mdto align with the hyphen convention used by all other workflow files- The
execution_contextblock is the single authoritative declaration of what a command loads — no duplication in prose