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
@@ -2,21 +2,25 @@
2
2
  //
3
3
  // 상태(state.mjs) + 전이(transitions.mjs) 통합 인터페이스
4
4
 
5
- import { writeFileSync, mkdirSync } from 'node:fs';
6
- import { join, resolve } from 'node:path';
7
- import { homedir } from 'node:os';
8
-
9
- import { canTransition, transitionPhase, ralphRestart, TERMINAL } from './transitions.mjs';
5
+ import { mkdirSync, writeFileSync } from "node:fs";
6
+ import { homedir } from "node:os";
7
+ import { join, resolve } from "node:path";
8
+ import { classifyIntent as _classifyIntent } from "../intent.mjs";
9
+ import { runConfidenceCheck } from "./gates/confidence.mjs";
10
+ import { runSelfCheck } from "./gates/selfcheck.mjs";
10
11
  import {
11
12
  ensurePipelineTable,
12
13
  initPipelineState,
13
14
  readPipelineState,
14
- updatePipelineState,
15
15
  removePipelineState,
16
- } from './state.mjs';
17
- import { runConfidenceCheck } from './gates/confidence.mjs';
18
- import { runSelfCheck } from './gates/selfcheck.mjs';
19
- import { classifyIntent as _classifyIntent } from '../intent.mjs';
16
+ updatePipelineState,
17
+ } from "./state.mjs";
18
+ import {
19
+ canTransition,
20
+ ralphRestart,
21
+ TERMINAL,
22
+ transitionPhase,
23
+ } from "./transitions.mjs";
20
24
  // deslop gate: 호출자가 scanDirectory/detectSlop 결과를 전달
21
25
 
22
26
  /**
@@ -127,12 +131,12 @@ export function createPipeline(db, teamName, opts = {}) {
127
131
  * @returns {string} 절대 경로
128
132
  */
129
133
  writePlanFile(content) {
130
- const safeName = teamName.replace(/[<>:"/\\|?*\x00-\x1f]/g, '_');
131
- const planDir = resolve(process.cwd(), '.tfx', 'plans');
134
+ const safeName = teamName.replace(/[<>:"/\\|?*\x00-\x1f]/g, "_");
135
+ const planDir = resolve(process.cwd(), ".tfx", "plans");
132
136
  mkdirSync(planDir, { recursive: true });
133
137
  const planPath = join(planDir, `${safeName}-plan.md`);
134
- writeFileSync(planPath, content, 'utf8');
135
- this.setArtifact('plan_path', planPath);
138
+ writeFileSync(planPath, content, "utf8");
139
+ this.setArtifact("plan_path", planPath);
136
140
  return planPath;
137
141
  },
138
142
 
@@ -170,20 +174,23 @@ export function createPipeline(db, teamName, opts = {}) {
170
174
  const current = readPipelineState(db, teamName);
171
175
  if (!current) return { ok: false, error: `파이프라인 없음: ${teamName}` };
172
176
 
173
- if (current.phase !== 'confidence') {
174
- return { ok: false, error: `confidence gate는 confidence 단계에서만 실행 가능 (현재: ${current.phase})` };
177
+ if (current.phase !== "confidence") {
178
+ return {
179
+ ok: false,
180
+ error: `confidence gate는 confidence 단계에서만 실행 가능 (현재: ${current.phase})`,
181
+ };
175
182
  }
176
183
 
177
184
  const gate = runConfidenceCheck(planArtifact, context);
178
- this.setArtifact('confidence_result', gate);
185
+ this.setArtifact("confidence_result", gate);
179
186
 
180
- if (gate.decision === 'abort') {
181
- const result = this.advance('failed');
187
+ if (gate.decision === "abort") {
188
+ const result = this.advance("failed");
182
189
  return { ok: true, gate, state: result.state };
183
190
  }
184
191
 
185
192
  // proceed 또는 alternative → exec로 전이
186
- const result = this.advance('exec');
193
+ const result = this.advance("exec");
187
194
  return { ok: result.ok, gate, state: result.state, error: result.error };
188
195
  },
189
196
 
@@ -198,15 +205,21 @@ export function createPipeline(db, teamName, opts = {}) {
198
205
  const current = readPipelineState(db, teamName);
199
206
  if (!current) return { ok: false, error: `파이프라인 없음: ${teamName}` };
200
207
 
201
- if (current.phase !== 'deslop') {
202
- return { ok: false, error: `deslop gate는 deslop 단계에서만 실행 가능 (현재: ${current.phase})` };
208
+ if (current.phase !== "deslop") {
209
+ return {
210
+ ok: false,
211
+ error: `deslop gate는 deslop 단계에서만 실행 가능 (현재: ${current.phase})`,
212
+ };
203
213
  }
204
214
 
205
- const gate = deslopResult || { files: [], summary: { total: 0, clean: 0 } };
206
- this.setArtifact('deslop_result', gate);
215
+ const gate = deslopResult || {
216
+ files: [],
217
+ summary: { total: 0, clean: 0 },
218
+ };
219
+ this.setArtifact("deslop_result", gate);
207
220
 
208
221
  // deslop은 항상 verify로 전이 (정보 제공 게이트, 차단 없음)
209
- const result = this.advance('verify');
222
+ const result = this.advance("verify");
210
223
  return { ok: result.ok, gate, state: result.state, error: result.error };
211
224
  },
212
225
 
@@ -222,20 +235,28 @@ export function createPipeline(db, teamName, opts = {}) {
222
235
  const current = readPipelineState(db, teamName);
223
236
  if (!current) return { ok: false, error: `파이프라인 없음: ${teamName}` };
224
237
 
225
- if (current.phase !== 'selfcheck') {
226
- return { ok: false, error: `selfcheck gate는 selfcheck 단계에서만 실행 가능 (현재: ${current.phase})` };
238
+ if (current.phase !== "selfcheck") {
239
+ return {
240
+ ok: false,
241
+ error: `selfcheck gate는 selfcheck 단계에서만 실행 가능 (현재: ${current.phase})`,
242
+ };
227
243
  }
228
244
 
229
245
  const gate = runSelfCheck(execResult, verifyResult, requirements);
230
- this.setArtifact('selfcheck_result', gate);
246
+ this.setArtifact("selfcheck_result", gate);
231
247
 
232
248
  if (gate.passed) {
233
- const result = this.advance('complete');
234
- return { ok: result.ok, gate, state: result.state, error: result.error };
249
+ const result = this.advance("complete");
250
+ return {
251
+ ok: result.ok,
252
+ gate,
253
+ state: result.state,
254
+ error: result.error,
255
+ };
235
256
  }
236
257
 
237
258
  // Red Flag 탐지 또는 필수 질문 실패 → fix
238
- const result = this.advance('fix');
259
+ const result = this.advance("fix");
239
260
  return { ok: result.ok, gate, state: result.state, error: result.error };
240
261
  },
241
262
  };
@@ -248,7 +269,7 @@ let _tokenSnapshotMod = null;
248
269
  async function loadTokenSnapshot() {
249
270
  if (_tokenSnapshotMod) return _tokenSnapshotMod;
250
271
  try {
251
- _tokenSnapshotMod = await import('../../scripts/token-snapshot.mjs');
272
+ _tokenSnapshotMod = await import("../../scripts/token-snapshot.mjs");
252
273
  } catch {
253
274
  _tokenSnapshotMod = null;
254
275
  }
@@ -266,7 +287,9 @@ export async function benchmarkStart(label) {
266
287
  try {
267
288
  const snapshot = mod.takeSnapshot(label);
268
289
  return { label, snapshot };
269
- } catch { return null; }
290
+ } catch {
291
+ return null;
292
+ }
270
293
  }
271
294
 
272
295
  /**
@@ -286,14 +309,22 @@ export async function benchmarkEnd(preLabel, postLabel, options = {}) {
286
309
  const diff = mod.computeDiff(preLabel, postLabel, options);
287
310
 
288
311
  // 추가로 타임스탬프 기반 사본 저장
289
- const diffsDir = join(homedir(), '.omc', 'state', 'cx-auto-tokens', 'diffs');
312
+ const diffsDir = join(
313
+ homedir(),
314
+ ".omc",
315
+ "state",
316
+ "cx-auto-tokens",
317
+ "diffs",
318
+ );
290
319
  mkdirSync(diffsDir, { recursive: true });
291
- const ts = new Date().toISOString().replace(/[:.]/g, '-');
320
+ const ts = new Date().toISOString().replace(/[:.]/g, "-");
292
321
  const outPath = join(diffsDir, `${ts}.json`);
293
322
  writeFileSync(outPath, JSON.stringify(diff, null, 2));
294
323
 
295
324
  return diff;
296
- } catch { return null; }
325
+ } catch {
326
+ return null;
327
+ }
297
328
  }
298
329
 
299
330
  /**
@@ -310,9 +341,13 @@ export function triageWithIntent(prompt, threshold = 0.8) {
310
341
  return { skip: false, routing: null, classification };
311
342
  }
312
343
 
313
- export { ensurePipelineTable } from './state.mjs';
314
- export { PHASES, TERMINAL, ALLOWED, canTransition } from './transitions.mjs';
315
- export { CRITERIA, runConfidenceCheck } from './gates/confidence.mjs';
316
- export { RED_FLAGS, QUESTIONS, runSelfCheck } from './gates/selfcheck.mjs';
317
- export { detectSlop, autoFixSlop, scanDirectory } from '../quality/deslop.mjs';
318
- export { quickClassify, classifyIntent, INTENT_CATEGORIES } from '../intent.mjs';
344
+ export {
345
+ classifyIntent,
346
+ INTENT_CATEGORIES,
347
+ quickClassify,
348
+ } from "../intent.mjs";
349
+ export { autoFixSlop, detectSlop, scanDirectory } from "../quality/deslop.mjs";
350
+ export { CRITERIA, runConfidenceCheck } from "./gates/confidence.mjs";
351
+ export { QUESTIONS, RED_FLAGS, runSelfCheck } from "./gates/selfcheck.mjs";
352
+ export { ensurePipelineTable } from "./state.mjs";
353
+ export { ALLOWED, canTransition, PHASES, TERMINAL } from "./transitions.mjs";
@@ -3,9 +3,9 @@
3
3
  // store.mjs의 기존 SQLite 연결(db)을 활용한다.
4
4
  // pipeline_state 테이블은 schema.sql에 정의.
5
5
 
6
- import { join } from 'node:path';
6
+ import { join } from "node:path";
7
7
 
8
- import { TFX_STATE_DIR, ensureTfxDirs } from '../paths.mjs';
8
+ import { ensureTfxDirs, TFX_STATE_DIR } from "../paths.mjs";
9
9
 
10
10
  /**
11
11
  * 파이프라인 상태 DB 경로를 계산한다.
@@ -13,7 +13,7 @@ import { TFX_STATE_DIR, ensureTfxDirs } from '../paths.mjs';
13
13
  * @returns {string}
14
14
  */
15
15
  export function getPipelineStateDbPath(baseDir) {
16
- return join(baseDir, TFX_STATE_DIR, 'state.db');
16
+ return join(baseDir, TFX_STATE_DIR, "state.db");
17
17
  }
18
18
 
19
19
  /**
@@ -54,7 +54,7 @@ function getStatements(db) {
54
54
  if (s) return s;
55
55
 
56
56
  s = {
57
- get: db.prepare('SELECT * FROM pipeline_state WHERE team_name = ?'),
57
+ get: db.prepare("SELECT * FROM pipeline_state WHERE team_name = ?"),
58
58
  insert: db.prepare(`
59
59
  INSERT INTO pipeline_state (team_name, phase, fix_attempt, fix_max, ralph_iteration, ralph_max, artifacts, phase_history, created_at, updated_at)
60
60
  VALUES (@team_name, @phase, @fix_attempt, @fix_max, @ralph_iteration, @ralph_max, @artifacts, @phase_history, @created_at, @updated_at)
@@ -71,8 +71,8 @@ function getStatements(db) {
71
71
  updated_at = @updated_at
72
72
  WHERE team_name = @team_name
73
73
  `),
74
- remove: db.prepare('DELETE FROM pipeline_state WHERE team_name = ?'),
75
- list: db.prepare('SELECT * FROM pipeline_state ORDER BY updated_at DESC'),
74
+ remove: db.prepare("DELETE FROM pipeline_state WHERE team_name = ?"),
75
+ list: db.prepare("SELECT * FROM pipeline_state ORDER BY updated_at DESC"),
76
76
  };
77
77
  STATEMENTS.set(db, s);
78
78
  return s;
@@ -82,15 +82,15 @@ function parseRow(row) {
82
82
  if (!row) return null;
83
83
  return {
84
84
  ...row,
85
- artifacts: JSON.parse(row.artifacts || '{}'),
86
- phase_history: JSON.parse(row.phase_history || '[]'),
85
+ artifacts: JSON.parse(row.artifacts || "{}"),
86
+ phase_history: JSON.parse(row.phase_history || "[]"),
87
87
  };
88
88
  }
89
89
 
90
90
  function serializeState(state) {
91
91
  return {
92
92
  team_name: state.team_name,
93
- phase: state.phase || 'plan',
93
+ phase: state.phase || "plan",
94
94
  fix_attempt: state.fix_attempt ?? 0,
95
95
  fix_max: state.fix_max ?? 3,
96
96
  ralph_iteration: state.ralph_iteration ?? 0,
@@ -115,7 +115,7 @@ export function initPipelineState(db, teamName, opts = {}) {
115
115
  const now = Date.now();
116
116
  const state = {
117
117
  team_name: teamName,
118
- phase: 'plan',
118
+ phase: "plan",
119
119
  fix_attempt: 0,
120
120
  fix_max: opts.fix_max ?? 3,
121
121
  ralph_iteration: 0,
@@ -5,23 +5,31 @@
5
5
  // complete, failed = 터미널 상태
6
6
 
7
7
  export const PHASES = [
8
- 'plan', 'prd', 'confidence', 'exec', 'deslop', 'verify', 'selfcheck',
9
- 'fix', 'complete', 'failed',
8
+ "plan",
9
+ "prd",
10
+ "confidence",
11
+ "exec",
12
+ "deslop",
13
+ "verify",
14
+ "selfcheck",
15
+ "fix",
16
+ "complete",
17
+ "failed",
10
18
  ];
11
19
 
12
- export const TERMINAL = new Set(['complete', 'failed']);
20
+ export const TERMINAL = new Set(["complete", "failed"]);
13
21
 
14
22
  export const ALLOWED = {
15
- 'plan': ['prd'],
16
- 'prd': ['confidence'],
17
- 'confidence': ['exec', 'failed'],
18
- 'exec': ['deslop'],
19
- 'deslop': ['verify'],
20
- 'verify': ['selfcheck', 'fix', 'failed'],
21
- 'selfcheck': ['complete', 'fix'],
22
- 'fix': ['exec', 'verify', 'complete', 'failed'],
23
- 'complete': [],
24
- 'failed': [],
23
+ plan: ["prd"],
24
+ prd: ["confidence"],
25
+ confidence: ["exec", "failed"],
26
+ exec: ["deslop"],
27
+ deslop: ["verify"],
28
+ verify: ["selfcheck", "fix", "failed"],
29
+ selfcheck: ["complete", "fix"],
30
+ fix: ["exec", "verify", "complete", "failed"],
31
+ complete: [],
32
+ failed: [],
25
33
  };
26
34
 
27
35
  /**
@@ -48,14 +56,14 @@ export function transitionPhase(state, nextPhase) {
48
56
  if (!canTransition(current, nextPhase)) {
49
57
  return {
50
58
  ok: false,
51
- error: `전이 불가: ${current} → ${nextPhase}. 허용: [${(ALLOWED[current] || []).join(', ')}]`,
59
+ error: `전이 불가: ${current} → ${nextPhase}. 허용: [${(ALLOWED[current] || []).join(", ")}]`,
52
60
  };
53
61
  }
54
62
 
55
63
  const next = { ...state, phase: nextPhase, updated_at: Date.now() };
56
64
 
57
65
  // fix 단계 진입 시 attempt 증가 + 바운딩
58
- if (nextPhase === 'fix') {
66
+ if (nextPhase === "fix") {
59
67
  next.fix_attempt = (state.fix_attempt || 0) + 1;
60
68
  if (next.fix_attempt > (state.fix_max || 3)) {
61
69
  return {
@@ -66,22 +74,24 @@ export function transitionPhase(state, nextPhase) {
66
74
  }
67
75
 
68
76
  // fix → exec 재진입 시 (fix 후 재실행)
69
- if (current === 'fix' && nextPhase === 'exec') {
77
+ if (current === "fix" && nextPhase === "exec") {
70
78
  // fix_attempt 유지 (이미 fix 진입 시 증가됨)
71
79
  }
72
80
 
73
81
  // verify → fix → ... → verify 반복 후 fix_max 초과 시 ralph loop
74
- if (nextPhase === 'failed' && current === 'fix') {
82
+ if (nextPhase === "failed" && current === "fix") {
75
83
  // ralph loop 반복 증가
76
84
  next.ralph_iteration = (state.ralph_iteration || 0) + 1;
77
85
  if (next.ralph_iteration > (state.ralph_max || 10)) {
78
86
  // 최종 실패 — ralph loop도 초과
79
- next.phase = 'failed';
87
+ next.phase = "failed";
80
88
  }
81
89
  }
82
90
 
83
91
  // phase_history 기록
84
- const history = Array.isArray(state.phase_history) ? [...state.phase_history] : [];
92
+ const history = Array.isArray(state.phase_history)
93
+ ? [...state.phase_history]
94
+ : [];
85
95
  history.push({ from: current, to: nextPhase, at: Date.now() });
86
96
  next.phase_history = history;
87
97
 
@@ -96,7 +106,7 @@ export function transitionPhase(state, nextPhase) {
96
106
  */
97
107
  export function ralphRestart(state) {
98
108
  if (TERMINAL.has(state.phase)) {
99
- return { ok: false, error: '터미널 상태에서 재시작 불가' };
109
+ return { ok: false, error: "터미널 상태에서 재시작 불가" };
100
110
  }
101
111
 
102
112
  const iteration = (state.ralph_iteration || 0) + 1;
@@ -107,14 +117,21 @@ export function ralphRestart(state) {
107
117
  };
108
118
  }
109
119
 
110
- const history = Array.isArray(state.phase_history) ? [...state.phase_history] : [];
111
- history.push({ from: state.phase, to: 'plan', at: Date.now(), ralph_restart: true });
120
+ const history = Array.isArray(state.phase_history)
121
+ ? [...state.phase_history]
122
+ : [];
123
+ history.push({
124
+ from: state.phase,
125
+ to: "plan",
126
+ at: Date.now(),
127
+ ralph_restart: true,
128
+ });
112
129
 
113
130
  return {
114
131
  ok: true,
115
132
  state: {
116
133
  ...state,
117
- phase: 'plan',
134
+ phase: "plan",
118
135
  fix_attempt: 0,
119
136
  ralph_iteration: iteration,
120
137
  phase_history: history,
package/hub/platform.mjs CHANGED
@@ -1,45 +1,45 @@
1
- import os from 'node:os';
2
- import path from 'node:path';
3
- import { execFile, execFileSync, execSync } from 'node:child_process';
4
-
5
- export const IS_WINDOWS = process.platform === 'win32';
6
- export const IS_MAC = process.platform === 'darwin';
7
- export const IS_LINUX = process.platform === 'linux';
8
- export const TEMP_DIR = IS_WINDOWS ? os.tmpdir() : '/tmp';
1
+ import { execFile, execFileSync, execSync } from "node:child_process";
2
+ import os from "node:os";
3
+ import path from "node:path";
4
+
5
+ export const IS_WINDOWS = process.platform === "win32";
6
+ export const IS_MAC = process.platform === "darwin";
7
+ export const IS_LINUX = process.platform === "linux";
8
+ export const TEMP_DIR = IS_WINDOWS ? os.tmpdir() : "/tmp";
9
9
  export const PATH_SEP = path.sep;
10
10
 
11
11
  function getPathApi(platform) {
12
- return platform === 'win32' ? path.win32 : path.posix;
12
+ return platform === "win32" ? path.win32 : path.posix;
13
13
  }
14
14
 
15
15
  function coercePathInput(value, platform) {
16
- const text = String(value ?? '');
17
- if (platform === 'win32') {
18
- return text.replaceAll('/', '\\');
16
+ const text = String(value ?? "");
17
+ if (platform === "win32") {
18
+ return text.replaceAll("/", "\\");
19
19
  }
20
- return text.replaceAll('\\', '/');
20
+ return text.replaceAll("\\", "/");
21
21
  }
22
22
 
23
23
  function sanitizePipeSegment(value) {
24
- return String(value ?? '')
24
+ return String(value ?? "")
25
25
  .trim()
26
- .replace(/[<>:"/\\|?*\u0000-\u001f]+/gu, '-')
27
- .replace(/-+/g, '-')
28
- .replace(/^-|-$/g, '');
26
+ .replace(/[<>:"/\\|?*\u0000-\u001f]+/gu, "-")
27
+ .replace(/-+/g, "-")
28
+ .replace(/^-|-$/g, "");
29
29
  }
30
30
 
31
31
  function buildWhichCommandSpec(name, options = {}) {
32
- const commandName = String(name ?? '').trim();
32
+ const commandName = String(name ?? "").trim();
33
33
  if (!commandName) return null;
34
34
 
35
35
  const platform = options.platform || process.platform;
36
36
  return {
37
- lookupCommand: platform === 'win32' ? 'where' : 'which',
37
+ lookupCommand: platform === "win32" ? "where" : "which",
38
38
  args: [commandName],
39
39
  execOptions: {
40
- encoding: 'utf8',
40
+ encoding: "utf8",
41
41
  timeout: options.timeout ?? 5000,
42
- stdio: ['ignore', 'pipe', 'ignore'],
42
+ stdio: ["ignore", "pipe", "ignore"],
43
43
  windowsHide: true,
44
44
  env: options.env || process.env,
45
45
  cwd: options.cwd,
@@ -48,10 +48,12 @@ function buildWhichCommandSpec(name, options = {}) {
48
48
  }
49
49
 
50
50
  function parseWhichCommandOutput(output) {
51
- return String(output)
52
- .split(/\r?\n/u)
53
- .map((line) => line.trim())
54
- .find(Boolean) || null;
51
+ return (
52
+ String(output)
53
+ .split(/\r?\n/u)
54
+ .map((line) => line.trim())
55
+ .find(Boolean) || null
56
+ );
55
57
  }
56
58
 
57
59
  function execFileAsync(command, args, options, execFileFn = execFile) {
@@ -69,7 +71,7 @@ function execFileAsync(command, args, options, execFileFn = execFile) {
69
71
  /**
70
72
  * 경로를 플랫폼에 맞게 정규화합니다.
71
73
  * Windows 환경에서는 역슬래시(\)를 슬래시(/)로 변환하여 반환합니다.
72
- *
74
+ *
73
75
  * @param {string} value - 정규화할 경로 문자열
74
76
  * @param {object} [options] - 옵션
75
77
  * @param {string} [options.platform] - 대상 플랫폼 (기본값: process.platform)
@@ -80,8 +82,8 @@ export function normalizePath(value, options = {}) {
80
82
  const pathApi = getPathApi(platform);
81
83
  const normalized = pathApi.normalize(coercePathInput(value, platform));
82
84
 
83
- if (platform === 'win32') {
84
- return normalized.replaceAll('\\', '/');
85
+ if (platform === "win32") {
86
+ return normalized.replaceAll("\\", "/");
85
87
  }
86
88
  return normalized;
87
89
  }
@@ -89,7 +91,7 @@ export function normalizePath(value, options = {}) {
89
91
  /**
90
92
  * 시스템에서 실행 가능한 명령의 절대 경로를 찾습니다.
91
93
  * Windows에서는 'where', Unix 계열에서는 'which' 명령을 사용합니다.
92
- *
94
+ *
93
95
  * @param {string} name - 찾을 명령어 이름
94
96
  * @param {object} [options] - 옵션
95
97
  * @param {string} [options.platform] - 대상 플랫폼
@@ -103,7 +105,11 @@ export function whichCommand(name, options = {}) {
103
105
  if (!spec) return null;
104
106
 
105
107
  try {
106
- const output = execFileSync(spec.lookupCommand, spec.args, spec.execOptions);
108
+ const output = execFileSync(
109
+ spec.lookupCommand,
110
+ spec.args,
111
+ spec.execOptions,
112
+ );
107
113
  return parseWhichCommandOutput(output);
108
114
  } catch {
109
115
  return null;
@@ -130,7 +136,7 @@ export async function whichCommandAsync(name, options = {}) {
130
136
  /**
131
137
  * 프로세스를 종료합니다.
132
138
  * Windows에서는 트리 구조 종료(/T) 및 강제 종료(/F)를 지원합니다.
133
- *
139
+ *
134
140
  * @param {number|string} pid - 종료할 프로세스 ID
135
141
  * @param {object} [options] - 옵션
136
142
  * @param {string} [options.platform] - 대상 플랫폼
@@ -145,23 +151,23 @@ export function killProcess(pid, options = {}) {
145
151
  if (!Number.isInteger(numericPid) || numericPid <= 0) return false;
146
152
 
147
153
  const platform = options.platform || process.platform;
148
- const signal = options.signal || 'SIGTERM';
154
+ const signal = options.signal || "SIGTERM";
149
155
  const tree = options.tree === true;
150
- const force = options.force === true || signal === 'SIGKILL';
156
+ const force = options.force === true || signal === "SIGKILL";
151
157
 
152
158
  try {
153
- if (platform === 'win32' && (tree || force)) {
159
+ if (platform === "win32" && (tree || force)) {
154
160
  const command = [
155
- 'taskkill',
156
- '/PID',
161
+ "taskkill",
162
+ "/PID",
157
163
  String(numericPid),
158
- tree ? '/T' : '',
159
- force ? '/F' : '',
164
+ tree ? "/T" : "",
165
+ force ? "/F" : "",
160
166
  ]
161
167
  .filter(Boolean)
162
- .join(' ');
168
+ .join(" ");
163
169
  execSync(command, {
164
- stdio: 'ignore',
170
+ stdio: "ignore",
165
171
  timeout: options.timeout ?? 5000,
166
172
  windowsHide: true,
167
173
  });
@@ -178,7 +184,7 @@ export function killProcess(pid, options = {}) {
178
184
  /**
179
185
  * 플랫폼별 IPC 파이프 또는 소켓 경로를 생성합니다.
180
186
  * Windows에서는 네임드 파이프 경로를, Unix 계열에서는 도메인 소켓 파일 경로를 반환합니다.
181
- *
187
+ *
182
188
  * @param {string} name - 파이프/소켓 기본 이름
183
189
  * @param {number|string} [pid=process.pid] - 프로세스 ID (식별자 추가용)
184
190
  * @param {object} [options] - 옵션
@@ -188,10 +194,10 @@ export function killProcess(pid, options = {}) {
188
194
  */
189
195
  export function pipePath(name, pid = process.pid, options = {}) {
190
196
  const platform = options.platform || process.platform;
191
- const safeName = sanitizePipeSegment(name) || 'triflux';
192
- const suffix = pid == null || pid === '' ? safeName : `${safeName}-${pid}`;
197
+ const safeName = sanitizePipeSegment(name) || "triflux";
198
+ const suffix = pid == null || pid === "" ? safeName : `${safeName}-${pid}`;
193
199
 
194
- if (platform === 'win32') {
200
+ if (platform === "win32") {
195
201
  return `\\\\.\\pipe\\${suffix}`;
196
202
  }
197
203
 
@@ -202,7 +208,7 @@ export function pipePath(name, pid = process.pid, options = {}) {
202
208
  /**
203
209
  * 특정 경로가 대상 디렉토리 내부에 포함되는지 확인합니다.
204
210
  * 대소문자 구분 및 상대 경로 처리를 플랫폼 규격에 맞게 수행합니다.
205
- *
211
+ *
206
212
  * @param {string} resolvedPath - 검사할 절대 경로
207
213
  * @param {string} dir - 기준이 되는 대상 디렉토리 경로
208
214
  * @param {object} [options] - 옵션
@@ -217,9 +223,12 @@ export function isPathWithin(resolvedPath, dir, options = {}) {
217
223
  const left = pathApi.resolve(coercePathInput(resolvedPath, platform));
218
224
  const right = pathApi.resolve(coercePathInput(dir, platform));
219
225
 
220
- const normalizedLeft = platform === 'win32' ? left.toLowerCase() : left;
221
- const normalizedRight = platform === 'win32' ? right.toLowerCase() : right;
226
+ const normalizedLeft = platform === "win32" ? left.toLowerCase() : left;
227
+ const normalizedRight = platform === "win32" ? right.toLowerCase() : right;
222
228
  const relative = pathApi.relative(normalizedRight, normalizedLeft);
223
229
 
224
- return relative === '' || (!relative.startsWith('..') && !pathApi.isAbsolute(relative));
230
+ return (
231
+ relative === "" ||
232
+ (!relative.startsWith("..") && !pathApi.isAbsolute(relative))
233
+ );
225
234
  }