@telora/daemon 0.21.82 → 0.21.98

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 (97) hide show
  1. package/build-info.json +7 -3
  2. package/dist/ci/ci-status.d.ts +63 -11
  3. package/dist/ci/ci-status.d.ts.map +1 -1
  4. package/dist/ci/ci-status.js +94 -27
  5. package/dist/ci/ci-status.js.map +1 -1
  6. package/dist/completion/event-phases.d.ts.map +1 -1
  7. package/dist/completion/event-phases.js +5 -3
  8. package/dist/completion/event-phases.js.map +1 -1
  9. package/dist/completion/review-exit-escalations.d.ts +36 -1
  10. package/dist/completion/review-exit-escalations.d.ts.map +1 -1
  11. package/dist/completion/review-exit-escalations.js +81 -0
  12. package/dist/completion/review-exit-escalations.js.map +1 -1
  13. package/dist/completion/review-exit-phase.d.ts +4 -2
  14. package/dist/completion/review-exit-phase.d.ts.map +1 -1
  15. package/dist/completion/review-exit-phase.js +39 -48
  16. package/dist/completion/review-exit-phase.js.map +1 -1
  17. package/dist/completion/status-advance-phase.d.ts.map +1 -1
  18. package/dist/completion/status-advance-phase.js +10 -29
  19. package/dist/completion/status-advance-phase.js.map +1 -1
  20. package/dist/completion/team-lifecycle.d.ts.map +1 -1
  21. package/dist/completion/team-lifecycle.js +8 -2
  22. package/dist/completion/team-lifecycle.js.map +1 -1
  23. package/dist/delivery/delivery-lifecycle.d.ts.map +1 -1
  24. package/dist/delivery/delivery-lifecycle.js +7 -13
  25. package/dist/delivery/delivery-lifecycle.js.map +1 -1
  26. package/dist/delivery/delivery-reconciler-apply.d.ts +80 -66
  27. package/dist/delivery/delivery-reconciler-apply.d.ts.map +1 -1
  28. package/dist/delivery/delivery-reconciler-apply.js +57 -61
  29. package/dist/delivery/delivery-reconciler-apply.js.map +1 -1
  30. package/dist/delivery/external-hold.d.ts +17 -0
  31. package/dist/delivery/external-hold.d.ts.map +1 -1
  32. package/dist/delivery/external-hold.js +30 -2
  33. package/dist/delivery/external-hold.js.map +1 -1
  34. package/dist/delivery/operator-hold.d.ts +1 -2
  35. package/dist/delivery/operator-hold.d.ts.map +1 -1
  36. package/dist/delivery/operator-hold.js +1 -2
  37. package/dist/delivery/operator-hold.js.map +1 -1
  38. package/dist/delivery/wait-reachability.d.ts +149 -0
  39. package/dist/delivery/wait-reachability.d.ts.map +1 -0
  40. package/dist/delivery/wait-reachability.js +182 -0
  41. package/dist/delivery/wait-reachability.js.map +1 -0
  42. package/dist/focus/listener-auto-advance.d.ts.map +1 -1
  43. package/dist/focus/listener-auto-advance.js +10 -55
  44. package/dist/focus/listener-auto-advance.js.map +1 -1
  45. package/dist/focus/listener.d.ts.map +1 -1
  46. package/dist/focus/listener.js +17 -1
  47. package/dist/focus/listener.js.map +1 -1
  48. package/dist/git/merge.d.ts.map +1 -1
  49. package/dist/git/merge.js +12 -3
  50. package/dist/git/merge.js.map +1 -1
  51. package/dist/queries/deliveries.d.ts +10 -0
  52. package/dist/queries/deliveries.d.ts.map +1 -1
  53. package/dist/queries/deliveries.js +1 -0
  54. package/dist/queries/deliveries.js.map +1 -1
  55. package/dist/queries/focuses.d.ts +10 -0
  56. package/dist/queries/focuses.d.ts.map +1 -1
  57. package/dist/queries/focuses.js +15 -0
  58. package/dist/queries/focuses.js.map +1 -1
  59. package/dist/queries/schemas.d.ts +2 -0
  60. package/dist/queries/schemas.d.ts.map +1 -1
  61. package/dist/queries/schemas.js +4 -0
  62. package/dist/queries/schemas.js.map +1 -1
  63. package/dist/shell/heartbeat.d.ts +7 -0
  64. package/dist/shell/heartbeat.d.ts.map +1 -1
  65. package/dist/shell/heartbeat.js +3 -3
  66. package/dist/shell/heartbeat.js.map +1 -1
  67. package/dist/shell/unified-shell.js +1 -1
  68. package/dist/shell/unified-shell.js.map +1 -1
  69. package/dist/spawn/respawn-cycle-escalation.d.ts +41 -0
  70. package/dist/spawn/respawn-cycle-escalation.d.ts.map +1 -0
  71. package/dist/spawn/respawn-cycle-escalation.js +83 -0
  72. package/dist/spawn/respawn-cycle-escalation.js.map +1 -0
  73. package/dist/spawn/spawn-cooldown.d.ts +85 -2
  74. package/dist/spawn/spawn-cooldown.d.ts.map +1 -1
  75. package/dist/spawn/spawn-cooldown.js +73 -10
  76. package/dist/spawn/spawn-cooldown.js.map +1 -1
  77. package/dist/testing/fixtures/index.d.ts +64 -0
  78. package/dist/testing/fixtures/index.d.ts.map +1 -0
  79. package/dist/testing/fixtures/index.js +220 -0
  80. package/dist/testing/fixtures/index.js.map +1 -0
  81. package/dist/update/build-info.d.ts +1 -0
  82. package/dist/update/build-info.d.ts.map +1 -1
  83. package/dist/update/build-info.js +2 -2
  84. package/dist/update/build-info.js.map +1 -1
  85. package/dist/verify/stall-detector-config.d.ts +8 -0
  86. package/dist/verify/stall-detector-config.d.ts.map +1 -1
  87. package/dist/verify/stall-detector-config.js +40 -0
  88. package/dist/verify/stall-detector-config.js.map +1 -1
  89. package/dist/verify/stall-detectors.d.ts +37 -6
  90. package/dist/verify/stall-detectors.d.ts.map +1 -1
  91. package/dist/verify/stall-detectors.js +45 -9
  92. package/dist/verify/stall-detectors.js.map +1 -1
  93. package/dist/verify/verification-feedback.d.ts +3 -4
  94. package/dist/verify/verification-feedback.d.ts.map +1 -1
  95. package/dist/verify/verification-feedback.js +3 -12
  96. package/dist/verify/verification-feedback.js.map +1 -1
  97. package/package.json +3 -3
@@ -1,38 +1,97 @@
1
1
  import { createLogger } from '../shell/log.js';
2
+ import { resolveRespawnCycleMaxHours, resolveRespawnCycleMaxCount, } from '../verify/stall-detector-config.js';
2
3
  const log = createLogger({ module: 'spawn-cooldown' });
3
- /**
4
- * Spawn cooldown: prevents crash loops by tracking recently-torn-down focuses.
5
- *
6
- * When a focus is torn down, it enters a cooldown period before it can be
7
- * respawned. Consecutive teardowns increase the cooldown exponentially
8
- * (1min, 2min, 4min, 8min, capped at 10min).
9
- */
10
4
  const teardownTimestamps = new Map();
11
5
  const SPAWN_COOLDOWN_BASE_MS = 60_000; // 1 minute base cooldown
12
6
  const SPAWN_COOLDOWN_MAX_MS = 10 * 60_000; // 10 minute max cooldown
13
7
  // Entries older than 2x the max cooldown window are definitely expired
14
8
  const COOLDOWN_CLEANUP_THRESHOLD_MS = 2 * SPAWN_COOLDOWN_MAX_MS;
9
+ /** Resolve the terminating bounds from env-config (hours -> ms). */
10
+ function resolveRespawnCycleBounds() {
11
+ return {
12
+ maxTotalMs: resolveRespawnCycleMaxHours() * 3_600_000,
13
+ maxCount: resolveRespawnCycleMaxCount(),
14
+ };
15
+ }
16
+ /**
17
+ * Pure decision: has this teardown streak exhausted its terminating bounds?
18
+ *
19
+ * True when the streak has run for at least `maxTotalMs` since its FIRST
20
+ * teardown, OR has accumulated at least `maxCount` teardowns. Either bound alone
21
+ * terminates the cycle -- duration catches a slow saturated loop; count catches a
22
+ * fast one. Exported for direct unit testing (no clock, no daemon-core).
23
+ */
24
+ export function isRespawnCycleExhausted(entry, nowMs, bounds) {
25
+ if (entry.count >= bounds.maxCount)
26
+ return true;
27
+ return nowMs - entry.firstTime >= bounds.maxTotalMs;
28
+ }
15
29
  /**
16
30
  * Remove stale entries from the teardown map to prevent unbounded growth.
17
31
  * Entries older than 2 * SPAWN_COOLDOWN_MAX_MS are guaranteed to be past
18
32
  * their cooldown window regardless of count.
33
+ *
34
+ * An `exhausted` entry is NEVER cleaned up by age: it latches the terminated
35
+ * cycle into a permanent skip and must survive until clearSpawnCooldown (genuine
36
+ * progress) or a daemon restart, so age-based cleanup would silently re-open the
37
+ * respawn cycle it exists to stop.
19
38
  */
20
39
  function cleanupStaleEntries() {
21
40
  const now = Date.now();
22
41
  for (const [focusId, entry] of teardownTimestamps) {
42
+ if (entry.exhausted)
43
+ continue;
23
44
  if (now - entry.time > COOLDOWN_CLEANUP_THRESHOLD_MS) {
24
45
  teardownTimestamps.delete(focusId);
25
46
  }
26
47
  }
27
48
  }
28
- /** Record a focus teardown for spawn cooldown tracking. */
49
+ /**
50
+ * Record a focus teardown for spawn cooldown tracking.
51
+ *
52
+ * Preserves the streak's firstTime, increments count, and -- when a terminating
53
+ * bound crosses -- latches `exhausted`. Returns the updated entry so the caller
54
+ * can detect the exhaustion edge and file the terminating escalation.
55
+ */
29
56
  export function recordFocusTeardown(focusId) {
30
57
  cleanupStaleEntries();
58
+ const now = Date.now();
31
59
  const existing = teardownTimestamps.get(focusId);
32
60
  const count = existing ? existing.count + 1 : 1;
33
- teardownTimestamps.set(focusId, { time: Date.now(), count });
61
+ const firstTime = existing?.firstTime ?? now;
62
+ const wasExhausted = existing?.exhausted ?? false;
63
+ const exhausted = wasExhausted || isRespawnCycleExhausted({ firstTime, count }, now, resolveRespawnCycleBounds());
64
+ const entry = { firstTime, time: now, count, exhausted };
65
+ teardownTimestamps.set(focusId, entry);
34
66
  const cooldownMs = Math.min(SPAWN_COOLDOWN_BASE_MS * Math.pow(2, count - 1), SPAWN_COOLDOWN_MAX_MS);
35
- log.info(`Focus ${focusId} torn down (count=${count}, cooldown=${Math.round(cooldownMs / 1000)}s)`);
67
+ if (exhausted && !wasExhausted) {
68
+ log.warn(`Focus ${focusId} respawn cycle EXHAUSTED (count=${count}, ` +
69
+ `elapsed=${Math.round((now - firstTime) / 1000)}s): respawns halted pending operator resolution.`);
70
+ }
71
+ else {
72
+ log.info(`Focus ${focusId} torn down (count=${count}, cooldown=${Math.round(cooldownMs / 1000)}s)`);
73
+ }
74
+ return entry;
75
+ }
76
+ /**
77
+ * True once a focus's respawn cycle has crossed its terminating bounds. Distinct
78
+ * from isInSpawnCooldown (which is also true during ordinary rate-limit cooldown):
79
+ * this is the TERMINAL signal the caller uses to file the one-per-focus
80
+ * respawn_cycle_exhausted escalation before skipping the spawn. Read-only.
81
+ */
82
+ export function isRespawnCycleTerminated(focusId) {
83
+ return teardownTimestamps.get(focusId)?.exhausted ?? false;
84
+ }
85
+ /**
86
+ * Read a focus's current teardown-streak descriptor (firstTime + count), or null
87
+ * when no streak is tracked. Used by the respawn_cycle_exhausted escalation to
88
+ * report the elapsed duration and teardown count in its body. Read-only.
89
+ */
90
+ export function getRespawnCycleStreak(focusId) {
91
+ const entry = teardownTimestamps.get(focusId);
92
+ if (!entry)
93
+ return null;
94
+ return { firstTime: entry.firstTime, count: entry.count };
36
95
  }
37
96
  /** Check if a focus is in spawn cooldown. */
38
97
  export function isInSpawnCooldown(focusId) {
@@ -40,6 +99,10 @@ export function isInSpawnCooldown(focusId) {
40
99
  const entry = teardownTimestamps.get(focusId);
41
100
  if (!entry)
42
101
  return false;
102
+ // An exhausted streak is a permanent skip: the rate-limit window no longer
103
+ // applies -- the cycle is terminated, not merely throttled.
104
+ if (entry.exhausted)
105
+ return true;
43
106
  const cooldownMs = Math.min(SPAWN_COOLDOWN_BASE_MS * Math.pow(2, entry.count - 1), SPAWN_COOLDOWN_MAX_MS);
44
107
  if (Date.now() - entry.time > cooldownMs) {
45
108
  return false;
@@ -1 +1 @@
1
- {"version":3,"file":"spawn-cooldown.js","sourceRoot":"","sources":["../../src/spawn/spawn-cooldown.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAE/C,MAAM,GAAG,GAAG,YAAY,CAAC,EAAE,MAAM,EAAE,gBAAgB,EAAE,CAAC,CAAC;AACvD;;;;;;GAMG;AAEH,MAAM,kBAAkB,GAAG,IAAI,GAAG,EAA2C,CAAC;AAC9E,MAAM,sBAAsB,GAAG,MAAM,CAAC,CAAC,yBAAyB;AAChE,MAAM,qBAAqB,GAAG,EAAE,GAAG,MAAM,CAAC,CAAC,yBAAyB;AAEpE,uEAAuE;AACvE,MAAM,6BAA6B,GAAG,CAAC,GAAG,qBAAqB,CAAC;AAEhE;;;;GAIG;AACH,SAAS,mBAAmB;IAC1B,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IACvB,KAAK,MAAM,CAAC,OAAO,EAAE,KAAK,CAAC,IAAI,kBAAkB,EAAE,CAAC;QAClD,IAAI,GAAG,GAAG,KAAK,CAAC,IAAI,GAAG,6BAA6B,EAAE,CAAC;YACrD,kBAAkB,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QACrC,CAAC;IACH,CAAC;AACH,CAAC;AAED,2DAA2D;AAC3D,MAAM,UAAU,mBAAmB,CAAC,OAAe;IACjD,mBAAmB,EAAE,CAAC;IACtB,MAAM,QAAQ,GAAG,kBAAkB,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;IACjD,MAAM,KAAK,GAAG,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAChD,kBAAkB,CAAC,GAAG,CAAC,OAAO,EAAE,EAAE,IAAI,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC;IAC7D,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,CAAC,sBAAsB,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,GAAG,CAAC,CAAC,EAAE,qBAAqB,CAAC,CAAC;IACpG,GAAG,CAAC,IAAI,CAAC,SAAS,OAAO,qBAAqB,KAAK,cAAc,IAAI,CAAC,KAAK,CAAC,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC;AACtG,CAAC;AAED,6CAA6C;AAC7C,MAAM,UAAU,iBAAiB,CAAC,OAAe;IAC/C,mBAAmB,EAAE,CAAC;IACtB,MAAM,KAAK,GAAG,kBAAkB,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;IAC9C,IAAI,CAAC,KAAK;QAAE,OAAO,KAAK,CAAC;IACzB,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,CAAC,sBAAsB,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,CAAC,KAAK,GAAG,CAAC,CAAC,EAAE,qBAAqB,CAAC,CAAC;IAC1G,IAAI,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC,IAAI,GAAG,UAAU,EAAE,CAAC;QACzC,OAAO,KAAK,CAAC;IACf,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,+EAA+E;AAC/E,MAAM,UAAU,kBAAkB,CAAC,OAAe;IAChD,kBAAkB,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;AACrC,CAAC"}
1
+ {"version":3,"file":"spawn-cooldown.js","sourceRoot":"","sources":["../../src/spawn/spawn-cooldown.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,64 @@
1
+ /**
2
+ * Shared test fixtures: typed builders for the daemon's core domain objects.
3
+ *
4
+ * Before this module, makeDelivery / makeIssue / makeConfig were copy-pasted
5
+ * into ~30 test files each, so a single field change to FocusDeliveryInfo /
6
+ * FocusIssueInfo / DaemonConfig meant editing dozens of files. These builders
7
+ * are the single source of truth; a type change is now one edit here.
8
+ *
9
+ * Each builder is a SUPERSET: it takes a `Partial<T>` of overrides spread last,
10
+ * so every existing call site keeps its specificity. The defaults below are the
11
+ * MAJORITY defaults observed across the suite; a file whose local builder used a
12
+ * different default keeps that default by passing it as an override (often via a
13
+ * thin file-local wrapper) so no test changes meaning.
14
+ *
15
+ * NOT included by design: `makeDeps` and `makeContext`. Those names collide
16
+ * across UNRELATED types -- makeDeps builds AdvanceDeliveryDeps /
17
+ * WorktreeStateDeps / SessionHealthDeps / various per-module `opts`; makeContext
18
+ * builds FocusTeamPromptContext / AssemblyContext / EvaluationContext. They are
19
+ * not one builder and cannot be merged into one typed function without a union
20
+ * or `any`, so they stay per-file. (See the delivery loop doc for the survey.)
21
+ */
22
+ import type { DaemonConfig, FocusDeliveryInfo, FocusIssueInfo, FocusExecutionConfig, FocusTeamState } from '../../types/index.js';
23
+ import type { VerificationDeps } from '../../verify/verification-deps.js';
24
+ import type { AutoInjectDeps } from '../../security/security-auto-inject.js';
25
+ import type { CompletionEventDeps } from '../../completion/event.js';
26
+ import type { PrdControllerDeps } from '../../prd/controller.js';
27
+ /**
28
+ * Build a FocusDeliveryInfo. Default executionStatus is 'queued' (the majority
29
+ * default across the suite); pass `{ executionStatus: ... }` for other states.
30
+ */
31
+ export declare function makeDelivery(overrides?: Partial<FocusDeliveryInfo>): FocusDeliveryInfo;
32
+ /**
33
+ * Build a FocusIssueInfo. Defaults to a To Do / Task issue on delivery-1.
34
+ */
35
+ export declare function makeIssue(overrides?: Partial<FocusIssueInfo>): FocusIssueInfo;
36
+ /**
37
+ * Build a DaemonConfig. Single-product, telemetry disabled, integration branch
38
+ * 'integration'. Pass overrides for product/branch/limits specifics.
39
+ */
40
+ export declare function makeConfig(overrides?: Partial<DaemonConfig>): DaemonConfig;
41
+ /**
42
+ * Build a FocusExecutionConfig. Defaults match DEFAULT_EXECUTION_CONFIG
43
+ * (maxWorkers 3, idle 30s, active 60s).
44
+ */
45
+ export declare function makeFocusExecutionConfig(overrides?: Partial<FocusExecutionConfig>): FocusExecutionConfig;
46
+ /**
47
+ * Build a FocusTeamState -- the wide in-memory team record. Centralizes the
48
+ * `makeTeam` / `makeTeamState` helpers that were copy-pasted into the
49
+ * focus-engine / watchdog / stall test files. Defaults to an executing coding
50
+ * team with no live process (leadPid/leadStdin null); pass overrides for the
51
+ * dimension under test. The many OPTIONAL clocks (lastActivityAt, shuttingDownAt,
52
+ * lastHandoffAt, toolActivityCount, ...) are omitted by default -- set them via
53
+ * the focus-team-state helpers or an override.
54
+ */
55
+ export declare function makeFocusTeamState(overrides?: Partial<FocusTeamState>): FocusTeamState;
56
+ /** Seed a VerificationDeps (verify/verification-engine runVerificationTick). */
57
+ export declare function makeVerificationDeps(overrides?: Partial<VerificationDeps>): Partial<VerificationDeps>;
58
+ /** Seed a CompletionEventDeps (completion/event handleCompletionEvent). */
59
+ export declare function makeCompletionEventDeps(overrides?: Partial<CompletionEventDeps>): Partial<CompletionEventDeps>;
60
+ /** Seed an AutoInjectDeps (security/security-auto-inject). */
61
+ export declare function makeAutoInjectDeps(overrides?: Partial<AutoInjectDeps>): Partial<AutoInjectDeps>;
62
+ /** Seed a PrdControllerDeps (prd/controller). */
63
+ export declare function makePrdControllerDeps(overrides?: Partial<PrdControllerDeps>): Partial<PrdControllerDeps>;
64
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/testing/fixtures/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,KAAK,EACV,YAAY,EACZ,iBAAiB,EACjB,cAAc,EACd,oBAAoB,EACpB,cAAc,EACf,MAAM,sBAAsB,CAAC;AAC9B,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,mCAAmC,CAAC;AAC1E,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,wCAAwC,CAAC;AAC7E,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAC;AACrE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAEjE;;;GAGG;AACH,wBAAgB,YAAY,CAAC,SAAS,GAAE,OAAO,CAAC,iBAAiB,CAAM,GAAG,iBAAiB,CAmB1F;AAED;;GAEG;AACH,wBAAgB,SAAS,CAAC,SAAS,GAAE,OAAO,CAAC,cAAc,CAAM,GAAG,cAAc,CAkBjF;AAED;;;GAGG;AACH,wBAAgB,UAAU,CAAC,SAAS,GAAE,OAAO,CAAC,YAAY,CAAM,GAAG,YAAY,CA0B9E;AAED;;;GAGG;AACH,wBAAgB,wBAAwB,CACtC,SAAS,GAAE,OAAO,CAAC,oBAAoB,CAAM,GAC5C,oBAAoB,CAOtB;AAED;;;;;;;;GAQG;AACH,wBAAgB,kBAAkB,CAAC,SAAS,GAAE,OAAO,CAAC,cAAc,CAAM,GAAG,cAAc,CAoC1F;AAcD,gFAAgF;AAChF,wBAAgB,oBAAoB,CAClC,SAAS,GAAE,OAAO,CAAC,gBAAgB,CAAM,GACxC,OAAO,CAAC,gBAAgB,CAAC,CAe3B;AAED,2EAA2E;AAC3E,wBAAgB,uBAAuB,CACrC,SAAS,GAAE,OAAO,CAAC,mBAAmB,CAAM,GAC3C,OAAO,CAAC,mBAAmB,CAAC,CAS9B;AAED,8DAA8D;AAC9D,wBAAgB,kBAAkB,CAChC,SAAS,GAAE,OAAO,CAAC,cAAc,CAAM,GACtC,OAAO,CAAC,cAAc,CAAC,CAMzB;AAED,iDAAiD;AACjD,wBAAgB,qBAAqB,CACnC,SAAS,GAAE,OAAO,CAAC,iBAAiB,CAAM,GACzC,OAAO,CAAC,iBAAiB,CAAC,CAc5B"}
@@ -0,0 +1,220 @@
1
+ /**
2
+ * Shared test fixtures: typed builders for the daemon's core domain objects.
3
+ *
4
+ * Before this module, makeDelivery / makeIssue / makeConfig were copy-pasted
5
+ * into ~30 test files each, so a single field change to FocusDeliveryInfo /
6
+ * FocusIssueInfo / DaemonConfig meant editing dozens of files. These builders
7
+ * are the single source of truth; a type change is now one edit here.
8
+ *
9
+ * Each builder is a SUPERSET: it takes a `Partial<T>` of overrides spread last,
10
+ * so every existing call site keeps its specificity. The defaults below are the
11
+ * MAJORITY defaults observed across the suite; a file whose local builder used a
12
+ * different default keeps that default by passing it as an override (often via a
13
+ * thin file-local wrapper) so no test changes meaning.
14
+ *
15
+ * NOT included by design: `makeDeps` and `makeContext`. Those names collide
16
+ * across UNRELATED types -- makeDeps builds AdvanceDeliveryDeps /
17
+ * WorktreeStateDeps / SessionHealthDeps / various per-module `opts`; makeContext
18
+ * builds FocusTeamPromptContext / AssemblyContext / EvaluationContext. They are
19
+ * not one builder and cannot be merged into one typed function without a union
20
+ * or `any`, so they stay per-file. (See the delivery loop doc for the survey.)
21
+ */
22
+ /**
23
+ * Build a FocusDeliveryInfo. Default executionStatus is 'queued' (the majority
24
+ * default across the suite); pass `{ executionStatus: ... }` for other states.
25
+ */
26
+ export function makeDelivery(overrides = {}) {
27
+ return {
28
+ id: 'd1',
29
+ name: 'Test Delivery',
30
+ description: null,
31
+ priorityRank: 0,
32
+ executionStatus: 'queued',
33
+ acceptanceCriteria: null,
34
+ techContext: null,
35
+ currentWorkflowStageId: null,
36
+ mergeCommitSha: null,
37
+ gitState: null,
38
+ injectionId: null,
39
+ stageDescription: null,
40
+ updatedAt: null,
41
+ gateState: null,
42
+ iterationCount: 0,
43
+ ...overrides,
44
+ };
45
+ }
46
+ /**
47
+ * Build a FocusIssueInfo. Defaults to a To Do / Task issue on delivery-1.
48
+ */
49
+ export function makeIssue(overrides = {}) {
50
+ return {
51
+ id: 'issue-1',
52
+ key: 'TEL-1',
53
+ title: 'Test Issue',
54
+ description: null,
55
+ status: 'To Do',
56
+ issueType: 'Task',
57
+ priority: 'P1',
58
+ deliveryId: 'delivery-1',
59
+ parentIssueId: null,
60
+ context: null,
61
+ relevantFiles: null,
62
+ dependsOn: null,
63
+ createdByRoleId: null,
64
+ createdAt: null,
65
+ ...overrides,
66
+ };
67
+ }
68
+ /**
69
+ * Build a DaemonConfig. Single-product, telemetry disabled, integration branch
70
+ * 'integration'. Pass overrides for product/branch/limits specifics.
71
+ */
72
+ export function makeConfig(overrides = {}) {
73
+ return {
74
+ teloraUrl: 'http://localhost',
75
+ trackerId: 'test-tracker',
76
+ organizationId: 'org-1',
77
+ productId: 'product-1',
78
+ repoPath: '/tmp/test-repo',
79
+ worktreeDir: '/tmp/test-repo/.telora/worktrees',
80
+ integrationBranch: 'integration',
81
+ claudeCodePath: 'claude',
82
+ logDir: '/tmp/test-repo/.telora/logs',
83
+ maxTotalSessions: 5,
84
+ sessionTimeoutMs: 3600000,
85
+ tokenLimit: 200000,
86
+ costLimit: 10.0,
87
+ mergeLockTimeoutMs: 300000,
88
+ mergeLockContentionWarningMs: 30000,
89
+ policyFailureMode: 'fail-open',
90
+ logMaxAgeDays: 7,
91
+ logMaxTotalBytes: 1073741824,
92
+ logMaxFiles: 500,
93
+ telemetry: { enabled: false, port: 4318, flushIntervalMs: 5000, retentionDays: 30 },
94
+ lacuna: { enabled: false, host: '127.0.0.1', port: 8787, compressEnabled: true, readyTimeoutMs: 30000 },
95
+ products: [{ id: 'product-1', repoPath: '/tmp/test-repo' }],
96
+ ...overrides,
97
+ };
98
+ }
99
+ /**
100
+ * Build a FocusExecutionConfig. Defaults match DEFAULT_EXECUTION_CONFIG
101
+ * (maxWorkers 3, idle 30s, active 60s).
102
+ */
103
+ export function makeFocusExecutionConfig(overrides = {}) {
104
+ return {
105
+ maxWorkers: 3,
106
+ idlePollIntervalMs: 30000,
107
+ activePollIntervalMs: 60000,
108
+ ...overrides,
109
+ };
110
+ }
111
+ /**
112
+ * Build a FocusTeamState -- the wide in-memory team record. Centralizes the
113
+ * `makeTeam` / `makeTeamState` helpers that were copy-pasted into the
114
+ * focus-engine / watchdog / stall test files. Defaults to an executing coding
115
+ * team with no live process (leadPid/leadStdin null); pass overrides for the
116
+ * dimension under test. The many OPTIONAL clocks (lastActivityAt, shuttingDownAt,
117
+ * lastHandoffAt, toolActivityCount, ...) are omitted by default -- set them via
118
+ * the focus-team-state helpers or an override.
119
+ */
120
+ export function makeFocusTeamState(overrides = {}) {
121
+ return {
122
+ focusId: 'focus-1',
123
+ focusName: 'Test Focus',
124
+ roleId: 'role-1',
125
+ roleName: 'Developer',
126
+ organizationId: 'org-1',
127
+ productId: 'product-1',
128
+ executionConfig: makeFocusExecutionConfig(),
129
+ pipelineConfig: null,
130
+ startedAt: new Date(0),
131
+ phase: 'executing',
132
+ knownDeliveryIds: new Set(),
133
+ mergedDeliveryIds: new Set(),
134
+ planningPhase: false,
135
+ leadSessionId: null,
136
+ leadPid: null,
137
+ leadStdin: null,
138
+ branchName: 'agent/dev/test',
139
+ worktreePath: null,
140
+ integrationBaseSha: null,
141
+ reviewSpawnTip: null,
142
+ deliveryStageIds: new Map(),
143
+ resolvingMergeConflict: false,
144
+ shutdownReason: null,
145
+ readOnly: false,
146
+ sessionType: 'coding',
147
+ lineage: 'coding',
148
+ completionDetector: null,
149
+ claudeSessionId: null,
150
+ lastProgressSnapshot: null,
151
+ noProgressCycles: 0,
152
+ commitNudgeAttempts: 0,
153
+ lastConsumedDirectiveHash: null,
154
+ ...overrides,
155
+ };
156
+ }
157
+ // ---------------------------------------------------------------------------
158
+ // Wide *Deps builders.
159
+ //
160
+ // Each returns a Partial<XDeps> seeded with type-trivial no-op stubs (the
161
+ // DB/IO functions tests must neutralize + the scalar identity fields), spread
162
+ // with overrides. Partial -- NOT the full type -- because every consuming engine
163
+ // takes `Partial<XDeps>` and merges its own production `defaultDeps`: a test
164
+ // passes this seed, overrides the fields it asserts on, and the module fills the
165
+ // rest. Fields with complex non-void return shapes are left to the override /
166
+ // the module default rather than faked here.
167
+ // ---------------------------------------------------------------------------
168
+ /** Seed a VerificationDeps (verify/verification-engine runVerificationTick). */
169
+ export function makeVerificationDeps(overrides = {}) {
170
+ return {
171
+ organizationId: 'org-1',
172
+ integrationBranch: 'integration',
173
+ getPendingVerifications: async () => [],
174
+ recordOutcome: async () => { },
175
+ verifyInjection: async () => { },
176
+ fileEscalation: async () => { },
177
+ emitDriftProposal: async () => { },
178
+ emitInwardDrift: async () => { },
179
+ resolveCwd: () => '/tmp/test-repo',
180
+ getActiveFocuses: async () => [],
181
+ getFocusDeliveries: async () => [],
182
+ ...overrides,
183
+ };
184
+ }
185
+ /** Seed a CompletionEventDeps (completion/event handleCompletionEvent). */
186
+ export function makeCompletionEventDeps(overrides = {}) {
187
+ return {
188
+ getFocusDeliveries: async () => [],
189
+ getFocusIssues: async () => [],
190
+ createEscalation: async () => { },
191
+ terminateTeam: () => false,
192
+ hasOpenTeamFailureEscalation: async () => false,
193
+ ...overrides,
194
+ };
195
+ }
196
+ /** Seed an AutoInjectDeps (security/security-auto-inject). */
197
+ export function makeAutoInjectDeps(overrides = {}) {
198
+ return {
199
+ linkFinding: async () => { },
200
+ writeAudit: async () => { },
201
+ ...overrides,
202
+ };
203
+ }
204
+ /** Seed a PrdControllerDeps (prd/controller). */
205
+ export function makePrdControllerDeps(overrides = {}) {
206
+ return {
207
+ organizationId: 'org-1',
208
+ worktreeDir: '/tmp/test-repo/.telora/worktrees',
209
+ loadPrtGraph: async () => ({ nodes: [], edges: [] }),
210
+ markNodeCleared: async () => { },
211
+ armFocus: async () => { },
212
+ markPrdDone: async () => { },
213
+ resolveArmRoleId: async () => null,
214
+ loadPathways: async () => [],
215
+ commitPathway: async () => { },
216
+ fileEscalation: async () => { },
217
+ ...overrides,
218
+ };
219
+ }
220
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/testing/fixtures/index.ts"],"names":[],"mappings":"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"}
@@ -12,6 +12,7 @@ export interface BuildInfo {
12
12
  builtAt: string;
13
13
  expectedMigrations: string[];
14
14
  }
15
+ export declare function defaultBuildInfoPath(): string;
15
16
  export declare function readBuildInfo(path?: string, reader?: (p: string) => string): BuildInfo;
16
17
  export declare function getExpectedMigrations(path?: string, reader?: (p: string) => string): string[];
17
18
  //# sourceMappingURL=build-info.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"build-info.d.ts","sourceRoot":"","sources":["../../src/update/build-info.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAMH,MAAM,WAAW,SAAS;IACxB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,kBAAkB,EAAE,MAAM,EAAE,CAAC;CAC9B;AAiBD,wBAAgB,aAAa,CAC3B,IAAI,GAAE,MAA+B,EACrC,MAAM,GAAE,CAAC,CAAC,EAAE,MAAM,KAAK,MAAwC,GAC9D,SAAS,CAYX;AAED,wBAAgB,qBAAqB,CACnC,IAAI,CAAC,EAAE,MAAM,EACb,MAAM,CAAC,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,MAAM,GAC7B,MAAM,EAAE,CAEV"}
1
+ {"version":3,"file":"build-info.d.ts","sourceRoot":"","sources":["../../src/update/build-info.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAMH,MAAM,WAAW,SAAS;IACxB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,kBAAkB,EAAE,MAAM,EAAE,CAAC;CAC9B;AAQD,wBAAgB,oBAAoB,IAAI,MAAM,CAO7C;AAED,wBAAgB,aAAa,CAC3B,IAAI,GAAE,MAA+B,EACrC,MAAM,GAAE,CAAC,CAAC,EAAE,MAAM,KAAK,MAAwC,GAC9D,SAAS,CAYX;AAED,wBAAgB,qBAAqB,CACnC,IAAI,CAAC,EAAE,MAAM,EACb,MAAM,CAAC,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,MAAM,GAC7B,MAAM,EAAE,CAEV"}
@@ -15,13 +15,13 @@ const EMPTY = {
15
15
  builtAt: '1970-01-01T00:00:00.000Z',
16
16
  expectedMigrations: [],
17
17
  };
18
- function defaultBuildInfoPath() {
18
+ export function defaultBuildInfoPath() {
19
19
  // packages/daemon/src/build-info.ts (source)
20
20
  // -> packages/daemon/build-info.json
21
21
  // packages/daemon/dist/build-info.js (compiled)
22
22
  // -> packages/daemon/build-info.json
23
23
  const here = dirname(fileURLToPath(import.meta.url));
24
- return resolve(here, '..', 'build-info.json');
24
+ return resolve(here, '..', '..', 'build-info.json');
25
25
  }
26
26
  export function readBuildInfo(path = defaultBuildInfoPath(), reader = (p) => readFileSync(p, 'utf-8')) {
27
27
  try {
@@ -1 +1 @@
1
- {"version":3,"file":"build-info.js","sourceRoot":"","sources":["../../src/update/build-info.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAQ7C,MAAM,KAAK,GAAc;IACvB,SAAS,EAAE,SAAS;IACpB,OAAO,EAAE,0BAA0B;IACnC,kBAAkB,EAAE,EAAE;CACvB,CAAC;AAEF,SAAS,oBAAoB;IAC3B,6CAA6C;IAC7C,uCAAuC;IACvC,gDAAgD;IAChD,uCAAuC;IACvC,MAAM,IAAI,GAAG,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;IACrD,OAAO,OAAO,CAAC,IAAI,EAAE,IAAI,EAAE,iBAAiB,CAAC,CAAC;AAChD,CAAC;AAED,MAAM,UAAU,aAAa,CAC3B,OAAe,oBAAoB,EAAE,EACrC,SAAgC,CAAC,CAAC,EAAE,EAAE,CAAC,YAAY,CAAC,CAAC,EAAE,OAAO,CAAC;IAE/D,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC;QACzB,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAuB,CAAC;QACrD,OAAO;YACL,SAAS,EAAE,MAAM,CAAC,SAAS,IAAI,KAAK,CAAC,SAAS;YAC9C,OAAO,EAAE,MAAM,CAAC,OAAO,IAAI,KAAK,CAAC,OAAO;YACxC,kBAAkB,EAAE,MAAM,CAAC,kBAAkB,IAAI,EAAE;SACpD,CAAC;IACJ,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED,MAAM,UAAU,qBAAqB,CACnC,IAAa,EACb,MAA8B;IAE9B,OAAO,aAAa,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,kBAAkB,CAAC;AACxD,CAAC"}
1
+ {"version":3,"file":"build-info.js","sourceRoot":"","sources":["../../src/update/build-info.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAQ7C,MAAM,KAAK,GAAc;IACvB,SAAS,EAAE,SAAS;IACpB,OAAO,EAAE,0BAA0B;IACnC,kBAAkB,EAAE,EAAE;CACvB,CAAC;AAEF,MAAM,UAAU,oBAAoB;IAClC,6CAA6C;IAC7C,uCAAuC;IACvC,gDAAgD;IAChD,uCAAuC;IACvC,MAAM,IAAI,GAAG,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;IACrD,OAAO,OAAO,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,iBAAiB,CAAC,CAAC;AACtD,CAAC;AAED,MAAM,UAAU,aAAa,CAC3B,OAAe,oBAAoB,EAAE,EACrC,SAAgC,CAAC,CAAC,EAAE,EAAE,CAAC,YAAY,CAAC,CAAC,EAAE,OAAO,CAAC;IAE/D,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC;QACzB,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAuB,CAAC;QACrD,OAAO;YACL,SAAS,EAAE,MAAM,CAAC,SAAS,IAAI,KAAK,CAAC,SAAS;YAC9C,OAAO,EAAE,MAAM,CAAC,OAAO,IAAI,KAAK,CAAC,OAAO;YACxC,kBAAkB,EAAE,MAAM,CAAC,kBAAkB,IAAI,EAAE;SACpD,CAAC;IACJ,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED,MAAM,UAAU,qBAAqB,CACnC,IAAa,EACb,MAA8B;IAE9B,OAAO,aAAa,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,kBAAkB,CAAC;AACxD,CAAC"}
@@ -16,4 +16,12 @@ export declare function resolveReviewWindowStaleHours(): number;
16
16
  export declare function resolveReviewCycleCap(): number;
17
17
  /** Resolve the idle-team stall threshold in hours (env override or default). */
18
18
  export declare function resolveIdleTeamStallHours(): number;
19
+ /** Resolve the review-exit hand-off cap (env override or default 3). */
20
+ export declare function resolveReviewHandoffCap(): number;
21
+ /** Resolve the review-liveness window in minutes (env override or default 15). */
22
+ export declare function resolveReviewLivenessWindowMinutes(): number;
23
+ /** Resolve the respawn-cycle max total duration in hours (env override or default 2). */
24
+ export declare function resolveRespawnCycleMaxHours(): number;
25
+ /** Resolve the respawn-cycle max cumulative teardown count (env override or default 12). */
26
+ export declare function resolveRespawnCycleMaxCount(): number;
19
27
  //# sourceMappingURL=stall-detector-config.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"stall-detector-config.d.ts","sourceRoot":"","sources":["../../src/verify/stall-detector-config.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAIH,uEAAuE;AACvE,wBAAgB,sBAAsB,IAAI,MAAM,CAE/C;AAED,wFAAwF;AACxF,wBAAgB,6BAA6B,IAAI,MAAM,CAEtD;AAED,0EAA0E;AAC1E,wBAAgB,qBAAqB,IAAI,MAAM,CAE9C;AAED,gFAAgF;AAChF,wBAAgB,yBAAyB,IAAI,MAAM,CAElD"}
1
+ {"version":3,"file":"stall-detector-config.d.ts","sourceRoot":"","sources":["../../src/verify/stall-detector-config.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAsBH,uEAAuE;AACvE,wBAAgB,sBAAsB,IAAI,MAAM,CAE/C;AAED,wFAAwF;AACxF,wBAAgB,6BAA6B,IAAI,MAAM,CAEtD;AAED,0EAA0E;AAC1E,wBAAgB,qBAAqB,IAAI,MAAM,CAE9C;AAED,gFAAgF;AAChF,wBAAgB,yBAAyB,IAAI,MAAM,CAElD;AASD,wEAAwE;AACxE,wBAAgB,uBAAuB,IAAI,MAAM,CAEhD;AAED,kFAAkF;AAClF,wBAAgB,kCAAkC,IAAI,MAAM,CAE3D;AAED,yFAAyF;AACzF,wBAAgB,2BAA2B,IAAI,MAAM,CAEpD;AAED,4FAA4F;AAC5F,wBAAgB,2BAA2B,IAAI,MAAM,CAEpD"}
@@ -9,6 +9,24 @@
9
9
  * can no longer silently fall back to a default on a typo'd value.
10
10
  */
11
11
  import { loadEnvConfig } from '@telora/daemon-core';
12
+ /**
13
+ * Raw positive-number env read with a fallback default, for knobs whose canonical
14
+ * Zod + ENV_VAR_METADATA declaration IS in packages/daemon-core/src/env-config.ts
15
+ * but which the REGISTRY-INSTALLED daemon-core does not yet carry: the daemon
16
+ * compiles against the published dist, so loadEnvConfig() cannot see a freshly
17
+ * added field until a daemon-core republish + pin bump lands. These reads are
18
+ * allowlisted in scripts/lint-config.json under "env-reads" with that reason.
19
+ * Once daemon-core is republished + pinned, switch each caller to loadEnvConfig()
20
+ * and remove the allowlist entry (mirrors the TELORA_SHORTFALL_DISPOSITION_ATTEMPT_CAP
21
+ * precedent). Invalid (non-positive / non-numeric) values fall back to the default
22
+ * rather than throwing -- the loud-fail happens at loadEnvConfig once republished.
23
+ */
24
+ function parsePositive(raw, fallback) {
25
+ if (raw === undefined || raw === '')
26
+ return fallback;
27
+ const n = Number(raw);
28
+ return Number.isFinite(n) && n > 0 ? n : fallback;
29
+ }
12
30
  /** Resolve the verify_failed re-code cap (env override or default). */
13
31
  export function resolveVerifyFailedCap() {
14
32
  return loadEnvConfig().TELORA_VERIFY_FAILED_ITERATION_CAP;
@@ -25,4 +43,26 @@ export function resolveReviewCycleCap() {
25
43
  export function resolveIdleTeamStallHours() {
26
44
  return loadEnvConfig().TELORA_IDLE_TEAM_STALL_HOURS;
27
45
  }
46
+ // NOTE: the four resolvers below read process.env RAW (via rawPositiveNumber)
47
+ // rather than loadEnvConfig() because their knobs are PENDING a daemon-core
48
+ // republish (see rawPositiveNumber). The canonical declarations already live in
49
+ // packages/daemon-core/src/env-config.ts; switch these to loadEnvConfig() and
50
+ // drop the scripts/lint-config.json env-reads allowlist entries once daemon-core
51
+ // is republished + pinned.
52
+ /** Resolve the review-exit hand-off cap (env override or default 3). */
53
+ export function resolveReviewHandoffCap() {
54
+ return parsePositive(process.env.TELORA_REVIEW_HANDOFF_CAP, 3);
55
+ }
56
+ /** Resolve the review-liveness window in minutes (env override or default 15). */
57
+ export function resolveReviewLivenessWindowMinutes() {
58
+ return parsePositive(process.env.TELORA_REVIEW_LIVENESS_WINDOW_MINUTES, 15);
59
+ }
60
+ /** Resolve the respawn-cycle max total duration in hours (env override or default 2). */
61
+ export function resolveRespawnCycleMaxHours() {
62
+ return parsePositive(process.env.TELORA_RESPAWN_CYCLE_MAX_HOURS, 2);
63
+ }
64
+ /** Resolve the respawn-cycle max cumulative teardown count (env override or default 12). */
65
+ export function resolveRespawnCycleMaxCount() {
66
+ return parsePositive(process.env.TELORA_RESPAWN_CYCLE_MAX_COUNT, 12);
67
+ }
28
68
  //# sourceMappingURL=stall-detector-config.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"stall-detector-config.js","sourceRoot":"","sources":["../../src/verify/stall-detector-config.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAEpD,uEAAuE;AACvE,MAAM,UAAU,sBAAsB;IACpC,OAAO,aAAa,EAAE,CAAC,kCAAkC,CAAC;AAC5D,CAAC;AAED,wFAAwF;AACxF,MAAM,UAAU,6BAA6B;IAC3C,OAAO,aAAa,EAAE,CAAC,gCAAgC,CAAC;AAC1D,CAAC;AAED,0EAA0E;AAC1E,MAAM,UAAU,qBAAqB;IACnC,OAAO,aAAa,EAAE,CAAC,uBAAuB,CAAC;AACjD,CAAC;AAED,gFAAgF;AAChF,MAAM,UAAU,yBAAyB;IACvC,OAAO,aAAa,EAAE,CAAC,4BAA4B,CAAC;AACtD,CAAC"}
1
+ {"version":3,"file":"stall-detector-config.js","sourceRoot":"","sources":["../../src/verify/stall-detector-config.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAEpD;;;;;;;;;;;GAWG;AACH,SAAS,aAAa,CAAC,GAAuB,EAAE,QAAgB;IAC9D,IAAI,GAAG,KAAK,SAAS,IAAI,GAAG,KAAK,EAAE;QAAE,OAAO,QAAQ,CAAC;IACrD,MAAM,CAAC,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC;IACtB,OAAO,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC;AACpD,CAAC;AAED,uEAAuE;AACvE,MAAM,UAAU,sBAAsB;IACpC,OAAO,aAAa,EAAE,CAAC,kCAAkC,CAAC;AAC5D,CAAC;AAED,wFAAwF;AACxF,MAAM,UAAU,6BAA6B;IAC3C,OAAO,aAAa,EAAE,CAAC,gCAAgC,CAAC;AAC1D,CAAC;AAED,0EAA0E;AAC1E,MAAM,UAAU,qBAAqB;IACnC,OAAO,aAAa,EAAE,CAAC,uBAAuB,CAAC;AACjD,CAAC;AAED,gFAAgF;AAChF,MAAM,UAAU,yBAAyB;IACvC,OAAO,aAAa,EAAE,CAAC,4BAA4B,CAAC;AACtD,CAAC;AAED,8EAA8E;AAC9E,4EAA4E;AAC5E,gFAAgF;AAChF,8EAA8E;AAC9E,iFAAiF;AACjF,2BAA2B;AAE3B,wEAAwE;AACxE,MAAM,UAAU,uBAAuB;IACrC,OAAO,aAAa,CAAC,OAAO,CAAC,GAAG,CAAC,yBAAyB,EAAE,CAAC,CAAC,CAAC;AACjE,CAAC;AAED,kFAAkF;AAClF,MAAM,UAAU,kCAAkC;IAChD,OAAO,aAAa,CAAC,OAAO,CAAC,GAAG,CAAC,qCAAqC,EAAE,EAAE,CAAC,CAAC;AAC9E,CAAC;AAED,yFAAyF;AACzF,MAAM,UAAU,2BAA2B;IACzC,OAAO,aAAa,CAAC,OAAO,CAAC,GAAG,CAAC,8BAA8B,EAAE,CAAC,CAAC,CAAC;AACtE,CAAC;AAED,4FAA4F;AAC5F,MAAM,UAAU,2BAA2B;IACzC,OAAO,aAAa,CAAC,OAAO,CAAC,GAAG,CAAC,8BAA8B,EAAE,EAAE,CAAC,CAAC;AACvE,CAAC"}
@@ -114,23 +114,54 @@ export interface ReviewWindowDeps {
114
114
  * review window silent (dismissal memory) until the focus's review state changes.
115
115
  */
116
116
  fileEscalation: (params: FileEscalationIdempotentParams) => Promise<FileEscalationIdempotentResult>;
117
- /** Focus IDs that currently have an active REVIEW team. Defaults to live teams. */
117
+ /** Focus IDs that currently have a REVIEW team PRESENT. Defaults to live teams. */
118
118
  activeReviewFocusIds: () => Set<string>;
119
+ /**
120
+ * The review team's per-team last-activity epoch ms, or null when nothing has
121
+ * been recorded yet. Presence alone is not liveness -- this distinguishes a
122
+ * review that is genuinely progressing from a respawn loop's idle-exiting
123
+ * teams. Defaults to the live per-team activity clock.
124
+ */
125
+ getReviewTeamLastActivityAt: (focusId: string) => number | null;
119
126
  /** Current epoch ms; injectable for tests. Defaults to Date.now. */
120
127
  now?: () => number;
121
128
  /** Override the staleness threshold (hours) for tests; defaults to env-config. */
122
129
  thresholdHours?: number;
130
+ /** Override the review-liveness window (minutes) for tests; defaults to env-config. */
131
+ livenessWindowMinutes?: number;
123
132
  }
124
133
  /** Focus IDs that currently have an active REVIEW team (live default). */
125
134
  export declare function activeReviewFocusIds(): Set<string>;
135
+ /**
136
+ * Pure decision: is a review GENUINELY active -- progressing, not merely present?
137
+ *
138
+ * Mere team presence is NOT liveness: a loop that respawns an idle review team
139
+ * every few minutes always has a team present, so presence taken as "a review is
140
+ * running" starves the very staleness escalation that exists to catch the loop.
141
+ * A review counts as genuinely active only when a team is present AND its
142
+ * per-team activity clock is fresh (last agent event within `livenessWindowMs`).
143
+ *
144
+ * A frozen clock (an idle-exiting respawn team) or a null clock (present but has
145
+ * produced no event) is NOT genuinely active. Treating null as not-active is safe
146
+ * because it only matters once review_requested_at is itself past the staleness
147
+ * threshold (isReviewWindowStale gates on that first): a just-spawned review is
148
+ * within the threshold and never trips, but a "review" that has produced zero
149
+ * events for hours is exactly the wedge. Mirrors the sibling team-idle detector's
150
+ * liveness-not-presence distinction. Exported for direct unit testing.
151
+ */
152
+ export declare function isReviewGenuinelyActive(hasReviewTeam: boolean, lastReviewActivityMs: number | null, nowMs: number, livenessWindowMs: number): boolean;
126
153
  /**
127
154
  * Pure decision: is this focus's review window stale? True when a
128
- * review_requested_at exists, is older than `thresholdMs`, and the focus has no
129
- * active review team. A completed review clears review_requested_at, so a
130
- * still-set timestamp older than the threshold with no active review team means
131
- * the review never ran (or never finished). Exported for direct unit testing.
155
+ * review_requested_at exists, is older than `thresholdMs`, and NO review is
156
+ * GENUINELY ACTIVE (progressing) on the focus. A completed review clears
157
+ * review_requested_at, so a still-set timestamp older than the threshold with no
158
+ * genuinely-active review means the review never ran, never finished, OR is stuck
159
+ * in a respawn loop whose idle-exiting teams never progress. The second argument
160
+ * is genuine liveness (isReviewGenuinelyActive), NOT mere team presence -- that is
161
+ * what stops the loop's own respawns from masking the stale window. Exported for
162
+ * direct unit testing.
132
163
  */
133
- export declare function isReviewWindowStale(reviewRequestedAt: string | null, hasActiveReview: boolean, nowMs: number, thresholdMs: number): boolean;
164
+ export declare function isReviewWindowStale(reviewRequestedAt: string | null, reviewGenuinelyActive: boolean, nowMs: number, thresholdMs: number): boolean;
134
165
  /**
135
166
  * Check ONE focus for a stale review window and file a review_window_stalled
136
167
  * escalation (needs_operator) -- at most one open per focus. The caller
@@ -1 +1 @@
1
- {"version":3,"file":"stall-detectors.d.ts","sourceRoot":"","sources":["../../src/verify/stall-detectors.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"stall-detectors.d.ts","sourceRoot":"","sources":["../../src/verify/stall-detectors.ts"],"names":[],"mappings":"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"}