kynjal-cli 3.1.4 → 4.0.1

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 (344) hide show
  1. package/.claude/agents/core/coder.md +1 -1
  2. package/.claude/agents/core/planner.md +2 -2
  3. package/.claude/agents/core/researcher.md +1 -1
  4. package/.claude/agents/core/reviewer.md +1 -1
  5. package/.claude/agents/core/tester.md +1 -1
  6. package/.claude/agents/data/data-ml-model.md +4 -4
  7. package/.claude/agents/development/dev-backend-api.md +4 -4
  8. package/.claude/agents/documentation/docs-api-openapi.md +4 -4
  9. package/.claude/agents/github/code-review-swarm.md +2 -2
  10. package/.claude/agents/github/issue-tracker.md +2 -2
  11. package/.claude/agents/github/pr-manager.md +2 -2
  12. package/.claude/agents/github/release-manager.md +2 -2
  13. package/.claude/agents/github/workflow-automation.md +2 -2
  14. package/.claude/agents/sparc/architecture.md +3 -3
  15. package/.claude/agents/sparc/pseudocode.md +2 -2
  16. package/.claude/agents/sparc/refinement.md +3 -3
  17. package/.claude/agents/sparc/specification.md +2 -2
  18. package/.claude/agents/swarm/adaptive-coordinator.md +1 -1
  19. package/.claude/agents/swarm/hierarchical-coordinator.md +1 -1
  20. package/.claude/agents/swarm/mesh-coordinator.md +1 -1
  21. package/.claude/agents/templates/base-template-generator.md +25 -4
  22. package/.claude/agents/templates/sparc-coordinator.md +3 -3
  23. package/.claude/helpers/auto-commit.sh +1 -1
  24. package/.claude/helpers/auto-memory-hook.mjs +27 -9
  25. package/.claude/helpers/hook-handler.cjs +58 -18
  26. package/.claude/helpers/statusline.cjs +420 -613
  27. package/.claude/helpers/statusline.js +3 -3
  28. package/.claude/settings.json +9 -9
  29. package/.claude/skills/reasoningbank-intelligence/SKILL.md +2 -2
  30. package/.claude/skills/swarm-orchestration/SKILL.md +1 -1
  31. package/README.md +383 -170
  32. package/bin/cli.js +6 -6
  33. package/bin/mcp-server.js +1 -1
  34. package/bin/preinstall.cjs +2 -0
  35. package/dist/src/appliance/gguf-engine.d.ts +91 -0
  36. package/dist/src/appliance/gguf-engine.d.ts.map +1 -0
  37. package/dist/src/appliance/gguf-engine.js +425 -0
  38. package/dist/src/appliance/gguf-engine.js.map +1 -0
  39. package/dist/src/appliance/ruvllm-bridge.d.ts +102 -0
  40. package/dist/src/appliance/ruvllm-bridge.d.ts.map +1 -0
  41. package/dist/src/appliance/ruvllm-bridge.js +292 -0
  42. package/dist/src/appliance/ruvllm-bridge.js.map +1 -0
  43. package/dist/src/appliance/rvfa-builder.d.ts +44 -0
  44. package/dist/src/appliance/rvfa-builder.d.ts.map +1 -0
  45. package/dist/src/appliance/rvfa-builder.js +329 -0
  46. package/dist/src/appliance/rvfa-builder.js.map +1 -0
  47. package/dist/src/appliance/rvfa-distribution.d.ts +97 -0
  48. package/dist/src/appliance/rvfa-distribution.d.ts.map +1 -0
  49. package/dist/src/appliance/rvfa-distribution.js +370 -0
  50. package/dist/src/appliance/rvfa-distribution.js.map +1 -0
  51. package/dist/src/appliance/rvfa-format.d.ts +111 -0
  52. package/dist/src/appliance/rvfa-format.d.ts.map +1 -0
  53. package/dist/src/appliance/rvfa-format.js +393 -0
  54. package/dist/src/appliance/rvfa-format.js.map +1 -0
  55. package/dist/src/appliance/rvfa-runner.d.ts +69 -0
  56. package/dist/src/appliance/rvfa-runner.d.ts.map +1 -0
  57. package/dist/src/appliance/rvfa-runner.js +237 -0
  58. package/dist/src/appliance/rvfa-runner.js.map +1 -0
  59. package/dist/src/appliance/rvfa-signing.d.ts +123 -0
  60. package/dist/src/appliance/rvfa-signing.d.ts.map +1 -0
  61. package/dist/src/appliance/rvfa-signing.js +347 -0
  62. package/dist/src/appliance/rvfa-signing.js.map +1 -0
  63. package/dist/src/commands/agent.d.ts.map +1 -1
  64. package/dist/src/commands/agent.js +121 -21
  65. package/dist/src/commands/agent.js.map +1 -1
  66. package/dist/src/commands/appliance-advanced.d.ts +9 -0
  67. package/dist/src/commands/appliance-advanced.d.ts.map +1 -0
  68. package/dist/src/commands/appliance-advanced.js +215 -0
  69. package/dist/src/commands/appliance-advanced.js.map +1 -0
  70. package/dist/src/commands/appliance.d.ts +8 -0
  71. package/dist/src/commands/appliance.d.ts.map +1 -0
  72. package/dist/src/commands/appliance.js +406 -0
  73. package/dist/src/commands/appliance.js.map +1 -0
  74. package/dist/src/commands/benchmark.js +2 -2
  75. package/dist/src/commands/benchmark.js.map +1 -1
  76. package/dist/src/commands/claims.js +1 -1
  77. package/dist/src/commands/claims.js.map +1 -1
  78. package/dist/src/commands/cleanup.d.ts +13 -0
  79. package/dist/src/commands/cleanup.d.ts.map +1 -0
  80. package/dist/src/commands/cleanup.js +218 -0
  81. package/dist/src/commands/cleanup.js.map +1 -0
  82. package/dist/src/commands/config.js +1 -1
  83. package/dist/src/commands/config.js.map +1 -1
  84. package/dist/src/commands/daemon.d.ts.map +1 -1
  85. package/dist/src/commands/daemon.js +81 -18
  86. package/dist/src/commands/daemon.js.map +1 -1
  87. package/dist/src/commands/deployment.js +1 -1
  88. package/dist/src/commands/deployment.js.map +1 -1
  89. package/dist/src/commands/doctor.d.ts.map +1 -1
  90. package/dist/src/commands/doctor.js +99 -51
  91. package/dist/src/commands/doctor.js.map +1 -1
  92. package/dist/src/commands/embeddings.js +1 -1
  93. package/dist/src/commands/embeddings.js.map +1 -1
  94. package/dist/src/commands/hive-mind.js +26 -26
  95. package/dist/src/commands/hive-mind.js.map +1 -1
  96. package/dist/src/commands/hooks.d.ts.map +1 -1
  97. package/dist/src/commands/hooks.js +800 -100
  98. package/dist/src/commands/hooks.js.map +1 -1
  99. package/dist/src/commands/index.d.ts +9 -2
  100. package/dist/src/commands/index.d.ts.map +1 -1
  101. package/dist/src/commands/index.js +20 -2
  102. package/dist/src/commands/index.js.map +1 -1
  103. package/dist/src/commands/init.d.ts +1 -1
  104. package/dist/src/commands/init.d.ts.map +1 -1
  105. package/dist/src/commands/init.js +22 -18
  106. package/dist/src/commands/init.js.map +1 -1
  107. package/dist/src/commands/mcp.d.ts.map +1 -1
  108. package/dist/src/commands/mcp.js +23 -5
  109. package/dist/src/commands/mcp.js.map +1 -1
  110. package/dist/src/commands/memory.d.ts.map +1 -1
  111. package/dist/src/commands/memory.js +24 -0
  112. package/dist/src/commands/memory.js.map +1 -1
  113. package/dist/src/commands/neural.d.ts.map +1 -1
  114. package/dist/src/commands/neural.js +13 -7
  115. package/dist/src/commands/neural.js.map +1 -1
  116. package/dist/src/commands/performance.js +1 -1
  117. package/dist/src/commands/performance.js.map +1 -1
  118. package/dist/src/commands/plugins.js +1 -1
  119. package/dist/src/commands/plugins.js.map +1 -1
  120. package/dist/src/commands/providers.js +1 -1
  121. package/dist/src/commands/providers.js.map +1 -1
  122. package/dist/src/commands/ruvector/import.js +2 -2
  123. package/dist/src/commands/ruvector/import.js.map +1 -1
  124. package/dist/src/commands/ruvector/index.js +1 -1
  125. package/dist/src/commands/ruvector/index.js.map +1 -1
  126. package/dist/src/commands/ruvector/setup.js +6 -6
  127. package/dist/src/commands/security.d.ts.map +1 -1
  128. package/dist/src/commands/security.js +47 -16
  129. package/dist/src/commands/security.js.map +1 -1
  130. package/dist/src/commands/session.d.ts +1 -1
  131. package/dist/src/commands/session.js +1 -1
  132. package/dist/src/commands/start.d.ts +1 -1
  133. package/dist/src/commands/start.js +12 -12
  134. package/dist/src/commands/start.js.map +1 -1
  135. package/dist/src/commands/status.d.ts +1 -1
  136. package/dist/src/commands/status.d.ts.map +1 -1
  137. package/dist/src/commands/status.js +13 -6
  138. package/dist/src/commands/status.js.map +1 -1
  139. package/dist/src/commands/swarm.js +2 -2
  140. package/dist/src/commands/swarm.js.map +1 -1
  141. package/dist/src/commands/task.d.ts +1 -1
  142. package/dist/src/commands/task.js +1 -1
  143. package/dist/src/commands/transfer-store.js +1 -1
  144. package/dist/src/commands/transfer-store.js.map +1 -1
  145. package/dist/src/config-adapter.js +1 -1
  146. package/dist/src/config-adapter.js.map +1 -1
  147. package/dist/src/index.d.ts +4 -3
  148. package/dist/src/index.d.ts.map +1 -1
  149. package/dist/src/index.js +5 -3
  150. package/dist/src/index.js.map +1 -1
  151. package/dist/src/init/claudemd-generator.js +30 -30
  152. package/dist/src/init/claudemd-generator.js.map +1 -1
  153. package/dist/src/init/executor.d.ts.map +1 -1
  154. package/dist/src/init/executor.js +86 -101
  155. package/dist/src/init/executor.js.map +1 -1
  156. package/dist/src/init/helpers-generator.d.ts.map +1 -1
  157. package/dist/src/init/helpers-generator.js +96 -26
  158. package/dist/src/init/helpers-generator.js.map +1 -1
  159. package/dist/src/init/mcp-generator.d.ts +0 -1
  160. package/dist/src/init/mcp-generator.d.ts.map +1 -1
  161. package/dist/src/init/mcp-generator.js +34 -18
  162. package/dist/src/init/mcp-generator.js.map +1 -1
  163. package/dist/src/init/settings-generator.d.ts.map +1 -1
  164. package/dist/src/init/settings-generator.js +107 -41
  165. package/dist/src/init/settings-generator.js.map +1 -1
  166. package/dist/src/init/statusline-generator.d.ts +16 -8
  167. package/dist/src/init/statusline-generator.d.ts.map +1 -1
  168. package/dist/src/init/statusline-generator.js +537 -1019
  169. package/dist/src/init/statusline-generator.js.map +1 -1
  170. package/dist/src/init/types.d.ts +14 -4
  171. package/dist/src/init/types.d.ts.map +1 -1
  172. package/dist/src/init/types.js +9 -2
  173. package/dist/src/init/types.js.map +1 -1
  174. package/dist/src/mcp-client.d.ts.map +1 -1
  175. package/dist/src/mcp-client.js +10 -0
  176. package/dist/src/mcp-client.js.map +1 -1
  177. package/dist/src/mcp-server.d.ts.map +1 -1
  178. package/dist/src/mcp-server.js +30 -4
  179. package/dist/src/mcp-server.js.map +1 -1
  180. package/dist/src/mcp-tools/agentdb-tools.d.ts +30 -0
  181. package/dist/src/mcp-tools/agentdb-tools.d.ts.map +1 -0
  182. package/dist/src/mcp-tools/agentdb-tools.js +557 -0
  183. package/dist/src/mcp-tools/agentdb-tools.js.map +1 -0
  184. package/dist/src/mcp-tools/browser-tools.js +2 -2
  185. package/dist/src/mcp-tools/browser-tools.js.map +1 -1
  186. package/dist/src/mcp-tools/config-tools.d.ts.map +1 -1
  187. package/dist/src/mcp-tools/config-tools.js +21 -2
  188. package/dist/src/mcp-tools/config-tools.js.map +1 -1
  189. package/dist/src/mcp-tools/coordination-tools.d.ts.map +1 -1
  190. package/dist/src/mcp-tools/coordination-tools.js +192 -13
  191. package/dist/src/mcp-tools/coordination-tools.js.map +1 -1
  192. package/dist/src/mcp-tools/daa-tools.js +5 -5
  193. package/dist/src/mcp-tools/daa-tools.js.map +1 -1
  194. package/dist/src/mcp-tools/github-tools.js +2 -2
  195. package/dist/src/mcp-tools/github-tools.js.map +1 -1
  196. package/dist/src/mcp-tools/hive-mind-tools.d.ts.map +1 -1
  197. package/dist/src/mcp-tools/hive-mind-tools.js +263 -35
  198. package/dist/src/mcp-tools/hive-mind-tools.js.map +1 -1
  199. package/dist/src/mcp-tools/hooks-tools.d.ts.map +1 -1
  200. package/dist/src/mcp-tools/hooks-tools.js +355 -40
  201. package/dist/src/mcp-tools/hooks-tools.js.map +1 -1
  202. package/dist/src/mcp-tools/index.d.ts +2 -0
  203. package/dist/src/mcp-tools/index.d.ts.map +1 -1
  204. package/dist/src/mcp-tools/index.js +2 -0
  205. package/dist/src/mcp-tools/index.js.map +1 -1
  206. package/dist/src/mcp-tools/memory-tools.d.ts.map +1 -1
  207. package/dist/src/mcp-tools/memory-tools.js +31 -1
  208. package/dist/src/mcp-tools/memory-tools.js.map +1 -1
  209. package/dist/src/mcp-tools/neural-tools.d.ts.map +1 -1
  210. package/dist/src/mcp-tools/neural-tools.js +32 -27
  211. package/dist/src/mcp-tools/neural-tools.js.map +1 -1
  212. package/dist/src/mcp-tools/performance-tools.js +1 -1
  213. package/dist/src/mcp-tools/performance-tools.js.map +1 -1
  214. package/dist/src/mcp-tools/ruvllm-tools.d.ts +9 -0
  215. package/dist/src/mcp-tools/ruvllm-tools.d.ts.map +1 -0
  216. package/dist/src/mcp-tools/ruvllm-tools.js +283 -0
  217. package/dist/src/mcp-tools/ruvllm-tools.js.map +1 -0
  218. package/dist/src/mcp-tools/swarm-tools.d.ts +2 -1
  219. package/dist/src/mcp-tools/swarm-tools.d.ts.map +1 -1
  220. package/dist/src/mcp-tools/swarm-tools.js +216 -30
  221. package/dist/src/mcp-tools/swarm-tools.js.map +1 -1
  222. package/dist/src/mcp-tools/system-tools.d.ts.map +1 -1
  223. package/dist/src/mcp-tools/system-tools.js +109 -6
  224. package/dist/src/mcp-tools/system-tools.js.map +1 -1
  225. package/dist/src/mcp-tools/task-tools.d.ts.map +1 -1
  226. package/dist/src/mcp-tools/task-tools.js +102 -0
  227. package/dist/src/mcp-tools/task-tools.js.map +1 -1
  228. package/dist/src/mcp-tools/wasm-agent-tools.d.ts +9 -0
  229. package/dist/src/mcp-tools/wasm-agent-tools.d.ts.map +1 -0
  230. package/dist/src/mcp-tools/wasm-agent-tools.js +230 -0
  231. package/dist/src/mcp-tools/wasm-agent-tools.js.map +1 -0
  232. package/dist/src/mcp-tools/workflow-tools.d.ts.map +1 -1
  233. package/dist/src/mcp-tools/workflow-tools.js +91 -0
  234. package/dist/src/mcp-tools/workflow-tools.js.map +1 -1
  235. package/dist/src/memory/ewc-consolidation.d.ts +24 -0
  236. package/dist/src/memory/ewc-consolidation.d.ts.map +1 -1
  237. package/dist/src/memory/ewc-consolidation.js +59 -0
  238. package/dist/src/memory/ewc-consolidation.js.map +1 -1
  239. package/dist/src/memory/intelligence.d.ts +53 -0
  240. package/dist/src/memory/intelligence.d.ts.map +1 -1
  241. package/dist/src/memory/intelligence.js +264 -7
  242. package/dist/src/memory/intelligence.js.map +1 -1
  243. package/dist/src/memory/memory-bridge.d.ts +407 -0
  244. package/dist/src/memory/memory-bridge.d.ts.map +1 -0
  245. package/dist/src/memory/memory-bridge.js +1494 -0
  246. package/dist/src/memory/memory-bridge.js.map +1 -0
  247. package/dist/src/memory/memory-initializer.d.ts +17 -1
  248. package/dist/src/memory/memory-initializer.d.ts.map +1 -1
  249. package/dist/src/memory/memory-initializer.js +320 -42
  250. package/dist/src/memory/memory-initializer.js.map +1 -1
  251. package/dist/src/output.d.ts.map +1 -1
  252. package/dist/src/output.js +1 -0
  253. package/dist/src/output.js.map +1 -1
  254. package/dist/src/parser.d.ts +10 -0
  255. package/dist/src/parser.d.ts.map +1 -1
  256. package/dist/src/parser.js +49 -3
  257. package/dist/src/parser.js.map +1 -1
  258. package/dist/src/plugins/manager.d.ts.map +1 -1
  259. package/dist/src/plugins/manager.js +31 -14
  260. package/dist/src/plugins/manager.js.map +1 -1
  261. package/dist/src/plugins/store/discovery.js +5 -5
  262. package/dist/src/plugins/store/discovery.js.map +1 -1
  263. package/dist/src/plugins/tests/standalone-test.js +4 -4
  264. package/dist/src/plugins/tests/standalone-test.js.map +1 -1
  265. package/dist/src/production/error-handler.js +1 -1
  266. package/dist/src/production/error-handler.js.map +1 -1
  267. package/dist/src/runtime/headless.d.ts +3 -3
  268. package/dist/src/runtime/headless.js +6 -6
  269. package/dist/src/runtime/headless.js.map +1 -1
  270. package/dist/src/ruvector/agent-wasm.d.ts +182 -0
  271. package/dist/src/ruvector/agent-wasm.d.ts.map +1 -0
  272. package/dist/src/ruvector/agent-wasm.js +316 -0
  273. package/dist/src/ruvector/agent-wasm.js.map +1 -0
  274. package/dist/src/ruvector/enhanced-model-router.d.ts.map +1 -1
  275. package/dist/src/ruvector/enhanced-model-router.js +25 -15
  276. package/dist/src/ruvector/enhanced-model-router.js.map +1 -1
  277. package/dist/src/ruvector/index.d.ts +7 -1
  278. package/dist/src/ruvector/index.d.ts.map +1 -1
  279. package/dist/src/ruvector/index.js +17 -1
  280. package/dist/src/ruvector/index.js.map +1 -1
  281. package/dist/src/ruvector/ruvllm-wasm.d.ts +179 -0
  282. package/dist/src/ruvector/ruvllm-wasm.d.ts.map +1 -0
  283. package/dist/src/ruvector/ruvllm-wasm.js +363 -0
  284. package/dist/src/ruvector/ruvllm-wasm.js.map +1 -0
  285. package/dist/src/services/agentic-flow-bridge.d.ts +50 -0
  286. package/dist/src/services/agentic-flow-bridge.d.ts.map +1 -0
  287. package/dist/src/services/agentic-flow-bridge.js +95 -0
  288. package/dist/src/services/agentic-flow-bridge.js.map +1 -0
  289. package/dist/src/services/claim-service.js +1 -1
  290. package/dist/src/services/claim-service.js.map +1 -1
  291. package/dist/src/services/container-worker-pool.d.ts.map +1 -1
  292. package/dist/src/services/container-worker-pool.js +3 -1
  293. package/dist/src/services/container-worker-pool.js.map +1 -1
  294. package/dist/src/services/index.d.ts +1 -1
  295. package/dist/src/services/index.d.ts.map +1 -1
  296. package/dist/src/services/registry-api.d.ts +1 -1
  297. package/dist/src/services/registry-api.js +1 -1
  298. package/dist/src/services/ruvector-training.d.ts +11 -2
  299. package/dist/src/services/ruvector-training.d.ts.map +1 -1
  300. package/dist/src/services/ruvector-training.js +233 -43
  301. package/dist/src/services/ruvector-training.js.map +1 -1
  302. package/dist/src/services/worker-daemon.d.ts +28 -3
  303. package/dist/src/services/worker-daemon.d.ts.map +1 -1
  304. package/dist/src/services/worker-daemon.js +156 -17
  305. package/dist/src/services/worker-daemon.js.map +1 -1
  306. package/dist/src/services/worker-queue.d.ts.map +1 -1
  307. package/dist/src/services/worker-queue.js +2 -0
  308. package/dist/src/services/worker-queue.js.map +1 -1
  309. package/dist/src/transfer/deploy-seraphine.d.ts +1 -1
  310. package/dist/src/transfer/deploy-seraphine.js +4 -4
  311. package/dist/src/transfer/deploy-seraphine.js.map +1 -1
  312. package/dist/src/transfer/ipfs/client.d.ts.map +1 -1
  313. package/dist/src/transfer/ipfs/client.js +8 -0
  314. package/dist/src/transfer/ipfs/client.js.map +1 -1
  315. package/dist/src/transfer/ipfs/upload.d.ts.map +1 -1
  316. package/dist/src/transfer/ipfs/upload.js +0 -2
  317. package/dist/src/transfer/ipfs/upload.js.map +1 -1
  318. package/dist/src/transfer/models/seraphine.d.ts +1 -1
  319. package/dist/src/transfer/models/seraphine.js +5 -5
  320. package/dist/src/transfer/models/seraphine.js.map +1 -1
  321. package/dist/src/transfer/serialization/cfp.d.ts +1 -1
  322. package/dist/src/transfer/serialization/cfp.d.ts.map +1 -1
  323. package/dist/src/transfer/serialization/cfp.js +9 -6
  324. package/dist/src/transfer/serialization/cfp.js.map +1 -1
  325. package/dist/src/transfer/storage/gcs.d.ts.map +1 -1
  326. package/dist/src/transfer/storage/gcs.js +71 -29
  327. package/dist/src/transfer/storage/gcs.js.map +1 -1
  328. package/dist/src/transfer/store/discovery.js +4 -4
  329. package/dist/src/transfer/store/discovery.js.map +1 -1
  330. package/dist/src/transfer/store/registry.js +1 -1
  331. package/dist/src/transfer/store/registry.js.map +1 -1
  332. package/dist/src/transfer/store/tests/standalone-test.js +4 -4
  333. package/dist/src/transfer/store/tests/standalone-test.js.map +1 -1
  334. package/dist/src/transfer/types.d.ts +1 -1
  335. package/dist/src/types.d.ts +1 -1
  336. package/dist/src/types.js +1 -1
  337. package/dist/src/update/validator.js +1 -1
  338. package/dist/src/update/validator.js.map +1 -1
  339. package/dist/tsconfig.tsbuildinfo +1 -1
  340. package/package.json +13 -10
  341. package/.claude/agents/custom/accessibility-auditor.yaml +0 -56
  342. package/.claude/agents/custom/design-architect.yaml +0 -48
  343. package/.claude/agents/custom/ui-developer.yaml +0 -46
  344. package/.claude/agents/custom/ux-researcher.yaml +0 -60
@@ -1,30 +1,48 @@
1
1
  #!/usr/bin/env node
2
2
  /**
3
- * KynjalFlow Statusline Generator (Optimized)
3
+ * RuFlo V3.5 Statusline Generator
4
4
  * Displays real-time V3 implementation progress and system status
5
5
  *
6
- * Usage: node statusline.cjs [--json] [--compact]
6
+ * Usage: node statusline.cjs [options]
7
7
  *
8
- * Performance notes:
9
- * - Single git execSync call (combines branch + status + upstream)
10
- * - No recursive file reading (only stat/readdir, never read test contents)
11
- * - No ps aux calls (uses process.memoryUsage() + file-based metrics)
12
- * - Strict 2s timeout on all execSync calls
13
- * - Shared settings cache across functions
8
+ * Options:
9
+ * (default) Safe multi-line output with collision zone avoidance
10
+ * --single Single-line output (completely avoids collision)
11
+ * --unsafe Legacy multi-line without collision avoidance
12
+ * --legacy Alias for --unsafe
13
+ * --json JSON output with pretty printing
14
+ * --compact JSON output without formatting
15
+ *
16
+ * Collision Zone Fix (Issue #985):
17
+ * Claude Code writes its internal status (e.g., "7s • 1p") at absolute
18
+ * terminal coordinates (columns 15-25 on second-to-last line). The safe
19
+ * mode pads the collision line with spaces to push content past column 25.
20
+ *
21
+ * IMPORTANT: This file uses .cjs extension to work in ES module projects.
22
+ * The require() syntax is intentional for CommonJS compatibility.
14
23
  */
15
24
 
16
25
  /* eslint-disable @typescript-eslint/no-var-requires */
17
26
  const fs = require('fs');
18
27
  const path = require('path');
19
28
  const { execSync } = require('child_process');
20
- const os = require('os');
21
29
 
22
30
  // Configuration
23
31
  const CONFIG = {
32
+ enabled: true,
33
+ showProgress: true,
34
+ showSecurity: true,
35
+ showSwarm: true,
36
+ showHooks: true,
37
+ showPerformance: true,
38
+ refreshInterval: 5000,
24
39
  maxAgents: 15,
40
+ topology: 'hierarchical-mesh',
25
41
  };
26
42
 
27
- const CWD = process.cwd();
43
+ // Cross-platform helpers
44
+ const isWindows = process.platform === 'win32';
45
+ const nullDevice = isWindows ? 'NUL' : '/dev/null';
28
46
 
29
47
  // ANSI colors
30
48
  const c = {
@@ -46,725 +64,514 @@ const c = {
46
64
  brightWhite: '\x1b[1;37m',
47
65
  };
48
66
 
49
- // Safe execSync with strict timeout (returns empty string on failure)
50
- function safeExec(cmd, timeoutMs = 2000) {
67
+ // Get user info
68
+ function getUserInfo() {
69
+ let name = 'user';
70
+ let gitBranch = '';
71
+ let modelName = 'Unknown';
72
+
51
73
  try {
52
- return execSync(cmd, {
53
- encoding: 'utf-8',
54
- timeout: timeoutMs,
55
- stdio: ['pipe', 'pipe', 'pipe'],
56
- }).trim();
57
- } catch {
58
- return '';
74
+ const gitUserCmd = isWindows
75
+ ? 'git config user.name 2>NUL || echo user'
76
+ : 'git config user.name 2>/dev/null || echo "user"';
77
+ const gitBranchCmd = isWindows
78
+ ? 'git branch --show-current 2>NUL || echo.'
79
+ : 'git branch --show-current 2>/dev/null || echo ""';
80
+ name = execSync(gitUserCmd, { encoding: 'utf-8' }).trim();
81
+ gitBranch = execSync(gitBranchCmd, { encoding: 'utf-8' }).trim();
82
+ if (gitBranch === '.') gitBranch = ''; // Windows echo. outputs a dot
83
+ } catch (e) {
84
+ // Ignore errors
59
85
  }
60
- }
61
86
 
62
- // Safe JSON file reader (returns null on failure)
63
- function readJSON(filePath) {
87
+ // Auto-detect model from Claude Code's config
64
88
  try {
65
- if (fs.existsSync(filePath)) {
66
- return JSON.parse(fs.readFileSync(filePath, 'utf-8'));
89
+ const homedir = require('os').homedir();
90
+ const claudeConfigPath = path.join(homedir, '.claude.json');
91
+ if (fs.existsSync(claudeConfigPath)) {
92
+ const claudeConfig = JSON.parse(fs.readFileSync(claudeConfigPath, 'utf-8'));
93
+ // Try to find lastModelUsage - check current dir and parent dirs
94
+ let lastModelUsage = null;
95
+ const cwd = process.cwd();
96
+ if (claudeConfig.projects) {
97
+ // Try exact match first, then check if cwd starts with any project path
98
+ for (const [projectPath, projectConfig] of Object.entries(claudeConfig.projects)) {
99
+ if (cwd === projectPath || cwd.startsWith(projectPath + '/')) {
100
+ lastModelUsage = projectConfig.lastModelUsage;
101
+ break;
102
+ }
103
+ }
104
+ }
105
+ if (lastModelUsage) {
106
+ const modelIds = Object.keys(lastModelUsage);
107
+ if (modelIds.length > 0) {
108
+ // Take the last model (most recently added to the object)
109
+ // Or find the one with most tokens (most actively used this session)
110
+ let modelId = modelIds[modelIds.length - 1];
111
+ if (modelIds.length > 1) {
112
+ // If multiple models, pick the one with most total tokens
113
+ let maxTokens = 0;
114
+ for (const id of modelIds) {
115
+ const usage = lastModelUsage[id];
116
+ const total = (usage.inputTokens || 0) + (usage.outputTokens || 0);
117
+ if (total > maxTokens) {
118
+ maxTokens = total;
119
+ modelId = id;
120
+ }
121
+ }
122
+ }
123
+ // Parse model ID to human-readable name
124
+ if (modelId.includes('opus')) modelName = 'Opus 4.6 (1M context)';
125
+ else if (modelId.includes('sonnet')) modelName = 'Sonnet 4.6';
126
+ else if (modelId.includes('haiku')) modelName = 'Haiku 4.5';
127
+ else modelName = modelId.split('-').slice(1, 3).join(' ');
128
+ }
129
+ }
67
130
  }
68
- } catch { /* ignore */ }
69
- return null;
70
- }
71
-
72
- // Safe file stat (returns null on failure)
73
- function safeStat(filePath) {
74
- try {
75
- return fs.statSync(filePath);
76
- } catch { /* ignore */ }
77
- return null;
78
- }
131
+ } catch (e) {
132
+ // Fallback to Unknown if can't read config
133
+ }
79
134
 
80
- // Shared settings cache — read once, used by multiple functions
81
- let _settingsCache = undefined;
82
- function getSettings() {
83
- if (_settingsCache !== undefined) return _settingsCache;
84
- _settingsCache = readJSON(path.join(CWD, '.claude', 'settings.json'))
85
- || readJSON(path.join(CWD, '.claude', 'settings.local.json'))
86
- || null;
87
- return _settingsCache;
135
+ return { name, gitBranch, modelName };
88
136
  }
89
137
 
90
- // ─── Data Collection (all pure-Node.js or single-exec) ──────────
91
-
92
- // Get all git info in ONE shell call
93
- function getGitInfo() {
94
- const result = {
95
- name: 'user', gitBranch: '', modified: 0, untracked: 0,
96
- staged: 0, ahead: 0, behind: 0,
97
- };
138
+ // Get learning stats from intelligence loop data (ADR-050)
139
+ function getLearningStats() {
140
+ let patterns = 0;
141
+ let sessions = 0;
142
+ let trajectories = 0;
143
+ let edges = 0;
144
+ let confidenceMean = 0;
145
+ let accessedCount = 0;
146
+ let trend = 'STABLE';
147
+
148
+ // PRIMARY: Read from intelligence loop data files
149
+ const dataDir = path.join(process.cwd(), '.claude-flow', 'data');
150
+
151
+ // 1. graph-state.json — authoritative node/edge counts
152
+ const graphPath = path.join(dataDir, 'graph-state.json');
153
+ if (fs.existsSync(graphPath)) {
154
+ try {
155
+ const graph = JSON.parse(fs.readFileSync(graphPath, 'utf-8'));
156
+ patterns = graph.nodes ? Object.keys(graph.nodes).length : 0;
157
+ edges = Array.isArray(graph.edges) ? graph.edges.length : 0;
158
+ } catch (e) { /* ignore */ }
159
+ }
98
160
 
99
- // Single shell: get user.name, branch, porcelain status, and upstream diff
100
- const script = [
101
- 'git config user.name 2>/dev/null || echo user',
102
- 'echo "---SEP---"',
103
- 'git branch --show-current 2>/dev/null',
104
- 'echo "---SEP---"',
105
- 'git status --porcelain 2>/dev/null',
106
- 'echo "---SEP---"',
107
- 'git rev-list --left-right --count HEAD...@{upstream} 2>/dev/null || echo "0 0"',
108
- ].join('; ');
109
-
110
- const raw = safeExec(`sh -c '${script}'`, 3000);
111
- if (!raw) return result;
112
-
113
- const parts = raw.split('---SEP---').map(s => s.trim());
114
- if (parts.length >= 4) {
115
- result.name = parts[0] || 'user';
116
- result.gitBranch = parts[1] || '';
117
-
118
- // Parse porcelain status
119
- if (parts[2]) {
120
- for (const line of parts[2].split('\n')) {
121
- if (!line || line.length < 2) continue;
122
- const x = line[0], y = line[1];
123
- if (x === '?' && y === '?') { result.untracked++; continue; }
124
- if (x !== ' ' && x !== '?') result.staged++;
125
- if (y !== ' ' && y !== '?') result.modified++;
161
+ // 2. ranked-context.json confidence and access data
162
+ const rankedPath = path.join(dataDir, 'ranked-context.json');
163
+ if (fs.existsSync(rankedPath)) {
164
+ try {
165
+ const ranked = JSON.parse(fs.readFileSync(rankedPath, 'utf-8'));
166
+ if (ranked.entries && ranked.entries.length > 0) {
167
+ patterns = Math.max(patterns, ranked.entries.length);
168
+ let confSum = 0;
169
+ let accCount = 0;
170
+ for (let i = 0; i < ranked.entries.length; i++) {
171
+ confSum += (ranked.entries[i].confidence || 0);
172
+ if ((ranked.entries[i].accessCount || 0) > 0) accCount++;
173
+ }
174
+ confidenceMean = confSum / ranked.entries.length;
175
+ accessedCount = accCount;
126
176
  }
127
- }
177
+ } catch (e) { /* ignore */ }
178
+ }
128
179
 
129
- // Parse ahead/behind
130
- const ab = (parts[3] || '0 0').split(/\s+/);
131
- result.ahead = parseInt(ab[0]) || 0;
132
- result.behind = parseInt(ab[1]) || 0;
180
+ // 3. intelligence-snapshot.json — trend history
181
+ const snapshotPath = path.join(dataDir, 'intelligence-snapshot.json');
182
+ if (fs.existsSync(snapshotPath)) {
183
+ try {
184
+ const snapshot = JSON.parse(fs.readFileSync(snapshotPath, 'utf-8'));
185
+ if (snapshot.history && snapshot.history.length >= 2) {
186
+ const first = snapshot.history[0];
187
+ const last = snapshot.history[snapshot.history.length - 1];
188
+ const confDrift = (last.confidenceMean || 0) - (first.confidenceMean || 0);
189
+ trend = confDrift > 0.01 ? 'IMPROVING' : confDrift < -0.01 ? 'DECLINING' : 'STABLE';
190
+ sessions = Math.max(sessions, snapshot.history.length);
191
+ }
192
+ } catch (e) { /* ignore */ }
133
193
  }
134
194
 
135
- return result;
136
- }
195
+ // 4. auto-memory-store.json — fallback entry count
196
+ if (patterns === 0) {
197
+ const autoMemPath = path.join(dataDir, 'auto-memory-store.json');
198
+ if (fs.existsSync(autoMemPath)) {
199
+ try {
200
+ const data = JSON.parse(fs.readFileSync(autoMemPath, 'utf-8'));
201
+ patterns = Array.isArray(data) ? data.length : (data.entries ? data.entries.length : 0);
202
+ } catch (e) { /* ignore */ }
203
+ }
204
+ }
137
205
 
138
- // Detect model name from Claude config (pure file reads, no exec)
139
- function getModelName() {
140
- try {
141
- const claudeConfig = readJSON(path.join(os.homedir(), '.claude.json'));
142
- if (claudeConfig?.projects) {
143
- for (const [projectPath, projectConfig] of Object.entries(claudeConfig.projects)) {
144
- if (CWD === projectPath || CWD.startsWith(projectPath + '/')) {
145
- const usage = projectConfig.lastModelUsage;
146
- if (usage) {
147
- const ids = Object.keys(usage);
148
- if (ids.length > 0) {
149
- let modelId = ids[ids.length - 1];
150
- let latest = 0;
151
- for (const id of ids) {
152
- const ts = usage[id]?.lastUsedAt ? new Date(usage[id].lastUsedAt).getTime() : 0;
153
- if (ts > latest) { latest = ts; modelId = id; }
154
- }
155
- if (modelId.includes('opus')) return 'Opus 4.6';
156
- if (modelId.includes('sonnet')) return 'Sonnet 4.6';
157
- if (modelId.includes('haiku')) return 'Haiku 4.5';
158
- return modelId.split('-').slice(1, 3).join(' ');
159
- }
160
- }
206
+ // FALLBACK: Legacy memory.db file-size estimation
207
+ if (patterns === 0) {
208
+ const memoryPaths = [
209
+ path.join(process.cwd(), '.swarm', 'memory.db'),
210
+ path.join(process.cwd(), '.claude', 'memory.db'),
211
+ path.join(process.cwd(), 'data', 'memory.db'),
212
+ ];
213
+ for (let j = 0; j < memoryPaths.length; j++) {
214
+ if (fs.existsSync(memoryPaths[j])) {
215
+ try {
216
+ const dbStats = fs.statSync(memoryPaths[j]);
217
+ patterns = Math.floor(dbStats.size / 1024 / 2);
161
218
  break;
162
- }
219
+ } catch (e) { /* ignore */ }
163
220
  }
164
221
  }
165
- } catch { /* ignore */ }
166
-
167
- // Fallback: settings.json model field
168
- const settings = getSettings();
169
- if (settings?.model) {
170
- const m = settings.model;
171
- if (m.includes('opus')) return 'Opus 4.6';
172
- if (m.includes('sonnet')) return 'Sonnet 4.6';
173
- if (m.includes('haiku')) return 'Haiku 4.5';
174
222
  }
175
- return 'Claude Code';
176
- }
177
223
 
178
- // Get learning stats from memory database (pure stat calls)
179
- function getLearningStats() {
180
- const memoryPaths = [
181
- path.join(CWD, '.swarm', 'memory.db'),
182
- path.join(CWD, '.kynjalflow', 'memory.db'),
183
- path.join(CWD, '.claude', 'memory.db'),
184
- path.join(CWD, 'data', 'memory.db'),
185
- path.join(CWD, '.agentdb', 'memory.db'),
186
- ];
187
-
188
- for (const dbPath of memoryPaths) {
189
- const stat = safeStat(dbPath);
190
- if (stat) {
191
- const sizeKB = stat.size / 1024;
192
- const patterns = Math.floor(sizeKB / 2);
193
- return {
194
- patterns,
195
- sessions: Math.max(1, Math.floor(patterns / 10)),
196
- };
197
- }
224
+ // Session count from session files
225
+ const sessionsPath = path.join(process.cwd(), '.claude', 'sessions');
226
+ if (fs.existsSync(sessionsPath)) {
227
+ try {
228
+ const sessionFiles = fs.readdirSync(sessionsPath).filter(f => f.endsWith('.json'));
229
+ sessions = Math.max(sessions, sessionFiles.length);
230
+ } catch (e) { /* ignore */ }
198
231
  }
199
232
 
200
- // Check session files count
201
- let sessions = 0;
202
- try {
203
- const sessDir = path.join(CWD, '.claude', 'sessions');
204
- if (fs.existsSync(sessDir)) {
205
- sessions = fs.readdirSync(sessDir).filter(f => f.endsWith('.json')).length;
206
- }
207
- } catch { /* ignore */ }
233
+ trajectories = Math.floor(patterns / 5);
208
234
 
209
- return { patterns: 0, sessions };
235
+ return { patterns, sessions, trajectories, edges, confidenceMean, accessedCount, trend };
210
236
  }
211
237
 
212
- // V3 progress from metrics files (pure file reads)
238
+ // Get V3 progress from learning state (grows as system learns)
213
239
  function getV3Progress() {
214
240
  const learning = getLearningStats();
215
- const totalDomains = 5;
216
241
 
217
- const dddData = readJSON(path.join(CWD, '.kynjalflow', 'metrics', 'ddd-progress.json'));
218
- let dddProgress = dddData?.progress || 0;
219
- let domainsCompleted = Math.min(5, Math.floor(dddProgress / 20));
220
-
221
- if (dddProgress === 0 && learning.patterns > 0) {
222
- if (learning.patterns >= 500) domainsCompleted = 5;
223
- else if (learning.patterns >= 200) domainsCompleted = 4;
224
- else if (learning.patterns >= 100) domainsCompleted = 3;
225
- else if (learning.patterns >= 50) domainsCompleted = 2;
226
- else if (learning.patterns >= 10) domainsCompleted = 1;
227
- dddProgress = Math.floor((domainsCompleted / totalDomains) * 100);
228
- }
242
+ // DDD progress based on actual learned patterns
243
+ // New install: 0 patterns = 0/5 domains, 0% DDD
244
+ // As patterns grow: 10+ patterns = 1 domain, 50+ = 2, 100+ = 3, 200+ = 4, 500+ = 5
245
+ let domainsCompleted = 0;
246
+ if (learning.patterns >= 500) domainsCompleted = 5;
247
+ else if (learning.patterns >= 200) domainsCompleted = 4;
248
+ else if (learning.patterns >= 100) domainsCompleted = 3;
249
+ else if (learning.patterns >= 50) domainsCompleted = 2;
250
+ else if (learning.patterns >= 10) domainsCompleted = 1;
251
+
252
+ const totalDomains = 5;
253
+ const dddProgress = Math.min(100, Math.floor((domainsCompleted / totalDomains) * 100));
229
254
 
230
255
  return {
231
- domainsCompleted, totalDomains, dddProgress,
256
+ domainsCompleted,
257
+ totalDomains,
258
+ dddProgress,
232
259
  patternsLearned: learning.patterns,
233
- sessionsCompleted: learning.sessions,
260
+ sessionsCompleted: learning.sessions
234
261
  };
235
262
  }
236
263
 
237
- // Security status (pure file reads)
264
+ // Get security status based on actual scans
238
265
  function getSecurityStatus() {
239
- const auditData = readJSON(path.join(CWD, '.kynjalflow', 'security', 'audit-status.json'));
240
- if (auditData) {
241
- const auditDate = auditData.lastAudit || auditData.lastScan;
242
- if (!auditDate) {
243
- // No audit has ever run — show as pending, not stale
244
- return { status: 'PENDING', cvesFixed: 0, totalCves: 0 };
266
+ // Check for security scan results in memory
267
+ const scanResultsPath = path.join(process.cwd(), '.claude', 'security-scans');
268
+ let cvesFixed = 0;
269
+ const totalCves = 3;
270
+
271
+ if (fs.existsSync(scanResultsPath)) {
272
+ try {
273
+ const scans = fs.readdirSync(scanResultsPath).filter(f => f.endsWith('.json'));
274
+ // Each successful scan file = 1 CVE addressed
275
+ cvesFixed = Math.min(totalCves, scans.length);
276
+ } catch (e) {
277
+ // Ignore
245
278
  }
246
- const auditAge = Date.now() - new Date(auditDate).getTime();
247
- const isStale = auditAge > 7 * 24 * 60 * 60 * 1000;
248
- return {
249
- status: isStale ? 'STALE' : (auditData.status || 'PENDING'),
250
- cvesFixed: auditData.cvesFixed || 0,
251
- totalCves: auditData.totalCves || 0,
252
- };
253
279
  }
254
280
 
255
- let scanCount = 0;
256
- try {
257
- const scanDir = path.join(CWD, '.claude', 'security-scans');
258
- if (fs.existsSync(scanDir)) {
259
- scanCount = fs.readdirSync(scanDir).filter(f => f.endsWith('.json')).length;
281
+ // Also check .swarm/security for audit results
282
+ const auditPath = path.join(process.cwd(), '.swarm', 'security');
283
+ if (fs.existsSync(auditPath)) {
284
+ try {
285
+ const audits = fs.readdirSync(auditPath).filter(f => f.includes('audit'));
286
+ cvesFixed = Math.min(totalCves, Math.max(cvesFixed, audits.length));
287
+ } catch (e) {
288
+ // Ignore
260
289
  }
261
- } catch { /* ignore */ }
290
+ }
291
+
292
+ const status = cvesFixed >= totalCves ? 'CLEAN' : cvesFixed > 0 ? 'IN_PROGRESS' : 'PENDING';
262
293
 
263
294
  return {
264
- status: scanCount > 0 ? 'SCANNED' : 'NONE',
265
- cvesFixed: 0,
266
- totalCves: 0,
295
+ status,
296
+ cvesFixed,
297
+ totalCves,
267
298
  };
268
299
  }
269
300
 
270
- // Swarm status (pure file reads, NO ps aux)
301
+ // Get swarm status
271
302
  function getSwarmStatus() {
272
- // Check swarm state file — only trust if recently updated (within 5 min)
273
- const staleThresholdMs = 5 * 60 * 1000;
274
- const now = Date.now();
275
-
276
- const swarmStatePath = path.join(CWD, '.kynjalflow', 'swarm', 'swarm-state.json');
277
- const swarmState = readJSON(swarmStatePath);
278
- if (swarmState) {
279
- const updatedAt = swarmState.updatedAt || swarmState.startedAt;
280
- const age = updatedAt ? now - new Date(updatedAt).getTime() : Infinity;
281
- if (age < staleThresholdMs) {
282
- return {
283
- activeAgents: swarmState.agents?.length || swarmState.agentCount || 0,
284
- maxAgents: swarmState.maxAgents || CONFIG.maxAgents,
285
- coordinationActive: true,
286
- };
287
- }
288
- }
303
+ let activeAgents = 0;
304
+ let coordinationActive = false;
289
305
 
290
- const activityData = readJSON(path.join(CWD, '.kynjalflow', 'metrics', 'swarm-activity.json'));
291
- if (activityData?.swarm) {
292
- const updatedAt = activityData.timestamp || activityData.swarm.timestamp;
293
- const age = updatedAt ? now - new Date(updatedAt).getTime() : Infinity;
294
- if (age < staleThresholdMs) {
295
- return {
296
- activeAgents: activityData.swarm.agent_count || 0,
297
- maxAgents: CONFIG.maxAgents,
298
- coordinationActive: activityData.swarm.coordination_active || activityData.swarm.active || false,
299
- };
306
+ try {
307
+ if (isWindows) {
308
+ // Windows: use tasklist and findstr
309
+ const ps = execSync('tasklist 2>NUL | findstr /I "agentic-flow" 2>NUL | find /C /V "" 2>NUL || echo 0', { encoding: 'utf-8' });
310
+ activeAgents = Math.max(0, parseInt(ps.trim()) || 0);
311
+ } else {
312
+ const ps = execSync('ps aux 2>/dev/null | grep -c agentic-flow || echo "0"', { encoding: 'utf-8' });
313
+ activeAgents = Math.max(0, parseInt(ps.trim()) - 1);
300
314
  }
315
+ coordinationActive = activeAgents > 0;
316
+ } catch (e) {
317
+ // Ignore errors - default to 0 agents
301
318
  }
302
319
 
303
- return { activeAgents: 0, maxAgents: CONFIG.maxAgents, coordinationActive: false };
320
+ return {
321
+ activeAgents,
322
+ maxAgents: CONFIG.maxAgents,
323
+ coordinationActive,
324
+ };
304
325
  }
305
326
 
306
- // System metrics (uses process.memoryUsage() no shell spawn)
327
+ // Get system metrics (dynamic based on actual state)
307
328
  function getSystemMetrics() {
308
- const memoryMB = Math.floor(process.memoryUsage().heapUsed / 1024 / 1024);
309
- const learning = getLearningStats();
310
- const agentdb = getAgentDBStats();
311
-
312
- // Intelligence from learning.json
313
- const learningData = readJSON(path.join(CWD, '.kynjalflow', 'metrics', 'learning.json'));
314
- let intelligencePct = 0;
315
- let contextPct = 0;
316
-
317
- if (learningData?.intelligence?.score !== undefined) {
318
- intelligencePct = Math.min(100, Math.floor(learningData.intelligence.score));
319
- } else {
320
- // Use actual vector/entry counts — 2000 entries = 100%
321
- const fromPatterns = learning.patterns > 0 ? Math.min(100, Math.floor(learning.patterns / 20)) : 0;
322
- const fromVectors = agentdb.vectorCount > 0 ? Math.min(100, Math.floor(agentdb.vectorCount / 20)) : 0;
323
- intelligencePct = Math.max(fromPatterns, fromVectors);
324
- }
325
-
326
- // Maturity fallback (pure fs checks, no git exec)
327
- if (intelligencePct === 0) {
328
- let score = 0;
329
- if (fs.existsSync(path.join(CWD, '.claude'))) score += 15;
330
- const srcDirs = ['src', 'lib', 'app', 'packages', 'v3'];
331
- for (const d of srcDirs) { if (fs.existsSync(path.join(CWD, d))) { score += 15; break; } }
332
- const testDirs = ['tests', 'test', '__tests__', 'spec'];
333
- for (const d of testDirs) { if (fs.existsSync(path.join(CWD, d))) { score += 10; break; } }
334
- const cfgFiles = ['package.json', 'tsconfig.json', 'pyproject.toml', 'Cargo.toml', 'go.mod'];
335
- for (const f of cfgFiles) { if (fs.existsSync(path.join(CWD, f))) { score += 5; break; } }
336
- intelligencePct = Math.min(100, score);
337
- }
338
-
339
- if (learningData?.sessions?.total !== undefined) {
340
- contextPct = Math.min(100, learningData.sessions.total * 5);
341
- } else {
342
- contextPct = Math.min(100, Math.floor(learning.sessions * 5));
343
- }
344
-
345
- // Sub-agents from file metrics (no ps aux)
329
+ let memoryMB = 0;
346
330
  let subAgents = 0;
347
- const activityData = readJSON(path.join(CWD, '.kynjalflow', 'metrics', 'swarm-activity.json'));
348
- if (activityData?.processes?.estimated_agents) {
349
- subAgents = activityData.processes.estimated_agents;
350
- }
351
-
352
- return { memoryMB, contextPct, intelligencePct, subAgents };
353
- }
354
-
355
- // ADR status (count files only — don't read contents)
356
- function getADRStatus() {
357
- // Count actual ADR files first — compliance JSON may be stale
358
- const adrPaths = [
359
- path.join(CWD, 'v3', 'implementation', 'adrs'),
360
- path.join(CWD, 'docs', 'adrs'),
361
- path.join(CWD, '.kynjalflow', 'adrs'),
362
- ];
363
-
364
- for (const adrPath of adrPaths) {
365
- try {
366
- if (fs.existsSync(adrPath)) {
367
- const files = fs.readdirSync(adrPath).filter(f =>
368
- f.endsWith('.md') && (f.startsWith('ADR-') || f.startsWith('adr-') || /^\d{4}-/.test(f))
369
- );
370
- // Report actual count — don't guess compliance without reading files
371
- return { count: files.length, implemented: files.length, compliance: 0 };
372
- }
373
- } catch { /* ignore */ }
374
- }
375
-
376
- return { count: 0, implemented: 0, compliance: 0 };
377
- }
378
-
379
- // Hooks status (shared settings cache)
380
- function getHooksStatus() {
381
- let enabled = 0;
382
- let total = 0;
383
- const settings = getSettings();
384
-
385
- if (settings?.hooks) {
386
- for (const category of Object.keys(settings.hooks)) {
387
- const matchers = settings.hooks[category];
388
- if (!Array.isArray(matchers)) continue;
389
- for (const matcher of matchers) {
390
- const hooks = matcher?.hooks;
391
- if (Array.isArray(hooks)) {
392
- total += hooks.length;
393
- enabled += hooks.length;
394
- }
395
- }
396
- }
397
- }
398
331
 
399
332
  try {
400
- const hooksDir = path.join(CWD, '.claude', 'hooks');
401
- if (fs.existsSync(hooksDir)) {
402
- const hookFiles = fs.readdirSync(hooksDir).filter(f => f.endsWith('.js') || f.endsWith('.sh')).length;
403
- total = Math.max(total, hookFiles);
404
- enabled = Math.max(enabled, hookFiles);
333
+ if (isWindows) {
334
+ // Windows: use tasklist for memory info, fallback to process.memoryUsage
335
+ // tasklist memory column is complex to parse, use Node.js API instead
336
+ memoryMB = Math.floor(process.memoryUsage().heapUsed / 1024 / 1024);
337
+ } else {
338
+ const mem = execSync('ps aux | grep -E "(node|agentic|claude)" | grep -v grep | awk \'{sum += $6} END {print int(sum/1024)}\'', { encoding: 'utf-8' });
339
+ memoryMB = parseInt(mem.trim()) || 0;
405
340
  }
406
- } catch { /* ignore */ }
407
-
408
- return { enabled, total };
409
- }
410
-
411
- // AgentDB stats — count real entries, not file-size heuristics
412
- function getAgentDBStats() {
413
- let vectorCount = 0;
414
- let dbSizeKB = 0;
415
- let namespaces = 0;
416
- let hasHnsw = false;
417
-
418
- // 1. Count real entries from auto-memory-store.json
419
- const storePath = path.join(CWD, '.kynjalflow', 'data', 'auto-memory-store.json');
420
- const storeStat = safeStat(storePath);
421
- if (storeStat) {
422
- dbSizeKB += storeStat.size / 1024;
423
- try {
424
- const store = JSON.parse(fs.readFileSync(storePath, 'utf-8'));
425
- if (Array.isArray(store)) vectorCount += store.length;
426
- else if (store?.entries) vectorCount += store.entries.length;
427
- } catch { /* fall back to size estimate */ }
341
+ } catch (e) {
342
+ // Fallback
343
+ memoryMB = Math.floor(process.memoryUsage().heapUsed / 1024 / 1024);
428
344
  }
429
345
 
430
- // 2. Count entries from ranked-context.json
431
- const rankedPath = path.join(CWD, '.kynjalflow', 'data', 'ranked-context.json');
432
- try {
433
- const ranked = readJSON(rankedPath);
434
- if (ranked?.entries?.length > vectorCount) vectorCount = ranked.entries.length;
435
- } catch { /* ignore */ }
436
-
437
- // 3. Add DB file sizes
438
- const dbFiles = [
439
- path.join(CWD, 'data', 'memory.db'),
440
- path.join(CWD, '.kynjalflow', 'memory.db'),
441
- path.join(CWD, '.swarm', 'memory.db'),
442
- ];
443
- for (const f of dbFiles) {
444
- const stat = safeStat(f);
445
- if (stat) {
446
- dbSizeKB += stat.size / 1024;
447
- namespaces++;
448
- }
449
- }
450
-
451
- // 4. Check for graph data
452
- const graphPath = path.join(CWD, 'data', 'memory.graph');
453
- const graphStat = safeStat(graphPath);
454
- if (graphStat) dbSizeKB += graphStat.size / 1024;
455
-
456
- // 5. HNSW index
457
- const hnswPaths = [
458
- path.join(CWD, '.swarm', 'hnsw.index'),
459
- path.join(CWD, '.kynjalflow', 'hnsw.index'),
460
- ];
461
- for (const p of hnswPaths) {
462
- const stat = safeStat(p);
463
- if (stat) {
464
- hasHnsw = true;
465
- break;
466
- }
467
- }
468
-
469
- // HNSW is available if memory package is present
470
- if (!hasHnsw) {
471
- const memPkgPaths = [
472
- path.join(CWD, 'v3', '@claude-flow', 'memory', 'dist'),
473
- path.join(CWD, 'node_modules', '@claude-flow', 'memory'),
474
- ];
475
- for (const p of memPkgPaths) {
476
- if (fs.existsSync(p)) { hasHnsw = true; break; }
477
- }
478
- }
479
-
480
- return { vectorCount, dbSizeKB: Math.floor(dbSizeKB), namespaces, hasHnsw };
481
- }
482
-
483
- // Test stats (count files only — NO reading file contents)
484
- function getTestStats() {
485
- let testFiles = 0;
346
+ // Get learning stats for intelligence %
347
+ const learning = getLearningStats();
486
348
 
487
- function countTestFiles(dir, depth = 0) {
488
- if (depth > 6) return;
489
- try {
490
- if (!fs.existsSync(dir)) return;
491
- const entries = fs.readdirSync(dir, { withFileTypes: true });
492
- for (const entry of entries) {
493
- if (entry.isDirectory() && !entry.name.startsWith('.') && entry.name !== 'node_modules') {
494
- countTestFiles(path.join(dir, entry.name), depth + 1);
495
- } else if (entry.isFile()) {
496
- const n = entry.name;
497
- if (n.includes('.test.') || n.includes('.spec.') || n.includes('_test.') || n.includes('_spec.')) {
498
- testFiles++;
499
- }
500
- }
501
- }
502
- } catch { /* ignore */ }
349
+ // Intelligence % from REAL intelligence loop data (ADR-050)
350
+ // Composite: 40% confidence mean + 30% access ratio + 30% pattern density
351
+ let intelligencePct = 0;
352
+ if (learning.confidenceMean > 0 || (learning.patterns > 0 && learning.accessedCount > 0)) {
353
+ const confScore = Math.min(100, Math.floor(learning.confidenceMean * 100));
354
+ const accessRatio = learning.patterns > 0 ? (learning.accessedCount / learning.patterns) : 0;
355
+ const accessScore = Math.min(100, Math.floor(accessRatio * 100));
356
+ const densityScore = Math.min(100, Math.floor(learning.patterns / 5));
357
+ intelligencePct = Math.floor(confScore * 0.4 + accessScore * 0.3 + densityScore * 0.3);
503
358
  }
504
-
505
- // Scan all source directories
506
- for (const d of ['tests', 'test', '__tests__', 'src', 'v3']) {
507
- countTestFiles(path.join(CWD, d));
359
+ // Fallback: legacy pattern count
360
+ if (intelligencePct === 0 && learning.patterns > 0) {
361
+ intelligencePct = Math.min(100, Math.floor(learning.patterns / 10));
508
362
  }
509
363
 
510
- // Estimate ~4 test cases per file (avoids reading every file)
511
- return { testFiles, testCases: testFiles * 4 };
512
- }
364
+ // Context % based on session history
365
+ const contextPct = Math.min(100, Math.floor(learning.sessions * 5));
513
366
 
514
- // Integration status (shared settings + file checks)
515
- function getIntegrationStatus() {
516
- const mcpServers = { total: 0, enabled: 0 };
517
- const settings = getSettings();
518
-
519
- if (settings?.mcpServers && typeof settings.mcpServers === 'object') {
520
- const servers = Object.keys(settings.mcpServers);
521
- mcpServers.total = servers.length;
522
- mcpServers.enabled = settings.enabledMcpjsonServers
523
- ? settings.enabledMcpjsonServers.filter(s => servers.includes(s)).length
524
- : servers.length;
525
- }
526
-
527
- // Fallback: .mcp.json
528
- if (mcpServers.total === 0) {
529
- const mcpConfig = readJSON(path.join(CWD, '.mcp.json'))
530
- || readJSON(path.join(os.homedir(), '.claude', 'mcp.json'));
531
- if (mcpConfig?.mcpServers) {
532
- const s = Object.keys(mcpConfig.mcpServers);
533
- mcpServers.total = s.length;
534
- mcpServers.enabled = s.length;
367
+ // Count active sub-agents from process list
368
+ try {
369
+ if (isWindows) {
370
+ // Windows: use tasklist and findstr for agent counting
371
+ const agents = execSync('tasklist 2>NUL | findstr /I "claude-flow" 2>NUL | find /C /V "" 2>NUL || echo 0', { encoding: 'utf-8' });
372
+ subAgents = Math.max(0, parseInt(agents.trim()) || 0);
373
+ } else {
374
+ const agents = execSync('ps aux 2>/dev/null | grep -c "claude-flow.*agent" || echo "0"', { encoding: 'utf-8' });
375
+ subAgents = Math.max(0, parseInt(agents.trim()) - 1);
535
376
  }
377
+ } catch (e) {
378
+ // Ignore - default to 0
536
379
  }
537
380
 
538
- const hasDatabase = ['.swarm/memory.db', '.kynjalflow/memory.db', 'data/memory.db']
539
- .some(p => fs.existsSync(path.join(CWD, p)));
540
- const hasApi = !!(process.env.ANTHROPIC_API_KEY || process.env.OPENAI_API_KEY);
541
-
542
- return { mcpServers, hasDatabase, hasApi };
543
- }
544
-
545
- // Session stats (pure file reads)
546
- function getSessionStats() {
547
- for (const p of ['.kynjalflow/session.json', '.claude/session.json']) {
548
- const data = readJSON(path.join(CWD, p));
549
- if (data?.startTime) {
550
- const diffMs = Date.now() - new Date(data.startTime).getTime();
551
- const mins = Math.floor(diffMs / 60000);
552
- const duration = mins < 60 ? `${mins}m` : `${Math.floor(mins / 60)}h${mins % 60}m`;
553
- return { duration };
554
- }
555
- }
556
- return { duration: '' };
381
+ return {
382
+ memoryMB,
383
+ contextPct,
384
+ intelligencePct,
385
+ subAgents,
386
+ };
557
387
  }
558
388
 
559
- // ─── Rendering ──────────────────────────────────────────────────
560
-
389
+ // Generate progress bar
561
390
  function progressBar(current, total) {
562
391
  const width = 5;
563
392
  const filled = Math.round((current / total) * width);
564
- return '[' + '\u25CF'.repeat(filled) + '\u25CB'.repeat(width - filled) + ']';
393
+ const empty = width - filled;
394
+ return '[' + '\u25CF'.repeat(filled) + '\u25CB'.repeat(empty) + ']';
565
395
  }
566
396
 
567
- // Single-line statusline for Claude Code's status bar
397
+ // Generate full statusline
568
398
  function generateStatusline() {
569
- const git = getGitInfo();
570
- const modelName = getModelName();
399
+ const user = getUserInfo();
400
+ const progress = getV3Progress();
401
+ const security = getSecurityStatus();
571
402
  const swarm = getSwarmStatus();
572
403
  const system = getSystemMetrics();
573
- const session = getSessionStats();
574
- const hooks = getHooksStatus();
575
- const integration = getIntegrationStatus();
576
-
577
- const parts = [];
578
-
579
- // Branding
580
- parts.push(`${c.bold}${c.brightPurple}\u258A KynjalFlow${c.reset}`);
581
-
582
- // User + swarm indicator
583
- const dot = swarm.coordinationActive ? `${c.brightGreen}\u25CF${c.reset}` : `${c.brightCyan}\u25CF${c.reset}`;
584
- parts.push(`${dot} ${c.brightCyan}${git.name}${c.reset}`);
585
-
586
- // Git branch + changes
587
- if (git.gitBranch) {
588
- let branchPart = `${c.brightBlue}\u23C7 ${git.gitBranch}${c.reset}`;
589
- const changes = [];
590
- if (git.staged > 0) changes.push(`${c.brightGreen}+${git.staged}${c.reset}`);
591
- if (git.modified > 0) changes.push(`${c.brightYellow}~${git.modified}${c.reset}`);
592
- if (git.untracked > 0) changes.push(`${c.dim}?${git.untracked}${c.reset}`);
593
- if (changes.length > 0) branchPart += ` ${changes.join('')}`;
594
- if (git.ahead > 0) branchPart += ` ${c.brightGreen}\u2191${git.ahead}${c.reset}`;
595
- if (git.behind > 0) branchPart += ` ${c.brightRed}\u2193${git.behind}${c.reset}`;
596
- parts.push(branchPart);
404
+ const lines = [];
405
+
406
+ // Header Line
407
+ let header = `${c.bold}${c.brightPurple}▊ RuFlo V3.5 ${c.reset}`;
408
+ header += `${swarm.coordinationActive ? c.brightCyan : c.dim}● ${c.brightCyan}${user.name}${c.reset}`;
409
+ if (user.gitBranch) {
410
+ header += ` ${c.dim}│${c.reset} ${c.brightBlue}⎇ ${user.gitBranch}${c.reset}`;
597
411
  }
412
+ header += ` ${c.dim}│${c.reset} ${c.purple}${user.modelName}${c.reset}`;
413
+ lines.push(header);
598
414
 
599
- // Model
600
- parts.push(`${c.purple}${modelName}${c.reset}`);
415
+ // Separator
416
+ lines.push(`${c.dim}─────────────────────────────────────────────────────${c.reset}`);
601
417
 
602
- // Session duration
603
- if (session.duration) {
604
- parts.push(`${c.cyan}\u23F1 ${session.duration}${c.reset}`);
605
- }
418
+ // Line 1: DDD Domain Progress
419
+ const domainsColor = progress.domainsCompleted >= 3 ? c.brightGreen : progress.domainsCompleted > 0 ? c.yellow : c.red;
420
+ lines.push(
421
+ `${c.brightCyan}🏗️ DDD Domains${c.reset} ${progressBar(progress.domainsCompleted, progress.totalDomains)} ` +
422
+ `${domainsColor}${progress.domainsCompleted}${c.reset}/${c.brightWhite}${progress.totalDomains}${c.reset} ` +
423
+ `${c.brightYellow}⚡ 1.0x${c.reset} ${c.dim}→${c.reset} ${c.brightYellow}2.49x-7.47x${c.reset}`
424
+ );
606
425
 
607
- // Intelligence %
608
- const intellColor = system.intelligencePct >= 80 ? c.brightGreen : system.intelligencePct >= 40 ? c.brightYellow : c.dim;
609
- parts.push(`${intellColor}\u25CF ${system.intelligencePct}%${c.reset}`);
426
+ // Line 2: Swarm + CVE + Memory + Context + Intelligence
427
+ const swarmIndicator = swarm.coordinationActive ? `${c.brightGreen}◉${c.reset}` : `${c.dim}○${c.reset}`;
428
+ const agentsColor = swarm.activeAgents > 0 ? c.brightGreen : c.red;
429
+ let securityIcon = security.status === 'CLEAN' ? '🟢' : security.status === 'IN_PROGRESS' ? '🟡' : '🔴';
430
+ let securityColor = security.status === 'CLEAN' ? c.brightGreen : security.status === 'IN_PROGRESS' ? c.brightYellow : c.brightRed;
610
431
 
611
- // Swarm agents (only if active)
612
- if (swarm.activeAgents > 0 || swarm.coordinationActive) {
613
- parts.push(`${c.brightYellow}\u25C9 ${swarm.activeAgents}/${swarm.maxAgents}${c.reset}`);
614
- }
432
+ lines.push(
433
+ `${c.brightYellow}🤖 Swarm${c.reset} ${swarmIndicator} [${agentsColor}${String(swarm.activeAgents).padStart(2)}${c.reset}/${c.brightWhite}${swarm.maxAgents}${c.reset}] ` +
434
+ `${c.brightPurple}👥 ${system.subAgents}${c.reset} ` +
435
+ `${securityIcon} ${securityColor}CVE ${security.cvesFixed}${c.reset}/${c.brightWhite}${security.totalCves}${c.reset} ` +
436
+ `${c.brightCyan}💾 ${system.memoryMB}MB${c.reset} ` +
437
+ `${c.brightGreen}📂 ${String(system.contextPct).padStart(3)}%${c.reset} ` +
438
+ `${c.dim}🧠 ${String(system.intelligencePct).padStart(3)}%${c.reset}`
439
+ );
615
440
 
616
- // Hooks (compact)
617
- if (hooks.enabled > 0) {
618
- parts.push(`${c.brightGreen}\u2713${hooks.enabled}h${c.reset}`);
619
- }
441
+ // Line 3: Architecture status
442
+ const dddColor = progress.dddProgress >= 50 ? c.brightGreen : progress.dddProgress > 0 ? c.yellow : c.red;
443
+ lines.push(
444
+ `${c.brightPurple}🔧 Architecture${c.reset} ` +
445
+ `${c.cyan}DDD${c.reset} ${dddColor}●${String(progress.dddProgress).padStart(3)}%${c.reset} ${c.dim}│${c.reset} ` +
446
+ `${c.cyan}Security${c.reset} ${securityColor}●${security.status}${c.reset} ${c.dim}│${c.reset} ` +
447
+ `${c.cyan}Memory${c.reset} ${c.brightGreen}●AgentDB${c.reset} ${c.dim}│${c.reset} ` +
448
+ `${c.cyan}Integration${c.reset} ${swarm.coordinationActive ? c.brightCyan : c.dim}●${c.reset}`
449
+ );
620
450
 
621
- // MCP (compact)
622
- if (integration.mcpServers.total > 0) {
623
- const mcpCol = integration.mcpServers.enabled === integration.mcpServers.total ? c.brightGreen : c.brightYellow;
624
- parts.push(`${mcpCol}MCP${integration.mcpServers.enabled}${c.reset}`);
625
- }
451
+ return lines.join('\n');
452
+ }
626
453
 
627
- return parts.join(` ${c.dim}\u2502${c.reset} `);
454
+ // Generate JSON data
455
+ function generateJSON() {
456
+ return {
457
+ user: getUserInfo(),
458
+ v3Progress: getV3Progress(),
459
+ security: getSecurityStatus(),
460
+ swarm: getSwarmStatus(),
461
+ system: getSystemMetrics(),
462
+ performance: {
463
+ flashAttentionTarget: '2.49x-7.47x',
464
+ searchImprovement: '150x-12,500x',
465
+ memoryReduction: '50-75%',
466
+ },
467
+ lastUpdated: new Date().toISOString(),
468
+ };
628
469
  }
629
470
 
630
- // Multi-line dashboard (for --dashboard flag)
631
- function generateDashboard() {
632
- const git = getGitInfo();
633
- const modelName = getModelName();
471
+ /**
472
+ * Generate single-line output for Claude Code compatibility
473
+ * This avoids the collision zone issue entirely by using one line
474
+ * @see https://github.com/ruvnet/claude-flow/issues/985
475
+ */
476
+ function generateSingleLine() {
477
+ if (!CONFIG.enabled) return '';
478
+
479
+ const user = getUserInfo();
480
+ const progress = getV3Progress();
481
+ const security = getSecurityStatus();
482
+ const swarm = getSwarmStatus();
483
+ const system = getSystemMetrics();
484
+
485
+ const swarmIndicator = swarm.coordinationActive ? '●' : '○';
486
+ const securityStatus = security.status === 'CLEAN' ? '✓' :
487
+ security.cvesFixed > 0 ? '~' : '✗';
488
+
489
+ return `${c.brightPurple}RuFlo${c.reset} ${c.dim}|${c.reset} ` +
490
+ `${c.cyan}D:${progress.domainsCompleted}/${progress.totalDomains}${c.reset} ${c.dim}|${c.reset} ` +
491
+ `${c.yellow}S:${swarmIndicator}${swarm.activeAgents}/${swarm.maxAgents}${c.reset} ${c.dim}|${c.reset} ` +
492
+ `${security.status === 'CLEAN' ? c.green : c.red}CVE:${securityStatus}${security.cvesFixed}/${security.totalCves}${c.reset} ${c.dim}|${c.reset} ` +
493
+ `${c.dim}🧠${system.intelligencePct}%${c.reset}`;
494
+ }
495
+
496
+ /**
497
+ * Generate safe multi-line statusline that avoids Claude Code collision zone
498
+ * The collision zone is columns 15-25 on the second-to-last line.
499
+ * We pad that line with spaces to push content past column 25.
500
+ * @see https://github.com/ruvnet/claude-flow/issues/985
501
+ */
502
+ function generateSafeStatusline() {
503
+ if (!CONFIG.enabled) return '';
504
+
505
+ const user = getUserInfo();
634
506
  const progress = getV3Progress();
635
507
  const security = getSecurityStatus();
636
508
  const swarm = getSwarmStatus();
637
509
  const system = getSystemMetrics();
638
- const adrs = getADRStatus();
639
- const hooks = getHooksStatus();
640
- const agentdb = getAgentDBStats();
641
- const tests = getTestStats();
642
- const session = getSessionStats();
643
- const integration = getIntegrationStatus();
644
510
  const lines = [];
645
511
 
646
- // Header
647
- let header = `${c.bold}${c.brightPurple}\u258A KynjalFlow ${c.reset}`;
648
- header += `${swarm.coordinationActive ? c.brightCyan : c.dim}\u25CF ${c.brightCyan}${git.name}${c.reset}`;
649
- if (git.gitBranch) {
650
- header += ` ${c.dim}\u2502${c.reset} ${c.brightBlue}\u23C7 ${git.gitBranch}${c.reset}`;
651
- const changes = git.modified + git.staged + git.untracked;
652
- if (changes > 0) {
653
- let ind = '';
654
- if (git.staged > 0) ind += `${c.brightGreen}+${git.staged}${c.reset}`;
655
- if (git.modified > 0) ind += `${c.brightYellow}~${git.modified}${c.reset}`;
656
- if (git.untracked > 0) ind += `${c.dim}?${git.untracked}${c.reset}`;
657
- header += ` ${ind}`;
658
- }
659
- if (git.ahead > 0) header += ` ${c.brightGreen}\u2191${git.ahead}${c.reset}`;
660
- if (git.behind > 0) header += ` ${c.brightRed}\u2193${git.behind}${c.reset}`;
512
+ // Header Line
513
+ let header = `${c.bold}${c.brightPurple} RuFlo V3.5 ${c.reset}`;
514
+ header += `${swarm.coordinationActive ? c.brightCyan : c.dim} ${c.brightCyan}${user.name}${c.reset}`;
515
+ if (user.gitBranch) {
516
+ header += ` ${c.dim}│${c.reset} ${c.brightBlue} ${user.gitBranch}${c.reset}`;
661
517
  }
662
- header += ` ${c.dim}\u2502${c.reset} ${c.purple}${modelName}${c.reset}`;
663
- if (session.duration) header += ` ${c.dim}\u2502${c.reset} ${c.cyan}\u23F1 ${session.duration}${c.reset}`;
518
+ header += ` ${c.dim}│${c.reset} ${c.purple}${user.modelName}${c.reset}`;
664
519
  lines.push(header);
665
520
 
666
521
  // Separator
667
- lines.push(`${c.dim}\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500${c.reset}`);
522
+ lines.push(`${c.dim}─────────────────────────────────────────────────────${c.reset}`);
668
523
 
669
- // Line 1: DDD Domains + perf
524
+ // Line 1: DDD Domain Progress
670
525
  const domainsColor = progress.domainsCompleted >= 3 ? c.brightGreen : progress.domainsCompleted > 0 ? c.yellow : c.red;
671
- let perfIndicator;
672
- if (agentdb.hasHnsw && agentdb.vectorCount > 0) {
673
- const speedup = agentdb.vectorCount > 10000 ? '12500x' : agentdb.vectorCount > 1000 ? '150x' : '10x';
674
- perfIndicator = `${c.brightGreen}\u26A1 HNSW ${speedup}${c.reset}`;
675
- } else if (progress.patternsLearned > 0) {
676
- const pk = progress.patternsLearned >= 1000 ? `${(progress.patternsLearned / 1000).toFixed(1)}k` : String(progress.patternsLearned);
677
- perfIndicator = `${c.brightYellow}\uD83D\uDCDA ${pk} patterns${c.reset}`;
678
- } else {
679
- perfIndicator = `${c.dim}\u26A1 target: 150x-12500x${c.reset}`;
680
- }
681
526
  lines.push(
682
- `${c.brightCyan}\uD83C\uDFD7\uFE0F DDD Domains${c.reset} ${progressBar(progress.domainsCompleted, progress.totalDomains)} ` +
683
- `${domainsColor}${progress.domainsCompleted}${c.reset}/${c.brightWhite}${progress.totalDomains}${c.reset} ${perfIndicator}`
527
+ `${c.brightCyan}🏗️ DDD Domains${c.reset} ${progressBar(progress.domainsCompleted, progress.totalDomains)} ` +
528
+ `${domainsColor}${progress.domainsCompleted}${c.reset}/${c.brightWhite}${progress.totalDomains}${c.reset} ` +
529
+ `${c.brightYellow}⚡ 1.0x${c.reset} ${c.dim}→${c.reset} ${c.brightYellow}2.49x-7.47x${c.reset}`
684
530
  );
685
531
 
686
- // Line 2: Swarm + Hooks + CVE + Memory + Intelligence
687
- const swarmInd = swarm.coordinationActive ? `${c.brightGreen}\u25C9${c.reset}` : `${c.dim}\u25CB${c.reset}`;
532
+ // Line 2 (COLLISION LINE): Swarm status with padding after label
533
+ // The emoji+label is ~10 columns. Padding pushes content past collision zone (cols 15-25)
534
+ const swarmIndicator = swarm.coordinationActive ? `${c.brightGreen}◉${c.reset}` : `${c.dim}○${c.reset}`;
688
535
  const agentsColor = swarm.activeAgents > 0 ? c.brightGreen : c.red;
689
- const secIcon = security.status === 'CLEAN' ? '\uD83D\uDFE2' : (security.status === 'IN_PROGRESS' || security.status === 'STALE') ? '\uD83D\uDFE1' : '\uD83D\uDD34';
690
- const secColor = security.status === 'CLEAN' ? c.brightGreen : (security.status === 'IN_PROGRESS' || security.status === 'STALE') ? c.brightYellow : c.brightRed;
691
- const hooksColor = hooks.enabled > 0 ? c.brightGreen : c.dim;
692
- const intellColor = system.intelligencePct >= 80 ? c.brightGreen : system.intelligencePct >= 40 ? c.brightYellow : c.dim;
536
+ let securityIcon = security.status === 'CLEAN' ? '🟢' : security.status === 'IN_PROGRESS' ? '🟡' : '🔴';
537
+ let securityColor = security.status === 'CLEAN' ? c.brightGreen : security.status === 'IN_PROGRESS' ? c.brightYellow : c.brightRed;
693
538
 
539
+ // Padding after "🤖 Swarm" (emoji 2 cols + " Swarm" 6 cols = 8, pad 18 to reach col 26)
694
540
  lines.push(
695
- `${c.brightYellow}\uD83E\uDD16 Swarm${c.reset} ${swarmInd} [${agentsColor}${String(swarm.activeAgents).padStart(2)}${c.reset}/${c.brightWhite}${swarm.maxAgents}${c.reset}] ` +
696
- `${c.brightPurple}\uD83D\uDC65 ${system.subAgents}${c.reset} ` +
697
- `${c.brightBlue}\uD83E\uDE9D ${hooksColor}${hooks.enabled}${c.reset}/${c.brightWhite}${hooks.total}${c.reset} ` +
698
- `${secIcon} ${secColor}CVE ${security.cvesFixed}${c.reset}/${c.brightWhite}${security.totalCves}${c.reset} ` +
699
- `${c.brightCyan}\uD83D\uDCBE ${system.memoryMB}MB${c.reset} ` +
700
- `${intellColor}\uD83E\uDDE0 ${String(system.intelligencePct).padStart(3)}%${c.reset}`
541
+ `${c.brightYellow}🤖 Swarm${c.reset} ` + // 18 spaces padding
542
+ `${swarmIndicator} [${agentsColor}${String(swarm.activeAgents).padStart(2)}${c.reset}/${c.brightWhite}${swarm.maxAgents}${c.reset}] ` +
543
+ `${c.brightPurple}👥 ${system.subAgents}${c.reset} ` +
544
+ `${securityIcon} ${securityColor}CVE ${security.cvesFixed}${c.reset}/${c.brightWhite}${security.totalCves}${c.reset} ` +
545
+ `${c.brightCyan}💾 ${system.memoryMB}MB${c.reset} ` +
546
+ `${c.dim}🧠 ${system.intelligencePct}%${c.reset}`
701
547
  );
702
548
 
703
- // Line 3: Architecture
549
+ // Line 3: Architecture status (this is the last line, not in collision zone)
704
550
  const dddColor = progress.dddProgress >= 50 ? c.brightGreen : progress.dddProgress > 0 ? c.yellow : c.red;
705
- const adrColor = adrs.count > 0 ? (adrs.implemented === adrs.count ? c.brightGreen : c.yellow) : c.dim;
706
- const adrDisplay = adrs.compliance > 0 ? `${adrColor}\u25CF${adrs.compliance}%${c.reset}` : `${adrColor}\u25CF${adrs.implemented}/${adrs.count}${c.reset}`;
707
-
708
- lines.push(
709
- `${c.brightPurple}\uD83D\uDD27 Architecture${c.reset} ` +
710
- `${c.cyan}ADRs${c.reset} ${adrDisplay} ${c.dim}\u2502${c.reset} ` +
711
- `${c.cyan}DDD${c.reset} ${dddColor}\u25CF${String(progress.dddProgress).padStart(3)}%${c.reset} ${c.dim}\u2502${c.reset} ` +
712
- `${c.cyan}Security${c.reset} ${secColor}\u25CF${security.status}${c.reset}`
713
- );
714
-
715
- // Line 4: AgentDB, Tests, Integration
716
- const hnswInd = agentdb.hasHnsw ? `${c.brightGreen}\u26A1${c.reset}` : '';
717
- const sizeDisp = agentdb.dbSizeKB >= 1024 ? `${(agentdb.dbSizeKB / 1024).toFixed(1)}MB` : `${agentdb.dbSizeKB}KB`;
718
- const vectorColor = agentdb.vectorCount > 0 ? c.brightGreen : c.dim;
719
- const testColor = tests.testFiles > 0 ? c.brightGreen : c.dim;
720
-
721
- let integStr = '';
722
- if (integration.mcpServers.total > 0) {
723
- const mcpCol = integration.mcpServers.enabled === integration.mcpServers.total ? c.brightGreen :
724
- integration.mcpServers.enabled > 0 ? c.brightYellow : c.red;
725
- integStr += `${c.cyan}MCP${c.reset} ${mcpCol}\u25CF${integration.mcpServers.enabled}/${integration.mcpServers.total}${c.reset}`;
726
- }
727
- if (integration.hasDatabase) integStr += (integStr ? ' ' : '') + `${c.brightGreen}\u25C6${c.reset}DB`;
728
- if (integration.hasApi) integStr += (integStr ? ' ' : '') + `${c.brightGreen}\u25C6${c.reset}API`;
729
- if (!integStr) integStr = `${c.dim}\u25CF none${c.reset}`;
730
-
731
551
  lines.push(
732
- `${c.brightCyan}\uD83D\uDCCA AgentDB${c.reset} ` +
733
- `${c.cyan}Vectors${c.reset} ${vectorColor}\u25CF${agentdb.vectorCount}${hnswInd}${c.reset} ${c.dim}\u2502${c.reset} ` +
734
- `${c.cyan}Size${c.reset} ${c.brightWhite}${sizeDisp}${c.reset} ${c.dim}\u2502${c.reset} ` +
735
- `${c.cyan}Tests${c.reset} ${testColor}\u25CF${tests.testFiles}${c.reset} ${c.dim}(~${tests.testCases} cases)${c.reset} ${c.dim}\u2502${c.reset} ` +
736
- integStr
552
+ `${c.brightPurple}🔧 Architecture${c.reset} ` +
553
+ `${c.cyan}DDD${c.reset} ${dddColor}●${String(progress.dddProgress).padStart(3)}%${c.reset} ${c.dim}│${c.reset} ` +
554
+ `${c.cyan}Security${c.reset} ${securityColor}●${security.status}${c.reset} ${c.dim}│${c.reset} ` +
555
+ `${c.cyan}Memory${c.reset} ${c.brightGreen}●AgentDB${c.reset} ${c.dim}│${c.reset} ` +
556
+ `${c.cyan}Integration${c.reset} ${swarm.coordinationActive ? c.brightCyan : c.dim}●${c.reset}`
737
557
  );
738
558
 
739
559
  return lines.join('\n');
740
560
  }
741
561
 
742
- // JSON output
743
- function generateJSON() {
744
- const git = getGitInfo();
745
- return {
746
- user: { name: git.name, gitBranch: git.gitBranch, modelName: getModelName() },
747
- v3Progress: getV3Progress(),
748
- security: getSecurityStatus(),
749
- swarm: getSwarmStatus(),
750
- system: getSystemMetrics(),
751
- adrs: getADRStatus(),
752
- hooks: getHooksStatus(),
753
- agentdb: getAgentDBStats(),
754
- tests: getTestStats(),
755
- git: { modified: git.modified, untracked: git.untracked, staged: git.staged, ahead: git.ahead, behind: git.behind },
756
- lastUpdated: new Date().toISOString(),
757
- };
758
- }
759
-
760
- // ─── Main ───────────────────────────────────────────────────────
562
+ // Main
761
563
  if (process.argv.includes('--json')) {
762
564
  console.log(JSON.stringify(generateJSON(), null, 2));
763
565
  } else if (process.argv.includes('--compact')) {
764
566
  console.log(JSON.stringify(generateJSON()));
765
- } else if (process.argv.includes('--single-line')) {
567
+ } else if (process.argv.includes('--single')) {
568
+ // Single-line mode - completely avoids collision zone
569
+ console.log(generateSingleLine());
570
+ } else if (process.argv.includes('--unsafe') || process.argv.includes('--legacy')) {
571
+ // Legacy mode - original multi-line without collision avoidance
766
572
  console.log(generateStatusline());
767
573
  } else {
768
- // Default: multi-line dashboard
769
- console.log(generateDashboard());
574
+ // Default: Safe multi-line mode with collision zone avoidance
575
+ // Use --unsafe or --legacy to get the original behavior
576
+ console.log(generateSafeStatusline());
770
577
  }