swarmdo 1.54.1 → 1.58.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 (188) hide show
  1. package/.claude/helpers/statusline.cjs +17 -11
  2. package/README.md +4 -3
  3. package/package.json +1 -1
  4. package/v3/@swarmdo/cli/dist/src/command-usage/usage.d.ts +74 -0
  5. package/v3/@swarmdo/cli/dist/src/command-usage/usage.js +161 -0
  6. package/v3/@swarmdo/cli/dist/src/commands/commands.d.ts +19 -0
  7. package/v3/@swarmdo/cli/dist/src/commands/commands.js +107 -0
  8. package/v3/@swarmdo/cli/dist/src/commands/hooks.d.ts +26 -0
  9. package/v3/@swarmdo/cli/dist/src/commands/hooks.js +96 -24
  10. package/v3/@swarmdo/cli/dist/src/commands/index.js +7 -3
  11. package/v3/@swarmdo/cli/dist/src/commands/swarm.js +5 -0
  12. package/v3/@swarmdo/cli/dist/src/commands/usage.js +57 -1
  13. package/v3/@swarmdo/cli/dist/src/comms/store.d.ts +11 -1
  14. package/v3/@swarmdo/cli/dist/src/comms/store.js +16 -2
  15. package/v3/@swarmdo/cli/dist/src/init/statusline-generator.d.ts +1 -1
  16. package/v3/@swarmdo/cli/dist/src/init/statusline-generator.js +17 -11
  17. package/v3/@swarmdo/cli/dist/src/integrations/integrations.js +19 -8
  18. package/v3/@swarmdo/cli/dist/src/mcp-tools/comms-tools.js +4 -4
  19. package/v3/@swarmdo/cli/dist/src/mcp-tools/swarm-tools.js +2 -0
  20. package/v3/@swarmdo/cli/dist/src/usage/transcript-friction.d.ts +77 -0
  21. package/v3/@swarmdo/cli/dist/src/usage/transcript-friction.js +151 -0
  22. package/v3/@swarmdo/cli/package.json +1 -1
  23. package/v3/@swarmdo/cli-core/dist/src/index.js +1 -1
  24. package/v3/@swarmdo/codex/dist/cli.js +0 -0
  25. package/v3/@swarmdo/hooks/dist/cli/guidance-cli.js +0 -0
  26. package/v3/@swarmdo/hooks/dist/statusline/index.d.ts +3 -3
  27. package/v3/@swarmdo/hooks/dist/statusline/index.js +3 -3
  28. package/v3/@swarmdo/integration/dist/__tests__/agentic-flow-agent.test.js +4 -1
  29. package/v3/@swarmdo/neural/dist/flash-attention.d.ts +1 -1
  30. package/v3/@swarmdo/neural/dist/flash-attention.js +1 -1
  31. package/v3/@swarmdo/plugin-agent-federation/dist/plugin.js +1 -1
  32. package/v3/@swarmdo/plugin-agent-federation/dist/transport/midstream-aware-loader.js +2 -2
  33. package/v3/@swarmdo/providers/dist/swarmvector-provider.d.ts +1 -1
  34. package/v3/@swarmdo/providers/dist/swarmvector-provider.js +1 -1
  35. package/v3/@swarmdo/security/dist/input-validator.d.ts +6 -6
  36. package/v3/@swarmdo/shared/dist/hooks/safety/git-commit.js +1 -1
  37. package/v3/@swarmdo/shared/dist/mcp/transport/http.js +8 -1
  38. package/.claude/settings.local.json +0 -7
  39. package/v3/@swarmdo/plugin-iot-cognitum/dist/application/index.d.ts +0 -2
  40. package/v3/@swarmdo/plugin-iot-cognitum/dist/application/index.js +0 -2
  41. package/v3/@swarmdo/plugin-iot-cognitum/dist/application/iot-coordinator.d.ts +0 -138
  42. package/v3/@swarmdo/plugin-iot-cognitum/dist/application/iot-coordinator.js +0 -418
  43. package/v3/@swarmdo/plugin-iot-cognitum/dist/bin.d.ts +0 -15
  44. package/v3/@swarmdo/plugin-iot-cognitum/dist/bin.js +0 -240
  45. package/v3/@swarmdo/plugin-iot-cognitum/dist/cli-commands.d.ts +0 -7
  46. package/v3/@swarmdo/plugin-iot-cognitum/dist/cli-commands.js +0 -508
  47. package/v3/@swarmdo/plugin-iot-cognitum/dist/domain/entities/device-agent.d.ts +0 -54
  48. package/v3/@swarmdo/plugin-iot-cognitum/dist/domain/entities/device-agent.js +0 -2
  49. package/v3/@swarmdo/plugin-iot-cognitum/dist/domain/entities/device-fleet.d.ts +0 -46
  50. package/v3/@swarmdo/plugin-iot-cognitum/dist/domain/entities/device-fleet.js +0 -2
  51. package/v3/@swarmdo/plugin-iot-cognitum/dist/domain/entities/device-trust-level.d.ts +0 -18
  52. package/v3/@swarmdo/plugin-iot-cognitum/dist/domain/entities/device-trust-level.js +0 -28
  53. package/v3/@swarmdo/plugin-iot-cognitum/dist/domain/entities/index.d.ts +0 -5
  54. package/v3/@swarmdo/plugin-iot-cognitum/dist/domain/entities/index.js +0 -2
  55. package/v3/@swarmdo/plugin-iot-cognitum/dist/domain/entities/telemetry.d.ts +0 -35
  56. package/v3/@swarmdo/plugin-iot-cognitum/dist/domain/entities/telemetry.js +0 -2
  57. package/v3/@swarmdo/plugin-iot-cognitum/dist/domain/repositories/device-repository.d.ts +0 -11
  58. package/v3/@swarmdo/plugin-iot-cognitum/dist/domain/repositories/device-repository.js +0 -2
  59. package/v3/@swarmdo/plugin-iot-cognitum/dist/domain/repositories/fleet-repository.d.ts +0 -9
  60. package/v3/@swarmdo/plugin-iot-cognitum/dist/domain/repositories/fleet-repository.js +0 -2
  61. package/v3/@swarmdo/plugin-iot-cognitum/dist/domain/repositories/index.d.ts +0 -5
  62. package/v3/@swarmdo/plugin-iot-cognitum/dist/domain/repositories/index.js +0 -2
  63. package/v3/@swarmdo/plugin-iot-cognitum/dist/domain/repositories/telemetry-repository.d.ts +0 -12
  64. package/v3/@swarmdo/plugin-iot-cognitum/dist/domain/repositories/telemetry-repository.js +0 -2
  65. package/v3/@swarmdo/plugin-iot-cognitum/dist/domain/repositories/trust-history-repository.d.ts +0 -19
  66. package/v3/@swarmdo/plugin-iot-cognitum/dist/domain/repositories/trust-history-repository.js +0 -2
  67. package/v3/@swarmdo/plugin-iot-cognitum/dist/domain/services/anomaly-detection-service.d.ts +0 -44
  68. package/v3/@swarmdo/plugin-iot-cognitum/dist/domain/services/anomaly-detection-service.js +0 -117
  69. package/v3/@swarmdo/plugin-iot-cognitum/dist/domain/services/device-lifecycle-service.d.ts +0 -70
  70. package/v3/@swarmdo/plugin-iot-cognitum/dist/domain/services/device-lifecycle-service.js +0 -194
  71. package/v3/@swarmdo/plugin-iot-cognitum/dist/domain/services/firmware-orchestration-service.d.ts +0 -69
  72. package/v3/@swarmdo/plugin-iot-cognitum/dist/domain/services/firmware-orchestration-service.js +0 -139
  73. package/v3/@swarmdo/plugin-iot-cognitum/dist/domain/services/fleet-topology-service.d.ts +0 -34
  74. package/v3/@swarmdo/plugin-iot-cognitum/dist/domain/services/fleet-topology-service.js +0 -101
  75. package/v3/@swarmdo/plugin-iot-cognitum/dist/domain/services/index.d.ts +0 -10
  76. package/v3/@swarmdo/plugin-iot-cognitum/dist/domain/services/index.js +0 -10
  77. package/v3/@swarmdo/plugin-iot-cognitum/dist/domain/services/mesh-service.d.ts +0 -64
  78. package/v3/@swarmdo/plugin-iot-cognitum/dist/domain/services/mesh-service.js +0 -70
  79. package/v3/@swarmdo/plugin-iot-cognitum/dist/domain/services/sona-integration-service.d.ts +0 -44
  80. package/v3/@swarmdo/plugin-iot-cognitum/dist/domain/services/sona-integration-service.js +0 -79
  81. package/v3/@swarmdo/plugin-iot-cognitum/dist/domain/services/telemetry-ingestion-service.d.ts +0 -37
  82. package/v3/@swarmdo/plugin-iot-cognitum/dist/domain/services/telemetry-ingestion-service.js +0 -39
  83. package/v3/@swarmdo/plugin-iot-cognitum/dist/domain/services/telemetry-service.d.ts +0 -67
  84. package/v3/@swarmdo/plugin-iot-cognitum/dist/domain/services/telemetry-service.js +0 -58
  85. package/v3/@swarmdo/plugin-iot-cognitum/dist/domain/services/witness-verification-service.d.ts +0 -45
  86. package/v3/@swarmdo/plugin-iot-cognitum/dist/domain/services/witness-verification-service.js +0 -63
  87. package/v3/@swarmdo/plugin-iot-cognitum/dist/index.d.ts +0 -26
  88. package/v3/@swarmdo/plugin-iot-cognitum/dist/index.js +0 -17
  89. package/v3/@swarmdo/plugin-iot-cognitum/dist/infrastructure/agentdb-telemetry-repository.d.ts +0 -51
  90. package/v3/@swarmdo/plugin-iot-cognitum/dist/infrastructure/agentdb-telemetry-repository.js +0 -110
  91. package/v3/@swarmdo/plugin-iot-cognitum/dist/infrastructure/in-memory-device-repository.d.ts +0 -13
  92. package/v3/@swarmdo/plugin-iot-cognitum/dist/infrastructure/in-memory-device-repository.js +0 -25
  93. package/v3/@swarmdo/plugin-iot-cognitum/dist/infrastructure/in-memory-fleet-repository.d.ts +0 -11
  94. package/v3/@swarmdo/plugin-iot-cognitum/dist/infrastructure/in-memory-fleet-repository.js +0 -19
  95. package/v3/@swarmdo/plugin-iot-cognitum/dist/infrastructure/in-memory-trust-history-repository.d.ts +0 -11
  96. package/v3/@swarmdo/plugin-iot-cognitum/dist/infrastructure/in-memory-trust-history-repository.js +0 -27
  97. package/v3/@swarmdo/plugin-iot-cognitum/dist/infrastructure/index.d.ts +0 -6
  98. package/v3/@swarmdo/plugin-iot-cognitum/dist/infrastructure/index.js +0 -6
  99. package/v3/@swarmdo/plugin-iot-cognitum/dist/infrastructure/seed-client-factory.d.ts +0 -41
  100. package/v3/@swarmdo/plugin-iot-cognitum/dist/infrastructure/seed-client-factory.js +0 -64
  101. package/v3/@swarmdo/plugin-iot-cognitum/dist/mcp-tools.d.ts +0 -8
  102. package/v3/@swarmdo/plugin-iot-cognitum/dist/mcp-tools.js +0 -703
  103. package/v3/@swarmdo/plugin-iot-cognitum/dist/plugin.d.ts +0 -23
  104. package/v3/@swarmdo/plugin-iot-cognitum/dist/plugin.js +0 -239
  105. package/v3/@swarmdo/plugin-iot-cognitum/dist/workers/anomaly-scan-worker.d.ts +0 -17
  106. package/v3/@swarmdo/plugin-iot-cognitum/dist/workers/anomaly-scan-worker.js +0 -42
  107. package/v3/@swarmdo/plugin-iot-cognitum/dist/workers/firmware-watch-worker.d.ts +0 -18
  108. package/v3/@swarmdo/plugin-iot-cognitum/dist/workers/firmware-watch-worker.js +0 -45
  109. package/v3/@swarmdo/plugin-iot-cognitum/dist/workers/health-probe-worker.d.ts +0 -19
  110. package/v3/@swarmdo/plugin-iot-cognitum/dist/workers/health-probe-worker.js +0 -50
  111. package/v3/@swarmdo/plugin-iot-cognitum/dist/workers/mesh-sync-worker.d.ts +0 -19
  112. package/v3/@swarmdo/plugin-iot-cognitum/dist/workers/mesh-sync-worker.js +0 -47
  113. package/v3/@swarmdo/plugin-iot-cognitum/dist/workers/telemetry-ingest-worker.d.ts +0 -17
  114. package/v3/@swarmdo/plugin-iot-cognitum/dist/workers/telemetry-ingest-worker.js +0 -40
  115. package/v3/@swarmdo/plugin-iot-cognitum/dist/workers/witness-audit-worker.d.ts +0 -18
  116. package/v3/@swarmdo/plugin-iot-cognitum/dist/workers/witness-audit-worker.js +0 -51
  117. package/v3/@swarmdo/testing/dist/fixtures/agent-fixtures.d.ts +0 -214
  118. package/v3/@swarmdo/testing/dist/fixtures/agent-fixtures.js +0 -595
  119. package/v3/@swarmdo/testing/dist/fixtures/agents.d.ts +0 -76
  120. package/v3/@swarmdo/testing/dist/fixtures/agents.js +0 -158
  121. package/v3/@swarmdo/testing/dist/fixtures/configurations.d.ts +0 -157
  122. package/v3/@swarmdo/testing/dist/fixtures/configurations.js +0 -337
  123. package/v3/@swarmdo/testing/dist/fixtures/index.d.ts +0 -10
  124. package/v3/@swarmdo/testing/dist/fixtures/index.js +0 -17
  125. package/v3/@swarmdo/testing/dist/fixtures/mcp-fixtures.d.ts +0 -329
  126. package/v3/@swarmdo/testing/dist/fixtures/mcp-fixtures.js +0 -714
  127. package/v3/@swarmdo/testing/dist/fixtures/memory-entries.d.ts +0 -159
  128. package/v3/@swarmdo/testing/dist/fixtures/memory-entries.js +0 -262
  129. package/v3/@swarmdo/testing/dist/fixtures/memory-fixtures.d.ts +0 -290
  130. package/v3/@swarmdo/testing/dist/fixtures/memory-fixtures.js +0 -547
  131. package/v3/@swarmdo/testing/dist/fixtures/swarm-fixtures.d.ts +0 -289
  132. package/v3/@swarmdo/testing/dist/fixtures/swarm-fixtures.js +0 -534
  133. package/v3/@swarmdo/testing/dist/fixtures/tasks.d.ts +0 -106
  134. package/v3/@swarmdo/testing/dist/fixtures/tasks.js +0 -229
  135. package/v3/@swarmdo/testing/dist/helpers/assertion-helpers.d.ts +0 -213
  136. package/v3/@swarmdo/testing/dist/helpers/assertion-helpers.js +0 -435
  137. package/v3/@swarmdo/testing/dist/helpers/assertions.d.ts +0 -135
  138. package/v3/@swarmdo/testing/dist/helpers/assertions.js +0 -217
  139. package/v3/@swarmdo/testing/dist/helpers/create-mock.d.ts +0 -96
  140. package/v3/@swarmdo/testing/dist/helpers/create-mock.js +0 -164
  141. package/v3/@swarmdo/testing/dist/helpers/index.d.ts +0 -14
  142. package/v3/@swarmdo/testing/dist/helpers/index.js +0 -22
  143. package/v3/@swarmdo/testing/dist/helpers/mock-factory.d.ts +0 -323
  144. package/v3/@swarmdo/testing/dist/helpers/mock-factory.js +0 -350
  145. package/v3/@swarmdo/testing/dist/helpers/setup-teardown.d.ts +0 -271
  146. package/v3/@swarmdo/testing/dist/helpers/setup-teardown.js +0 -446
  147. package/v3/@swarmdo/testing/dist/helpers/swarm-instance.d.ts +0 -142
  148. package/v3/@swarmdo/testing/dist/helpers/swarm-instance.js +0 -205
  149. package/v3/@swarmdo/testing/dist/helpers/test-application.d.ts +0 -190
  150. package/v3/@swarmdo/testing/dist/helpers/test-application.js +0 -138
  151. package/v3/@swarmdo/testing/dist/helpers/test-utils.d.ts +0 -274
  152. package/v3/@swarmdo/testing/dist/helpers/test-utils.js +0 -456
  153. package/v3/@swarmdo/testing/dist/index.d.ts +0 -42
  154. package/v3/@swarmdo/testing/dist/index.js +0 -66
  155. package/v3/@swarmdo/testing/dist/mocks/index.d.ts +0 -8
  156. package/v3/@swarmdo/testing/dist/mocks/index.js +0 -10
  157. package/v3/@swarmdo/testing/dist/mocks/mock-mcp-client.d.ts +0 -206
  158. package/v3/@swarmdo/testing/dist/mocks/mock-mcp-client.js +0 -575
  159. package/v3/@swarmdo/testing/dist/mocks/mock-services.d.ts +0 -287
  160. package/v3/@swarmdo/testing/dist/mocks/mock-services.js +0 -563
  161. package/v3/@swarmdo/testing/dist/regression/api-contract.d.ts +0 -109
  162. package/v3/@swarmdo/testing/dist/regression/api-contract.js +0 -374
  163. package/v3/@swarmdo/testing/dist/regression/index.d.ts +0 -18
  164. package/v3/@swarmdo/testing/dist/regression/index.js +0 -18
  165. package/v3/@swarmdo/testing/dist/regression/integration-regression.d.ts +0 -67
  166. package/v3/@swarmdo/testing/dist/regression/integration-regression.js +0 -334
  167. package/v3/@swarmdo/testing/dist/regression/performance-baseline.d.ts +0 -106
  168. package/v3/@swarmdo/testing/dist/regression/performance-baseline.js +0 -268
  169. package/v3/@swarmdo/testing/dist/regression/regression-runner.d.ts +0 -124
  170. package/v3/@swarmdo/testing/dist/regression/regression-runner.js +0 -227
  171. package/v3/@swarmdo/testing/dist/regression/security-regression.d.ts +0 -73
  172. package/v3/@swarmdo/testing/dist/regression/security-regression.js +0 -258
  173. package/v3/@swarmdo/testing/dist/setup.d.ts +0 -43
  174. package/v3/@swarmdo/testing/dist/setup.js +0 -91
  175. package/v3/@swarmdo/testing/dist/v2-compat/api-compat.test.d.ts +0 -10
  176. package/v3/@swarmdo/testing/dist/v2-compat/api-compat.test.js +0 -433
  177. package/v3/@swarmdo/testing/dist/v2-compat/cli-compat.test.d.ts +0 -10
  178. package/v3/@swarmdo/testing/dist/v2-compat/cli-compat.test.js +0 -352
  179. package/v3/@swarmdo/testing/dist/v2-compat/compatibility-validator.d.ts +0 -206
  180. package/v3/@swarmdo/testing/dist/v2-compat/compatibility-validator.js +0 -839
  181. package/v3/@swarmdo/testing/dist/v2-compat/hooks-compat.test.d.ts +0 -10
  182. package/v3/@swarmdo/testing/dist/v2-compat/hooks-compat.test.js +0 -428
  183. package/v3/@swarmdo/testing/dist/v2-compat/index.d.ts +0 -38
  184. package/v3/@swarmdo/testing/dist/v2-compat/index.js +0 -41
  185. package/v3/@swarmdo/testing/dist/v2-compat/mcp-compat.test.d.ts +0 -10
  186. package/v3/@swarmdo/testing/dist/v2-compat/mcp-compat.test.js +0 -419
  187. package/v3/@swarmdo/testing/dist/v2-compat/report-generator.d.ts +0 -34
  188. package/v3/@swarmdo/testing/dist/v2-compat/report-generator.js +0 -372
@@ -105,7 +105,7 @@ function resolveCliBin() {
105
105
  ];
106
106
  try {
107
107
  const binDir = path.dirname(process.execPath);
108
- const globalModuleDirs = [path.join(binDir, '..', 'lib', 'node_modules'), path.join(binDir, 'node_modules')];
108
+ const globalModuleDirs = [path.join(binDir, '..', 'lib', 'node_modules'), path.join(binDir, 'node_modules'), '/opt/homebrew/lib/node_modules', '/usr/local/lib/node_modules'];
109
109
  for (const prefix of [process.env.npm_config_prefix, process.env.PREFIX, path.join(home, '.npm-global')]) {
110
110
  if (prefix) globalModuleDirs.push(path.join(prefix, 'lib', 'node_modules'));
111
111
  }
@@ -148,6 +148,13 @@ function writeCache(data) {
148
148
  * and only counted ADRs in v3/implementation/adrs/ (missed v3/docs/adr/).
149
149
  */
150
150
  function getStatuslineData() {
151
+ // SWARMDO_STATUSLINE_NO_CLI: skip the CLI-delegation fork and render from local
152
+ // reads + stdin only. A cold render otherwise forks the hooks-statusline CLI
153
+ // (now more reachable via the global-node_modules probes below), and that fork
154
+ // can disturb the stdin cost payload; skipping it keeps renders fast, hermetic,
155
+ // and subprocess-free. Set by the statusline tests; usable by anyone who wants
156
+ // a no-fork statusline.
157
+ if (process.env.SWARMDO_STATUSLINE_NO_CLI) return buildLocalFallback();
151
158
  const cached = readCache();
152
159
  if (cached) return cached;
153
160
 
@@ -324,8 +331,8 @@ function buildLocalFallback() {
324
331
  user: { name: 'user', gitBranch: '', modelName: 'Claude Code' },
325
332
  v3Progress: { domainsCompleted: 0, totalDomains: 5, dddProgress: 0, patternsLearned: 0, sessionsCompleted: 0 },
326
333
  security: { status: 'NONE', critical: 0, high: 0, total: 0 },
327
- swarm: { activeAgents: 0, maxAgents: CONFIG.maxAgents, coordinationActive: false },
328
- system: { memoryMB: memMB, contextPct: 0, intelligencePct: 0, subAgents: 0 },
334
+ swarm: { activeSwarms: 0, activeAgents: 0, coordinationActive: false },
335
+ system: { memoryMB: memMB, contextPct: 0, intelligencePct: 0 },
329
336
  lastUpdated: new Date().toISOString(),
330
337
  });
331
338
  }
@@ -515,7 +522,7 @@ function getCostFromStdin() {
515
522
  // misses, the displayed version is meaningful (matches what the user
516
523
  // installed), not a stale hard-coded string.
517
524
  function getPkgVersion() {
518
- let ver = '1.19.0';
525
+ let ver = '1.58.4';
519
526
  try {
520
527
  const home = os.homedir();
521
528
  const pkgPaths = [
@@ -531,7 +538,7 @@ function getPkgVersion() {
531
538
  // (bin/node_modules) layouts.
532
539
  try {
533
540
  const binDir = path.dirname(process.execPath);
534
- const globalModuleDirs = [path.join(binDir, '..', 'lib', 'node_modules'), path.join(binDir, 'node_modules')];
541
+ const globalModuleDirs = [path.join(binDir, '..', 'lib', 'node_modules'), path.join(binDir, 'node_modules'), '/opt/homebrew/lib/node_modules', '/usr/local/lib/node_modules'];
535
542
  // #2221 follow-up: a custom npm prefix (e.g. ~/.npm-global) is decoupled from
536
543
  // the node binary location, so the binDir-derived probes above all miss. Also
537
544
  // probe the npm prefix from the environment and the common ~/.npm-global default.
@@ -585,12 +592,11 @@ function generateStatusline() {
585
592
  const totalDomains = progress.totalDomains || 5;
586
593
  const dddProgress = progress.dddProgress || 0;
587
594
  const patternsLearned = progress.patternsLearned || 0;
595
+ const activeSwarms = swarm.activeSwarms || 0;
588
596
  const activeAgents = swarm.activeAgents || 0;
589
- const maxAgents = swarm.maxAgents || CONFIG.maxAgents;
590
597
  const coordinationActive = swarm.coordinationActive || false;
591
598
  const intelligencePct = system.intelligencePct || 0;
592
599
  const memoryMB = system.memoryMB || 0;
593
- const subAgents = system.subAgents || 0;
594
600
  const secCritHigh = (security.critical || 0) + (security.high || 0);
595
601
  const secStatus = security.status || 'NONE';
596
602
  const secLabel = secStatus === 'VULN' ? 'sec ' + secCritHigh + '!' : secStatus === 'CLEAN' ? 'sec ✓' : secStatus === 'STALE' ? 'sec stale' : 'sec —';
@@ -657,16 +663,16 @@ function generateStatusline() {
657
663
  );
658
664
 
659
665
  // Line 2: Swarm + Hooks + CVE + Memory + Intelligence
660
- const swarmInd = coordinationActive ? c.brightGreen + '◉' + c.reset : c.dim + '○' + c.reset;
661
- const agentsColor = activeAgents > 0 ? c.brightGreen : c.red;
666
+ const swarmsColor = activeSwarms > 0 ? c.brightGreen : c.dim;
667
+ const agentsColor = activeAgents > 0 ? c.brightGreen : c.dim;
662
668
  const secIcon = secStatus === 'CLEAN' ? '🟢' : secStatus === 'STALE' ? '🟡' : (secStatus === 'NONE' ? '⚪' : '🔴');
663
669
  const secColor = secStatus === 'CLEAN' ? c.brightGreen : secStatus === 'STALE' ? c.brightYellow : (secStatus === 'NONE' ? c.dim : c.brightRed);
664
670
  const hooksColor = hooksEnabled > 0 ? c.brightGreen : c.dim;
665
671
  const intellColor = intelligencePct >= 80 ? c.brightGreen : intelligencePct >= 40 ? c.brightYellow : c.dim;
666
672
 
667
673
  if (seg('swarm')) lines.push(
668
- c.brightYellow + '🤖 Swarm' + c.reset + ' ' + swarmInd + ' [' + agentsColor + String(activeAgents).padStart(2) + c.reset + '/' + c.brightWhite + maxAgents + c.reset + '] ' +
669
- c.brightPurple + '👥 ' + subAgents + c.reset + ' ' +
674
+ c.brightYellow + '🐝 Swarms' + c.reset + ' ' + swarmsColor + activeSwarms + c.reset + ' ' +
675
+ c.brightYellow + '🤖 Agents' + c.reset + ' ' + agentsColor + activeAgents + c.reset + ' ' +
670
676
  c.brightBlue + '🪝 ' + hooksColor + hooksEnabled + c.reset + '/' + c.brightWhite + hooksTotal + c.reset + ' ' +
671
677
  secIcon + ' ' + secColor + secLabel + c.reset + ' ' +
672
678
  c.brightCyan + '💾 ' + memoryMB + 'MB' + c.reset + ' ' +
package/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  [![swarmdo](swarmdo/assets/brand/logo-full.svg)](https://swarmdo.com)
4
4
 
5
- [![npm version (swarmdo)](https://img.shields.io/badge/npx%20swarmdo-v1.54.1-cb3837?style=for-the-badge&logo=npm&logoColor=white)](https://github.com/SwarmDo/swarmdo/releases)
5
+ [![npm version (swarmdo)](https://img.shields.io/badge/npx%20swarmdo-v1.58.6-cb3837?style=for-the-badge&logo=npm&logoColor=white)](https://github.com/SwarmDo/swarmdo/releases)
6
6
  [![MIT License](https://img.shields.io/badge/License-MIT-yellow?style=for-the-badge)](https://github.com/SwarmDo/swarmdo/blob/main/LICENSE)
7
7
  [![Website](https://img.shields.io/badge/swarmdo.com-e2a33c?style=for-the-badge&logoColor=black)](https://swarmdo.com)
8
8
  [![Star on GitHub](https://img.shields.io/github/stars/SwarmDo/swarmdo?style=for-the-badge&logo=github&color=gold)](https://github.com/SwarmDo/swarmdo)
@@ -271,7 +271,7 @@ The recent release train added a full day-to-day operations layer around the swa
271
271
 
272
272
  | Command | What it does |
273
273
  |---------|-------------|
274
- | `swarmdo usage` (alias `cost`) | Claude Code **spend analytics** from your local transcripts — `daily`, `weekly`, `monthly` (with a month-end spend projection), `models`, `projects`, `sessions`, live 5-hour `blocks` burn, `errors` (tool-failure analytics), `cache` (prompt-cache efficiency + $ saved), `diff` (period-over-period comparison with per-model movers), `reflect` (a wrapped-style retrospective — busiest day, streak, top models/projects, peak hour, delegation ratio — with a shareable `--html` dashboard), and `limits` (an official-quota **exhaustion forecaster** over Claude Code's `rate_limits`); the standard views take `--csv` for spreadsheet export |
274
+ | `swarmdo usage` (alias `cost`) | Claude Code **spend analytics** from your local transcripts — `daily`, `weekly`, `monthly` (with a month-end spend projection), `models`, `projects`, `sessions`, live 5-hour `blocks` burn, `errors` (tool-failure analytics), `friction` (how often you interrupt Claude + which tool was running + dominant error categories), `cache` (prompt-cache efficiency + $ saved), `diff` (period-over-period comparison with per-model movers), `reflect` (a wrapped-style retrospective — busiest day, streak, top models/projects, peak hour, delegation ratio — with a shareable `--html` dashboard), and `limits` (an official-quota **exhaustion forecaster** over Claude Code's `rate_limits`); the standard views take `--csv` for spreadsheet export |
275
275
  | `swarmdo usage guard` | **Budget policy** — limits for the active 5h block / today / month via flags or `SWARMDO_GUARD_*` env → ok / warn / over; `--strict` exits 1, safe for CI gates and Stop hooks |
276
276
  | `swarmdo hud` | **One-screen ops HUD** — 5h block burn, task readiness, daemon workers, memory snapshots (`--watch`, `--json`) |
277
277
  | `swarmdo repair` (alias `tdd-repair`) | **Test-Driven Repair** — a bounded, budget-capped headless `claude` loop that fixes source until a failing test passes; dry-run unless `--confirm` |
@@ -293,6 +293,7 @@ The recent release train added a full day-to-day operations layer around the swa
293
293
  | `swarmdo ownership` | **Who owns each file, and what breaks if they leave** — a per-file knowledge map + bus factor from git history: the dominant author, ownership concentration, and the fewest authors whose churn clears 50% (a lone owner is flagged ⚠ key-person), plus a repo-wide truck factor. `--since`, `--min-churn`, `--top`, `--csv`, `--format json`. code-maat main-dev / CodeScene "Knowledge Map"; also an MCP tool (`ownership`). Deterministic |
294
294
  | `swarmdo hidden-coupling` | **Co-change with no import edge** — join the two graphs swarmdo already owns (temporal `coupling` from git + `codegraph`'s import graph) and emit the set difference: file pairs that keep changing together yet nothing in the code links them ("logical minus structural coupling" — a config and its consumers, a schema and its mirror type). The co-edit `affected` can't see. `--since`, `--min-shared`, `--csv`, `--format json`. Grounded in Gall et al. (ICSM 1998). Deterministic |
295
295
  | `swarmdo standup` (alias `mine`) | **What did I do?** — your commits since your last working day, grouped by day with a diffstat. **Weekend-aware** (git-standup parity): on Monday it reaches back to Friday, on Sunday to Friday, otherwise to yesterday — one-command recall for a standup or for re-orienting at the start of a session. Defaults to the current git user; `--author <name>`/`--all` for teammates, `--days N` or `--since 2w` to override the window, `--format json`. Pure engine (weekend math + per-day fold) → fixture-tested. Deterministic |
296
+ | `swarmdo commands` (alias `slash`) | **Hot/cold/orphan usage report** for your authored `.claude/` surface — which custom slash-commands (`.claude/commands/**`) and subagents (`.claude/agents/**`) you actually invoke (**hot**, with counts), which are **cold** (defined but never used → prune candidates), and which are **orphan** (invoked but undefined → a typo or a builtin). `config lint` says "are these valid?"; this says "are these used?" — joining the defined files against invocation counts mined from local transcripts (`<command-name>` markers + `subagent_type` fields). `--unused` prints just the prune list, `--unused --strict` is a CI gate (exit 1 if anything's dead), `--all` counts across every project, `--json`. Pure parsers + join → fixture-tested |
296
297
  | `swarmdo agent bridge` | **Link Claude Code agents ⇄ Swarmdo** — the fix for "Swarmdo is installed but never actually used." Swarmdo can't call Claude Code's `Agent` tool (only the main loop can), so `agent bridge register -n <name>` binds a real Claude Code agent into Swarmdo's registry (`swarmdo agent list` stops being empty) and **auto-spins-up a swarm from your config, enrolling the agent** — the next bind joins the same swarm. `bridge list` (bound vs native), `bridge sync --live a,b` (reconcile drift), `bridge advise "<prompt>"` (should this warrant a swarm? which roles?). Also MCP tools `agent_bridge_register`/`agent_bridge_list`. Pure engine → 16 tests |
297
298
  | `swarmdo testreport` | **JUnit/TAP → failure digest** — turn raw test-result files into the exact failing test names + `file:line` + assertion messages, instead of scanning hundreds of log lines. The front-half of the test→fix loop: feed the failures straight into `repair`. Reads a file, a directory, or stdin; `--ci` exits 1 on any failure, `--format json`. Also an MCP tool (`testreport`). Deterministic |
298
299
  | `swarmdo integrations` (alias `integrate`) | **Use swarmdo from Codex CLI, GitHub Copilot CLI, and pi** — one command wires AGENTS.md + each CLI's MCP config (idempotent, dry-run first, never touches your Claude Code setup) |
@@ -301,7 +302,7 @@ The recent release train added a full day-to-day operations layer around the swa
301
302
  | `swarmdo mcp doctor` | **MCP config diagnosis** — missing binaries, bad URLs, malformed entries across `.mcp.json` + `~/.claude.json` |
302
303
  | `swarmdo config lint` | **Static config validation** — the pure shape layer for `swarmdo.config.json`, the `.claude/settings*.json` hooks block, `.mcp.json`, **`.claude/agents/*.md` subagents** (missing `name`/`description`, a `name` duplicated across files — CC silently loads only one — a bad `model`, malformed frontmatter), and **custom slash commands + skills** (malformed YAML that makes CC load empty metadata, a bad `effort`, an inline `` !`cmd` `` bash-injection that's inert or not covered by `allowed-tools`). `--strict` gates CI |
303
304
  | `swarmdo permissions` (alias `perms`) | **Audit your Claude Code permission rules** — static analysis of `permissions.allow`/`deny`/`ask` in `.claude/settings*.json`: flags allow↔deny conflicts (dead rules), over-broad `Bash(*)` grants, shadowed/redundant rules, duplicates, and malformed entries. `--strict` gates CI. Read-only; the static-safety sibling of `config lint` / `mcp doctor` |
304
- | `swarmdo comms` (alias `mailbox`) | **Cross-session agent mailbox** — one Claude Code session messages another by name (`send -t <session>`, `-t all` broadcasts, `inbox`, `read`, `watch`); sessions on the same repo share `.swarmdo/comms/`. `inbox --hook` surfaces new mail as prompt context without polling. Also MCP tools (`comms_send`/`comms_inbox`) |
305
+ | `swarmdo comms` (alias `mailbox`) | **Cross-session, cross-tool agent mailbox** — one agent session (Claude Code, Codex, Copilot, or pi) messages another by name (`send -t <session>`, `-t all` broadcasts, `inbox`, `read`, `watch`); sessions on the same repo share `.swarmdo/comms/`. Non-Claude agents set `$SWARMDO_AGENT` for a stable identity. `inbox --hook` surfaces new mail as prompt context without polling. Also MCP tools (`comms_send`/`comms_inbox`) |
305
306
  | `swarmdo hooks memory-inject` | **Prompt-time semantic memory injection** — embeds each prompt, vector-searches your stored memories, and injects the most relevant under a token budget (recall at the moment of need); wire it with `hooks recipe memory-inject` |
306
307
  | `swarmdo hooks notify -d` | **Desktop notifications** — OS-native toast (macOS `osascript`, Linux `notify-send`) |
307
308
  | `swarmdo hooks recipe` | **One-command Claude Code hooks** — install `notify-done`/`notify-input` (desktop pings), `memory-inject` (relevant memories each prompt), `comms-inbox` (new mail as context), or `command-guard` (a PreToolUse deny hook that blocks dangerous bash — `rm -rf /`, pipe-to-shell, force-push to main — the net swarmdo needs when running headless); dry-run by default, idempotent merge that never clobbers your settings |
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "swarmdo",
3
- "version": "1.54.1",
3
+ "version": "1.58.6",
4
4
  "description": "Swarmdo - Enterprise AI agent orchestration for Claude Code. Deploy 60+ specialized agents in coordinated swarms with self-learning, fault-tolerant consensus, vector memory, and MCP integration",
5
5
  "main": "dist/index.js",
6
6
  "type": "module",
@@ -0,0 +1,74 @@
1
+ /**
2
+ * command-usage/usage.ts — a hot/cold/orphan USAGE report for a project's
3
+ * authored `.claude/` surface. `config lint` validates these files; this answers
4
+ * the orthogonal "are they actually used?" by joining the DEFINED set
5
+ * (`.claude/commands/**​/*.md` + `.claude/agents/**​/*.md`) against INVOCATION
6
+ * counts mined from the local transcripts (`<command-name>` markers +
7
+ * `"subagent_type"` fields). Three buckets: hot (defined & invoked), cold
8
+ * (defined, never invoked → prune candidates), orphan (invoked, not defined →
9
+ * typo / removed / builtin). #101.
10
+ *
11
+ * The parsers + join are pure and unit-tested; only collectCommandUsage touches
12
+ * the filesystem. Reuses defaultClaudeProjectDirs/findTranscriptFiles.
13
+ */
14
+ export interface UsageItem {
15
+ name: string;
16
+ count: number;
17
+ }
18
+ export interface UsageBuckets {
19
+ /** defined AND invoked (count > 0), desc by count */
20
+ hot: UsageItem[];
21
+ /** defined but never invoked — prune candidates, sorted */
22
+ cold: string[];
23
+ /** invoked but not defined (typo / removed / builtin), sorted */
24
+ orphan: string[];
25
+ }
26
+ export interface CommandUsageReport {
27
+ commands: UsageBuckets;
28
+ agents: UsageBuckets;
29
+ filesScanned: number;
30
+ definedCommands: number;
31
+ definedAgents: number;
32
+ scope: 'project' | 'all';
33
+ }
34
+ /**
35
+ * Count custom slash-command invocations from raw transcript lines. Scoped to
36
+ * user-role lines (the `<command-name>` marker is injected on the user turn) so
37
+ * an assistant merely quoting the marker never inflates a count. The captured
38
+ * name is de-slashed (`/goal` → `goal`) to match the discovered-file key space.
39
+ * Pure.
40
+ */
41
+ export declare function parseCommandInvocations(lines: string[]): Map<string, number>;
42
+ /**
43
+ * Count subagent (Task tool) invocations by `subagent_type` from raw transcript
44
+ * lines. Not user-scoped — the field lives in an assistant `tool_use` block. Pure.
45
+ */
46
+ export declare function parseSubagentInvocations(lines: string[]): Map<string, number>;
47
+ /** Merge src counts into dest (dest mutated). */
48
+ export declare function mergeCounts(dest: Map<string, number>, src: Map<string, number>): void;
49
+ /**
50
+ * Join a DEFINED name list against INVOCATION counts into hot/cold/orphan. Both
51
+ * sides are compared de-slashed, so a defined `/build` matches a `build` count
52
+ * (agents carry no slash, so they're unaffected). Pure & deterministic. */
53
+ export declare function joinUsage(defined: string[], counts: Map<string, number> | Record<string, number>): UsageBuckets;
54
+ /**
55
+ * Discover the authored `.claude/` surface for a project. Command names use
56
+ * Claude Code's subdir namespacing (`.claude/commands/sDo/x.md` → `sDo:x`, top
57
+ * level → `x`) to match the `<command-name>` marker; agent names are the file
58
+ * basename (subagent_type is never namespaced). Pure w.r.t. inputs (reads fs).
59
+ */
60
+ export declare function discoverAuthored(cwd: string): {
61
+ commands: string[];
62
+ agents: string[];
63
+ };
64
+ export interface CollectOptions {
65
+ cwd?: string;
66
+ /** scan every project's transcripts (default: only the current project) */
67
+ all?: boolean;
68
+ }
69
+ /** The encoded transcript-dir name Claude Code uses for a project path. */
70
+ export declare function encodeProjectDir(cwd: string): string;
71
+ /** Build the full report: discover authored files, mine invocation counts from
72
+ * the (project-scoped, or --all) transcripts, and join. fs-touching wrapper. */
73
+ export declare function collectCommandUsage(opts?: CollectOptions): CommandUsageReport;
74
+ //# sourceMappingURL=usage.d.ts.map
@@ -0,0 +1,161 @@
1
+ /**
2
+ * command-usage/usage.ts — a hot/cold/orphan USAGE report for a project's
3
+ * authored `.claude/` surface. `config lint` validates these files; this answers
4
+ * the orthogonal "are they actually used?" by joining the DEFINED set
5
+ * (`.claude/commands/**​/*.md` + `.claude/agents/**​/*.md`) against INVOCATION
6
+ * counts mined from the local transcripts (`<command-name>` markers +
7
+ * `"subagent_type"` fields). Three buckets: hot (defined & invoked), cold
8
+ * (defined, never invoked → prune candidates), orphan (invoked, not defined →
9
+ * typo / removed / builtin). #101.
10
+ *
11
+ * The parsers + join are pure and unit-tested; only collectCommandUsage touches
12
+ * the filesystem. Reuses defaultClaudeProjectDirs/findTranscriptFiles.
13
+ */
14
+ import * as fs from 'node:fs';
15
+ import * as path from 'node:path';
16
+ import { defaultClaudeProjectDirs, findTranscriptFiles } from '../usage/transcript-usage.js';
17
+ const uniqSort = (xs) => [...new Set(xs)].sort((a, b) => a.localeCompare(b));
18
+ /**
19
+ * Count custom slash-command invocations from raw transcript lines. Scoped to
20
+ * user-role lines (the `<command-name>` marker is injected on the user turn) so
21
+ * an assistant merely quoting the marker never inflates a count. The captured
22
+ * name is de-slashed (`/goal` → `goal`) to match the discovered-file key space.
23
+ * Pure.
24
+ */
25
+ export function parseCommandInvocations(lines) {
26
+ const counts = new Map();
27
+ for (const line of lines) {
28
+ if (!/"(?:type|role)"\s*:\s*"user"/.test(line))
29
+ continue;
30
+ for (const m of line.matchAll(/<command-name>([^<]+)<\/command-name>/g)) {
31
+ const name = m[1].trim().replace(/^\/+/, '');
32
+ if (!name || name === '…')
33
+ continue;
34
+ counts.set(name, (counts.get(name) ?? 0) + 1);
35
+ }
36
+ }
37
+ return counts;
38
+ }
39
+ /**
40
+ * Count subagent (Task tool) invocations by `subagent_type` from raw transcript
41
+ * lines. Not user-scoped — the field lives in an assistant `tool_use` block. Pure.
42
+ */
43
+ export function parseSubagentInvocations(lines) {
44
+ const counts = new Map();
45
+ for (const line of lines) {
46
+ for (const m of line.matchAll(/"subagent_type"\s*:\s*"([^"]+)"/g)) {
47
+ const name = m[1].trim();
48
+ if (name)
49
+ counts.set(name, (counts.get(name) ?? 0) + 1);
50
+ }
51
+ }
52
+ return counts;
53
+ }
54
+ /** Merge src counts into dest (dest mutated). */
55
+ export function mergeCounts(dest, src) {
56
+ for (const [k, v] of src)
57
+ dest.set(k, (dest.get(k) ?? 0) + v);
58
+ }
59
+ /**
60
+ * Join a DEFINED name list against INVOCATION counts into hot/cold/orphan. Both
61
+ * sides are compared de-slashed, so a defined `/build` matches a `build` count
62
+ * (agents carry no slash, so they're unaffected). Pure & deterministic. */
63
+ export function joinUsage(defined, counts) {
64
+ const asMap = counts instanceof Map ? counts : new Map(Object.entries(counts));
65
+ const norm = (n) => n.replace(/^\/+/, '');
66
+ const get = (n) => asMap.get(norm(n)) ?? 0;
67
+ const definedNorm = new Set(defined.map(norm));
68
+ const hot = [];
69
+ const cold = [];
70
+ for (const d of defined) {
71
+ const c = get(d);
72
+ if (c > 0)
73
+ hot.push({ name: d, count: c });
74
+ else
75
+ cold.push(d);
76
+ }
77
+ const orphan = [];
78
+ for (const [k, v] of asMap) {
79
+ if (v > 0 && !definedNorm.has(norm(k)))
80
+ orphan.push(k);
81
+ }
82
+ hot.sort((a, b) => b.count - a.count || a.name.localeCompare(b.name));
83
+ return { hot, cold: uniqSort(cold), orphan: uniqSort(orphan) };
84
+ }
85
+ /** All `.md` files under `root`, as paths RELATIVE to root (recursive; skips
86
+ * dotfiles). Mirrors config.ts's walkMd so `config lint` and this command agree
87
+ * on what counts as "defined". */
88
+ function walkMdRel(root) {
89
+ const out = [];
90
+ const rec = (dir, prefix) => {
91
+ let entries;
92
+ try {
93
+ entries = fs.readdirSync(dir, { withFileTypes: true });
94
+ }
95
+ catch {
96
+ return;
97
+ }
98
+ for (const e of entries) {
99
+ if (e.name.startsWith('.'))
100
+ continue;
101
+ const rel = prefix ? `${prefix}/${e.name}` : e.name;
102
+ if (e.isDirectory())
103
+ rec(path.join(dir, e.name), rel);
104
+ else if (e.isFile() && e.name.endsWith('.md'))
105
+ out.push(rel);
106
+ }
107
+ };
108
+ rec(root, '');
109
+ return out;
110
+ }
111
+ /**
112
+ * Discover the authored `.claude/` surface for a project. Command names use
113
+ * Claude Code's subdir namespacing (`.claude/commands/sDo/x.md` → `sDo:x`, top
114
+ * level → `x`) to match the `<command-name>` marker; agent names are the file
115
+ * basename (subagent_type is never namespaced). Pure w.r.t. inputs (reads fs).
116
+ */
117
+ export function discoverAuthored(cwd) {
118
+ const commands = walkMdRel(path.join(cwd, '.claude', 'commands')).map((rel) => rel.replace(/\.md$/, '').split('/').join(':'));
119
+ const agents = walkMdRel(path.join(cwd, '.claude', 'agents')).map((rel) => path.basename(rel).replace(/\.md$/, ''));
120
+ return { commands: uniqSort(commands), agents: uniqSort(agents) };
121
+ }
122
+ /** The encoded transcript-dir name Claude Code uses for a project path. */
123
+ export function encodeProjectDir(cwd) {
124
+ return cwd.replace(/\//g, '-');
125
+ }
126
+ /** Build the full report: discover authored files, mine invocation counts from
127
+ * the (project-scoped, or --all) transcripts, and join. fs-touching wrapper. */
128
+ export function collectCommandUsage(opts = {}) {
129
+ const cwd = opts.cwd ?? process.cwd();
130
+ const { commands: definedCommands, agents: definedAgents } = discoverAuthored(cwd);
131
+ const encoded = encodeProjectDir(cwd);
132
+ const cmdCounts = new Map();
133
+ const agentCounts = new Map();
134
+ let filesScanned = 0;
135
+ for (const dir of defaultClaudeProjectDirs()) {
136
+ for (const t of findTranscriptFiles(dir)) {
137
+ if (!opts.all && t.project !== encoded)
138
+ continue;
139
+ filesScanned++;
140
+ let content;
141
+ try {
142
+ content = fs.readFileSync(t.file, 'utf8');
143
+ }
144
+ catch {
145
+ continue;
146
+ }
147
+ const fileLines = content.split('\n');
148
+ mergeCounts(cmdCounts, parseCommandInvocations(fileLines));
149
+ mergeCounts(agentCounts, parseSubagentInvocations(fileLines));
150
+ }
151
+ }
152
+ return {
153
+ commands: joinUsage(definedCommands, cmdCounts),
154
+ agents: joinUsage(definedAgents, agentCounts),
155
+ filesScanned,
156
+ definedCommands: definedCommands.length,
157
+ definedAgents: definedAgents.length,
158
+ scope: opts.all ? 'all' : 'project',
159
+ };
160
+ }
161
+ //# sourceMappingURL=usage.js.map
@@ -0,0 +1,19 @@
1
+ /**
2
+ * `swarmdo commands` (alias `slash`) — a hot/cold/orphan USAGE report for the
3
+ * project's authored `.claude/` slash-commands + subagents. `config lint` says
4
+ * "are these valid?"; this says "are these used?" by joining defined files
5
+ * against invocation counts mined from the local transcripts. #101.
6
+ *
7
+ * swarmdo commands # this project's authored surface
8
+ * swarmdo commands --all # count invocations across every project
9
+ * swarmdo commands --unused # only the cold (never-invoked) items
10
+ * swarmdo commands --unused --strict # exit 1 if anything is unused (CI gate)
11
+ * swarmdo commands --json # machine-readable
12
+ *
13
+ * Engine (../command-usage/usage.ts) is pure + fixture-tested; this thin layer
14
+ * renders and applies the --unused/--strict policy.
15
+ */
16
+ import type { Command } from '../types.js';
17
+ export declare const commandsCommand: Command;
18
+ export default commandsCommand;
19
+ //# sourceMappingURL=commands.d.ts.map
@@ -0,0 +1,107 @@
1
+ /**
2
+ * `swarmdo commands` (alias `slash`) — a hot/cold/orphan USAGE report for the
3
+ * project's authored `.claude/` slash-commands + subagents. `config lint` says
4
+ * "are these valid?"; this says "are these used?" by joining defined files
5
+ * against invocation counts mined from the local transcripts. #101.
6
+ *
7
+ * swarmdo commands # this project's authored surface
8
+ * swarmdo commands --all # count invocations across every project
9
+ * swarmdo commands --unused # only the cold (never-invoked) items
10
+ * swarmdo commands --unused --strict # exit 1 if anything is unused (CI gate)
11
+ * swarmdo commands --json # machine-readable
12
+ *
13
+ * Engine (../command-usage/usage.ts) is pure + fixture-tested; this thin layer
14
+ * renders and applies the --unused/--strict policy.
15
+ */
16
+ import { output } from '../output.js';
17
+ import { collectCommandUsage } from '../command-usage/usage.js';
18
+ /** Render one domain's hot/cold/orphan buckets. `slash` prefixes command names. */
19
+ function renderBuckets(label, defined, b, slash) {
20
+ const nm = (n) => (slash ? `/${n}` : n);
21
+ output.writeln('');
22
+ output.writeln(output.bold(`${label}`) + output.dim(` (${defined} defined · ${b.hot.length} hot · ${b.cold.length} cold · ${b.orphan.length} orphan)`));
23
+ if (b.hot.length > 0) {
24
+ output.printTable({
25
+ columns: [
26
+ { key: 'name', header: 'Hot (used)', width: 34 },
27
+ { key: 'count', header: 'Invocations', width: 12, align: 'right' },
28
+ ],
29
+ data: b.hot.map((h) => ({ name: nm(h.name), count: h.count.toLocaleString('en-US') })),
30
+ });
31
+ }
32
+ if (b.cold.length > 0) {
33
+ output.writeln(output.warning(` cold (never invoked — prune candidates): `) + b.cold.map(nm).join(' '));
34
+ }
35
+ if (b.orphan.length > 0) {
36
+ output.writeln(output.dim(` orphan (invoked, not defined — builtin or typo): `) + b.orphan.map(nm).join(' '));
37
+ }
38
+ if (b.hot.length === 0 && b.cold.length === 0 && b.orphan.length === 0) {
39
+ output.writeln(output.dim(' (none)'));
40
+ }
41
+ }
42
+ /** Print only the cold (unused) items — the prune list. Returns the cold count. */
43
+ function renderUnused(report) {
44
+ const coldCmds = report.commands.cold;
45
+ const coldAgents = report.agents.cold;
46
+ const total = coldCmds.length + coldAgents.length;
47
+ output.writeln(output.bold('Unused (cold) authored items') + output.dim(` (${report.scope} scope · ${report.filesScanned} transcript files)`));
48
+ if (total === 0) {
49
+ output.writeln(output.info(' none — every authored command and agent has been invoked 🎉'));
50
+ return 0;
51
+ }
52
+ if (coldCmds.length > 0)
53
+ output.writeln(` commands: ${coldCmds.map((c) => `/${c}`).join(' ')}`);
54
+ if (coldAgents.length > 0)
55
+ output.writeln(` agents: ${coldAgents.join(' ')}`);
56
+ return total;
57
+ }
58
+ async function run(ctx) {
59
+ const cwd = ctx.cwd || process.cwd();
60
+ const all = ctx.flags.all === true;
61
+ const report = collectCommandUsage({ cwd, all });
62
+ if (ctx.flags.json === true) {
63
+ output.writeln(JSON.stringify(report, null, 2));
64
+ return { success: true, exitCode: 0 };
65
+ }
66
+ if (report.definedCommands === 0 && report.definedAgents === 0) {
67
+ output.writeln(output.info('nothing authored — no .claude/commands or .claude/agents in this project'));
68
+ return { success: true, exitCode: 0 };
69
+ }
70
+ if (ctx.flags.unused === true) {
71
+ const coldCount = renderUnused(report);
72
+ const strict = ctx.flags.strict === true;
73
+ const exitCode = strict && coldCount > 0 ? 1 : 0;
74
+ if (exitCode === 1)
75
+ output.writeln(output.dim(`exit 1 (--strict + ${coldCount} unused)`));
76
+ return { success: exitCode === 0, exitCode };
77
+ }
78
+ output.writeln(output.bold('Authored .claude/ surface — usage') + output.dim(` (${report.scope} scope · ${report.filesScanned} transcript files)`));
79
+ renderBuckets('Commands', report.definedCommands, report.commands, true);
80
+ renderBuckets('Agents', report.definedAgents, report.agents, false);
81
+ const totalCold = report.commands.cold.length + report.agents.cold.length;
82
+ if (totalCold > 0) {
83
+ output.writeln('');
84
+ output.writeln(output.dim(`${totalCold} unused — see \`swarmdo commands --unused\` (add --strict for a CI gate)`));
85
+ }
86
+ return { success: true, exitCode: 0 };
87
+ }
88
+ export const commandsCommand = {
89
+ name: 'commands',
90
+ aliases: ['slash'],
91
+ description: "Usage report (hot/cold/orphan) for the project's authored .claude/ slash-commands & subagents",
92
+ options: [
93
+ { name: 'all', description: 'count invocations across every project (default: current project only)', type: 'boolean', default: false },
94
+ { name: 'unused', description: 'print only the cold (never-invoked) items — the prune list', type: 'boolean', default: false },
95
+ { name: 'strict', description: 'with --unused, exit 1 if anything is unused (CI gate)', type: 'boolean', default: false },
96
+ { name: 'json', description: 'machine-readable output', type: 'boolean', default: false },
97
+ ],
98
+ examples: [
99
+ { command: 'swarmdo commands', description: 'Hot/cold/orphan report for your authored .claude/ surface' },
100
+ { command: 'swarmdo commands --unused', description: 'List slash-commands & agents you defined but never invoke' },
101
+ { command: 'swarmdo commands --unused --strict', description: 'CI gate: fail if any authored command/agent is unused' },
102
+ { command: 'swarmdo slash --all --json', description: 'Cross-project invocation counts as JSON (alias)' },
103
+ ],
104
+ action: run,
105
+ };
106
+ export default commandsCommand;
107
+ //# sourceMappingURL=commands.js.map
@@ -3,6 +3,32 @@
3
3
  * Self-learning hooks system for intelligent workflow automation
4
4
  */
5
5
  import type { Command } from '../types.js';
6
+ /**
7
+ * Live swarm + agent counts for the statusline (`🐝 Swarms N 🤖 Agents M`).
8
+ * These are two distinct numbers, read from two canonical registries:
9
+ * - agents: `.swarmdo/agents/store.json` + the hive `.swarmdo/agents.json`
10
+ * (what `agent_spawn`, `swarm_init`, `agent bridge register`, and hive-mind
11
+ * workers write) — every non-terminated agent is counted.
12
+ * - swarms: `.swarmdo/swarm/swarm-state.json` — every `status: 'running'`
13
+ * swarm whose host process is still alive; dead-pid / >24h-stale orphans are
14
+ * skipped read-only (mirrors reconcileOrphanSwarms without persisting).
15
+ *
16
+ * The agent count replaces the old `ps aux | grep -c agentic-flow` heuristic,
17
+ * which (a) was blind to in-process agents — Claude Code Task-tool subagents and
18
+ * bridged agents never appear as a separate `agentic-flow` OS process — so the
19
+ * count never moved when a swarm spun up, and (b) false-positived on any process
20
+ * whose args merely mention "agentic-flow" (a grep, an open editor buffer, the
21
+ * ONNX embedder), showing phantom agents when none were running.
22
+ *
23
+ * No `maxAgents` denominator is reported: swarm size is never enforced at spawn
24
+ * time (the config value is an advisory hint feeding an internal [1,50]
25
+ * backstop), so a `[N/max]` gauge would imply a live cap that does not exist.
26
+ */
27
+ export declare function computeSwarmStatus(cwd?: string): {
28
+ activeSwarms: number;
29
+ activeAgents: number;
30
+ coordinationActive: boolean;
31
+ };
6
32
  export declare const hooksCommand: Command;
7
33
  export default hooksCommand;
8
34
  //# sourceMappingURL=hooks.d.ts.map