swarmdo 1.4.8 → 1.6.0

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 (215) hide show
  1. package/.claude/helpers/statusline.cjs +7 -7
  2. package/README.md +9 -6
  3. package/package.json +5 -3
  4. package/v3/@swarmdo/cli/dist/src/commands/compact.d.ts +16 -0
  5. package/v3/@swarmdo/cli/dist/src/commands/compact.js +106 -0
  6. package/v3/@swarmdo/cli/dist/src/commands/hooks.js +26 -24
  7. package/v3/@swarmdo/cli/dist/src/commands/index.js +10 -3
  8. package/v3/@swarmdo/cli/dist/src/commands/integrations.d.ts +14 -0
  9. package/v3/@swarmdo/cli/dist/src/commands/integrations.js +158 -0
  10. package/v3/@swarmdo/cli/dist/src/commands/memory.js +50 -1
  11. package/v3/@swarmdo/cli/dist/src/commands/providers.js +3 -0
  12. package/v3/@swarmdo/cli/dist/src/commands/release.d.ts +15 -0
  13. package/v3/@swarmdo/cli/dist/src/commands/release.js +241 -0
  14. package/v3/@swarmdo/cli/dist/src/commands/security.js +14 -0
  15. package/v3/@swarmdo/cli/dist/src/commands/transcript.js +82 -1
  16. package/v3/@swarmdo/cli/dist/src/commands/usage.js +80 -1
  17. package/v3/@swarmdo/cli/dist/src/compact/compact.d.ts +60 -0
  18. package/v3/@swarmdo/cli/dist/src/compact/compact.js +170 -0
  19. package/v3/@swarmdo/cli/dist/src/config-lint/lint.js +11 -1
  20. package/v3/@swarmdo/cli/dist/src/index.js +4 -2
  21. package/v3/@swarmdo/cli/dist/src/init/statusline-generator.js +6 -6
  22. package/v3/@swarmdo/cli/dist/src/integrations/integrations.d.ts +54 -0
  23. package/v3/@swarmdo/cli/dist/src/integrations/integrations.js +162 -0
  24. package/v3/@swarmdo/cli/dist/src/mcp-tools/agent-execute-core.js +25 -3
  25. package/v3/@swarmdo/cli/dist/src/mcp-tools/agentdb-tools.js +8 -8
  26. package/v3/@swarmdo/cli/dist/src/memory/graph-edge-writer.d.ts +12 -0
  27. package/v3/@swarmdo/cli/dist/src/memory/graph-edge-writer.js +32 -1
  28. package/v3/@swarmdo/cli/dist/src/memory-vault/watch.d.ts +32 -0
  29. package/v3/@swarmdo/cli/dist/src/memory-vault/watch.js +66 -0
  30. package/v3/@swarmdo/cli/dist/src/providers/openrouter-config.d.ts +91 -0
  31. package/v3/@swarmdo/cli/dist/src/providers/openrouter-config.js +186 -0
  32. package/v3/@swarmdo/cli/dist/src/release/release.d.ts +72 -0
  33. package/v3/@swarmdo/cli/dist/src/release/release.js +86 -0
  34. package/v3/@swarmdo/cli/dist/src/resilience/backoff.d.ts +23 -0
  35. package/v3/@swarmdo/cli/dist/src/resilience/backoff.js +30 -0
  36. package/v3/@swarmdo/cli/dist/src/swarmvector/model-router.js +14 -0
  37. package/v3/@swarmdo/cli/dist/src/transcript/search.d.ts +39 -0
  38. package/v3/@swarmdo/cli/dist/src/transcript/search.js +67 -0
  39. package/v3/@swarmdo/cli/dist/src/usage/diff.d.ts +69 -0
  40. package/v3/@swarmdo/cli/dist/src/usage/diff.js +112 -0
  41. package/v3/@swarmdo/cli/package.json +4 -4
  42. package/v3/@swarmdo/cli-core/dist/src/index.js +1 -1
  43. package/v3/@swarmdo/codex/dist/cli.js +0 -0
  44. package/v3/@swarmdo/hooks/dist/cli/guidance-cli.js +0 -0
  45. package/v3/@swarmdo/hooks/dist/statusline/index.d.ts +3 -3
  46. package/v3/@swarmdo/hooks/dist/statusline/index.js +3 -3
  47. package/v3/@swarmdo/integration/dist/__tests__/agentic-flow-agent.test.js +4 -1
  48. package/v3/@swarmdo/neural/dist/flash-attention.d.ts +1 -1
  49. package/v3/@swarmdo/neural/dist/flash-attention.js +1 -1
  50. package/v3/@swarmdo/plugin-agent-federation/dist/plugin.js +1 -1
  51. package/v3/@swarmdo/plugin-agent-federation/dist/transport/midstream-aware-loader.js +2 -2
  52. package/v3/@swarmdo/providers/dist/swarmvector-provider.d.ts +1 -1
  53. package/v3/@swarmdo/providers/dist/swarmvector-provider.js +1 -1
  54. package/v3/@swarmdo/security/dist/input-validator.d.ts +6 -6
  55. package/v3/@swarmdo/shared/dist/hooks/safety/git-commit.js +1 -1
  56. package/v3/@swarmdo/shared/dist/mcp/transport/http.js +8 -1
  57. package/v3/vendor/agentdb/package.json +0 -1
  58. package/v3/vendor/agentic-flow/package.json +0 -1
  59. package/.claude/scheduled_tasks.lock +0 -1
  60. package/.claude/skills/sdo-caveman-compress/scripts/__pycache__/__init__.cpython-314.pyc +0 -0
  61. package/.claude/skills/sdo-caveman-compress/scripts/__pycache__/__main__.cpython-314.pyc +0 -0
  62. package/.claude/skills/sdo-caveman-compress/scripts/__pycache__/cli.cpython-314.pyc +0 -0
  63. package/.claude/skills/sdo-caveman-compress/scripts/__pycache__/compress.cpython-314.pyc +0 -0
  64. package/.claude/skills/sdo-caveman-compress/scripts/__pycache__/detect.cpython-314.pyc +0 -0
  65. package/.claude/skills/sdo-caveman-compress/scripts/__pycache__/validate.cpython-314.pyc +0 -0
  66. package/v3/@swarmdo/plugin-iot-cognitum/dist/application/index.d.ts +0 -2
  67. package/v3/@swarmdo/plugin-iot-cognitum/dist/application/index.js +0 -2
  68. package/v3/@swarmdo/plugin-iot-cognitum/dist/application/iot-coordinator.d.ts +0 -138
  69. package/v3/@swarmdo/plugin-iot-cognitum/dist/application/iot-coordinator.js +0 -418
  70. package/v3/@swarmdo/plugin-iot-cognitum/dist/bin.d.ts +0 -15
  71. package/v3/@swarmdo/plugin-iot-cognitum/dist/bin.js +0 -240
  72. package/v3/@swarmdo/plugin-iot-cognitum/dist/cli-commands.d.ts +0 -7
  73. package/v3/@swarmdo/plugin-iot-cognitum/dist/cli-commands.js +0 -508
  74. package/v3/@swarmdo/plugin-iot-cognitum/dist/domain/entities/device-agent.d.ts +0 -54
  75. package/v3/@swarmdo/plugin-iot-cognitum/dist/domain/entities/device-agent.js +0 -2
  76. package/v3/@swarmdo/plugin-iot-cognitum/dist/domain/entities/device-fleet.d.ts +0 -46
  77. package/v3/@swarmdo/plugin-iot-cognitum/dist/domain/entities/device-fleet.js +0 -2
  78. package/v3/@swarmdo/plugin-iot-cognitum/dist/domain/entities/device-trust-level.d.ts +0 -18
  79. package/v3/@swarmdo/plugin-iot-cognitum/dist/domain/entities/device-trust-level.js +0 -28
  80. package/v3/@swarmdo/plugin-iot-cognitum/dist/domain/entities/index.d.ts +0 -5
  81. package/v3/@swarmdo/plugin-iot-cognitum/dist/domain/entities/index.js +0 -2
  82. package/v3/@swarmdo/plugin-iot-cognitum/dist/domain/entities/telemetry.d.ts +0 -35
  83. package/v3/@swarmdo/plugin-iot-cognitum/dist/domain/entities/telemetry.js +0 -2
  84. package/v3/@swarmdo/plugin-iot-cognitum/dist/domain/repositories/device-repository.d.ts +0 -11
  85. package/v3/@swarmdo/plugin-iot-cognitum/dist/domain/repositories/device-repository.js +0 -2
  86. package/v3/@swarmdo/plugin-iot-cognitum/dist/domain/repositories/fleet-repository.d.ts +0 -9
  87. package/v3/@swarmdo/plugin-iot-cognitum/dist/domain/repositories/fleet-repository.js +0 -2
  88. package/v3/@swarmdo/plugin-iot-cognitum/dist/domain/repositories/index.d.ts +0 -5
  89. package/v3/@swarmdo/plugin-iot-cognitum/dist/domain/repositories/index.js +0 -2
  90. package/v3/@swarmdo/plugin-iot-cognitum/dist/domain/repositories/telemetry-repository.d.ts +0 -12
  91. package/v3/@swarmdo/plugin-iot-cognitum/dist/domain/repositories/telemetry-repository.js +0 -2
  92. package/v3/@swarmdo/plugin-iot-cognitum/dist/domain/repositories/trust-history-repository.d.ts +0 -19
  93. package/v3/@swarmdo/plugin-iot-cognitum/dist/domain/repositories/trust-history-repository.js +0 -2
  94. package/v3/@swarmdo/plugin-iot-cognitum/dist/domain/services/anomaly-detection-service.d.ts +0 -44
  95. package/v3/@swarmdo/plugin-iot-cognitum/dist/domain/services/anomaly-detection-service.js +0 -117
  96. package/v3/@swarmdo/plugin-iot-cognitum/dist/domain/services/device-lifecycle-service.d.ts +0 -70
  97. package/v3/@swarmdo/plugin-iot-cognitum/dist/domain/services/device-lifecycle-service.js +0 -194
  98. package/v3/@swarmdo/plugin-iot-cognitum/dist/domain/services/firmware-orchestration-service.d.ts +0 -69
  99. package/v3/@swarmdo/plugin-iot-cognitum/dist/domain/services/firmware-orchestration-service.js +0 -139
  100. package/v3/@swarmdo/plugin-iot-cognitum/dist/domain/services/fleet-topology-service.d.ts +0 -34
  101. package/v3/@swarmdo/plugin-iot-cognitum/dist/domain/services/fleet-topology-service.js +0 -101
  102. package/v3/@swarmdo/plugin-iot-cognitum/dist/domain/services/index.d.ts +0 -10
  103. package/v3/@swarmdo/plugin-iot-cognitum/dist/domain/services/index.js +0 -10
  104. package/v3/@swarmdo/plugin-iot-cognitum/dist/domain/services/mesh-service.d.ts +0 -64
  105. package/v3/@swarmdo/plugin-iot-cognitum/dist/domain/services/mesh-service.js +0 -70
  106. package/v3/@swarmdo/plugin-iot-cognitum/dist/domain/services/sona-integration-service.d.ts +0 -44
  107. package/v3/@swarmdo/plugin-iot-cognitum/dist/domain/services/sona-integration-service.js +0 -79
  108. package/v3/@swarmdo/plugin-iot-cognitum/dist/domain/services/telemetry-ingestion-service.d.ts +0 -37
  109. package/v3/@swarmdo/plugin-iot-cognitum/dist/domain/services/telemetry-ingestion-service.js +0 -39
  110. package/v3/@swarmdo/plugin-iot-cognitum/dist/domain/services/telemetry-service.d.ts +0 -67
  111. package/v3/@swarmdo/plugin-iot-cognitum/dist/domain/services/telemetry-service.js +0 -58
  112. package/v3/@swarmdo/plugin-iot-cognitum/dist/domain/services/witness-verification-service.d.ts +0 -45
  113. package/v3/@swarmdo/plugin-iot-cognitum/dist/domain/services/witness-verification-service.js +0 -63
  114. package/v3/@swarmdo/plugin-iot-cognitum/dist/index.d.ts +0 -26
  115. package/v3/@swarmdo/plugin-iot-cognitum/dist/index.js +0 -17
  116. package/v3/@swarmdo/plugin-iot-cognitum/dist/infrastructure/agentdb-telemetry-repository.d.ts +0 -51
  117. package/v3/@swarmdo/plugin-iot-cognitum/dist/infrastructure/agentdb-telemetry-repository.js +0 -110
  118. package/v3/@swarmdo/plugin-iot-cognitum/dist/infrastructure/in-memory-device-repository.d.ts +0 -13
  119. package/v3/@swarmdo/plugin-iot-cognitum/dist/infrastructure/in-memory-device-repository.js +0 -25
  120. package/v3/@swarmdo/plugin-iot-cognitum/dist/infrastructure/in-memory-fleet-repository.d.ts +0 -11
  121. package/v3/@swarmdo/plugin-iot-cognitum/dist/infrastructure/in-memory-fleet-repository.js +0 -19
  122. package/v3/@swarmdo/plugin-iot-cognitum/dist/infrastructure/in-memory-trust-history-repository.d.ts +0 -11
  123. package/v3/@swarmdo/plugin-iot-cognitum/dist/infrastructure/in-memory-trust-history-repository.js +0 -27
  124. package/v3/@swarmdo/plugin-iot-cognitum/dist/infrastructure/index.d.ts +0 -6
  125. package/v3/@swarmdo/plugin-iot-cognitum/dist/infrastructure/index.js +0 -6
  126. package/v3/@swarmdo/plugin-iot-cognitum/dist/infrastructure/seed-client-factory.d.ts +0 -41
  127. package/v3/@swarmdo/plugin-iot-cognitum/dist/infrastructure/seed-client-factory.js +0 -64
  128. package/v3/@swarmdo/plugin-iot-cognitum/dist/mcp-tools.d.ts +0 -8
  129. package/v3/@swarmdo/plugin-iot-cognitum/dist/mcp-tools.js +0 -703
  130. package/v3/@swarmdo/plugin-iot-cognitum/dist/plugin.d.ts +0 -23
  131. package/v3/@swarmdo/plugin-iot-cognitum/dist/plugin.js +0 -239
  132. package/v3/@swarmdo/plugin-iot-cognitum/dist/workers/anomaly-scan-worker.d.ts +0 -17
  133. package/v3/@swarmdo/plugin-iot-cognitum/dist/workers/anomaly-scan-worker.js +0 -42
  134. package/v3/@swarmdo/plugin-iot-cognitum/dist/workers/firmware-watch-worker.d.ts +0 -18
  135. package/v3/@swarmdo/plugin-iot-cognitum/dist/workers/firmware-watch-worker.js +0 -45
  136. package/v3/@swarmdo/plugin-iot-cognitum/dist/workers/health-probe-worker.d.ts +0 -19
  137. package/v3/@swarmdo/plugin-iot-cognitum/dist/workers/health-probe-worker.js +0 -50
  138. package/v3/@swarmdo/plugin-iot-cognitum/dist/workers/mesh-sync-worker.d.ts +0 -19
  139. package/v3/@swarmdo/plugin-iot-cognitum/dist/workers/mesh-sync-worker.js +0 -47
  140. package/v3/@swarmdo/plugin-iot-cognitum/dist/workers/telemetry-ingest-worker.d.ts +0 -17
  141. package/v3/@swarmdo/plugin-iot-cognitum/dist/workers/telemetry-ingest-worker.js +0 -40
  142. package/v3/@swarmdo/plugin-iot-cognitum/dist/workers/witness-audit-worker.d.ts +0 -18
  143. package/v3/@swarmdo/plugin-iot-cognitum/dist/workers/witness-audit-worker.js +0 -51
  144. package/v3/@swarmdo/testing/dist/fixtures/agent-fixtures.d.ts +0 -214
  145. package/v3/@swarmdo/testing/dist/fixtures/agent-fixtures.js +0 -595
  146. package/v3/@swarmdo/testing/dist/fixtures/agents.d.ts +0 -76
  147. package/v3/@swarmdo/testing/dist/fixtures/agents.js +0 -158
  148. package/v3/@swarmdo/testing/dist/fixtures/configurations.d.ts +0 -157
  149. package/v3/@swarmdo/testing/dist/fixtures/configurations.js +0 -337
  150. package/v3/@swarmdo/testing/dist/fixtures/index.d.ts +0 -10
  151. package/v3/@swarmdo/testing/dist/fixtures/index.js +0 -17
  152. package/v3/@swarmdo/testing/dist/fixtures/mcp-fixtures.d.ts +0 -329
  153. package/v3/@swarmdo/testing/dist/fixtures/mcp-fixtures.js +0 -714
  154. package/v3/@swarmdo/testing/dist/fixtures/memory-entries.d.ts +0 -159
  155. package/v3/@swarmdo/testing/dist/fixtures/memory-entries.js +0 -262
  156. package/v3/@swarmdo/testing/dist/fixtures/memory-fixtures.d.ts +0 -290
  157. package/v3/@swarmdo/testing/dist/fixtures/memory-fixtures.js +0 -547
  158. package/v3/@swarmdo/testing/dist/fixtures/swarm-fixtures.d.ts +0 -289
  159. package/v3/@swarmdo/testing/dist/fixtures/swarm-fixtures.js +0 -534
  160. package/v3/@swarmdo/testing/dist/fixtures/tasks.d.ts +0 -106
  161. package/v3/@swarmdo/testing/dist/fixtures/tasks.js +0 -229
  162. package/v3/@swarmdo/testing/dist/helpers/assertion-helpers.d.ts +0 -213
  163. package/v3/@swarmdo/testing/dist/helpers/assertion-helpers.js +0 -435
  164. package/v3/@swarmdo/testing/dist/helpers/assertions.d.ts +0 -135
  165. package/v3/@swarmdo/testing/dist/helpers/assertions.js +0 -217
  166. package/v3/@swarmdo/testing/dist/helpers/create-mock.d.ts +0 -96
  167. package/v3/@swarmdo/testing/dist/helpers/create-mock.js +0 -164
  168. package/v3/@swarmdo/testing/dist/helpers/index.d.ts +0 -14
  169. package/v3/@swarmdo/testing/dist/helpers/index.js +0 -22
  170. package/v3/@swarmdo/testing/dist/helpers/mock-factory.d.ts +0 -323
  171. package/v3/@swarmdo/testing/dist/helpers/mock-factory.js +0 -350
  172. package/v3/@swarmdo/testing/dist/helpers/setup-teardown.d.ts +0 -271
  173. package/v3/@swarmdo/testing/dist/helpers/setup-teardown.js +0 -446
  174. package/v3/@swarmdo/testing/dist/helpers/swarm-instance.d.ts +0 -142
  175. package/v3/@swarmdo/testing/dist/helpers/swarm-instance.js +0 -205
  176. package/v3/@swarmdo/testing/dist/helpers/test-application.d.ts +0 -190
  177. package/v3/@swarmdo/testing/dist/helpers/test-application.js +0 -138
  178. package/v3/@swarmdo/testing/dist/helpers/test-utils.d.ts +0 -274
  179. package/v3/@swarmdo/testing/dist/helpers/test-utils.js +0 -456
  180. package/v3/@swarmdo/testing/dist/index.d.ts +0 -42
  181. package/v3/@swarmdo/testing/dist/index.js +0 -66
  182. package/v3/@swarmdo/testing/dist/mocks/index.d.ts +0 -8
  183. package/v3/@swarmdo/testing/dist/mocks/index.js +0 -10
  184. package/v3/@swarmdo/testing/dist/mocks/mock-mcp-client.d.ts +0 -206
  185. package/v3/@swarmdo/testing/dist/mocks/mock-mcp-client.js +0 -575
  186. package/v3/@swarmdo/testing/dist/mocks/mock-services.d.ts +0 -287
  187. package/v3/@swarmdo/testing/dist/mocks/mock-services.js +0 -563
  188. package/v3/@swarmdo/testing/dist/regression/api-contract.d.ts +0 -109
  189. package/v3/@swarmdo/testing/dist/regression/api-contract.js +0 -374
  190. package/v3/@swarmdo/testing/dist/regression/index.d.ts +0 -18
  191. package/v3/@swarmdo/testing/dist/regression/index.js +0 -18
  192. package/v3/@swarmdo/testing/dist/regression/integration-regression.d.ts +0 -67
  193. package/v3/@swarmdo/testing/dist/regression/integration-regression.js +0 -334
  194. package/v3/@swarmdo/testing/dist/regression/performance-baseline.d.ts +0 -106
  195. package/v3/@swarmdo/testing/dist/regression/performance-baseline.js +0 -268
  196. package/v3/@swarmdo/testing/dist/regression/regression-runner.d.ts +0 -124
  197. package/v3/@swarmdo/testing/dist/regression/regression-runner.js +0 -227
  198. package/v3/@swarmdo/testing/dist/regression/security-regression.d.ts +0 -73
  199. package/v3/@swarmdo/testing/dist/regression/security-regression.js +0 -258
  200. package/v3/@swarmdo/testing/dist/setup.d.ts +0 -43
  201. package/v3/@swarmdo/testing/dist/setup.js +0 -91
  202. package/v3/@swarmdo/testing/dist/v2-compat/api-compat.test.d.ts +0 -10
  203. package/v3/@swarmdo/testing/dist/v2-compat/api-compat.test.js +0 -433
  204. package/v3/@swarmdo/testing/dist/v2-compat/cli-compat.test.d.ts +0 -10
  205. package/v3/@swarmdo/testing/dist/v2-compat/cli-compat.test.js +0 -352
  206. package/v3/@swarmdo/testing/dist/v2-compat/compatibility-validator.d.ts +0 -206
  207. package/v3/@swarmdo/testing/dist/v2-compat/compatibility-validator.js +0 -839
  208. package/v3/@swarmdo/testing/dist/v2-compat/hooks-compat.test.d.ts +0 -10
  209. package/v3/@swarmdo/testing/dist/v2-compat/hooks-compat.test.js +0 -428
  210. package/v3/@swarmdo/testing/dist/v2-compat/index.d.ts +0 -38
  211. package/v3/@swarmdo/testing/dist/v2-compat/index.js +0 -41
  212. package/v3/@swarmdo/testing/dist/v2-compat/mcp-compat.test.d.ts +0 -10
  213. package/v3/@swarmdo/testing/dist/v2-compat/mcp-compat.test.js +0 -419
  214. package/v3/@swarmdo/testing/dist/v2-compat/report-generator.d.ts +0 -34
  215. package/v3/@swarmdo/testing/dist/v2-compat/report-generator.js +0 -372
@@ -323,7 +323,7 @@ function buildLocalFallback() {
323
323
  return applyLocalOverlays({
324
324
  user: { name: 'user', gitBranch: '', modelName: 'Claude Code' },
325
325
  v3Progress: { domainsCompleted: 0, totalDomains: 5, dddProgress: 0, patternsLearned: 0, sessionsCompleted: 0 },
326
- security: { status: 'NONE', cvesFixed: 0, totalCves: 0 },
326
+ security: { status: 'NONE', critical: 0, high: 0, total: 0 },
327
327
  swarm: { activeAgents: 0, maxAgents: CONFIG.maxAgents, coordinationActive: false },
328
328
  system: { memoryMB: memMB, contextPct: 0, intelligencePct: 0, subAgents: 0 },
329
329
  lastUpdated: new Date().toISOString(),
@@ -515,7 +515,7 @@ function getCostFromStdin() {
515
515
  // misses, the displayed version is meaningful (matches what the user
516
516
  // installed), not a stale hard-coded string.
517
517
  function getPkgVersion() {
518
- let ver = '1.3.30';
518
+ let ver = '1.6.0';
519
519
  try {
520
520
  const home = os.homedir();
521
521
  const pkgPaths = [
@@ -591,9 +591,9 @@ function generateStatusline() {
591
591
  const intelligencePct = system.intelligencePct || 0;
592
592
  const memoryMB = system.memoryMB || 0;
593
593
  const subAgents = system.subAgents || 0;
594
- const cvesFixed = security.cvesFixed || 0;
595
- const totalCves = security.totalCves || 0;
594
+ const secCritHigh = (security.critical || 0) + (security.high || 0);
596
595
  const secStatus = security.status || 'NONE';
596
+ const secLabel = secStatus === 'VULN' ? 'sec ' + secCritHigh + '!' : secStatus === 'CLEAN' ? 'sec ✓' : secStatus === 'STALE' ? 'sec stale' : 'sec —';
597
597
  const adrCount = adrs.count || 0;
598
598
  const adrImpl = adrs.implemented || 0;
599
599
  const hooksEnabled = hooks.enabled || 0;
@@ -659,8 +659,8 @@ function generateStatusline() {
659
659
  // Line 2: Swarm + Hooks + CVE + Memory + Intelligence
660
660
  const swarmInd = coordinationActive ? c.brightGreen + '◉' + c.reset : c.dim + '○' + c.reset;
661
661
  const agentsColor = activeAgents > 0 ? c.brightGreen : c.red;
662
- const secIcon = secStatus === 'CLEAN' ? '🟢' : (secStatus === 'IN_PROGRESS' || secStatus === 'STALE') ? '🟡' : (secStatus === 'NONE' ? '⚪' : '🔴');
663
- const secColor = secStatus === 'CLEAN' ? c.brightGreen : (secStatus === 'IN_PROGRESS' || secStatus === 'STALE') ? c.brightYellow : (secStatus === 'NONE' ? c.dim : c.brightRed);
662
+ const secIcon = secStatus === 'CLEAN' ? '🟢' : secStatus === 'STALE' ? '🟡' : (secStatus === 'NONE' ? '⚪' : '🔴');
663
+ const secColor = secStatus === 'CLEAN' ? c.brightGreen : secStatus === 'STALE' ? c.brightYellow : (secStatus === 'NONE' ? c.dim : c.brightRed);
664
664
  const hooksColor = hooksEnabled > 0 ? c.brightGreen : c.dim;
665
665
  const intellColor = intelligencePct >= 80 ? c.brightGreen : intelligencePct >= 40 ? c.brightYellow : c.dim;
666
666
 
@@ -668,7 +668,7 @@ function generateStatusline() {
668
668
  c.brightYellow + '🤖 Swarm' + c.reset + ' ' + swarmInd + ' [' + agentsColor + String(activeAgents).padStart(2) + c.reset + '/' + c.brightWhite + maxAgents + c.reset + '] ' +
669
669
  c.brightPurple + '👥 ' + subAgents + c.reset + ' ' +
670
670
  c.brightBlue + '🪝 ' + hooksColor + hooksEnabled + c.reset + '/' + c.brightWhite + hooksTotal + c.reset + ' ' +
671
- secIcon + ' ' + secColor + 'CVE ' + cvesFixed + c.reset + '/' + c.brightWhite + totalCves + c.reset + ' ' +
671
+ secIcon + ' ' + secColor + secLabel + c.reset + ' ' +
672
672
  c.brightCyan + '💾 ' + memoryMB + 'MB' + c.reset + ' ' +
673
673
  intellColor + '🧠 ' + String(intelligencePct).padStart(3) + '%' + c.reset
674
674
  );
package/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  [![swarmdo](swarmdo/assets/swarmdo-banner.svg)](https://swarmdo.com)
4
4
 
5
- [![npm version (swarmdo)](https://img.shields.io/badge/npx%20swarmdo-v1.4.8-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.6.0-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)
@@ -89,7 +89,7 @@ This adds slash commands and agent definitions only. The Swarmdo MCP server is N
89
89
  | [**swarmdo-agentdb**](plugins/swarmdo-agentdb/README.md) | Fast vector database for agent memory |
90
90
  | [**swarmdo-rag-memory**](plugins/swarmdo-rag-memory/README.md) | Smart retrieval — hybrid search, graph hops, diversity ranking |
91
91
  | [**swarmdo-rvf**](plugins/swarmdo-rvf/README.md) | Save and restore agent memory across sessions |
92
- | [**swarmdo-swarmvector**](plugins/swarmdo-swarmvector/README.md) | [`swarmvector`](https://npmjs.com/package/swarmvector) — GPU-accelerated search, Graph RAG, 103 tools |
92
+ | [**swarmdo-swarmvector**](plugins/swarmdo-swarmvector/README.md) | `swarmvector` (vendored in-repo at `v3/vendor/swarmvector`) — GPU-accelerated search, Graph RAG, 103 tools |
93
93
  | [**swarmdo-knowledge-graph**](plugins/swarmdo-knowledge-graph/README.md) | Build and traverse entity relationship maps |
94
94
 
95
95
  #### Intelligence & Learning
@@ -269,19 +269,22 @@ The recent release train added a full day-to-day operations layer around the swa
269
269
 
270
270
  | Command | What it does |
271
271
  |---------|-------------|
272
- | `swarmdo usage` (alias `cost`) | Claude Code **spend analytics** from your local transcripts — `daily`, `monthly`, `models`, `projects`, `sessions`, live 5-hour `blocks` burn, `errors` (tool-failure analytics), and `cache` (prompt-cache efficiency + $ saved) |
272
+ | `swarmdo usage` (alias `cost`) | Claude Code **spend analytics** from your local transcripts — `daily`, `monthly`, `models`, `projects`, `sessions`, live 5-hour `blocks` burn, `errors` (tool-failure analytics), `cache` (prompt-cache efficiency + $ saved), and `diff` (period-over-period comparison with per-model movers) |
273
273
  | `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 |
274
274
  | `swarmdo hud` | **One-screen ops HUD** — 5h block burn, task readiness, daemon workers, memory snapshots (`--watch`, `--json`) |
275
275
  | `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` |
276
- | `swarmdo task … --dependencies` | **Task dependency DAG** — `task ready` lists unblocked work, `task graph` renders the graph, the dispatcher gates on readiness |
276
+ | `swarmdo task … --dependencies` | **Task dependency DAG** — `task ready` lists unblocked work, `task graph` renders the graph, the dispatcher gates on readiness; `task parse-prd <spec.md>` decomposes a PRD straight into the DAG |
277
277
  | `swarmdo worktree` (alias `wt`) | **Parallel-agent isolation** on git worktrees — add / list / diff / merge / remove |
278
- | `swarmdo transcript` (alias `tx`) | **Export any Claude Code session** to clean markdown — system noise stripped, ready to share |
278
+ | `swarmdo transcript` (alias `tx`) | **Export any Claude Code session** to clean markdown — system noise stripped, ready to share; `transcript search <query>` full-text-searches every session |
279
+ | `swarmdo compact` | **Compress noisy command output** before it reaches an LLM — strip ANSI, collapse repeats, fold `node_modules` stack frames, window long logs. `npm test 2>&1 \| swarmdo compact` or `swarmdo compact -- npm test` (exit code propagates). Deterministic, zero tokens |
280
+ | `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) |
281
+ | OpenRouter model pool | **Let swarms pick from any models you configure** — declare tier-mapped OpenRouter models in `swarmdo.config.json`; the router Thompson-samples among them per task and the execution layer dispatches the winner |
279
282
  | `swarmdo changelog` (alias `notes`) | **Release notes from conventional commits** — `--out NOTES.md` feeds `gh release create --notes-file` |
280
283
  | `swarmdo mcp doctor` | **MCP config diagnosis** — missing binaries, bad URLs, malformed entries across `.mcp.json` + `~/.claude.json` |
281
284
  | `swarmdo hooks notify -d` | **Desktop notifications** — OS-native toast (macOS `osascript`, Linux `notify-send`) |
282
285
  | `swarmdo hooks recipe` | **One-command Claude Code hooks** — "ping me when Claude finishes / needs input"; dry-run by default, idempotent merge that never clobbers your settings |
283
286
  | `swarmdo preset` + `init --preset` | **5-tier capability ladder** — `minimal` → `basic`★ → `standard` → `advanced` → `max`; one word instead of dozens of flags |
284
- | `swarmdo memory export/import -f obsidian` | **Obsidian vault roundtrip** — DB → markdown notes (YAML frontmatter, `[[wikilinks]]` stay live) → edit in Obsidian → sync back, re-embedded |
287
+ | `swarmdo memory export/import -f obsidian` | **Obsidian vault roundtrip** — DB → markdown notes (YAML frontmatter, `[[wikilinks]]` stay live) → edit in Obsidian → sync back, re-embedded; `import --watch` keeps the vault live-synced as you edit |
285
288
  | `swarmdo memory backup` / `revectorize` | WAL-safe nightly DB snapshots · repair hash-era vectors |
286
289
 
287
290
  ```bash
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "swarmdo",
3
- "version": "1.4.8",
3
+ "version": "1.6.0",
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",
@@ -56,7 +56,9 @@
56
56
  "!.claude/**/*.db",
57
57
  "!.claude/**/*.map",
58
58
  "README.md",
59
- "LICENSE"
59
+ "LICENSE",
60
+ "!.claude/scheduled_tasks.lock",
61
+ "!.claude/**/__pycache__/**"
60
62
  ],
61
63
  "scripts": {
62
64
  "dev": "tsx watch src/index.ts",
@@ -86,7 +88,7 @@
86
88
  "@swarmdo/shared": "file:v3/@swarmdo/shared",
87
89
  "@swarmvector/rabitq-wasm": "file:v3/@swarmvector/rabitq-wasm",
88
90
  "agentic-flow": "file:v3/vendor/agentic-flow",
89
- "pg": "^8.22.0",
91
+ "pg": "8.22.0",
90
92
  "swarmvector": "file:v3/vendor/swarmvector",
91
93
  "swarmvector-attention-wasm": "file:v3/vendor/swarmvector-attention-wasm",
92
94
  "swarmvector-graph-transformer-wasm": "file:v3/vendor/swarmvector-graph-transformer-wasm",
@@ -0,0 +1,16 @@
1
+ /**
2
+ * `swarmdo compact` — compress noisy command output before it reaches an LLM.
3
+ *
4
+ * Two modes:
5
+ * npm test 2>&1 | swarmdo compact # stdin filter
6
+ * swarmdo compact -- npm test # wrap a command (stdout+stderr)
7
+ *
8
+ * Compacted text goes to stdout (pipeable); a one-line savings summary goes to
9
+ * stderr unless --quiet. When wrapping a command, the command's exit code is
10
+ * propagated verbatim — `swarmdo compact -- npm test` still fails if the tests
11
+ * fail. Deterministic, zero tokens (see ../compact/compact.ts).
12
+ */
13
+ import type { Command } from '../types.js';
14
+ export declare const compactCommand: Command;
15
+ export default compactCommand;
16
+ //# sourceMappingURL=compact.d.ts.map
@@ -0,0 +1,106 @@
1
+ /**
2
+ * `swarmdo compact` — compress noisy command output before it reaches an LLM.
3
+ *
4
+ * Two modes:
5
+ * npm test 2>&1 | swarmdo compact # stdin filter
6
+ * swarmdo compact -- npm test # wrap a command (stdout+stderr)
7
+ *
8
+ * Compacted text goes to stdout (pipeable); a one-line savings summary goes to
9
+ * stderr unless --quiet. When wrapping a command, the command's exit code is
10
+ * propagated verbatim — `swarmdo compact -- npm test` still fails if the tests
11
+ * fail. Deterministic, zero tokens (see ../compact/compact.ts).
12
+ */
13
+ import { spawnSync } from 'node:child_process';
14
+ import { output } from '../output.js';
15
+ import { compactOutput, formatSavings } from '../compact/compact.js';
16
+ /**
17
+ * Read all of stdin as UTF-8. A stream read (not readFileSync(0)) — the
18
+ * synchronous form throws EAGAIN on a non-blocking pipe on macOS/Linux.
19
+ */
20
+ function readStdin() {
21
+ return new Promise((resolve) => {
22
+ const chunks = [];
23
+ process.stdin.on('data', (c) => chunks.push(Buffer.from(c)));
24
+ process.stdin.on('end', () => resolve(Buffer.concat(chunks).toString('utf8')));
25
+ process.stdin.on('error', () => resolve(Buffer.concat(chunks).toString('utf8')));
26
+ });
27
+ }
28
+ function optsFromFlags(ctx) {
29
+ const opts = {
30
+ stripAnsi: ctx.flags['no-ansi'] !== true,
31
+ foldNodeModules: ctx.flags['no-fold'] !== true,
32
+ collapseBlanks: true,
33
+ };
34
+ if (typeof ctx.flags['min-run'] === 'number')
35
+ opts.minRun = ctx.flags['min-run'];
36
+ else if (typeof ctx.flags['min-run'] === 'string')
37
+ opts.minRun = parseInt(ctx.flags['min-run'], 10) || 3;
38
+ const win = ctx.flags.window;
39
+ if (typeof win === 'string' && /^\d+:\d+$/.test(win)) {
40
+ const [head, tail] = win.split(':').map((n) => parseInt(n, 10));
41
+ opts.window = { head, tail };
42
+ }
43
+ return opts;
44
+ }
45
+ async function run(ctx) {
46
+ const opts = optsFromFlags(ctx);
47
+ const quiet = ctx.flags.quiet === true;
48
+ // Command-wrap mode: everything after `--` is the command to run.
49
+ if (ctx.args.length > 0) {
50
+ const [cmd, ...cmdArgs] = ctx.args;
51
+ const r = spawnSync(cmd, cmdArgs, {
52
+ cwd: ctx.cwd,
53
+ encoding: 'utf8',
54
+ maxBuffer: 256 * 1024 * 1024,
55
+ // Merge streams so interleaved stdout/stderr stay in order.
56
+ stdio: ['inherit', 'pipe', 'pipe'],
57
+ });
58
+ if (r.error) {
59
+ output.printError(`failed to run ${cmd}: ${r.error.message}`);
60
+ return { success: false, exitCode: 127 };
61
+ }
62
+ const combined = (r.stdout || '') + (r.stderr || '');
63
+ const { text, stats } = compactOutput(combined, opts);
64
+ process.stdout.write(text);
65
+ if (!quiet)
66
+ process.stderr.write(formatSavings(stats) + '\n');
67
+ // Propagate the wrapped command's exit code verbatim.
68
+ const code = r.status ?? (r.signal ? 1 : 0);
69
+ return { success: code === 0, exitCode: code };
70
+ }
71
+ // Stdin-filter mode.
72
+ if (process.stdin.isTTY) {
73
+ output.writeln(output.error('Usage: swarmdo compact -- <command> OR <command> | swarmdo compact'));
74
+ return { success: false, exitCode: 1 };
75
+ }
76
+ const input = await readStdin();
77
+ const { text, stats } = compactOutput(input, opts);
78
+ if (ctx.flags['stats-json'] === true) {
79
+ process.stderr.write(JSON.stringify(stats) + '\n');
80
+ }
81
+ else if (!quiet) {
82
+ process.stderr.write(formatSavings(stats) + '\n');
83
+ }
84
+ process.stdout.write(text);
85
+ return { success: true, exitCode: 0 };
86
+ }
87
+ export const compactCommand = {
88
+ name: 'compact',
89
+ description: 'Compress noisy command output (tests/builds/logs) before it reaches an LLM — deterministic, zero tokens',
90
+ options: [
91
+ { name: 'no-ansi', description: 'keep ANSI colour/escape codes (default: strip)', type: 'boolean' },
92
+ { name: 'no-fold', description: 'keep full node_modules stack frames (default: fold)', type: 'boolean' },
93
+ { name: 'min-run', description: 'collapse a run of ≥N identical lines (default 3; 0 disables)', type: 'string' },
94
+ { name: 'window', description: 'keep first H + last T lines of long output, e.g. --window 40:20', type: 'string' },
95
+ { name: 'stats-json', description: 'emit compaction stats as JSON on stderr (stdin mode)', type: 'boolean' },
96
+ { name: 'quiet', description: 'suppress the savings summary on stderr', type: 'boolean' },
97
+ ],
98
+ examples: [
99
+ { command: 'npm test 2>&1 | swarmdo compact', description: 'Filter noisy test output on stdin' },
100
+ { command: 'swarmdo compact -- npm run build', description: 'Wrap a command; exit code propagates' },
101
+ { command: 'swarmdo compact --window 40:20 -- pnpm install', description: 'Head+tail window a long install log' },
102
+ ],
103
+ action: run,
104
+ };
105
+ export default compactCommand;
106
+ //# sourceMappingURL=compact.js.map
@@ -3413,32 +3413,34 @@ const statuslineCommand = {
3413
3413
  const dddProgress = Math.min(100, Math.floor((domainsCompleted / totalDomains) * 100));
3414
3414
  return { domainsCompleted, totalDomains, dddProgress, patternsLearned: learning.patterns, sessionsCompleted: learning.sessions };
3415
3415
  }
3416
- // Get security status
3416
+ // Get security status from the last real `security scan` artifact.
3417
+ // (Until v1.4.17 this counted files in never-written directories against a
3418
+ // hardcoded totalCves=3 — the V3-era CVE-1/2/3 tracker — so every install
3419
+ // showed PENDING forever.)
3417
3420
  function getSecurityStatus() {
3418
- const scanResultsPath = path.join(process.cwd(), '.claude', 'security-scans');
3419
- let cvesFixed = 0;
3420
- const totalCves = 3;
3421
- if (fs.existsSync(scanResultsPath)) {
3422
- try {
3423
- const scans = fs.readdirSync(scanResultsPath).filter((f) => f.endsWith('.json'));
3424
- cvesFixed = Math.min(totalCves, scans.length);
3425
- }
3426
- catch {
3427
- // Ignore
3428
- }
3429
- }
3430
- const auditPath = path.join(process.cwd(), '.swarm', 'security');
3431
- if (fs.existsSync(auditPath)) {
3421
+ const candidates = [
3422
+ path.join(process.cwd(), '.swarmdo', 'security', 'last-scan.json'),
3423
+ path.join(process.cwd(), '.swarm', 'security', 'last-scan.json'), // legacy layout
3424
+ ];
3425
+ for (const p of candidates) {
3432
3426
  try {
3433
- const audits = fs.readdirSync(auditPath).filter((f) => f.includes('audit'));
3434
- cvesFixed = Math.min(totalCves, Math.max(cvesFixed, audits.length));
3427
+ if (!fs.existsSync(p))
3428
+ continue;
3429
+ const scan = JSON.parse(fs.readFileSync(p, 'utf-8'));
3430
+ const critical = Number(scan.critical) || 0;
3431
+ const high = Number(scan.high) || 0;
3432
+ const total = Number(scan.total) || 0;
3433
+ const scannedAt = typeof scan.scannedAt === 'string' ? scan.scannedAt : null;
3434
+ const ageMs = scannedAt ? Date.now() - new Date(scannedAt).getTime() : Number.POSITIVE_INFINITY;
3435
+ const status = critical + high > 0 ? 'VULN' : ageMs > 7 * 24 * 3600 * 1000 ? 'STALE' : 'CLEAN';
3436
+ return { status, critical, high, total, scannedAt };
3435
3437
  }
3436
3438
  catch {
3437
- // Ignore
3439
+ // unreadable artifact — try next candidate
3438
3440
  }
3439
3441
  }
3440
- const status = cvesFixed >= totalCves ? 'CLEAN' : cvesFixed > 0 ? 'IN_PROGRESS' : 'PENDING';
3441
- return { status, cvesFixed, totalCves };
3442
+ // no scan has ever run nothing is "pending", there is just no data
3443
+ return { status: 'NONE', critical: 0, high: 0, total: 0, scannedAt: null };
3442
3444
  }
3443
3445
  // Get swarm status
3444
3446
  function getSwarmStatus() {
@@ -3578,7 +3580,7 @@ const statuslineCommand = {
3578
3580
  const terminalCols = process.stdout.columns ?? 80;
3579
3581
  const autoCompact = !ctx.flags.full && terminalCols < COMPACT_WIDTH_THRESHOLD;
3580
3582
  if (ctx.flags.compact || autoCompact) {
3581
- const line = `DDD:${progress.domainsCompleted}/${progress.totalDomains} CVE:${security.cvesFixed}/${security.totalCves} Swarm:${swarm.activeAgents}/${swarm.maxAgents} Ctx:${system.contextPct}% Int:${system.intelligencePct}%`;
3583
+ const line = `DDD:${progress.domainsCompleted}/${progress.totalDomains} Sec:${security.status} Swarm:${swarm.activeAgents}/${swarm.maxAgents} Ctx:${system.contextPct}% Int:${system.intelligencePct}%`;
3582
3584
  output.writeln(line);
3583
3585
  return { success: true, data: statusData };
3584
3586
  }
@@ -3752,13 +3754,13 @@ const statuslineCommand = {
3752
3754
  perfIndicator;
3753
3755
  const swarmIndicator = swarm.coordinationActive ? `${c.brightGreen}◉${c.reset}` : `${c.dim}○${c.reset}`;
3754
3756
  const agentsColor = swarm.activeAgents > 0 ? c.brightGreen : c.red;
3755
- const securityIcon = security.status === 'CLEAN' ? '🟢' : security.status === 'IN_PROGRESS' ? '🟡' : '🔴';
3756
- const securityColor = security.status === 'CLEAN' ? c.brightGreen : security.status === 'IN_PROGRESS' ? c.brightYellow : c.brightRed;
3757
+ const securityIcon = security.status === 'CLEAN' ? '🟢' : security.status === 'STALE' ? '🟡' : security.status === 'NONE' ? '⚪' : '🔴';
3758
+ const securityColor = security.status === 'CLEAN' ? c.brightGreen : security.status === 'STALE' ? c.brightYellow : security.status === 'NONE' ? c.dim : c.brightRed;
3757
3759
  const hooksColor = hooksStats.enabled > 0 ? c.brightGreen : c.dim;
3758
3760
  const line2 = `${c.brightYellow}🤖 Swarm${c.reset} ${swarmIndicator} [${agentsColor}${String(swarm.activeAgents).padStart(2)}${c.reset}/${c.brightWhite}${swarm.maxAgents}${c.reset}] ` +
3759
3761
  `${c.brightPurple}👥 ${system.subAgents}${c.reset} ` +
3760
3762
  `${c.brightBlue}🪝 ${hooksColor}${hooksStats.enabled}${c.reset}/${c.brightWhite}${hooksStats.total}${c.reset} ` +
3761
- `${securityIcon} ${securityColor}CVE ${security.cvesFixed}${c.reset}/${c.brightWhite}${security.totalCves}${c.reset} ` +
3763
+ `${securityIcon} ${securityColor}sec ${security.status === 'VULN' ? (security.critical + security.high) + '!' : security.status === 'CLEAN' ? '✓' : security.status === 'STALE' ? 'stale' : '—'}${c.reset} ` +
3762
3764
  `${c.brightCyan}💾 ${system.memoryMB}MB${c.reset} ` +
3763
3765
  `${c.brightPurple}🧠 ${String(system.intelligencePct).padStart(3)}%${c.reset}`;
3764
3766
  const dddColor = progress.dddProgress >= 50 ? c.brightGreen : progress.dddProgress > 0 ? c.yellow : c.red;
@@ -19,6 +19,9 @@ const commandLoaders = {
19
19
  status: () => import('./status.js'),
20
20
  statusline: () => import('./statusline.js'),
21
21
  compress: () => import('./compress.js'),
22
+ // Deterministic command-output compression (rtk/headroom demand) — a
23
+ // zero-token stream filter, distinct from caveman `compress` for files.
24
+ compact: () => import('./compact.js'),
22
25
  efficiency: () => import('./efficiency.js'),
23
26
  task: () => import('./task.js'),
24
27
  session: () => import('./session.js'),
@@ -68,6 +71,10 @@ const commandLoaders = {
68
71
  preset: () => import('./preset.js'),
69
72
  presets: () => import('./preset.js'), // alias via loader key
70
73
  // Release notes from conventional commits (git-cliff/conventional-changelog demand)
74
+ integrations: () => import('./integrations.js'),
75
+ integrate: () => import('./integrations.js'), // alias via loader key
76
+ release: () => import('./release.js'),
77
+ ship: () => import('./release.js'), // alias via loader key
71
78
  changelog: () => import('./changelog.js'),
72
79
  notes: () => import('./changelog.js'), // alias via loader key
73
80
  // Q-Learning Routing Commands
@@ -244,7 +251,7 @@ export async function getCommandsByCategory() {
244
251
  // three slots from 'statusline' onward (completionsCmd received the
245
252
  // statusline module, analyzeCmd received completions, …), scrambling the
246
253
  // categorized help. Every load now has a named slot.
247
- const [daemonCmd, doctorCmd, embeddingsCmd, neuralCmd, performanceCmd, securityCmd, swarmvectorCmd, hiveMindCmd, configCmd, statuslineCmd, compressCmd, efficiencyCmd, completionsCmd, migrateCmd, workflowCmd, analyzeCmd, routeCmd, progressCmd, providersCmd, pluginsCmd, deploymentCmd, claimsCmd, issuesCmd, updateCmd, processCmd, guidanceCmd, applianceCmd, cleanupCmd, autopilotCmd, demoCmd, usageCmd, repairCmd, hudCmd,] = await Promise.all([
254
+ const [daemonCmd, doctorCmd, embeddingsCmd, neuralCmd, performanceCmd, securityCmd, swarmvectorCmd, hiveMindCmd, configCmd, statuslineCmd, compressCmd, efficiencyCmd, completionsCmd, migrateCmd, workflowCmd, analyzeCmd, routeCmd, progressCmd, providersCmd, pluginsCmd, deploymentCmd, claimsCmd, issuesCmd, updateCmd, processCmd, guidanceCmd, applianceCmd, cleanupCmd, autopilotCmd, demoCmd, usageCmd, repairCmd, hudCmd, compactCmd,] = await Promise.all([
248
255
  loadCommand('daemon'), loadCommand('doctor'), loadCommand('embeddings'), loadCommand('neural'),
249
256
  loadCommand('performance'), loadCommand('security'), loadCommand('swarmvector'), loadCommand('hive-mind'),
250
257
  loadCommand('config'), loadCommand('statusline'), loadCommand('compress'), loadCommand('efficiency'),
@@ -252,7 +259,7 @@ export async function getCommandsByCategory() {
252
259
  loadCommand('analyze'), loadCommand('route'), loadCommand('progress'), loadCommand('providers'),
253
260
  loadCommand('plugins'), loadCommand('deployment'), loadCommand('claims'), loadCommand('issues'),
254
261
  loadCommand('update'), loadCommand('process'), loadCommand('guidance'), loadCommand('appliance'),
255
- loadCommand('cleanup'), loadCommand('autopilot'), loadCommand('demo'), loadCommand('usage'), loadCommand('repair'), loadCommand('hud'),
262
+ loadCommand('cleanup'), loadCommand('autopilot'), loadCommand('demo'), loadCommand('usage'), loadCommand('repair'), loadCommand('hud'), loadCommand('compact'),
256
263
  ]);
257
264
  return {
258
265
  primary: [
@@ -268,7 +275,7 @@ export async function getCommandsByCategory() {
268
275
  utility: [
269
276
  configCmd, doctorCmd, daemonCmd, completionsCmd,
270
277
  migrateCmd, workflowCmd, demoCmd,
271
- statuslineCmd, compressCmd, efficiencyCmd,
278
+ statuslineCmd, compressCmd, compactCmd, efficiencyCmd,
272
279
  ].filter(Boolean),
273
280
  analysis: [
274
281
  analyzeCmd, routeCmd, progressCmd, usageCmd, hudCmd,
@@ -0,0 +1,14 @@
1
+ /**
2
+ * integrations.ts — `swarmdo integrations` (alias `integrate`)
3
+ *
4
+ * Wire swarmdo into agent CLIs beyond Claude Code: Codex CLI, GitHub
5
+ * Copilot CLI, pi. Dry-run by default; `--apply` writes. All merges are
6
+ * additive + idempotent (pure engine in ../integrations/integrations.js).
7
+ *
8
+ * NEVER writes `.claude/**`, `.mcp.json`, or `CLAUDE.md` — the Claude Code
9
+ * integration is owned by `swarmdo init` and only read for status.
10
+ */
11
+ import type { Command } from '../types.js';
12
+ export declare const integrationsCommand: Command;
13
+ export default integrationsCommand;
14
+ //# sourceMappingURL=integrations.d.ts.map
@@ -0,0 +1,158 @@
1
+ /**
2
+ * integrations.ts — `swarmdo integrations` (alias `integrate`)
3
+ *
4
+ * Wire swarmdo into agent CLIs beyond Claude Code: Codex CLI, GitHub
5
+ * Copilot CLI, pi. Dry-run by default; `--apply` writes. All merges are
6
+ * additive + idempotent (pure engine in ../integrations/integrations.js).
7
+ *
8
+ * NEVER writes `.claude/**`, `.mcp.json`, or `CLAUDE.md` — the Claude Code
9
+ * integration is owned by `swarmdo init` and only read for status.
10
+ */
11
+ import * as fs from 'node:fs';
12
+ import * as path from 'node:path';
13
+ import * as os from 'node:os';
14
+ import { output } from '../output.js';
15
+ import { mergeCodexToml, mergeCopilotMcpJson, crossAgentAgentsMd, copilotInstructionsMd, evaluateStatus, INSTALLABLE, } from '../integrations/integrations.js';
16
+ function readOrNull(p) {
17
+ try {
18
+ return fs.readFileSync(p, 'utf8');
19
+ }
20
+ catch {
21
+ return null;
22
+ }
23
+ }
24
+ function planFor(target, cwd, home) {
25
+ const writes = [];
26
+ const notes = [];
27
+ const agentsPath = path.join(cwd, 'AGENTS.md');
28
+ const ensureAgentsMd = () => {
29
+ if (readOrNull(agentsPath) === null) {
30
+ writes.push({ file: agentsPath, kind: 'create', content: crossAgentAgentsMd() });
31
+ }
32
+ else {
33
+ notes.push('AGENTS.md already exists — left untouched (teams own their AGENTS.md)');
34
+ }
35
+ };
36
+ switch (target) {
37
+ case 'codex': {
38
+ ensureAgentsMd();
39
+ const tomlPath = path.join(home, '.codex', 'config.toml');
40
+ const merged = mergeCodexToml(readOrNull(tomlPath));
41
+ if (merged.changed)
42
+ writes.push({ file: tomlPath, kind: readOrNull(tomlPath) === null ? 'create' : 'update', content: merged.content });
43
+ else
44
+ notes.push('~/.codex/config.toml already has [mcp_servers.swarmdo]');
45
+ break;
46
+ }
47
+ case 'copilot': {
48
+ ensureAgentsMd();
49
+ const instrPath = path.join(cwd, '.github', 'copilot-instructions.md');
50
+ if (readOrNull(instrPath) === null)
51
+ writes.push({ file: instrPath, kind: 'create', content: copilotInstructionsMd() });
52
+ else
53
+ notes.push('.github/copilot-instructions.md already exists — left untouched');
54
+ const jsonPath = path.join(home, '.copilot', 'mcp-config.json');
55
+ const merged = mergeCopilotMcpJson(readOrNull(jsonPath));
56
+ if (merged.changed)
57
+ writes.push({ file: jsonPath, kind: readOrNull(jsonPath) === null ? 'create' : 'update', content: merged.content });
58
+ else
59
+ notes.push('~/.copilot/mcp-config.json already has the swarmdo server (or is unparseable — never clobbered)');
60
+ break;
61
+ }
62
+ case 'pi': {
63
+ ensureAgentsMd();
64
+ notes.push('pi reads AGENTS.md natively; if your pi build supports MCP servers, point it at: npx -y swarmdo@latest mcp start');
65
+ break;
66
+ }
67
+ case 'claude':
68
+ notes.push('Claude Code integration is managed by `swarmdo init` — nothing to install here (read-only status)');
69
+ break;
70
+ }
71
+ return { writes, notes };
72
+ }
73
+ export const integrationsCommand = {
74
+ name: 'integrations',
75
+ aliases: ['integrate'],
76
+ description: 'Wire swarmdo into other agent CLIs (codex, copilot, pi) via AGENTS.md + MCP — never touches the Claude Code surfaces',
77
+ options: [
78
+ { name: 'apply', type: 'boolean', description: 'write the changes (default: preview)', default: false },
79
+ { name: 'json', type: 'boolean', description: 'machine-readable output', default: false },
80
+ ],
81
+ examples: [
82
+ { command: 'swarmdo integrations', description: 'Status of every CLI integration' },
83
+ { command: 'swarmdo integrations install all --apply', description: 'Wire codex + copilot + pi' },
84
+ { command: 'swarmdo integrations install codex --apply', description: 'AGENTS.md + [mcp_servers.swarmdo] in ~/.codex/config.toml' },
85
+ ],
86
+ action: async (ctx) => {
87
+ const cwd = ctx.cwd || process.cwd();
88
+ const home = os.homedir();
89
+ const sub = (ctx.args[0] || 'status').toLowerCase();
90
+ const gatherStatus = () => evaluateStatus({
91
+ agentsMd: readOrNull(path.join(cwd, 'AGENTS.md')),
92
+ codexToml: readOrNull(path.join(home, '.codex', 'config.toml')),
93
+ copilotJson: readOrNull(path.join(home, '.copilot', 'mcp-config.json')),
94
+ copilotInstructions: readOrNull(path.join(cwd, '.github', 'copilot-instructions.md')),
95
+ claudeMcpJson: readOrNull(path.join(cwd, '.mcp.json')),
96
+ claudeUserJson: readOrNull(path.join(home, '.claude.json')),
97
+ claudeDirExists: fs.existsSync(path.join(cwd, '.claude')),
98
+ });
99
+ if (sub === 'status' || sub === 'list') {
100
+ const statuses = gatherStatus();
101
+ if (ctx.flags.json === true) {
102
+ output.printJson(statuses);
103
+ return { success: true, data: statuses };
104
+ }
105
+ output.writeln(output.bold('Agent CLI integrations'));
106
+ for (const s of statuses) {
107
+ output.writeln(` ${s.ok ? '◉' : '○'} ${s.target}`);
108
+ for (const d of s.details)
109
+ output.writeln(output.dim(` ${d}`));
110
+ }
111
+ output.writeln(output.dim('install: swarmdo integrations install <codex|copilot|pi|all> --apply'));
112
+ return { success: true };
113
+ }
114
+ if (sub !== 'install') {
115
+ output.printError(`unknown subcommand "${sub}" (expected status|install)`);
116
+ return { success: false, exitCode: 1 };
117
+ }
118
+ const rawTarget = (ctx.args[1] || '').toLowerCase();
119
+ const targets = rawTarget === 'all'
120
+ ? INSTALLABLE
121
+ : INSTALLABLE.includes(rawTarget) ? [rawTarget] : [];
122
+ if (targets.length === 0) {
123
+ output.printError(`install what? (${INSTALLABLE.join('|')}|all) — claude is managed by \`swarmdo init\``);
124
+ return { success: false, exitCode: 1 };
125
+ }
126
+ const allWrites = [];
127
+ for (const t of targets) {
128
+ const { writes, notes } = planFor(t, cwd, home);
129
+ output.writeln(output.bold(`▸ ${t}`));
130
+ for (const w of writes) {
131
+ // safety invariant: never under .claude/, never .mcp.json, never CLAUDE.md
132
+ const rel = path.relative(cwd, w.file);
133
+ if (rel.startsWith('.claude') || rel === '.mcp.json' || rel === 'CLAUDE.md') {
134
+ output.printError(`refusing to touch Claude Code surface: ${w.file}`);
135
+ return { success: false, exitCode: 1 };
136
+ }
137
+ output.writeln(` ${w.kind === 'create' ? '+' : '~'} ${w.file}`);
138
+ allWrites.push(w);
139
+ }
140
+ for (const n of notes)
141
+ output.writeln(output.dim(` · ${n}`));
142
+ }
143
+ if (ctx.flags.apply !== true) {
144
+ output.writeln('');
145
+ output.writeln(output.dim(`dry run — ${allWrites.length} write(s) planned; re-run with --apply`));
146
+ return { success: true, data: { dryRun: true, writes: allWrites.map((w) => w.file) } };
147
+ }
148
+ for (const w of allWrites) {
149
+ fs.mkdirSync(path.dirname(w.file), { recursive: true });
150
+ fs.writeFileSync(w.file, w.content, 'utf8');
151
+ }
152
+ output.printSuccess(`applied ${allWrites.length} write(s)`);
153
+ output.writeln(output.dim('restart the target CLI(s) to pick up MCP config changes'));
154
+ return { success: true, data: { applied: allWrites.map((w) => w.file) } };
155
+ },
156
+ };
157
+ export default integrationsCommand;
158
+ //# sourceMappingURL=integrations.js.map
@@ -1230,12 +1230,20 @@ const importCommand = {
1230
1230
  type: 'string',
1231
1231
  choices: ['json', 'obsidian', 'md'],
1232
1232
  default: 'json'
1233
+ },
1234
+ {
1235
+ name: 'watch',
1236
+ short: 'w',
1237
+ description: 'Keep watching the vault directory and sync notes as they change (obsidian format only; Ctrl-C to stop)',
1238
+ type: 'boolean',
1239
+ default: false
1233
1240
  }
1234
1241
  ],
1235
1242
  examples: [
1236
1243
  { command: 'swarmdo memory import -i ./backup.json', description: 'Import from file' },
1237
1244
  { command: 'swarmdo memory import -i ./data.json -n archive', description: 'Import to namespace' },
1238
- { command: 'swarmdo memory import -i ./vault -f obsidian', description: 'Sync an edited Obsidian vault back into memory (re-embeds; foreign notes skipped)' }
1245
+ { command: 'swarmdo memory import -i ./vault -f obsidian', description: 'Sync an edited Obsidian vault back into memory (re-embeds; foreign notes skipped)' },
1246
+ { command: 'swarmdo memory import -i ./vault -f obsidian --watch', description: 'Live-sync: watch the vault and import notes as you save them in Obsidian' }
1239
1247
  ],
1240
1248
  action: async (ctx) => {
1241
1249
  const inputPath = ctx.flags.input || ctx.args[0];
@@ -1290,6 +1298,47 @@ const importCommand = {
1290
1298
  `Foreign notes ignored: ${foreign}`,
1291
1299
  `Index files ignored: ${index}`,
1292
1300
  ]);
1301
+ if (ctx.flags.watch === true) {
1302
+ const { ChangeCollector } = await import('../memory-vault/watch.js');
1303
+ const { parseVault } = await import('../memory-vault/import.js');
1304
+ output.writeln(output.dim(`watching ${inputPath}/ — save a note in Obsidian to sync it (Ctrl-C to stop)`));
1305
+ const syncBatch = async (rels) => {
1306
+ const files = rels
1307
+ .filter((rel) => fs.existsSync(path.join(inputPath, rel)))
1308
+ .map((rel) => ({ relPath: rel, content: fs.readFileSync(path.join(inputPath, rel), 'utf8') }));
1309
+ const parsed = parseVault(files);
1310
+ if (parsed.entries.length === 0)
1311
+ return;
1312
+ const btmp = path.join(os.tmpdir(), `swarmdo-vaultwatch-${process.pid}-${Math.floor(Math.random() * 1e6)}.json`);
1313
+ try {
1314
+ fs.writeFileSync(btmp, JSON.stringify({ schema: 'swarmdo-memory-export/v1', entries: parsed.entries }), 'utf8');
1315
+ const r = await callMCPTool('memory_import', { inputPath: btmp, merge: true, namespace: ctx.flags.namespace });
1316
+ output.writeln(` ⇄ synced ${r.imported.entries} note${r.imported.entries === 1 ? '' : 's'}: ${rels.join(', ')}`);
1317
+ }
1318
+ catch (e) {
1319
+ output.printError(`sync failed for ${rels.join(', ')}: ${e instanceof MCPClientError ? e.message : String(e)}`);
1320
+ }
1321
+ finally {
1322
+ try {
1323
+ fs.rmSync(btmp, { force: true });
1324
+ }
1325
+ catch { /* best-effort */ }
1326
+ }
1327
+ };
1328
+ let syncing = Promise.resolve();
1329
+ const collector = new ChangeCollector((rels) => { syncing = syncing.then(() => syncBatch(rels)); });
1330
+ const watcher = fs.watch(inputPath, { recursive: true }, (_event, filename) => {
1331
+ if (filename)
1332
+ collector.add(String(filename));
1333
+ });
1334
+ await new Promise((resolve) => {
1335
+ const stop = () => { watcher.close(); collector.drain(); resolve(); };
1336
+ process.once('SIGINT', stop);
1337
+ process.once('SIGTERM', stop);
1338
+ });
1339
+ await syncing;
1340
+ return { success: true, data: { watched: true } };
1341
+ }
1293
1342
  return { success: true, data: { imported: result.imported.entries, foreign, index } };
1294
1343
  }
1295
1344
  catch (error) {
@@ -14,6 +14,9 @@ const PROVIDER_CATALOG = [
14
14
  // #1725: Ollama Cloud — Tier-2 default per ADR-026 (~$100/mo flat-rate alternative
15
15
  // to per-token pricing). OpenAI-compat API at https://ollama.com/v1/chat/completions.
16
16
  { name: 'Ollama', type: 'LLM', models: 'gpt-oss:120b-cloud, llama3:70b-cloud, qwen2.5-coder:32b-cloud', envVar: 'OLLAMA_API_KEY', configName: 'ollama' },
17
+ // Configurable multi-model gateway: swarms select among the models the
18
+ // user declares in swarmdo.config.json `openrouter.models` (tier-mapped).
19
+ { name: 'OpenRouter', type: 'LLM', models: 'any OpenRouter slug — pool configured in swarmdo.config.json', envVar: 'OPENROUTER_API_KEY', configName: 'openrouter' },
17
20
  { name: 'Transformers.js', type: 'Embedding', models: 'Xenova/all-MiniLM-L6-v2' },
18
21
  { name: 'Agentic Flow', type: 'Embedding', models: 'ONNX optimized' },
19
22
  { name: 'Mock', type: 'All', models: 'mock-*' },