@ikunin/sprintpilot 2.0.10 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +245 -10
- package/_Sprintpilot/Sprintpilot.md +1 -1
- package/_Sprintpilot/bin/autopilot.js +581 -0
- package/_Sprintpilot/lib/orchestrator/action-ledger.js +148 -0
- package/_Sprintpilot/lib/orchestrator/adapt.js +502 -0
- package/_Sprintpilot/lib/orchestrator/decision-log.js +224 -0
- package/_Sprintpilot/lib/orchestrator/divergence.js +201 -0
- package/_Sprintpilot/lib/orchestrator/git-plan.js +259 -0
- package/_Sprintpilot/lib/orchestrator/impact-classifier.js +108 -0
- package/_Sprintpilot/lib/orchestrator/land.js +155 -0
- package/_Sprintpilot/lib/orchestrator/parallel-batch.js +99 -0
- package/_Sprintpilot/lib/orchestrator/profile-rules.js +167 -0
- package/_Sprintpilot/lib/orchestrator/report.js +95 -0
- package/_Sprintpilot/lib/orchestrator/state-machine.js +402 -0
- package/_Sprintpilot/lib/orchestrator/state-store.js +260 -0
- package/_Sprintpilot/lib/orchestrator/user-command-applier.js +157 -0
- package/_Sprintpilot/lib/orchestrator/user-commands.js +115 -0
- package/_Sprintpilot/lib/orchestrator/verify.js +397 -0
- package/_Sprintpilot/manifest.yaml +1 -1
- package/_Sprintpilot/modules/git/config.yaml +26 -0
- package/_Sprintpilot/scripts/agent-adapter.js +4 -5
- package/_Sprintpilot/scripts/auto-merge-bmad-docs.js +112 -0
- package/_Sprintpilot/scripts/dispatch-layer.js +12 -8
- package/_Sprintpilot/scripts/infer-dependencies.js +78 -21
- package/_Sprintpilot/scripts/inject-tasks-section.js +4 -3
- package/_Sprintpilot/scripts/land-this-pr.js +110 -0
- package/_Sprintpilot/scripts/lint-test-pitfalls.js +133 -0
- package/_Sprintpilot/scripts/list-remaining-stories.js +1 -1
- package/_Sprintpilot/scripts/log-timing.js +12 -3
- package/_Sprintpilot/scripts/merge-shards.js +32 -12
- package/_Sprintpilot/scripts/post-green-gates.js +187 -0
- package/_Sprintpilot/scripts/preflight-merge.js +2 -1
- package/_Sprintpilot/scripts/resolve-dag.js +3 -1
- package/_Sprintpilot/scripts/stack-snapshot.js +128 -0
- package/_Sprintpilot/scripts/state-shard.js +8 -1
- package/_Sprintpilot/scripts/summarize-timings.js +30 -12
- package/_Sprintpilot/scripts/with-retry.js +17 -5
- package/_Sprintpilot/skills/sprint-autopilot-on/SKILL.md +23 -1
- package/_Sprintpilot/skills/sprint-autopilot-on/workflow.orchestrator.md +148 -0
- package/lib/core/update-check.js +11 -1
- package/package.json +1 -1
- package/_Sprintpilot/skills/sprint-autopilot-on/workflow.md +0 -1388
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
# Sprintpilot — ON (Orchestrator Mode)
|
|
2
|
+
|
|
3
|
+
You are running under the **orchestrator-driven** autopilot. Flow control is
|
|
4
|
+
owned by `_Sprintpilot/bin/autopilot.js` — a deterministic Node.js
|
|
5
|
+
state machine that enforces the BMad 7-step sequence. You own the
|
|
6
|
+
*in-skill execution, diagnosis, triage, and small-judgment decisions* —
|
|
7
|
+
not the flow.
|
|
8
|
+
|
|
9
|
+
This file is the **≤150-line** authoritative workflow. It is the only
|
|
10
|
+
workflow shipped — the v2.0.x prose `workflow.md` is gone.
|
|
11
|
+
|
|
12
|
+
## The loop
|
|
13
|
+
|
|
14
|
+
Repeat until the orchestrator emits `halt`:
|
|
15
|
+
|
|
16
|
+
1. `node _Sprintpilot/bin/autopilot.js next` → JSON Action.
|
|
17
|
+
2. Execute the Action per the dispatch table below.
|
|
18
|
+
3. While executing, scan the host chat for user interjections. If
|
|
19
|
+
present, record them via a `user_input` signal (step 4) and re-loop.
|
|
20
|
+
4. `node _Sprintpilot/bin/autopilot.js record --signal <json>` → JSON
|
|
21
|
+
`{ action, verdict, phase, profile }`. Use the new action.
|
|
22
|
+
5. If `verdict: prompted` → ask the user the question in `action.prompt`.
|
|
23
|
+
Apply their answer as a `user_input` signal and re-loop.
|
|
24
|
+
6. If `action.type: halt` → STOP. The orchestrator already wrote
|
|
25
|
+
resume state and (when relevant) the fresh-context handoff flag.
|
|
26
|
+
|
|
27
|
+
Never improvise. Never skip a step. Never invent a next action: the
|
|
28
|
+
orchestrator emits it.
|
|
29
|
+
|
|
30
|
+
## Action dispatch
|
|
31
|
+
|
|
32
|
+
| `action.type` | What you do |
|
|
33
|
+
|-------------------|--------------------------------------------------------------------------------------------------|
|
|
34
|
+
| `invoke_skill` | Run the named BMad skill **verbatim from its own body** (e.g. `bmad-create-story`, `bmad-quick-dev`, `bmad-code-review`). `action.template_slots` is a parameter bag (story_key, prior_diagnosis, relevant_decisions, prior_signals_summary, …) — it's input context for BMad's skill, NOT a replacement for the skill's instructions. When `implementation_flow=quick`, you'll receive `invoke_skill: bmad-quick-dev` per story — follow BMad's `step-oneshot.md`. |
|
|
35
|
+
| `run_script` | Execute `action.command` via the host's shell-equivalent. Argv-only — no shell interpolation. |
|
|
36
|
+
| `git_op` | Execute `action.steps` in order. The orchestrator pre-plans every git op (commit_and_push_story, merge_epic, push, fetch, create_branch) via `git-plan.js` and inlines the resulting argv sequence — each step has `args: [cmd, ...argv]`, a `description`, and an optional `retry` policy. Run each step's argv verbatim (NO shell interpolation), halt on first non-retryable failure. Never improvise the git commands or skip a step — `git push` lives in `steps`, not in `op`. |
|
|
37
|
+
| `parallel_batch` | Dispatch each child action concurrently (M6+ hosts only — fall back to sequential otherwise). |
|
|
38
|
+
| `user_prompt` | Ask the user `action.prompt`. Pass the answer back via `user_input` signal. |
|
|
39
|
+
| `halt` | Stop. Honor `action.handoff: 'sprint_finalize_pending'` by ending the session cleanly. |
|
|
40
|
+
| `noop` | Re-loop (state machine advancing without an external effect). |
|
|
41
|
+
|
|
42
|
+
## Signals you emit
|
|
43
|
+
|
|
44
|
+
Wrap everything in `{ "status": "...", ... }` and pass to
|
|
45
|
+
`autopilot record --signal '<json>'`. Optional `decisions[]` on any signal.
|
|
46
|
+
|
|
47
|
+
| `status` | Required fields |
|
|
48
|
+
|-----------------------|--------------------------------------------------------------------------------------------------|
|
|
49
|
+
| `success` | `output?: object` (for `bmad-code-review` MUST include `findings[]` with `action: 'block'\|'patch'\|'defer'`); `next_skill_hint?` |
|
|
50
|
+
| `failure` | `reason`, `diagnosis` (first-class — fed back into next retry), `recoverable: boolean` |
|
|
51
|
+
| `blocked` | `blocker_kind` (one of the 5 TRUE BLOCKERS or recoverable kinds), `details`, `user_input_needed`, `consecutive_count?` |
|
|
52
|
+
| `propose_alternative` | `reason`, `alternative` (full Action object), `urgency_hint?` (raises impact only) |
|
|
53
|
+
| `user_input` | `commands: UserCommand[]` (validated server-side; see user-commands.js) |
|
|
54
|
+
| `verify_override` | `evidence: { decision_log_ref?, explanation, expected_paths? }` — used when verify.js is wrong |
|
|
55
|
+
|
|
56
|
+
## TRUE BLOCKER kinds (per AGENTS.md)
|
|
57
|
+
|
|
58
|
+
`creative_user_input_required`, `new_external_dependency`,
|
|
59
|
+
`consecutive_test_failures` (carry `consecutive_count`),
|
|
60
|
+
`security_architectural_decision`, `contradictory_acceptance_criteria`.
|
|
61
|
+
|
|
62
|
+
Plus recoverable kinds the orchestrator handles deterministically:
|
|
63
|
+
`missing_dependency`, `failed_invariant`, `external_service`, `unknown`.
|
|
64
|
+
|
|
65
|
+
## Decision audit channel
|
|
66
|
+
|
|
67
|
+
Include `decisions[]` on ANY signal to log small judgment calls without
|
|
68
|
+
round-tripping through `propose_alternative`. Each entry has
|
|
69
|
+
`category` (one of: architecture, test-strategy, dependency,
|
|
70
|
+
review-triage, review-accept, halt-recovery, scope, workaround), `impact`
|
|
71
|
+
(low/medium/high), `phase` (e.g. `dev-story:RED`), `decision`, and
|
|
72
|
+
`rationale`. The orchestrator stamps id + timestamp + story
|
|
73
|
+
automatically and appends to `decision-log.yaml`.
|
|
74
|
+
|
|
75
|
+
## Code-review triage
|
|
76
|
+
|
|
77
|
+
When `bmad-code-review` completes, `success.output.findings[]` MUST
|
|
78
|
+
classify each finding:
|
|
79
|
+
|
|
80
|
+
- `action: 'block'` → orchestrator pauses the autopilot. Manual decision required.
|
|
81
|
+
- `action: 'patch'` → orchestrator enters PATCH_APPLY (step 6a) then PATCH_RETEST (step 6b).
|
|
82
|
+
- `action: 'defer'` → recorded but not blocking; story proceeds.
|
|
83
|
+
|
|
84
|
+
This is LLM intelligence the orchestrator routes on — you own the triage.
|
|
85
|
+
|
|
86
|
+
## BMad bookkeeping is enforced
|
|
87
|
+
|
|
88
|
+
`verify.js` checks more than artifact existence — it enforces the BMad
|
|
89
|
+
bookkeeping you'd otherwise be tempted to skip:
|
|
90
|
+
|
|
91
|
+
| Phase | Bookkeeping that MUST be true before you signal `success` |
|
|
92
|
+
|---|---|
|
|
93
|
+
| `create_story` | Story file has `## Acceptance Criteria` (≥1 bullet) AND a `## Tasks` (or `## Tasks/Subtasks`) section with at least one `[ ]` or `[x]` checkbox. |
|
|
94
|
+
| `dev_red` / `dev_green` | Test files exist on disk; runner exit codes match the phase contract; `tests_run` matches the runner's count. |
|
|
95
|
+
| `code_review` | `_bmad-output/reviews/<story_key>.md` exists; `findings[]` carries `{id, severity, category, action: 'block'\|'patch'\|'defer', rationale}` for every finding. |
|
|
96
|
+
| `patch_apply` | Every `patch_finding` id present in `state.patch_findings` is included in `applied_finding_ids`. |
|
|
97
|
+
| `story_done` (and `nano_quick_dev`) | sprint-status.yaml shows this story as `done` (under `development_status.<story_key>` or inline). Story file has zero remaining `[ ]` task boxes — dev-story is responsible for flipping them to `[x]`. `commit_sha` and `branch` reported; `story_key` matches. **`git_steps_completed: true` in success output** — set this ONLY after every step in `action.steps` (the orchestrator's decorated git plan: `git add`, `git commit`, `git push -u origin <branch>`) has exited 0. Skipping `git push` and reporting success leaves the branch unpushed and trips this check. |
|
|
98
|
+
| `retrospective` | `_bmad-output/retrospectives/<epic>.md` exists. |
|
|
99
|
+
|
|
100
|
+
Skipping any of these — even when the code is "obviously done" — produces
|
|
101
|
+
`verify_rejected` in the ledger and the orchestrator re-emits the same
|
|
102
|
+
action with the verifier's issues threaded into the template slot. After
|
|
103
|
+
the per-profile `verify_reject_budget` is exhausted, the session pauses
|
|
104
|
+
for the user.
|
|
105
|
+
|
|
106
|
+
If you're confident verify is wrong (e.g. you renamed a test file per a
|
|
107
|
+
logged decision), emit `verify_override` with `evidence.expected_paths`
|
|
108
|
+
and a `decision_log_ref`. The orchestrator re-runs verify with augmented
|
|
109
|
+
expectations.
|
|
110
|
+
|
|
111
|
+
After N consecutive verify rejections on the same state (profile-
|
|
112
|
+
configured budget), the orchestrator escalates to `user_prompt`.
|
|
113
|
+
|
|
114
|
+
## Git workflow knobs
|
|
115
|
+
|
|
116
|
+
These knobs in `_Sprintpilot/modules/git/config.yaml` change what the
|
|
117
|
+
orchestrator emits as `git_op` / `run_script` actions. Always read them
|
|
118
|
+
from the action payload — do NOT improvise.
|
|
119
|
+
|
|
120
|
+
| Knob | Values | Behavior |
|
|
121
|
+
|---|---|---|
|
|
122
|
+
| `granularity` | `story` (default) / `epic` | Per-unit branch creation (default). Suppressed when `reuse_user_branch=true`. |
|
|
123
|
+
| `reuse_user_branch` | `false` (default) / `true` | If `true`, autopilot detects the current non-base branch on boot and commits **every** story onto it. No `story/*` or `epic/*` branches are created. PR is opened from this branch at sprint-end. |
|
|
124
|
+
| `merge_strategy` | `stacked` (default) / `land_as_you_go` | `stacked` keeps every story-branch open until sprint-end. `land_as_you_go` runs the new `STORY_LAND` state right after STORY_DONE to merge the PR immediately. |
|
|
125
|
+
| `land_when` | `no_wait` / `ci_pass` (default) / `ci_and_review` | Under `land_as_you_go`, when to merge: synchronously, after CI is green, or after CI + an approved review. |
|
|
126
|
+
| `land_wait_minutes` | int (default 30) | Max wait for CI / review under `land_as_you_go`. After this the orchestrator halts and prompts. |
|
|
127
|
+
|
|
128
|
+
On `STORY_LAND` rebase conflicts (base moved during the story), the
|
|
129
|
+
orchestrator auto-rebases the story branch onto latest base. If the
|
|
130
|
+
rebase has conflicts, the orchestrator halts with a `user_prompt`. You
|
|
131
|
+
resolve conflicts manually, then resume autopilot — it retries the
|
|
132
|
+
land step from `state.land_pending`.
|
|
133
|
+
|
|
134
|
+
## Resume
|
|
135
|
+
|
|
136
|
+
On the next `autopilot start`, the orchestrator fingerprints
|
|
137
|
+
`_bmad-output/`, sprint-status.yaml, and per-story branch HEADs against
|
|
138
|
+
the fingerprint recorded at the last halt. Any divergence is emitted as
|
|
139
|
+
`{ kind: 'resume_divergence', differences: ... }`. Forward the diff to
|
|
140
|
+
the user; let them resolve via `user_input` (`force_continue` or
|
|
141
|
+
`override_decision`).
|
|
142
|
+
|
|
143
|
+
## What you must NEVER do
|
|
144
|
+
|
|
145
|
+
- Decide the next BMad step yourself; skip step-6 patch loop; auto-accept
|
|
146
|
+
your own `propose_alternative`; write `autopilot-state.yaml` /
|
|
147
|
+
`ledger.jsonl` directly; commit secrets; use `git push --no-verify`;
|
|
148
|
+
drift from the typed Signal schema.
|
package/lib/core/update-check.js
CHANGED
|
@@ -5,7 +5,17 @@ const PACKAGE_NAME = '@ikunin/sprintpilot';
|
|
|
5
5
|
|
|
6
6
|
function spawnCapture(cmd, args, { timeoutMs = 7000 } = {}) {
|
|
7
7
|
return new Promise((resolve) => {
|
|
8
|
-
|
|
8
|
+
// On Windows, npm ships as `npm.cmd` (a batch shim). Node's `execFile`
|
|
9
|
+
// doesn't resolve `.cmd` / `.bat` extensions through PATHEXT — pass
|
|
10
|
+
// `shell: true` so cmd.exe handles the lookup. Args are hardcoded
|
|
11
|
+
// here so there's no injection risk. (Linux/macOS execFile is fine
|
|
12
|
+
// as-is.)
|
|
13
|
+
const opts = {
|
|
14
|
+
timeout: timeoutMs,
|
|
15
|
+
windowsHide: true,
|
|
16
|
+
shell: process.platform === 'win32',
|
|
17
|
+
};
|
|
18
|
+
const child = execFile(cmd, args, opts, (err, stdout) => {
|
|
9
19
|
if (err) return resolve(null);
|
|
10
20
|
resolve(String(stdout || '').trim());
|
|
11
21
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ikunin/sprintpilot",
|
|
3
|
-
"version": "2.0
|
|
3
|
+
"version": "2.1.0",
|
|
4
4
|
"description": "Sprintpilot — autopilot and multi-agent addon for BMad Method v6: git workflow, parallel agents, autonomous story execution",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"repository": {
|