triflux 10.4.0 → 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 (391) hide show
  1. package/.claude-plugin/marketplace.json +34 -0
  2. package/.claude-plugin/plugin.json +22 -0
  3. package/bin/tfx-doctor-tui.mjs +1 -1
  4. package/bin/tfx-doctor.mjs +6 -1
  5. package/bin/tfx-profile.mjs +1 -1
  6. package/bin/tfx-setup-tui.mjs +1 -1
  7. package/bin/tfx-setup.mjs +6 -1
  8. package/bin/triflux.mjs +2396 -1140
  9. package/config/mcp-registry.json +29 -0
  10. package/hooks/agent-route-guard.mjs +12 -8
  11. package/hooks/cross-review-tracker.mjs +21 -8
  12. package/hooks/error-context.mjs +19 -7
  13. package/hooks/hook-adaptive-collector.mjs +18 -16
  14. package/hooks/hook-manager.mjs +93 -32
  15. package/hooks/hook-orchestrator.mjs +108 -24
  16. package/hooks/hook-registry.json +267 -256
  17. package/hooks/keyword-rules.json +6 -10
  18. package/hooks/lib/resolve-root.mjs +1 -1
  19. package/hooks/mcp-config-watcher.mjs +6 -2
  20. package/hooks/pipeline-stop.mjs +3 -6
  21. package/hooks/safety-guard.mjs +99 -28
  22. package/hooks/session-start-fast.mjs +143 -0
  23. package/hooks/subagent-verifier.mjs +5 -4
  24. package/hub/account-broker.mjs +256 -60
  25. package/hub/adaptive-diagnostic.mjs +75 -48
  26. package/hub/adaptive-inject.mjs +96 -58
  27. package/hub/adaptive-memory.mjs +156 -42
  28. package/hub/adaptive.mjs +60 -31
  29. package/hub/assign-callbacks.mjs +163 -126
  30. package/hub/bridge.mjs +0 -1
  31. package/hub/cli-adapter-base.mjs +200 -48
  32. package/hub/codex-adapter.mjs +76 -96
  33. package/hub/codex-compat.mjs +3 -3
  34. package/hub/codex-preflight.mjs +63 -37
  35. package/hub/delegator/contracts.mjs +19 -23
  36. package/hub/delegator/index.mjs +14 -14
  37. package/hub/delegator/service.mjs +88 -64
  38. package/hub/delegator/tool-definitions.mjs +35 -35
  39. package/hub/fullcycle.mjs +33 -17
  40. package/hub/gemini-adapter.mjs +69 -94
  41. package/hub/hitl.mjs +202 -143
  42. package/hub/intent.mjs +161 -38
  43. package/hub/lib/cache-guard.mjs +43 -17
  44. package/hub/lib/mcp-response-cache.mjs +66 -32
  45. package/hub/lib/memory-store.mjs +285 -111
  46. package/hub/lib/path-utils.mjs +35 -37
  47. package/hub/lib/process-utils.mjs +106 -37
  48. package/hub/lib/spawn-trace.mjs +527 -0
  49. package/hub/lib/ssh-command.mjs +34 -4
  50. package/hub/lib/ssh-retry.mjs +5 -1
  51. package/hub/lib/uuidv7.mjs +4 -3
  52. package/hub/memory-doctor.mjs +266 -106
  53. package/hub/middleware/request-logger.mjs +61 -34
  54. package/hub/paths.mjs +9 -9
  55. package/hub/pipeline/gates/confidence.mjs +34 -15
  56. package/hub/pipeline/gates/consensus.mjs +27 -15
  57. package/hub/pipeline/gates/index.mjs +7 -3
  58. package/hub/pipeline/gates/selfcheck.mjs +57 -19
  59. package/hub/pipeline/index.mjs +77 -42
  60. package/hub/pipeline/state.mjs +10 -10
  61. package/hub/pipeline/transitions.mjs +40 -23
  62. package/hub/platform.mjs +57 -48
  63. package/hub/promote-penalties.mjs +25 -7
  64. package/hub/quality/deslop.mjs +70 -49
  65. package/hub/research.mjs +32 -25
  66. package/hub/router.mjs +924 -791
  67. package/hub/routing/complexity.mjs +132 -29
  68. package/hub/routing/index.mjs +17 -12
  69. package/hub/routing/q-learning.mjs +76 -28
  70. package/hub/server.mjs +4 -4
  71. package/hub/session-fingerprint.mjs +127 -61
  72. package/hub/state.mjs +84 -43
  73. package/hub/store-adapter.mjs +59 -26
  74. package/hub/store.mjs +356 -153
  75. package/hub/team/agent-map.json +22 -7
  76. package/hub/team/ansi.mjs +186 -122
  77. package/hub/team/backend.mjs +28 -10
  78. package/hub/team/cli/commands/attach.mjs +57 -37
  79. package/hub/team/cli/commands/control.mjs +29 -8
  80. package/hub/team/cli/commands/debug.mjs +95 -74
  81. package/hub/team/cli/commands/focus.mjs +80 -53
  82. package/hub/team/cli/commands/interrupt.mjs +18 -6
  83. package/hub/team/cli/commands/kill.mjs +16 -5
  84. package/hub/team/cli/commands/list.mjs +31 -24
  85. package/hub/team/cli/commands/send.mjs +19 -6
  86. package/hub/team/cli/commands/start/index.mjs +154 -31
  87. package/hub/team/cli/commands/start/parse-args.mjs +38 -11
  88. package/hub/team/cli/commands/start/start-headless.mjs +112 -36
  89. package/hub/team/cli/commands/start/start-in-process.mjs +50 -40
  90. package/hub/team/cli/commands/start/start-mux.mjs +122 -73
  91. package/hub/team/cli/commands/start/start-wt.mjs +86 -69
  92. package/hub/team/cli/commands/status.mjs +43 -14
  93. package/hub/team/cli/commands/stop.mjs +11 -4
  94. package/hub/team/cli/commands/task.mjs +8 -3
  95. package/hub/team/cli/commands/tasks.mjs +13 -13
  96. package/hub/team/cli/index.mjs +2 -2
  97. package/hub/team/cli/manifest.mjs +38 -8
  98. package/hub/team/cli/render.mjs +52 -30
  99. package/hub/team/cli/services/attach-fallback.mjs +74 -54
  100. package/hub/team/cli/services/hub-client.mjs +42 -14
  101. package/hub/team/cli/services/member-selector.mjs +37 -30
  102. package/hub/team/cli/services/native-control.mjs +143 -116
  103. package/hub/team/cli/services/runtime-mode.mjs +2 -1
  104. package/hub/team/cli/services/state-store.mjs +25 -8
  105. package/hub/team/cli/services/task-model.mjs +40 -30
  106. package/hub/team/conductor-mesh-bridge.mjs +24 -23
  107. package/hub/team/conductor.mjs +8 -4
  108. package/hub/team/dashboard-anchor.mjs +4 -5
  109. package/hub/team/dashboard-layout.mjs +3 -1
  110. package/hub/team/dashboard-open.mjs +41 -21
  111. package/hub/team/dashboard.mjs +76 -28
  112. package/hub/team/event-log.mjs +18 -10
  113. package/hub/team/handoff.mjs +31 -15
  114. package/hub/team/headless.mjs +2 -1
  115. package/hub/team/health-probe.mjs +69 -54
  116. package/hub/team/launcher-template.mjs +16 -13
  117. package/hub/team/native-supervisor.mjs +65 -21
  118. package/hub/team/native.mjs +74 -35
  119. package/hub/team/nativeProxy.mjs +184 -113
  120. package/hub/team/notify.mjs +120 -77
  121. package/hub/team/orchestrator.mjs +166 -161
  122. package/hub/team/pane.mjs +12 -7
  123. package/hub/team/process-cleanup.mjs +25 -16
  124. package/hub/team/psmux.mjs +491 -201
  125. package/hub/team/remote-probe.mjs +68 -52
  126. package/hub/team/remote-session.mjs +117 -59
  127. package/hub/team/remote-watcher.mjs +61 -33
  128. package/hub/team/routing.mjs +51 -25
  129. package/hub/team/runtime-strategy.mjs +3 -1
  130. package/hub/team/session.mjs +675 -611
  131. package/hub/team/shared.mjs +13 -13
  132. package/hub/team/staleState.mjs +72 -30
  133. package/hub/team/swarm-locks.mjs +15 -13
  134. package/hub/team/swarm-planner.mjs +32 -21
  135. package/hub/team/swarm-reconciler.mjs +48 -23
  136. package/hub/team/tui-lite.mjs +266 -68
  137. package/hub/team/tui-remote-adapter.mjs +14 -10
  138. package/hub/team/tui-viewer.mjs +99 -43
  139. package/hub/team/tui.mjs +708 -271
  140. package/hub/team/worktree-lifecycle.mjs +152 -58
  141. package/hub/team/wt-manager.mjs +24 -14
  142. package/hub/token-mode.mjs +71 -71
  143. package/hub/tray.mjs +411 -368
  144. package/hub/workers/claude-worker.mjs +162 -118
  145. package/hub/workers/codex-mcp.mjs +558 -507
  146. package/hub/workers/delegator-mcp.mjs +507 -333
  147. package/hub/workers/factory.mjs +21 -21
  148. package/hub/workers/gemini-worker.mjs +115 -84
  149. package/hub/workers/interface.mjs +6 -1
  150. package/hub/workers/worker-utils.mjs +21 -14
  151. package/hud/colors.mjs +27 -9
  152. package/hud/constants.mjs +162 -26
  153. package/hud/context-monitor.mjs +82 -41
  154. package/hud/hud-qos-status.mjs +129 -49
  155. package/hud/mission-board.mjs +6 -3
  156. package/hud/providers/claude.mjs +226 -115
  157. package/hud/providers/codex.mjs +62 -22
  158. package/hud/providers/gemini.mjs +168 -56
  159. package/hud/renderers.mjs +384 -119
  160. package/hud/terminal.mjs +101 -31
  161. package/hud/utils.mjs +78 -38
  162. package/mesh/index.mjs +11 -5
  163. package/mesh/mesh-budget.mjs +18 -9
  164. package/mesh/mesh-heartbeat.mjs +1 -1
  165. package/mesh/mesh-queue.mjs +3 -5
  166. package/mesh/mesh-router.mjs +5 -4
  167. package/package.json +56 -21
  168. package/scripts/__tests__/gen-skill-docs.test.mjs +36 -7
  169. package/scripts/__tests__/keyword-detector.test.mjs +77 -28
  170. package/scripts/__tests__/mcp-guard-engine.test.mjs +58 -20
  171. package/scripts/__tests__/remote-spawn-transfer.test.mjs +30 -19
  172. package/scripts/__tests__/remote-spawn.test.mjs +10 -4
  173. package/scripts/__tests__/session-start-fast.test.mjs +36 -0
  174. package/scripts/__tests__/skill-template.test.mjs +98 -50
  175. package/scripts/__tests__/smoke.test.mjs +1 -1
  176. package/scripts/__tests__/spawn-trace.test.mjs +102 -0
  177. package/scripts/__tests__/tfx-doctor-diagnose.test.mjs +48 -0
  178. package/scripts/cache-doctor.mjs +11 -4
  179. package/scripts/cache-warmup.mjs +96 -37
  180. package/scripts/claudemd-sync.mjs +27 -17
  181. package/scripts/codex-gateway-preflight.mjs +52 -37
  182. package/scripts/codex-mcp-gateway-sync.mjs +59 -39
  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 +139 -120
  193. package/scripts/keyword-detector.mjs +293 -272
  194. package/scripts/keyword-rules-expander.mjs +538 -521
  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 +355 -118
  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 +669 -554
  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 +61 -57
  229. package/scripts/tfx-batch-stats.mjs +117 -96
  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/idle-notif-cooldown.json +1 -1
  237. package/skills/.omc/state/last-tool-error.json +1 -1
  238. package/skills/.omc/state/subagent-tracking.json +1 -1
  239. package/skills/_templates/base.md +1 -6
  240. package/skills/merge-worktree/SKILL.md.tmpl +144 -0
  241. package/skills/shared/telemetry-segment.md +6 -0
  242. package/skills/star-prompt/SKILL.md.tmpl +222 -0
  243. package/skills/tfx-analysis/SKILL.md.tmpl +107 -0
  244. package/skills/tfx-analysis/skill.json +1 -6
  245. package/skills/tfx-auto/SKILL.md +1 -0
  246. package/skills/{tfx-workspace/skill-snapshot/tfx-auto-codex/SKILL.md → tfx-auto-codex/SKILL.md.tmpl} +33 -4
  247. package/skills/tfx-auto-codex/skill.json +1 -3
  248. package/skills/tfx-autopilot/SKILL.md.tmpl +116 -0
  249. package/skills/tfx-autopilot/skill.json +1 -5
  250. package/skills/tfx-autoresearch/SKILL.md.tmpl +136 -0
  251. package/skills/tfx-autoroute/SKILL.md.tmpl +189 -0
  252. package/skills/tfx-autoroute/skill.json +1 -7
  253. package/skills/tfx-codex/SKILL.md +1 -0
  254. package/skills/tfx-codex/skill.json +1 -3
  255. package/skills/tfx-codex-swarm/SKILL.md.tmpl +16 -0
  256. package/skills/tfx-codex-swarm/evals/evals.json +1 -1
  257. package/skills/tfx-codex-swarm/skill.json +1 -4
  258. package/skills/tfx-codex-swarm-workspace/iteration-1/benchmark.json +54 -12
  259. package/skills/tfx-codex-swarm-workspace/iteration-1/full-swarm-all-prds/with_skill/grading.json +35 -7
  260. package/skills/tfx-codex-swarm-workspace/iteration-1/full-swarm-all-prds/without_skill/grading.json +35 -7
  261. package/skills/tfx-codex-swarm-workspace/iteration-1/implicit-swarm-no-keywords/with_skill/grading.json +25 -5
  262. package/skills/tfx-codex-swarm-workspace/iteration-1/implicit-swarm-no-keywords/without_skill/grading.json +25 -5
  263. package/skills/tfx-codex-swarm-workspace/iteration-1/selective-spawn-with-override/with_skill/grading.json +20 -4
  264. package/skills/tfx-codex-swarm-workspace/iteration-1/selective-spawn-with-override/without_skill/grading.json +16 -4
  265. package/skills/tfx-consensus/SKILL.md.tmpl +146 -0
  266. package/skills/tfx-debate/SKILL.md.tmpl +192 -0
  267. package/skills/tfx-debate/skill.json +1 -7
  268. package/skills/tfx-deep-analysis/SKILL.md.tmpl +228 -0
  269. package/skills/tfx-deep-analysis/skill.json +1 -5
  270. package/skills/tfx-deep-interview/SKILL.md.tmpl +203 -0
  271. package/skills/tfx-deep-plan/SKILL.md.tmpl +282 -0
  272. package/skills/tfx-deep-qa/SKILL.md.tmpl +165 -0
  273. package/skills/tfx-deep-qa/skill.json +1 -6
  274. package/skills/tfx-deep-research/SKILL.md.tmpl +217 -0
  275. package/skills/tfx-deep-review/SKILL.md.tmpl +179 -0
  276. package/skills/tfx-doctor/SKILL.md +21 -0
  277. package/skills/tfx-doctor/SKILL.md.tmpl +172 -0
  278. package/skills/tfx-doctor/skill.json +1 -3
  279. package/skills/tfx-find/SKILL.md +1 -0
  280. package/skills/tfx-forge/SKILL.md.tmpl +187 -0
  281. package/skills/tfx-fullcycle/SKILL.md.tmpl +286 -0
  282. package/skills/tfx-fullcycle/skill.json +1 -6
  283. package/skills/{tfx-workspace/skill-snapshot/tfx-gemini/SKILL.md → tfx-gemini/SKILL.md.tmpl} +16 -7
  284. package/skills/tfx-gemini/skill.json +1 -3
  285. package/skills/tfx-hooks/SKILL.md.tmpl +216 -0
  286. package/skills/tfx-hooks/skill.json +1 -3
  287. package/skills/tfx-hub/SKILL.md.tmpl +212 -0
  288. package/skills/tfx-hub/skill.json +1 -3
  289. package/skills/tfx-index/SKILL.md +1 -0
  290. package/skills/tfx-index/skill.json +1 -6
  291. package/skills/tfx-interview/SKILL.md.tmpl +285 -0
  292. package/skills/tfx-multi/SKILL.md.tmpl +183 -0
  293. package/skills/tfx-multi/skill.json +1 -3
  294. package/skills/tfx-panel/SKILL.md.tmpl +189 -0
  295. package/skills/tfx-panel/skill.json +1 -7
  296. package/skills/tfx-persist/SKILL.md.tmpl +270 -0
  297. package/skills/tfx-persist/skill.json +1 -7
  298. package/skills/tfx-plan/SKILL.md +1 -0
  299. package/skills/tfx-plan/skill.json +1 -6
  300. package/skills/tfx-profile/SKILL.md.tmpl +239 -0
  301. package/skills/tfx-profile/skill.json +1 -3
  302. package/skills/tfx-prune/SKILL.md.tmpl +200 -0
  303. package/skills/tfx-prune/skill.json +1 -7
  304. package/skills/tfx-psmux-rules/SKILL.md.tmpl +326 -0
  305. package/skills/tfx-psmux-rules/skill.json +1 -4
  306. package/skills/tfx-qa/SKILL.md +1 -0
  307. package/skills/tfx-qa/skill.json +1 -6
  308. package/skills/tfx-ralph/SKILL.md.tmpl +28 -0
  309. package/skills/tfx-ralph/skill.json +1 -4
  310. package/skills/tfx-remote-setup/SKILL.md.tmpl +576 -0
  311. package/skills/tfx-remote-setup/skill.json +1 -3
  312. package/skills/tfx-remote-spawn/SKILL.md.tmpl +263 -0
  313. package/skills/tfx-remote-spawn/references/hosts.json +16 -16
  314. package/skills/tfx-remote-spawn/skill.json +1 -4
  315. package/skills/tfx-research/SKILL.md +1 -0
  316. package/skills/tfx-review/SKILL.md +1 -0
  317. package/skills/tfx-review/skill.json +1 -6
  318. package/skills/tfx-setup/SKILL.md.tmpl +504 -0
  319. package/skills/tfx-setup/skill.json +1 -3
  320. package/skills/tfx-swarm/SKILL.md +22 -0
  321. package/skills/tfx-swarm/SKILL.md.tmpl +218 -0
  322. package/tui/codex-profile.mjs +457 -0
  323. package/tui/core.mjs +266 -0
  324. package/tui/doctor.mjs +375 -0
  325. package/tui/gemini-profile.mjs +299 -0
  326. package/tui/monitor-data.mjs +152 -0
  327. package/tui/monitor.mjs +339 -0
  328. package/tui/setup.mjs +533 -0
  329. package/CLAUDE.md +0 -193
  330. package/references/hosts.json +0 -33
  331. package/skills/tfx-workspace/async-tests/run-tests.sh +0 -203
  332. package/skills/tfx-workspace/evals/evals.json +0 -79
  333. package/skills/tfx-workspace/iteration-1/benchmark.json +0 -162
  334. package/skills/tfx-workspace/iteration-1/codex-gemini-remap/eval_metadata.json +0 -11
  335. package/skills/tfx-workspace/iteration-1/codex-gemini-remap/old_skill/grading.json +0 -9
  336. package/skills/tfx-workspace/iteration-1/codex-gemini-remap/old_skill/outputs/analysis.md +0 -154
  337. package/skills/tfx-workspace/iteration-1/codex-gemini-remap/old_skill/timing.json +0 -5
  338. package/skills/tfx-workspace/iteration-1/codex-gemini-remap/with_skill/grading.json +0 -9
  339. package/skills/tfx-workspace/iteration-1/codex-gemini-remap/with_skill/outputs/analysis.md +0 -126
  340. package/skills/tfx-workspace/iteration-1/codex-gemini-remap/with_skill/timing.json +0 -5
  341. package/skills/tfx-workspace/iteration-1/doctor-diagnosis/eval_metadata.json +0 -11
  342. package/skills/tfx-workspace/iteration-1/doctor-diagnosis/old_skill/grading.json +0 -9
  343. package/skills/tfx-workspace/iteration-1/doctor-diagnosis/old_skill/outputs/analysis.md +0 -119
  344. package/skills/tfx-workspace/iteration-1/doctor-diagnosis/old_skill/timing.json +0 -5
  345. package/skills/tfx-workspace/iteration-1/doctor-diagnosis/with_skill/grading.json +0 -9
  346. package/skills/tfx-workspace/iteration-1/doctor-diagnosis/with_skill/outputs/analysis.md +0 -115
  347. package/skills/tfx-workspace/iteration-1/doctor-diagnosis/with_skill/timing.json +0 -5
  348. package/skills/tfx-workspace/iteration-1/hub-start-sequence/eval_metadata.json +0 -10
  349. package/skills/tfx-workspace/iteration-1/hub-start-sequence/old_skill/grading.json +0 -8
  350. package/skills/tfx-workspace/iteration-1/hub-start-sequence/old_skill/outputs/analysis.md +0 -86
  351. package/skills/tfx-workspace/iteration-1/hub-start-sequence/old_skill/timing.json +0 -5
  352. package/skills/tfx-workspace/iteration-1/hub-start-sequence/with_skill/grading.json +0 -8
  353. package/skills/tfx-workspace/iteration-1/hub-start-sequence/with_skill/outputs/analysis.md +0 -81
  354. package/skills/tfx-workspace/iteration-1/hub-start-sequence/with_skill/timing.json +0 -5
  355. package/skills/tfx-workspace/iteration-1/multi-team-creation/eval_metadata.json +0 -12
  356. package/skills/tfx-workspace/iteration-1/multi-team-creation/old_skill/grading.json +0 -10
  357. package/skills/tfx-workspace/iteration-1/multi-team-creation/old_skill/outputs/analysis.md +0 -316
  358. package/skills/tfx-workspace/iteration-1/multi-team-creation/old_skill/timing.json +0 -5
  359. package/skills/tfx-workspace/iteration-1/multi-team-creation/with_skill/grading.json +0 -10
  360. package/skills/tfx-workspace/iteration-1/multi-team-creation/with_skill/outputs/analysis.md +0 -352
  361. package/skills/tfx-workspace/iteration-1/multi-team-creation/with_skill/timing.json +0 -5
  362. package/skills/tfx-workspace/iteration-1/review.html +0 -1325
  363. package/skills/tfx-workspace/iteration-1/routing-implement-shortcut/eval_metadata.json +0 -12
  364. package/skills/tfx-workspace/iteration-1/routing-implement-shortcut/old_skill/grading.json +0 -10
  365. package/skills/tfx-workspace/iteration-1/routing-implement-shortcut/old_skill/outputs/analysis.md +0 -97
  366. package/skills/tfx-workspace/iteration-1/routing-implement-shortcut/old_skill/timing.json +0 -5
  367. package/skills/tfx-workspace/iteration-1/routing-implement-shortcut/with_skill/grading.json +0 -10
  368. package/skills/tfx-workspace/iteration-1/routing-implement-shortcut/with_skill/outputs/analysis.md +0 -94
  369. package/skills/tfx-workspace/iteration-1/routing-implement-shortcut/with_skill/timing.json +0 -5
  370. package/skills/tfx-workspace/iteration-1/routing-multi-task-triage/eval_metadata.json +0 -12
  371. package/skills/tfx-workspace/iteration-1/routing-multi-task-triage/old_skill/grading.json +0 -10
  372. package/skills/tfx-workspace/iteration-1/routing-multi-task-triage/old_skill/outputs/analysis.md +0 -209
  373. package/skills/tfx-workspace/iteration-1/routing-multi-task-triage/old_skill/timing.json +0 -5
  374. package/skills/tfx-workspace/iteration-1/routing-multi-task-triage/with_skill/grading.json +0 -10
  375. package/skills/tfx-workspace/iteration-1/routing-multi-task-triage/with_skill/outputs/analysis.md +0 -193
  376. package/skills/tfx-workspace/iteration-1/routing-multi-task-triage/with_skill/timing.json +0 -5
  377. package/skills/tfx-workspace/iteration-2/benchmark.json +0 -62
  378. package/skills/tfx-workspace/iteration-2/multi-team-creation-refactored/eval_metadata.json +0 -13
  379. package/skills/tfx-workspace/iteration-2/multi-team-creation-refactored/old_skill/grading.json +0 -11
  380. package/skills/tfx-workspace/iteration-2/multi-team-creation-refactored/old_skill/outputs/analysis.md +0 -382
  381. package/skills/tfx-workspace/iteration-2/multi-team-creation-refactored/old_skill/timing.json +0 -5
  382. package/skills/tfx-workspace/iteration-2/multi-team-creation-refactored/with_skill/grading.json +0 -11
  383. package/skills/tfx-workspace/iteration-2/multi-team-creation-refactored/with_skill/outputs/analysis.md +0 -333
  384. package/skills/tfx-workspace/iteration-2/multi-team-creation-refactored/with_skill/timing.json +0 -5
  385. package/skills/tfx-workspace/iteration-2/review.html +0 -1325
  386. package/skills/tfx-workspace/skill-snapshot/tfx-auto/SKILL.md +0 -217
  387. package/skills/tfx-workspace/skill-snapshot/tfx-codex/SKILL.md +0 -65
  388. package/skills/tfx-workspace/skill-snapshot/tfx-doctor/SKILL.md +0 -94
  389. package/skills/tfx-workspace/skill-snapshot/tfx-hub/SKILL.md +0 -133
  390. package/skills/tfx-workspace/skill-snapshot/tfx-multi/SKILL.md +0 -426
  391. package/skills/tfx-workspace/skill-snapshot/tfx-setup/SKILL.md +0 -101
package/hud/renderers.mjs CHANGED
@@ -5,26 +5,51 @@ import { existsSync, readdirSync } from "node:fs";
5
5
  import { homedir } from "node:os";
6
6
  import { join } from "node:path";
7
7
  import {
8
- dim, bold, green, red, yellow, cyan,
9
- claudeOrange, codexWhite, geminiBlue,
10
- colorByPercent, colorByProvider,
11
- CLAUDE_ORANGE, CODEX_WHITE, GEMINI_BLUE,
8
+ bold,
9
+ CLAUDE_ORANGE,
10
+ CODEX_WHITE,
11
+ claudeOrange,
12
+ codexWhite,
13
+ colorByPercent,
14
+ colorByProvider,
15
+ dim,
16
+ GEMINI_BLUE,
17
+ geminiBlue,
18
+ green,
19
+ red,
20
+ yellow,
12
21
  } from "./colors.mjs";
13
22
  import {
14
- PROVIDER_PREFIX_WIDTH, ACCOUNT_LABEL_WIDTH,
15
- FIVE_HOUR_MS, SEVEN_DAY_MS, ONE_DAY_MS,
16
- TEAM_STATE_PATH, SV_ACCUMULATOR_PATH, LEGACY_SV_ACCUMULATOR,
23
+ ACCOUNT_LABEL_WIDTH,
24
+ FIVE_HOUR_MS,
25
+ LEGACY_SV_ACCUMULATOR,
26
+ ONE_DAY_MS,
27
+ PROVIDER_PREFIX_WIDTH,
28
+ SEVEN_DAY_MS,
29
+ SV_ACCUMULATOR_PATH,
30
+ TEAM_STATE_PATH,
17
31
  } from "./constants.mjs";
32
+ import { buildContextUsageView } from "./context-monitor.mjs";
33
+ import { deriveGeminiLimits } from "./providers/gemini.mjs";
34
+ import { getTerminalColumns, tierBar, tierDimBar } from "./terminal.mjs";
18
35
  import {
19
- readJson, readJsonMigrate, stripAnsi, padAnsiRight, fitText, truncateAnsi,
20
- clampPercent, formatPercentCell, formatPlaceholderPercentCell,
21
- formatTimeCell, formatTimeCellDH,
22
- formatResetRemaining, formatResetRemainingDayHour,
23
- formatTokenCount, formatSvPct, formatSavings,
36
+ clampPercent,
37
+ fitText,
38
+ formatPercentCell,
39
+ formatPlaceholderPercentCell,
40
+ formatResetRemaining,
41
+ formatResetRemainingDayHour,
42
+ formatSavings,
43
+ formatSvPct,
44
+ formatTimeCell,
45
+ formatTimeCellDH,
46
+ formatTokenCount,
47
+ padAnsiRight,
48
+ readJson,
49
+ readJsonMigrate,
50
+ stripAnsi,
51
+ truncateAnsi,
24
52
  } from "./utils.mjs";
25
- import { tierBar, tierDimBar, getTerminalColumns } from "./terminal.mjs";
26
- import { deriveGeminiLimits } from "./providers/gemini.mjs";
27
- import { buildContextUsageView } from "./context-monitor.mjs";
28
53
 
29
54
  // ============================================================================
30
55
  // 최근 벤치마크 diff 파일 읽기
@@ -33,15 +58,26 @@ export function readLatestBenchmarkDiff() {
33
58
  const diffsDir = join(homedir(), ".omc", "state", "cx-auto-tokens", "diffs");
34
59
  if (!existsSync(diffsDir)) return null;
35
60
  try {
36
- const files = readdirSync(diffsDir).filter(f => f.endsWith(".json")).sort().reverse();
61
+ const files = readdirSync(diffsDir)
62
+ .filter((f) => f.endsWith(".json"))
63
+ .sort()
64
+ .reverse();
37
65
  if (files.length === 0) return null;
38
66
  return readJson(join(diffsDir, files[0]), null);
39
- } catch { return null; }
67
+ } catch {
68
+ return null;
69
+ }
40
70
  }
41
71
 
42
72
  // 토큰 절약액 누적치 읽기 (tfx-auto token tracker)
43
73
  export function readTokenSavings() {
44
- const savingsPath = join(homedir(), ".omc", "state", "tfx-auto-tokens", "savings-total.json");
74
+ const savingsPath = join(
75
+ homedir(),
76
+ ".omc",
77
+ "state",
78
+ "tfx-auto-tokens",
79
+ "savings-total.json",
80
+ );
45
81
  const data = readJson(savingsPath, null);
46
82
  if (!data || data.totalSaved === 0) return null;
47
83
  return data;
@@ -63,14 +99,15 @@ export function formatTokenSummary(diff) {
63
99
  const inputStr = formatTokenCount(t.input);
64
100
  const outputStr = formatTokenCount(t.output);
65
101
  const actualStr = formatSavings(s.actualCost);
66
- const claudeStr = formatSavings(s.claudeCost);
67
- const savedPct = s.claudeCost > 0
68
- ? Math.round((s.saved / s.claudeCost) * 100)
69
- : 0;
102
+ const _claudeStr = formatSavings(s.claudeCost);
103
+ const savedPct =
104
+ s.claudeCost > 0 ? Math.round((s.saved / s.claudeCost) * 100) : 0;
70
105
 
71
- return `${dim("tok:")}${inputStr}${dim("in")} ${outputStr}${dim("out")} ` +
106
+ return (
107
+ `${dim("tok:")}${inputStr}${dim("in")} ${outputStr}${dim("out")} ` +
72
108
  `${dim("cost:")}${actualStr} ` +
73
- `${dim("sv:")}${green(formatSavings(s.saved))}${dim("(")}${savedPct}%${dim(")")}`;
109
+ `${dim("sv:")}${green(formatSavings(s.saved))}${dim("(")}${savedPct}%${dim(")")}`
110
+ );
74
111
  }
75
112
 
76
113
  // ============================================================================
@@ -78,10 +115,14 @@ export function formatTokenSummary(diff) {
78
115
  // ============================================================================
79
116
  export function getTeamRow(currentTier) {
80
117
  const teamState = readJson(TEAM_STATE_PATH, null);
81
- if (!teamState || !teamState.sessionName) return null;
118
+ if (!teamState?.sessionName) return null;
82
119
 
83
120
  // 팀 생존 확인: startedAt 기준 24시간 초과면 stale로 간주
84
- if (teamState.startedAt && (Date.now() - teamState.startedAt) > 24 * 60 * 60 * 1000) return null;
121
+ if (
122
+ teamState.startedAt &&
123
+ Date.now() - teamState.startedAt > 24 * 60 * 60 * 1000
124
+ )
125
+ return null;
85
126
 
86
127
  const workers = (teamState.members || []).filter((m) => m.role === "worker");
87
128
  if (!workers.length) return null;
@@ -92,26 +133,44 @@ export function getTeamRow(currentTier) {
92
133
  const total = tasks.length || workers.length;
93
134
 
94
135
  // 경과 시간 (80col 이상에서만 표시)
95
- const elapsed = (teamState.startedAt && (currentTier === "full" || currentTier === "compact"))
96
- ? `${Math.round((Date.now() - teamState.startedAt) / 60000)}m`
97
- : "";
136
+ const elapsed =
137
+ teamState.startedAt && (currentTier === "full" || currentTier === "compact")
138
+ ? `${Math.round((Date.now() - teamState.startedAt) / 60000)}m`
139
+ : "";
98
140
 
99
141
  // CLI 브랜드: 단일문자 + ANSI 색상 (x=codex, g=gemini, c=claude)
100
- const cliTag = (cli) => cli === "codex" ? bold(codexWhite("x")) : cli === "gemini" ? bold(geminiBlue("g")) : bold(claudeOrange("c"));
142
+ const cliTag = (cli) =>
143
+ cli === "codex"
144
+ ? bold(codexWhite("x"))
145
+ : cli === "gemini"
146
+ ? bold(geminiBlue("g"))
147
+ : bold(claudeOrange("c"));
101
148
  // 멤버 상태: 태그 + 상태기호 (60col 이상)
102
- const memberIcons = (currentTier === "full" || currentTier === "compact" || currentTier === "minimal") ? workers.map((m) => {
103
- const task = tasks.find((t) => t.owner === m.name);
104
- const status = task?.status === "completed" ? green("\u2713")
105
- : task?.status === "in_progress" ? yellow("\u22EF")
106
- : task?.status === "failed" ? red("\u2717")
107
- : dim("\u25CC");
108
- return `${cliTag(m.cli)}${status}`;
109
- }).join(" ") : "";
149
+ const memberIcons =
150
+ currentTier === "full" ||
151
+ currentTier === "compact" ||
152
+ currentTier === "minimal"
153
+ ? workers
154
+ .map((m) => {
155
+ const task = tasks.find((t) => t.owner === m.name);
156
+ const status =
157
+ task?.status === "completed"
158
+ ? green("\u2713")
159
+ : task?.status === "in_progress"
160
+ ? yellow("\u22EF")
161
+ : task?.status === "failed"
162
+ ? red("\u2717")
163
+ : dim("\u25CC");
164
+ return `${cliTag(m.cli)}${status}`;
165
+ })
166
+ .join(" ")
167
+ : "";
110
168
 
111
169
  // 진행 텍스트
112
- const doneText = failed > 0
113
- ? `${completed}/${total} ${red(`${failed}\u2717`)}`
114
- : `${completed}/${total}`;
170
+ const doneText =
171
+ failed > 0
172
+ ? `${completed}/${total} ${red(`${failed}\u2717`)}`
173
+ : `${completed}/${total}`;
115
174
 
116
175
  const leftText = elapsed ? `${doneText} ${dim(elapsed)}` : doneText;
117
176
 
@@ -159,8 +218,13 @@ export function renderMissionBoard(state) {
159
218
  // ============================================================================
160
219
  export function renderAlignedRows(rows) {
161
220
  const cols = getTerminalColumns() || 120;
162
- const rightRows = rows.filter((row) => stripAnsi(String(row.right || "")).trim().length > 0);
163
- const rawLeftWidth = rightRows.reduce((max, row) => Math.max(max, stripAnsi(row.left).length), 0);
221
+ const rightRows = rows.filter(
222
+ (row) => stripAnsi(String(row.right || "")).trim().length > 0,
223
+ );
224
+ const rawLeftWidth = rightRows.reduce(
225
+ (max, row) => Math.max(max, stripAnsi(row.left).length),
226
+ 0,
227
+ );
164
228
  return rows.map((row) => {
165
229
  const prefix = padAnsiRight(row.prefix, PROVIDER_PREFIX_WIDTH);
166
230
  const hasRight = stripAnsi(String(row.right || "")).trim().length > 0;
@@ -179,9 +243,10 @@ export function renderAlignedRows(rows) {
179
243
  return truncateAnsi(`${prefix} ${left}`, cols);
180
244
  }
181
245
  const rightVisible = stripAnsi(row.right).length;
182
- const right = rightVisible <= availableForRight
183
- ? row.right
184
- : truncateAnsi(row.right, availableForRight);
246
+ const right =
247
+ rightVisible <= availableForRight
248
+ ? row.right
249
+ : truncateAnsi(row.right, availableForRight);
185
250
  return `${prefix} ${left} ${dim("|")} ${right}`;
186
251
  });
187
252
  }
@@ -189,24 +254,44 @@ export function renderAlignedRows(rows) {
189
254
  // ============================================================================
190
255
  // micro tier: 모든 프로바이더를 1줄로 압축
191
256
  // ============================================================================
192
- export function getMicroLine(contextView, claudeUsage, codexBuckets, geminiSession, geminiBucket, combinedSvPct) {
257
+ export function getMicroLine(
258
+ contextView,
259
+ claudeUsage,
260
+ codexBuckets,
261
+ geminiSession,
262
+ geminiBucket,
263
+ combinedSvPct,
264
+ ) {
193
265
  const ctxView = contextView || buildContextUsageView({}, null);
194
266
  const staleMarker = claudeUsage?.stale ? ` ${dim("[stale]")}` : "";
195
267
 
196
268
  // Claude 5h/1w
197
- const cF = claudeUsage?.fiveHourPercent != null ? clampPercent(claudeUsage.fiveHourPercent) : null;
198
- const cW = claudeUsage?.weeklyPercent != null ? clampPercent(claudeUsage.weeklyPercent) : null;
199
- const cVal = claudeUsage != null
200
- ? `${cF != null ? colorByProvider(cF, `${cF}`, claudeOrange) : dim("--")}${dim("/")}${cW != null ? colorByProvider(cW, `${cW}`, claudeOrange) : dim("--")}`
201
- : dim("--/--");
269
+ const cF =
270
+ claudeUsage?.fiveHourPercent != null
271
+ ? clampPercent(claudeUsage.fiveHourPercent)
272
+ : null;
273
+ const cW =
274
+ claudeUsage?.weeklyPercent != null
275
+ ? clampPercent(claudeUsage.weeklyPercent)
276
+ : null;
277
+ const cVal =
278
+ claudeUsage != null
279
+ ? `${cF != null ? colorByProvider(cF, `${cF}`, claudeOrange) : dim("--")}${dim("/")}${cW != null ? colorByProvider(cW, `${cW}`, claudeOrange) : dim("--")}`
280
+ : dim("--/--");
202
281
 
203
282
  // Codex 5h/1w
204
283
  let xVal = dim("--/--");
205
284
  if (codexBuckets) {
206
285
  const mb = codexBuckets.codex || codexBuckets[Object.keys(codexBuckets)[0]];
207
286
  if (mb) {
208
- const xF = mb.primary?.used_percent != null ? clampPercent(mb.primary.used_percent) : null;
209
- const xW = mb.secondary?.used_percent != null ? clampPercent(mb.secondary.used_percent) : null;
287
+ const xF =
288
+ mb.primary?.used_percent != null
289
+ ? clampPercent(mb.primary.used_percent)
290
+ : null;
291
+ const xW =
292
+ mb.secondary?.used_percent != null
293
+ ? clampPercent(mb.secondary.used_percent)
294
+ : null;
210
295
  xVal = `${xF != null ? colorByProvider(xF, `${xF}`, codexWhite) : dim("--")}${dim("/")}${xW != null ? colorByProvider(xW, `${xW}`, codexWhite) : dim("--")}`;
211
296
  }
212
297
  }
@@ -215,7 +300,9 @@ export function getMicroLine(contextView, claudeUsage, codexBuckets, geminiSessi
215
300
  let gVal;
216
301
  if (geminiBucket) {
217
302
  const gl = deriveGeminiLimits(geminiBucket);
218
- const gU = gl ? gl.usedPct : clampPercent((1 - (geminiBucket.remainingFraction ?? 1)) * 100);
303
+ const gU = gl
304
+ ? gl.usedPct
305
+ : clampPercent((1 - (geminiBucket.remainingFraction ?? 1)) * 100);
219
306
  gVal = colorByProvider(gU, `${gU}`, geminiBlue);
220
307
  } else if ((geminiSession?.total || 0) > 0) {
221
308
  gVal = geminiBlue("\u221E");
@@ -227,7 +314,8 @@ export function getMicroLine(contextView, claudeUsage, codexBuckets, geminiSessi
227
314
  const sv = formatSvPct(combinedSvPct || 0).trim();
228
315
 
229
316
  const cols = getTerminalColumns() || 120;
230
- const line = `${bold(claudeOrange("c"))}${dim(":")}${cVal} ` +
317
+ const line =
318
+ `${bold(claudeOrange("c"))}${dim(":")}${cVal} ` +
231
319
  `${bold(codexWhite("x"))}${dim(":")}${xVal} ` +
232
320
  `${bold(geminiBlue("g"))}${dim(":")}${gVal} ` +
233
321
  `${dim("sv:")}${sv} ` +
@@ -238,7 +326,12 @@ export function getMicroLine(contextView, claudeUsage, codexBuckets, geminiSessi
238
326
  // ============================================================================
239
327
  // Claude 행 렌더러
240
328
  // ============================================================================
241
- export function getClaudeRows(currentTier, contextView, claudeUsage, combinedSvPct) {
329
+ export function getClaudeRows(
330
+ currentTier,
331
+ contextView,
332
+ claudeUsage,
333
+ combinedSvPct,
334
+ ) {
242
335
  const ctxView = contextView || buildContextUsageView({}, null);
243
336
  const prefix = `${bold(claudeOrange("c"))}:`;
244
337
  const staleMarker = claudeUsage?.stale ? ` ${dim("[stale]")}` : "";
@@ -259,16 +352,42 @@ export function getClaudeRows(currentTier, contextView, claudeUsage, combinedSvP
259
352
 
260
353
  const hasData = claudeUsage != null;
261
354
 
262
- const fStr = hasData && fiveHourPercent != null ? colorByProvider(fiveHourPercent, formatPercentCell(fiveHourPercent), claudeOrange) : dim(formatPlaceholderPercentCell());
263
- const wStr = hasData && weeklyPercent != null ? colorByProvider(weeklyPercent, formatPercentCell(weeklyPercent), claudeOrange) : dim(formatPlaceholderPercentCell());
264
- const fBar = hasData && fiveHourPercent != null ? tierBar(currentTier, fiveHourPercent, CLAUDE_ORANGE) : tierDimBar(currentTier);
265
- const wBar = hasData && weeklyPercent != null ? tierBar(currentTier, weeklyPercent, CLAUDE_ORANGE) : tierDimBar(currentTier);
355
+ const fStr =
356
+ hasData && fiveHourPercent != null
357
+ ? colorByProvider(
358
+ fiveHourPercent,
359
+ formatPercentCell(fiveHourPercent),
360
+ claudeOrange,
361
+ )
362
+ : dim(formatPlaceholderPercentCell());
363
+ const wStr =
364
+ hasData && weeklyPercent != null
365
+ ? colorByProvider(
366
+ weeklyPercent,
367
+ formatPercentCell(weeklyPercent),
368
+ claudeOrange,
369
+ )
370
+ : dim(formatPlaceholderPercentCell());
371
+ const fBar =
372
+ hasData && fiveHourPercent != null
373
+ ? tierBar(currentTier, fiveHourPercent, CLAUDE_ORANGE)
374
+ : tierDimBar(currentTier);
375
+ const wBar =
376
+ hasData && weeklyPercent != null
377
+ ? tierBar(currentTier, weeklyPercent, CLAUDE_ORANGE)
378
+ : tierDimBar(currentTier);
266
379
  const fTime = formatTimeCell(fiveHourReset);
267
380
  const wTime = formatTimeCellDH(weeklyReset);
268
381
 
269
382
  if (currentTier === "nano" || currentTier === "micro") {
270
- const fShort = hasData && fiveHourPercent != null ? colorByProvider(fiveHourPercent, `${fiveHourPercent}%`, claudeOrange) : dim("--");
271
- const wShort = hasData && weeklyPercent != null ? colorByProvider(weeklyPercent, `${weeklyPercent}%`, claudeOrange) : dim("--");
383
+ const fShort =
384
+ hasData && fiveHourPercent != null
385
+ ? colorByProvider(fiveHourPercent, `${fiveHourPercent}%`, claudeOrange)
386
+ : dim("--");
387
+ const wShort =
388
+ hasData && weeklyPercent != null
389
+ ? colorByProvider(weeklyPercent, `${weeklyPercent}%`, claudeOrange)
390
+ : dim("--");
272
391
  const quotaSection = `${fShort}${dim("/")}${wShort}${staleMarker}`;
273
392
  return [{ prefix, left: quotaSection, right: "" }];
274
393
  }
@@ -281,14 +400,18 @@ export function getClaudeRows(currentTier, contextView, claudeUsage, combinedSvP
281
400
 
282
401
  if (currentTier === "compact") {
283
402
  const quotaSection = `${dim("5h:")}${fStr} ${dim(fTime)} ${dim("1w:")}${wStr} ${dim(wTime)}${staleMarker}`;
284
- const warning = ctxView.warningTag ? ` ${dim("|")} ${yellow(ctxView.warningTag)}` : "";
403
+ const warning = ctxView.warningTag
404
+ ? ` ${dim("|")} ${yellow(ctxView.warningTag)}`
405
+ : "";
285
406
  const contextSection = `${svSuffix} ${dim("|")} ${dim("CTX:")}${colorByPercent(ctxView.percent, ctxView.display)}${warning}`;
286
407
  return [{ prefix, left: quotaSection, right: contextSection }];
287
408
  }
288
409
 
289
410
  // full tier (>= 120 cols)
290
411
  const quotaSection = `${dim("5h:")}${fBar}${fStr} ${dim(fTime)} ${dim("1w:")}${wBar}${wStr} ${dim(wTime)}${staleMarker}`;
291
- const warning = ctxView.warningTag ? ` ${dim("|")} ${yellow(ctxView.warningTag)}` : "";
412
+ const warning = ctxView.warningTag
413
+ ? ` ${dim("|")} ${yellow(ctxView.warningTag)}`
414
+ : "";
292
415
  const contextSection = `${svSuffix} ${dim("|")} ${dim("CTX:")}${colorByPercent(ctxView.percent, ctxView.display)}${warning}`;
293
416
  return [{ prefix, left: quotaSection, right: contextSection }];
294
417
  }
@@ -296,53 +419,116 @@ export function getClaudeRows(currentTier, contextView, claudeUsage, combinedSvP
296
419
  // ============================================================================
297
420
  // 계정 라벨 + 범용 프로바이더 행 렌더러
298
421
  // ============================================================================
299
- export function getAccountLabel(provider, accountsConfig, accountsState, codexEmail) {
422
+ export function getAccountLabel(
423
+ provider,
424
+ accountsConfig,
425
+ accountsState,
426
+ codexEmail,
427
+ ) {
300
428
  const providerConfig = accountsConfig?.providers?.[provider] || [];
301
429
  const providerState = accountsState?.providers?.[provider] || {};
302
430
  const lastId = providerState.last_selected_id;
303
- const picked = providerConfig.find((a) => a.id === lastId) || providerConfig[0]
304
- || { id: `${provider}-main`, label: provider };
431
+ const picked = providerConfig.find((a) => a.id === lastId) ||
432
+ providerConfig[0] || { id: `${provider}-main`, label: provider };
305
433
  let label = picked.label || picked.id;
306
434
  if (codexEmail) label = codexEmail;
307
435
  if (label.includes("@")) label = label.split("@")[0];
308
436
  return label;
309
437
  }
310
438
 
311
- export function getProviderRow(currentTier, provider, marker, markerColor, qosProfile, accountsConfig, accountsState, realQuota, codexEmail, savingsMultiplier, modelLabel) {
312
- const accountLabel = fitText(getAccountLabel(provider, accountsConfig, accountsState, codexEmail), ACCOUNT_LABEL_WIDTH);
439
+ export function getProviderRow(
440
+ currentTier,
441
+ provider,
442
+ marker,
443
+ markerColor,
444
+ qosProfile,
445
+ accountsConfig,
446
+ accountsState,
447
+ realQuota,
448
+ codexEmail,
449
+ savingsMultiplier,
450
+ modelLabel,
451
+ ) {
452
+ const accountLabel = fitText(
453
+ getAccountLabel(provider, accountsConfig, accountsState, codexEmail),
454
+ ACCOUNT_LABEL_WIDTH,
455
+ );
313
456
 
314
457
  // 절약 퍼센트 섹션
315
- const svPct = savingsMultiplier != null ? Math.round(savingsMultiplier * 100) : null;
458
+ const svPct =
459
+ savingsMultiplier != null ? Math.round(savingsMultiplier * 100) : null;
316
460
  const svStr = formatSvPct(svPct);
317
- const modelLabelStr = modelLabel ? ` ${markerColor(modelLabel)}` : "";
461
+ const _modelLabelStr = modelLabel ? ` ${markerColor(modelLabel)}` : "";
318
462
 
319
463
  // 프로바이더별 색상 프로필
320
- const provAnsi = provider === "codex" ? CODEX_WHITE : provider === "gemini" ? GEMINI_BLUE : GREEN;
321
- const provFn = provider === "codex" ? codexWhite : provider === "gemini" ? geminiBlue : green;
464
+ const provAnsi =
465
+ provider === "codex"
466
+ ? CODEX_WHITE
467
+ : provider === "gemini"
468
+ ? GEMINI_BLUE
469
+ : GREEN;
470
+ const provFn =
471
+ provider === "codex"
472
+ ? codexWhite
473
+ : provider === "gemini"
474
+ ? geminiBlue
475
+ : green;
322
476
 
323
477
  let quotaSection;
324
- let extraRightSection = "";
478
+ const _extraRightSection = "";
325
479
 
326
480
  if (currentTier === "nano" || currentTier === "micro") {
327
481
  const minPrefix = `${bold(markerColor(`${marker}`))}:`;
328
482
  if (realQuota?.type === "codex") {
329
- const main = realQuota.buckets.codex || realQuota.buckets[Object.keys(realQuota.buckets)[0]];
483
+ const main =
484
+ realQuota.buckets.codex ||
485
+ realQuota.buckets[Object.keys(realQuota.buckets)[0]];
330
486
  if (main) {
331
- const fiveP = main.primary?.used_percent != null ? clampPercent(main.primary.used_percent) : null;
332
- const weekP = main.secondary?.used_percent != null ? clampPercent(main.secondary.used_percent) : null;
333
- const fCellN = fiveP != null ? colorByProvider(fiveP, `${fiveP}%`, provFn) : dim("--%");
334
- const wCellN = weekP != null ? colorByProvider(weekP, `${weekP}%`, provFn) : dim("--%");
335
- return { prefix: minPrefix, left: `${fCellN}${dim("/")}${wCellN}`, right: "" };
487
+ const fiveP =
488
+ main.primary?.used_percent != null
489
+ ? clampPercent(main.primary.used_percent)
490
+ : null;
491
+ const weekP =
492
+ main.secondary?.used_percent != null
493
+ ? clampPercent(main.secondary.used_percent)
494
+ : null;
495
+ const fCellN =
496
+ fiveP != null
497
+ ? colorByProvider(fiveP, `${fiveP}%`, provFn)
498
+ : dim("--%");
499
+ const wCellN =
500
+ weekP != null
501
+ ? colorByProvider(weekP, `${weekP}%`, provFn)
502
+ : dim("--%");
503
+ return {
504
+ prefix: minPrefix,
505
+ left: `${fCellN}${dim("/")}${wCellN}`,
506
+ right: "",
507
+ };
336
508
  }
337
509
  }
338
510
  if (realQuota?.type === "gemini") {
339
511
  const pools = realQuota.pools || {};
340
512
  if (pools.pro || pools.flash) {
341
- const pP = pools.pro ? clampPercent(Math.round((1 - (pools.pro.remainingFraction ?? 1)) * 100)) : null;
342
- const pF = pools.flash ? clampPercent(Math.round((1 - (pools.flash.remainingFraction ?? 1)) * 100)) : null;
343
- const pStr = pP != null ? colorByProvider(pP, `${pP}`, provFn) : dim("--");
344
- const fStr = pF != null ? colorByProvider(pF, `${pF}`, provFn) : dim("--");
345
- return { prefix: minPrefix, left: `${pStr}${dim("/")}${fStr}`, right: "" };
513
+ const pP = pools.pro
514
+ ? clampPercent(
515
+ Math.round((1 - (pools.pro.remainingFraction ?? 1)) * 100),
516
+ )
517
+ : null;
518
+ const pF = pools.flash
519
+ ? clampPercent(
520
+ Math.round((1 - (pools.flash.remainingFraction ?? 1)) * 100),
521
+ )
522
+ : null;
523
+ const pStr =
524
+ pP != null ? colorByProvider(pP, `${pP}`, provFn) : dim("--");
525
+ const fStr =
526
+ pF != null ? colorByProvider(pF, `${pF}`, provFn) : dim("--");
527
+ return {
528
+ prefix: minPrefix,
529
+ left: `${pStr}${dim("/")}${fStr}`,
530
+ right: "",
531
+ };
346
532
  }
347
533
  }
348
534
  return { prefix: minPrefix, left: dim("--/--"), right: "" };
@@ -350,12 +536,26 @@ export function getProviderRow(currentTier, provider, marker, markerColor, qosPr
350
536
 
351
537
  if (currentTier === "minimal") {
352
538
  if (realQuota?.type === "codex") {
353
- const main = realQuota.buckets.codex || realQuota.buckets[Object.keys(realQuota.buckets)[0]];
539
+ const main =
540
+ realQuota.buckets.codex ||
541
+ realQuota.buckets[Object.keys(realQuota.buckets)[0]];
354
542
  if (main) {
355
- const fiveP = main.primary?.used_percent != null ? clampPercent(main.primary.used_percent) : null;
356
- const weekP = main.secondary?.used_percent != null ? clampPercent(main.secondary.used_percent) : null;
357
- const fCell = fiveP != null ? colorByProvider(fiveP, formatPercentCell(fiveP), provFn) : dim(formatPlaceholderPercentCell());
358
- const wCell = weekP != null ? colorByProvider(weekP, formatPercentCell(weekP), provFn) : dim(formatPlaceholderPercentCell());
543
+ const fiveP =
544
+ main.primary?.used_percent != null
545
+ ? clampPercent(main.primary.used_percent)
546
+ : null;
547
+ const weekP =
548
+ main.secondary?.used_percent != null
549
+ ? clampPercent(main.secondary.used_percent)
550
+ : null;
551
+ const fCell =
552
+ fiveP != null
553
+ ? colorByProvider(fiveP, formatPercentCell(fiveP), provFn)
554
+ : dim(formatPlaceholderPercentCell());
555
+ const wCell =
556
+ weekP != null
557
+ ? colorByProvider(weekP, formatPercentCell(weekP), provFn)
558
+ : dim(formatPlaceholderPercentCell());
359
559
  quotaSection = `${dim("5h:")}${fCell} ${dim("1w:")}${wCell}`;
360
560
  }
361
561
  }
@@ -363,9 +563,12 @@ export function getProviderRow(currentTier, provider, marker, markerColor, qosPr
363
563
  const pools = realQuota.pools || {};
364
564
  if (pools.pro || pools.flash) {
365
565
  const slot = (bucket, label) => {
366
- if (!bucket) return `${dim(label + ":")}${dim(formatPlaceholderPercentCell())}`;
566
+ if (!bucket)
567
+ return `${dim(label + ":")}${dim(formatPlaceholderPercentCell())}`;
367
568
  const gl = deriveGeminiLimits(bucket);
368
- const usedP = gl ? gl.usedPct : clampPercent((1 - (bucket.remainingFraction ?? 1)) * 100);
569
+ const usedP = gl
570
+ ? gl.usedPct
571
+ : clampPercent((1 - (bucket.remainingFraction ?? 1)) * 100);
369
572
  return `${dim(label + ":")}${colorByProvider(usedP, formatPercentCell(usedP), provFn)}`;
370
573
  };
371
574
  quotaSection = `${slot(pools.pro, "Pr")} ${slot(pools.flash, "Fl")}`;
@@ -377,19 +580,42 @@ export function getProviderRow(currentTier, provider, marker, markerColor, qosPr
377
580
  quotaSection = `${dim("5h:")}${dim(formatPlaceholderPercentCell())} ${dim("1w:")}${dim(formatPlaceholderPercentCell())}`;
378
581
  }
379
582
  const prefix = `${bold(markerColor(`${marker}`))}:`;
380
- return { prefix, left: quotaSection, right: accountLabel ? markerColor(accountLabel) : "" };
583
+ return {
584
+ prefix,
585
+ left: quotaSection,
586
+ right: accountLabel ? markerColor(accountLabel) : "",
587
+ };
381
588
  }
382
589
 
383
590
  if (currentTier === "compact") {
384
591
  if (realQuota?.type === "codex") {
385
- const main = realQuota.buckets.codex || realQuota.buckets[Object.keys(realQuota.buckets)[0]];
592
+ const main =
593
+ realQuota.buckets.codex ||
594
+ realQuota.buckets[Object.keys(realQuota.buckets)[0]];
386
595
  if (main) {
387
- const fiveP = main.primary?.used_percent != null ? clampPercent(main.primary.used_percent) : null;
388
- const weekP = main.secondary?.used_percent != null ? clampPercent(main.secondary.used_percent) : null;
389
- const fCell = fiveP != null ? colorByProvider(fiveP, formatPercentCell(fiveP), provFn) : dim(formatPlaceholderPercentCell());
390
- const wCell = weekP != null ? colorByProvider(weekP, formatPercentCell(weekP), provFn) : dim(formatPlaceholderPercentCell());
391
- const fiveReset = formatResetRemaining(main.primary?.resets_at, FIVE_HOUR_MS) || "n/a";
392
- const weekReset = formatResetRemainingDayHour(main.secondary?.resets_at, SEVEN_DAY_MS) || "n/a";
596
+ const fiveP =
597
+ main.primary?.used_percent != null
598
+ ? clampPercent(main.primary.used_percent)
599
+ : null;
600
+ const weekP =
601
+ main.secondary?.used_percent != null
602
+ ? clampPercent(main.secondary.used_percent)
603
+ : null;
604
+ const fCell =
605
+ fiveP != null
606
+ ? colorByProvider(fiveP, formatPercentCell(fiveP), provFn)
607
+ : dim(formatPlaceholderPercentCell());
608
+ const wCell =
609
+ weekP != null
610
+ ? colorByProvider(weekP, formatPercentCell(weekP), provFn)
611
+ : dim(formatPlaceholderPercentCell());
612
+ const fiveReset =
613
+ formatResetRemaining(main.primary?.resets_at, FIVE_HOUR_MS) || "n/a";
614
+ const weekReset =
615
+ formatResetRemainingDayHour(
616
+ main.secondary?.resets_at,
617
+ SEVEN_DAY_MS,
618
+ ) || "n/a";
393
619
  quotaSection = `${dim("5h:")}${fCell} ${dim(formatTimeCell(fiveReset))} ${dim("1w:")}${wCell} ${dim(formatTimeCellDH(weekReset))}`;
394
620
  }
395
621
  }
@@ -398,10 +624,14 @@ export function getProviderRow(currentTier, provider, marker, markerColor, qosPr
398
624
  const hasAnyPool = pools.pro || pools.flash;
399
625
  if (hasAnyPool) {
400
626
  const slot = (bucket, label) => {
401
- if (!bucket) return `${dim(label + ":")}${dim(formatPlaceholderPercentCell())} ${dim(formatTimeCell("n/a"))}`;
627
+ if (!bucket)
628
+ return `${dim(label + ":")}${dim(formatPlaceholderPercentCell())} ${dim(formatTimeCell("n/a"))}`;
402
629
  const gl = deriveGeminiLimits(bucket);
403
- const usedP = gl ? gl.usedPct : clampPercent((1 - (bucket.remainingFraction ?? 1)) * 100);
404
- const rstRemaining = formatResetRemaining(bucket.resetTime, ONE_DAY_MS) || "n/a";
630
+ const usedP = gl
631
+ ? gl.usedPct
632
+ : clampPercent((1 - (bucket.remainingFraction ?? 1)) * 100);
633
+ const rstRemaining =
634
+ formatResetRemaining(bucket.resetTime, ONE_DAY_MS) || "n/a";
405
635
  return `${dim(label + ":")}${colorByProvider(usedP, formatPercentCell(usedP), provFn)} ${dim(formatTimeCell(rstRemaining))}`;
406
636
  };
407
637
  quotaSection = `${slot(pools.pro, "Pr")} ${slot(pools.flash, "Fl")}`;
@@ -413,23 +643,52 @@ export function getProviderRow(currentTier, provider, marker, markerColor, qosPr
413
643
  quotaSection = `${dim("5h:")}${dim(formatPlaceholderPercentCell())} ${dim(formatTimeCell("n/a"))} ${dim("1w:")}${dim(formatPlaceholderPercentCell())} ${dim(formatTimeCellDH("--d--h"))}`;
414
644
  }
415
645
  const prefix = `${bold(markerColor(`${marker}`))}:`;
416
- const compactRight = [svStr ? `${dim("sv:")}${svStr}` : "", accountLabel ? markerColor(accountLabel) : ""].filter(Boolean).join(" ");
646
+ const compactRight = [
647
+ svStr ? `${dim("sv:")}${svStr}` : "",
648
+ accountLabel ? markerColor(accountLabel) : "",
649
+ ]
650
+ .filter(Boolean)
651
+ .join(" ");
417
652
  return { prefix, left: quotaSection, right: compactRight };
418
653
  }
419
654
 
420
655
  // full tier
421
656
  if (realQuota?.type === "codex") {
422
- const main = realQuota.buckets.codex || realQuota.buckets[Object.keys(realQuota.buckets)[0]];
657
+ const main =
658
+ realQuota.buckets.codex ||
659
+ realQuota.buckets[Object.keys(realQuota.buckets)[0]];
423
660
  if (main) {
424
- const fiveP = main.primary?.used_percent != null ? clampPercent(main.primary.used_percent) : null;
425
- const weekP = main.secondary?.used_percent != null ? clampPercent(main.secondary.used_percent) : null;
426
- const fiveReset = formatResetRemaining(main.primary?.resets_at, FIVE_HOUR_MS) || "n/a";
427
- const weekReset = formatResetRemainingDayHour(main.secondary?.resets_at, SEVEN_DAY_MS) || "n/a";
428
- const fCell = fiveP != null ? colorByProvider(fiveP, formatPercentCell(fiveP), provFn) : dim(formatPlaceholderPercentCell());
429
- const wCell = weekP != null ? colorByProvider(weekP, formatPercentCell(weekP), provFn) : dim(formatPlaceholderPercentCell());
430
- const fBar = fiveP != null ? tierBar(currentTier, fiveP, provAnsi) : tierDimBar(currentTier);
431
- const wBar = weekP != null ? tierBar(currentTier, weekP, provAnsi) : tierDimBar(currentTier);
432
- quotaSection = `${dim("5h:")}${fBar}${fCell} ` +
661
+ const fiveP =
662
+ main.primary?.used_percent != null
663
+ ? clampPercent(main.primary.used_percent)
664
+ : null;
665
+ const weekP =
666
+ main.secondary?.used_percent != null
667
+ ? clampPercent(main.secondary.used_percent)
668
+ : null;
669
+ const fiveReset =
670
+ formatResetRemaining(main.primary?.resets_at, FIVE_HOUR_MS) || "n/a";
671
+ const weekReset =
672
+ formatResetRemainingDayHour(main.secondary?.resets_at, SEVEN_DAY_MS) ||
673
+ "n/a";
674
+ const fCell =
675
+ fiveP != null
676
+ ? colorByProvider(fiveP, formatPercentCell(fiveP), provFn)
677
+ : dim(formatPlaceholderPercentCell());
678
+ const wCell =
679
+ weekP != null
680
+ ? colorByProvider(weekP, formatPercentCell(weekP), provFn)
681
+ : dim(formatPlaceholderPercentCell());
682
+ const fBar =
683
+ fiveP != null
684
+ ? tierBar(currentTier, fiveP, provAnsi)
685
+ : tierDimBar(currentTier);
686
+ const wBar =
687
+ weekP != null
688
+ ? tierBar(currentTier, weekP, provAnsi)
689
+ : tierDimBar(currentTier);
690
+ quotaSection =
691
+ `${dim("5h:")}${fBar}${fCell} ` +
433
692
  `${dim(formatTimeCell(fiveReset))} ` +
434
693
  `${dim("1w:")}${wBar}${wCell} ` +
435
694
  `${dim(formatTimeCellDH(weekReset))}`;
@@ -446,14 +705,18 @@ export function getProviderRow(currentTier, provider, marker, markerColor, qosPr
446
705
  return `${dim(label + ":")}${tierDimBar(currentTier)}${dim(formatPlaceholderPercentCell())} ${dim(formatTimeCell("n/a"))}`;
447
706
  }
448
707
  const gl = deriveGeminiLimits(bucket);
449
- const usedP = gl ? gl.usedPct : clampPercent((1 - (bucket.remainingFraction ?? 1)) * 100);
450
- const rstRemaining = formatResetRemaining(bucket.resetTime, ONE_DAY_MS) || "n/a";
708
+ const usedP = gl
709
+ ? gl.usedPct
710
+ : clampPercent((1 - (bucket.remainingFraction ?? 1)) * 100);
711
+ const rstRemaining =
712
+ formatResetRemaining(bucket.resetTime, ONE_DAY_MS) || "n/a";
451
713
  return `${dim(label + ":")}${tierBar(currentTier, usedP, provAnsi)}${colorByProvider(usedP, formatPercentCell(usedP), provFn)} ${dim(formatTimeCell(rstRemaining))}`;
452
714
  };
453
715
 
454
716
  quotaSection = `${slot(pools.pro, "Pr")} ${slot(pools.flash, "Fl")}`;
455
717
  } else {
456
- quotaSection = `${dim("Pr:")}${tierDimBar(currentTier)}${dim(formatPlaceholderPercentCell())} ${dim(formatTimeCell("n/a"))} ` +
718
+ quotaSection =
719
+ `${dim("Pr:")}${tierDimBar(currentTier)}${dim(formatPlaceholderPercentCell())} ${dim(formatTimeCell("n/a"))} ` +
457
720
  `${dim("Fl:")}${tierDimBar(currentTier)}${dim(formatPlaceholderPercentCell())} ${dim(formatTimeCell("n/a"))}`;
458
721
  }
459
722
  }
@@ -467,7 +730,9 @@ export function getProviderRow(currentTier, provider, marker, markerColor, qosPr
467
730
  const accountSection = `${markerColor(accountLabel)}`;
468
731
  const svSection = svStr ? `${dim("sv:")}${svStr}` : "";
469
732
  const modelLabelSection = modelLabel ? markerColor(modelLabel) : "";
470
- const rightParts = [svSection, accountSection, modelLabelSection].filter(Boolean);
733
+ const rightParts = [svSection, accountSection, modelLabelSection].filter(
734
+ Boolean,
735
+ );
471
736
  return {
472
737
  prefix,
473
738
  left: quotaSection,