Speckit.Run

Run a contiguous speckit pipeline sequence with BLOCKING checkpoints at every gate

colin-prologue 1 updated 1mo ago
Claude CodeGeneric
View source ↗
---
description: Run a contiguous speckit pipeline sequence with BLOCKING checkpoints at every gate
---

## Input

`$ARGUMENTS` — parse the following flags:

- `--target <seq>` **(required)** — pipeline subsequence, e.g. `specify→plan→tasks`. Reordering rejected.
- `--checkpoints <list>` *(optional)* — comma-separated non-code gate names to BLOCK. Code-action gates (`implement`, `codereview`, `audit`) always BLOCK regardless.
- `--force` — bypass the spec-exists / no-log guard (FR-023).
- `--break-lock` — surface and clear a stale lock from a prior session.

---

## Initialization

Helper prefix: `.specify/scripts/bash/`. Invoke each helper from the repo root.

1. Run `check-prerequisites.sh --json`. Parse `FEATURE_DIR` (absolute path) from output.
2. Run `run-target.sh validate "$TARGET"`. On exit ≠ 0: print the validation error, stop.
3. If `--break-lock`:
   - Run `run-lock.sh break "$FEATURE_DIR"`. Print the prior lock's `session_id` and `created_at`.
   - Ask: "Confirm prior session is dead and lock can be cleared? (yes/no)." On "no": stop.
4. FR-023 guard (skip if `--force`): if `$FEATURE_DIR/spec.md` exists and `$FEATURE_DIR/decisions-log.md` absent — halt with: "spec.md exists but no decisions-log.md found. Re-invoke with `--force` to start a fresh run."
5. Run `run-lock.sh acquire "$FEATURE_DIR"`. On exit ≠ 0 — halt (§Halt: lock-conflict).
6. Set `STAGE` = first stage in `--target`.

---

## Per-Stage Loop

Repeat until `STAGE = __END__`. On any failure, jump to §TERMINATE with the appropriate kind.

### a. Completeness check

run-completeness.sh "$FEATURE_DIR" "$STAGE"


If output = `complete`: write a `stage-skip` entry to `decisions-log.md`, then route:
```bash
ts=$(date -u +%Y-%m-%dT%H:%M:%SZ)
run_id=$(grep '^run_id=' "$FEATURE_DIR/.run/run-lock" | cut -d= -f2-)
printf '## stage-skip:%s · %s\n\n- author: orchestrator\n- status: success\n- run_id: %s\n\nArtifact present.\n\n' \
    "$STAGE" "$ts" "$run_id" >> "$FEATURE_DIR/decisions-log.md"
run-route.sh "$FEATURE_DIR" stage="$STAGE" criterion="artifact already present"

Advance: STAGE = run-target.sh next "$TARGET" "$STAGE". Continue loop.

b. Emit stage-start

run-emit-event.sh "$FEATURE_DIR" stage-start stage="$STAGE"

c. Store pre-dispatch HEAD (ADR-030)

git rev-parse HEAD > "$FEATURE_DIR/.run/pre-dispatch-head"

d. Code-gate BLOCKING pause

Only if STAGE ∈ {implement, codereview, audit}:

→ about to dispatch: $STAGE
   review the prior stage output in $FEATURE_DIR/decisions-log.md
   type `proceed` to continue or `abort` to stop

Wait for user input. On abort: TERMINATE(abort).

e. Pre-dispatch sentinel check

run-lock.sh check-sentinel "$FEATURE_DIR"

On exit 1 (abort file present): TERMINATE(abort).

f. Dispatch subagent

LOG_OFFSET=$(wc -c < "$FEATURE_DIR/decisions-log.md" 2>/dev/null | tr -d ' ' || echo 0)

Use the Task tool. Pass the following to the subagent:

Feature directory: $FEATURE_DIR (absolute path) Stage: $STAGE

Run /speckit.$STAGE for this feature. Then write a FR-006-conforming record to $FEATURE_DIR/decisions-log.md. Schema: .specify/contracts/decision-log-entry.md. The halt_directive block MUST include:

  • halt: true or halt: false
  • reason: <required when halt=true>
  • failure_class: <required when halt=true — one of: temporal, semantic, permission> Do NOT skip writing the canonical log entry.

Wait for Task completion before proceeding.

Per-stage diff capture:

pre_head=$(cat "$FEATURE_DIR/.run/pre-dispatch-head" 2>/dev/null || true)
if [[ -n "$pre_head" ]]; then
    git diff "$pre_head"..HEAD --name-only > "$FEATURE_DIR/.run/stage-diff-${STAGE}.files"
    git diff "$pre_head"..HEAD             > "$FEATURE_DIR/.run/stage-diff-${STAGE}.patch"
fi

Produces stage-diff-<stage>.files (changed file list, always shown) and stage-diff-<stage>.patch (full diff, read on request). Both live in $FEATURE_DIR/.run/ and are swept by the next run-lock.sh acquire.

Schema validation:

run-validate-entry.sh "$FEATURE_DIR/decisions-log.md" "$LOG_OFFSET"

On exit 1 or 2: TERMINATE(halt) — schema-violation.

g. Post-dispatch checks (code-action stages only)

Only if STAGE ∈ {implement, codereview, audit}:

Sandbox check:

run-check-sandbox.sh "$FEATURE_DIR" "$STAGE"

On exit ≠ 0: TERMINATE(permission-failure) — include violation list in halt message.

Postcheck:

run-postcheck.sh "$FEATURE_DIR" "$STAGE"

On exit 0 (postcheck: no findings): continue to step h. On exit ≠ 0: present findings, then prompt:

postcheck findings above — type `proceed` to override (recorded) or `abort` to stop

On proceed: proceed to step h with POSTCHECK_OVERRIDE=true. On abort: TERMINATE(abort).

h. Route

NEXT_STAGE=$(run-target.sh next "$TARGET" "$STAGE")
run-route.sh "$FEATURE_DIR" from="$STAGE" to="$NEXT_STAGE" reason="subagent complete"

If POSTCHECK_OVERRIDE=true, use reason=postcheck-override instead.

Read stdout:

Verdict Action
continue Advance STAGE → continue loop
halt:<reason> TERMINATE(halt) with that reason
abort TERMINATE(abort)
skip:<stage> Advance STAGE → continue loop

Advance: STAGE = NEXT_STAGE.

When run-target.sh next outputs __END__: TERMINATE(clean).


TERMINATE

On every exit path, run in this order before stopping:

run-serialize.sh "$FEATURE_DIR" <kind>
run-lock.sh release "$FEATURE_DIR"

<kind>: clean | halt | abort | permission-failure

Then present the appropriate halt message (§Halt Messages), or on clean:

Pipeline complete. Stages run: [list]. Artifacts in $FEATURE_DIR.


Halt Messages

Every message is self-contained: stage, failure class, re-trigger command.

subagent-halt-directive

$STAGE halted with blocking findings. Address the findings in $FEATURE_DIR/decisions-log.md, then re-run: `/speckit.run


Maintain Speckit.Run?

Let people know it's listed here — add the badge (live metrics, light/dark aware) or a plain link to your README or docs.

[Speckit.Run on getagentictools](https://getagentictools.com/loops/colin-prologue-speckit-run?ref=badge)