Skip to content

SPEC-128 build — drift-as-warn and mechanism-token tests

Date: 2026-07-06 · Phase: 3-build (re-shape)

Decision: drift check is a warn, not a fatal exit (build-gate #2)

decisions.md §3 phrased the drift check as "warning (non-zero from --verify)". On inspection, the setup.sh dispatcher maps --verify to a non-zero exit only when $ERRORS > 0$WARNINGS never flips the exit code. The archive drift check already used warn (WARNINGS), so it was never actually fatal.

Making drift fatal (fail) would exit --verify non-zero on every machine still on the old pin (currently everyone: v0.8.7 → v0.11.5 = guaranteed drift) until they re-install. Consumers (/vt-c-0-start, CI) may treat that exit code as fatal → a self-inflicted block of the same shape Decision 1 rejects for the hard gate. So drift stays a loud warn, exit 0. Reconciled the spec US-1 AC, the manifest comment, and the pattern doc to match.

Lesson (durable): before shipping any new --verify signal, grep how the dispatcher maps --verify → exit code and which consumers treat non-zero as fatal. Captured in external-cli-pinned-and-gated.md pillar 3.

Decision: negative tests assert mechanism tokens, not English prose

Test 16 (locks Decision 1's warn-not-block) first tried to forbid the strings "hard block" / "exit non-zero" in the Step 0 region. That false-fired on the skill's own descriptive prose ("this is not a hard block"). Grep can't tell a block instruction from a block description.

Rewrote the negatives to target unambiguous mechanism tokens that only exist if the hard gate is actually built (PreToolUse, check-speckit, vt_skip_speckit_check), plus a positive assertion that the "Continue with standard planning" fallback offer survives (the real anti-block guarantee).

Lesson (durable): captured in external-cli-pinned-and-gated.md pillar 4.

Build-gate #1: v0.11.5 confirmed

uv tool install specify-cli --from git+…@v0.11.5 built clean, CLI functions (init/check/version/self/extension), package version == pin, drift comparison resolves OK. Command surface /speckit.specify|plan|tasks|analyze preserved (research static diff; v0.11.5 only adds converge). No re-pin.