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
@@ -8,78 +8,78 @@
8
8
  */
9
9
  export const COMPACT_RULES = [
10
10
  // ── 심볼 치환 (긴 매칭 우선 정렬) ──
11
- { from: ['greater than or equal'], to: '', type: 'symbol' },
12
- { from: ['less than or equal'], to: '', type: 'symbol' },
13
- { from: ['results in', '결과적으로'], to: '', type: 'symbol' },
14
- { from: ['therefore', '따라서'], to: '', type: 'symbol' },
15
- { from: ['because', '왜냐하면'], to: '', type: 'symbol' },
16
- { from: ['approximately', '대략'], to: '', type: 'symbol' },
17
- { from: ['not equal', '같지 않'], to: '', type: 'symbol' },
18
- { from: ['in progress', '진행 중'], to: '', type: 'symbol' },
19
- { from: ['completed', '완료'], to: '', type: 'symbol' },
20
- { from: ['success', '성공'], to: '', type: 'symbol' },
21
- { from: ['failure', '실패'], to: '', type: 'symbol' },
22
- { from: ['warning', '경고'], to: '', type: 'symbol' },
23
- { from: ['error', '에러'], to: '', type: 'symbol' },
24
- { from: ['pending', '대기'], to: '', type: 'symbol' },
11
+ { from: ["greater than or equal"], to: "", type: "symbol" },
12
+ { from: ["less than or equal"], to: "", type: "symbol" },
13
+ { from: ["results in", "결과적으로"], to: "", type: "symbol" },
14
+ { from: ["therefore", "따라서"], to: "", type: "symbol" },
15
+ { from: ["because", "왜냐하면"], to: "", type: "symbol" },
16
+ { from: ["approximately", "대략"], to: "", type: "symbol" },
17
+ { from: ["not equal", "같지 않"], to: "", type: "symbol" },
18
+ { from: ["in progress", "진행 중"], to: "", type: "symbol" },
19
+ { from: ["completed", "완료"], to: "", type: "symbol" },
20
+ { from: ["success", "성공"], to: "", type: "symbol" },
21
+ { from: ["failure", "실패"], to: "", type: "symbol" },
22
+ { from: ["warning", "경고"], to: "", type: "symbol" },
23
+ { from: ["error", "에러"], to: "", type: "symbol" },
24
+ { from: ["pending", "대기"], to: "", type: "symbol" },
25
25
 
26
26
  // ── 약어 (긴 매칭 우선 정렬) ──
27
- { from: ['configuration', '설정'], to: 'cfg', type: 'abbrev' },
28
- { from: ['implementation', '구현'], to: 'impl', type: 'abbrev' },
29
- { from: ['architecture', '아키텍처'], to: 'arch', type: 'abbrev' },
30
- { from: ['dependency', '의존성'], to: 'dep', type: 'abbrev' },
31
- { from: ['function', '함수'], to: 'fn', type: 'abbrev' },
32
- { from: ['parameter', '파라미터'], to: 'param', type: 'abbrev' },
33
- { from: ['repository', '저장소'], to: 'repo', type: 'abbrev' },
34
- { from: ['environment', '환경'], to: 'env', type: 'abbrev' },
35
- { from: ['variable', '변수'], to: 'var', type: 'abbrev' },
36
- { from: ['directory', '디렉토리'], to: 'dir', type: 'abbrev' },
27
+ { from: ["configuration", "설정"], to: "cfg", type: "abbrev" },
28
+ { from: ["implementation", "구현"], to: "impl", type: "abbrev" },
29
+ { from: ["architecture", "아키텍처"], to: "arch", type: "abbrev" },
30
+ { from: ["dependency", "의존성"], to: "dep", type: "abbrev" },
31
+ { from: ["function", "함수"], to: "fn", type: "abbrev" },
32
+ { from: ["parameter", "파라미터"], to: "param", type: "abbrev" },
33
+ { from: ["repository", "저장소"], to: "repo", type: "abbrev" },
34
+ { from: ["environment", "환경"], to: "env", type: "abbrev" },
35
+ { from: ["variable", "변수"], to: "var", type: "abbrev" },
36
+ { from: ["directory", "디렉토리"], to: "dir", type: "abbrev" },
37
37
 
38
38
  // ── 한국어 동사/명령형 약어 ──
39
- { from: ['구현해'], to: 'impl', type: 'abbrev' },
40
- { from: ['확인해'], to: 'check', type: 'abbrev' },
41
- { from: ['수정해'], to: 'fix', type: 'abbrev' },
42
- { from: ['테스트'], to: 'test', type: 'abbrev' },
43
- { from: ['리뷰'], to: 'review', type: 'abbrev' },
44
- { from: ['분석'], to: 'analyze', type: 'abbrev' },
45
- { from: ['설계'], to: 'design', type: 'abbrev' },
46
- { from: ['문서화'], to: 'docs', type: 'abbrev' },
39
+ { from: ["구현해"], to: "impl", type: "abbrev" },
40
+ { from: ["확인해"], to: "check", type: "abbrev" },
41
+ { from: ["수정해"], to: "fix", type: "abbrev" },
42
+ { from: ["테스트"], to: "test", type: "abbrev" },
43
+ { from: ["리뷰"], to: "review", type: "abbrev" },
44
+ { from: ["분석"], to: "analyze", type: "abbrev" },
45
+ { from: ["설계"], to: "design", type: "abbrev" },
46
+ { from: ["문서화"], to: "docs", type: "abbrev" },
47
47
  ];
48
48
 
49
49
  /** @type {Array<{ from: string[], to: string, type: 'symbol'|'abbrev' }>} */
50
50
  export const REVIEW_RULES = [
51
- { from: ['looks good to me', 'lgtm'], to: '✓lgtm', type: 'abbrev' },
52
- { from: ['needs changes', '수정 필요'], to: '✗chg', type: 'abbrev' },
53
- { from: ['nitpick', '사소한'], to: 'nit', type: 'abbrev' },
54
- { from: ['blocking', '블로킹'], to: 'blk', type: 'abbrev' },
55
- { from: ['suggestion', '제안'], to: 'sug', type: 'abbrev' },
56
- { from: ['question', '질문'], to: 'q', type: 'abbrev' },
57
- { from: ['approved', '승인'], to: '✓apv', type: 'abbrev' },
58
- { from: ['request changes', '변경 요청'], to: '✗req', type: 'abbrev' },
51
+ { from: ["looks good to me", "lgtm"], to: "✓lgtm", type: "abbrev" },
52
+ { from: ["needs changes", "수정 필요"], to: "✗chg", type: "abbrev" },
53
+ { from: ["nitpick", "사소한"], to: "nit", type: "abbrev" },
54
+ { from: ["blocking", "블로킹"], to: "blk", type: "abbrev" },
55
+ { from: ["suggestion", "제안"], to: "sug", type: "abbrev" },
56
+ { from: ["question", "질문"], to: "q", type: "abbrev" },
57
+ { from: ["approved", "승인"], to: "✓apv", type: "abbrev" },
58
+ { from: ["request changes", "변경 요청"], to: "✗req", type: "abbrev" },
59
59
  ];
60
60
 
61
61
  /** @type {Array<{ from: string[], to: string, type: 'symbol'|'abbrev' }>} */
62
62
  export const DESIGN_RULES = [
63
- { from: ['component', '컴포넌트'], to: 'cmp', type: 'abbrev' },
64
- { from: ['interface', '인터페이스'], to: 'iface', type: 'abbrev' },
65
- { from: ['abstraction', '추상화'], to: 'abs', type: 'abbrev' },
66
- { from: ['pattern', '패턴'], to: 'ptn', type: 'abbrev' },
67
- { from: ['dependency injection', '의존성 주입'], to: 'di', type: 'abbrev' },
68
- { from: ['single responsibility', '단일 책임'], to: 'srp', type: 'abbrev' },
69
- { from: ['open closed', '개방 폐쇄'], to: 'ocp', type: 'abbrev' },
70
- { from: ['inheritance', '상속'], to: 'inh', type: 'abbrev' },
63
+ { from: ["component", "컴포넌트"], to: "cmp", type: "abbrev" },
64
+ { from: ["interface", "인터페이스"], to: "iface", type: "abbrev" },
65
+ { from: ["abstraction", "추상화"], to: "abs", type: "abbrev" },
66
+ { from: ["pattern", "패턴"], to: "ptn", type: "abbrev" },
67
+ { from: ["dependency injection", "의존성 주입"], to: "di", type: "abbrev" },
68
+ { from: ["single responsibility", "단일 책임"], to: "srp", type: "abbrev" },
69
+ { from: ["open closed", "개방 폐쇄"], to: "ocp", type: "abbrev" },
70
+ { from: ["inheritance", "상속"], to: "inh", type: "abbrev" },
71
71
  ];
72
72
 
73
73
  /** @type {Array<{ from: string[], to: string, type: 'symbol'|'abbrev' }>} */
74
74
  export const DOCS_RULES = [
75
- { from: ['description', '설명'], to: 'desc', type: 'abbrev' },
76
- { from: ['example', '예시'], to: 'ex', type: 'abbrev' },
77
- { from: ['reference', '참조'], to: 'ref', type: 'abbrev' },
78
- { from: ['introduction', '소개'], to: 'intro', type: 'abbrev' },
79
- { from: ['deprecated', '사용 중단'], to: 'dep', type: 'abbrev' },
80
- { from: ['optional', '선택적'], to: 'opt', type: 'abbrev' },
81
- { from: ['required', '필수'], to: 'req', type: 'abbrev' },
82
- { from: ['returns', '반환'], to: 'ret', type: 'abbrev' },
75
+ { from: ["description", "설명"], to: "desc", type: "abbrev" },
76
+ { from: ["example", "예시"], to: "ex", type: "abbrev" },
77
+ { from: ["reference", "참조"], to: "ref", type: "abbrev" },
78
+ { from: ["introduction", "소개"], to: "intro", type: "abbrev" },
79
+ { from: ["deprecated", "사용 중단"], to: "dep", type: "abbrev" },
80
+ { from: ["optional", "선택적"], to: "opt", type: "abbrev" },
81
+ { from: ["required", "필수"], to: "req", type: "abbrev" },
82
+ { from: ["returns", "반환"], to: "ret", type: "abbrev" },
83
83
  ];
84
84
 
85
85
  // ── 프로필 맵 ──
@@ -87,9 +87,9 @@ export const DOCS_RULES = [
87
87
  /** @type {Record<string, Array<{ from: string[], to: string, type: 'symbol'|'abbrev' }>>} */
88
88
  const PROFILE_MAP = {
89
89
  default: COMPACT_RULES,
90
- review: [...COMPACT_RULES, ...REVIEW_RULES],
91
- design: [...COMPACT_RULES, ...DESIGN_RULES],
92
- docs: [...COMPACT_RULES, ...DOCS_RULES],
90
+ review: [...COMPACT_RULES, ...REVIEW_RULES],
91
+ design: [...COMPACT_RULES, ...DESIGN_RULES],
92
+ docs: [...COMPACT_RULES, ...DOCS_RULES],
93
93
  };
94
94
 
95
95
  // ── 내부: 정렬된 치환 쌍 빌드 헬퍼 ──
@@ -135,7 +135,7 @@ const CODE_BLOCK_RE = /```[\s\S]*?```/g;
135
135
  */
136
136
  function withCodeProtection(text, transform) {
137
137
  const blocks = [];
138
- const placeholder = '\x00CB';
138
+ const placeholder = "\x00CB";
139
139
  let idx = 0;
140
140
  const masked = text.replace(CODE_BLOCK_RE, (match) => {
141
141
  blocks.push(match);
@@ -146,7 +146,7 @@ function withCodeProtection(text, transform) {
146
146
 
147
147
  // 플레이스홀더 복원
148
148
  return transformed.replace(
149
- new RegExp(`${placeholder}(\\d+)${placeholder}`, 'g'),
149
+ new RegExp(`${placeholder}(\\d+)${placeholder}`, "g"),
150
150
  (_, i) => blocks[Number(i)],
151
151
  );
152
152
  }
@@ -170,14 +170,14 @@ export function isCompactMode() {
170
170
  * @returns {string}
171
171
  */
172
172
  export function compactify(text) {
173
- if (!text || typeof text !== 'string') return text ?? '';
173
+ if (!text || typeof text !== "string") return text ?? "";
174
174
  _compactMode = true;
175
175
 
176
176
  return withCodeProtection(text, (segment) => {
177
177
  let result = segment;
178
178
  for (const { pattern, to } of _compactPairs) {
179
- const escaped = pattern.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
180
- const re = new RegExp(escaped, 'gi');
179
+ const escaped = pattern.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
180
+ const re = new RegExp(escaped, "gi");
181
181
  result = result.replace(re, to);
182
182
  }
183
183
  return result;
@@ -190,8 +190,8 @@ export function compactify(text) {
190
190
  * @param {'default'|'review'|'design'|'docs'} [profile='default'] — 도메인 프로필
191
191
  * @returns {string}
192
192
  */
193
- export function applyCompactRules(text, profile = 'default') {
194
- if (!text || typeof text !== 'string') return text ?? '';
193
+ export function applyCompactRules(text, profile = "default") {
194
+ if (!text || typeof text !== "string") return text ?? "";
195
195
 
196
196
  const rules = PROFILE_MAP[profile] ?? COMPACT_RULES;
197
197
  const pairs = buildCompactPairs(rules);
@@ -199,8 +199,8 @@ export function applyCompactRules(text, profile = 'default') {
199
199
  return withCodeProtection(text, (segment) => {
200
200
  let result = segment;
201
201
  for (const { pattern, to } of pairs) {
202
- const escaped = pattern.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
203
- const re = new RegExp(escaped, 'gi');
202
+ const escaped = pattern.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
203
+ const re = new RegExp(escaped, "gi");
204
204
  result = result.replace(re, to);
205
205
  }
206
206
  return result;
@@ -213,14 +213,14 @@ export function applyCompactRules(text, profile = 'default') {
213
213
  * @returns {string}
214
214
  */
215
215
  export function expand(text) {
216
- if (!text || typeof text !== 'string') return text ?? '';
216
+ if (!text || typeof text !== "string") return text ?? "";
217
217
  _compactMode = false;
218
218
 
219
219
  return withCodeProtection(text, (segment) => {
220
220
  let result = segment;
221
221
  for (const { symbol, restore } of _expandPairs) {
222
- const escaped = symbol.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
223
- const re = new RegExp(escaped, 'g');
222
+ const escaped = symbol.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
223
+ const re = new RegExp(escaped, "g");
224
224
  result = result.replace(re, restore);
225
225
  }
226
226
  return result;
package/hub/tray.mjs CHANGED
@@ -1,7 +1,9 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  import _SysTrayModule from "systray2";
4
+
4
5
  const SysTray = _SysTrayModule.default || _SysTrayModule;
6
+
5
7
  import { exec } from "node:child_process";
6
8
  import { existsSync, readFileSync } from "node:fs";
7
9
  import { homedir } from "node:os";
@@ -13,7 +15,8 @@ const HUB_PID_FILE = join(homedir(), ".claude", "cache", "tfx-hub", "hub.pid");
13
15
  const DEFAULT_HUB_PORT = "27888";
14
16
 
15
17
  function getHubBaseUrl() {
16
- if (process.env.TFX_HUB_URL) return process.env.TFX_HUB_URL.replace(/\/+$/, "");
18
+ if (process.env.TFX_HUB_URL)
19
+ return process.env.TFX_HUB_URL.replace(/\/+$/, "");
17
20
  try {
18
21
  const info = JSON.parse(readFileSync(HUB_PID_FILE, "utf8"));
19
22
  if (info.port) return `http://${info.host || "127.0.0.1"}:${info.port}`;
@@ -42,7 +45,8 @@ const CODEX_RATE_LIMITS_FILE = join(CACHE_DIR, "codex-rate-limits-cache.json");
42
45
  const GEMINI_QUOTA_FILE = join(CACHE_DIR, "gemini-quota-cache.json");
43
46
  const CLAUDE_USAGE_FILE = join(CACHE_DIR, "claude-usage-cache.json");
44
47
 
45
- const TRAY_ICON_BASE64 = "AAABAAEAICAAAAEAIAADAQAAFgAAAIlQTkcNChoKAAAADUlIRFIAAAAgAAAAIAgGAAAAc3p69AAAAMpJREFUeJzV1UEKgzAQheEcwnXP4a17gl6n6yy7U1IIqDSTeW/m0TYwK8X/E6OW8m9rWW5Pa74SlWLYeBgRDcOQ7V42a+SIGSALkwKIQKDnroJQmy4bAgO8EDnAA4EBkV3do7VWeAOfAO0Cx/EC+vnMG2QCLND12Pp4vUcK+DQ9fBxqI47uDI23oV7F2fNVxF2A64zCTBwCWGE2Pv0WzKKp8ba8wWg4DIiGKUBWdBjP+i+E4z8BUCJccRUCimdC6HAGIiWOYiRR5doBauXshzcEs0UAAAAASUVORK5CYII=";
48
+ const TRAY_ICON_BASE64 =
49
+ "AAABAAEAICAAAAEAIAADAQAAFgAAAIlQTkcNChoKAAAADUlIRFIAAAAgAAAAIAgGAAAAc3p69AAAAMpJREFUeJzV1UEKgzAQheEcwnXP4a17gl6n6yy7U1IIqDSTeW/m0TYwK8X/E6OW8m9rWW5Pa74SlWLYeBgRDcOQ7V42a+SIGSALkwKIQKDnroJQmy4bAgO8EDnAA4EBkV3do7VWeAOfAO0Cx/EC+vnMG2QCLND12Pp4vUcK+DQ9fBxqI47uDI23oV7F2fNVxF2A64zCTBwCWGE2Pv0WzKKp8ba8wWg4DIiGKUBWdBjP+i+E4z8BUCJccRUCimdC6HAGIiWOYiRR5doBauXshzcEs0UAAAAASUVORK5CYII=";
46
50
 
47
51
  function clampPercent(value) {
48
52
  if (!Number.isFinite(Number(value))) return null;
@@ -96,8 +100,10 @@ function getAimdBatchSize(now = Date.now()) {
96
100
 
97
101
  function getCodexPercent() {
98
102
  const data = readJson(CODEX_RATE_LIMITS_FILE);
99
- const buckets = data?.buckets && typeof data.buckets === "object" ? data.buckets : null;
100
- const primaryBucket = buckets?.codex ?? Object.values(buckets ?? {})[0] ?? null;
103
+ const buckets =
104
+ data?.buckets && typeof data.buckets === "object" ? data.buckets : null;
105
+ const primaryBucket =
106
+ buckets?.codex ?? Object.values(buckets ?? {})[0] ?? null;
101
107
  return clampPercent(primaryBucket?.primary?.used_percent);
102
108
  }
103
109
 
@@ -117,7 +123,10 @@ function pickGeminiBucket(data) {
117
123
  if (match) return match;
118
124
  }
119
125
 
120
- return buckets.find((bucket) => String(bucket?.modelId ?? "").includes("flash")) ?? buckets[0];
126
+ return (
127
+ buckets.find((bucket) => String(bucket?.modelId ?? "").includes("flash")) ??
128
+ buckets[0]
129
+ );
121
130
  }
122
131
 
123
132
  function getGeminiPercent() {
@@ -140,8 +149,11 @@ async function getHubStatusLabel() {
140
149
  if (!response.ok) throw new Error(`HTTP ${response.status}`);
141
150
 
142
151
  const data = await response.json();
143
- const state = typeof data?.hub?.state === "string" ? data.hub.state : "connected";
144
- const sessions = Number.isFinite(Number(data?.sessions)) ? Number(data.sessions) : null;
152
+ const state =
153
+ typeof data?.hub?.state === "string" ? data.hub.state : "connected";
154
+ const sessions = Number.isFinite(Number(data?.sessions))
155
+ ? Number(data.sessions)
156
+ : null;
145
157
  return sessions == null ? `Hub: ${state}` : `Hub: ${state} | S:${sessions}`;
146
158
  } catch {
147
159
  return "Hub 미연결";
@@ -167,12 +179,32 @@ function buildUsageTitle(snapshot) {
167
179
 
168
180
  function findChromePath() {
169
181
  const candidates = [
170
- join(process.env.ProgramFiles || "", "Google", "Chrome", "Application", "chrome.exe"),
171
- join(process.env["ProgramFiles(x86)"] || "", "Google", "Chrome", "Application", "chrome.exe"),
172
- join(process.env.LOCALAPPDATA || "", "Google", "Chrome", "Application", "chrome.exe"),
182
+ join(
183
+ process.env.ProgramFiles || "",
184
+ "Google",
185
+ "Chrome",
186
+ "Application",
187
+ "chrome.exe",
188
+ ),
189
+ join(
190
+ process.env["ProgramFiles(x86)"] || "",
191
+ "Google",
192
+ "Chrome",
193
+ "Application",
194
+ "chrome.exe",
195
+ ),
196
+ join(
197
+ process.env.LOCALAPPDATA || "",
198
+ "Google",
199
+ "Chrome",
200
+ "Application",
201
+ "chrome.exe",
202
+ ),
173
203
  ];
174
204
  for (const p of candidates) {
175
- try { if (existsSync(p)) return p; } catch {}
205
+ try {
206
+ if (existsSync(p)) return p;
207
+ } catch {}
176
208
  }
177
209
  return null;
178
210
  }
@@ -183,11 +215,15 @@ function openDashboard() {
183
215
  const chrome = findChromePath();
184
216
  if (chrome) {
185
217
  // Chrome --app: 주소바/탭 없는 앱 윈도우로 열기
186
- exec(`start "" "${chrome}" "--app=${url}"`, { shell, windowsHide: true }, (err) => {
187
- if (err) {
188
- exec(`start "" "${url}"`, { shell, windowsHide: true }, () => {});
189
- }
190
- });
218
+ exec(
219
+ `start "" "${chrome}" "--app=${url}"`,
220
+ { shell, windowsHide: true },
221
+ (err) => {
222
+ if (err) {
223
+ exec(`start "" "${url}"`, { shell, windowsHide: true }, () => {});
224
+ }
225
+ },
226
+ );
191
227
  } else {
192
228
  exec(`start "" "${url}"`, { shell, windowsHide: true }, () => {});
193
229
  }
@@ -277,17 +313,22 @@ async function refreshMenu() {
277
313
  await systray.sendAction({ type: "update-item", item: aimdItem });
278
314
  await systray.sendAction({ type: "update-item", item: quotaItem });
279
315
  await systray.sendAction({ type: "update-item", item: hubItem });
280
- await systray.sendAction({ type: "update-item-and-title", item: { title: buildTooltip(snapshot) } });
316
+ await systray.sendAction({
317
+ type: "update-item-and-title",
318
+ item: { title: buildTooltip(snapshot) },
319
+ });
281
320
  }
282
321
  }
283
322
 
284
323
  function scheduleRefresh() {
285
324
  if (refreshPromise) return refreshPromise;
286
- refreshPromise = refreshMenu().catch((error) => {
287
- console.error(`[tfx-tray] refresh failed: ${error.message}`);
288
- }).finally(() => {
289
- refreshPromise = null;
290
- });
325
+ refreshPromise = refreshMenu()
326
+ .catch((error) => {
327
+ console.error(`[tfx-tray] refresh failed: ${error.message}`);
328
+ })
329
+ .finally(() => {
330
+ refreshPromise = null;
331
+ });
291
332
  return refreshPromise;
292
333
  }
293
334
 
@@ -366,7 +407,9 @@ export async function startTray() {
366
407
  };
367
408
  }
368
409
 
369
- const selfRun = process.argv[1] && resolve(process.argv[1]) === resolve(fileURLToPath(import.meta.url));
410
+ const selfRun =
411
+ process.argv[1] &&
412
+ resolve(process.argv[1]) === resolve(fileURLToPath(import.meta.url));
370
413
 
371
414
  if (selfRun) {
372
415
  startTray().catch((error) => {