@ikunin/sprintpilot 2.0.9 → 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/scan.js +109 -13
- 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/_Sprintpilot/skills/sprintpilot-codebase-map/agents/architecture-mapper.md +9 -0
- package/_Sprintpilot/skills/sprintpilot-codebase-map/agents/concerns-hunter.md +9 -0
- package/_Sprintpilot/skills/sprintpilot-codebase-map/agents/integration-mapper.md +9 -0
- package/_Sprintpilot/skills/sprintpilot-codebase-map/agents/quality-assessor.md +9 -0
- package/_Sprintpilot/skills/sprintpilot-codebase-map/agents/stack-analyzer.md +10 -0
- package/_Sprintpilot/skills/sprintpilot-codebase-map/workflow.md +2 -0
- package/_Sprintpilot/skills/sprintpilot-reverse-architect/agents/component-mapper.md +7 -0
- package/_Sprintpilot/skills/sprintpilot-reverse-architect/agents/data-flow-tracer.md +7 -0
- package/_Sprintpilot/skills/sprintpilot-reverse-architect/agents/pattern-extractor.md +7 -0
- package/lib/core/update-check.js +11 -1
- package/package.json +1 -1
- package/_Sprintpilot/skills/sprint-autopilot-on/workflow.md +0 -1388
|
@@ -176,7 +176,12 @@ function pairEvents(events) {
|
|
|
176
176
|
for (const key of Object.keys(openByStoryPhase)) {
|
|
177
177
|
const [story, phase] = key.split('::');
|
|
178
178
|
for (const startMs of openByStoryPhase[key]) {
|
|
179
|
-
orphans.push({
|
|
179
|
+
orphans.push({
|
|
180
|
+
story,
|
|
181
|
+
phase,
|
|
182
|
+
event: 'start-without-end',
|
|
183
|
+
ts: new Date(startMs).toISOString(),
|
|
184
|
+
});
|
|
180
185
|
}
|
|
181
186
|
}
|
|
182
187
|
|
|
@@ -213,14 +218,21 @@ function aggregate(paired) {
|
|
|
213
218
|
withPct.sort((a, b) => b.sum_ms - a.sum_ms);
|
|
214
219
|
const hotspots = withPct.filter((r) => r.pct_of_total > HOTSPOT_THRESHOLD);
|
|
215
220
|
|
|
216
|
-
const stories = Object.keys(paired.stories)
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
.
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
221
|
+
const stories = Object.keys(paired.stories)
|
|
222
|
+
.sort()
|
|
223
|
+
.map((key) => {
|
|
224
|
+
const s = paired.stories[key];
|
|
225
|
+
const wall_ms = s.first !== null && s.last !== null ? s.last - s.first : 0;
|
|
226
|
+
const phaseSum = Object.values(s.phases)
|
|
227
|
+
.flat()
|
|
228
|
+
.reduce((acc, v) => acc + v, 0);
|
|
229
|
+
return {
|
|
230
|
+
story: key,
|
|
231
|
+
wall_ms,
|
|
232
|
+
phase_sum_ms: phaseSum,
|
|
233
|
+
phase_count: Object.keys(s.phases).length,
|
|
234
|
+
};
|
|
235
|
+
});
|
|
224
236
|
|
|
225
237
|
return {
|
|
226
238
|
total_paired_ms: totalPaired,
|
|
@@ -263,7 +275,9 @@ function renderText(report) {
|
|
|
263
275
|
if (report.phases.length === 0) {
|
|
264
276
|
lines.push(' (no paired start/end events)');
|
|
265
277
|
} else {
|
|
266
|
-
lines.push(
|
|
278
|
+
lines.push(
|
|
279
|
+
' phase count sum p50 p95 max %',
|
|
280
|
+
);
|
|
267
281
|
for (const r of report.phases) {
|
|
268
282
|
lines.push(
|
|
269
283
|
` ${r.phase.padEnd(40)} ${String(r.count).padStart(5)} ${fmtMs(r.sum_ms).padStart(6)} ${fmtMs(r.p50_ms).padStart(6)} ${fmtMs(r.p95_ms).padStart(6)} ${fmtMs(r.max_ms).padStart(6)} ${fmtPct(r.pct_of_total).padStart(6)}`,
|
|
@@ -318,7 +332,9 @@ function renderMarkdown(report) {
|
|
|
318
332
|
lines.push('| Story | Wall | Phase sum | # phases |');
|
|
319
333
|
lines.push('|---|---|---|---|');
|
|
320
334
|
for (const s of report.stories) {
|
|
321
|
-
lines.push(
|
|
335
|
+
lines.push(
|
|
336
|
+
`| ${s.story} | ${fmtMs(s.wall_ms)} | ${fmtMs(s.phase_sum_ms)} | ${s.phase_count} |`,
|
|
337
|
+
);
|
|
322
338
|
}
|
|
323
339
|
}
|
|
324
340
|
lines.push('');
|
|
@@ -360,7 +376,9 @@ function renderMarkdown(report) {
|
|
|
360
376
|
lines.push('');
|
|
361
377
|
lines.push('## Anomalies');
|
|
362
378
|
lines.push('');
|
|
363
|
-
lines.push(
|
|
379
|
+
lines.push(
|
|
380
|
+
"_Excluded from p50/p95/max so a single skew/stale-marker doesn't poison aggregates._",
|
|
381
|
+
);
|
|
364
382
|
lines.push('');
|
|
365
383
|
lines.push('| Phase | clock_skew | over_threshold |');
|
|
366
384
|
lines.push('|---|---:|---:|');
|
|
@@ -27,7 +27,8 @@ const log = require('../lib/runtime/log');
|
|
|
27
27
|
const DEFAULT_ATTEMPTS = 3;
|
|
28
28
|
const DEFAULT_MIN_MS = 500;
|
|
29
29
|
const DEFAULT_MAX_MS = 2000;
|
|
30
|
-
const DEFAULT_REF_LOCK_PATTERN =
|
|
30
|
+
const DEFAULT_REF_LOCK_PATTERN =
|
|
31
|
+
/cannot lock ref|Unable to create.*\.lock|Reference already exists|failed to lock|lock\.ref/i;
|
|
31
32
|
|
|
32
33
|
function help() {
|
|
33
34
|
log.out(
|
|
@@ -79,7 +80,15 @@ function runOnce(cmd, args, inherit = false) {
|
|
|
79
80
|
};
|
|
80
81
|
}
|
|
81
82
|
|
|
82
|
-
function runWithRetry({
|
|
83
|
+
function runWithRetry({
|
|
84
|
+
cmd,
|
|
85
|
+
args,
|
|
86
|
+
attempts = DEFAULT_ATTEMPTS,
|
|
87
|
+
minMs = DEFAULT_MIN_MS,
|
|
88
|
+
maxMs = DEFAULT_MAX_MS,
|
|
89
|
+
pattern = DEFAULT_REF_LOCK_PATTERN,
|
|
90
|
+
onAttempt = null,
|
|
91
|
+
}) {
|
|
83
92
|
const actualAttempts = Math.max(1, attempts | 0);
|
|
84
93
|
let last = null;
|
|
85
94
|
for (let i = 0; i < actualAttempts; i++) {
|
|
@@ -107,9 +116,12 @@ function main() {
|
|
|
107
116
|
help();
|
|
108
117
|
process.exit(opts.help ? 0 : 1);
|
|
109
118
|
}
|
|
110
|
-
const attempts =
|
|
111
|
-
|
|
112
|
-
const
|
|
119
|
+
const attempts =
|
|
120
|
+
opts.attempts !== undefined ? Number.parseInt(String(opts.attempts), 10) : DEFAULT_ATTEMPTS;
|
|
121
|
+
const minMs =
|
|
122
|
+
opts['min-ms'] !== undefined ? Number.parseInt(String(opts['min-ms']), 10) : DEFAULT_MIN_MS;
|
|
123
|
+
const maxMs =
|
|
124
|
+
opts['max-ms'] !== undefined ? Number.parseInt(String(opts['max-ms']), 10) : DEFAULT_MAX_MS;
|
|
113
125
|
let pattern = DEFAULT_REF_LOCK_PATTERN;
|
|
114
126
|
if (opts.pattern) {
|
|
115
127
|
try {
|
|
@@ -3,4 +3,26 @@ name: sprint-autopilot-on
|
|
|
3
3
|
description: 'Engage autonomous story execution for BMad Method with git workflow integration. Implements stories end-to-end with automatic branching (git worktrees), commits, linting, and PR creation. Uses standard git worktree commands for story isolation — works with any coding agent. Falls back to stock BMad behavior when git is disabled. Use when user says "/sprint-autopilot-on" or "start autopilot".'
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
-
|
|
6
|
+
## STOP — read this entire file before doing anything
|
|
7
|
+
|
|
8
|
+
Sprintpilot is driven by a deterministic Node.js state machine at
|
|
9
|
+
`_Sprintpilot/bin/autopilot.js`. The LLM owns in-skill execution,
|
|
10
|
+
diagnosis, triage, and small-judgment decisions — not the flow.
|
|
11
|
+
|
|
12
|
+
Follow **`./workflow.orchestrator.md`** verbatim. Flow control lives in
|
|
13
|
+
`_Sprintpilot/bin/autopilot.js` (a Node CLI you call via `autopilot next`
|
|
14
|
+
/ `autopilot record`). The orchestrator emits actions; you execute them.
|
|
15
|
+
|
|
16
|
+
### Never improvise
|
|
17
|
+
|
|
18
|
+
- Never decide which BMad skill runs next yourself — the state machine
|
|
19
|
+
emits an `invoke_skill` action telling you.
|
|
20
|
+
- Never skip the `autopilot next` → `autopilot record` cycle. Even when
|
|
21
|
+
a step feels "obvious," route through the CLI so the ledger, verify,
|
|
22
|
+
and bookkeeping enforcement run.
|
|
23
|
+
- Do not search for `workflow.md` or reconstruct it from memory; do not
|
|
24
|
+
read cached BMad legacy patterns and apply them ahead of the
|
|
25
|
+
orchestrator's state machine.
|
|
26
|
+
|
|
27
|
+
`workflow.orchestrator.md` is the **sole authority** for the rest of the
|
|
28
|
+
session.
|
|
@@ -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.
|
|
@@ -19,6 +19,15 @@ Scan the project at `{{project_root}}` and write your findings to `{{output_file
|
|
|
19
19
|
- `*.key`, `*.pem`, `*.p12` (private keys)
|
|
20
20
|
- `credentials.json`, `service-account.json`
|
|
21
21
|
|
|
22
|
+
## Ignore-file Awareness
|
|
23
|
+
|
|
24
|
+
Before any Glob or Grep, read `{{project_root}}/.gitignore` and
|
|
25
|
+
`{{project_root}}/.aiexclude` if they exist. Treat every non-comment,
|
|
26
|
+
non-negation pattern as an additional excluded path: skip those files and
|
|
27
|
+
directories entirely, do not Read them, and filter them out of pattern search
|
|
28
|
+
results. `scan.js` applies these patterns automatically. Skip negation (`!`)
|
|
29
|
+
lines.
|
|
30
|
+
|
|
22
31
|
## Exploration
|
|
23
32
|
|
|
24
33
|
Use your native file tools (Read, Glob, Grep). The lists below describe what data to collect; pick the appropriate tool for your CLI.
|
|
@@ -20,6 +20,15 @@ Scan the project at `{{project_root}}` and write your findings to `{{output_file
|
|
|
20
20
|
- `credentials.json`, `service-account.json`
|
|
21
21
|
- Files in `.git/` directory
|
|
22
22
|
|
|
23
|
+
## Ignore-file Awareness
|
|
24
|
+
|
|
25
|
+
Before any Glob or Grep, read `{{project_root}}/.gitignore` and
|
|
26
|
+
`{{project_root}}/.aiexclude` if they exist. Treat every non-comment,
|
|
27
|
+
non-negation pattern as an additional excluded path: skip those files and
|
|
28
|
+
directories entirely, do not Read them, and filter them out of pattern search
|
|
29
|
+
results. `scan.js` applies these patterns automatically. Skip negation (`!`)
|
|
30
|
+
lines.
|
|
31
|
+
|
|
23
32
|
## Exploration
|
|
24
33
|
|
|
25
34
|
Use Grep for pattern searches and `scan.js` for aggregations. All Grep calls below should filter to code file types (e.g., `*.ts`, `*.js`, `*.py`, `*.java`, `*.go`, `*.rs`, `*.rb`, `*.cs`, `*.sql`, `*.sps`, `*.spb`, `*.xml`, `*.sh`, `*.c`, `*.h`, `*.cpp`, `*.hpp`, `*.cc`, `*.cxx`, `*.hxx`) and cap each result set (~20-50).
|
|
@@ -21,6 +21,15 @@ Scan the project at `{{project_root}}` and write your findings to `{{output_file
|
|
|
21
21
|
|
|
22
22
|
**DO read**: `.env.example`, `.env.sample`, `.env.template` (safe — contain variable names only)
|
|
23
23
|
|
|
24
|
+
## Ignore-file Awareness
|
|
25
|
+
|
|
26
|
+
Before any Glob or Grep, read `{{project_root}}/.gitignore` and
|
|
27
|
+
`{{project_root}}/.aiexclude` if they exist. Treat every non-comment,
|
|
28
|
+
non-negation pattern as an additional excluded path: skip those files and
|
|
29
|
+
directories entirely, do not Read them, and filter them out of pattern search
|
|
30
|
+
results. `scan.js` applies these patterns automatically. Skip negation (`!`)
|
|
31
|
+
lines.
|
|
32
|
+
|
|
24
33
|
## Exploration
|
|
25
34
|
|
|
26
35
|
Use Grep and Read. Below are the patterns to search for — file-type filters match the original language coverage (`*.ts`, `*.js`, `*.py`, `*.rb`, `*.go`, `*.rs`, `*.java`, `*.sh`, `*.c`, `*.h`, `*.cpp`, `*.hpp`, `*.cc`, `*.cxx`, `*.hxx`, `*.sql`, `*.sps`, `*.spb`, `*.xml`). Cap each result set (~15-30 matches).
|
|
@@ -19,6 +19,15 @@ Scan the project at `{{project_root}}` and write your findings to `{{output_file
|
|
|
19
19
|
- `*.key`, `*.pem`, `*.p12` (private keys)
|
|
20
20
|
- `credentials.json`, `service-account.json`
|
|
21
21
|
|
|
22
|
+
## Ignore-file Awareness
|
|
23
|
+
|
|
24
|
+
Before any Glob or Grep, read `{{project_root}}/.gitignore` and
|
|
25
|
+
`{{project_root}}/.aiexclude` if they exist. Treat every non-comment,
|
|
26
|
+
non-negation pattern as an additional excluded path: skip those files and
|
|
27
|
+
directories entirely, do not Read them, and filter them out of pattern search
|
|
28
|
+
results. `scan.js` applies these patterns automatically. Skip negation (`!`)
|
|
29
|
+
lines.
|
|
30
|
+
|
|
22
31
|
## Exploration
|
|
23
32
|
|
|
24
33
|
Use your native file tools (Read, Glob, Grep) plus the `scan.js` helper for aggregations.
|
|
@@ -20,6 +20,16 @@ Scan the project at `{{project_root}}` and write your findings to `{{output_file
|
|
|
20
20
|
- `credentials.json`, `service-account.json`
|
|
21
21
|
- `*.secret`, `*password*`, `*token*` (in filenames)
|
|
22
22
|
|
|
23
|
+
## Ignore-file Awareness
|
|
24
|
+
|
|
25
|
+
Before any Glob or Grep, read `{{project_root}}/.gitignore` and
|
|
26
|
+
`{{project_root}}/.aiexclude` if they exist. Treat every non-comment,
|
|
27
|
+
non-negation pattern as an additional excluded path: skip those files and
|
|
28
|
+
directories entirely, do not Read them, and filter them out of any pattern
|
|
29
|
+
search results. `scan.js` already applies these patterns automatically — pass
|
|
30
|
+
`--no-respect-ignore-files` only if you have a deliberate reason. Skip negation
|
|
31
|
+
(`!`) lines.
|
|
32
|
+
|
|
23
33
|
## Exploration
|
|
24
34
|
|
|
25
35
|
Gather data using your native file tools (Read, Glob, Grep). The commands below are illustrative — use the equivalent tool from your CLI. Skip files that don't exist; do not fail the task on missing manifests.
|
|
@@ -21,6 +21,8 @@ Complementary, not a replacement. `bmad-document-project` generates comprehensiv
|
|
|
21
21
|
<action>Create output directory `{output_folder}/codebase-analysis` (use your native file-create tool; it will create parent directories as needed). The first `Write` tool call targeting a file inside this directory will auto-create it, so no explicit mkdir is required in practice.</action>
|
|
22
22
|
<action>Determine project root absolute path: `{{project_root}}`</action>
|
|
23
23
|
|
|
24
|
+
<action>Note: each agent reads `{{project_root}}/.gitignore` and `{{project_root}}/.aiexclude` (if present) and treats every listed file/directory as off-limits. The `scan.js` helper applies these patterns automatically; agents apply them to their Glob/Grep operations as well. This prevents inclusion of build artifacts, vendored code, secrets, and explicitly AI-excluded paths in the analysis.</action>
|
|
25
|
+
|
|
24
26
|
---
|
|
25
27
|
|
|
26
28
|
## Step 2 — Launch 5 Analysis Agents in Parallel
|
|
@@ -6,6 +6,13 @@ You are extracting module boundaries and component contracts from an existing co
|
|
|
6
6
|
|
|
7
7
|
Using the architecture-analysis.md analysis as a starting point, go deeper: trace actual imports, identify public APIs, and map the internal dependency graph.
|
|
8
8
|
|
|
9
|
+
## Ignore-file Awareness
|
|
10
|
+
|
|
11
|
+
Before any Glob or Grep, read the project's `.gitignore` and `.aiexclude` if
|
|
12
|
+
they exist. Treat every non-comment, non-negation pattern as an additional
|
|
13
|
+
excluded path: skip those files and directories entirely, do not Read them,
|
|
14
|
+
and filter them out of pattern search results. Skip negation (`!`) lines.
|
|
15
|
+
|
|
9
16
|
## Method
|
|
10
17
|
|
|
11
18
|
1. For each module/directory identified in architecture-analysis.md:
|
|
@@ -6,6 +6,13 @@ You are tracing how data flows through the system — from entry points to stora
|
|
|
6
6
|
|
|
7
7
|
Using architecture-analysis.md and integrations-analysis.md as context, trace the actual request/data paths through the code.
|
|
8
8
|
|
|
9
|
+
## Ignore-file Awareness
|
|
10
|
+
|
|
11
|
+
Before any Glob or Grep, read the project's `.gitignore` and `.aiexclude` if
|
|
12
|
+
they exist. Treat every non-comment, non-negation pattern as an additional
|
|
13
|
+
excluded path: skip those files and directories entirely, do not Read them,
|
|
14
|
+
and filter them out of pattern search results. Skip negation (`!`) lines.
|
|
15
|
+
|
|
9
16
|
## Method
|
|
10
17
|
|
|
11
18
|
1. Start from entry points (routes, CLI handlers, event listeners)
|
|
@@ -6,6 +6,13 @@ You are identifying design patterns, conventions, and architectural decisions em
|
|
|
6
6
|
|
|
7
7
|
Using architecture-analysis.md and stack-analysis.md as context, identify the actual patterns the codebase follows (not what it claims to follow).
|
|
8
8
|
|
|
9
|
+
## Ignore-file Awareness
|
|
10
|
+
|
|
11
|
+
Before any Glob or Grep, read the project's `.gitignore` and `.aiexclude` if
|
|
12
|
+
they exist. Treat every non-comment, non-negation pattern as an additional
|
|
13
|
+
excluded path: skip those files and directories entirely, do not Read them,
|
|
14
|
+
and filter them out of pattern search results. Skip negation (`!`) lines.
|
|
15
|
+
|
|
9
16
|
## Method
|
|
10
17
|
|
|
11
18
|
1. Look for structural patterns: Factory, Repository, Observer, Middleware, Decorator
|
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