@ikunin/sprintpilot 2.0.6 → 2.0.7

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.
@@ -1,6 +1,6 @@
1
1
  addon:
2
2
  name: sprintpilot
3
- version: 2.0.6
3
+ version: 2.0.7
4
4
  description: Sprintpilot — autopilot and multi-agent addon for BMad Method (git workflow, parallel agents, autonomous story execution)
5
5
  bmad_compatibility: ">=6.2.0"
6
6
  modules:
@@ -52,12 +52,13 @@ const VALID_ACTIONS = ['start', 'end', 'once', 'mark'];
52
52
  // rename target). The constant is gone; runtime always uses per-story
53
53
  // paths.
54
54
  //
55
- // Sanity ceiling for a single duration record. A wall-clock skip
56
- // forward of more than this many ms is treated as clock skew rather
57
- // than a real duration clamped to 0 with `clock_skew: true` stamped.
58
- // 24h chosen because no realistic skill phase is longer than that, and
59
- // it's well above any plausible CI timeout.
60
- const MAX_PLAUSIBLE_DURATION_MS = 24 * 60 * 60 * 1000;
55
+ // Sanity ceiling for a single duration record. Phase durations longer
56
+ // than this are treated as overflow (likely a forgotten _end across
57
+ // sessions or a long-paused autopilot run) and clamped to 0 with
58
+ // `over_threshold: true` stamped. 7 days chosen so legitimate
59
+ // weekend-spanning sprint-level phases (sprint, dispatch.layer-X) are
60
+ // preserved; only genuinely stale markers get clamped.
61
+ const MAX_PLAUSIBLE_DURATION_MS = 7 * 24 * 60 * 60 * 1000;
61
62
 
62
63
  function help() {
63
64
  log.out(
@@ -336,8 +337,14 @@ function markPhase(projectRoot, story, phase, meta) {
336
337
  const prevTs = Date.parse(prev.ts);
337
338
  if (!Number.isNaN(prevTs)) {
338
339
  const rawDelta = now.getTime() - prevTs;
339
- const clamped = rawDelta < 0 || rawDelta > MAX_PLAUSIBLE_DURATION_MS;
340
- durationMs = clamped ? 0 : rawDelta;
340
+ // Two distinct anomalies flagged separately so consumers can
341
+ // treat them differently. clock_skew = wall-clock went backwards
342
+ // (NTP backstep, DST, manual change). over_threshold = elapsed
343
+ // time exceeds the sanity ceiling (likely a stale marker, not
344
+ // genuine clock skew). Both clamp duration_ms to 0.
345
+ const clockSkew = rawDelta < 0;
346
+ const overThreshold = rawDelta > MAX_PLAUSIBLE_DURATION_MS;
347
+ durationMs = clockSkew || overThreshold ? 0 : rawDelta;
341
348
  prevPhase = prev.phase;
342
349
  durationEntry = {
343
350
  event: 'duration',
@@ -347,7 +354,8 @@ function markPhase(projectRoot, story, phase, meta) {
347
354
  ended: now.toISOString(),
348
355
  duration_ms: durationMs,
349
356
  };
350
- if (clamped) durationEntry.clock_skew = true;
357
+ if (clockSkew) durationEntry.clock_skew = true;
358
+ if (overThreshold) durationEntry.over_threshold = true;
351
359
  if (prev.meta !== undefined) durationEntry.meta = prev.meta;
352
360
  }
353
361
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ikunin/sprintpilot",
3
- "version": "2.0.6",
3
+ "version": "2.0.7",
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": {