Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 40 additions & 1 deletion AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,46 @@ The per-story flow depends on the active `complexity_profile` in

This policy is enforced by the orchestrator state machine (`_Sprintpilot/lib/orchestrator/state-machine.js` and `adapt.js`) driven from `_Sprintpilot/skills/sprint-autopilot-on/workflow.orchestrator.md`, using profile resolution from `_Sprintpilot/scripts/resolve-profile.js`. When the profile key is absent, the autopilot falls back to `medium`.

### Mandatory sequence per story (all profiles except `nano`)
### Fast lane — sanctioned per-story quick-dev under full profiles (opt-in, default OFF)

When `autopilot.fast_lane.enabled` is `true`, the full profiles (`small`,
`medium`, `large`, `legacy`) may route **individual LOW-RISK stories** through
`bmad-quick-dev` (one-shot) instead of the 7-step cycle, while every
substantial story keeps the full cycle. This is the **same kind of sanctioned,
opt-in exception as `nano`** — not an implicit relaxation of the RED-first
rule. It is **OFF by default**; the installer asks whether to enable it, and
full profiles behave exactly as before when it is off.

A fast-laned story still runs `bmad-create-story` first (only then does it go
to `bmad-quick-dev` instead of the 7-step cycle) — the gate needs the story
file's Acceptance Criteria and declared paths to enforce its guardrails, and
that file doesn't exist until create-story writes it. (nano, by contrast,
skips create-story entirely.)

A story is fast-laned only when a deterministic pre-story gate
(`_Sprintpilot/lib/orchestrator/fast-lane-gate.js`) says so. The gate is
**conservative — it defaults to `full` on any uncertainty**:

- more Acceptance Criteria than `fast_lane.max_ac` → full;
- any declared path matching a `deny_globs` entry (auth / migrations /
secrets) → full, even if the story is tagged `fast_lane: true`;
- inference only routes `fast` when **every** path the story declares is
covered by `allow_globs`;
- an explicit story tag (`fast_lane: true|false` / `risk: low|high`) can force
the decision (a `full`-forcing tag always wins over a `fast` one).

Guardrails that still hold on a fast-laned story: **tests are still required**
(`verifyNanoQuickDev` needs `tests_run > 0`, a commit SHA, and
sprint-status `done`). If the story's quick-dev run **fails outright**, the
autopilot re-runs the full 7-step cycle for it (from `bmad-create-story`); if it
**completes but reports failing tests or a high-severity finding**, the
autopilot routes it through the full adversarial `bmad-code-review` it skipped.
Either way the story is remembered (`fast_lane_forced_full`) so it is never
re-fast-laned — a misclassified story self-corrects rather than shipping
unreviewed. Every routing choice is auditable via the `fast_lane_decision`
ledger entry.

### Mandatory sequence per story (all profiles except `nano`, and non-fast-laned stories under the fast lane)

1. `bmad-create-story` — story file complete
2. `bmad-check-implementation-readiness` — no blockers
Expand Down
3 changes: 3 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,8 @@ The orchestrator separates **decision logic** (deterministic, pure, fully tested
- `state-store.js` — the **single chokepoint** for `autopilot-state.yaml` writes. `coalesce_state_writes` splits CRITICAL_KEYS (write-through) from non-critical (buffered, flushed at story boundary). Atomic write via tmp + rename. **Deep-merges; cannot delete a nested key** — that constraint is why `excluded-stories.json` is its own file rather than a field on `autopilot-state.yaml`.
- `action-ledger.js` — append-only JSONL audit at `_bmad-output/implementation-artifacts/ledger.jsonl`. Unknown kinds are tolerated by consumers; add new kinds freely.
- `excluded-stories.js` — Sprintpilot-owned authoritative exclusion ledger. Resolver consults it; `apply_user_commands` populates from `skip_story` / `remove_from_sprint`; `reconcileFromSprintStatus` folds sprint-status terminal-non-done values in. Designed to survive BMad-side clobbers.
- `fast-lane-gate.js` — pure, deterministic pre-story classifier for the opt-in quick-dev fast lane (default OFF). `(story signals + fast_lane config + forced-full ledger) → fast|full`, conservative (defaults `full`). The CLI (`deriveEffectiveProfile` in `autopilot.js`) reads the story file + `fast_lane_*` profile fields and flips `implementation_flow` to `quick` per-story when the gate says `fast`; a fast-laned quick-dev failure escalates via `escalateOnFailure` (`escalated_from: 'fast_lane'`) and records the story in `state.fast_lane_forced_full` so it re-runs the full cycle and never re-fast-lanes.
- `fast-lane-overrides.js` — Sprintpilot-owned, durable per-story/epic `fast|full` marks (`fast-lane-overrides.json`), clobber-resistant like `excluded-stories.js`. The highest-authority routing signal: `deriveEffectiveProfile` consults it before the gate (a `fast` mark beats deny-globs/size/tags and applies even when the lane is off; `fast_lane_forced_full` still wins to prevent loops). Set via the `set_fast_lane` UserCommand, the `autopilot fast-lane` CLI, or `/sprintpilot-plan-sprint`.
- `user-commands.js` / `user-command-applier.js` — validates and applies `UserCommand`s. The applier is pure: `(state, profile, commands) → { newState, newProfile, sideEffects }`. The CLI runs the side-effects.
- `sprint-plan.js` + `_Sprintpilot/scripts/sprint-plan.js` — dependency-aware plan and the mirror parser. `TERMINAL_STATUSES` is duplicated across `autopilot.js` and `sprint-plan.js`; tests assert the mirror.

Expand Down Expand Up @@ -87,6 +89,7 @@ Knowing who writes what is critical to avoid stepping on BMad's domain:
| `autopilot-state.yaml` | Sprintpilot | Volatile per-session state; deep-merged, never wholesale-replaced. |
| `ledger.jsonl` | Sprintpilot | Append-only audit. |
| `excluded-stories.json` | Sprintpilot | Durable exclusion ledger; replace-on-write semantics. |
| `fast-lane-overrides.json` | Sprintpilot | Durable per-story/epic fast\|full marks; replace-on-write; clobber-resistant (survives re-plan). |
| `sprint-plan.yaml` | Sprintpilot | Dependency-aware plan; validated against the DAG. |
| `decision-log.yaml` | Sprintpilot | Per-phase decisions audit. |
| `flaky-quarantine.yaml` | Sprintpilot | Flaky test flip counts + quarantine. |
Expand Down
10 changes: 10 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ Sprintpilot turns a planned BMad sprint into merged, reviewed, tested code **wit

**`nano` profile** swaps the 7-step cycle for BMad's one-shot `bmad-quick-dev` (Implement → Review → Classify → Commit) — and automatically escalates back to the full cycle if its tests fail or its review flags a high-severity finding.

**The quick-dev fast lane (opt-in, default OFF)** brings that speed to the full profiles *per story*: a conservative pre-story gate routes genuinely low-risk stories (docs, tiny config, small pure functions) through one-shot `bmad-quick-dev` while substantial stories keep the full 7-step cycle. The story spec is still written first (`bmad-create-story`) so the gate can judge it from real acceptance criteria and declared paths; the gate defaults to `full` on any doubt and hard-denies auth / migrations / secrets. Tests remain required, and a fast-laned story that fails re-runs the full cycle (or, if it completed but flagged a problem, gets the adversarial code review it skipped). Off unless you enable it at install; every routing choice is auditable and shown in `autopilot progress`.

**You control the loop, not the steps.** The autopilot drives continuously until it has completed `session_story_limit` stories (default 3), the sprint is finished, or it hits one of five genuine blockers — then it halts cleanly with a handoff report. Steer it mid-flight in plain language ("skip this story, the spec is wrong", "pause", "land before the next story") and it maps that to the right action. Under the hood a deterministic Node state machine (`_Sprintpilot/bin/autopilot.js`) decides what runs next and enforces the sequence; the LLM owns in-skill execution and small-judgment calls. Sprintpilot never invents workflows of its own — it composes BMad's skills.

**The benefit:** a planned sprint implements itself overnight with TDD, multi-reviewer code review, and your real git process applied to every story — instead of you hand-running `create-story → readiness → dev → review → patch → commit → PR` dozens of times. You review PRs and answer the occasional genuine question; the autopilot does the mechanical execution faithfully and auditably (every action is logged to an append-only ledger).
Expand Down Expand Up @@ -122,6 +124,8 @@ Pick at install: `--profile <name>`. Missing profile defaults to `medium`.

**Nano safety net:** if `bmad-quick-dev` tests fail or its review classifies a finding as `high` severity, the autopilot escalates that session to the full 7-step cycle (session-scoped, never written back to config).

**Fast lane (opt-in, default OFF):** the full profiles (`small`/`medium`/`large`) can route *individual* low-risk stories — docs, tiny config, small pure-function additions — through one-shot `bmad-quick-dev` while substantial stories keep the full 7-step cycle. Each fast-lane candidate still runs `bmad-create-story` first, then a conservative pre-story gate decides `fast | full` from its real acceptance criteria and declared paths (defaulting to `full` on any doubt, hard-denying auth/migrations/secrets, and honoring an AC-count budget + explicit story/epic tags). Tests stay required; a fast-laned story that **fails** re-runs the full cycle, and one that **completes but flags a problem** gets routed through the adversarial code review it skipped. The installer asks whether to enable it (and for the `max_ac` budget); per-project knobs live under `autopilot.fast_lane.*`, and counts show in `autopilot progress`. See [docs/quick-dev-fast-lane-plan.md](docs/quick-dev-fast-lane-plan.md).

## Running a session

The autopilot scans the host chat for your interjections every turn — you can steer it without learning a command vocabulary:
Expand Down Expand Up @@ -187,6 +191,11 @@ Most projects only ever change a handful of settings. Pick the change you want,
| `complexity_profile` | `autopilot/config.yaml` | `medium` | Per-story flow + which optimization layers are enabled |
| `autopilot.session_story_limit` | `autopilot/config.yaml` | `3` (nano: `5`) | Stories per session before checkpoint. `0` = unlimited |
| `autopilot.retrospective_mode` | `autopilot/config.yaml` | `auto` | `auto` / `stop` / `skip` |
| `autopilot.fast_lane.enabled` | `autopilot/config.yaml` | `false` | Route low-risk stories through one-shot quick-dev under full profiles (installer prompts) |
| `autopilot.fast_lane.max_ac` | `autopilot/config.yaml` | `3` | Stories with more Acceptance Criteria never fast-lane |
| `autopilot.fast_lane.allow_globs` | `autopilot/config.yaml` | `"docs/**,**/*.md"` | Inference only fast-lanes when every declared path is allow-listed (comma-sep) |
| `autopilot.fast_lane.deny_globs` | `autopilot/config.yaml` | `"**/auth/**,**/migrations/**,**/*secret*,**/*secret*/**"` | Any declared path matching forces `full` — hard safety |
| `autopilot.fast_lane.require_story_tag` | `autopilot/config.yaml` | `false` | Only fast-lane stories explicitly tagged `fast_lane: true` / `risk: low` |
| `git.merge_strategy` | `git/config.yaml` | `stacked` | `stacked` / `land_as_you_go` |
| `git.push.create_pr` | `git/config.yaml` | `true` | `false` = direct merge to base |
| `git.reuse_user_branch` | `git/config.yaml` | `false` | Commit every story onto the current user branch |
Expand Down Expand Up @@ -425,6 +434,7 @@ Skill internals + output schemas: [docs/USAGE.md](docs/USAGE.md#multi-agent-skil
- [Sprint Planning Reference](docs/sprint-planning.md) — focused guide to `/sprintpilot-plan-sprint`: curation, validation, mid-flight commands, companion skills
- [Architecture](docs/ARCHITECTURE.md) — state machine, action / signal vocabulary, verify contracts
- [Configuration Reference](docs/CONFIGURATION.md) — every setting, default, profile override
- [Quick-Dev Fast Lane](docs/quick-dev-fast-lane-plan.md) — per-story quick-dev routing under full profiles: gate, guardrails, escalation
- [Extending (Platforms & Languages)](docs/EXTENDING.md)
- [Contributing](docs/CONTRIBUTING.md)
- [Changelog](CHANGELOG.md)
Expand Down
20 changes: 20 additions & 0 deletions _Sprintpilot/Sprintpilot.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,11 @@ Edit `_Sprintpilot/modules/autopilot/config.yaml`:
| `autopilot.retrospective_mode` | `auto` | `auto` / `stop` / `skip` | How epic-end retrospectives are handled (see below). |
| `autopilot.auto_infer_dependencies` | `false` (was `true` pre-v2.3.0) | bool | **Legacy flag — superseded by `auto_plan_on_start` in v2.3.0.** See "Sprint Planning + DAG-Aware Execution" below. |
| `autopilot.auto_plan_on_start` | `false` | bool | **v2.3.0.** When `true`, `autopilot start` emits `invoke_skill: sprintpilot-plan-sprint` on greenfield projects (no `sprint-plan.yaml`). Default `false`: missing plan → fall back to sprint-status order. Once a plan exists, staleness triggers auto-derive regardless of this knob. |
| `autopilot.fast_lane.enabled` | `false` | bool | **Fast lane.** When `true`, a full profile (`small`/`medium`/`large`) may route *individual* low-risk stories through one-shot `bmad-quick-dev` instead of the 7-step cycle. A conservative pre-story gate decides `fast\|full` (defaults `full` on doubt); any failure bounces the story back to the full cycle and remembers it. Prompted at install. See "Fast lane" below. |
| `autopilot.fast_lane.max_ac` | `3` | integer ≥ 0 | Stories with more Acceptance Criteria than this never fast-lane (a size gate that beats an explicit fast tag). |
| `autopilot.fast_lane.allow_globs` | `"docs/**,**/*.md"` | comma-sep globs | A story only *infers* `fast` when every path it declares is allow-listed here. |
| `autopilot.fast_lane.deny_globs` | `"**/auth/**,**/migrations/**,**/*secret*,**/*secret*/**"` | comma-sep globs | Any declared path matching these forces `full` — hard safety, beats a fast tag. |
| `autopilot.fast_lane.require_story_tag` | `false` | bool | When `true`, only stories explicitly tagged `fast_lane: true` / `risk: low` fast-lane. |
| `git.lock.stale_timeout_minutes` | `30` | integer ≥ 0 | `.autopilot.lock` older than this is auto-taken-over by the next session. `0` disables auto-takeover (locks held until released manually). |
| `git.worktree.health_check_on_boot` | `true` | bool | At session start, scan `.worktrees/` for orphans from crashed sessions and halt with a prune hint when any are found. |
| `git.worktree.cleanup_on_merge` | `true` | bool | After an epic merges, prune worktree metadata and remove `.worktrees/<key>/` directories whose branches no longer exist locally or on origin. |
Expand All @@ -55,6 +60,21 @@ Edit `_Sprintpilot/modules/autopilot/config.yaml`:

Both settings are prompted during `sprintpilot install` (interactive mode) with existing values as defaults, so reinstalls preserve your choices.

#### Fast lane (per-story quick-dev under full profiles)

**Default OFF.** When `autopilot.fast_lane.enabled` is true, a deterministic pre-story gate routes **individual low-risk stories** through `bmad-quick-dev` (one-shot) under a full profile, while substantial stories keep the mandatory 7-step cycle. This is a sanctioned, opt-in relaxation of the RED-first rule — the same kind of exception as `nano`, not a silent skip. The installer asks whether to enable it.

How a story is routed (the gate is conservative — **any uncertainty → `full`**):

- more Acceptance Criteria than `max_ac` → `full` (beats a fast tag);
- any declared path matching `deny_globs` (auth / migrations / secrets) → `full`, even against an explicit fast tag;
- inference routes `fast` only when **every** path the story declares is covered by `allow_globs`;
- an explicit tag forces the decision — in the story file (`fast_lane: true` / `risk: low|high`) or on the story's **epic entry** in `sprint-plan.yaml` (story-file tag wins). A `full`-forcing tag always beats a `fast` one.

**Guardrails.** Tests are still required (`verifyNanoQuickDev` needs `tests_run > 0`, a commit SHA, and sprint-status `done`). If a fast-laned quick-dev run **fails, reports failing tests, or flags a high-severity finding**, the autopilot bounces that story back to the full 7-step cycle (re-running `bmad-create-story` → the 7 steps) and records it in `fast_lane_forced_full` so it never re-fast-lanes. The re-run carries an escalation note telling the dev step it's hardening existing committed code, not doing greenfield RED.

**Auditing.** Every routing choice is a `fast_lane_decision` ledger entry; `autopilot progress` and the session report show fast-laned and escalated counts.

### Sprint Planning + DAG-Aware Execution (v2.3.0)

`/sprintpilot-plan-sprint` builds the authoritative sprint plan at `_bmad-output/implementation-artifacts/sprint-plan.yaml`. The plan persists per-epic dependencies, cross-epic edges, per-story `plan_status`, priorities, and optional external issue-tracker links. BMad's `sprint-status.yaml` remains the source of truth for *what stories exist*; the plan is the source of truth for *what runs next, in what order, and with what dependencies*.
Expand Down
Loading
Loading