Specwright Validate: Quality Gates Orchestrator
Runs all enabled validation gates sequentially with evidence management and freshness checks.
Arguments
Parse $ARGUMENTS for:
- •
--gate=<name>— Run only a specific gate (e.g.,--gate=build) - •
--no-stop-on-failure— Continue running gates even if one fails - •
--unlock— Force-clear a stuck pipeline lock
Steps
1. Read Configuration
Read .specwright/config.json to get:
- •
gates.enabled— list of enabled gates (e.g., ["build", "tests", "wiring", "security"]) - •Note: "spec" (spec compliance) gate is always enabled regardless of config
2. Read Workflow State
Read .specwright/state/workflow.json to get current epic context and gate status.
If no active epic: STOP with "No active epic. Run /specwright:specify first."
3. Handle Force Unlock
If --unlock flag present:
- •Clear the
lockfield in workflow.json - •Output "Pipeline lock cleared"
- •Exit
4. Check Pipeline Lock
If lock field exists in workflow.json:
- •Calculate lock age from
lock.sincetimestamp - •If age > 30 minutes: auto-clear stale lock, log warning
- •If age <= 30 minutes: STOP with "Pipeline locked by {lock.skill} since {lock.since}. Use --unlock to force-clear."
5. Acquire Pipeline Lock
Set lock: {"skill": "validate", "since": "<ISO-timestamp>"} in workflow.json.
6. Check Evidence Freshness
For each gate in the gates object of workflow.json:
- •If gate has
lastRuntimestamp older than 5 minutes, mark as stale - •If
--gate=<name>specified, only check that gate - •Log which gates need re-run due to stale evidence
7. Run Gates Sequentially
Determine which gates to run:
- •If
--gate=<name>specified: run ONLY that gate - •Otherwise: run all enabled gates from config + always include "spec"
For each gate in order [review, build, tests, wiring, security, spec], perform the following sequence:
- •Invoke the gate skill using Skill tool:
skill: "gate-{gateName}"(e.g.,gate-build,gate-tests) - •After completion, read
.specwright/state/workflow.jsonand checkgates.{gateName}.status - •Handle result:
- •Status
"FAIL"+ no--no-stop-on-failureflag: release lock, report failure, STOP - •Status
"WARN"+ no--no-stop-on-failure: proceed (non-blocking) - •Status
"PASS": proceed to next gate - •Status
"ERROR"+ no--no-stop-on-failure: release lock, report error, STOP - •Skill not found or invocation failure: mark as
"ERROR", log issue, continue only if--no-stop-on-failureset
- •Status
Note: Skip gates not in the enabled list (except "spec" which always runs).
8. Compile Evidence Report
Read all gate results from workflow.json:
- •Extract status (PASS/WARN/FAIL/ERROR/SKIP) for each gate
- •Extract evidence paths from gate results
- •Calculate overall (precedence: FAIL > ERROR > WARN > PASS): FAIL if any FAIL, ERROR if any ERROR, WARN if any WARN, else PASS
9. Release Pipeline Lock
Clear the lock field in workflow.json.
10. Update Timestamp
Set lastUpdated to current ISO timestamp in workflow.json.
11. Report Results
Output structured summary:
=== VALIDATION RESULTS ===
Gate: review [PASS/WARN/FAIL/ERROR/SKIP] Evidence: {path} Last Run: {timestamp}
Gate: build [PASS/WARN/FAIL/ERROR/SKIP] Evidence: {path} Last Run: {timestamp}
Gate: tests [PASS/WARN/FAIL/ERROR/SKIP] Evidence: {path} Last Run: {timestamp}
Gate: wiring [PASS/WARN/FAIL/ERROR/SKIP] Evidence: {path} Last Run: {timestamp}
Gate: security [PASS/WARN/FAIL/ERROR/SKIP] Evidence: {path} Last Run: {timestamp}
Gate: spec [PASS/WARN/FAIL/ERROR/SKIP] Evidence: {path} Last Run: {timestamp}
Overall: PASS/WARN/FAIL/ERROR
Only show gates that are enabled. Mark disabled gates as SKIP.
Compaction Recovery
If compaction occurs during validation:
- •Read
.specwright/state/workflow.json— check lock and gate status - •If lock exists with skill "validate": resume from where gates left off
- •If some gates have fresh results: skip those, run remaining
Error Handling
| Error | Action |
|---|---|
| No active epic | "No active epic. Run /specwright:specify first." |
| Config missing | "Run /specwright:init first." |
| Gate skill not found/fails to invoke | Mark gate as ERROR (distinct from FAIL), log error, continue if --no-stop-on-failure |
| Lock conflict | Show lock info, suggest --unlock |
Notes
- •Pipeline lock prevents concurrent validation runs
- •5-minute evidence freshness ensures current results
- •Single-gate mode (--gate=) is useful for rapid iteration
- •Stale locks auto-clear after 30 minutes