@bradygaster/squad-cli 0.9.1 → 0.9.2-insider.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 (320) hide show
  1. package/README.md +329 -329
  2. package/dist/cli/commands/build.d.ts.map +1 -1
  3. package/dist/cli/commands/build.js +10 -10
  4. package/dist/cli/commands/build.js.map +1 -1
  5. package/dist/cli/commands/config.d.ts +12 -0
  6. package/dist/cli/commands/config.d.ts.map +1 -0
  7. package/dist/cli/commands/config.js +157 -0
  8. package/dist/cli/commands/config.js.map +1 -0
  9. package/dist/cli/commands/consult.d.ts.map +1 -1
  10. package/dist/cli/commands/consult.js +9 -4
  11. package/dist/cli/commands/consult.js.map +1 -1
  12. package/dist/cli/commands/copilot.d.ts.map +1 -1
  13. package/dist/cli/commands/copilot.js +8 -7
  14. package/dist/cli/commands/copilot.js.map +1 -1
  15. package/dist/cli/commands/doctor.d.ts.map +1 -1
  16. package/dist/cli/commands/doctor.js +50 -17
  17. package/dist/cli/commands/doctor.js.map +1 -1
  18. package/dist/cli/commands/economy.d.ts.map +1 -1
  19. package/dist/cli/commands/economy.js +3 -2
  20. package/dist/cli/commands/economy.js.map +1 -1
  21. package/dist/cli/commands/export.d.ts.map +1 -1
  22. package/dist/cli/commands/export.js +22 -16
  23. package/dist/cli/commands/export.js.map +1 -1
  24. package/dist/cli/commands/extract.d.ts.map +1 -1
  25. package/dist/cli/commands/extract.js +14 -10
  26. package/dist/cli/commands/extract.js.map +1 -1
  27. package/dist/cli/commands/import.d.ts.map +1 -1
  28. package/dist/cli/commands/import.js +21 -18
  29. package/dist/cli/commands/import.js.map +1 -1
  30. package/dist/cli/commands/init-remote.d.ts.map +1 -1
  31. package/dist/cli/commands/init-remote.js +7 -6
  32. package/dist/cli/commands/init-remote.js.map +1 -1
  33. package/dist/cli/commands/link.d.ts.map +1 -1
  34. package/dist/cli/commands/link.js +11 -10
  35. package/dist/cli/commands/link.js.map +1 -1
  36. package/dist/cli/commands/migrate.d.ts.map +1 -1
  37. package/dist/cli/commands/migrate.js +19 -18
  38. package/dist/cli/commands/migrate.js.map +1 -1
  39. package/dist/cli/commands/personal.d.ts.map +1 -1
  40. package/dist/cli/commands/personal.js +57 -65
  41. package/dist/cli/commands/personal.js.map +1 -1
  42. package/dist/cli/commands/plugin.d.ts.map +1 -1
  43. package/dist/cli/commands/plugin.js +8 -7
  44. package/dist/cli/commands/plugin.js.map +1 -1
  45. package/dist/cli/commands/rc.d.ts.map +1 -1
  46. package/dist/cli/commands/rc.js +19 -12
  47. package/dist/cli/commands/rc.js.map +1 -1
  48. package/dist/cli/commands/schedule.d.ts.map +1 -1
  49. package/dist/cli/commands/schedule.js +6 -5
  50. package/dist/cli/commands/schedule.js.map +1 -1
  51. package/dist/cli/commands/start.d.ts.map +1 -1
  52. package/dist/cli/commands/start.js +18 -11
  53. package/dist/cli/commands/start.js.map +1 -1
  54. package/dist/cli/commands/streams.d.ts.map +1 -1
  55. package/dist/cli/commands/streams.js +3 -2
  56. package/dist/cli/commands/streams.js.map +1 -1
  57. package/dist/cli/commands/upstream.d.ts.map +1 -1
  58. package/dist/cli/commands/upstream.js +23 -19
  59. package/dist/cli/commands/upstream.js.map +1 -1
  60. package/dist/cli/commands/watch/capabilities/board.d.ts +22 -0
  61. package/dist/cli/commands/watch/capabilities/board.d.ts.map +1 -0
  62. package/dist/cli/commands/watch/capabilities/board.js +121 -0
  63. package/dist/cli/commands/watch/capabilities/board.js.map +1 -0
  64. package/dist/cli/commands/watch/capabilities/budget-check.d.ts +29 -0
  65. package/dist/cli/commands/watch/capabilities/budget-check.d.ts.map +1 -0
  66. package/dist/cli/commands/watch/capabilities/budget-check.js +38 -0
  67. package/dist/cli/commands/watch/capabilities/budget-check.js.map +1 -0
  68. package/dist/cli/commands/watch/capabilities/circuit-breaker.d.ts +52 -0
  69. package/dist/cli/commands/watch/capabilities/circuit-breaker.d.ts.map +1 -0
  70. package/dist/cli/commands/watch/capabilities/circuit-breaker.js +152 -0
  71. package/dist/cli/commands/watch/capabilities/circuit-breaker.js.map +1 -0
  72. package/dist/cli/commands/watch/capabilities/decision-hygiene.d.ts +14 -0
  73. package/dist/cli/commands/watch/capabilities/decision-hygiene.d.ts.map +1 -0
  74. package/dist/cli/commands/watch/capabilities/decision-hygiene.js +72 -0
  75. package/dist/cli/commands/watch/capabilities/decision-hygiene.js.map +1 -0
  76. package/dist/cli/commands/watch/capabilities/execute.d.ts +33 -0
  77. package/dist/cli/commands/watch/capabilities/execute.d.ts.map +1 -0
  78. package/dist/cli/commands/watch/capabilities/execute.js +156 -0
  79. package/dist/cli/commands/watch/capabilities/execute.js.map +1 -0
  80. package/dist/cli/commands/watch/capabilities/health-check.d.ts +29 -0
  81. package/dist/cli/commands/watch/capabilities/health-check.d.ts.map +1 -0
  82. package/dist/cli/commands/watch/capabilities/health-check.js +139 -0
  83. package/dist/cli/commands/watch/capabilities/health-check.js.map +1 -0
  84. package/dist/cli/commands/watch/capabilities/heartbeat.d.ts +48 -0
  85. package/dist/cli/commands/watch/capabilities/heartbeat.d.ts.map +1 -0
  86. package/dist/cli/commands/watch/capabilities/heartbeat.js +115 -0
  87. package/dist/cli/commands/watch/capabilities/heartbeat.js.map +1 -0
  88. package/dist/cli/commands/watch/capabilities/index.d.ts +9 -0
  89. package/dist/cli/commands/watch/capabilities/index.d.ts.map +1 -0
  90. package/dist/cli/commands/watch/capabilities/index.js +40 -0
  91. package/dist/cli/commands/watch/capabilities/index.js.map +1 -0
  92. package/dist/cli/commands/watch/capabilities/lockfile.d.ts +30 -0
  93. package/dist/cli/commands/watch/capabilities/lockfile.d.ts.map +1 -0
  94. package/dist/cli/commands/watch/capabilities/lockfile.js +100 -0
  95. package/dist/cli/commands/watch/capabilities/lockfile.js.map +1 -0
  96. package/dist/cli/commands/watch/capabilities/machine-capabilities.d.ts +30 -0
  97. package/dist/cli/commands/watch/capabilities/machine-capabilities.d.ts.map +1 -0
  98. package/dist/cli/commands/watch/capabilities/machine-capabilities.js +103 -0
  99. package/dist/cli/commands/watch/capabilities/machine-capabilities.js.map +1 -0
  100. package/dist/cli/commands/watch/capabilities/monitor-email.d.ts +14 -0
  101. package/dist/cli/commands/watch/capabilities/monitor-email.d.ts.map +1 -0
  102. package/dist/cli/commands/watch/capabilities/monitor-email.js +54 -0
  103. package/dist/cli/commands/watch/capabilities/monitor-email.js.map +1 -0
  104. package/dist/cli/commands/watch/capabilities/monitor-teams.d.ts +14 -0
  105. package/dist/cli/commands/watch/capabilities/monitor-teams.d.ts.map +1 -0
  106. package/dist/cli/commands/watch/capabilities/monitor-teams.js +55 -0
  107. package/dist/cli/commands/watch/capabilities/monitor-teams.js.map +1 -0
  108. package/dist/cli/commands/watch/capabilities/post-failure.d.ts +19 -0
  109. package/dist/cli/commands/watch/capabilities/post-failure.d.ts.map +1 -0
  110. package/dist/cli/commands/watch/capabilities/post-failure.js +58 -0
  111. package/dist/cli/commands/watch/capabilities/post-failure.js.map +1 -0
  112. package/dist/cli/commands/watch/capabilities/priority.d.ts +59 -0
  113. package/dist/cli/commands/watch/capabilities/priority.d.ts.map +1 -0
  114. package/dist/cli/commands/watch/capabilities/priority.js +101 -0
  115. package/dist/cli/commands/watch/capabilities/priority.js.map +1 -0
  116. package/dist/cli/commands/watch/capabilities/rate-pool.d.ts +67 -0
  117. package/dist/cli/commands/watch/capabilities/rate-pool.d.ts.map +1 -0
  118. package/dist/cli/commands/watch/capabilities/rate-pool.js +187 -0
  119. package/dist/cli/commands/watch/capabilities/rate-pool.js.map +1 -0
  120. package/dist/cli/commands/watch/capabilities/retro.d.ts +14 -0
  121. package/dist/cli/commands/watch/capabilities/retro.d.ts.map +1 -0
  122. package/dist/cli/commands/watch/capabilities/retro.js +81 -0
  123. package/dist/cli/commands/watch/capabilities/retro.js.map +1 -0
  124. package/dist/cli/commands/watch/capabilities/self-pull.d.ts +14 -0
  125. package/dist/cli/commands/watch/capabilities/self-pull.d.ts.map +1 -0
  126. package/dist/cli/commands/watch/capabilities/self-pull.js +33 -0
  127. package/dist/cli/commands/watch/capabilities/self-pull.js.map +1 -0
  128. package/dist/cli/commands/watch/capabilities/stale-reclaim.d.ts +23 -0
  129. package/dist/cli/commands/watch/capabilities/stale-reclaim.d.ts.map +1 -0
  130. package/dist/cli/commands/watch/capabilities/stale-reclaim.js +87 -0
  131. package/dist/cli/commands/watch/capabilities/stale-reclaim.js.map +1 -0
  132. package/dist/cli/commands/watch/capabilities/two-pass.d.ts +14 -0
  133. package/dist/cli/commands/watch/capabilities/two-pass.d.ts.map +1 -0
  134. package/dist/cli/commands/watch/capabilities/two-pass.js +66 -0
  135. package/dist/cli/commands/watch/capabilities/two-pass.js.map +1 -0
  136. package/dist/cli/commands/watch/capabilities/wave-dispatch.d.ts +14 -0
  137. package/dist/cli/commands/watch/capabilities/wave-dispatch.d.ts.map +1 -0
  138. package/dist/cli/commands/watch/capabilities/wave-dispatch.js +117 -0
  139. package/dist/cli/commands/watch/capabilities/wave-dispatch.js.map +1 -0
  140. package/dist/cli/commands/watch/capabilities/webhook-alerts.d.ts +29 -0
  141. package/dist/cli/commands/watch/capabilities/webhook-alerts.d.ts.map +1 -0
  142. package/dist/cli/commands/watch/capabilities/webhook-alerts.js +114 -0
  143. package/dist/cli/commands/watch/capabilities/webhook-alerts.js.map +1 -0
  144. package/dist/cli/commands/watch/config.d.ts +40 -0
  145. package/dist/cli/commands/watch/config.d.ts.map +1 -0
  146. package/dist/cli/commands/watch/config.js +129 -0
  147. package/dist/cli/commands/watch/config.js.map +1 -0
  148. package/dist/cli/commands/watch/index.d.ts +109 -0
  149. package/dist/cli/commands/watch/index.d.ts.map +1 -0
  150. package/dist/cli/commands/watch/index.js +757 -0
  151. package/dist/cli/commands/watch/index.js.map +1 -0
  152. package/dist/cli/commands/watch/registry.d.ts +19 -0
  153. package/dist/cli/commands/watch/registry.d.ts.map +1 -0
  154. package/dist/cli/commands/watch/registry.js +28 -0
  155. package/dist/cli/commands/watch/registry.js.map +1 -0
  156. package/dist/cli/commands/watch/types.d.ts +57 -0
  157. package/dist/cli/commands/watch/types.d.ts.map +1 -0
  158. package/dist/cli/commands/watch/types.js +8 -0
  159. package/dist/cli/commands/watch/types.js.map +1 -0
  160. package/dist/cli/core/cast.d.ts.map +1 -1
  161. package/dist/cli/core/cast.js +15 -19
  162. package/dist/cli/core/cast.js.map +1 -1
  163. package/dist/cli/core/detect-squad-dir.d.ts.map +1 -1
  164. package/dist/cli/core/detect-squad-dir.js +12 -10
  165. package/dist/cli/core/detect-squad-dir.js.map +1 -1
  166. package/dist/cli/core/email-scrub.d.ts.map +1 -1
  167. package/dist/cli/core/email-scrub.js +12 -11
  168. package/dist/cli/core/email-scrub.js.map +1 -1
  169. package/dist/cli/core/gh-cli.d.ts +13 -0
  170. package/dist/cli/core/gh-cli.d.ts.map +1 -1
  171. package/dist/cli/core/gh-cli.js +24 -0
  172. package/dist/cli/core/gh-cli.js.map +1 -1
  173. package/dist/cli/core/init.d.ts +2 -0
  174. package/dist/cli/core/init.d.ts.map +1 -1
  175. package/dist/cli/core/init.js +22 -5
  176. package/dist/cli/core/init.js.map +1 -1
  177. package/dist/cli/core/migrate-directory.d.ts.map +1 -1
  178. package/dist/cli/core/migrate-directory.js +14 -13
  179. package/dist/cli/core/migrate-directory.js.map +1 -1
  180. package/dist/cli/core/migrations.d.ts.map +1 -1
  181. package/dist/cli/core/migrations.js +22 -8
  182. package/dist/cli/core/migrations.js.map +1 -1
  183. package/dist/cli/core/nap.d.ts.map +1 -1
  184. package/dist/cli/core/nap.js +116 -49
  185. package/dist/cli/core/nap.js.map +1 -1
  186. package/dist/cli/core/project-type.d.ts.map +1 -1
  187. package/dist/cli/core/project-type.js +11 -10
  188. package/dist/cli/core/project-type.js.map +1 -1
  189. package/dist/cli/core/team-md.d.ts.map +1 -1
  190. package/dist/cli/core/team-md.js +43 -38
  191. package/dist/cli/core/team-md.js.map +1 -1
  192. package/dist/cli/core/templates.d.ts.map +1 -1
  193. package/dist/cli/core/templates.js +4 -3
  194. package/dist/cli/core/templates.js.map +1 -1
  195. package/dist/cli/core/upgrade.d.ts.map +1 -1
  196. package/dist/cli/core/upgrade.js +68 -55
  197. package/dist/cli/core/upgrade.js.map +1 -1
  198. package/dist/cli/core/version.d.ts.map +1 -1
  199. package/dist/cli/core/version.js +8 -7
  200. package/dist/cli/core/version.js.map +1 -1
  201. package/dist/cli/index.d.ts +1 -1
  202. package/dist/cli/index.d.ts.map +1 -1
  203. package/dist/cli/index.js +1 -1
  204. package/dist/cli/index.js.map +1 -1
  205. package/dist/cli/self-update.d.ts.map +1 -1
  206. package/dist/cli/self-update.js +7 -4
  207. package/dist/cli/self-update.js.map +1 -1
  208. package/dist/cli/shell/agent-name-parser.d.ts +16 -0
  209. package/dist/cli/shell/agent-name-parser.d.ts.map +1 -0
  210. package/dist/cli/shell/agent-name-parser.js +54 -0
  211. package/dist/cli/shell/agent-name-parser.js.map +1 -0
  212. package/dist/cli/shell/commands.d.ts.map +1 -1
  213. package/dist/cli/shell/commands.js +4 -3
  214. package/dist/cli/shell/commands.js.map +1 -1
  215. package/dist/cli/shell/coordinator.d.ts +4 -1
  216. package/dist/cli/shell/coordinator.d.ts.map +1 -1
  217. package/dist/cli/shell/coordinator.js +29 -26
  218. package/dist/cli/shell/coordinator.js.map +1 -1
  219. package/dist/cli/shell/index.d.ts.map +1 -1
  220. package/dist/cli/shell/index.js +33 -35
  221. package/dist/cli/shell/index.js.map +1 -1
  222. package/dist/cli/shell/lifecycle.d.ts +13 -2
  223. package/dist/cli/shell/lifecycle.d.ts.map +1 -1
  224. package/dist/cli/shell/lifecycle.js +26 -13
  225. package/dist/cli/shell/lifecycle.js.map +1 -1
  226. package/dist/cli/shell/session-store.d.ts.map +1 -1
  227. package/dist/cli/shell/session-store.js +16 -12
  228. package/dist/cli/shell/session-store.js.map +1 -1
  229. package/dist/cli/shell/spawn.d.ts +4 -1
  230. package/dist/cli/shell/spawn.d.ts.map +1 -1
  231. package/dist/cli/shell/spawn.js +28 -10
  232. package/dist/cli/shell/spawn.js.map +1 -1
  233. package/dist/cli-entry.js +136 -12
  234. package/dist/cli-entry.js.map +1 -1
  235. package/package.json +8 -4
  236. package/scripts/patch-esm-imports.mjs +105 -105
  237. package/scripts/patch-ink-rendering.mjs +115 -115
  238. package/templates/casting/Futurama.json +9 -9
  239. package/templates/casting-history.json +4 -4
  240. package/templates/casting-policy.json +37 -37
  241. package/templates/casting-reference.md +104 -104
  242. package/templates/casting-registry.json +3 -3
  243. package/templates/ceremonies.md +41 -41
  244. package/templates/charter.md +53 -53
  245. package/templates/constraint-tracking.md +38 -38
  246. package/templates/cooperative-rate-limiting.md +229 -229
  247. package/templates/copilot-instructions.md +46 -46
  248. package/templates/history.md +10 -10
  249. package/templates/identity/now.md +9 -9
  250. package/templates/identity/wisdom.md +15 -15
  251. package/templates/issue-lifecycle.md +412 -412
  252. package/templates/keda-scaler.md +164 -164
  253. package/templates/machine-capabilities.md +74 -74
  254. package/templates/mcp-config.md +90 -90
  255. package/templates/multi-agent-format.md +28 -28
  256. package/templates/orchestration-log.md +27 -27
  257. package/templates/plugin-marketplace.md +49 -49
  258. package/templates/ralph-circuit-breaker.md +313 -313
  259. package/templates/raw-agent-output.md +37 -37
  260. package/templates/roster.md +60 -60
  261. package/templates/routing.md +39 -39
  262. package/templates/run-output.md +50 -50
  263. package/templates/scribe-charter.md +123 -119
  264. package/templates/skill.md +24 -24
  265. package/templates/skills/agent-collaboration/SKILL.md +42 -42
  266. package/templates/skills/agent-conduct/SKILL.md +24 -24
  267. package/templates/skills/architectural-proposals/SKILL.md +151 -151
  268. package/templates/skills/ci-validation-gates/SKILL.md +84 -84
  269. package/templates/skills/cli-wiring/SKILL.md +47 -47
  270. package/templates/skills/client-compatibility/SKILL.md +89 -89
  271. package/templates/skills/cross-machine-coordination/SKILL.md +434 -0
  272. package/templates/skills/cross-squad/SKILL.md +114 -114
  273. package/templates/skills/distributed-mesh/SKILL.md +287 -287
  274. package/templates/skills/distributed-mesh/mesh.json.example +30 -30
  275. package/templates/skills/distributed-mesh/sync-mesh.ps1 +111 -111
  276. package/templates/skills/distributed-mesh/sync-mesh.sh +104 -104
  277. package/templates/skills/docs-standards/SKILL.md +71 -71
  278. package/templates/skills/economy-mode/SKILL.md +114 -114
  279. package/templates/skills/error-recovery/SKILL.md +99 -0
  280. package/templates/skills/external-comms/SKILL.md +329 -329
  281. package/templates/skills/gh-auth-isolation/SKILL.md +183 -183
  282. package/templates/skills/git-workflow/SKILL.md +204 -204
  283. package/templates/skills/github-multi-account/SKILL.md +95 -95
  284. package/templates/skills/history-hygiene/SKILL.md +36 -36
  285. package/templates/skills/humanizer/SKILL.md +105 -105
  286. package/templates/skills/init-mode/SKILL.md +102 -102
  287. package/templates/skills/iterative-retrieval/SKILL.md +165 -0
  288. package/templates/skills/model-selection/SKILL.md +117 -117
  289. package/templates/skills/nap/SKILL.md +24 -24
  290. package/templates/skills/notification-routing/SKILL.md +105 -0
  291. package/templates/skills/personal-squad/SKILL.md +57 -57
  292. package/templates/skills/pr-screenshots/SKILL.md +149 -0
  293. package/templates/skills/ralph-two-pass-scan/SKILL.md +35 -0
  294. package/templates/skills/reflect/SKILL.md +229 -0
  295. package/templates/skills/release-process/SKILL.md +131 -423
  296. package/templates/skills/reskill/SKILL.md +92 -92
  297. package/templates/skills/retro-enforcement/SKILL.md +148 -0
  298. package/templates/skills/reviewer-protocol/SKILL.md +79 -79
  299. package/templates/skills/secret-handling/SKILL.md +200 -200
  300. package/templates/skills/session-recovery/SKILL.md +155 -155
  301. package/templates/skills/squad-conventions/SKILL.md +69 -69
  302. package/templates/skills/test-discipline/SKILL.md +37 -37
  303. package/templates/skills/tiered-memory/SKILL.md +234 -0
  304. package/templates/skills/windows-compatibility/SKILL.md +98 -74
  305. package/templates/{squad.agent.md → squad.agent.md.template} +1316 -1287
  306. package/templates/workflows/squad-ci.yml +24 -24
  307. package/templates/workflows/squad-docs.yml +54 -54
  308. package/templates/workflows/squad-heartbeat.yml +0 -4
  309. package/templates/workflows/squad-insider-release.yml +61 -61
  310. package/templates/workflows/squad-issue-assign.yml +161 -161
  311. package/templates/workflows/squad-label-enforce.yml +181 -181
  312. package/templates/workflows/squad-preview.yml +55 -55
  313. package/templates/workflows/squad-promote.yml +120 -120
  314. package/templates/workflows/squad-release.yml +77 -77
  315. package/templates/workflows/squad-triage.yml +260 -260
  316. package/templates/workflows/sync-squad-labels.yml +169 -169
  317. package/dist/cli/commands/watch.d.ts +0 -18
  318. package/dist/cli/commands/watch.d.ts.map +0 -1
  319. package/dist/cli/commands/watch.js +0 -306
  320. package/dist/cli/commands/watch.js.map +0 -1
@@ -0,0 +1,121 @@
1
+ /**
2
+ * Board capability — project board lifecycle + reconciliation.
3
+ */
4
+ import { execFile, execFileSync } from 'node:child_process';
5
+ import { promisify } from 'node:util';
6
+ const execFileAsync = promisify(execFile);
7
+ export class BoardCapability {
8
+ name = 'board';
9
+ description = 'Project board lifecycle (In Progress / Done / Blocked + reconciliation)';
10
+ configShape = 'object';
11
+ requires = ['gh'];
12
+ phase = 'post-execute';
13
+ async preflight(_context) {
14
+ try {
15
+ await execFileAsync('gh', ['project', '--help']);
16
+ return { ok: true };
17
+ }
18
+ catch {
19
+ return { ok: false, reason: 'gh project CLI not available or not authenticated' };
20
+ }
21
+ }
22
+ async execute(context) {
23
+ const projectNumber = context.config['projectNumber'] ?? 1;
24
+ let mismatches = 0;
25
+ try {
26
+ // Reconcile: move closed issues to Done, open issues out of Done
27
+ const { stdout: itemsJson } = await execFileAsync('gh', [
28
+ 'project', 'item-list', String(projectNumber),
29
+ '--owner', '@me',
30
+ '--format', 'json',
31
+ '--limit', '300',
32
+ ], { maxBuffer: 10 * 1024 * 1024 });
33
+ const items = JSON.parse(itemsJson);
34
+ if (items.items?.length) {
35
+ const threeDaysMs = 3 * 24 * 60 * 60 * 1000;
36
+ for (const item of items.items) {
37
+ if (!item.content?.number || item.content.type !== 'Issue')
38
+ continue;
39
+ const isClosed = item.content.state === 'CLOSED';
40
+ const isDone = item.status?.toLowerCase() === 'done';
41
+ if (isClosed && !isDone) {
42
+ mismatches++;
43
+ }
44
+ else if (!isClosed && isDone) {
45
+ mismatches++;
46
+ }
47
+ // Archive: close issues in Done for >3 days
48
+ if (item.status?.toLowerCase() === 'done' &&
49
+ item.content.state !== 'CLOSED' &&
50
+ item.updatedAt) {
51
+ const updatedAt = new Date(item.updatedAt).getTime();
52
+ if (Date.now() - updatedAt >= threeDaysMs) {
53
+ try {
54
+ await new Promise((resolve, reject) => {
55
+ execFile('gh', ['issue', 'close', String(item.content.number), '--comment',
56
+ '🤖 Ralph: Auto-closing — issue has been in Done for >3 days.'], { maxBuffer: 5 * 1024 * 1024 }, (err) => (err ? reject(err) : resolve()));
57
+ });
58
+ }
59
+ catch { /* best-effort */ }
60
+ }
61
+ }
62
+ }
63
+ }
64
+ return {
65
+ success: true,
66
+ summary: mismatches > 0 ? `${mismatches} board mismatch(es) reconciled` : 'board in sync',
67
+ data: { mismatches },
68
+ };
69
+ }
70
+ catch (e) {
71
+ return { success: false, summary: `board error: ${e.message}` };
72
+ }
73
+ }
74
+ }
75
+ /**
76
+ * Move an issue to a status column on a GitHub Projects v2 board.
77
+ * Exported so the main orchestrator can call it for execute-mode transitions.
78
+ */
79
+ export async function updateBoardStatus(issueNumber, status, options) {
80
+ const projectNum = options.projectNumber ?? 1;
81
+ try {
82
+ let repoUrl;
83
+ try {
84
+ const repoName = execFileSync('gh', ['repo', 'view', '--json', 'nameWithOwner', '-q', '.nameWithOwner'], {
85
+ encoding: 'utf-8', timeout: 10_000,
86
+ }).trim();
87
+ repoUrl = `https://github.com/${repoName}/issues/${issueNumber}`;
88
+ }
89
+ catch {
90
+ return;
91
+ }
92
+ await execFileAsync('gh', [
93
+ 'project', 'item-add', String(projectNum),
94
+ '--owner', options.owner ?? '@me',
95
+ '--url', repoUrl,
96
+ ], { maxBuffer: 5 * 1024 * 1024 });
97
+ const statusMap = {
98
+ 'todo': 'Todo', 'in-progress': 'In Progress', 'done': 'Done', 'blocked': 'Blocked',
99
+ };
100
+ const statusValue = statusMap[status] ?? 'Todo';
101
+ const { stdout: itemsJson } = await execFileAsync('gh', [
102
+ 'project', 'item-list', String(projectNum),
103
+ '--owner', options.owner ?? '@me',
104
+ '--format', 'json',
105
+ '--limit', '300',
106
+ ], { maxBuffer: 10 * 1024 * 1024 });
107
+ const items = JSON.parse(itemsJson);
108
+ const item = items.items?.find(i => i.content?.number === issueNumber);
109
+ if (!item)
110
+ return;
111
+ await execFileAsync('gh', [
112
+ 'project', 'item-edit',
113
+ '--project-id', String(projectNum),
114
+ '--id', item.id,
115
+ '--field-id', 'Status',
116
+ '--single-select-option-id', statusValue,
117
+ ], { maxBuffer: 5 * 1024 * 1024 });
118
+ }
119
+ catch { /* best-effort */ }
120
+ }
121
+ //# sourceMappingURL=board.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"board.js","sourceRoot":"","sources":["../../../../../src/cli/commands/watch/capabilities/board.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Budget check utility — enforce configurable per-round limits.
3
+ *
4
+ * Ported from ralph-watch.ps1 rate-pool / budget tracking logic.
5
+ *
6
+ * Config (via squad.config.ts → watch.capabilities or CLI flags):
7
+ * maxIssuesPerRound – max issues to execute in a single round (default: 5)
8
+ * maxCostPerRound – cost cap (abstract units) per round (default: Infinity)
9
+ *
10
+ * This is a utility module — not a WatchCapability.
11
+ * Called by the execute capability before spawning agent sessions.
12
+ */
13
+ export interface BudgetConfig {
14
+ maxIssuesPerRound?: number;
15
+ maxCostPerRound?: number;
16
+ }
17
+ export interface BudgetResult {
18
+ allowed: number;
19
+ reason: string;
20
+ }
21
+ /**
22
+ * Determine how many issues can be executed this round given budget constraints.
23
+ *
24
+ * @param requested Number of issues the execute phase wants to process.
25
+ * @param config Budget limits from config or CLI.
26
+ * @returns How many are allowed + explanation.
27
+ */
28
+ export declare function checkBudget(requested: number, config?: BudgetConfig): BudgetResult;
29
+ //# sourceMappingURL=budget-check.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"budget-check.d.ts","sourceRoot":"","sources":["../../../../../src/cli/commands/watch/capabilities/budget-check.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,MAAM,WAAW,YAAY;IAC3B,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;CAChB;AAID;;;;;;GAMG;AACH,wBAAgB,WAAW,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,YAAY,GAAG,YAAY,CAmBlF"}
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Budget check utility — enforce configurable per-round limits.
3
+ *
4
+ * Ported from ralph-watch.ps1 rate-pool / budget tracking logic.
5
+ *
6
+ * Config (via squad.config.ts → watch.capabilities or CLI flags):
7
+ * maxIssuesPerRound – max issues to execute in a single round (default: 5)
8
+ * maxCostPerRound – cost cap (abstract units) per round (default: Infinity)
9
+ *
10
+ * This is a utility module — not a WatchCapability.
11
+ * Called by the execute capability before spawning agent sessions.
12
+ */
13
+ const DEFAULT_MAX_ISSUES = 5;
14
+ /**
15
+ * Determine how many issues can be executed this round given budget constraints.
16
+ *
17
+ * @param requested Number of issues the execute phase wants to process.
18
+ * @param config Budget limits from config or CLI.
19
+ * @returns How many are allowed + explanation.
20
+ */
21
+ export function checkBudget(requested, config) {
22
+ const maxIssues = config?.maxIssuesPerRound ?? DEFAULT_MAX_ISSUES;
23
+ const maxCost = config?.maxCostPerRound ?? Infinity;
24
+ // Simple issue-count gate
25
+ if (requested <= maxIssues && maxCost === Infinity) {
26
+ return { allowed: requested, reason: `within budget (${requested}/${maxIssues})` };
27
+ }
28
+ const allowed = Math.min(requested, maxIssues);
29
+ const reasons = [];
30
+ if (requested > maxIssues) {
31
+ reasons.push(`capped to ${maxIssues} issues/round`);
32
+ }
33
+ if (maxCost !== Infinity) {
34
+ reasons.push(`cost cap: ${maxCost}`);
35
+ }
36
+ return { allowed, reason: reasons.join('; ') };
37
+ }
38
+ //# sourceMappingURL=budget-check.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"budget-check.js","sourceRoot":"","sources":["../../../../../src/cli/commands/watch/capabilities/budget-check.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAYH,MAAM,kBAAkB,GAAG,CAAC,CAAC;AAE7B;;;;;;GAMG;AACH,MAAM,UAAU,WAAW,CAAC,SAAiB,EAAE,MAAqB;IAClE,MAAM,SAAS,GAAG,MAAM,EAAE,iBAAiB,IAAI,kBAAkB,CAAC;IAClE,MAAM,OAAO,GAAG,MAAM,EAAE,eAAe,IAAI,QAAQ,CAAC;IAEpD,0BAA0B;IAC1B,IAAI,SAAS,IAAI,SAAS,IAAI,OAAO,KAAK,QAAQ,EAAE,CAAC;QACnD,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,kBAAkB,SAAS,IAAI,SAAS,GAAG,EAAE,CAAC;IACrF,CAAC;IAED,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC;IAC/C,MAAM,OAAO,GAAa,EAAE,CAAC;IAC7B,IAAI,SAAS,GAAG,SAAS,EAAE,CAAC;QAC1B,OAAO,CAAC,IAAI,CAAC,aAAa,SAAS,eAAe,CAAC,CAAC;IACtD,CAAC;IACD,IAAI,OAAO,KAAK,QAAQ,EAAE,CAAC;QACzB,OAAO,CAAC,IAAI,CAAC,aAAa,OAAO,EAAE,CAAC,CAAC;IACvC,CAAC;IAED,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;AACjD,CAAC"}
@@ -0,0 +1,52 @@
1
+ /**
2
+ * Enhanced Circuit Breaker capability — model-level fallback with cooldown.
3
+ *
4
+ * Ported from ralph-watch.ps1 `Get-CircuitBreakerState` / `Update-CircuitBreakerOn*`.
5
+ * Tracks model failures, auto-fallback through a configurable chain, and
6
+ * cooldown timer. State persisted to `.squad/ralph-circuit-breaker.json`.
7
+ *
8
+ * This is a **utility module** consumed by the main watch loop, not a
9
+ * phase-based capability (it gates every round, not a specific phase).
10
+ *
11
+ * Config (via squad.config.ts → watch.circuitBreaker):
12
+ * preferredModel – default model to use (default: "claude-sonnet-4")
13
+ * fallbackChain – ordered list of fallback models
14
+ * cooldownMinutes – minutes before half-open probe (default: 10)
15
+ * requiredSuccessesToClose – successes in half-open before closing (default: 2)
16
+ */
17
+ export type CircuitState = 'closed' | 'open' | 'half-open';
18
+ export interface ModelCircuitBreakerState {
19
+ state: CircuitState;
20
+ preferredModel: string;
21
+ currentModel: string;
22
+ fallbackChain: string[];
23
+ lastRateLimitHit: string | null;
24
+ cooldownMinutes: number;
25
+ consecutiveSuccesses: number;
26
+ requiredSuccessesToClose: number;
27
+ totalFallbacks: number;
28
+ totalRecoveries: number;
29
+ }
30
+ export interface CircuitBreakerConfig {
31
+ preferredModel?: string;
32
+ fallbackChain?: string[];
33
+ cooldownMinutes?: number;
34
+ requiredSuccessesToClose?: number;
35
+ }
36
+ export declare class ModelCircuitBreaker {
37
+ private statePath;
38
+ constructor(squadDir: string, config?: CircuitBreakerConfig);
39
+ load(): ModelCircuitBreakerState;
40
+ save(state: ModelCircuitBreakerState): void;
41
+ /** Get the model to use for the current round. */
42
+ getCurrentModel(): string;
43
+ /** Call after a successful round. */
44
+ onSuccess(): void;
45
+ /** Call when a rate limit or model error is detected. */
46
+ onRateLimit(): void;
47
+ /** Reset to defaults (used by post-failure remediation). */
48
+ reset(): void;
49
+ /** Get full state for diagnostics. */
50
+ getState(): ModelCircuitBreakerState;
51
+ }
52
+ //# sourceMappingURL=circuit-breaker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"circuit-breaker.d.ts","sourceRoot":"","sources":["../../../../../src/cli/commands/watch/capabilities/circuit-breaker.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAKH,MAAM,MAAM,YAAY,GAAG,QAAQ,GAAG,MAAM,GAAG,WAAW,CAAC;AAE3D,MAAM,WAAW,wBAAwB;IACvC,KAAK,EAAE,YAAY,CAAC;IACpB,cAAc,EAAE,MAAM,CAAC;IACvB,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,eAAe,EAAE,MAAM,CAAC;IACxB,oBAAoB,EAAE,MAAM,CAAC;IAC7B,wBAAwB,EAAE,MAAM,CAAC;IACjC,cAAc,EAAE,MAAM,CAAC;IACvB,eAAe,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,oBAAoB;IACnC,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;IACzB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,wBAAwB,CAAC,EAAE,MAAM,CAAC;CACnC;AAeD,qBAAa,mBAAmB;IAC9B,OAAO,CAAC,SAAS,CAAS;gBAEd,QAAQ,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,oBAAoB;IAkB3D,IAAI,IAAI,wBAAwB;IAuBhC,IAAI,CAAC,KAAK,EAAE,wBAAwB,GAAG,IAAI;IAU3C,kDAAkD;IAClD,eAAe,IAAI,MAAM;IAmBzB,qCAAqC;IACrC,SAAS,IAAI,IAAI;IAcjB,yDAAyD;IACzD,WAAW,IAAI,IAAI;IAanB,4DAA4D;IAC5D,KAAK,IAAI,IAAI;IAIb,sCAAsC;IACtC,QAAQ,IAAI,wBAAwB;CAGrC"}
@@ -0,0 +1,152 @@
1
+ /**
2
+ * Enhanced Circuit Breaker capability — model-level fallback with cooldown.
3
+ *
4
+ * Ported from ralph-watch.ps1 `Get-CircuitBreakerState` / `Update-CircuitBreakerOn*`.
5
+ * Tracks model failures, auto-fallback through a configurable chain, and
6
+ * cooldown timer. State persisted to `.squad/ralph-circuit-breaker.json`.
7
+ *
8
+ * This is a **utility module** consumed by the main watch loop, not a
9
+ * phase-based capability (it gates every round, not a specific phase).
10
+ *
11
+ * Config (via squad.config.ts → watch.circuitBreaker):
12
+ * preferredModel – default model to use (default: "claude-sonnet-4")
13
+ * fallbackChain – ordered list of fallback models
14
+ * cooldownMinutes – minutes before half-open probe (default: 10)
15
+ * requiredSuccessesToClose – successes in half-open before closing (default: 2)
16
+ */
17
+ import path from 'node:path';
18
+ import fs from 'node:fs';
19
+ const DEFAULT_STATE = {
20
+ state: 'closed',
21
+ preferredModel: 'claude-sonnet-4',
22
+ currentModel: 'claude-sonnet-4',
23
+ fallbackChain: ['gpt-4.1', 'claude-haiku-4.5'],
24
+ lastRateLimitHit: null,
25
+ cooldownMinutes: 10,
26
+ consecutiveSuccesses: 0,
27
+ requiredSuccessesToClose: 2,
28
+ totalFallbacks: 0,
29
+ totalRecoveries: 0,
30
+ };
31
+ export class ModelCircuitBreaker {
32
+ statePath;
33
+ constructor(squadDir, config) {
34
+ this.statePath = path.join(squadDir, 'ralph-circuit-breaker.json');
35
+ // Ensure defaults incorporate any user config
36
+ if (config) {
37
+ const state = this.load();
38
+ let dirty = false;
39
+ if (config.preferredModel && state.preferredModel !== config.preferredModel) {
40
+ state.preferredModel = config.preferredModel;
41
+ if (state.state === 'closed')
42
+ state.currentModel = config.preferredModel;
43
+ dirty = true;
44
+ }
45
+ if (config.fallbackChain) {
46
+ state.fallbackChain = config.fallbackChain;
47
+ dirty = true;
48
+ }
49
+ if (config.cooldownMinutes) {
50
+ state.cooldownMinutes = config.cooldownMinutes;
51
+ dirty = true;
52
+ }
53
+ if (config.requiredSuccessesToClose) {
54
+ state.requiredSuccessesToClose = config.requiredSuccessesToClose;
55
+ dirty = true;
56
+ }
57
+ if (dirty)
58
+ this.save(state);
59
+ }
60
+ }
61
+ load() {
62
+ try {
63
+ if (!fs.existsSync(this.statePath))
64
+ return { ...DEFAULT_STATE };
65
+ const raw = fs.readFileSync(this.statePath, 'utf-8');
66
+ if (!raw)
67
+ return { ...DEFAULT_STATE };
68
+ const parsed = JSON.parse(raw);
69
+ // Handle legacy nested schema (model_fallback wrapper)
70
+ const legacy = parsed;
71
+ if (!parsed.preferredModel && legacy['model_fallback']) {
72
+ const mf = legacy['model_fallback'];
73
+ return {
74
+ ...DEFAULT_STATE,
75
+ preferredModel: mf['preferred'] ?? DEFAULT_STATE.preferredModel,
76
+ currentModel: mf['preferred'] ?? DEFAULT_STATE.currentModel,
77
+ fallbackChain: mf['fallback_chain'] ?? DEFAULT_STATE.fallbackChain,
78
+ };
79
+ }
80
+ return { ...DEFAULT_STATE, ...parsed };
81
+ }
82
+ catch {
83
+ return { ...DEFAULT_STATE };
84
+ }
85
+ }
86
+ save(state) {
87
+ try {
88
+ const dir = path.dirname(this.statePath);
89
+ if (!fs.existsSync(dir)) {
90
+ fs.mkdirSync(dir, { recursive: true });
91
+ }
92
+ fs.writeFileSync(this.statePath, JSON.stringify(state, null, 2), 'utf-8');
93
+ }
94
+ catch { /* best-effort */ }
95
+ }
96
+ /** Get the model to use for the current round. */
97
+ getCurrentModel() {
98
+ const state = this.load();
99
+ if (state.state === 'closed')
100
+ return state.preferredModel;
101
+ if (state.state === 'open') {
102
+ if (state.lastRateLimitHit) {
103
+ const elapsed = Date.now() - new Date(state.lastRateLimitHit).getTime();
104
+ if (elapsed >= state.cooldownMinutes * 60_000) {
105
+ state.state = 'half-open';
106
+ state.currentModel = state.preferredModel;
107
+ this.save(state);
108
+ return state.preferredModel;
109
+ }
110
+ }
111
+ return state.currentModel;
112
+ }
113
+ // half-open — probe preferred
114
+ return state.preferredModel;
115
+ }
116
+ /** Call after a successful round. */
117
+ onSuccess() {
118
+ const state = this.load();
119
+ if (state.state === 'half-open') {
120
+ state.consecutiveSuccesses++;
121
+ if (state.consecutiveSuccesses >= state.requiredSuccessesToClose) {
122
+ state.state = 'closed';
123
+ state.currentModel = state.preferredModel;
124
+ state.consecutiveSuccesses = 0;
125
+ state.totalRecoveries++;
126
+ }
127
+ this.save(state);
128
+ }
129
+ }
130
+ /** Call when a rate limit or model error is detected. */
131
+ onRateLimit() {
132
+ const state = this.load();
133
+ state.state = 'open';
134
+ state.lastRateLimitHit = new Date().toISOString();
135
+ state.consecutiveSuccesses = 0;
136
+ state.totalFallbacks++;
137
+ // Pick first fallback
138
+ if (state.fallbackChain.length > 0) {
139
+ state.currentModel = state.fallbackChain[0];
140
+ }
141
+ this.save(state);
142
+ }
143
+ /** Reset to defaults (used by post-failure remediation). */
144
+ reset() {
145
+ this.save({ ...DEFAULT_STATE });
146
+ }
147
+ /** Get full state for diagnostics. */
148
+ getState() {
149
+ return this.load();
150
+ }
151
+ }
152
+ //# sourceMappingURL=circuit-breaker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"circuit-breaker.js","sourceRoot":"","sources":["../../../../../src/cli/commands/watch/capabilities/circuit-breaker.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,MAAM,SAAS,CAAC;AAwBzB,MAAM,aAAa,GAA6B;IAC9C,KAAK,EAAE,QAAQ;IACf,cAAc,EAAE,iBAAiB;IACjC,YAAY,EAAE,iBAAiB;IAC/B,aAAa,EAAE,CAAC,SAAS,EAAE,kBAAkB,CAAC;IAC9C,gBAAgB,EAAE,IAAI;IACtB,eAAe,EAAE,EAAE;IACnB,oBAAoB,EAAE,CAAC;IACvB,wBAAwB,EAAE,CAAC;IAC3B,cAAc,EAAE,CAAC;IACjB,eAAe,EAAE,CAAC;CACnB,CAAC;AAEF,MAAM,OAAO,mBAAmB;IACtB,SAAS,CAAS;IAE1B,YAAY,QAAgB,EAAE,MAA6B;QACzD,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,4BAA4B,CAAC,CAAC;QACnE,8CAA8C;QAC9C,IAAI,MAAM,EAAE,CAAC;YACX,MAAM,KAAK,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;YAC1B,IAAI,KAAK,GAAG,KAAK,CAAC;YAClB,IAAI,MAAM,CAAC,cAAc,IAAI,KAAK,CAAC,cAAc,KAAK,MAAM,CAAC,cAAc,EAAE,CAAC;gBAC5E,KAAK,CAAC,cAAc,GAAG,MAAM,CAAC,cAAc,CAAC;gBAC7C,IAAI,KAAK,CAAC,KAAK,KAAK,QAAQ;oBAAE,KAAK,CAAC,YAAY,GAAG,MAAM,CAAC,cAAc,CAAC;gBACzE,KAAK,GAAG,IAAI,CAAC;YACf,CAAC;YACD,IAAI,MAAM,CAAC,aAAa,EAAE,CAAC;gBAAC,KAAK,CAAC,aAAa,GAAG,MAAM,CAAC,aAAa,CAAC;gBAAC,KAAK,GAAG,IAAI,CAAC;YAAC,CAAC;YACvF,IAAI,MAAM,CAAC,eAAe,EAAE,CAAC;gBAAC,KAAK,CAAC,eAAe,GAAG,MAAM,CAAC,eAAe,CAAC;gBAAC,KAAK,GAAG,IAAI,CAAC;YAAC,CAAC;YAC7F,IAAI,MAAM,CAAC,wBAAwB,EAAE,CAAC;gBAAC,KAAK,CAAC,wBAAwB,GAAG,MAAM,CAAC,wBAAwB,CAAC;gBAAC,KAAK,GAAG,IAAI,CAAC;YAAC,CAAC;YACxH,IAAI,KAAK;gBAAE,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC9B,CAAC;IACH,CAAC;IAED,IAAI;QACF,IAAI,CAAC;YACH,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,SAAS,CAAC;gBAAE,OAAO,EAAE,GAAG,aAAa,EAAE,CAAC;YAChE,MAAM,GAAG,GAAG,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;YACrD,IAAI,CAAC,GAAG;gBAAE,OAAO,EAAE,GAAG,aAAa,EAAE,CAAC;YACtC,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAsC,CAAC;YACpE,uDAAuD;YACvD,MAAM,MAAM,GAAG,MAAiC,CAAC;YACjD,IAAI,CAAC,MAAM,CAAC,cAAc,IAAI,MAAM,CAAC,gBAAgB,CAAC,EAAE,CAAC;gBACvD,MAAM,EAAE,GAAG,MAAM,CAAC,gBAAgB,CAA4B,CAAC;gBAC/D,OAAO;oBACL,GAAG,aAAa;oBAChB,cAAc,EAAG,EAAE,CAAC,WAAW,CAAY,IAAI,aAAa,CAAC,cAAc;oBAC3E,YAAY,EAAG,EAAE,CAAC,WAAW,CAAY,IAAI,aAAa,CAAC,YAAY;oBACvE,aAAa,EAAG,EAAE,CAAC,gBAAgB,CAAc,IAAI,aAAa,CAAC,aAAa;iBACjF,CAAC;YACJ,CAAC;YACD,OAAO,EAAE,GAAG,aAAa,EAAE,GAAG,MAAM,EAAE,CAAC;QACzC,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,EAAE,GAAG,aAAa,EAAE,CAAC;QAC9B,CAAC;IACH,CAAC;IAED,IAAI,CAAC,KAA+B;QAClC,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;YACzC,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;gBACxB,EAAE,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;YACzC,CAAC;YACD,EAAE,CAAC,aAAa,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;QAC5E,CAAC;QAAC,MAAM,CAAC,CAAC,iBAAiB,CAAC,CAAC;IAC/B,CAAC;IAED,kDAAkD;IAClD,eAAe;QACb,MAAM,KAAK,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;QAC1B,IAAI,KAAK,CAAC,KAAK,KAAK,QAAQ;YAAE,OAAO,KAAK,CAAC,cAAc,CAAC;QAC1D,IAAI,KAAK,CAAC,KAAK,KAAK,MAAM,EAAE,CAAC;YAC3B,IAAI,KAAK,CAAC,gBAAgB,EAAE,CAAC;gBAC3B,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,IAAI,CAAC,KAAK,CAAC,gBAAgB,CAAC,CAAC,OAAO,EAAE,CAAC;gBACxE,IAAI,OAAO,IAAI,KAAK,CAAC,eAAe,GAAG,MAAM,EAAE,CAAC;oBAC9C,KAAK,CAAC,KAAK,GAAG,WAAW,CAAC;oBAC1B,KAAK,CAAC,YAAY,GAAG,KAAK,CAAC,cAAc,CAAC;oBAC1C,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;oBACjB,OAAO,KAAK,CAAC,cAAc,CAAC;gBAC9B,CAAC;YACH,CAAC;YACD,OAAO,KAAK,CAAC,YAAY,CAAC;QAC5B,CAAC;QACD,8BAA8B;QAC9B,OAAO,KAAK,CAAC,cAAc,CAAC;IAC9B,CAAC;IAED,qCAAqC;IACrC,SAAS;QACP,MAAM,KAAK,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;QAC1B,IAAI,KAAK,CAAC,KAAK,KAAK,WAAW,EAAE,CAAC;YAChC,KAAK,CAAC,oBAAoB,EAAE,CAAC;YAC7B,IAAI,KAAK,CAAC,oBAAoB,IAAI,KAAK,CAAC,wBAAwB,EAAE,CAAC;gBACjE,KAAK,CAAC,KAAK,GAAG,QAAQ,CAAC;gBACvB,KAAK,CAAC,YAAY,GAAG,KAAK,CAAC,cAAc,CAAC;gBAC1C,KAAK,CAAC,oBAAoB,GAAG,CAAC,CAAC;gBAC/B,KAAK,CAAC,eAAe,EAAE,CAAC;YAC1B,CAAC;YACD,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACnB,CAAC;IACH,CAAC;IAED,yDAAyD;IACzD,WAAW;QACT,MAAM,KAAK,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;QAC1B,KAAK,CAAC,KAAK,GAAG,MAAM,CAAC;QACrB,KAAK,CAAC,gBAAgB,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;QAClD,KAAK,CAAC,oBAAoB,GAAG,CAAC,CAAC;QAC/B,KAAK,CAAC,cAAc,EAAE,CAAC;QACvB,sBAAsB;QACtB,IAAI,KAAK,CAAC,aAAa,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACnC,KAAK,CAAC,YAAY,GAAG,KAAK,CAAC,aAAa,CAAC,CAAC,CAAE,CAAC;QAC/C,CAAC;QACD,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACnB,CAAC;IAED,4DAA4D;IAC5D,KAAK;QACH,IAAI,CAAC,IAAI,CAAC,EAAE,GAAG,aAAa,EAAE,CAAC,CAAC;IAClC,CAAC;IAED,sCAAsC;IACtC,QAAQ;QACN,OAAO,IAAI,CAAC,IAAI,EAAE,CAAC;IACrB,CAAC;CACF"}
@@ -0,0 +1,14 @@
1
+ /**
2
+ * DecisionHygiene capability — merge decision inbox when >5 files.
3
+ */
4
+ import type { WatchCapability, WatchContext, PreflightResult, CapabilityResult } from '../types.js';
5
+ export declare class DecisionHygieneCapability implements WatchCapability {
6
+ readonly name = "decision-hygiene";
7
+ readonly description = "Auto-merge decision inbox when >5 files accumulate";
8
+ readonly configShape: "boolean";
9
+ readonly requires: string[];
10
+ readonly phase: "housekeeping";
11
+ preflight(context: WatchContext): Promise<PreflightResult>;
12
+ execute(context: WatchContext): Promise<CapabilityResult>;
13
+ }
14
+ //# sourceMappingURL=decision-hygiene.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"decision-hygiene.d.ts","sourceRoot":"","sources":["../../../../../src/cli/commands/watch/capabilities/decision-hygiene.ts"],"names":[],"mappings":"AAAA;;GAEG;AAKH,OAAO,KAAK,EAAE,eAAe,EAAE,YAAY,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AA2BpG,qBAAa,yBAA0B,YAAW,eAAe;IAC/D,QAAQ,CAAC,IAAI,sBAAsB;IACnC,QAAQ,CAAC,WAAW,wDAAwD;IAC5E,QAAQ,CAAC,WAAW,EAAG,SAAS,CAAU;IAC1C,QAAQ,CAAC,QAAQ,WAAU;IAC3B,QAAQ,CAAC,KAAK,EAAG,cAAc,CAAU;IAEnC,SAAS,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,eAAe,CAAC;IAQ1D,OAAO,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,gBAAgB,CAAC;CA8BhE"}
@@ -0,0 +1,72 @@
1
+ /**
2
+ * DecisionHygiene capability — merge decision inbox when >5 files.
3
+ */
4
+ import path from 'node:path';
5
+ import { execFile } from 'node:child_process';
6
+ import { FSStorageProvider } from '@bradygaster/squad-sdk';
7
+ const storage = new FSStorageProvider();
8
+ function buildAgentCommand(prompt, context) {
9
+ if (context.agentCmd) {
10
+ const parts = context.agentCmd.trim().split(/\s+/);
11
+ return { cmd: parts[0], args: [...parts.slice(1), '--message', prompt] };
12
+ }
13
+ const args = ['copilot', '--message', prompt];
14
+ if (context.copilotFlags)
15
+ args.push(...context.copilotFlags.trim().split(/\s+/));
16
+ return { cmd: 'gh', args };
17
+ }
18
+ function spawnWithTimeout(cmd, args, cwd, timeoutMs) {
19
+ return new Promise((resolve, reject) => {
20
+ execFile(cmd, args, { cwd, timeout: timeoutMs, maxBuffer: 50 * 1024 * 1024 }, (err) => {
21
+ if (err) {
22
+ const execErr = err;
23
+ reject(new Error(execErr.killed ? `Timed out after ${Math.round(timeoutMs / 1000)}s` : execErr.message));
24
+ }
25
+ else {
26
+ resolve();
27
+ }
28
+ });
29
+ });
30
+ }
31
+ export class DecisionHygieneCapability {
32
+ name = 'decision-hygiene';
33
+ description = 'Auto-merge decision inbox when >5 files accumulate';
34
+ configShape = 'boolean';
35
+ requires = ['gh'];
36
+ phase = 'housekeeping';
37
+ async preflight(context) {
38
+ const inboxDir = path.join(context.teamRoot, '.squad', 'decisions', 'inbox');
39
+ if (!storage.existsSync(inboxDir)) {
40
+ return { ok: false, reason: 'no decision inbox directory found' };
41
+ }
42
+ return { ok: true };
43
+ }
44
+ async execute(context) {
45
+ try {
46
+ const inboxDir = path.join(context.teamRoot, '.squad', 'decisions', 'inbox');
47
+ if (!storage.existsSync(inboxDir)) {
48
+ return { success: true, summary: 'no decision inbox' };
49
+ }
50
+ let fileCount = 0;
51
+ try {
52
+ const files = storage.listSync?.(inboxDir) ?? [];
53
+ fileCount = Array.isArray(files) ? files.filter((f) => f.endsWith('.md')).length : 0;
54
+ }
55
+ catch {
56
+ return { success: true, summary: 'decision inbox empty' };
57
+ }
58
+ if (fileCount <= 5) {
59
+ return { success: true, summary: `decision inbox: ${fileCount} files (threshold: >5)` };
60
+ }
61
+ const prompt = 'Merge the decision inbox files in .squad/decisions/inbox/ into .squad/decisions.md. ' +
62
+ 'Append each decision as a new section. After merging, delete the inbox files.';
63
+ const { cmd, args } = buildAgentCommand(prompt, context);
64
+ await spawnWithTimeout(cmd, args, context.teamRoot, 60_000);
65
+ return { success: true, summary: `decision inbox merged (${fileCount} files)` };
66
+ }
67
+ catch (e) {
68
+ return { success: false, summary: `decision hygiene: ${e.message}` };
69
+ }
70
+ }
71
+ }
72
+ //# sourceMappingURL=decision-hygiene.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"decision-hygiene.js","sourceRoot":"","sources":["../../../../../src/cli/commands/watch/capabilities/decision-hygiene.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Execute capability — spawns Copilot sessions for eligible issues.
3
+ */
4
+ import type { WatchCapability, WatchContext, PreflightResult, CapabilityResult } from '../types.js';
5
+ import type { MachineCapabilities } from '@bradygaster/squad-sdk/ralph/capabilities';
6
+ /** Normalized work item for execution. */
7
+ export interface ExecutableWorkItem {
8
+ number: number;
9
+ title: string;
10
+ body?: string;
11
+ labels: Array<{
12
+ name: string;
13
+ }>;
14
+ assignees: Array<{
15
+ login: string;
16
+ }>;
17
+ }
18
+ /** Find issues eligible for autonomous execution. */
19
+ export declare function findExecutableIssues(roster: Array<{
20
+ name: string;
21
+ label: string;
22
+ expertise: string[];
23
+ }>, capabilities: MachineCapabilities | null, issues: ExecutableWorkItem[]): ExecutableWorkItem[];
24
+ export declare class ExecuteCapability implements WatchCapability {
25
+ readonly name = "execute";
26
+ readonly description = "Spawn Copilot sessions to work on eligible issues";
27
+ readonly configShape: "boolean";
28
+ readonly requires: string[];
29
+ readonly phase: "post-execute";
30
+ preflight(_context: WatchContext): Promise<PreflightResult>;
31
+ execute(context: WatchContext): Promise<CapabilityResult>;
32
+ }
33
+ //# sourceMappingURL=execute.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"execute.d.ts","sourceRoot":"","sources":["../../../../../src/cli/commands/watch/capabilities/execute.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,OAAO,KAAK,EAAE,eAAe,EAAE,YAAY,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AACpG,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,2CAA2C,CAAC;AAGrF,0CAA0C;AAC1C,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAChC,SAAS,EAAE,KAAK,CAAC;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CACrC;AAiCD,qDAAqD;AACrD,wBAAgB,oBAAoB,CAClC,MAAM,EAAE,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,EAAE,CAAA;CAAE,CAAC,EACnE,YAAY,EAAE,mBAAmB,GAAG,IAAI,EACxC,MAAM,EAAE,kBAAkB,EAAE,GAC3B,kBAAkB,EAAE,CAStB;AAsCD,qBAAa,iBAAkB,YAAW,eAAe;IACvD,QAAQ,CAAC,IAAI,aAAa;IAC1B,QAAQ,CAAC,WAAW,uDAAuD;IAC3E,QAAQ,CAAC,WAAW,EAAG,SAAS,CAAU;IAC1C,QAAQ,CAAC,QAAQ,WAAU;IAC3B,QAAQ,CAAC,KAAK,EAAG,cAAc,CAAU;IAEnC,SAAS,CAAC,QAAQ,EAAE,YAAY,GAAG,OAAO,CAAC,eAAe,CAAC;IAQ3D,OAAO,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,gBAAgB,CAAC;CA8EhE"}