squads-cli 0.2.1 → 0.2.2

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 (129) hide show
  1. package/dist/{autonomy-PSVZVX7A.js → autonomy-GARI6J2J.js} +4 -4
  2. package/dist/chunk-NP5BDPE6.js +240 -0
  3. package/dist/chunk-NP5BDPE6.js.map +1 -0
  4. package/dist/chunk-O632SBON.js +62 -0
  5. package/dist/chunk-O632SBON.js.map +1 -0
  6. package/dist/{chunk-QHNUMM4V.js → chunk-QRNR4GIT.js} +3 -2
  7. package/dist/chunk-QRNR4GIT.js.map +1 -0
  8. package/dist/chunk-XTHZT53Y.js +364 -0
  9. package/dist/chunk-XTHZT53Y.js.map +1 -0
  10. package/dist/cli.js +1026 -88
  11. package/dist/cli.js.map +1 -1
  12. package/dist/{context-GWPF4SEY.js → context-PYTO2UQG.js} +7 -7
  13. package/dist/{context-feed-AJGVAR6H.js → context-feed-TLVZZ24S.js} +15 -15
  14. package/dist/{cost-XBCDJ7XC.js → cost-OALPURUQ.js} +7 -7
  15. package/dist/{dashboard-LGT2B2BL.js → dashboard-HQIEHTZC.js} +14 -14
  16. package/dist/{doctor-XPUIIBHJ.js → doctor-TWHMR23W.js} +4 -4
  17. package/dist/{exec-OUXM7JBF.js → exec-DYLI4TXY.js} +2 -2
  18. package/dist/{feedback-KNAOG5QK.js → feedback-5AEACUX6.js} +8 -8
  19. package/dist/{goal-BVHV5573.js → goal-XUNV3CKV.js} +8 -8
  20. package/dist/{health-4UXN44PF.js → health-ZF3HSA4W.js} +4 -4
  21. package/dist/{history-ILH3SWHB.js → history-WP6R5BNG.js} +5 -5
  22. package/dist/history-WP6R5BNG.js.map +1 -0
  23. package/dist/{init-XQZ7BOGT.js → init-BQSCG57S.js} +115 -6
  24. package/dist/init-BQSCG57S.js.map +1 -0
  25. package/dist/{kpi-RQIU7WGK.js → kpi-VBGDO4GI.js} +6 -6
  26. package/dist/{learn-OIFUVZAS.js → learn-C4B2PQ5J.js} +8 -8
  27. package/dist/{login-DXZANWZY.js → login-F6ITE7PR.js} +7 -7
  28. package/dist/{memory-T3ACCS7E.js → memory-33HYD6AN.js} +11 -11
  29. package/dist/observability-CL23L7LD.js +20 -0
  30. package/dist/observability-CL23L7LD.js.map +1 -0
  31. package/dist/org-cycle-Q74OT4I4.js +130 -0
  32. package/dist/org-cycle-Q74OT4I4.js.map +1 -0
  33. package/dist/{progress-DAUZMT3N.js → progress-P2EIZBKP.js} +5 -5
  34. package/dist/{providers-3P5D2XL5.js → providers-LE744DM6.js} +2 -2
  35. package/dist/repo-enforcement-JJQMKDAU.js +75 -0
  36. package/dist/repo-enforcement-JJQMKDAU.js.map +1 -0
  37. package/dist/{results-UECWGLTB.js → results-6TH33HPN.js} +6 -6
  38. package/dist/{run-I6KAXU6U.js → run-DOY5SGF3.js} +3713 -3688
  39. package/dist/run-DOY5SGF3.js.map +1 -0
  40. package/dist/run-context-GB6GUCKZ.js +26 -0
  41. package/dist/run-context-GB6GUCKZ.js.map +1 -0
  42. package/dist/{status-AQNLDZVN.js → status-PFFB2NV6.js} +16 -16
  43. package/dist/{sync-ZI3MHA4G.js → sync-FR6LQJ4C.js} +12 -12
  44. package/dist/templates/seed/config/SYSTEM.md +6 -0
  45. package/dist/templates/seed/idp/catalog/service.yaml.template +25 -0
  46. package/dist/templates/seed/memory/_squad/goals.md +23 -0
  47. package/dist/templates/seed/memory/_squad/priorities.md +25 -0
  48. package/dist/templates/seed/memory/company/company.md +31 -0
  49. package/dist/templates/seed/skills/squads-cli/SKILL.md +302 -57
  50. package/dist/templates/seed/skills/squads-cli/references/commands.md +181 -0
  51. package/dist/templates/seed/squads/company/company-critic.md +12 -4
  52. package/dist/templates/seed/squads/company/company-eval.md +12 -4
  53. package/dist/templates/seed/squads/company/event-dispatcher.md +14 -4
  54. package/dist/templates/seed/squads/company/goal-tracker.md +12 -4
  55. package/dist/templates/seed/squads/company/manager.md +17 -11
  56. package/dist/templates/seed/squads/engineering/code-reviewer.md +14 -2
  57. package/dist/templates/seed/squads/engineering/issue-solver.md +10 -2
  58. package/dist/templates/seed/squads/engineering/test-writer.md +15 -5
  59. package/dist/templates/seed/squads/intelligence/intel-critic.md +19 -2
  60. package/dist/templates/seed/squads/intelligence/intel-eval.md +18 -1
  61. package/dist/templates/seed/squads/intelligence/intel-lead.md +12 -4
  62. package/dist/templates/seed/squads/marketing/content-drafter.md +14 -4
  63. package/dist/templates/seed/squads/marketing/growth-analyst.md +14 -2
  64. package/dist/templates/seed/squads/marketing/social-poster.md +15 -3
  65. package/dist/templates/seed/squads/operations/finance-tracker.md +11 -3
  66. package/dist/templates/seed/squads/operations/goal-tracker.md +14 -2
  67. package/dist/templates/seed/squads/operations/ops-lead.md +14 -4
  68. package/dist/templates/seed/squads/product/lead.md +11 -3
  69. package/dist/templates/seed/squads/product/scanner.md +12 -4
  70. package/dist/templates/seed/squads/product/worker.md +12 -4
  71. package/dist/templates/seed/squads/research/analyst.md +12 -4
  72. package/dist/templates/seed/squads/research/lead.md +11 -5
  73. package/dist/templates/seed/squads/research/synthesizer.md +12 -4
  74. package/dist/tier-detect-YX2HPNNR.js +15 -0
  75. package/dist/tier-detect-YX2HPNNR.js.map +1 -0
  76. package/package.json +1 -1
  77. package/templates/seed/config/SYSTEM.md +6 -0
  78. package/templates/seed/idp/catalog/service.yaml.template +25 -0
  79. package/templates/seed/memory/_squad/goals.md +23 -0
  80. package/templates/seed/memory/_squad/priorities.md +25 -0
  81. package/templates/seed/memory/company/company.md +31 -0
  82. package/templates/seed/skills/squads-cli/SKILL.md +302 -57
  83. package/templates/seed/skills/squads-cli/references/commands.md +181 -0
  84. package/templates/seed/squads/company/company-critic.md +12 -4
  85. package/templates/seed/squads/company/company-eval.md +12 -4
  86. package/templates/seed/squads/company/event-dispatcher.md +14 -4
  87. package/templates/seed/squads/company/goal-tracker.md +12 -4
  88. package/templates/seed/squads/company/manager.md +17 -11
  89. package/templates/seed/squads/engineering/code-reviewer.md +14 -2
  90. package/templates/seed/squads/engineering/issue-solver.md +10 -2
  91. package/templates/seed/squads/engineering/test-writer.md +15 -5
  92. package/templates/seed/squads/intelligence/intel-critic.md +19 -2
  93. package/templates/seed/squads/intelligence/intel-eval.md +18 -1
  94. package/templates/seed/squads/intelligence/intel-lead.md +12 -4
  95. package/templates/seed/squads/marketing/content-drafter.md +14 -4
  96. package/templates/seed/squads/marketing/growth-analyst.md +14 -2
  97. package/templates/seed/squads/marketing/social-poster.md +15 -3
  98. package/templates/seed/squads/operations/finance-tracker.md +11 -3
  99. package/templates/seed/squads/operations/goal-tracker.md +14 -2
  100. package/templates/seed/squads/operations/ops-lead.md +14 -4
  101. package/templates/seed/squads/product/lead.md +11 -3
  102. package/templates/seed/squads/product/scanner.md +12 -4
  103. package/templates/seed/squads/product/worker.md +12 -4
  104. package/templates/seed/squads/research/analyst.md +12 -4
  105. package/templates/seed/squads/research/lead.md +11 -5
  106. package/templates/seed/squads/research/synthesizer.md +12 -4
  107. package/dist/chunk-QHNUMM4V.js.map +0 -1
  108. package/dist/history-ILH3SWHB.js.map +0 -1
  109. package/dist/init-XQZ7BOGT.js.map +0 -1
  110. package/dist/run-I6KAXU6U.js.map +0 -1
  111. /package/dist/{autonomy-PSVZVX7A.js.map → autonomy-GARI6J2J.js.map} +0 -0
  112. /package/dist/{context-GWPF4SEY.js.map → context-PYTO2UQG.js.map} +0 -0
  113. /package/dist/{context-feed-AJGVAR6H.js.map → context-feed-TLVZZ24S.js.map} +0 -0
  114. /package/dist/{cost-XBCDJ7XC.js.map → cost-OALPURUQ.js.map} +0 -0
  115. /package/dist/{dashboard-LGT2B2BL.js.map → dashboard-HQIEHTZC.js.map} +0 -0
  116. /package/dist/{doctor-XPUIIBHJ.js.map → doctor-TWHMR23W.js.map} +0 -0
  117. /package/dist/{exec-OUXM7JBF.js.map → exec-DYLI4TXY.js.map} +0 -0
  118. /package/dist/{feedback-KNAOG5QK.js.map → feedback-5AEACUX6.js.map} +0 -0
  119. /package/dist/{goal-BVHV5573.js.map → goal-XUNV3CKV.js.map} +0 -0
  120. /package/dist/{health-4UXN44PF.js.map → health-ZF3HSA4W.js.map} +0 -0
  121. /package/dist/{kpi-RQIU7WGK.js.map → kpi-VBGDO4GI.js.map} +0 -0
  122. /package/dist/{learn-OIFUVZAS.js.map → learn-C4B2PQ5J.js.map} +0 -0
  123. /package/dist/{login-DXZANWZY.js.map → login-F6ITE7PR.js.map} +0 -0
  124. /package/dist/{memory-T3ACCS7E.js.map → memory-33HYD6AN.js.map} +0 -0
  125. /package/dist/{progress-DAUZMT3N.js.map → progress-P2EIZBKP.js.map} +0 -0
  126. /package/dist/{providers-3P5D2XL5.js.map → providers-LE744DM6.js.map} +0 -0
  127. /package/dist/{results-UECWGLTB.js.map → results-6TH33HPN.js.map} +0 -0
  128. /package/dist/{status-AQNLDZVN.js.map → status-PFFB2NV6.js.map} +0 -0
  129. /package/dist/{sync-ZI3MHA4G.js.map → sync-FR6LQJ4C.js.map} +0 -0
package/dist/cli.js CHANGED
@@ -4,6 +4,20 @@ import {
4
4
  getNextCronRun,
5
5
  parseCooldown
6
6
  } from "./chunk-RM6BWILN.js";
7
+ import {
8
+ registerExitHandler,
9
+ track,
10
+ version
11
+ } from "./chunk-QJ7C7CMB.js";
12
+ import {
13
+ RESET,
14
+ bold,
15
+ colors,
16
+ writeLine
17
+ } from "./chunk-M5FXNY6Y.js";
18
+ import {
19
+ findMemoryDir
20
+ } from "./chunk-ZTQ7ISUR.js";
7
21
  import {
8
22
  getApiUrl
9
23
  } from "./chunk-EHQJHRIW.js";
@@ -11,32 +25,26 @@ import {
11
25
  loadSession
12
26
  } from "./chunk-Z2UKDBNL.js";
13
27
  import {
14
- registerExitHandler,
15
- track,
16
- version
17
- } from "./chunk-QJ7C7CMB.js";
28
+ detectTier
29
+ } from "./chunk-O632SBON.js";
30
+ import {
31
+ calculateCostSummary,
32
+ queryExecutions
33
+ } from "./chunk-NP5BDPE6.js";
18
34
  import {
35
+ findProjectRoot,
19
36
  findSquadsDir,
20
37
  listAgents,
21
38
  listSquads,
22
39
  loadSquad,
23
40
  resolveMcpConfigPath
24
41
  } from "./chunk-TYFTF53O.js";
25
- import {
26
- findMemoryDir
27
- } from "./chunk-ZTQ7ISUR.js";
28
- import {
29
- RESET,
30
- bold,
31
- colors,
32
- writeLine
33
- } from "./chunk-M5FXNY6Y.js";
34
42
  import "./chunk-7OCVIDC7.js";
35
43
 
36
44
  // src/cli.ts
37
45
  import { config } from "dotenv";
38
- import { existsSync as existsSync7 } from "fs";
39
- import { join as join6 } from "path";
46
+ import { existsSync as existsSync12 } from "fs";
47
+ import { join as join10 } from "path";
40
48
  import { homedir as homedir3 } from "os";
41
49
  import { Command } from "commander";
42
50
  import chalk6 from "chalk";
@@ -874,7 +882,7 @@ async function startScheduler() {
874
882
  }
875
883
  );
876
884
  child.unref();
877
- await new Promise((resolve) => setTimeout(resolve, 2e3));
885
+ await new Promise((resolve2) => setTimeout(resolve2, 2e3));
878
886
  const check = isRunning();
879
887
  if (check.running) {
880
888
  writeLine(chalk2.green(`
@@ -1194,7 +1202,7 @@ Approval: ${approvalId}`);
1194
1202
  }
1195
1203
  writeLine(chalk3.dim(`Waiting for decision on ${approvalId}...`));
1196
1204
  while (Date.now() - startTime < timeoutMs) {
1197
- await new Promise((resolve) => setTimeout(resolve, 5e3));
1205
+ await new Promise((resolve2) => setTimeout(resolve2, 5e3));
1198
1206
  const updated = await check();
1199
1207
  if (!updated) {
1200
1208
  console.error(chalk3.red("Approval disappeared"));
@@ -1226,7 +1234,7 @@ function registerApprovalCommand(program2) {
1226
1234
  Types: issue, pr, content, run, brief
1227
1235
 
1228
1236
  Examples:
1229
- $ squads approval send pr --title "Merge feature X" --json '{"repo":"agents-squads/hq","number":123}'
1237
+ $ squads approval send pr --title "Merge feature X" --json '{"repo":"my-org/my-repo","number":123}'
1230
1238
  $ squads approval send content -t "LinkedIn post" -d "New blog announcement"
1231
1239
  $ echo '{"title":"Run overnight"}' | squads approval send run --json -
1232
1240
  `
@@ -1446,13 +1454,13 @@ async function deployPullCommand(options) {
1446
1454
  writeLine("");
1447
1455
  writeLine(chalk4.bold("Recent Platform Executions"));
1448
1456
  writeLine(chalk4.dim("\u2500".repeat(70)));
1449
- for (const exec2 of executions) {
1450
- const statusColor = exec2.status === "completed" ? chalk4.green : exec2.status === "failed" ? chalk4.red : exec2.status === "running" ? chalk4.yellow : chalk4.dim;
1451
- const cost = exec2.cost_usd !== null ? chalk4.dim(`$${exec2.cost_usd.toFixed(2)}`) : "";
1452
- const time = new Date(exec2.started_at).toLocaleString();
1453
- writeLine(` ${statusColor(exec2.status.padEnd(10))} ${chalk4.cyan(exec2.trigger_name)} ${chalk4.dim(time)} ${cost}`);
1454
- if (options.verbose && exec2.completed_at) {
1455
- const duration = (new Date(exec2.completed_at).getTime() - new Date(exec2.started_at).getTime()) / 1e3;
1457
+ for (const exec4 of executions) {
1458
+ const statusColor = exec4.status === "completed" ? chalk4.green : exec4.status === "failed" ? chalk4.red : exec4.status === "running" ? chalk4.yellow : chalk4.dim;
1459
+ const cost = exec4.cost_usd !== null ? chalk4.dim(`$${exec4.cost_usd.toFixed(2)}`) : "";
1460
+ const time = new Date(exec4.started_at).toLocaleString();
1461
+ writeLine(` ${statusColor(exec4.status.padEnd(10))} ${chalk4.cyan(exec4.trigger_name)} ${chalk4.dim(time)} ${cost}`);
1462
+ if (options.verbose && exec4.completed_at) {
1463
+ const duration = (new Date(exec4.completed_at).getTime() - new Date(exec4.started_at).getTime()) / 1e3;
1456
1464
  writeLine(` ${chalk4.dim(`duration: ${duration.toFixed(0)}s`)}`);
1457
1465
  }
1458
1466
  }
@@ -2170,6 +2178,928 @@ Examples:
2170
2178
  cmd.command("reflect").description("Trigger meta-cognition reflection").option("-s, --scope <scope>", "Reflection scope (business, squad:X, agent:X)", "business").action(async (options) => reflectCommand(options));
2171
2179
  }
2172
2180
 
2181
+ // src/lib/idp/catalog-loader.ts
2182
+ import { readdirSync as readdirSync5, readFileSync as readFileSync7, existsSync as existsSync8 } from "fs";
2183
+ import { join as join7 } from "path";
2184
+ import matter3 from "gray-matter";
2185
+
2186
+ // src/lib/idp/resolver.ts
2187
+ import { existsSync as existsSync7 } from "fs";
2188
+ import { join as join6, resolve } from "path";
2189
+ function findIdpDir() {
2190
+ const envPath = process.env.SQUADS_IDP_PATH;
2191
+ if (envPath && existsSync7(envPath)) {
2192
+ return resolve(envPath);
2193
+ }
2194
+ const projectRoot = findProjectRoot();
2195
+ if (projectRoot) {
2196
+ const colocated = join6(projectRoot, ".agents", "idp");
2197
+ if (existsSync7(join6(colocated, "catalog"))) {
2198
+ return colocated;
2199
+ }
2200
+ const sibling = join6(projectRoot, "..", "idp");
2201
+ if (existsSync7(join6(sibling, "catalog"))) {
2202
+ return resolve(sibling);
2203
+ }
2204
+ }
2205
+ const home = process.env.HOME || process.env.USERPROFILE || "";
2206
+ const absolute = join6(home, "agents-squads", "idp");
2207
+ if (existsSync7(join6(absolute, "catalog"))) {
2208
+ return absolute;
2209
+ }
2210
+ return null;
2211
+ }
2212
+
2213
+ // src/lib/idp/catalog-loader.ts
2214
+ function loadYaml(filePath) {
2215
+ if (!existsSync8(filePath)) return null;
2216
+ try {
2217
+ const raw = readFileSync7(filePath, "utf-8");
2218
+ const { data } = matter3(`---
2219
+ ${raw}
2220
+ ---`);
2221
+ return data;
2222
+ } catch {
2223
+ return null;
2224
+ }
2225
+ }
2226
+ function loadCatalog() {
2227
+ const idpDir = findIdpDir();
2228
+ if (!idpDir) return [];
2229
+ const catalogDir = join7(idpDir, "catalog");
2230
+ if (!existsSync8(catalogDir)) return [];
2231
+ const entries = [];
2232
+ for (const file of readdirSync5(catalogDir).filter((f) => f.endsWith(".yaml")).sort()) {
2233
+ const entry = loadYaml(join7(catalogDir, file));
2234
+ if (entry?.metadata?.name) {
2235
+ entries.push(entry);
2236
+ }
2237
+ }
2238
+ return entries;
2239
+ }
2240
+ function loadService(name) {
2241
+ const idpDir = findIdpDir();
2242
+ if (!idpDir) return null;
2243
+ const filePath = join7(idpDir, "catalog", `${name}.yaml`);
2244
+ return loadYaml(filePath);
2245
+ }
2246
+ function loadScorecard(name) {
2247
+ const idpDir = findIdpDir();
2248
+ if (!idpDir) return null;
2249
+ const filePath = join7(idpDir, "scorecards", `${name}.yaml`);
2250
+ return loadYaml(filePath);
2251
+ }
2252
+ function loadDependencyGraph() {
2253
+ const idpDir = findIdpDir();
2254
+ if (!idpDir) return null;
2255
+ return loadYaml(join7(idpDir, "dependencies", "graph.yaml"));
2256
+ }
2257
+
2258
+ // src/lib/idp/scorecard-engine.ts
2259
+ import { existsSync as existsSync9, statSync as statSync2 } from "fs";
2260
+ import { join as join8 } from "path";
2261
+ import { execSync as execSync3 } from "child_process";
2262
+ function exec(cmd, cwd) {
2263
+ try {
2264
+ return execSync3(cmd, { encoding: "utf-8", timeout: 15e3, cwd, stdio: ["pipe", "pipe", "pipe"] }).trim();
2265
+ } catch {
2266
+ return null;
2267
+ }
2268
+ }
2269
+ function ghAvailable() {
2270
+ return exec("gh --version") !== null;
2271
+ }
2272
+ function runCheck(check, service, repoPath) {
2273
+ const result = { name: check.name, passed: false, weight: check.weight, detail: "unknown" };
2274
+ const repo = service.metadata.repo;
2275
+ switch (check.name) {
2276
+ case "ci-passing": {
2277
+ if (!ghAvailable()) {
2278
+ result.detail = "gh CLI not available";
2279
+ break;
2280
+ }
2281
+ const out = exec(`gh api repos/${repo}/actions/runs?per_page=1&status=completed --jq '.[0].conclusion // empty'`);
2282
+ const out2 = exec(`gh api repos/${repo}/actions/runs --jq '.workflow_runs[0].conclusion // empty'`);
2283
+ const conclusion = out || out2;
2284
+ if (conclusion === "success") {
2285
+ result.passed = true;
2286
+ result.detail = "latest run: success";
2287
+ } else if (conclusion) {
2288
+ result.detail = `latest run: ${conclusion}`;
2289
+ } else {
2290
+ result.detail = "no CI runs found";
2291
+ }
2292
+ break;
2293
+ }
2294
+ case "test-coverage": {
2295
+ if (service.spec.ci.test_command && service.spec.ci.test_command !== "null") {
2296
+ result.passed = true;
2297
+ result.detail = `test command defined: ${service.spec.ci.test_command}`;
2298
+ } else {
2299
+ result.detail = "no test command configured";
2300
+ }
2301
+ break;
2302
+ }
2303
+ case "build-succeeds": {
2304
+ if (repoPath && service.spec.ci.build_command) {
2305
+ const buildResult = exec(`cd "${repoPath}" && ${service.spec.ci.build_command} 2>&1`);
2306
+ if (buildResult !== null) {
2307
+ result.passed = true;
2308
+ result.detail = "build passed";
2309
+ } else {
2310
+ result.detail = "build failed";
2311
+ }
2312
+ } else {
2313
+ result.detail = repoPath ? "no build command" : "repo not found locally";
2314
+ }
2315
+ break;
2316
+ }
2317
+ case "no-security-alerts": {
2318
+ if (!ghAvailable()) {
2319
+ result.detail = "gh CLI not available";
2320
+ break;
2321
+ }
2322
+ const alerts = exec(`gh api repos/${repo}/dependabot/alerts --jq '[.[] | select(.state=="open" and (.security_advisory.severity=="high" or .security_advisory.severity=="critical"))] | length'`);
2323
+ if (alerts === "0") {
2324
+ result.passed = true;
2325
+ result.detail = "no high/critical alerts";
2326
+ } else if (alerts) {
2327
+ result.detail = `${alerts} high/critical alerts`;
2328
+ } else {
2329
+ result.detail = "could not check alerts";
2330
+ }
2331
+ break;
2332
+ }
2333
+ case "readme-exists": {
2334
+ if (repoPath) {
2335
+ const readmePath = join8(repoPath, "README.md");
2336
+ if (existsSync9(readmePath)) {
2337
+ const size = statSync2(readmePath).size;
2338
+ if (size > 100) {
2339
+ result.passed = true;
2340
+ result.detail = `README.md (${size} bytes)`;
2341
+ } else {
2342
+ result.detail = `README.md too short (${size} bytes)`;
2343
+ }
2344
+ } else {
2345
+ result.detail = "README.md not found";
2346
+ }
2347
+ } else {
2348
+ result.detail = "repo not found locally";
2349
+ }
2350
+ break;
2351
+ }
2352
+ case "branch-protection": {
2353
+ if (!ghAvailable()) {
2354
+ result.detail = "gh CLI not available";
2355
+ break;
2356
+ }
2357
+ const protection = exec(`gh api repos/${repo}/branches/${service.spec.branches.default}/protection --jq '.required_status_checks.strict // false' 2>/dev/null`);
2358
+ if (protection && protection !== "null") {
2359
+ result.passed = true;
2360
+ result.detail = "branch protection enabled";
2361
+ } else {
2362
+ result.detail = "no branch protection";
2363
+ }
2364
+ break;
2365
+ }
2366
+ case "deploy-frequency": {
2367
+ if (!ghAvailable()) {
2368
+ result.detail = "gh CLI not available";
2369
+ break;
2370
+ }
2371
+ const runs = exec(`gh api repos/${repo}/actions/runs --jq '[.workflow_runs[] | select(.event=="push" and .head_branch=="${service.spec.branches.default}")] | length'`);
2372
+ const count = parseInt(runs || "0", 10);
2373
+ if (count > 0) {
2374
+ result.passed = true;
2375
+ result.detail = `${count} deploys recently`;
2376
+ } else {
2377
+ result.detail = "no recent deploys";
2378
+ }
2379
+ break;
2380
+ }
2381
+ case "stale-prs": {
2382
+ if (!ghAvailable()) {
2383
+ result.detail = "gh CLI not available";
2384
+ break;
2385
+ }
2386
+ const stalePrs = exec(`gh pr list --repo ${repo} --state open --json updatedAt --jq '[.[] | select((now - (.updatedAt | fromdateiso8601)) > 1209600)] | length'`);
2387
+ const count = parseInt(stalePrs || "0", 10);
2388
+ if (count === 0) {
2389
+ result.passed = true;
2390
+ result.detail = "no stale PRs";
2391
+ } else {
2392
+ result.detail = `${count} PRs stale >14d`;
2393
+ }
2394
+ break;
2395
+ }
2396
+ case "recent-activity": {
2397
+ if (repoPath) {
2398
+ const commits = exec(`git -C "${repoPath}" log --since="30 days ago" --oneline 2>/dev/null | wc -l`);
2399
+ const count = parseInt(commits?.trim() || "0", 10);
2400
+ if (count > 0) {
2401
+ result.passed = true;
2402
+ result.detail = `${count} commits in last 30d`;
2403
+ } else {
2404
+ result.detail = "no commits in 30 days";
2405
+ }
2406
+ } else if (ghAvailable()) {
2407
+ const out = exec(`gh api repos/${repo}/commits?per_page=1 --jq '.[0].commit.committer.date // empty'`);
2408
+ if (out) {
2409
+ result.passed = true;
2410
+ result.detail = `last commit: ${out.slice(0, 10)}`;
2411
+ } else {
2412
+ result.detail = "no recent commits";
2413
+ }
2414
+ } else {
2415
+ result.detail = "repo not found locally";
2416
+ }
2417
+ break;
2418
+ }
2419
+ case "no-stale-prs": {
2420
+ if (!ghAvailable()) {
2421
+ result.detail = "gh CLI not available";
2422
+ break;
2423
+ }
2424
+ const stalePrs = exec(`gh pr list --repo ${repo} --state open --json updatedAt --jq '[.[] | select((now - (.updatedAt | fromdateiso8601)) > 604800)] | length'`);
2425
+ const count = parseInt(stalePrs || "0", 10);
2426
+ if (count === 0) {
2427
+ result.passed = true;
2428
+ result.detail = "no stale PRs";
2429
+ } else {
2430
+ result.detail = `${count} PRs stale >7d`;
2431
+ }
2432
+ break;
2433
+ }
2434
+ case "clean-structure": {
2435
+ result.passed = true;
2436
+ result.detail = "check not implemented (v0.2)";
2437
+ break;
2438
+ }
2439
+ default:
2440
+ result.detail = `unknown check: ${check.name}`;
2441
+ }
2442
+ return result;
2443
+ }
2444
+ function findRepoPath(repoFullName) {
2445
+ const repoName = repoFullName.split("/")[1];
2446
+ if (!repoName) return null;
2447
+ const home = process.env.HOME || "";
2448
+ const candidates = [
2449
+ join8(home, "agents-squads", repoName),
2450
+ join8(process.cwd(), "..", repoName)
2451
+ ];
2452
+ for (const candidate of candidates) {
2453
+ if (existsSync9(candidate)) return candidate;
2454
+ }
2455
+ return null;
2456
+ }
2457
+ function evaluateService(service, scorecard) {
2458
+ const repoPath = findRepoPath(service.metadata.repo);
2459
+ const checks = [];
2460
+ for (const check of scorecard.checks) {
2461
+ checks.push(runCheck(check, service, repoPath));
2462
+ }
2463
+ const totalWeight = checks.reduce((sum, c) => sum + c.weight, 0);
2464
+ const earnedWeight = checks.filter((c) => c.passed).reduce((sum, c) => sum + c.weight, 0);
2465
+ const score = totalWeight > 0 ? Math.round(earnedWeight / totalWeight * 100) : 0;
2466
+ let grade = "F";
2467
+ const sortedGrades = Object.entries(scorecard.grades).sort((a, b) => b[1].min - a[1].min);
2468
+ for (const [g, { min }] of sortedGrades) {
2469
+ if (score >= min) {
2470
+ grade = g;
2471
+ break;
2472
+ }
2473
+ }
2474
+ return {
2475
+ service: service.metadata.name,
2476
+ scorecard: scorecard.metadata.name,
2477
+ score,
2478
+ grade,
2479
+ checks,
2480
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
2481
+ };
2482
+ }
2483
+
2484
+ // src/commands/catalog.ts
2485
+ function noIdp() {
2486
+ if (!findIdpDir()) {
2487
+ writeLine(` ${colors.red}IDP not found${RESET}`);
2488
+ writeLine(` ${colors.dim}Set SQUADS_IDP_PATH or clone the idp repo as a sibling directory.${RESET}`);
2489
+ return true;
2490
+ }
2491
+ return false;
2492
+ }
2493
+ function registerCatalogCommands(program2) {
2494
+ const catalog = program2.command("catalog").description("Service catalog \u2014 browse, inspect, and validate services");
2495
+ catalog.command("list").description("List all services in the catalog").option("--type <type>", "Filter by type (product, domain)").option("--json", "Output as JSON").action((opts) => {
2496
+ if (noIdp()) return;
2497
+ const entries = loadCatalog();
2498
+ if (entries.length === 0) {
2499
+ writeLine(" No catalog entries found.");
2500
+ return;
2501
+ }
2502
+ const filtered = opts.type ? entries.filter((e) => e.spec.type === opts.type) : entries;
2503
+ if (opts.json) {
2504
+ console.log(JSON.stringify(filtered.map((e) => ({
2505
+ name: e.metadata.name,
2506
+ type: e.spec.type,
2507
+ stack: e.spec.stack,
2508
+ owner: e.metadata.owner,
2509
+ repo: e.metadata.repo
2510
+ })), null, 2));
2511
+ return;
2512
+ }
2513
+ writeLine();
2514
+ writeLine(` ${bold}Service Catalog${RESET} (${filtered.length} services)`);
2515
+ writeLine();
2516
+ const products = filtered.filter((e) => e.spec.type === "product");
2517
+ const domains = filtered.filter((e) => e.spec.type === "domain");
2518
+ if (products.length > 0) {
2519
+ writeLine(` ${colors.cyan}Product Services${RESET}`);
2520
+ writeLine();
2521
+ for (const e of products) {
2522
+ const ci = e.spec.ci.template ? `ci:${e.spec.ci.template}` : "no-ci";
2523
+ const deploy = e.spec.deploy?.target || "manual";
2524
+ writeLine(` ${bold}${e.metadata.name}${RESET} ${colors.dim}${e.spec.stack} | ${ci} | deploy:${deploy} | owner:${e.metadata.owner}${RESET}`);
2525
+ writeLine(` ${colors.dim}${e.metadata.description}${RESET}`);
2526
+ }
2527
+ writeLine();
2528
+ }
2529
+ if (domains.length > 0) {
2530
+ writeLine(` ${colors.cyan}Domain Repos${RESET}`);
2531
+ writeLine();
2532
+ for (const e of domains) {
2533
+ writeLine(` ${e.metadata.name} ${colors.dim}owner:${e.metadata.owner} | ${e.metadata.repo}${RESET}`);
2534
+ }
2535
+ writeLine();
2536
+ }
2537
+ });
2538
+ catalog.command("show <service>").description("Show detailed info for a service").option("--json", "Output as JSON").action((serviceName, opts) => {
2539
+ if (noIdp()) return;
2540
+ const entry = loadService(serviceName);
2541
+ if (!entry) {
2542
+ writeLine(` ${colors.red}Service not found: ${serviceName}${RESET}`);
2543
+ writeLine(` ${colors.dim}Run 'squads catalog list' to see available services.${RESET}`);
2544
+ return;
2545
+ }
2546
+ if (opts.json) {
2547
+ console.log(JSON.stringify(entry, null, 2));
2548
+ return;
2549
+ }
2550
+ writeLine();
2551
+ writeLine(` ${bold}${entry.metadata.name}${RESET} ${colors.dim}${entry.spec.type}${RESET}`);
2552
+ writeLine(` ${entry.metadata.description}`);
2553
+ writeLine();
2554
+ writeLine(` ${colors.cyan}General${RESET}`);
2555
+ writeLine(` Owner: ${entry.metadata.owner}`);
2556
+ writeLine(` Repo: ${entry.metadata.repo}`);
2557
+ writeLine(` Stack: ${entry.spec.stack}${entry.spec.framework ? ` (${entry.spec.framework})` : ""}`);
2558
+ writeLine(` Scorecard: ${entry.spec.scorecard}`);
2559
+ writeLine(` Tags: ${entry.metadata.tags?.join(", ") || "none"}`);
2560
+ writeLine();
2561
+ writeLine(` ${colors.cyan}Branches${RESET}`);
2562
+ writeLine(` Default: ${entry.spec.branches.default}`);
2563
+ writeLine(` Workflow: ${entry.spec.branches.workflow}`);
2564
+ if (entry.spec.branches.development) {
2565
+ writeLine(` Dev branch: ${entry.spec.branches.development}`);
2566
+ }
2567
+ writeLine();
2568
+ if (entry.spec.ci.template) {
2569
+ writeLine(` ${colors.cyan}CI/CD${RESET}`);
2570
+ writeLine(` Template: ${entry.spec.ci.template}`);
2571
+ writeLine(` Checks: ${entry.spec.ci.required_checks.join(", ") || "none"}`);
2572
+ if (entry.spec.ci.build_command) writeLine(` Build: ${entry.spec.ci.build_command}`);
2573
+ if (entry.spec.ci.test_command) writeLine(` Test: ${entry.spec.ci.test_command}`);
2574
+ writeLine();
2575
+ }
2576
+ if (entry.spec.deploy) {
2577
+ writeLine(` ${colors.cyan}Deploy${RESET}`);
2578
+ writeLine(` Target: ${entry.spec.deploy.target}`);
2579
+ writeLine(` Trigger: ${entry.spec.deploy.trigger}`);
2580
+ if (entry.spec.deploy.environments) {
2581
+ for (const env2 of entry.spec.deploy.environments) {
2582
+ writeLine(` ${env2.name}: ${env2.url}`);
2583
+ }
2584
+ }
2585
+ writeLine();
2586
+ }
2587
+ if (entry.spec.dependencies.runtime.length > 0) {
2588
+ writeLine(` ${colors.cyan}Dependencies${RESET}`);
2589
+ for (const dep of entry.spec.dependencies.runtime) {
2590
+ const req = dep.required === false ? "(optional)" : "(required)";
2591
+ writeLine(` \u2192 ${dep.service} ${dep.version || ""} ${req}`);
2592
+ writeLine(` ${colors.dim}${dep.description}${RESET}`);
2593
+ }
2594
+ writeLine();
2595
+ }
2596
+ if (entry.spec.health.length > 0) {
2597
+ writeLine(` ${colors.cyan}Health Endpoints${RESET}`);
2598
+ for (const h of entry.spec.health) {
2599
+ writeLine(` ${h.name}: ${h.url}`);
2600
+ }
2601
+ writeLine();
2602
+ }
2603
+ });
2604
+ catalog.command("check [service]").description("Run scorecard checks for a service (or all)").option("--json", "Output as JSON").action((serviceName, opts) => {
2605
+ if (noIdp()) return;
2606
+ const entries = serviceName ? [loadService(serviceName)].filter(Boolean) : loadCatalog();
2607
+ if (entries.length === 0) {
2608
+ writeLine(` ${colors.red}No services found${RESET}`);
2609
+ return;
2610
+ }
2611
+ const results = [];
2612
+ for (const entry of entries) {
2613
+ const scorecard = loadScorecard(entry.spec.scorecard);
2614
+ if (!scorecard) {
2615
+ writeLine(` ${colors.dim}No scorecard '${entry.spec.scorecard}' for ${entry.metadata.name}${RESET}`);
2616
+ continue;
2617
+ }
2618
+ const result = evaluateService(entry, scorecard);
2619
+ results.push(result);
2620
+ if (!opts.json) {
2621
+ const gradeColor = result.grade === "A" ? colors.green : result.grade === "B" ? colors.cyan : result.grade === "C" ? colors.yellow : colors.red;
2622
+ writeLine();
2623
+ writeLine(` ${bold}${result.service}${RESET} ${gradeColor}${result.grade}${RESET} (${result.score}/100)`);
2624
+ for (const check of result.checks) {
2625
+ const icon = check.passed ? `${colors.green}pass${RESET}` : `${colors.red}fail${RESET}`;
2626
+ writeLine(` ${icon} ${check.name} ${colors.dim}(${check.detail})${RESET}`);
2627
+ }
2628
+ }
2629
+ }
2630
+ if (opts.json) {
2631
+ console.log(JSON.stringify(results, null, 2));
2632
+ } else {
2633
+ writeLine();
2634
+ }
2635
+ });
2636
+ }
2637
+
2638
+ // src/commands/release-check.ts
2639
+ async function checkHealth(url, expect) {
2640
+ try {
2641
+ const response = await fetch(url, { signal: AbortSignal.timeout(1e4) });
2642
+ return { ok: response.status === expect, status: response.status };
2643
+ } catch (e) {
2644
+ return { ok: false, status: e instanceof Error ? e.message : "unreachable" };
2645
+ }
2646
+ }
2647
+ function registerReleaseCommands(program2) {
2648
+ const release = program2.command("release").description("Release management \u2014 pre-deploy checks and status");
2649
+ release.command("pre-check <service>").description("Validate dependencies and health before deploying a service").option("--skip-health", "Skip health endpoint checks").action(async (serviceName, opts) => {
2650
+ const idpDir = findIdpDir();
2651
+ if (!idpDir) {
2652
+ writeLine(` ${colors.red}IDP not found${RESET}`);
2653
+ return;
2654
+ }
2655
+ const service = loadService(serviceName);
2656
+ if (!service) {
2657
+ writeLine(` ${colors.red}Service not found: ${serviceName}${RESET}`);
2658
+ return;
2659
+ }
2660
+ const graph = loadDependencyGraph();
2661
+ const deps = service.spec.dependencies.runtime;
2662
+ writeLine();
2663
+ writeLine(` ${bold}Release Pre-Check: ${serviceName}${RESET}`);
2664
+ writeLine();
2665
+ let allGreen = true;
2666
+ if (deps.length === 0) {
2667
+ writeLine(` ${colors.green}pass${RESET} No runtime dependencies`);
2668
+ } else {
2669
+ writeLine(` ${colors.cyan}Dependencies${RESET}`);
2670
+ for (const dep of deps) {
2671
+ const depService = loadService(dep.service);
2672
+ const req = dep.required !== false;
2673
+ if (!depService) {
2674
+ if (dep.type === "infrastructure") {
2675
+ writeLine(` ${colors.dim}skip${RESET} ${dep.service} (infrastructure \u2014 not in catalog)`);
2676
+ continue;
2677
+ }
2678
+ if (req) {
2679
+ writeLine(` ${colors.red}fail${RESET} ${dep.service} \u2014 not found in catalog`);
2680
+ allGreen = false;
2681
+ } else {
2682
+ writeLine(` ${colors.yellow}warn${RESET} ${dep.service} \u2014 not in catalog (optional)`);
2683
+ }
2684
+ continue;
2685
+ }
2686
+ if (!opts.skipHealth && depService.spec.health.length > 0) {
2687
+ for (const h of depService.spec.health) {
2688
+ const result = await checkHealth(h.url, h.expect);
2689
+ if (result.ok) {
2690
+ writeLine(` ${colors.green}pass${RESET} ${dep.service}/${h.name} \u2014 ${result.status}`);
2691
+ } else if (req) {
2692
+ writeLine(` ${colors.red}fail${RESET} ${dep.service}/${h.name} \u2014 ${result.status}`);
2693
+ allGreen = false;
2694
+ } else {
2695
+ writeLine(` ${colors.yellow}warn${RESET} ${dep.service}/${h.name} \u2014 ${result.status} (optional)`);
2696
+ }
2697
+ }
2698
+ } else {
2699
+ writeLine(` ${colors.dim}skip${RESET} ${dep.service} health check (${opts.skipHealth ? "skipped" : "no endpoints"})`);
2700
+ }
2701
+ }
2702
+ }
2703
+ writeLine();
2704
+ if (graph) {
2705
+ const order = graph.deploy_order;
2706
+ let servicePhase = -1;
2707
+ for (let i = 0; i < order.length; i++) {
2708
+ if (order[i].includes(serviceName)) {
2709
+ servicePhase = i;
2710
+ break;
2711
+ }
2712
+ }
2713
+ if (servicePhase >= 0) {
2714
+ writeLine(` ${colors.cyan}Deploy Order${RESET}`);
2715
+ for (let i = 0; i < order.length; i++) {
2716
+ const marker = i === servicePhase ? `${colors.green}\u2192${RESET}` : " ";
2717
+ const phase = order[i].join(", ");
2718
+ writeLine(` ${marker} Phase ${i + 1}: ${i === servicePhase ? bold : colors.dim}${phase}${RESET}`);
2719
+ }
2720
+ writeLine();
2721
+ }
2722
+ }
2723
+ if (!opts.skipHealth && service.spec.health.length > 0) {
2724
+ writeLine(` ${colors.cyan}Self Health${RESET}`);
2725
+ for (const h of service.spec.health) {
2726
+ const result = await checkHealth(h.url, h.expect);
2727
+ if (result.ok) {
2728
+ writeLine(` ${colors.green}pass${RESET} ${h.name} \u2014 ${result.status}`);
2729
+ } else {
2730
+ writeLine(` ${colors.yellow}warn${RESET} ${h.name} \u2014 ${result.status}`);
2731
+ }
2732
+ }
2733
+ writeLine();
2734
+ }
2735
+ if (allGreen) {
2736
+ writeLine(` ${colors.green}All checks passed \u2014 safe to deploy ${serviceName}${RESET}`);
2737
+ } else {
2738
+ writeLine(` ${colors.red}Pre-check failed \u2014 fix issues before deploying ${serviceName}${RESET}`);
2739
+ }
2740
+ writeLine();
2741
+ });
2742
+ }
2743
+
2744
+ // src/commands/observability.ts
2745
+ function registerObservabilityCommands(program2) {
2746
+ const obs = program2.command("obs").description("Observability \u2014 execution history, token costs, and trends");
2747
+ obs.command("history").description("Show execution history with tokens and cost").option("-s, --squad <squad>", "Filter by squad").option("-a, --agent <agent>", "Filter by agent").option("-n, --limit <n>", "Number of records", "20").option("--since <date>", "Since date (ISO or relative: 1d, 7d, 30d)").option("--json", "Output as JSON").action((opts) => {
2748
+ let since = opts.since;
2749
+ if (since && /^\d+d$/.test(since)) {
2750
+ const days = parseInt(since, 10);
2751
+ since = new Date(Date.now() - days * 24 * 60 * 60 * 1e3).toISOString();
2752
+ }
2753
+ const records = queryExecutions({
2754
+ squad: opts.squad,
2755
+ agent: opts.agent,
2756
+ since,
2757
+ limit: parseInt(opts.limit, 10)
2758
+ });
2759
+ if (records.length === 0) {
2760
+ writeLine(`
2761
+ ${colors.dim}No executions found. Run \`squads run <squad>\` to generate data.${RESET}
2762
+ `);
2763
+ return;
2764
+ }
2765
+ if (opts.json) {
2766
+ console.log(JSON.stringify(records, null, 2));
2767
+ return;
2768
+ }
2769
+ writeLine(`
2770
+ ${bold}Execution History${RESET} (${records.length} records)
2771
+ `);
2772
+ for (const r of records) {
2773
+ const icon = r.status === "completed" ? `${colors.green}pass${RESET}` : r.status === "failed" ? `${colors.red}fail${RESET}` : `${colors.yellow}timeout${RESET}`;
2774
+ const dur = r.duration_ms > 6e4 ? `${Math.round(r.duration_ms / 6e4)}m` : `${Math.round(r.duration_ms / 1e3)}s`;
2775
+ const cost = r.cost_usd > 0 ? `$${r.cost_usd.toFixed(3)}` : "$\u2014";
2776
+ const tok = r.input_tokens + r.output_tokens > 0 ? `${(r.input_tokens + r.output_tokens).toLocaleString()} tok` : "\u2014 tok";
2777
+ const date = r.ts.slice(0, 16).replace("T", " ");
2778
+ const grade = r.grade ? ` ${r.grade}` : "";
2779
+ writeLine(` ${icon} ${bold}${r.squad}/${r.agent}${RESET} ${colors.dim}${date} ${dur} ${tok} ${cost} ${r.model}${grade}${RESET}`);
2780
+ if (r.error) writeLine(` ${colors.red}${r.error.slice(0, 80)}${RESET}`);
2781
+ if (r.goals_changed && r.goals_changed.length > 0) {
2782
+ for (const g of r.goals_changed) {
2783
+ writeLine(` ${colors.green}goal: ${g.name} ${g.before} \u2192 ${g.after}${RESET}`);
2784
+ }
2785
+ }
2786
+ }
2787
+ writeLine();
2788
+ });
2789
+ obs.command("cost").description("Show token spend summary").option("-p, --period <period>", "Time period: today, 7d, 30d, all", "7d").option("--json", "Output as JSON").action((opts) => {
2790
+ const summary = calculateCostSummary(opts.period);
2791
+ if (summary.total_runs === 0) {
2792
+ writeLine(`
2793
+ ${colors.dim}No executions in the last ${opts.period}.${RESET}
2794
+ `);
2795
+ return;
2796
+ }
2797
+ if (opts.json) {
2798
+ console.log(JSON.stringify(summary, null, 2));
2799
+ return;
2800
+ }
2801
+ writeLine(`
2802
+ ${bold}Cost Summary${RESET} (${summary.period})`);
2803
+ writeLine(`
2804
+ Total: ${bold}$${summary.total_cost.toFixed(2)}${RESET} across ${summary.total_runs} runs`);
2805
+ writeLine(` Tokens: ${summary.total_input_tokens.toLocaleString()} in / ${summary.total_output_tokens.toLocaleString()} out
2806
+ `);
2807
+ const squads = Object.entries(summary.by_squad).sort((a, b) => b[1].cost - a[1].cost);
2808
+ if (squads.length > 0) {
2809
+ writeLine(` ${colors.cyan}By Squad${RESET}`);
2810
+ for (const [name, data] of squads) {
2811
+ const bar = "\u2588".repeat(Math.max(1, Math.round(data.cost / (summary.total_cost || 1) * 20)));
2812
+ writeLine(` ${name.padEnd(20)} ${colors.dim}${bar}${RESET} $${data.cost.toFixed(2)} (${data.runs} runs, avg $${data.avg_cost.toFixed(3)})`);
2813
+ }
2814
+ writeLine();
2815
+ }
2816
+ const models = Object.entries(summary.by_model).sort((a, b) => b[1].cost - a[1].cost);
2817
+ if (models.length > 0) {
2818
+ writeLine(` ${colors.cyan}By Model${RESET}`);
2819
+ for (const [name, data] of models) {
2820
+ writeLine(` ${name.padEnd(30)} $${data.cost.toFixed(2)} (${data.runs} runs)`);
2821
+ }
2822
+ writeLine();
2823
+ }
2824
+ });
2825
+ obs.command("sync").description("Backfill JSONL execution data to Postgres (Tier 2)").option("--dry-run", "Show what would be synced without sending").action(async (opts) => {
2826
+ const { detectTier: detectTier2 } = await import("./tier-detect-YX2HPNNR.js");
2827
+ const { queryExecutions: queryExecutions2 } = await import("./observability-CL23L7LD.js");
2828
+ const info = await detectTier2();
2829
+ if (info.tier < 2 || !info.urls.api) {
2830
+ writeLine(`
2831
+ ${colors.dim}Tier 2 not available. Run 'squads services up' first.${RESET}
2832
+ `);
2833
+ return;
2834
+ }
2835
+ const records = queryExecutions2({ limit: 1e4 });
2836
+ if (records.length === 0) {
2837
+ writeLine(`
2838
+ ${colors.dim}No JSONL records to sync.${RESET}
2839
+ `);
2840
+ return;
2841
+ }
2842
+ writeLine(`
2843
+ ${bold}Syncing ${records.length} records to Postgres...${RESET}
2844
+ `);
2845
+ let synced = 0;
2846
+ let skipped = 0;
2847
+ let errors = 0;
2848
+ for (const record of records) {
2849
+ if (opts.dryRun) {
2850
+ writeLine(` ${colors.dim}[dry-run] ${record.ts} ${record.squad}/${record.agent} $${record.cost_usd.toFixed(3)}${RESET}`);
2851
+ synced++;
2852
+ continue;
2853
+ }
2854
+ try {
2855
+ const res = await fetch(`${info.urls.api}/agent-executions`, {
2856
+ method: "POST",
2857
+ headers: { "Content-Type": "application/json" },
2858
+ body: JSON.stringify({
2859
+ execution_id: record.id,
2860
+ squad: record.squad,
2861
+ agent: record.agent,
2862
+ model: record.model,
2863
+ status: record.status,
2864
+ input_tokens: record.input_tokens,
2865
+ output_tokens: record.output_tokens,
2866
+ cache_read_tokens: record.cache_read_tokens,
2867
+ cache_write_tokens: record.cache_write_tokens,
2868
+ cost_usd: record.cost_usd,
2869
+ duration_seconds: Math.round(record.duration_ms / 1e3),
2870
+ error_message: record.error || null,
2871
+ metadata: { trigger: record.trigger, provider: record.provider }
2872
+ }),
2873
+ signal: AbortSignal.timeout(5e3)
2874
+ });
2875
+ if (res.ok) {
2876
+ synced++;
2877
+ } else if (res.status === 409) {
2878
+ skipped++;
2879
+ } else {
2880
+ errors++;
2881
+ }
2882
+ } catch {
2883
+ errors++;
2884
+ }
2885
+ }
2886
+ writeLine(` ${colors.green}Synced: ${synced}${RESET} ${colors.dim}Skipped: ${skipped} Errors: ${errors}${RESET}
2887
+ `);
2888
+ });
2889
+ }
2890
+
2891
+ // src/commands/tier.ts
2892
+ import { existsSync as existsSync10, readdirSync as readdirSync6 } from "fs";
2893
+ function registerTierCommand(program2) {
2894
+ program2.command("tier").description("Show active infrastructure tier and available services").option("--json", "Output as JSON").action(async (opts) => {
2895
+ const info = await detectTier();
2896
+ if (opts.json) {
2897
+ console.log(JSON.stringify(info, null, 2));
2898
+ return;
2899
+ }
2900
+ writeLine();
2901
+ if (info.tier === 1) {
2902
+ writeLine(` ${bold}Tier 1${RESET} ${colors.dim}(file-based)${RESET}`);
2903
+ } else {
2904
+ writeLine(` ${bold}Tier 2${RESET} ${colors.green}(local services)${RESET}`);
2905
+ }
2906
+ writeLine();
2907
+ writeLine(` ${colors.cyan}Data${RESET}`);
2908
+ const executions = queryExecutions({ limit: 1e3 });
2909
+ writeLine(` Observability: ${executions.length} executions logged`);
2910
+ const squadsDir = findSquadsDir();
2911
+ if (squadsDir) {
2912
+ const squads = readdirSync6(squadsDir).filter((f) => {
2913
+ try {
2914
+ return existsSync10(`${squadsDir}/${f}/SQUAD.md`);
2915
+ } catch {
2916
+ return false;
2917
+ }
2918
+ });
2919
+ writeLine(` Squads: ${squads.length} defined`);
2920
+ }
2921
+ const memoryDir = findMemoryDir();
2922
+ if (memoryDir) {
2923
+ writeLine(` Memory: ${memoryDir}`);
2924
+ }
2925
+ const idpDir = findIdpDir();
2926
+ if (idpDir) {
2927
+ const catalog = loadCatalog();
2928
+ writeLine(` IDP: ${catalog.length} catalog entries`);
2929
+ } else {
2930
+ writeLine(` IDP: not configured`);
2931
+ }
2932
+ writeLine();
2933
+ writeLine(` ${colors.cyan}Services${RESET}`);
2934
+ const svc = info.services;
2935
+ const icon = (ok) => ok ? `${colors.green}up${RESET}` : `${colors.dim}\u2014${RESET}`;
2936
+ writeLine(` API: ${icon(svc.api)}${svc.api ? ` ${info.urls.api}` : ""}`);
2937
+ writeLine(` Bridge: ${icon(svc.bridge)}${svc.bridge ? ` ${info.urls.bridge}` : ""}`);
2938
+ writeLine(` Postgres: ${icon(svc.postgres)}`);
2939
+ writeLine(` Redis: ${icon(svc.redis)}`);
2940
+ writeLine();
2941
+ if (info.tier === 1) {
2942
+ writeLine(` ${colors.dim}Upgrade: run 'squads services up' for Tier 2${RESET}`);
2943
+ writeLine(` ${colors.dim}(smart triggers, Postgres, webhooks, budget enforcement)${RESET}`);
2944
+ } else {
2945
+ writeLine(` ${colors.dim}All local services healthy. Data syncs to Postgres.${RESET}`);
2946
+ }
2947
+ writeLine();
2948
+ });
2949
+ }
2950
+
2951
+ // src/commands/services.ts
2952
+ import { execSync as execSync4 } from "child_process";
2953
+ import { existsSync as existsSync11 } from "fs";
2954
+ import { join as join9 } from "path";
2955
+ function exec2(cmd, opts) {
2956
+ try {
2957
+ return execSync4(cmd, { encoding: "utf-8", timeout: 3e4, stdio: ["pipe", "pipe", "pipe"], ...opts }).trim();
2958
+ } catch {
2959
+ return null;
2960
+ }
2961
+ }
2962
+ function findComposeFile() {
2963
+ const home = process.env.HOME || "";
2964
+ const candidates = [
2965
+ join9(home, "agents-squads", "engineering", "docker", "docker-compose.yml"),
2966
+ join9(home, "agents-squads", "engineering", "docker", "docker-compose.yaml"),
2967
+ join9(process.cwd(), "..", "engineering", "docker", "docker-compose.yml")
2968
+ ];
2969
+ for (const candidate of candidates) {
2970
+ if (existsSync11(candidate)) return candidate;
2971
+ }
2972
+ return null;
2973
+ }
2974
+ function dockerAvailable() {
2975
+ return exec2("docker --version") !== null;
2976
+ }
2977
+ function dockerComposeAvailable() {
2978
+ return exec2("docker compose version") !== null;
2979
+ }
2980
+ function registerServicesCommands(program2) {
2981
+ const services = program2.command("services").description("Manage Tier 2 local services (Postgres, Redis, API, Bridge)");
2982
+ services.command("up").description("Start local services (Docker required)").option("--webhooks", "Also start ngrok tunnel for GitHub webhooks").option("--telemetry", "Also start OpenTelemetry collector").action(async (opts) => {
2983
+ if (!dockerAvailable()) {
2984
+ writeLine(`
2985
+ ${colors.red}Docker not found.${RESET}`);
2986
+ writeLine(` ${colors.dim}Install Docker Desktop: https://www.docker.com/products/docker-desktop${RESET}
2987
+ `);
2988
+ return;
2989
+ }
2990
+ if (!dockerComposeAvailable()) {
2991
+ writeLine(`
2992
+ ${colors.red}Docker Compose not found.${RESET}
2993
+ `);
2994
+ return;
2995
+ }
2996
+ const composeFile = findComposeFile();
2997
+ if (!composeFile) {
2998
+ writeLine(`
2999
+ ${colors.red}docker-compose.yml not found.${RESET}`);
3000
+ writeLine(` ${colors.dim}Expected at: ../engineering/docker/docker-compose.yml (sibling repo)${RESET}
3001
+ `);
3002
+ return;
3003
+ }
3004
+ const composeDir = join9(composeFile, "..");
3005
+ writeLine(`
3006
+ ${bold}Starting Tier 2 services...${RESET}
3007
+ `);
3008
+ let profileArgs = "";
3009
+ if (opts.webhooks) profileArgs += " --profile webhooks";
3010
+ if (opts.telemetry) profileArgs += " --profile telemetry";
3011
+ try {
3012
+ writeLine(` ${colors.dim}docker compose up -d${profileArgs}${RESET}`);
3013
+ execSync4(`docker compose${profileArgs} up -d`, {
3014
+ cwd: composeDir,
3015
+ stdio: "inherit",
3016
+ timeout: 12e4
3017
+ });
3018
+ writeLine();
3019
+ writeLine(` ${colors.green}Services started.${RESET} Waiting for health checks...`);
3020
+ let healthy = false;
3021
+ for (let i = 0; i < 15; i++) {
3022
+ await new Promise((r) => setTimeout(r, 2e3));
3023
+ const info = await detectTier();
3024
+ if (info.services.api) {
3025
+ healthy = true;
3026
+ break;
3027
+ }
3028
+ }
3029
+ if (healthy) {
3030
+ writeLine(` ${colors.green}Tier 2 active.${RESET} All services healthy.
3031
+ `);
3032
+ writeLine(` ${colors.dim}API: http://localhost:8090${RESET}`);
3033
+ writeLine(` ${colors.dim}Bridge: http://localhost:8088${RESET}`);
3034
+ writeLine(` ${colors.dim}Postgres: localhost:5432${RESET}`);
3035
+ writeLine(` ${colors.dim}Redis: localhost:6379${RESET}`);
3036
+ } else {
3037
+ writeLine(` ${colors.yellow}Services started but API not healthy yet. Run 'squads services status' to check.${RESET}`);
3038
+ }
3039
+ writeLine();
3040
+ } catch (e) {
3041
+ writeLine(`
3042
+ ${colors.red}Failed to start services: ${e instanceof Error ? e.message : String(e)}${RESET}
3043
+ `);
3044
+ }
3045
+ });
3046
+ services.command("down").description("Stop local services").action(() => {
3047
+ const composeFile = findComposeFile();
3048
+ if (!composeFile) {
3049
+ writeLine(`
3050
+ ${colors.dim}No docker-compose.yml found. Nothing to stop.${RESET}
3051
+ `);
3052
+ return;
3053
+ }
3054
+ const composeDir = join9(composeFile, "..");
3055
+ writeLine(`
3056
+ ${bold}Stopping Tier 2 services...${RESET}
3057
+ `);
3058
+ try {
3059
+ execSync4("docker compose down", {
3060
+ cwd: composeDir,
3061
+ stdio: "inherit",
3062
+ timeout: 6e4
3063
+ });
3064
+ writeLine(`
3065
+ ${colors.dim}Services stopped. Falling back to Tier 1 (file-based).${RESET}
3066
+ `);
3067
+ } catch (e) {
3068
+ writeLine(`
3069
+ ${colors.red}Failed to stop services: ${e instanceof Error ? e.message : String(e)}${RESET}
3070
+ `);
3071
+ }
3072
+ });
3073
+ services.command("status").description("Show running services and health").action(async () => {
3074
+ const info = await detectTier();
3075
+ writeLine();
3076
+ writeLine(` ${bold}Services${RESET} (Tier ${info.tier})
3077
+ `);
3078
+ const containers = exec2('docker ps --filter name=squads --format "{{.Names}}\\t{{.Status}}\\t{{.Ports}}"');
3079
+ if (!containers) {
3080
+ writeLine(` ${colors.dim}No Docker containers running.${RESET}
3081
+ `);
3082
+ return;
3083
+ }
3084
+ for (const line of containers.split("\n").filter(Boolean)) {
3085
+ const [name, status, ports] = line.split(" ");
3086
+ const healthy = status?.includes("healthy") || status?.includes("Up");
3087
+ const icon = healthy ? `${colors.green}up${RESET}` : `${colors.red}down${RESET}`;
3088
+ const portStr = ports ? ` ${colors.dim}${ports.split(",")[0]}${RESET}` : "";
3089
+ writeLine(` ${icon} ${bold}${name}${RESET}${portStr}`);
3090
+ }
3091
+ writeLine();
3092
+ const jobCount = exec2("docker exec squads-postgres psql -U squads -d squads -t -c 'SELECT count(*) FROM procrastinate_jobs;'");
3093
+ const execCount = exec2("docker exec squads-postgres psql -U squads -d squads -t -c 'SELECT count(*) FROM agent_executions;'");
3094
+ if (jobCount || execCount) {
3095
+ writeLine(` ${colors.cyan}Database${RESET}`);
3096
+ if (jobCount) writeLine(` Procrastinate jobs: ${jobCount.trim()}`);
3097
+ if (execCount) writeLine(` Agent executions: ${execCount.trim()}`);
3098
+ writeLine();
3099
+ }
3100
+ });
3101
+ }
3102
+
2173
3103
  // src/cli.ts
2174
3104
  if (!process.stdout.isTTY) {
2175
3105
  chalk6.level = 0;
@@ -2187,12 +3117,12 @@ process.stderr.on("error", (err) => {
2187
3117
  throw err;
2188
3118
  });
2189
3119
  var envPaths = [
2190
- join6(process.cwd(), ".env"),
2191
- join6(process.cwd(), "..", "hq", ".env"),
2192
- join6(homedir3(), "agents-squads", "hq", ".env")
3120
+ join10(process.cwd(), ".env"),
3121
+ join10(process.cwd(), "..", "hq", ".env"),
3122
+ join10(homedir3(), "agents-squads", "hq", ".env")
2193
3123
  ];
2194
3124
  for (const envPath of envPaths) {
2195
- if (existsSync7(envPath)) {
3125
+ if (existsSync12(envPath)) {
2196
3126
  config({ path: envPath, quiet: true });
2197
3127
  break;
2198
3128
  }
@@ -2318,11 +3248,11 @@ program.name("squads").description("Your AI workforce \u2014 business operating
2318
3248
  writeLine(` ${colors3.dim}Run \`squads update\` to install${RESET2}`);
2319
3249
  writeLine();
2320
3250
  }
2321
- const { statusCommand } = await import("./status-AQNLDZVN.js");
3251
+ const { statusCommand } = await import("./status-PFFB2NV6.js");
2322
3252
  await statusCommand(void 0, {});
2323
3253
  });
2324
3254
  program.command("init").description("Plant the seed: create manager agent, CLI skill, and starter squads").option("-p, --provider <provider>", "LLM provider (claude, gemini, openai, ollama, none)").option("--pack <packs...>", "Additional squad packs to install (engineering, marketing, operations, all)").option("--skip-infra", "Skip infrastructure setup prompt").option("--force", "Skip requirement checks (for CI/testing)").option("-y, --yes", "Accept all defaults (non-interactive mode)").option("-q, --quick", "Quick init - create files only, skip interactive prompts").action(async (options) => {
2325
- const { initCommand } = await import("./init-XQZ7BOGT.js");
3255
+ const { initCommand } = await import("./init-BQSCG57S.js");
2326
3256
  return initCommand(options);
2327
3257
  });
2328
3258
  program.command("add <name>").description("Add a new squad with directory structure and starter files").option("-d, --description <text>", "Squad mission (one sentence)").option("-g, --goal <text>", "First goal for the squad").option("-m, --model <model>", "Default model (default: sonnet)").option("-f, --force", "Overwrite existing squad").option("-y, --yes", "Accept all defaults (non-interactive)").option("-r, --repo", "Create a GitHub repository for the squad").option("-o, --org <org>", "GitHub organization for --repo (default: detected from git remote)").addHelpText("after", `
@@ -2337,7 +3267,7 @@ Examples:
2337
3267
  return createCommand(name, options);
2338
3268
  });
2339
3269
  program.command("create <name>", { hidden: true }).description("[renamed]").action(removedCommand("create", "Renamed to: squads add <name>"));
2340
- program.command("run [target]").description("Run a squad, agent, or autopilot (no target = autopilot mode)").option("-v, --verbose", "Verbose output").option("-d, --dry-run", "Show what would be run without executing").option("-a, --agent <agent>", "Run specific agent within squad").option("-t, --timeout <minutes>", "Execution timeout in minutes (default: 30)", "30").option("-p, --parallel", "Run all agents in parallel (N tmux sessions)").option("-l, --lead", "Lead mode: single orchestrator using Task tool for parallelization").option("-b, --background", "Run agent in background (detached process)").option("-w, --watch", "Run in background but tail the log for visibility").option("--use-api", "Use API credits instead of subscription").option("--effort <level>", "Effort level: high, medium, low (default: from SQUAD.md or high)").option("--skills <skills...>", "Skills to load (skill IDs or local paths)").option("--provider <provider>", "LLM provider: anthropic, google, openai, mistral, xai, aider, ollama").option("--model <model>", "Model to use (e.g., opus, sonnet, haiku, gemini-2.5-flash, gpt-4o)").option("--trigger <type>", "Trigger source: manual, scheduled, event, smart (default: manual)").option("--cloud", "Dispatch execution to cloud worker via API (requires squads login)").option("--task <directive>", "Founder directive for conversation mode (replaces lead briefing)").option("--max-turns <n>", "Max conversation turns (default: 20)", "20").option("--cost-ceiling <usd>", "Cost ceiling in USD (default: 25)", "25").option("--no-verify", "Skip post-execution verification (Ralph loop)").option("--execute", "Explicitly execute agents (default for run <target>)").option("-j, --json", "Output as JSON").option("-i, --interval <minutes>", "Autopilot: minutes between cycles", "30").option("--max-parallel <count>", "Autopilot: max parallel squad loops", "2").option("--budget <usd>", "Autopilot: daily budget cap ($)", "0").option("--once", "Autopilot: run one cycle then exit").option("--phased", "Autopilot: use dependency-based phase ordering (from SQUAD.md depends_on)").option("--no-eval", "Skip post-run COO evaluation").addHelpText("after", `
3270
+ program.command("run [target]").description("Run a squad, agent, or autopilot (no target = autopilot mode)").option("-v, --verbose", "Verbose output").option("-d, --dry-run", "Show what would be run without executing").option("-a, --agent <agent>", "Run specific agent within squad").option("-t, --timeout <minutes>", "Execution timeout in minutes (default: 30)", "30").option("-p, --parallel", "Run all agents in parallel (N tmux sessions)").option("-l, --lead", "Lead mode: single orchestrator using Task tool for parallelization").option("-b, --background", "Run agent in background (detached process)").option("-w, --watch", "Run in background but tail the log for visibility").option("--use-api", "Use API credits instead of subscription").option("--effort <level>", "Effort level: high, medium, low (default: from SQUAD.md or high)").option("--skills <skills...>", "Skills to load (skill IDs or local paths)").option("--provider <provider>", "LLM provider: anthropic, google, openai, mistral, xai, aider, ollama").option("--model <model>", "Model to use (e.g., opus, sonnet, haiku, gemini-2.5-flash, gpt-4o)").option("--trigger <type>", "Trigger source: manual, scheduled, event, smart (default: manual)").option("--cloud", "Dispatch execution to cloud worker via API (requires squads login)").option("--task <directive>", "Founder directive for conversation mode (replaces lead briefing)").option("--max-turns <n>", "Max conversation turns (default: 20)", "20").option("--cost-ceiling <usd>", "Cost ceiling in USD (default: 25)", "25").option("--no-verify", "Skip post-execution verification (Ralph loop)").option("--execute", "Explicitly execute agents (default for run <target>)").option("-j, --json", "Output as JSON").option("-i, --interval <minutes>", "Autopilot: minutes between cycles", "30").option("--max-parallel <count>", "Autopilot: max parallel squad loops", "2").option("--budget <usd>", "Autopilot: daily budget cap ($)", "0").option("--once", "Autopilot: run one cycle then exit").option("--phased", "Autopilot: use dependency-based phase ordering (from SQUAD.md depends_on)").option("--no-eval", "Skip post-run COO evaluation").option("--org", "Run all squads as a coordinated org cycle (scan \u2192 plan \u2192 execute \u2192 report)").addHelpText("after", `
2341
3271
  Examples:
2342
3272
  $ squads run engineering Run squad conversation (lead \u2192 scan \u2192 work \u2192 review)
2343
3273
  $ squads run engineering --task "fix CI" Conversation with founder directive
@@ -2354,37 +3284,40 @@ Examples:
2354
3284
  $ squads run --once --dry-run Preview one autopilot cycle
2355
3285
  $ squads run -i 15 --budget 50 Autopilot: 15min cycles, $50/day cap
2356
3286
  `).action(async (target, options) => {
2357
- const { runCommand } = await import("./run-I6KAXU6U.js");
3287
+ const { runCommand } = await import("./run-DOY5SGF3.js");
2358
3288
  return runCommand(target || null, { ...options, timeout: parseInt(options.timeout, 10) });
2359
3289
  });
2360
- program.command("list", { hidden: true }).description("[removed]").action(removedCommand("list", "Use: squads status"));
3290
+ program.command("list").description("List squads (alias for: squads status)").action(async () => {
3291
+ const { statusCommand } = await import("./status-PFFB2NV6.js");
3292
+ return statusCommand();
3293
+ });
2361
3294
  registerOrchestrateCommand(program);
2362
3295
  var env = program.command("env").description("View squad execution environment (MCP, skills, model, budget)").action(() => {
2363
3296
  env.outputHelp();
2364
3297
  });
2365
3298
  env.command("show <squad>").description("Show execution environment for a squad").option("--json", "Output as JSON").action(async (squad, options) => {
2366
- const { contextShowCommand } = await import("./context-GWPF4SEY.js");
3299
+ const { contextShowCommand } = await import("./context-PYTO2UQG.js");
2367
3300
  return contextShowCommand(squad, options);
2368
3301
  });
2369
3302
  env.command("prompt <squad>").description("Output ready-to-use prompt for Claude Code execution").option("-a, --agent <agent>", "Agent to execute (required)").option("--json", "Output as JSON").action(async (squad, options) => {
2370
- const { contextPromptCommand } = await import("./context-GWPF4SEY.js");
3303
+ const { contextPromptCommand } = await import("./context-PYTO2UQG.js");
2371
3304
  return contextPromptCommand(squad, options);
2372
3305
  });
2373
- var exec = program.command("exec").description("View execution history and statistics");
2374
- exec.command("list").description("List recent executions").option("-s, --squad <squad>", "Filter by squad").option("-a, --agent <agent>", "Filter by agent").option("--status <status>", "Filter by status (running, completed, failed)").option("-n, --limit <n>", "Number of executions to show", "20").option("--json", "Output as JSON").action(async (options) => {
2375
- const { execListCommand } = await import("./exec-OUXM7JBF.js");
3306
+ var exec3 = program.command("exec").description("View execution history and statistics");
3307
+ exec3.command("list").description("List recent executions").option("-s, --squad <squad>", "Filter by squad").option("-a, --agent <agent>", "Filter by agent").option("--status <status>", "Filter by status (running, completed, failed)").option("-n, --limit <n>", "Number of executions to show", "20").option("--json", "Output as JSON").action(async (options) => {
3308
+ const { execListCommand } = await import("./exec-DYLI4TXY.js");
2376
3309
  return execListCommand({ ...options, limit: parseInt(options.limit, 10) });
2377
3310
  });
2378
- exec.command("show <id>").description("Show execution details").option("--json", "Output as JSON").action(async (id, options) => {
2379
- const { execShowCommand } = await import("./exec-OUXM7JBF.js");
3311
+ exec3.command("show <id>").description("Show execution details").option("--json", "Output as JSON").action(async (id, options) => {
3312
+ const { execShowCommand } = await import("./exec-DYLI4TXY.js");
2380
3313
  return execShowCommand(id, options);
2381
3314
  });
2382
- exec.command("stats").description("Show execution statistics").option("-s, --squad <squad>", "Filter by squad").option("--json", "Output as JSON").action(async (options) => {
2383
- const { execStatsCommand } = await import("./exec-OUXM7JBF.js");
3315
+ exec3.command("stats").description("Show execution statistics").option("-s, --squad <squad>", "Filter by squad").option("--json", "Output as JSON").action(async (options) => {
3316
+ const { execStatsCommand } = await import("./exec-DYLI4TXY.js");
2384
3317
  return execStatsCommand(options);
2385
3318
  });
2386
- exec.action(async (options) => {
2387
- const { execListCommand } = await import("./exec-OUXM7JBF.js");
3319
+ exec3.action(async (options) => {
3320
+ const { execListCommand } = await import("./exec-DYLI4TXY.js");
2388
3321
  return execListCommand(options);
2389
3322
  });
2390
3323
  program.command("dashboard [name]").alias("dash").description('Show dashboards. Use "squads dash" for overview, "squads dash <name>" for specific dashboard, "squads dash --list" to see all.').option("-v, --verbose", "Show additional details").option("-c, --ceo", "Executive summary with priorities and blockers").option("-f, --full", "Include GitHub PR/issue stats (slower, ~30s)").option("-l, --list", "List available declarative dashboards").option("--view <view>", "Render specific view from dashboard").option("-j, --json", "Output as JSON").action(async (name, options) => {
@@ -2403,58 +3336,58 @@ program.command("dashboard [name]").alias("dash").description('Show dashboards.
2403
3336
  writeLine(` Dashboard "${name}" not found. Showing default dashboard.
2404
3337
  `);
2405
3338
  }
2406
- const { dashboardCommand } = await import("./dashboard-LGT2B2BL.js");
3339
+ const { dashboardCommand } = await import("./dashboard-HQIEHTZC.js");
2407
3340
  dashboardCommand({ ...options, fast: !options.full });
2408
3341
  });
2409
3342
  program.command("status [squad]").description("Show squad status and state").option("-v, --verbose", "Show detailed status").option("-j, --json", "Output as JSON").action(async (squad, options) => {
2410
- const { statusCommand } = await import("./status-AQNLDZVN.js");
3343
+ const { statusCommand } = await import("./status-PFFB2NV6.js");
2411
3344
  return statusCommand(squad, options);
2412
3345
  });
2413
3346
  program.command("context").alias("feed").description("Get business context for alignment: goals, memory, costs, activity").option("-s, --squad <squad>", "Focus on specific squad").option("-t, --topic <topic>", "Search memory for relevant context").option("-a, --agent", "Output JSON for agent consumption").option("-j, --json", "Output as JSON (alias for --agent)").option("-v, --verbose", "Show additional details").action(async (options) => {
2414
- const { contextFeedCommand } = await import("./context-feed-AJGVAR6H.js");
3347
+ const { contextFeedCommand } = await import("./context-feed-TLVZZ24S.js");
2415
3348
  return contextFeedCommand(options);
2416
3349
  });
2417
3350
  program.command("cost").description("Show cost summary (today, week, by squad)").option("-s, --squad <squad>", "Filter to specific squad").option("--json", "Output as JSON").action(async (options) => {
2418
- const { costCommand } = await import("./cost-XBCDJ7XC.js");
3351
+ const { costCommand } = await import("./cost-OALPURUQ.js");
2419
3352
  return costCommand(options);
2420
3353
  });
2421
3354
  program.command("budget").description("Check budget status for a squad").argument("<squad>", "Squad to check").option("--json", "Output as JSON").action(async (squad, options) => {
2422
- const { budgetCheckCommand } = await import("./cost-XBCDJ7XC.js");
3355
+ const { budgetCheckCommand } = await import("./cost-OALPURUQ.js");
2423
3356
  return budgetCheckCommand(squad, options);
2424
3357
  });
2425
3358
  program.command("health").description("Quick health check for all infrastructure services").option("-v, --verbose", "Show optional services").action(async (options) => {
2426
- const { healthCommand } = await import("./health-4UXN44PF.js");
3359
+ const { healthCommand } = await import("./health-ZF3HSA4W.js");
2427
3360
  return healthCommand(options);
2428
3361
  });
2429
3362
  program.command("doctor").description("Check local tools, auth, and project readiness").option("-v, --verbose", "Show install hints and optional tools").action(async (options) => {
2430
- const { doctorCommand } = await import("./doctor-XPUIIBHJ.js");
3363
+ const { doctorCommand } = await import("./doctor-TWHMR23W.js");
2431
3364
  return doctorCommand(options);
2432
3365
  });
2433
3366
  program.command("history").description("Show recent agent execution history").option("-d, --days <days>", "Days to look back", "7").option("-s, --squad <squad>", "Filter by squad").option("-v, --verbose", "Show cost and token details").option("-j, --json", "Output as JSON").action(async (options) => {
2434
- const { historyCommand } = await import("./history-ILH3SWHB.js");
3367
+ const { historyCommand } = await import("./history-WP6R5BNG.js");
2435
3368
  return historyCommand(options);
2436
3369
  });
2437
3370
  program.command("results [squad]").description("Show squad results: git activity + KPI goals vs actuals").option("-d, --days <days>", "Days to look back", "7").option("-v, --verbose", "Show detailed KPIs per goal").action(async (squad, options) => {
2438
- const { resultsCommand } = await import("./results-UECWGLTB.js");
3371
+ const { resultsCommand } = await import("./results-6TH33HPN.js");
2439
3372
  return resultsCommand({ ...options, squad });
2440
3373
  });
2441
3374
  var goal = program.command("goal").description("Manage squad goals").action(() => {
2442
3375
  goal.outputHelp();
2443
3376
  });
2444
3377
  goal.command("set <squad> <description>").description("Set a goal for a squad").option("-m, --metric <metrics...>", "Metrics to track").action(async (squad, description, options) => {
2445
- const { goalSetCommand } = await import("./goal-BVHV5573.js");
3378
+ const { goalSetCommand } = await import("./goal-XUNV3CKV.js");
2446
3379
  return goalSetCommand(squad, description, options);
2447
3380
  });
2448
3381
  goal.command("list [squad]").description("List goals for squad(s)").option("-a, --all", "Show completed goals too").option("-j, --json", "Output as JSON").action(async (squad, options) => {
2449
- const { goalListCommand } = await import("./goal-BVHV5573.js");
3382
+ const { goalListCommand } = await import("./goal-XUNV3CKV.js");
2450
3383
  return goalListCommand(squad, options);
2451
3384
  });
2452
3385
  goal.command("complete <squad> <index>").description("Mark a goal as completed").action(async (squad, index) => {
2453
- const { goalCompleteCommand } = await import("./goal-BVHV5573.js");
3386
+ const { goalCompleteCommand } = await import("./goal-XUNV3CKV.js");
2454
3387
  return goalCompleteCommand(squad, index);
2455
3388
  });
2456
3389
  goal.command("progress <squad> <index> <progress>").description("Update goal progress").action(async (squad, index, progress2) => {
2457
- const { goalProgressCommand } = await import("./goal-BVHV5573.js");
3390
+ const { goalProgressCommand } = await import("./goal-XUNV3CKV.js");
2458
3391
  return goalProgressCommand(squad, index, progress2);
2459
3392
  });
2460
3393
  var kpi = program.command("kpi").description("Track and analyze squad KPIs (defined in SQUAD.md frontmatter)").addHelpText("after", `
@@ -2468,60 +3401,60 @@ Examples:
2468
3401
  kpi.outputHelp();
2469
3402
  });
2470
3403
  kpi.command("list").description("List all KPIs across squads").option("-j, --json", "Output as JSON").action(async (options) => {
2471
- const { kpiListCommand } = await import("./kpi-RQIU7WGK.js");
3404
+ const { kpiListCommand } = await import("./kpi-VBGDO4GI.js");
2472
3405
  return kpiListCommand(options);
2473
3406
  });
2474
3407
  kpi.command("show <squad>").description("Show KPI status for a squad").option("-j, --json", "Output as JSON").action(async (squad, options) => {
2475
- const { kpiShowCommand } = await import("./kpi-RQIU7WGK.js");
3408
+ const { kpiShowCommand } = await import("./kpi-VBGDO4GI.js");
2476
3409
  return kpiShowCommand(squad, options);
2477
3410
  });
2478
3411
  kpi.command("record <squad> <kpi> <value>").description("Record a KPI value").option("-n, --note <note>", "Add a note to the record").option("-j, --json", "Output as JSON").action(async (squad, kpi2, value, options) => {
2479
- const { kpiRecordCommand } = await import("./kpi-RQIU7WGK.js");
3412
+ const { kpiRecordCommand } = await import("./kpi-VBGDO4GI.js");
2480
3413
  return kpiRecordCommand(squad, kpi2, value, options);
2481
3414
  });
2482
3415
  kpi.command("trend <squad> <kpi>").description("Show KPI trend over time").option("-p, --periods <n>", "Number of periods to show", "7").option("-j, --json", "Output as JSON").action(async (squad, kpi2, options) => {
2483
- const { kpiTrendCommand } = await import("./kpi-RQIU7WGK.js");
3416
+ const { kpiTrendCommand } = await import("./kpi-VBGDO4GI.js");
2484
3417
  return kpiTrendCommand(squad, kpi2, options);
2485
3418
  });
2486
3419
  kpi.command("insights [squad]").description("Generate insights from KPI data").option("-j, --json", "Output as JSON").action(async (squad, options) => {
2487
- const { kpiInsightsCommand } = await import("./kpi-RQIU7WGK.js");
3420
+ const { kpiInsightsCommand } = await import("./kpi-VBGDO4GI.js");
2488
3421
  return kpiInsightsCommand(squad, options);
2489
3422
  });
2490
3423
  var progress = program.command("progress").description("Track active and completed agent tasks").option("-v, --verbose", "Show more activity").action(async (options) => {
2491
- const { progressCommand } = await import("./progress-DAUZMT3N.js");
3424
+ const { progressCommand } = await import("./progress-P2EIZBKP.js");
2492
3425
  return progressCommand(options);
2493
3426
  });
2494
3427
  progress.command("start <squad> <description>").description("Register a new active task").action(async (squad, description) => {
2495
- const { progressStartCommand } = await import("./progress-DAUZMT3N.js");
3428
+ const { progressStartCommand } = await import("./progress-P2EIZBKP.js");
2496
3429
  return progressStartCommand(squad, description);
2497
3430
  });
2498
3431
  progress.command("complete <taskId>").description("Mark a task as completed").option("-f, --failed", "Mark as failed instead").action(async (taskId, options) => {
2499
- const { progressCompleteCommand } = await import("./progress-DAUZMT3N.js");
3432
+ const { progressCompleteCommand } = await import("./progress-P2EIZBKP.js");
2500
3433
  return progressCompleteCommand(taskId, options);
2501
3434
  });
2502
3435
  var feedback = program.command("feedback").description("Record and view execution feedback").action(() => {
2503
3436
  feedback.outputHelp();
2504
3437
  });
2505
3438
  feedback.command("add <squad> <rating> <feedback>").description("Add feedback for last execution (rating 1-5)").option("-l, --learning <learnings...>", "Learnings to extract").action(async (squad, rating, feedbackText, options) => {
2506
- const { feedbackAddCommand } = await import("./feedback-KNAOG5QK.js");
3439
+ const { feedbackAddCommand } = await import("./feedback-5AEACUX6.js");
2507
3440
  return feedbackAddCommand(squad, rating, feedbackText, options);
2508
3441
  });
2509
3442
  feedback.command("show <squad>").description("Show feedback history").option("-n, --limit <n>", "Number of entries to show", "5").action(async (squad, options) => {
2510
- const { feedbackShowCommand } = await import("./feedback-KNAOG5QK.js");
3443
+ const { feedbackShowCommand } = await import("./feedback-5AEACUX6.js");
2511
3444
  return feedbackShowCommand(squad, options);
2512
3445
  });
2513
3446
  feedback.command("stats").description("Show feedback summary across all squads").action(async () => {
2514
- const { feedbackStatsCommand } = await import("./feedback-KNAOG5QK.js");
3447
+ const { feedbackStatsCommand } = await import("./feedback-5AEACUX6.js");
2515
3448
  return feedbackStatsCommand();
2516
3449
  });
2517
3450
  program.command("autonomy").description("Show autonomy score and confidence metrics").option("-s, --squad <squad>", "Filter by squad").option("-p, --period <period>", "Time period: today, week, month", "today").option("-j, --json", "Output as JSON").action(async (options) => {
2518
- const { autonomyCommand } = await import("./autonomy-PSVZVX7A.js");
3451
+ const { autonomyCommand } = await import("./autonomy-GARI6J2J.js");
2519
3452
  return autonomyCommand({ squad: options.squad, period: options.period, json: options.json });
2520
3453
  });
2521
3454
  program.command("autopilot").alias("daemon").description('[deprecated] Use "squads run" instead \u2014 autopilot mode when no target given').option("-i, --interval <minutes>", "Minutes between cycles", "30").option("-p, --parallel <count>", "Max parallel agent runs", "2").option("-b, --budget <dollars>", "Max daily spend in dollars (0 = unlimited/subscription)", "0").option("--once", "Run one cycle and exit").option("--dry-run", "Show what would run without dispatching").option("-v, --verbose", "Show detailed scoring").action(async (options) => {
2522
3455
  const colors3 = colors;
2523
3456
  writeLine(` ${colors3.yellow}Note: "squads autopilot" is now "squads run" (no arguments)${RESET}`);
2524
- const { runCommand } = await import("./run-I6KAXU6U.js");
3457
+ const { runCommand } = await import("./run-DOY5SGF3.js");
2525
3458
  return runCommand(null, { interval: parseInt(options.interval || "30", 10), ...options });
2526
3459
  });
2527
3460
  program.command("stats [squad]").description("Show agent outcome scorecards: merge rate, waste, cost per outcome").option("-p, --period <period>", "Time period: 7d or 30d", "7d").option("-j, --json", "Output as JSON").action(async (squad, options) => {
@@ -2539,27 +3472,27 @@ Examples:
2539
3472
  memory.outputHelp();
2540
3473
  });
2541
3474
  memory.command("query <query>").description("Search across all squad memory").option("-s, --squad <squad>", "Limit search to specific squad").option("-a, --agent <agent>", "Limit search to specific agent").action(async (query, options) => {
2542
- const { memoryQueryCommand } = await import("./memory-T3ACCS7E.js");
3475
+ const { memoryQueryCommand } = await import("./memory-33HYD6AN.js");
2543
3476
  return memoryQueryCommand(query, options);
2544
3477
  });
2545
3478
  memory.command("read <squad>").alias("show").description("Show memory for a squad").action(async (squad, options) => {
2546
- const { memoryShowCommand } = await import("./memory-T3ACCS7E.js");
3479
+ const { memoryShowCommand } = await import("./memory-33HYD6AN.js");
2547
3480
  return memoryShowCommand(squad, options);
2548
3481
  });
2549
3482
  memory.command("write <squad> <content>").alias("update").description("Add to squad memory").option("-a, --agent <agent>", "Specific agent (default: squad-lead)").option("-t, --type <type>", "Memory type: state, learnings, feedback", "learnings").action(async (squad, content, options) => {
2550
- const { memoryUpdateCommand } = await import("./memory-T3ACCS7E.js");
3483
+ const { memoryUpdateCommand } = await import("./memory-33HYD6AN.js");
2551
3484
  return memoryUpdateCommand(squad, content, options);
2552
3485
  });
2553
3486
  memory.command("list").description("List all memory entries").action(async () => {
2554
- const { memoryListCommand } = await import("./memory-T3ACCS7E.js");
3487
+ const { memoryListCommand } = await import("./memory-33HYD6AN.js");
2555
3488
  return memoryListCommand();
2556
3489
  });
2557
3490
  memory.command("sync").description("Sync memory from git: pull remote changes, process commits, optionally push to Postgres").option("-v, --verbose", "Show detailed commit info").option("-p, --push", "Push local memory changes to remote after sync").option("--no-pull", "Skip pulling from remote").option("--postgres", "Sync cycle data (goals, feedback, KPIs, learnings) to Postgres").option("--dimensions", "Sync squad/agent definitions to Postgres dim tables").option("--learnings", "Sync learnings.md files to Postgres").option("--auto-learn", "Auto-generate learnings from session commits").action(async (options) => {
2558
- const { syncCommand } = await import("./sync-ZI3MHA4G.js");
3491
+ const { syncCommand } = await import("./sync-FR6LQJ4C.js");
2559
3492
  return syncCommand({ verbose: options.verbose, push: options.push, pull: options.pull, postgres: options.postgres, dimensions: options.dimensions, learnings: options.learnings, autoLearn: options.autoLearn });
2560
3493
  });
2561
3494
  memory.command("search <query>").description("Search stored conversations (requires authentication: squads login)").option("-l, --limit <limit>", "Number of results", "10").option("-r, --role <role>", "Filter by role: user, assistant, thinking").option("-i, --importance <importance>", "Filter by importance: low, normal, high").action(async (query, opts) => {
2562
- const { memorySearchCommand } = await import("./memory-T3ACCS7E.js");
3495
+ const { memorySearchCommand } = await import("./memory-33HYD6AN.js");
2563
3496
  return memorySearchCommand(query, {
2564
3497
  limit: parseInt(opts.limit, 10),
2565
3498
  role: opts.role,
@@ -2567,7 +3500,7 @@ memory.command("search <query>").description("Search stored conversations (requi
2567
3500
  });
2568
3501
  });
2569
3502
  memory.command("extract").description("Extract memories from recent conversations into Engram").option("-s, --session <session>", "Extract specific session only").option("-h, --hours <hours>", "Look back period in hours", "24").option("-d, --dry-run", "Preview without sending to Engram").action(async (opts) => {
2570
- const { memoryExtractCommand } = await import("./memory-T3ACCS7E.js");
3503
+ const { memoryExtractCommand } = await import("./memory-33HYD6AN.js");
2571
3504
  return memoryExtractCommand({
2572
3505
  session: opts.session,
2573
3506
  hours: parseInt(opts.hours, 10),
@@ -2575,20 +3508,20 @@ memory.command("extract").description("Extract memories from recent conversation
2575
3508
  });
2576
3509
  });
2577
3510
  program.command("learn <insight>").description("Capture a learning for future sessions").option("-s, --squad <squad>", "Squad to associate learning with").option("-c, --category <category>", "Category: success, failure, pattern, tip").option("-t, --tags <tags>", "Comma-separated tags").option("--context <context>", "Additional context").action(async (insight, options) => {
2578
- const { learnCommand } = await import("./learn-OIFUVZAS.js");
3511
+ const { learnCommand } = await import("./learn-C4B2PQ5J.js");
2579
3512
  return learnCommand(insight, options);
2580
3513
  });
2581
3514
  var learn = program.command("learnings").description("View and search learnings");
2582
3515
  learn.command("show <squad>").description("Show learnings for a squad").option("-n, --limit <n>", "Number to show", "10").option("-c, --category <category>", "Filter by category").option("--tag <tag>", "Filter by tag").action(async (squad, options) => {
2583
- const { learnShowCommand } = await import("./learn-OIFUVZAS.js");
3516
+ const { learnShowCommand } = await import("./learn-C4B2PQ5J.js");
2584
3517
  return learnShowCommand(squad, options);
2585
3518
  });
2586
3519
  learn.command("search <query>").description("Search learnings across all squads").option("-n, --limit <n>", "Max results", "10").action(async (query, options) => {
2587
- const { learnSearchCommand } = await import("./learn-OIFUVZAS.js");
3520
+ const { learnSearchCommand } = await import("./learn-C4B2PQ5J.js");
2588
3521
  return learnSearchCommand(query, options);
2589
3522
  });
2590
3523
  program.command("sync").description("Git memory synchronization (Postgres sync optional)").option("-v, --verbose", "Show detailed commit info").option("-p, --push", "Push local memory changes to remote after sync").option("--no-pull", "Skip pulling from remote").option("--postgres", "Sync cycle data to Postgres").action(async (options) => {
2591
- const { syncCommand } = await import("./sync-ZI3MHA4G.js");
3524
+ const { syncCommand } = await import("./sync-FR6LQJ4C.js");
2592
3525
  return syncCommand({ verbose: options.verbose, push: options.push, pull: options.pull, postgres: options.postgres });
2593
3526
  });
2594
3527
  registerTriggerCommand(program);
@@ -2610,8 +3543,8 @@ sessions.command("summary").description("Show pretty session summary (auto-detec
2610
3543
  const { buildCurrentSessionSummary, sessionsSummaryCommand } = await import("./sessions-CK25VGPL.js");
2611
3544
  let data;
2612
3545
  if (options.file) {
2613
- const { readFileSync: readFileSync7 } = await import("fs");
2614
- data = JSON.parse(readFileSync7(options.file, "utf-8"));
3546
+ const { readFileSync: readFileSync9 } = await import("fs");
3547
+ data = JSON.parse(readFileSync9(options.file, "utf-8"));
2615
3548
  } else if (options.data) {
2616
3549
  data = JSON.parse(options.data);
2617
3550
  } else if (!process.stdin.isTTY) {
@@ -2650,22 +3583,27 @@ program.command("detect-squad").description("Detect current squad based on cwd (
2650
3583
  return detectSquadCommand();
2651
3584
  });
2652
3585
  program.command("login").description("Log in to Squads (Pro & Enterprise)").action(async () => {
2653
- const { loginCommand } = await import("./login-DXZANWZY.js");
3586
+ const { loginCommand } = await import("./login-F6ITE7PR.js");
2654
3587
  return loginCommand();
2655
3588
  });
2656
3589
  program.command("logout").description("Log out from Squads").action(async () => {
2657
- const { logoutCommand } = await import("./login-DXZANWZY.js");
3590
+ const { logoutCommand } = await import("./login-F6ITE7PR.js");
2658
3591
  return logoutCommand();
2659
3592
  });
2660
3593
  program.command("whoami").description("Show current logged in user").action(async () => {
2661
- const { whoamiCommand } = await import("./login-DXZANWZY.js");
3594
+ const { whoamiCommand } = await import("./login-F6ITE7PR.js");
2662
3595
  return whoamiCommand();
2663
3596
  });
2664
3597
  registerEvalCommand(program);
2665
3598
  registerDeployCommand(program);
2666
3599
  registerCognitionCommand(program);
3600
+ registerCatalogCommands(program);
3601
+ registerReleaseCommands(program);
3602
+ registerObservabilityCommands(program);
3603
+ registerTierCommand(program);
3604
+ registerServicesCommands(program);
2667
3605
  program.command("providers").description("Show available LLM CLI providers (claude, gemini, codex, etc.)").option("-j, --json", "Output as JSON").action(async (options) => {
2668
- const { providersCommand } = await import("./providers-3P5D2XL5.js");
3606
+ const { providersCommand } = await import("./providers-LE744DM6.js");
2669
3607
  return providersCommand(options);
2670
3608
  });
2671
3609
  program.command("update").description("Check for and install updates").option("-y, --yes", "Auto-confirm update without prompting").option("-c, --check", "Check for updates without installing").action(async (options) => {