@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
@@ -1,169 +1,169 @@
1
- name: Sync Squad Labels
2
-
3
- on:
4
- push:
5
- paths:
6
- - '.squad/team.md'
7
- - '.ai-team/team.md'
8
- workflow_dispatch:
9
-
10
- permissions:
11
- issues: write
12
- contents: read
13
-
14
- jobs:
15
- sync-labels:
16
- runs-on: ubuntu-latest
17
- steps:
18
- - uses: actions/checkout@v4
19
-
20
- - name: Parse roster and sync labels
21
- uses: actions/github-script@v7
22
- with:
23
- script: |
24
- const fs = require('fs');
25
- let teamFile = '.squad/team.md';
26
- if (!fs.existsSync(teamFile)) {
27
- teamFile = '.ai-team/team.md';
28
- }
29
-
30
- if (!fs.existsSync(teamFile)) {
31
- core.info('No .squad/team.md or .ai-team/team.md found — skipping label sync');
32
- return;
33
- }
34
-
35
- const content = fs.readFileSync(teamFile, 'utf8');
36
- const lines = content.split('\n');
37
-
38
- // Parse the Members table for agent names
39
- const members = [];
40
- let inMembersTable = false;
41
- for (const line of lines) {
42
- if (line.match(/^##\s+(Members|Team Roster)/i)) {
43
- inMembersTable = true;
44
- continue;
45
- }
46
- if (inMembersTable && line.startsWith('## ')) {
47
- break;
48
- }
49
- if (inMembersTable && line.startsWith('|') && !line.includes('---') && !line.includes('Name')) {
50
- const cells = line.split('|').map(c => c.trim()).filter(Boolean);
51
- if (cells.length >= 2 && cells[0] !== 'Scribe') {
52
- members.push({
53
- name: cells[0],
54
- role: cells[1]
55
- });
56
- }
57
- }
58
- }
59
-
60
- core.info(`Found ${members.length} squad members: ${members.map(m => m.name).join(', ')}`);
61
-
62
- // Check if @copilot is on the team
63
- const hasCopilot = content.includes('🤖 Coding Agent');
64
-
65
- // Define label color palette for squad labels
66
- const SQUAD_COLOR = '9B8FCC';
67
- const MEMBER_COLOR = '9B8FCC';
68
- const COPILOT_COLOR = '10b981';
69
-
70
- // Define go: and release: labels (static)
71
- const GO_LABELS = [
72
- { name: 'go:yes', color: '0E8A16', description: 'Ready to implement' },
73
- { name: 'go:no', color: 'B60205', description: 'Not pursuing' },
74
- { name: 'go:needs-research', color: 'FBCA04', description: 'Needs investigation' }
75
- ];
76
-
77
- const RELEASE_LABELS = [
78
- { name: 'release:v0.4.0', color: '6B8EB5', description: 'Targeted for v0.4.0' },
79
- { name: 'release:v0.5.0', color: '6B8EB5', description: 'Targeted for v0.5.0' },
80
- { name: 'release:v0.6.0', color: '8B7DB5', description: 'Targeted for v0.6.0' },
81
- { name: 'release:v1.0.0', color: '8B7DB5', description: 'Targeted for v1.0.0' },
82
- { name: 'release:backlog', color: 'D4E5F7', description: 'Not yet targeted' }
83
- ];
84
-
85
- const TYPE_LABELS = [
86
- { name: 'type:feature', color: 'DDD1F2', description: 'New capability' },
87
- { name: 'type:bug', color: 'FF0422', description: 'Something broken' },
88
- { name: 'type:spike', color: 'F2DDD4', description: 'Research/investigation — produces a plan, not code' },
89
- { name: 'type:docs', color: 'D4E5F7', description: 'Documentation work' },
90
- { name: 'type:chore', color: 'D4E5F7', description: 'Maintenance, refactoring, cleanup' },
91
- { name: 'type:epic', color: 'CC4455', description: 'Parent issue that decomposes into sub-issues' }
92
- ];
93
-
94
- // High-signal labels — these MUST visually dominate all others
95
- const SIGNAL_LABELS = [
96
- { name: 'bug', color: 'FF0422', description: 'Something isn\'t working' },
97
- { name: 'feedback', color: '00E5FF', description: 'User feedback — high signal, needs attention' }
98
- ];
99
-
100
- const PRIORITY_LABELS = [
101
- { name: 'priority:p0', color: 'B60205', description: 'Blocking release' },
102
- { name: 'priority:p1', color: 'D93F0B', description: 'This sprint' },
103
- { name: 'priority:p2', color: 'FBCA04', description: 'Next sprint' }
104
- ];
105
-
106
- // Ensure the base "squad" triage label exists
107
- const labels = [
108
- { name: 'squad', color: SQUAD_COLOR, description: 'Squad triage inbox — Lead will assign to a member' }
109
- ];
110
-
111
- for (const member of members) {
112
- labels.push({
113
- name: `squad:${member.name.toLowerCase()}`,
114
- color: MEMBER_COLOR,
115
- description: `Assigned to ${member.name} (${member.role})`
116
- });
117
- }
118
-
119
- // Add @copilot label if coding agent is on the team
120
- if (hasCopilot) {
121
- labels.push({
122
- name: 'squad:copilot',
123
- color: COPILOT_COLOR,
124
- description: 'Assigned to @copilot (Coding Agent) for autonomous work'
125
- });
126
- }
127
-
128
- // Add go:, release:, type:, priority:, and high-signal labels
129
- labels.push(...GO_LABELS);
130
- labels.push(...RELEASE_LABELS);
131
- labels.push(...TYPE_LABELS);
132
- labels.push(...PRIORITY_LABELS);
133
- labels.push(...SIGNAL_LABELS);
134
-
135
- // Sync labels (create or update)
136
- for (const label of labels) {
137
- try {
138
- await github.rest.issues.getLabel({
139
- owner: context.repo.owner,
140
- repo: context.repo.repo,
141
- name: label.name
142
- });
143
- // Label exists — update it
144
- await github.rest.issues.updateLabel({
145
- owner: context.repo.owner,
146
- repo: context.repo.repo,
147
- name: label.name,
148
- color: label.color,
149
- description: label.description
150
- });
151
- core.info(`Updated label: ${label.name}`);
152
- } catch (err) {
153
- if (err.status === 404) {
154
- // Label doesn't exist — create it
155
- await github.rest.issues.createLabel({
156
- owner: context.repo.owner,
157
- repo: context.repo.repo,
158
- name: label.name,
159
- color: label.color,
160
- description: label.description
161
- });
162
- core.info(`Created label: ${label.name}`);
163
- } else {
164
- throw err;
165
- }
166
- }
167
- }
168
-
169
- core.info(`Label sync complete: ${labels.length} labels synced`);
1
+ name: Sync Squad Labels
2
+
3
+ on:
4
+ push:
5
+ paths:
6
+ - '.squad/team.md'
7
+ - '.ai-team/team.md'
8
+ workflow_dispatch:
9
+
10
+ permissions:
11
+ issues: write
12
+ contents: read
13
+
14
+ jobs:
15
+ sync-labels:
16
+ runs-on: ubuntu-latest
17
+ steps:
18
+ - uses: actions/checkout@v4
19
+
20
+ - name: Parse roster and sync labels
21
+ uses: actions/github-script@v7
22
+ with:
23
+ script: |
24
+ const fs = require('fs');
25
+ let teamFile = '.squad/team.md';
26
+ if (!fs.existsSync(teamFile)) {
27
+ teamFile = '.ai-team/team.md';
28
+ }
29
+
30
+ if (!fs.existsSync(teamFile)) {
31
+ core.info('No .squad/team.md or .ai-team/team.md found — skipping label sync');
32
+ return;
33
+ }
34
+
35
+ const content = fs.readFileSync(teamFile, 'utf8');
36
+ const lines = content.split('\n');
37
+
38
+ // Parse the Members table for agent names
39
+ const members = [];
40
+ let inMembersTable = false;
41
+ for (const line of lines) {
42
+ if (line.match(/^##\s+(Members|Team Roster)/i)) {
43
+ inMembersTable = true;
44
+ continue;
45
+ }
46
+ if (inMembersTable && line.startsWith('## ')) {
47
+ break;
48
+ }
49
+ if (inMembersTable && line.startsWith('|') && !line.includes('---') && !line.includes('Name')) {
50
+ const cells = line.split('|').map(c => c.trim()).filter(Boolean);
51
+ if (cells.length >= 2 && cells[0] !== 'Scribe') {
52
+ members.push({
53
+ name: cells[0],
54
+ role: cells[1]
55
+ });
56
+ }
57
+ }
58
+ }
59
+
60
+ core.info(`Found ${members.length} squad members: ${members.map(m => m.name).join(', ')}`);
61
+
62
+ // Check if @copilot is on the team
63
+ const hasCopilot = content.includes('🤖 Coding Agent');
64
+
65
+ // Define label color palette for squad labels
66
+ const SQUAD_COLOR = '9B8FCC';
67
+ const MEMBER_COLOR = '9B8FCC';
68
+ const COPILOT_COLOR = '10b981';
69
+
70
+ // Define go: and release: labels (static)
71
+ const GO_LABELS = [
72
+ { name: 'go:yes', color: '0E8A16', description: 'Ready to implement' },
73
+ { name: 'go:no', color: 'B60205', description: 'Not pursuing' },
74
+ { name: 'go:needs-research', color: 'FBCA04', description: 'Needs investigation' }
75
+ ];
76
+
77
+ const RELEASE_LABELS = [
78
+ { name: 'release:v0.4.0', color: '6B8EB5', description: 'Targeted for v0.4.0' },
79
+ { name: 'release:v0.5.0', color: '6B8EB5', description: 'Targeted for v0.5.0' },
80
+ { name: 'release:v0.6.0', color: '8B7DB5', description: 'Targeted for v0.6.0' },
81
+ { name: 'release:v1.0.0', color: '8B7DB5', description: 'Targeted for v1.0.0' },
82
+ { name: 'release:backlog', color: 'D4E5F7', description: 'Not yet targeted' }
83
+ ];
84
+
85
+ const TYPE_LABELS = [
86
+ { name: 'type:feature', color: 'DDD1F2', description: 'New capability' },
87
+ { name: 'type:bug', color: 'FF0422', description: 'Something broken' },
88
+ { name: 'type:spike', color: 'F2DDD4', description: 'Research/investigation — produces a plan, not code' },
89
+ { name: 'type:docs', color: 'D4E5F7', description: 'Documentation work' },
90
+ { name: 'type:chore', color: 'D4E5F7', description: 'Maintenance, refactoring, cleanup' },
91
+ { name: 'type:epic', color: 'CC4455', description: 'Parent issue that decomposes into sub-issues' }
92
+ ];
93
+
94
+ // High-signal labels — these MUST visually dominate all others
95
+ const SIGNAL_LABELS = [
96
+ { name: 'bug', color: 'FF0422', description: 'Something isn\'t working' },
97
+ { name: 'feedback', color: '00E5FF', description: 'User feedback — high signal, needs attention' }
98
+ ];
99
+
100
+ const PRIORITY_LABELS = [
101
+ { name: 'priority:p0', color: 'B60205', description: 'Blocking release' },
102
+ { name: 'priority:p1', color: 'D93F0B', description: 'This sprint' },
103
+ { name: 'priority:p2', color: 'FBCA04', description: 'Next sprint' }
104
+ ];
105
+
106
+ // Ensure the base "squad" triage label exists
107
+ const labels = [
108
+ { name: 'squad', color: SQUAD_COLOR, description: 'Squad triage inbox — Lead will assign to a member' }
109
+ ];
110
+
111
+ for (const member of members) {
112
+ labels.push({
113
+ name: `squad:${member.name.toLowerCase()}`,
114
+ color: MEMBER_COLOR,
115
+ description: `Assigned to ${member.name} (${member.role})`
116
+ });
117
+ }
118
+
119
+ // Add @copilot label if coding agent is on the team
120
+ if (hasCopilot) {
121
+ labels.push({
122
+ name: 'squad:copilot',
123
+ color: COPILOT_COLOR,
124
+ description: 'Assigned to @copilot (Coding Agent) for autonomous work'
125
+ });
126
+ }
127
+
128
+ // Add go:, release:, type:, priority:, and high-signal labels
129
+ labels.push(...GO_LABELS);
130
+ labels.push(...RELEASE_LABELS);
131
+ labels.push(...TYPE_LABELS);
132
+ labels.push(...PRIORITY_LABELS);
133
+ labels.push(...SIGNAL_LABELS);
134
+
135
+ // Sync labels (create or update)
136
+ for (const label of labels) {
137
+ try {
138
+ await github.rest.issues.getLabel({
139
+ owner: context.repo.owner,
140
+ repo: context.repo.repo,
141
+ name: label.name
142
+ });
143
+ // Label exists — update it
144
+ await github.rest.issues.updateLabel({
145
+ owner: context.repo.owner,
146
+ repo: context.repo.repo,
147
+ name: label.name,
148
+ color: label.color,
149
+ description: label.description
150
+ });
151
+ core.info(`Updated label: ${label.name}`);
152
+ } catch (err) {
153
+ if (err.status === 404) {
154
+ // Label doesn't exist — create it
155
+ await github.rest.issues.createLabel({
156
+ owner: context.repo.owner,
157
+ repo: context.repo.repo,
158
+ name: label.name,
159
+ color: label.color,
160
+ description: label.description
161
+ });
162
+ core.info(`Created label: ${label.name}`);
163
+ } else {
164
+ throw err;
165
+ }
166
+ }
167
+ }
168
+
169
+ core.info(`Label sync complete: ${labels.length} labels synced`);
@@ -1,18 +0,0 @@
1
- /**
2
- * Watch command — Ralph's standalone polling process
3
- */
4
- export interface BoardState {
5
- untriaged: number;
6
- assigned: number;
7
- drafts: number;
8
- needsReview: number;
9
- changesRequested: number;
10
- ciFailures: number;
11
- readyToMerge: number;
12
- }
13
- export declare function reportBoard(state: BoardState, round: number): void;
14
- /**
15
- * Run watch command — Ralph's local polling process
16
- */
17
- export declare function runWatch(dest: string, intervalMinutes: number): Promise<void>;
18
- //# sourceMappingURL=watch.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"watch.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/watch.ts"],"names":[],"mappings":"AAAA;;GAEG;AAmBH,MAAM,WAAW,UAAU;IACzB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,gBAAgB,EAAE,MAAM,CAAC;IACzB,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAkBlE;AAoMD;;GAEG;AACH,wBAAsB,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CA4HnF"}
@@ -1,306 +0,0 @@
1
- /**
2
- * Watch command — Ralph's standalone polling process
3
- */
4
- import fs from 'node:fs';
5
- import path from 'node:path';
6
- import { detectSquadDir } from '../core/detect-squad-dir.js';
7
- import { fatal } from '../core/errors.js';
8
- import { GREEN, RED, DIM, BOLD, RESET, YELLOW } from '../core/output.js';
9
- import { parseRoutingRules, parseModuleOwnership, parseRoster, triageIssue, } from '@bradygaster/squad-sdk/ralph/triage';
10
- import { RalphMonitor } from '@bradygaster/squad-sdk/ralph';
11
- import { EventBus } from '@bradygaster/squad-sdk/runtime/event-bus';
12
- import { ghAvailable, ghAuthenticated, ghIssueList, ghIssueEdit, ghPrList } from '../core/gh-cli.js';
13
- export function reportBoard(state, round) {
14
- const total = Object.values(state).reduce((a, b) => a + b, 0);
15
- if (total === 0) {
16
- console.log(`${DIM}📋 Board is clear — Ralph is idling${RESET}`);
17
- return;
18
- }
19
- console.log(`\n${BOLD}🔄 Ralph — Round ${round}${RESET}`);
20
- console.log('━'.repeat(30));
21
- if (state.untriaged > 0)
22
- console.log(` 🔴 Untriaged: ${state.untriaged}`);
23
- if (state.assigned > 0)
24
- console.log(` 🟡 Assigned: ${state.assigned}`);
25
- if (state.drafts > 0)
26
- console.log(` 🟡 Draft PRs: ${state.drafts}`);
27
- if (state.changesRequested > 0)
28
- console.log(` ⚠️ Changes requested: ${state.changesRequested}`);
29
- if (state.ciFailures > 0)
30
- console.log(` ❌ CI failures: ${state.ciFailures}`);
31
- if (state.needsReview > 0)
32
- console.log(` 🔵 Needs review: ${state.needsReview}`);
33
- if (state.readyToMerge > 0)
34
- console.log(` 🟢 Ready to merge: ${state.readyToMerge}`);
35
- console.log();
36
- }
37
- function emptyBoardState() {
38
- return {
39
- untriaged: 0,
40
- assigned: 0,
41
- drafts: 0,
42
- needsReview: 0,
43
- changesRequested: 0,
44
- ciFailures: 0,
45
- readyToMerge: 0,
46
- };
47
- }
48
- async function checkPRs(roster) {
49
- const timestamp = new Date().toLocaleTimeString();
50
- const prs = await ghPrList({ state: 'open', limit: 20 });
51
- // Filter to squad-related PRs (has squad label or branch starts with squad/)
52
- const squadPRs = prs.filter(pr => pr.labels.some(l => l.name.startsWith('squad')) ||
53
- pr.headRefName.startsWith('squad/'));
54
- if (squadPRs.length === 0) {
55
- return {
56
- drafts: 0,
57
- needsReview: 0,
58
- changesRequested: 0,
59
- ciFailures: 0,
60
- readyToMerge: 0,
61
- totalOpen: 0,
62
- };
63
- }
64
- const drafts = squadPRs.filter(pr => pr.isDraft);
65
- const changesRequested = squadPRs.filter(pr => pr.reviewDecision === 'CHANGES_REQUESTED');
66
- const approved = squadPRs.filter(pr => pr.reviewDecision === 'APPROVED' && !pr.isDraft);
67
- const ciFailures = squadPRs.filter(pr => pr.statusCheckRollup?.some(check => check.state === 'FAILURE' || check.state === 'ERROR'));
68
- const readyToMerge = approved.filter(pr => !pr.statusCheckRollup?.some(c => c.state === 'FAILURE' || c.state === 'ERROR' || c.state === 'PENDING'));
69
- const changesRequestedSet = new Set(changesRequested.map(pr => pr.number));
70
- const ciFailureSet = new Set(ciFailures.map(pr => pr.number));
71
- const readyToMergeSet = new Set(readyToMerge.map(pr => pr.number));
72
- const needsReview = squadPRs.filter(pr => !pr.isDraft &&
73
- !changesRequestedSet.has(pr.number) &&
74
- !ciFailureSet.has(pr.number) &&
75
- !readyToMergeSet.has(pr.number));
76
- const memberNames = new Set(roster.map(m => m.name.toLowerCase()));
77
- // Report each category
78
- if (drafts.length > 0) {
79
- console.log(`${DIM}[${timestamp}]${RESET} 🟡 ${drafts.length} draft PR(s) in progress`);
80
- for (const pr of drafts) {
81
- console.log(` ${DIM}PR #${pr.number}: ${pr.title} (${pr.author.login})${RESET}`);
82
- }
83
- }
84
- if (changesRequested.length > 0) {
85
- console.log(`${YELLOW}[${timestamp}]${RESET} ⚠️ ${changesRequested.length} PR(s) need revision`);
86
- for (const pr of changesRequested) {
87
- const owner = memberNames.has(pr.author.login.toLowerCase()) ? ` — ${pr.author.login}` : '';
88
- console.log(` PR #${pr.number}: ${pr.title} — changes requested${owner}`);
89
- }
90
- }
91
- if (ciFailures.length > 0) {
92
- console.log(`${RED}[${timestamp}]${RESET} ❌ ${ciFailures.length} PR(s) with CI failures`);
93
- for (const pr of ciFailures) {
94
- const failedChecks = pr.statusCheckRollup?.filter(c => c.state === 'FAILURE' || c.state === 'ERROR') || [];
95
- const owner = memberNames.has(pr.author.login.toLowerCase()) ? ` — ${pr.author.login}` : '';
96
- console.log(` PR #${pr.number}: ${pr.title}${owner} — ${failedChecks.map(c => c.name).join(', ')}`);
97
- }
98
- }
99
- if (approved.length > 0) {
100
- if (readyToMerge.length > 0) {
101
- console.log(`${GREEN}[${timestamp}]${RESET} 🟢 ${readyToMerge.length} PR(s) ready to merge`);
102
- for (const pr of readyToMerge) {
103
- console.log(` PR #${pr.number}: ${pr.title} — approved, CI green`);
104
- }
105
- }
106
- }
107
- return {
108
- drafts: drafts.length,
109
- needsReview: needsReview.length,
110
- changesRequested: changesRequestedSet.size,
111
- ciFailures: ciFailureSet.size,
112
- readyToMerge: readyToMergeSet.size,
113
- totalOpen: squadPRs.length,
114
- };
115
- }
116
- /**
117
- * Run a single check cycle
118
- */
119
- async function runCheck(rules, modules, roster, hasCopilot, autoAssign, capabilities = null) {
120
- const timestamp = new Date().toLocaleTimeString();
121
- try {
122
- // Fetch open issues with squad label
123
- const issues = await ghIssueList({ label: 'squad', state: 'open', limit: 20 });
124
- // Filter by machine capabilities (#514)
125
- const { filterByCapabilities } = await import('@bradygaster/squad-sdk/ralph/capabilities');
126
- const { handled: capableIssues, skipped: incapableIssues } = filterByCapabilities(issues, capabilities);
127
- for (const { issue, missing } of incapableIssues) {
128
- console.log(`${DIM}[${timestamp}] ⏭️ Skipping #${issue.number} "${issue.title}" — missing: ${missing.join(', ')}${RESET}`);
129
- }
130
- // Find untriaged issues (no squad:{member} label)
131
- const memberLabels = roster.map(m => m.label);
132
- const untriaged = capableIssues.filter(issue => {
133
- const issueLabels = issue.labels.map(l => l.name);
134
- return !memberLabels.some(ml => issueLabels.includes(ml));
135
- });
136
- const assignedIssues = capableIssues.filter(issue => {
137
- const issueLabels = issue.labels.map(l => l.name);
138
- return memberLabels.some(ml => issueLabels.includes(ml));
139
- });
140
- // Find unassigned squad:copilot issues
141
- let unassignedCopilot = [];
142
- if (hasCopilot && autoAssign) {
143
- try {
144
- const copilotIssues = await ghIssueList({ label: 'squad:copilot', state: 'open', limit: 10 });
145
- unassignedCopilot = copilotIssues.filter(i => !i.assignees || i.assignees.length === 0);
146
- }
147
- catch {
148
- // Label may not exist yet
149
- }
150
- }
151
- // Triage untriaged issues
152
- for (const issue of untriaged) {
153
- const triageInput = {
154
- number: issue.number,
155
- title: issue.title,
156
- body: issue.body,
157
- labels: issue.labels.map((l) => l.name),
158
- };
159
- const triage = triageIssue(triageInput, rules, modules, roster);
160
- if (triage) {
161
- try {
162
- await ghIssueEdit(issue.number, { addLabel: triage.agent.label });
163
- console.log(`${GREEN}✓${RESET} [${timestamp}] Triaged #${issue.number} "${issue.title}" → ${triage.agent.name} (${triage.reason})`);
164
- }
165
- catch (e) {
166
- const err = e;
167
- console.error(`${RED}✗${RESET} [${timestamp}] Failed to label #${issue.number}: ${err.message}`);
168
- }
169
- }
170
- }
171
- // Assign @copilot to unassigned copilot issues
172
- for (const issue of unassignedCopilot) {
173
- try {
174
- await ghIssueEdit(issue.number, { addAssignee: 'copilot-swe-agent' });
175
- console.log(`${GREEN}✓${RESET} [${timestamp}] Assigned @copilot to #${issue.number} "${issue.title}"`);
176
- }
177
- catch (e) {
178
- const err = e;
179
- console.error(`${RED}✗${RESET} [${timestamp}] Failed to assign @copilot to #${issue.number}: ${err.message}`);
180
- }
181
- }
182
- const prState = await checkPRs(roster);
183
- return {
184
- untriaged: untriaged.length,
185
- assigned: assignedIssues.length,
186
- ...prState,
187
- };
188
- }
189
- catch (e) {
190
- const err = e;
191
- console.error(`${RED}✗${RESET} [${timestamp}] Check failed: ${err.message}`);
192
- return emptyBoardState();
193
- }
194
- }
195
- /**
196
- * Run watch command — Ralph's local polling process
197
- */
198
- export async function runWatch(dest, intervalMinutes) {
199
- // Validate interval
200
- if (isNaN(intervalMinutes) || intervalMinutes < 1) {
201
- fatal('--interval must be a positive number of minutes');
202
- }
203
- // Detect squad directory
204
- const squadDirInfo = detectSquadDir(dest);
205
- const teamMd = path.join(squadDirInfo.path, 'team.md');
206
- const routingMdPath = path.join(squadDirInfo.path, 'routing.md');
207
- if (!fs.existsSync(teamMd)) {
208
- fatal('No squad found — run init first.');
209
- }
210
- // Verify gh CLI
211
- if (!(await ghAvailable())) {
212
- fatal('gh CLI not found — install from https://cli.github.com');
213
- }
214
- if (!(await ghAuthenticated())) {
215
- console.error(`${YELLOW}⚠️${RESET} gh CLI not authenticated`);
216
- console.error(` Run: ${BOLD}gh auth login${RESET}\n`);
217
- fatal('gh authentication required');
218
- }
219
- // Parse team.md
220
- const content = fs.readFileSync(teamMd, 'utf8');
221
- const roster = parseRoster(content);
222
- const routingContent = fs.existsSync(routingMdPath) ? fs.readFileSync(routingMdPath, 'utf8') : '';
223
- const rules = parseRoutingRules(routingContent);
224
- const modules = parseModuleOwnership(routingContent);
225
- // Load machine capabilities for needs:* label filtering (#514)
226
- const { loadCapabilities } = await import('@bradygaster/squad-sdk/ralph/capabilities');
227
- const capabilities = await loadCapabilities(path.dirname(squadDirInfo.path));
228
- if (capabilities) {
229
- console.log(`${DIM}📦 Machine: ${capabilities.machine} — ${capabilities.capabilities.length} capabilities loaded${RESET}`);
230
- }
231
- if (roster.length === 0) {
232
- fatal('No squad members found in team.md');
233
- }
234
- const hasCopilot = content.includes('🤖 Coding Agent') || content.includes('@copilot');
235
- const autoAssign = content.includes('<!-- copilot-auto-assign: true -->');
236
- const monitorSessionId = 'ralph-watch';
237
- const eventBus = new EventBus();
238
- const monitor = new RalphMonitor({
239
- teamRoot: path.dirname(squadDirInfo.path),
240
- healthCheckInterval: intervalMinutes * 60 * 1000,
241
- staleSessionThreshold: intervalMinutes * 60 * 1000 * 3,
242
- statePath: path.join(squadDirInfo.path, '.ralph-state.json'),
243
- });
244
- await monitor.start(eventBus);
245
- await eventBus.emit({
246
- type: 'session:created',
247
- sessionId: monitorSessionId,
248
- agentName: 'Ralph',
249
- payload: { intervalMinutes },
250
- timestamp: new Date(),
251
- });
252
- // Print startup banner
253
- console.log(`\n${BOLD}🔄 Ralph — Watch Mode${RESET}`);
254
- console.log(`${DIM}Polling every ${intervalMinutes} minute(s) for squad work. Ctrl+C to stop.${RESET}\n`);
255
- let round = 0;
256
- // Run immediately, then on interval
257
- round++;
258
- const state = await runCheck(rules, modules, roster, hasCopilot, autoAssign, capabilities);
259
- await eventBus.emit({
260
- type: 'agent:milestone',
261
- sessionId: monitorSessionId,
262
- agentName: 'Ralph',
263
- payload: { milestone: `Completed watch round ${round}`, task: 'watch cycle' },
264
- timestamp: new Date(),
265
- });
266
- await monitor.healthCheck();
267
- reportBoard(state, round);
268
- return new Promise((resolve) => {
269
- const intervalId = setInterval(async () => {
270
- round++;
271
- const roundState = await runCheck(rules, modules, roster, hasCopilot, autoAssign, capabilities);
272
- await eventBus.emit({
273
- type: 'agent:milestone',
274
- sessionId: monitorSessionId,
275
- agentName: 'Ralph',
276
- payload: { milestone: `Completed watch round ${round}`, task: 'watch cycle' },
277
- timestamp: new Date(),
278
- });
279
- await monitor.healthCheck();
280
- reportBoard(roundState, round);
281
- }, intervalMinutes * 60 * 1000);
282
- // Graceful shutdown
283
- let isShuttingDown = false;
284
- const shutdown = async () => {
285
- if (isShuttingDown)
286
- return;
287
- isShuttingDown = true;
288
- clearInterval(intervalId);
289
- process.off('SIGINT', shutdown);
290
- process.off('SIGTERM', shutdown);
291
- await eventBus.emit({
292
- type: 'session:destroyed',
293
- sessionId: monitorSessionId,
294
- agentName: 'Ralph',
295
- payload: null,
296
- timestamp: new Date(),
297
- });
298
- await monitor.stop();
299
- console.log(`\n${DIM}🔄 Ralph — Watch stopped${RESET}`);
300
- resolve();
301
- };
302
- process.on('SIGINT', shutdown);
303
- process.on('SIGTERM', shutdown);
304
- });
305
- }
306
- //# sourceMappingURL=watch.js.map