maskweaver 0.9.4 → 0.9.6

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 (229) hide show
  1. package/README.ko.md +638 -592
  2. package/README.md +671 -667
  3. package/dist/cli/doctor.js +5 -21
  4. package/dist/cli/install.d.ts +0 -8
  5. package/dist/cli/install.js +0 -39
  6. package/dist/context/config.d.ts +0 -22
  7. package/dist/context/config.js +0 -28
  8. package/dist/context/feature.d.ts +0 -39
  9. package/dist/context/feature.js +0 -77
  10. package/dist/context/files.d.ts +0 -13
  11. package/dist/context/files.js +1 -24
  12. package/dist/context/index.d.ts +0 -7
  13. package/dist/context/index.js +0 -12
  14. package/dist/context/project.d.ts +0 -21
  15. package/dist/context/project.js +0 -30
  16. package/dist/context/types.d.ts +0 -48
  17. package/dist/context/types.js +0 -12
  18. package/dist/context/utils.d.ts +0 -18
  19. package/dist/context/utils.js +0 -27
  20. package/dist/core/engine/promptBuilder.d.ts +0 -17
  21. package/dist/core/engine/promptBuilder.js +0 -28
  22. package/dist/core/index.d.ts +0 -6
  23. package/dist/core/index.js +0 -9
  24. package/dist/core/loader/MaskLoader.d.ts +0 -23
  25. package/dist/core/loader/MaskLoader.js +0 -29
  26. package/dist/core/schema/types.d.ts +0 -47
  27. package/dist/core/schema/types.js +0 -6
  28. package/dist/core/schema/validator.d.ts +0 -14
  29. package/dist/core/schema/validator.js +0 -18
  30. package/dist/i18n/index.d.ts +0 -18
  31. package/dist/i18n/index.js +4 -23
  32. package/dist/index.d.ts +0 -8
  33. package/dist/index.js +0 -8
  34. package/dist/lib.d.ts +0 -5
  35. package/dist/lib.js +0 -12
  36. package/dist/memory/chunking.d.ts +0 -22
  37. package/dist/memory/chunking.js +2 -37
  38. package/dist/memory/core.d.ts +0 -29
  39. package/dist/memory/core.js +1 -52
  40. package/dist/memory/index.d.ts +0 -5
  41. package/dist/memory/index.js +0 -10
  42. package/dist/memory/indexer.d.ts +0 -21
  43. package/dist/memory/indexer.js +0 -44
  44. package/dist/memory/providers/examples.d.ts +0 -5
  45. package/dist/memory/providers/examples.js +4 -64
  46. package/dist/memory/providers/factory.d.ts +0 -44
  47. package/dist/memory/providers/factory.js +0 -46
  48. package/dist/memory/providers/index.d.ts +0 -26
  49. package/dist/memory/providers/index.js +0 -28
  50. package/dist/memory/providers/ollama.d.ts +0 -6
  51. package/dist/memory/providers/ollama.js +1 -8
  52. package/dist/memory/providers/openai.d.ts +0 -6
  53. package/dist/memory/providers/openai.js +1 -8
  54. package/dist/memory/providers/openrouter.d.ts +0 -6
  55. package/dist/memory/providers/openrouter.js +0 -8
  56. package/dist/memory/providers/text-only.d.ts +0 -13
  57. package/dist/memory/providers/text-only.js +0 -17
  58. package/dist/memory/providers/types.d.ts +0 -39
  59. package/dist/memory/providers/types.js +0 -7
  60. package/dist/memory/providers/voyage.d.ts +0 -22
  61. package/dist/memory/providers/voyage.js +1 -24
  62. package/dist/memory/search/hybrid.d.ts +0 -12
  63. package/dist/memory/search/hybrid.js +1 -22
  64. package/dist/memory/store/sqlite.d.ts +0 -72
  65. package/dist/memory/store/sqlite.js +4 -127
  66. package/dist/plugin/config/index.d.ts +0 -112
  67. package/dist/plugin/config/index.js +0 -115
  68. package/dist/plugin/index.d.ts +0 -13
  69. package/dist/plugin/index.js +1 -123
  70. package/dist/plugin/tools/command-registry.d.ts +0 -6
  71. package/dist/plugin/tools/command-registry.js +0 -14
  72. package/dist/plugin/tools/context.d.ts +0 -12
  73. package/dist/plugin/tools/context.js +0 -58
  74. package/dist/plugin/tools/maskSave.d.ts +0 -3
  75. package/dist/plugin/tools/maskSave.js +0 -3
  76. package/dist/plugin/tools/memoryGet.d.ts +0 -3
  77. package/dist/plugin/tools/memoryGet.js +0 -3
  78. package/dist/plugin/tools/memoryIndexer.d.ts +0 -3
  79. package/dist/plugin/tools/memoryIndexer.js +0 -10
  80. package/dist/plugin/tools/memorySearch.d.ts +0 -31
  81. package/dist/plugin/tools/memorySearch.js +0 -79
  82. package/dist/plugin/tools/memoryWrite.d.ts +0 -8
  83. package/dist/plugin/tools/memoryWrite.js +0 -32
  84. package/dist/plugin/tools/retrospect.d.ts +0 -3
  85. package/dist/plugin/tools/retrospect.js +0 -3
  86. package/dist/plugin/tools/slashcommand.d.ts +0 -11
  87. package/dist/plugin/tools/slashcommand.js +0 -38
  88. package/dist/plugin/tools/squad.d.ts +0 -12
  89. package/dist/plugin/tools/squad.js +11 -83
  90. package/dist/plugin/tools/weave.d.ts +0 -6
  91. package/dist/plugin/tools/weave.js +0 -78
  92. package/dist/plugin/types.d.ts +0 -20
  93. package/dist/plugin/types.js +0 -7
  94. package/dist/retrospect/index.d.ts +0 -7
  95. package/dist/retrospect/index.js +0 -9
  96. package/dist/retrospect/mask-save.d.ts +0 -12
  97. package/dist/retrospect/mask-save.js +1 -80
  98. package/dist/retrospect/retrospect.d.ts +0 -18
  99. package/dist/retrospect/retrospect.js +0 -63
  100. package/dist/retrospect/strategies/base.d.ts +0 -15
  101. package/dist/retrospect/strategies/base.js +0 -7
  102. package/dist/retrospect/strategies/deep.d.ts +0 -12
  103. package/dist/retrospect/strategies/deep.js +0 -24
  104. package/dist/retrospect/strategies/index.d.ts +0 -12
  105. package/dist/retrospect/strategies/index.js +0 -12
  106. package/dist/retrospect/strategies/quick.d.ts +0 -12
  107. package/dist/retrospect/strategies/quick.js +0 -19
  108. package/dist/retrospect/strategies/standard.d.ts +0 -12
  109. package/dist/retrospect/strategies/standard.js +0 -15
  110. package/dist/retrospect/types.d.ts +0 -7
  111. package/dist/retrospect/types.js +0 -7
  112. package/dist/shared/config.d.ts +0 -105
  113. package/dist/shared/config.js +0 -33
  114. package/dist/shared/errors.d.ts +0 -18
  115. package/dist/shared/errors.js +0 -19
  116. package/dist/shared/generate-agents.d.ts +0 -69
  117. package/dist/shared/generate-agents.js +2 -86
  118. package/dist/shared/image.d.ts +0 -67
  119. package/dist/shared/image.js +6 -104
  120. package/dist/shared/index.d.ts +0 -5
  121. package/dist/shared/index.js +0 -7
  122. package/dist/shared/model-registry.d.ts +0 -72
  123. package/dist/shared/model-registry.js +5 -95
  124. package/dist/shared/types.d.ts +0 -15
  125. package/dist/shared/types.js +0 -3
  126. package/dist/shared-context/dag.d.ts +0 -105
  127. package/dist/shared-context/dag.js +3 -114
  128. package/dist/shared-context/index.d.ts +0 -5
  129. package/dist/shared-context/index.js +0 -15
  130. package/dist/shared-context/logger.d.ts +0 -37
  131. package/dist/shared-context/logger.js +0 -41
  132. package/dist/shared-context/parallel-executor.d.ts +0 -54
  133. package/dist/shared-context/parallel-executor.js +4 -56
  134. package/dist/shared-context/session.d.ts +0 -56
  135. package/dist/shared-context/session.js +0 -47
  136. package/dist/shared-context/squad.d.ts +0 -68
  137. package/dist/shared-context/squad.js +0 -63
  138. package/dist/shared-context/storage.d.ts +0 -132
  139. package/dist/shared-context/storage.js +0 -116
  140. package/dist/shared-context/task.d.ts +0 -120
  141. package/dist/shared-context/task.js +0 -152
  142. package/dist/shared-context/test/dag.test.js +9 -14
  143. package/dist/shared-context/test/logger.test.d.ts +0 -8
  144. package/dist/shared-context/test/logger.test.js +0 -52
  145. package/dist/shared-context/test/session.test.d.ts +0 -7
  146. package/dist/shared-context/test/session.test.js +0 -63
  147. package/dist/shared-context/test/squad.test.d.ts +0 -10
  148. package/dist/shared-context/test/squad.test.js +2 -68
  149. package/dist/shared-context/test/storage.test.d.ts +0 -8
  150. package/dist/shared-context/test/storage.test.js +0 -68
  151. package/dist/shared-context/test/task.test.d.ts +0 -7
  152. package/dist/shared-context/test/task.test.js +0 -54
  153. package/dist/shared-context/test/watchdog.test.d.ts +0 -7
  154. package/dist/shared-context/test/watchdog.test.js +3 -58
  155. package/dist/shared-context/types.d.ts +0 -215
  156. package/dist/shared-context/types.js +0 -125
  157. package/dist/shared-context/watchdog.d.ts +0 -127
  158. package/dist/shared-context/watchdog.js +0 -148
  159. package/dist/shared-context/worktree.d.ts +0 -68
  160. package/dist/shared-context/worktree.js +2 -34
  161. package/dist/verify/budget.d.ts +0 -29
  162. package/dist/verify/budget.js +0 -34
  163. package/dist/verify/critical-files.d.ts +0 -17
  164. package/dist/verify/critical-files.js +0 -37
  165. package/dist/verify/escalation.d.ts +0 -20
  166. package/dist/verify/escalation.js +0 -22
  167. package/dist/verify/index.d.ts +0 -5
  168. package/dist/verify/index.js +0 -11
  169. package/dist/verify/prompts.d.ts +0 -20
  170. package/dist/verify/prompts.js +0 -20
  171. package/dist/verify/types.d.ts +0 -26
  172. package/dist/verify/types.js +1 -12
  173. package/dist/verify/verifier.d.ts +0 -29
  174. package/dist/verify/verifier.js +0 -54
  175. package/dist/version.d.ts +1 -16
  176. package/dist/version.js +1 -16
  177. package/dist/weave/bridge.d.ts +0 -35
  178. package/dist/weave/bridge.js +0 -51
  179. package/dist/weave/environment/detector.d.ts +0 -6
  180. package/dist/weave/environment/detector.js +4 -45
  181. package/dist/weave/environment/index.d.ts +0 -19
  182. package/dist/weave/environment/index.js +1 -39
  183. package/dist/weave/environment/issues.d.ts +0 -35
  184. package/dist/weave/environment/issues.js +0 -59
  185. package/dist/weave/git.d.ts +0 -8
  186. package/dist/weave/git.js +0 -8
  187. package/dist/weave/index.d.ts +0 -13
  188. package/dist/weave/index.js +2 -28
  189. package/dist/weave/knowledge/global.d.ts +0 -39
  190. package/dist/weave/knowledge/global.js +2 -78
  191. package/dist/weave/loop.js +0 -3
  192. package/dist/weave/orchestrator.d.ts +0 -69
  193. package/dist/weave/orchestrator.js +1 -101
  194. package/dist/weave/phase-manager.d.ts +0 -64
  195. package/dist/weave/phase-manager.js +0 -89
  196. package/dist/weave/security/secret-scan.d.ts +0 -14
  197. package/dist/weave/security/secret-scan.js +0 -19
  198. package/dist/weave/stages/build.js +0 -15
  199. package/dist/weave/stages/execute.d.ts +0 -42
  200. package/dist/weave/stages/execute.js +4 -86
  201. package/dist/weave/stages/handoff.d.ts +0 -7
  202. package/dist/weave/stages/handoff.js +0 -43
  203. package/dist/weave/stages/index.d.ts +0 -3
  204. package/dist/weave/stages/index.js +0 -3
  205. package/dist/weave/stages/intake.d.ts +0 -8
  206. package/dist/weave/stages/intake.js +5 -65
  207. package/dist/weave/stages/map.d.ts +0 -1
  208. package/dist/weave/stages/openspec.d.ts +0 -1
  209. package/dist/weave/stages/plan.d.ts +0 -11
  210. package/dist/weave/stages/plan.js +1 -53
  211. package/dist/weave/stages/refine.d.ts +0 -7
  212. package/dist/weave/stages/refine.js +0 -7
  213. package/dist/weave/stages/research.d.ts +0 -6
  214. package/dist/weave/stages/research.js +0 -6
  215. package/dist/weave/stages/spec.d.ts +0 -12
  216. package/dist/weave/stages/spec.js +0 -17
  217. package/dist/weave/types.d.ts +0 -20
  218. package/dist/weave/types.js +0 -5
  219. package/dist/weave/verification/commands.d.ts +0 -12
  220. package/dist/weave/verification/commands.js +0 -19
  221. package/dist/weave/verification/index.d.ts +0 -6
  222. package/dist/weave/verification/index.js +1 -19
  223. package/dist/weave/verification/playwright.d.ts +0 -47
  224. package/dist/weave/verification/playwright.js +1 -90
  225. package/dist/weave/worktree.d.ts +0 -16
  226. package/dist/weave/worktree.js +0 -23
  227. package/dist/weave/yaml-repair.d.ts +0 -39
  228. package/dist/weave/yaml-repair.js +13 -116
  229. package/package.json +1 -1
@@ -1,144 +1,17 @@
1
- /**
2
- * Watchdog - Squad Timeout Monitoring
3
- *
4
- * Monitors squad health and detects stuck or unresponsive agents.
5
- * "If you can't measure it, you can't improve it." - Brendan Gregg
6
- *
7
- * Key metrics:
8
- * - Elapsed time since last activity (updatedAt)
9
- * - Time remaining before timeout threshold
10
- * - Grace period for cleanup before hard kill
11
- *
12
- * Design principles:
13
- * - Pure functions for timeout checking (no side effects)
14
- * - Deterministic behavior for testing
15
- * - Observability-first: expose all timing details
16
- *
17
- * @author Kent Beck's Dummy Human
18
- */
19
1
  import type { SquadState, TaskState, TimeoutStatus } from "./types.js";
20
2
  import type { Session } from "./session.js";
21
- /**
22
- * Check if a squad has exceeded its timeout threshold.
23
- * Pure function based on squadState.updatedAt timestamp.
24
- *
25
- * This is the primary health check for detecting stuck agents.
26
- * A squad is considered stuck if no activity has occurred within
27
- * the timeout period (default: 5 minutes).
28
- *
29
- * @param squadState - Current squad state with updatedAt timestamp
30
- * @param timeoutMs - Optional custom timeout (defaults to LIMITS.watchdogTimeoutMs)
31
- * @returns TimeoutStatus with expiration state and timing details
32
- *
33
- * @example
34
- * const status = checkSquadTimeout(squadState);
35
- * if (status.isExpired) {
36
- * console.log(`Squad stuck for ${status.elapsedMs}ms`);
37
- * await markSquadExpired(session, squadState.squadId);
38
- * }
39
- *
40
- * @example
41
- * // With custom timeout for long-running tasks
42
- * const status = checkSquadTimeout(squadState, 30 * 60 * 1000); // 30 minutes
43
- */
44
3
  export declare function checkSquadTimeout(squadState: SquadState, timeoutMs?: number): TimeoutStatus;
45
- /**
46
- * Check if a task has exceeded its timeout threshold.
47
- * Pure function - deterministic and side-effect free.
48
- *
49
- * "If you can't measure it, you can't improve it." - Brendan Gregg
50
- *
51
- * This enables fine-grained observability at the task level,
52
- * complementing squad-level timeout checks.
53
- *
54
- * @param task - TaskState with optional startedAt timestamp
55
- * @param timeoutMs - Timeout threshold (defaults to LIMITS.watchdogTimeoutMs)
56
- * @returns TimeoutStatus or null if task hasn't started
57
- *
58
- * @example
59
- * const status = checkTaskTimeout(task);
60
- * if (status === null) {
61
- * console.log("Task hasn't started yet");
62
- * } else if (status.isExpired) {
63
- * console.log(`Task stuck for ${status.elapsedMs}ms`);
64
- * }
65
- *
66
- * @example
67
- * // With custom timeout for quick tasks
68
- * const status = checkTaskTimeout(task, 60 * 1000); // 1 minute
69
- */
70
4
  export declare function checkTaskTimeout(task: TaskState, timeoutMs?: number): TimeoutStatus | null;
71
- /**
72
- * Mark a squad as expired due to timeout.
73
- * Sets status to "failed" and logs the timeout event.
74
- *
75
- * This should be called after checkSquadTimeout() returns isExpired: true.
76
- * The function is idempotent - calling it multiple times is safe.
77
- *
78
- * @param session - Parent session containing the squad
79
- * @param squadId - ID of the squad to expire
80
- * @returns Updated squad state with status="failed"
81
- *
82
- * @example
83
- * const status = checkSquadTimeout(squadState);
84
- * if (status.isExpired) {
85
- * const failedState = await markSquadExpired(session, squadId);
86
- * console.log(`Squad ${squadId} expired after ${status.elapsedMs}ms`);
87
- * }
88
- */
89
5
  export declare function markSquadExpired(session: Session, squadId: string): Promise<SquadState>;
90
- /**
91
- * Summary of a watchdog run.
92
- * "If you can't measure it, you can't improve it." - Brendan Gregg
93
- */
94
6
  export interface WatchdogSummary {
95
- /** Number of squads checked */
96
7
  checkedSquads: number;
97
- /** Number of tasks checked (across all squads) */
98
8
  checkedTasks: number;
99
- /** IDs of squads that were found expired */
100
9
  expiredSquads: string[];
101
- /** Tasks that were found expired */
102
10
  expiredTasks: Array<{
103
11
  squadId: string;
104
12
  taskId: string;
105
13
  }>;
106
14
  }
107
- /**
108
- * Run watchdog check on all active squads and tasks.
109
- * Marks expired squads/tasks as failed.
110
- *
111
- * This is meant to be called periodically (e.g., every 30 seconds)
112
- * to detect and handle stuck agents.
113
- *
114
- * "If you can't measure it, you can't improve it." - Brendan Gregg
115
- *
116
- * The dryRun mode allows "measure before fix" - check without modifying state.
117
- *
118
- * @param session - Session to check
119
- * @param options - Optional configuration
120
- * @returns Summary of watchdog run with all metrics
121
- *
122
- * @example
123
- * // Periodic watchdog check (production mode)
124
- * const summary = await runWatchdog(session);
125
- * console.log(`Checked ${summary.checkedSquads} squads`);
126
- * console.log(`Expired: ${summary.expiredSquads.length} squads`);
127
- *
128
- * @example
129
- * // Dry run for monitoring without side effects
130
- * const summary = await runWatchdog(session, { dryRun: true });
131
- * if (summary.expiredSquads.length > 0) {
132
- * alertOnCall(summary);
133
- * }
134
- *
135
- * @example
136
- * // Custom timeouts for specific workloads
137
- * const summary = await runWatchdog(session, {
138
- * squadTimeoutMs: 30 * 60 * 1000, // 30 minutes
139
- * taskTimeoutMs: 10 * 60 * 1000, // 10 minutes
140
- * });
141
- */
142
15
  export declare function runWatchdog(session: Session, options?: {
143
16
  squadTimeoutMs?: number;
144
17
  taskTimeoutMs?: number;
@@ -1,37 +1,7 @@
1
- /**
2
- * Watchdog - Squad Timeout Monitoring
3
- *
4
- * Monitors squad health and detects stuck or unresponsive agents.
5
- * "If you can't measure it, you can't improve it." - Brendan Gregg
6
- *
7
- * Key metrics:
8
- * - Elapsed time since last activity (updatedAt)
9
- * - Time remaining before timeout threshold
10
- * - Grace period for cleanup before hard kill
11
- *
12
- * Design principles:
13
- * - Pure functions for timeout checking (no side effects)
14
- * - Deterministic behavior for testing
15
- * - Observability-first: expose all timing details
16
- *
17
- * @author Kent Beck's Dummy Human
18
- */
19
1
  import { LIMITS } from "./types.js";
20
2
  import { getSquad, updateSquadState } from "./squad.js";
21
3
  import { updateTask } from "./task.js";
22
4
  import { logEvent } from "./logger.js";
23
- // ============================================================================
24
- // Internal Helpers
25
- // ============================================================================
26
- /**
27
- * Calculate timeout status from last activity timestamp.
28
- * Pure function - deterministic and side-effect free.
29
- *
30
- * @param lastActivityAt - ISO timestamp of last recorded activity
31
- * @param timeoutMs - Timeout threshold in milliseconds
32
- * @param now - Current time (injectable for testing)
33
- * @returns Computed timeout status with all timing details
34
- */
35
5
  function getTimeoutStatus(lastActivityAt, timeoutMs, now = new Date()) {
36
6
  const lastActivity = new Date(lastActivityAt);
37
7
  const elapsedMs = now.getTime() - lastActivity.getTime();
@@ -44,140 +14,27 @@ function getTimeoutStatus(lastActivityAt, timeoutMs, now = new Date()) {
44
14
  lastActivityAt,
45
15
  };
46
16
  }
47
- // ============================================================================
48
- // Timeout Checking - Pure Functions
49
- // ============================================================================
50
- /**
51
- * Check if a squad has exceeded its timeout threshold.
52
- * Pure function based on squadState.updatedAt timestamp.
53
- *
54
- * This is the primary health check for detecting stuck agents.
55
- * A squad is considered stuck if no activity has occurred within
56
- * the timeout period (default: 5 minutes).
57
- *
58
- * @param squadState - Current squad state with updatedAt timestamp
59
- * @param timeoutMs - Optional custom timeout (defaults to LIMITS.watchdogTimeoutMs)
60
- * @returns TimeoutStatus with expiration state and timing details
61
- *
62
- * @example
63
- * const status = checkSquadTimeout(squadState);
64
- * if (status.isExpired) {
65
- * console.log(`Squad stuck for ${status.elapsedMs}ms`);
66
- * await markSquadExpired(session, squadState.squadId);
67
- * }
68
- *
69
- * @example
70
- * // With custom timeout for long-running tasks
71
- * const status = checkSquadTimeout(squadState, 30 * 60 * 1000); // 30 minutes
72
- */
73
17
  export function checkSquadTimeout(squadState, timeoutMs) {
74
18
  const effectiveTimeout = timeoutMs ?? LIMITS.watchdogTimeoutMs;
75
19
  return getTimeoutStatus(squadState.updatedAt, effectiveTimeout);
76
20
  }
77
- // ============================================================================
78
- // Task Timeout Checking - Fine-grained observability
79
- // ============================================================================
80
- /**
81
- * Check if a task has exceeded its timeout threshold.
82
- * Pure function - deterministic and side-effect free.
83
- *
84
- * "If you can't measure it, you can't improve it." - Brendan Gregg
85
- *
86
- * This enables fine-grained observability at the task level,
87
- * complementing squad-level timeout checks.
88
- *
89
- * @param task - TaskState with optional startedAt timestamp
90
- * @param timeoutMs - Timeout threshold (defaults to LIMITS.watchdogTimeoutMs)
91
- * @returns TimeoutStatus or null if task hasn't started
92
- *
93
- * @example
94
- * const status = checkTaskTimeout(task);
95
- * if (status === null) {
96
- * console.log("Task hasn't started yet");
97
- * } else if (status.isExpired) {
98
- * console.log(`Task stuck for ${status.elapsedMs}ms`);
99
- * }
100
- *
101
- * @example
102
- * // With custom timeout for quick tasks
103
- * const status = checkTaskTimeout(task, 60 * 1000); // 1 minute
104
- */
105
21
  export function checkTaskTimeout(task, timeoutMs) {
106
- // Task hasn't started - no timeout to check
107
22
  if (!task.startedAt) {
108
23
  return null;
109
24
  }
110
25
  const effectiveTimeout = timeoutMs ?? LIMITS.watchdogTimeoutMs;
111
26
  return getTimeoutStatus(task.startedAt, effectiveTimeout);
112
27
  }
113
- // ============================================================================
114
- // State Mutations - Expire Stuck Squads
115
- // ============================================================================
116
- /**
117
- * Mark a squad as expired due to timeout.
118
- * Sets status to "failed" and logs the timeout event.
119
- *
120
- * This should be called after checkSquadTimeout() returns isExpired: true.
121
- * The function is idempotent - calling it multiple times is safe.
122
- *
123
- * @param session - Parent session containing the squad
124
- * @param squadId - ID of the squad to expire
125
- * @returns Updated squad state with status="failed"
126
- *
127
- * @example
128
- * const status = checkSquadTimeout(squadState);
129
- * if (status.isExpired) {
130
- * const failedState = await markSquadExpired(session, squadId);
131
- * console.log(`Squad ${squadId} expired after ${status.elapsedMs}ms`);
132
- * }
133
- */
134
28
  export async function markSquadExpired(session, squadId) {
135
- // Log the timeout event for observability
136
29
  await logEvent(session, squadId, {
137
30
  type: "error",
138
31
  message: "Squad timeout expired",
139
32
  });
140
- // Update state to failed
141
33
  const updatedState = await updateSquadState(session, squadId, {
142
34
  status: "failed",
143
35
  });
144
36
  return updatedState;
145
37
  }
146
- /**
147
- * Run watchdog check on all active squads and tasks.
148
- * Marks expired squads/tasks as failed.
149
- *
150
- * This is meant to be called periodically (e.g., every 30 seconds)
151
- * to detect and handle stuck agents.
152
- *
153
- * "If you can't measure it, you can't improve it." - Brendan Gregg
154
- *
155
- * The dryRun mode allows "measure before fix" - check without modifying state.
156
- *
157
- * @param session - Session to check
158
- * @param options - Optional configuration
159
- * @returns Summary of watchdog run with all metrics
160
- *
161
- * @example
162
- * // Periodic watchdog check (production mode)
163
- * const summary = await runWatchdog(session);
164
- * console.log(`Checked ${summary.checkedSquads} squads`);
165
- * console.log(`Expired: ${summary.expiredSquads.length} squads`);
166
- *
167
- * @example
168
- * // Dry run for monitoring without side effects
169
- * const summary = await runWatchdog(session, { dryRun: true });
170
- * if (summary.expiredSquads.length > 0) {
171
- * alertOnCall(summary);
172
- * }
173
- *
174
- * @example
175
- * // Custom timeouts for specific workloads
176
- * const summary = await runWatchdog(session, {
177
- * squadTimeoutMs: 30 * 60 * 1000, // 30 minutes
178
- * taskTimeoutMs: 10 * 60 * 1000, // 10 minutes
179
- * });
180
- */
181
38
  export async function runWatchdog(session, options) {
182
39
  const squadTimeoutMs = options?.squadTimeoutMs ?? LIMITS.watchdogTimeoutMs;
183
40
  const taskTimeoutMs = options?.taskTimeoutMs ?? LIMITS.watchdogTimeoutMs;
@@ -186,15 +43,12 @@ export async function runWatchdog(session, options) {
186
43
  const expiredTasks = [];
187
44
  let checkedSquads = 0;
188
45
  let checkedTasks = 0;
189
- // Iterate through all squads in the session
190
46
  for (const squadId of session.manifest.squads) {
191
47
  const squad = await getSquad(session, squadId);
192
- // Skip if squad doesn't exist (may have been cleaned up)
193
48
  if (!squad) {
194
49
  continue;
195
50
  }
196
51
  checkedSquads++;
197
- // Only check active squads (skip completed/failed)
198
52
  if (squad.state.status === "active" || squad.state.status === "pending") {
199
53
  const squadStatus = checkSquadTimeout(squad.state, squadTimeoutMs);
200
54
  if (squadStatus.isExpired) {
@@ -204,9 +58,7 @@ export async function runWatchdog(session, options) {
204
58
  }
205
59
  }
206
60
  }
207
- // Check all active tasks in this squad
208
61
  for (const task of squad.state.tasks) {
209
- // Only check tasks that are in progress (active status with startedAt)
210
62
  if (task.status === "active" && task.startedAt) {
211
63
  checkedTasks++;
212
64
  const taskStatus = checkTaskTimeout(task, taskTimeoutMs);
@@ -1,11 +1,3 @@
1
- /**
2
- * Git Worktree Manager
3
- *
4
- * Provides isolated working directories for parallel task execution.
5
- * Each task gets its own git worktree to prevent file conflicts.
6
- *
7
- * @author Linus Torvalds' Dummy Human
8
- */
9
1
  export interface WorktreeInfo {
10
2
  path: string;
11
3
  branch: string;
@@ -13,75 +5,15 @@ export interface WorktreeInfo {
13
5
  createdAt: string;
14
6
  }
15
7
  export interface WorktreeManagerOptions {
16
- /** Root git repository path */
17
8
  repoRoot: string;
18
- /** Base directory for worktrees (default: <repoRoot>/.worktrees) */
19
9
  worktreeBase?: string;
20
- /** Branch prefix for worktree branches (default: "squad/") */
21
10
  branchPrefix?: string;
22
11
  }
23
12
  export interface WorktreeManager {
24
- /**
25
- * Create isolated worktree for a task.
26
- * @param taskId - The ID of the task to associate with the worktree.
27
- * @param baseBranch - The branch to create the worktree from (defaults to current branch).
28
- * @returns Information about the created worktree.
29
- * @throws {Error} If git command fails.
30
- * @example
31
- * const manager = createWorktreeManager({ repoRoot: '/path/to/repo' });
32
- * const info = await manager.create('task-123');
33
- * console.log(info.path); // /path/to/repo/.worktrees/task-123
34
- */
35
13
  create(taskId: string, baseBranch?: string): Promise<WorktreeInfo>;
36
- /**
37
- * Remove worktree after task completion.
38
- * @param taskId - The ID of the task whose worktree should be removed.
39
- * @throws {Error} If git command fails.
40
- * @example
41
- * const manager = createWorktreeManager({ repoRoot: '/path/to/repo' });
42
- * await manager.remove('task-123');
43
- */
44
14
  remove(taskId: string): Promise<void>;
45
- /**
46
- * List all active worktrees managed by this manager.
47
- * @returns A list of active worktree information.
48
- * @throws {Error} If git command fails.
49
- * @example
50
- * const manager = createWorktreeManager({ repoRoot: '/path/to/repo' });
51
- * const worktrees = await manager.list();
52
- * console.log(worktrees);
53
- */
54
15
  list(): Promise<WorktreeInfo[]>;
55
- /**
56
- * Clean up all worktrees managed by this manager (for session end).
57
- * @throws {Error} If git command fails.
58
- * @example
59
- * const manager = createWorktreeManager({ repoRoot: '/path/to/repo' });
60
- * await manager.cleanup();
61
- */
62
16
  cleanup(): Promise<void>;
63
- /**
64
- * Get worktree info for a specific task.
65
- * @param taskId - The ID of the task.
66
- * @returns WorktreeInfo if found, otherwise null.
67
- * @throws {Error} If git command fails.
68
- * @example
69
- * const manager = createWorktreeManager({ repoRoot: '/path/to/repo' });
70
- * const info = await manager.get('task-123');
71
- * if (info) console.log(info.branch);
72
- */
73
17
  get(taskId: string): Promise<WorktreeInfo | null>;
74
18
  }
75
- /**
76
- * Create a WorktreeManager instance.
77
- * Uses git worktree add/remove commands internally.
78
- * @param options - Configuration options for the WorktreeManager.
79
- * @returns A WorktreeManager instance.
80
- * @example
81
- * const manager = createWorktreeManager({
82
- * repoRoot: process.cwd(),
83
- * worktreeBase: './.squad-worktrees',
84
- * branchPrefix: 'squad-task/'
85
- * });
86
- */
87
19
  export declare function createWorktreeManager(options: WorktreeManagerOptions): WorktreeManager;
@@ -1,28 +1,8 @@
1
- /**
2
- * Git Worktree Manager
3
- *
4
- * Provides isolated working directories for parallel task execution.
5
- * Each task gets its own git worktree to prevent file conflicts.
6
- *
7
- * @author Linus Torvalds' Dummy Human
8
- */
9
1
  import { execFile } from 'child_process';
10
2
  import { join, resolve } from 'path';
11
3
  import { promisify } from 'util';
12
4
  import { mkdir } from 'fs/promises';
13
5
  const execFileAsync = promisify(execFile);
14
- /**
15
- * Create a WorktreeManager instance.
16
- * Uses git worktree add/remove commands internally.
17
- * @param options - Configuration options for the WorktreeManager.
18
- * @returns A WorktreeManager instance.
19
- * @example
20
- * const manager = createWorktreeManager({
21
- * repoRoot: process.cwd(),
22
- * worktreeBase: './.squad-worktrees',
23
- * branchPrefix: 'squad-task/'
24
- * });
25
- */
26
6
  export function createWorktreeManager(options) {
27
7
  const repoRoot = resolve(options.repoRoot);
28
8
  const worktreeBase = resolve(repoRoot, options.worktreeBase || '.worktrees');
@@ -43,9 +23,7 @@ export function createWorktreeManager(options) {
43
23
  async create(taskId, baseBranch) {
44
24
  const worktreePath = getWorktreePath(taskId);
45
25
  const branchName = getBranchName(taskId);
46
- // Ensure worktreeBase directory exists
47
26
  await mkdir(worktreeBase, { recursive: true });
48
- // Check if worktree already exists
49
27
  try {
50
28
  const existing = await this.get(taskId);
51
29
  if (existing) {
@@ -53,11 +31,8 @@ export function createWorktreeManager(options) {
53
31
  }
54
32
  }
55
33
  catch {
56
- // Ignore error if list fails, proceed to create
57
34
  }
58
- // Determine the base commit to branch from
59
35
  const base = baseBranch || 'HEAD';
60
- // Create worktree with a new branch in one step
61
36
  await git(['worktree', 'add', '-b', branchName, worktreePath, base]);
62
37
  return {
63
38
  path: worktreePath,
@@ -69,15 +44,12 @@ export function createWorktreeManager(options) {
69
44
  async remove(taskId) {
70
45
  const worktreePath = getWorktreePath(taskId);
71
46
  const branchName = getBranchName(taskId);
72
- // Check if worktree exists before trying to remove
73
47
  const existing = await this.get(taskId);
74
48
  if (!existing) {
75
49
  console.warn(`Worktree for task ${taskId} not found at ${worktreePath}. Skipping removal.`);
76
50
  return;
77
51
  }
78
- // Remove worktree
79
52
  await git(['worktree', 'remove', worktreePath]);
80
- // Remove associated branch
81
53
  try {
82
54
  await git(['branch', '-D', branchName]);
83
55
  }
@@ -93,7 +65,6 @@ export function createWorktreeManager(options) {
93
65
  for (const line of lines) {
94
66
  if (line.startsWith('worktree ')) {
95
67
  if (currentWorktree.path) {
96
- // Check if it's a squad worktree
97
68
  if (currentWorktree.branch && currentWorktree.branch.startsWith(branchPrefix)) {
98
69
  const taskId = currentWorktree.branch.substring(branchPrefix.length);
99
70
  if (taskId) {
@@ -101,7 +72,7 @@ export function createWorktreeManager(options) {
101
72
  path: currentWorktree.path,
102
73
  branch: currentWorktree.branch,
103
74
  taskId: taskId,
104
- createdAt: new Date().toISOString(), // Placeholder, git worktree list doesn't provide creation time
75
+ createdAt: new Date().toISOString(),
105
76
  });
106
77
  }
107
78
  }
@@ -109,13 +80,10 @@ export function createWorktreeManager(options) {
109
80
  currentWorktree = { path: line.substring('worktree '.length) };
110
81
  }
111
82
  else if (line.startsWith('branch ')) {
112
- // git outputs full ref, e.g. "refs/heads/squad/task-123"
113
83
  const ref = line.substring('branch '.length).trim();
114
84
  currentWorktree.branch = ref.replace(/^refs\/heads\//, '');
115
85
  }
116
- // Other fields like HEAD, bare, etc., are ignored for WorktreeInfo
117
86
  }
118
- // Add the last parsed worktree if it's a squad worktree
119
87
  if (currentWorktree.path && currentWorktree.branch && currentWorktree.branch.startsWith(branchPrefix)) {
120
88
  const taskId = currentWorktree.branch.substring(branchPrefix.length);
121
89
  if (taskId) {
@@ -132,7 +100,7 @@ export function createWorktreeManager(options) {
132
100
  async cleanup() {
133
101
  const worktrees = await this.list();
134
102
  for (const worktree of worktrees) {
135
- if (worktree.branch.startsWith(branchPrefix)) { // Only clean up squad-managed worktrees
103
+ if (worktree.branch.startsWith(branchPrefix)) {
136
104
  await this.remove(worktree.taskId);
137
105
  }
138
106
  }
@@ -1,44 +1,15 @@
1
- /**
2
- * Budget Tracker
3
- *
4
- * Tracks verification costs and enforces budget limits
5
- */
6
1
  import type { BudgetState, ReviewerTier, VerifyConfig } from "./types.js";
7
- /**
8
- * Budget tracker class
9
- */
10
2
  export declare class BudgetTracker {
11
3
  private readonly sessionLimit;
12
4
  private readonly checkLimit;
13
5
  private sessionTotal;
14
6
  private checkTotal;
15
7
  constructor(sessionLimit: number, checkLimit: number);
16
- /**
17
- * Estimate cost for a verification request
18
- */
19
8
  estimateCost(content: string, context: string | undefined, reviewer: ReviewerTier): number;
20
- /**
21
- * Check if a verification can proceed within budget
22
- */
23
9
  canProceed(estimatedCost: number): boolean;
24
- /**
25
- * Record actual cost
26
- */
27
10
  recordCost(cost: number): void;
28
- /**
29
- * Get current budget state
30
- */
31
11
  getState(): BudgetState;
32
- /**
33
- * Reset session budget
34
- */
35
12
  resetSession(): void;
36
- /**
37
- * Reset check budget
38
- */
39
13
  resetCheck(): void;
40
14
  }
41
- /**
42
- * Create budget tracker from config
43
- */
44
15
  export declare function createBudgetTracker(config: VerifyConfig): BudgetTracker;
@@ -1,19 +1,7 @@
1
- /**
2
- * Budget Tracker
3
- *
4
- * Tracks verification costs and enforces budget limits
5
- */
6
1
  import { COST_RATES } from "./types.js";
7
- /**
8
- * Estimates token count from text length
9
- * Rough approximation: 1 token ≈ 4 characters
10
- */
11
2
  function estimateTokens(text) {
12
3
  return Math.ceil(text.length / 4);
13
4
  }
14
- /**
15
- * Budget tracker class
16
- */
17
5
  export class BudgetTracker {
18
6
  sessionLimit;
19
7
  checkLimit;
@@ -23,21 +11,14 @@ export class BudgetTracker {
23
11
  this.sessionLimit = sessionLimit;
24
12
  this.checkLimit = checkLimit;
25
13
  }
26
- /**
27
- * Estimate cost for a verification request
28
- */
29
14
  estimateCost(content, context, reviewer) {
30
15
  const contentTokens = estimateTokens(content);
31
16
  const contextTokens = context ? estimateTokens(context) : 0;
32
17
  const totalTokens = contentTokens + contextTokens;
33
- // Add overhead for prompt template and response (~500 tokens)
34
18
  const totalWithOverhead = totalTokens + 500;
35
19
  const costPer1K = COST_RATES[reviewer];
36
20
  return (totalWithOverhead / 1000) * costPer1K;
37
21
  }
38
- /**
39
- * Check if a verification can proceed within budget
40
- */
41
22
  canProceed(estimatedCost) {
42
23
  if (this.sessionTotal + estimatedCost > this.sessionLimit) {
43
24
  return false;
@@ -47,16 +28,10 @@ export class BudgetTracker {
47
28
  }
48
29
  return true;
49
30
  }
50
- /**
51
- * Record actual cost
52
- */
53
31
  recordCost(cost) {
54
32
  this.sessionTotal += cost;
55
33
  this.checkTotal = cost;
56
34
  }
57
- /**
58
- * Get current budget state
59
- */
60
35
  getState() {
61
36
  return {
62
37
  sessionTotal: this.sessionTotal,
@@ -66,23 +41,14 @@ export class BudgetTracker {
66
41
  exceeded: this.sessionTotal >= this.sessionLimit,
67
42
  };
68
43
  }
69
- /**
70
- * Reset session budget
71
- */
72
44
  resetSession() {
73
45
  this.sessionTotal = 0;
74
46
  this.checkTotal = 0;
75
47
  }
76
- /**
77
- * Reset check budget
78
- */
79
48
  resetCheck() {
80
49
  this.checkTotal = 0;
81
50
  }
82
51
  }
83
- /**
84
- * Create budget tracker from config
85
- */
86
52
  export function createBudgetTracker(config) {
87
53
  return new BudgetTracker(config.budget.maxPerSessionUSD, config.budget.maxPerCheckUSD);
88
54
  }
@@ -1,21 +1,4 @@
1
- /**
2
- * Critical File Detection
3
- *
4
- * Identifies files that require extra scrutiny
5
- */
6
- /**
7
- * Default critical file patterns
8
- */
9
1
  export declare const DEFAULT_CRITICAL_PATTERNS: string[];
10
- /**
11
- * Check if a file path matches critical file patterns
12
- */
13
2
  export declare function isCriticalFile(filePath: string, patterns?: string[]): boolean;
14
- /**
15
- * Get matched critical patterns for a file
16
- */
17
3
  export declare function getMatchedPatterns(filePath: string, patterns?: string[]): string[];
18
- /**
19
- * Categorize criticality level
20
- */
21
4
  export declare function getCriticalityLevel(filePath: string): "critical" | "sensitive" | "normal";