triflux 10.3.4 → 10.7.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 (329) hide show
  1. package/LICENSE +21 -21
  2. package/bin/tfx-doctor-tui.mjs +1 -1
  3. package/bin/tfx-doctor.mjs +6 -1
  4. package/bin/tfx-profile.mjs +1 -1
  5. package/bin/tfx-setup-tui.mjs +1 -1
  6. package/bin/tfx-setup.mjs +6 -1
  7. package/bin/triflux.mjs +2396 -1140
  8. package/hooks/agent-route-guard.mjs +12 -8
  9. package/hooks/cross-review-tracker.mjs +21 -8
  10. package/hooks/error-context.mjs +19 -7
  11. package/hooks/hook-adaptive-collector.mjs +18 -16
  12. package/hooks/hook-manager.mjs +93 -32
  13. package/hooks/hook-orchestrator.mjs +108 -24
  14. package/hooks/hook-registry.json +11 -0
  15. package/hooks/keyword-rules.json +6 -10
  16. package/hooks/lib/resolve-root.mjs +1 -1
  17. package/hooks/mcp-config-watcher.mjs +6 -2
  18. package/hooks/pipeline-stop.mjs +3 -6
  19. package/hooks/safety-guard.mjs +99 -28
  20. package/hooks/session-start-fast.mjs +143 -0
  21. package/hooks/subagent-verifier.mjs +5 -4
  22. package/hub/account-broker.mjs +256 -60
  23. package/hub/adaptive-diagnostic.mjs +75 -48
  24. package/hub/adaptive-inject.mjs +95 -57
  25. package/hub/adaptive-memory.mjs +156 -42
  26. package/hub/adaptive.mjs +60 -31
  27. package/hub/assign-callbacks.mjs +67 -30
  28. package/hub/bridge.mjs +0 -1
  29. package/hub/cli-adapter-base.mjs +200 -48
  30. package/hub/codex-adapter.mjs +76 -96
  31. package/hub/codex-compat.mjs +3 -3
  32. package/hub/codex-preflight.mjs +63 -37
  33. package/hub/delegator/contracts.mjs +19 -23
  34. package/hub/delegator/index.mjs +3 -3
  35. package/hub/delegator/service.mjs +88 -64
  36. package/hub/delegator/tool-definitions.mjs +5 -5
  37. package/hub/fullcycle.mjs +33 -17
  38. package/hub/gemini-adapter.mjs +69 -94
  39. package/hub/hitl.mjs +89 -30
  40. package/hub/intent.mjs +161 -38
  41. package/hub/lib/cache-guard.mjs +43 -17
  42. package/hub/lib/mcp-response-cache.mjs +66 -32
  43. package/hub/lib/memory-store.mjs +285 -111
  44. package/hub/lib/path-utils.mjs +35 -37
  45. package/hub/lib/process-utils.mjs +106 -37
  46. package/hub/lib/spawn-trace.mjs +527 -0
  47. package/hub/lib/ssh-command.mjs +34 -4
  48. package/hub/lib/ssh-retry.mjs +5 -1
  49. package/hub/lib/uuidv7.mjs +4 -3
  50. package/hub/memory-doctor.mjs +266 -106
  51. package/hub/middleware/request-logger.mjs +61 -34
  52. package/hub/paths.mjs +9 -9
  53. package/hub/pipeline/gates/confidence.mjs +34 -15
  54. package/hub/pipeline/gates/consensus.mjs +27 -15
  55. package/hub/pipeline/gates/index.mjs +7 -3
  56. package/hub/pipeline/gates/selfcheck.mjs +57 -19
  57. package/hub/pipeline/index.mjs +77 -42
  58. package/hub/pipeline/state.mjs +10 -10
  59. package/hub/pipeline/transitions.mjs +40 -23
  60. package/hub/platform.mjs +57 -48
  61. package/hub/promote-penalties.mjs +25 -7
  62. package/hub/quality/deslop.mjs +70 -49
  63. package/hub/research.mjs +32 -25
  64. package/hub/router.mjs +240 -107
  65. package/hub/routing/complexity.mjs +132 -29
  66. package/hub/routing/index.mjs +17 -12
  67. package/hub/routing/q-learning.mjs +76 -28
  68. package/hub/server.mjs +4 -4
  69. package/hub/session-fingerprint.mjs +126 -60
  70. package/hub/state.mjs +84 -43
  71. package/hub/store-adapter.mjs +59 -26
  72. package/hub/store.mjs +356 -153
  73. package/hub/team/agent-map.json +22 -7
  74. package/hub/team/ansi.mjs +186 -122
  75. package/hub/team/backend.mjs +28 -10
  76. package/hub/team/cli/commands/attach.mjs +29 -9
  77. package/hub/team/cli/commands/control.mjs +29 -8
  78. package/hub/team/cli/commands/debug.mjs +32 -11
  79. package/hub/team/cli/commands/focus.mjs +38 -11
  80. package/hub/team/cli/commands/interrupt.mjs +18 -6
  81. package/hub/team/cli/commands/kill.mjs +16 -5
  82. package/hub/team/cli/commands/list.mjs +11 -4
  83. package/hub/team/cli/commands/send.mjs +19 -6
  84. package/hub/team/cli/commands/start/index.mjs +154 -31
  85. package/hub/team/cli/commands/start/parse-args.mjs +38 -11
  86. package/hub/team/cli/commands/start/start-headless.mjs +112 -36
  87. package/hub/team/cli/commands/start/start-in-process.mjs +12 -2
  88. package/hub/team/cli/commands/start/start-mux.mjs +70 -21
  89. package/hub/team/cli/commands/start/start-wt.mjs +29 -12
  90. package/hub/team/cli/commands/status.mjs +43 -14
  91. package/hub/team/cli/commands/stop.mjs +11 -4
  92. package/hub/team/cli/commands/task.mjs +8 -3
  93. package/hub/team/cli/commands/tasks.mjs +1 -1
  94. package/hub/team/cli/index.mjs +2 -2
  95. package/hub/team/cli/manifest.mjs +38 -8
  96. package/hub/team/cli/render.mjs +30 -8
  97. package/hub/team/cli/services/attach-fallback.mjs +31 -11
  98. package/hub/team/cli/services/hub-client.mjs +42 -14
  99. package/hub/team/cli/services/member-selector.mjs +11 -4
  100. package/hub/team/cli/services/native-control.mjs +48 -21
  101. package/hub/team/cli/services/runtime-mode.mjs +2 -1
  102. package/hub/team/cli/services/state-store.mjs +25 -8
  103. package/hub/team/cli/services/task-model.mjs +16 -6
  104. package/hub/team/conductor-mesh-bridge.mjs +24 -23
  105. package/hub/team/conductor.mjs +8 -4
  106. package/hub/team/dashboard-anchor.mjs +4 -5
  107. package/hub/team/dashboard-layout.mjs +3 -1
  108. package/hub/team/dashboard-open.mjs +41 -21
  109. package/hub/team/dashboard.mjs +76 -28
  110. package/hub/team/event-log.mjs +18 -10
  111. package/hub/team/handoff.mjs +31 -15
  112. package/hub/team/headless.mjs +2 -1
  113. package/hub/team/health-probe.mjs +69 -54
  114. package/hub/team/launcher-template.mjs +16 -13
  115. package/hub/team/native-supervisor.mjs +65 -21
  116. package/hub/team/native.mjs +74 -35
  117. package/hub/team/nativeProxy.mjs +184 -113
  118. package/hub/team/notify.mjs +119 -76
  119. package/hub/team/orchestrator.mjs +9 -4
  120. package/hub/team/pane.mjs +12 -7
  121. package/hub/team/process-cleanup.mjs +25 -16
  122. package/hub/team/psmux.mjs +491 -201
  123. package/hub/team/remote-probe.mjs +68 -52
  124. package/hub/team/remote-session.mjs +117 -59
  125. package/hub/team/remote-watcher.mjs +61 -33
  126. package/hub/team/routing.mjs +51 -25
  127. package/hub/team/runtime-strategy.mjs +3 -1
  128. package/hub/team/session.mjs +98 -34
  129. package/hub/team/staleState.mjs +72 -30
  130. package/hub/team/swarm-locks.mjs +15 -13
  131. package/hub/team/swarm-planner.mjs +32 -21
  132. package/hub/team/swarm-reconciler.mjs +48 -23
  133. package/hub/team/tui-lite.mjs +266 -68
  134. package/hub/team/tui-remote-adapter.mjs +14 -10
  135. package/hub/team/tui-viewer.mjs +99 -43
  136. package/hub/team/tui.mjs +708 -271
  137. package/hub/team/worktree-lifecycle.mjs +152 -58
  138. package/hub/team/wt-manager.mjs +24 -14
  139. package/hub/token-mode.mjs +71 -71
  140. package/hub/tray.mjs +66 -23
  141. package/hub/workers/claude-worker.mjs +162 -118
  142. package/hub/workers/codex-mcp.mjs +192 -141
  143. package/hub/workers/delegator-mcp.mjs +507 -333
  144. package/hub/workers/factory.mjs +8 -8
  145. package/hub/workers/gemini-worker.mjs +115 -84
  146. package/hub/workers/interface.mjs +6 -1
  147. package/hub/workers/worker-utils.mjs +21 -14
  148. package/hud/colors.mjs +27 -9
  149. package/hud/constants.mjs +162 -26
  150. package/hud/context-monitor.mjs +82 -41
  151. package/hud/hud-qos-status.mjs +129 -49
  152. package/hud/mission-board.mjs +6 -3
  153. package/hud/providers/claude.mjs +226 -115
  154. package/hud/providers/codex.mjs +62 -22
  155. package/hud/providers/gemini.mjs +168 -56
  156. package/hud/renderers.mjs +384 -119
  157. package/hud/terminal.mjs +101 -31
  158. package/hud/utils.mjs +78 -38
  159. package/mesh/index.mjs +11 -5
  160. package/mesh/mesh-budget.mjs +18 -9
  161. package/mesh/mesh-heartbeat.mjs +1 -1
  162. package/mesh/mesh-queue.mjs +3 -5
  163. package/mesh/mesh-router.mjs +5 -4
  164. package/package.json +2 -1
  165. package/scripts/__tests__/gen-skill-docs.test.mjs +36 -7
  166. package/scripts/__tests__/keyword-detector.test.mjs +77 -28
  167. package/scripts/__tests__/mcp-guard-engine.test.mjs +58 -20
  168. package/scripts/__tests__/remote-spawn-transfer.test.mjs +30 -19
  169. package/scripts/__tests__/remote-spawn.test.mjs +10 -4
  170. package/scripts/__tests__/session-start-fast.test.mjs +36 -0
  171. package/scripts/__tests__/skill-template.test.mjs +98 -50
  172. package/scripts/__tests__/smoke.test.mjs +1 -1
  173. package/scripts/__tests__/spawn-trace.test.mjs +102 -0
  174. package/scripts/__tests__/tfx-doctor-diagnose.test.mjs +48 -0
  175. package/scripts/cache-doctor.mjs +11 -4
  176. package/scripts/cache-warmup.mjs +96 -37
  177. package/scripts/claudemd-sync.mjs +27 -17
  178. package/scripts/codex-gateway-preflight.mjs +52 -37
  179. package/scripts/codex-mcp-gateway-sync.mjs +59 -39
  180. package/scripts/completions/tfx.bash +47 -47
  181. package/scripts/completions/tfx.fish +44 -44
  182. package/scripts/completions/tfx.zsh +83 -83
  183. package/scripts/config-audit.mjs +232 -0
  184. package/scripts/convert-to-tmpl.mjs +54 -0
  185. package/scripts/cross-review-gate.mjs +35 -12
  186. package/scripts/cross-review-tracker.mjs +21 -8
  187. package/scripts/demo.mjs +35 -17
  188. package/scripts/doctor-diagnose.mjs +284 -0
  189. package/scripts/gen-skill-docs.mjs +7 -2
  190. package/scripts/gen-skill-manifest.mjs +2 -1
  191. package/scripts/headless-guard.mjs +86 -48
  192. package/scripts/hub-ensure.mjs +45 -26
  193. package/scripts/keyword-detector.mjs +41 -20
  194. package/scripts/keyword-rules-expander.mjs +47 -30
  195. package/scripts/lib/claudemd-scanner.mjs +6 -1
  196. package/scripts/lib/context.mjs +3 -3
  197. package/scripts/lib/cross-review-utils.mjs +6 -3
  198. package/scripts/lib/env-probe.mjs +47 -28
  199. package/scripts/lib/gemini-profiles.mjs +44 -10
  200. package/scripts/lib/handoff.mjs +33 -17
  201. package/scripts/lib/hook-utils.mjs +8 -6
  202. package/scripts/lib/keyword-rules.mjs +43 -19
  203. package/scripts/lib/logger.mjs +24 -24
  204. package/scripts/lib/mcp-filter.mjs +377 -239
  205. package/scripts/lib/mcp-guard-engine.mjs +194 -79
  206. package/scripts/lib/mcp-manifest.mjs +23 -13
  207. package/scripts/lib/mcp-server-catalog.mjs +300 -63
  208. package/scripts/lib/psmux-info.mjs +11 -6
  209. package/scripts/lib/remote-spawn-transfer.mjs +44 -14
  210. package/scripts/lib/skill-template.mjs +30 -7
  211. package/scripts/mcp-check.mjs +58 -39
  212. package/scripts/mcp-gateway-config.mjs +83 -39
  213. package/scripts/mcp-gateway-ensure.mjs +43 -35
  214. package/scripts/mcp-gateway-integration-test.mjs +70 -58
  215. package/scripts/mcp-gateway-start.mjs +126 -60
  216. package/scripts/mcp-gateway-verify.mjs +24 -22
  217. package/scripts/mcp-safety-guard.mjs +44 -11
  218. package/scripts/notion-read.mjs +199 -84
  219. package/scripts/pack.mjs +94 -89
  220. package/scripts/preflight-cache.mjs +27 -10
  221. package/scripts/preinstall.mjs +42 -13
  222. package/scripts/remote-spawn.mjs +309 -94
  223. package/scripts/run.cjs +8 -5
  224. package/scripts/session-spawn-helper.mjs +130 -39
  225. package/scripts/session-stale-cleanup.mjs +123 -0
  226. package/scripts/setup.mjs +941 -492
  227. package/scripts/test-lock.mjs +20 -7
  228. package/scripts/test-tfx-route-no-claude-native.mjs +16 -12
  229. package/scripts/tfx-batch-stats.mjs +32 -11
  230. package/scripts/tfx-gate-activate.mjs +11 -4
  231. package/scripts/tfx-route-post.mjs +87 -20
  232. package/scripts/tfx-route-worker.mjs +57 -51
  233. package/scripts/tfx-route.sh +41 -124
  234. package/scripts/tmp-cleanup.mjs +21 -7
  235. package/scripts/token-snapshot.mjs +204 -85
  236. package/skills/.omc/state/agent-replay-8f0e10a9-9693-4410-96f5-a6b07e8ed995.jsonl +1 -0
  237. package/skills/.omc/state/idle-notif-cooldown.json +3 -0
  238. package/skills/.omc/state/last-tool-error.json +7 -0
  239. package/skills/.omc/state/subagent-tracking.json +7 -0
  240. package/skills/_templates/base.md +1 -6
  241. package/skills/merge-worktree/SKILL.md.tmpl +144 -0
  242. package/skills/shared/telemetry-segment.md +6 -0
  243. package/skills/star-prompt/SKILL.md.tmpl +222 -0
  244. package/skills/tfx-analysis/SKILL.md.tmpl +107 -0
  245. package/skills/tfx-analysis/skill.json +1 -6
  246. package/skills/tfx-auto/SKILL.md +1 -0
  247. package/skills/tfx-auto-codex/SKILL.md.tmpl +106 -0
  248. package/skills/tfx-auto-codex/skill.json +1 -3
  249. package/skills/tfx-autopilot/SKILL.md.tmpl +116 -0
  250. package/skills/tfx-autopilot/skill.json +1 -5
  251. package/skills/tfx-autoresearch/SKILL.md.tmpl +136 -0
  252. package/skills/tfx-autoroute/SKILL.md.tmpl +189 -0
  253. package/skills/tfx-autoroute/skill.json +1 -7
  254. package/skills/tfx-codex/SKILL.md +1 -0
  255. package/skills/tfx-codex/skill.json +1 -3
  256. package/skills/tfx-codex-swarm/SKILL.md.tmpl +16 -0
  257. package/skills/tfx-codex-swarm/evals/evals.json +1 -1
  258. package/skills/tfx-codex-swarm/skill.json +1 -4
  259. package/skills/tfx-codex-swarm-workspace/iteration-1/benchmark.json +54 -12
  260. package/skills/tfx-codex-swarm-workspace/iteration-1/full-swarm-all-prds/with_skill/grading.json +35 -7
  261. package/skills/tfx-codex-swarm-workspace/iteration-1/full-swarm-all-prds/without_skill/grading.json +35 -7
  262. package/skills/tfx-codex-swarm-workspace/iteration-1/implicit-swarm-no-keywords/with_skill/grading.json +25 -5
  263. package/skills/tfx-codex-swarm-workspace/iteration-1/implicit-swarm-no-keywords/without_skill/grading.json +25 -5
  264. package/skills/tfx-codex-swarm-workspace/iteration-1/selective-spawn-with-override/with_skill/grading.json +20 -4
  265. package/skills/tfx-codex-swarm-workspace/iteration-1/selective-spawn-with-override/without_skill/grading.json +16 -4
  266. package/skills/tfx-consensus/SKILL.md.tmpl +146 -0
  267. package/skills/tfx-debate/SKILL.md.tmpl +192 -0
  268. package/skills/tfx-debate/skill.json +1 -7
  269. package/skills/tfx-deep-analysis/SKILL.md.tmpl +228 -0
  270. package/skills/tfx-deep-analysis/skill.json +1 -5
  271. package/skills/tfx-deep-interview/SKILL.md.tmpl +203 -0
  272. package/skills/tfx-deep-plan/SKILL.md.tmpl +282 -0
  273. package/skills/tfx-deep-qa/SKILL.md.tmpl +165 -0
  274. package/skills/tfx-deep-qa/skill.json +1 -6
  275. package/skills/tfx-deep-research/SKILL.md.tmpl +217 -0
  276. package/skills/tfx-deep-review/SKILL.md.tmpl +179 -0
  277. package/skills/tfx-doctor/SKILL.md +21 -0
  278. package/skills/tfx-doctor/SKILL.md.tmpl +172 -0
  279. package/skills/tfx-doctor/skill.json +1 -3
  280. package/skills/tfx-find/SKILL.md +1 -0
  281. package/skills/tfx-forge/SKILL.md.tmpl +187 -0
  282. package/skills/tfx-fullcycle/SKILL.md.tmpl +286 -0
  283. package/skills/tfx-fullcycle/skill.json +1 -6
  284. package/skills/tfx-gemini/SKILL.md.tmpl +91 -0
  285. package/skills/tfx-gemini/skill.json +1 -3
  286. package/skills/tfx-hooks/SKILL.md.tmpl +216 -0
  287. package/skills/tfx-hooks/skill.json +1 -3
  288. package/skills/tfx-hub/SKILL.md.tmpl +212 -0
  289. package/skills/tfx-hub/skill.json +1 -3
  290. package/skills/tfx-index/SKILL.md +1 -0
  291. package/skills/tfx-index/skill.json +1 -6
  292. package/skills/tfx-interview/SKILL.md.tmpl +285 -0
  293. package/skills/tfx-multi/SKILL.md.tmpl +183 -0
  294. package/skills/tfx-multi/skill.json +1 -3
  295. package/skills/tfx-panel/SKILL.md.tmpl +189 -0
  296. package/skills/tfx-panel/skill.json +1 -7
  297. package/skills/tfx-persist/SKILL.md.tmpl +270 -0
  298. package/skills/tfx-persist/skill.json +1 -7
  299. package/skills/tfx-plan/SKILL.md +1 -0
  300. package/skills/tfx-plan/skill.json +1 -6
  301. package/skills/tfx-profile/SKILL.md.tmpl +239 -0
  302. package/skills/tfx-profile/skill.json +1 -3
  303. package/skills/tfx-prune/SKILL.md.tmpl +200 -0
  304. package/skills/tfx-prune/skill.json +1 -7
  305. package/skills/tfx-psmux-rules/SKILL.md.tmpl +326 -0
  306. package/skills/tfx-psmux-rules/skill.json +1 -4
  307. package/skills/tfx-qa/SKILL.md +1 -0
  308. package/skills/tfx-qa/skill.json +1 -6
  309. package/skills/tfx-ralph/SKILL.md.tmpl +28 -0
  310. package/skills/tfx-ralph/skill.json +1 -4
  311. package/skills/tfx-remote-setup/SKILL.md.tmpl +576 -0
  312. package/skills/tfx-remote-setup/skill.json +1 -3
  313. package/skills/tfx-remote-spawn/SKILL.md.tmpl +263 -0
  314. package/skills/tfx-remote-spawn/references/hosts.json +16 -0
  315. package/skills/tfx-remote-spawn/skill.json +1 -4
  316. package/skills/tfx-research/SKILL.md +1 -0
  317. package/skills/tfx-review/SKILL.md +1 -0
  318. package/skills/tfx-review/skill.json +1 -6
  319. package/skills/tfx-setup/SKILL.md.tmpl +504 -0
  320. package/skills/tfx-setup/skill.json +1 -3
  321. package/skills/tfx-swarm/SKILL.md +22 -0
  322. package/skills/tfx-swarm/SKILL.md.tmpl +218 -0
  323. package/tui/codex-profile.mjs +88 -33
  324. package/tui/core.mjs +45 -15
  325. package/tui/doctor.mjs +75 -28
  326. package/tui/gemini-profile.mjs +74 -29
  327. package/tui/monitor-data.mjs +8 -4
  328. package/tui/monitor.mjs +71 -27
  329. package/tui/setup.mjs +133 -42
@@ -1,17 +1,17 @@
1
1
  #!/usr/bin/env node
2
+
2
3
  // hub/team/tui-viewer.mjs — worker state aggregator v5
3
4
  // psmux capture-pane 기반 워커 상태 집계 + TUI 렌더링
4
5
  // data ingest: ~2Hz (500ms), render: 8-12FPS (별도 루프)
5
6
 
6
- import { existsSync, readFileSync, statSync } from "node:fs";
7
7
  import { execFileSync } from "node:child_process";
8
- import { join } from "node:path";
8
+ import { existsSync, readFileSync, statSync } from "node:fs";
9
9
  import { tmpdir } from "node:os";
10
- import { createLogDashboard } from "./tui.mjs";
11
- import { createLiteDashboard } from "./tui-lite.mjs";
10
+ import { join } from "node:path";
12
11
  import { openHeadlessDashboardTarget } from "./dashboard-open.mjs";
13
12
  import { processHandoff } from "./handoff.mjs";
14
-
13
+ import { createLogDashboard } from "./tui.mjs";
14
+ import { createLiteDashboard } from "./tui-lite.mjs";
15
15
 
16
16
  // ── CLI 인자 파싱 ──
17
17
  const args = process.argv.slice(2);
@@ -20,9 +20,9 @@ function argVal(flag) {
20
20
  return idx >= 0 ? args[idx + 1] : null;
21
21
  }
22
22
 
23
- const SESSION = argVal("--session");
23
+ const SESSION = argVal("--session");
24
24
  const RESULT_DIR = argVal("--result-dir") ?? join(tmpdir(), "tfx-headless");
25
- const LAYOUT = argVal("--layout") ?? "single";
25
+ const LAYOUT = argVal("--layout") ?? "single";
26
26
 
27
27
  if (!SESSION) {
28
28
  process.stderr.write(
@@ -48,20 +48,22 @@ const MAX_BODY_BYTES = 10240;
48
48
  // forceTTY 시 alternate screen이 WT pane에서 렌더링 안 되는 문제 → append-only 유지
49
49
  const tuiFactory = LAYOUT === "lite" ? createLiteDashboard : createLogDashboard;
50
50
  const tui = tuiFactory({
51
- refreshMs: 0, // render 루프를 직접 제어
51
+ refreshMs: 0, // render 루프를 직접 제어
52
52
  stream: process.stdout,
53
53
  input: process.stdin,
54
54
  columns: process.stdout.columns || parseInt(process.env.COLUMNS, 10) || 120,
55
55
  layout: LAYOUT,
56
- onOpenSelectedWorker: (workerName) => openHeadlessDashboardTarget(SESSION, {
57
- worker: workerName,
58
- openAll: false,
59
- cwd: process.cwd(),
60
- }),
61
- onOpenAllWorkers: () => openHeadlessDashboardTarget(SESSION, {
62
- openAll: true,
63
- cwd: process.cwd(),
64
- }),
56
+ onOpenSelectedWorker: (workerName) =>
57
+ openHeadlessDashboardTarget(SESSION, {
58
+ worker: workerName,
59
+ openAll: false,
60
+ cwd: process.cwd(),
61
+ }),
62
+ onOpenAllWorkers: () =>
63
+ openHeadlessDashboardTarget(SESSION, {
64
+ openAll: true,
65
+ cwd: process.cwd(),
66
+ }),
65
67
  });
66
68
  const startTime = Date.now();
67
69
  tui.setStartTime(startTime);
@@ -126,10 +128,10 @@ function extractFindings(lines, verdict = "") {
126
128
 
127
129
  // ── Phase 가중치 진행률 (Plan=10%, Research=30%, Exec=50%, Verify=10%) ──
128
130
  const PHASE_WEIGHTS = {
129
- plan: 0.10,
130
- research:0.40, // plan + research
131
- exec: 0.90, // plan + research + exec
132
- verify: 1.00,
131
+ plan: 0.1,
132
+ research: 0.4, // plan + research
133
+ exec: 0.9, // plan + research + exec
134
+ verify: 1.0,
133
135
  };
134
136
 
135
137
  function estimateProgress(lines, context = {}) {
@@ -138,9 +140,11 @@ function estimateProgress(lines, context = {}) {
138
140
  const text = lines.join("\n").toLowerCase();
139
141
  let phase = "plan";
140
142
 
141
- if (/verify|assert|test|check|confirm/.test(text)) phase = "verify";
142
- else if (/edit|patch|implement|write|update|fix|refactor/.test(text)) phase = "exec";
143
- else if (/search|read|inspect|analy|review|research/.test(text)) phase = "research";
143
+ if (/verify|assert|test|check|confirm/.test(text)) phase = "verify";
144
+ else if (/edit|patch|implement|write|update|fix|refactor/.test(text))
145
+ phase = "exec";
146
+ else if (/search|read|inspect|analy|review|research/.test(text))
147
+ phase = "research";
144
148
 
145
149
  let ratio = PHASE_WEIGHTS[phase];
146
150
 
@@ -161,7 +165,13 @@ function listPanes() {
161
165
  try {
162
166
  const out = execFileSync(
163
167
  "psmux",
164
- ["list-panes", "-t", SESSION, "-F", "#{pane_index}:#{pane_title}:#{pane_pid}"],
168
+ [
169
+ "list-panes",
170
+ "-t",
171
+ SESSION,
172
+ "-F",
173
+ "#{pane_index}:#{pane_title}:#{pane_pid}",
174
+ ],
165
175
  { encoding: "utf8", timeout: 2000 },
166
176
  );
167
177
  return out
@@ -245,7 +255,7 @@ function splitHandoff(handoff) {
245
255
  }
246
256
 
247
257
  // ── 상태 집계 저장소 ──
248
- const workerState = new Map(); // paneName → 내부 상태
258
+ const workerState = new Map(); // paneName → 내부 상태
249
259
  let emptyPollCount = 0;
250
260
 
251
261
  // ── data ingest (4Hz = 250ms) ──
@@ -260,13 +270,21 @@ function ingest() {
260
270
  clearInterval(ingestTimer);
261
271
  clearInterval(renderTimer);
262
272
  tui.render();
263
- process.stdout.write("\n\x1b[38;5;245m 세션 종료됨 — 아무 키나 누르면 닫힘\x1b[0m");
273
+ process.stdout.write(
274
+ "\n\x1b[38;5;245m 세션 종료됨 — 아무 키나 누르면 닫힘\x1b[0m",
275
+ );
264
276
  if (process.stdin.isTTY) {
265
277
  process.stdin.setRawMode(true);
266
278
  process.stdin.resume();
267
- process.stdin.once("data", () => { cleanup(); process.exit(0); });
279
+ process.stdin.once("data", () => {
280
+ cleanup();
281
+ process.exit(0);
282
+ });
268
283
  } else {
269
- setTimeout(() => { cleanup(); process.exit(0); }, 30000);
284
+ setTimeout(() => {
285
+ cleanup();
286
+ process.exit(0);
287
+ }, 30000);
270
288
  }
271
289
  return;
272
290
  }
@@ -287,8 +305,10 @@ function ingest() {
287
305
 
288
306
  // CLI 타입 감지
289
307
  let cli = "codex";
290
- if (pane.title.includes("gemini") || pane.title.includes("🔵")) cli = "gemini";
291
- else if (pane.title.includes("claude") || pane.title.includes("🟠")) cli = "claude";
308
+ if (pane.title.includes("gemini") || pane.title.includes("🔵"))
309
+ cli = "gemini";
310
+ else if (pane.title.includes("claude") || pane.title.includes("🟠"))
311
+ cli = "claude";
292
312
  ws.title = pane.title;
293
313
  ws.cli = cli;
294
314
 
@@ -334,7 +354,11 @@ function ingest() {
334
354
 
335
355
  const resultFile = join(RESULT_DIR, `${SESSION}-${paneName}.txt`);
336
356
  let resultSize = 0;
337
- try { resultSize = statSync(resultFile).size; } catch { /* missing */ }
357
+ try {
358
+ resultSize = statSync(resultFile).size;
359
+ } catch {
360
+ /* missing */
361
+ }
338
362
 
339
363
  const shellReturned = /^(PS\s|>|\$)\s*/.test(lastLine) && lines.length > 2;
340
364
  const tokens = extractTokenLabel(snapshot);
@@ -346,7 +370,9 @@ function ingest() {
346
370
  : snapshot;
347
371
  const rLines = toLines(resultContent);
348
372
  const verdict = extractFindings(rLines).at(-1) || lastLine || "completed";
349
- const handoffStatus = /fail|error|exception/i.test(rLines.join("\n")) ? "failed" : "ok";
373
+ const handoffStatus = /fail|error|exception/i.test(rLines.join("\n"))
374
+ ? "failed"
375
+ : "ok";
350
376
  const handoff = {
351
377
  status: handoffStatus,
352
378
  lead_action: handoffStatus === "failed" ? "retry" : "accept",
@@ -378,11 +404,22 @@ function ingest() {
378
404
  }
379
405
 
380
406
  // 진행 중
381
- const progress = estimateProgress(lines, { tokens, resultSize, shellReturned, done: false });
407
+ const progress = estimateProgress(lines, {
408
+ tokens,
409
+ resultSize,
410
+ shellReturned,
411
+ done: false,
412
+ });
382
413
  const verdict = lastLine;
383
414
 
384
- ws.raw_body = raw_body.length > MAX_BODY_BYTES ? raw_body.slice(-MAX_BODY_BYTES) : raw_body;
385
- ws.filtered_body = filtered_body.length > MAX_BODY_BYTES ? filtered_body.slice(-MAX_BODY_BYTES) : filtered_body;
415
+ ws.raw_body =
416
+ raw_body.length > MAX_BODY_BYTES
417
+ ? raw_body.slice(-MAX_BODY_BYTES)
418
+ : raw_body;
419
+ ws.filtered_body =
420
+ filtered_body.length > MAX_BODY_BYTES
421
+ ? filtered_body.slice(-MAX_BODY_BYTES)
422
+ : filtered_body;
386
423
  ws.verdict = verdict;
387
424
  ws.findings = extractFindings(lines, lastLine);
388
425
  ws.progress = progress;
@@ -415,7 +452,9 @@ function pushToTui(paneName, cli, paneTitle, update) {
415
452
  // ── render 루프 (8-12FPS ≈ 100ms) ──
416
453
  let renderTimer = null;
417
454
  function startRender() {
418
- renderTimer = setInterval(() => { tui.render(); }, 100);
455
+ renderTimer = setInterval(() => {
456
+ tui.render();
457
+ }, 100);
419
458
  if (renderTimer.unref) renderTimer.unref();
420
459
  }
421
460
 
@@ -426,13 +465,21 @@ const doneCheck = setInterval(() => {
426
465
  clearInterval(doneCheck);
427
466
  clearInterval(ingestTimer);
428
467
  clearInterval(renderTimer);
429
- process.stdout.write("\n\x1b[38;5;245m 전체 완료 — 아무 키나 누르면 닫힘\x1b[0m");
468
+ process.stdout.write(
469
+ "\n\x1b[38;5;245m 전체 완료 — 아무 키나 누르면 닫힘\x1b[0m",
470
+ );
430
471
  if (process.stdin.isTTY) {
431
472
  process.stdin.setRawMode(true);
432
473
  process.stdin.resume();
433
- process.stdin.once("data", () => { cleanup(); process.exit(0); });
474
+ process.stdin.once("data", () => {
475
+ cleanup();
476
+ process.exit(0);
477
+ });
434
478
  } else {
435
- setTimeout(() => { cleanup(); process.exit(0); }, 30000);
479
+ setTimeout(() => {
480
+ cleanup();
481
+ process.exit(0);
482
+ }, 30000);
436
483
  }
437
484
  }
438
485
  }, 2000);
@@ -452,11 +499,20 @@ function cleanup() {
452
499
 
453
500
  // ── 진입점 ──
454
501
  tui.render();
455
- const ingestTimer = setInterval(ingest, 500); // 2Hz
502
+ const ingestTimer = setInterval(ingest, 500); // 2Hz
456
503
  startRender();
457
504
 
458
505
  // 타임아웃 (10분)
459
- setTimeout(() => { cleanup(); process.exit(0); }, 10 * 60 * 1000);
506
+ setTimeout(
507
+ () => {
508
+ cleanup();
509
+ process.exit(0);
510
+ },
511
+ 10 * 60 * 1000,
512
+ );
460
513
 
461
514
  // Ctrl-C
462
- process.on("SIGINT", () => { cleanup(); process.exit(0); });
515
+ process.on("SIGINT", () => {
516
+ cleanup();
517
+ process.exit(0);
518
+ });