@ikunin/sprintpilot 2.2.31 → 2.3.1

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.
Files changed (47) hide show
  1. package/README.md +228 -415
  2. package/_Sprintpilot/Sprintpilot.md +76 -8
  3. package/_Sprintpilot/bin/autopilot.js +734 -68
  4. package/_Sprintpilot/lib/orchestrator/action-ledger.js +208 -0
  5. package/_Sprintpilot/lib/orchestrator/adapt.js +93 -15
  6. package/_Sprintpilot/lib/orchestrator/profile-rules.js +7 -16
  7. package/_Sprintpilot/lib/orchestrator/sprint-plan.js +488 -0
  8. package/_Sprintpilot/lib/orchestrator/state-store.js +9 -5
  9. package/_Sprintpilot/lib/orchestrator/user-command-applier.js +78 -0
  10. package/_Sprintpilot/lib/orchestrator/user-commands.js +114 -0
  11. package/_Sprintpilot/lib/orchestrator/verify.js +10 -17
  12. package/_Sprintpilot/manifest.yaml +4 -3
  13. package/_Sprintpilot/modules/autopilot/profiles/_base.yaml +18 -4
  14. package/_Sprintpilot/modules/git/config.yaml +15 -9
  15. package/_Sprintpilot/modules/ma/config.yaml +29 -27
  16. package/_Sprintpilot/scripts/dispatch-layer.js +12 -15
  17. package/_Sprintpilot/scripts/infer-dependencies.js +706 -254
  18. package/_Sprintpilot/scripts/log-timing.js +6 -10
  19. package/_Sprintpilot/scripts/merge-shards.js +21 -23
  20. package/_Sprintpilot/scripts/post-green-gates.js +3 -1
  21. package/_Sprintpilot/scripts/resolve-dag.js +452 -280
  22. package/_Sprintpilot/scripts/sprint-plan.js +1068 -0
  23. package/_Sprintpilot/scripts/state-shard.js +13 -5
  24. package/_Sprintpilot/scripts/summarize-timings.js +2 -3
  25. package/_Sprintpilot/skills/sprint-autopilot-on/SKILL.md +30 -2
  26. package/_Sprintpilot/skills/sprint-autopilot-on/workflow.orchestrator.md +36 -10
  27. package/_Sprintpilot/skills/sprintpilot-codebase-map/agents/architecture-mapper.md +10 -8
  28. package/_Sprintpilot/skills/sprintpilot-codebase-map/agents/concerns-hunter.md +11 -9
  29. package/_Sprintpilot/skills/sprintpilot-codebase-map/agents/integration-mapper.md +11 -9
  30. package/_Sprintpilot/skills/sprintpilot-codebase-map/agents/quality-assessor.md +10 -8
  31. package/_Sprintpilot/skills/sprintpilot-codebase-map/agents/stack-analyzer.md +11 -9
  32. package/_Sprintpilot/skills/sprintpilot-codebase-map/workflow.md +1 -1
  33. package/_Sprintpilot/skills/sprintpilot-dependency-graph/SKILL.md +63 -0
  34. package/_Sprintpilot/skills/sprintpilot-dependency-graph/workflow.md +227 -0
  35. package/_Sprintpilot/skills/sprintpilot-plan-sprint/SKILL.md +67 -0
  36. package/_Sprintpilot/skills/sprintpilot-plan-sprint/workflow.md +435 -0
  37. package/_Sprintpilot/skills/sprintpilot-sprint-progress/SKILL.md +53 -0
  38. package/_Sprintpilot/skills/sprintpilot-sprint-progress/workflow.md +169 -0
  39. package/lib/commands/install.js +186 -12
  40. package/package.json +1 -1
  41. package/_Sprintpilot/skills/sprintpilot-code-review/SKILL.md +0 -6
  42. package/_Sprintpilot/skills/sprintpilot-code-review/agents/acceptance-auditor.md +0 -51
  43. package/_Sprintpilot/skills/sprintpilot-code-review/agents/blind-hunter.md +0 -39
  44. package/_Sprintpilot/skills/sprintpilot-code-review/agents/edge-case-hunter.md +0 -46
  45. package/_Sprintpilot/skills/sprintpilot-code-review/workflow.md +0 -111
  46. package/_Sprintpilot/skills/sprintpilot-party-mode/SKILL.md +0 -6
  47. package/_Sprintpilot/skills/sprintpilot-party-mode/workflow.md +0 -138
@@ -47,10 +47,8 @@ const META_MAX_BYTES = 2048;
47
47
  const LINE_MAX_BYTES = 4096; // POSIX PIPE_BUF floor — single write() is atomic
48
48
  const VALID_ACTIONS = ['start', 'end', 'once', 'mark'];
49
49
  // Marker filenames are `.mark.<story>.json` — built by `markerPath()`.
50
- // Pre-2.0.5 used a single global `.mark.json`, which corrupted timing
51
- // data under parallel dispatch (concurrent sub-agents racing on one
52
- // rename target). The constant is gone; runtime always uses per-story
53
- // paths.
50
+ // Per-story paths so parallel dispatch (concurrent sub-agents) can't
51
+ // race on a shared rename target.
54
52
  //
55
53
  // Sanity ceiling for a single duration record. Phase durations longer
56
54
  // than this are treated as overflow (likely a stale marker from an
@@ -304,12 +302,10 @@ function clearMarker(projectRoot, story) {
304
302
  * for a given story emits no duration record — there's no "previous
305
303
  * phase" yet for that story.
306
304
  *
307
- * Pre-2.0.5 used a single global marker file shared across stories,
308
- * which under parallel dispatch (sub-agents marking different stories
309
- * concurrently against the same project root) raced on a single file —
310
- * one rename clobbered the other and durations were attributed to the
311
- * wrong (story, phase). Per-story markers eliminate the race entirely:
312
- * each story has its own marker file `.mark.<story>.json`.
305
+ * Per-story marker files (`.mark.<story>.json`) ensure parallel
306
+ * dispatch is race-free sub-agents marking different stories
307
+ * concurrently never share a rename target, so durations are always
308
+ * attributed to the correct (story, phase) pair.
313
309
  *
314
310
  * Use phase = "_end" to close THIS story's last open phase without
315
311
  * starting a new one (e.g. at sprint-complete time, or per-story
@@ -76,17 +76,17 @@ function implArtifactsDir(projectRoot) {
76
76
  // Cross-process merge lock
77
77
  // ──────────────────────────────────────────────────────────────────
78
78
  //
79
- // Pre-2.0.8 two concurrent merge invocations would each compute the
80
- // merge in-memory then both rename their tmp file over autopilot-state
81
- // .yaml. Tmp filenames are unique, so the renames never collided on
82
- // the source — but the LAST rename wins on the destination, and the
83
- // earlier merge (potentially with newer shard data) was clobbered.
84
- // Combined with the archive race below, the loser's archived shards
85
- // were also gone silent state rewind.
79
+ // Two concurrent merge invocations would each compute the merge in
80
+ // memory then both rename their tmp file over autopilot-state.yaml.
81
+ // Tmp filenames are unique so renames don't collide on the source,
82
+ // but the LAST rename wins on the destination the earlier merge
83
+ // (potentially with newer shard data) would be clobbered. Combined
84
+ // with archive races below, the loser's archived shards would also
85
+ // vanish a silent state rewind.
86
86
  //
87
- // The fix: a sibling lock file. If another invocation holds the lock,
88
- // either wait briefly + retry, or fail with a clear message naming
89
- // the holder's pid and start time so the operator can diagnose.
87
+ // A sibling lock file serializes merges. If another invocation holds
88
+ // the lock, callers wait briefly + retry, or fail with a clear message
89
+ // naming the holder's pid and start time so the operator can diagnose.
90
90
 
91
91
  const MERGE_LOCK_FILE = '.merge-shards.lock';
92
92
  const STALE_LOCK_AGE_MS = 5 * 60 * 1000; // 5 minutes — merges are fast
@@ -186,10 +186,10 @@ function compareStamps(a, b) {
186
186
  }
187
187
 
188
188
  // Snapshot file stat at read time so we can verify it's unchanged
189
- // before archiving. Pre-2.0.8: a worker writing a fresh shard between
190
- // merge-read and archive-rename would have its shard moved into
191
- // .archive/ without ever being folded into the merged YAML — silent
192
- // data loss under parallel dispatch.
189
+ // before archiving. Without the guard, a worker writing a fresh shard
190
+ // between merge-read and archive-rename would have its shard moved
191
+ // into .archive/ without being folded into the merged YAML —
192
+ // silent data loss under parallel dispatch.
193
193
  function snapshotShard(file) {
194
194
  try {
195
195
  const st = fs.statSync(file);
@@ -242,10 +242,8 @@ function mergeStateShards(projectRoot) {
242
242
  }
243
243
 
244
244
  // Parse a timestamp string defensively: malformed `ts` returns 0
245
- // rather than NaN (which Array.sort treats unpredictably). Pre-2.0.8
246
- // `Date.parse('not-a-date')` returned NaN, NaN comparisons returned
247
- // 0, and entries clustered in undefined order — the documented
248
- // "sort by ts ascending" claim was silently violated.
245
+ // rather than NaN (which Array.sort treats unpredictably; NaN
246
+ // comparisons always return 0 and entries cluster in undefined order).
249
247
  function tsToMs(ts) {
250
248
  if (!ts) return 0;
251
249
  const v = Date.parse(ts);
@@ -281,11 +279,11 @@ function mergeDecisionShards(projectRoot) {
281
279
  }
282
280
  snapshots[story] = snap;
283
281
  }
284
- // Deterministic dedup: sort by (id asc, ts DESC) first, then keep the
285
- // first entry for each id — that's the latest-by-ts. Pre-2.0.8 the
286
- // dedup was iteration-order-dependent (filesystem readdir order is
287
- // unspecified), so identical inputs produced different outputs across
288
- // OSes. Idempotency claim was filesystem-dependent.
282
+ // Deterministic dedup: sort by (id asc, ts DESC) first, then keep
283
+ // the first entry for each id — that's the latest-by-ts. The
284
+ // explicit sort avoids depending on filesystem readdir order, which
285
+ // is unspecified and varies by OS, so identical inputs always
286
+ // produce identical outputs.
289
287
  entries.sort((a, b) => {
290
288
  const ai = a.id !== undefined && a.id !== null ? String(a.id) : '';
291
289
  const bi = b.id !== undefined && b.id !== null ? String(b.id) : '';
@@ -20,7 +20,9 @@
20
20
  // --output-limit: max lines of lint output per gate (forwarded to
21
21
  // lint-changed.js as --limit). Honors
22
22
  // `git.lint.output_limit` from config when called
23
- // from the orchestrator (v2.2.28+).
23
+ // from the orchestrator.
24
+ // --linters-json: per-language linter map (forwarded to
25
+ // lint-changed.js). See git.lint.linters.
24
26
  //
25
27
  // Each gate runs in a child process via execFileSync. Argv-only — no shell.
26
28