triflux 10.3.4 → 10.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (329) hide show
  1. package/LICENSE +21 -21
  2. package/bin/tfx-doctor-tui.mjs +1 -1
  3. package/bin/tfx-doctor.mjs +6 -1
  4. package/bin/tfx-profile.mjs +1 -1
  5. package/bin/tfx-setup-tui.mjs +1 -1
  6. package/bin/tfx-setup.mjs +6 -1
  7. package/bin/triflux.mjs +2396 -1140
  8. package/hooks/agent-route-guard.mjs +12 -8
  9. package/hooks/cross-review-tracker.mjs +21 -8
  10. package/hooks/error-context.mjs +19 -7
  11. package/hooks/hook-adaptive-collector.mjs +18 -16
  12. package/hooks/hook-manager.mjs +93 -32
  13. package/hooks/hook-orchestrator.mjs +108 -24
  14. package/hooks/hook-registry.json +11 -0
  15. package/hooks/keyword-rules.json +6 -10
  16. package/hooks/lib/resolve-root.mjs +1 -1
  17. package/hooks/mcp-config-watcher.mjs +6 -2
  18. package/hooks/pipeline-stop.mjs +3 -6
  19. package/hooks/safety-guard.mjs +99 -28
  20. package/hooks/session-start-fast.mjs +143 -0
  21. package/hooks/subagent-verifier.mjs +5 -4
  22. package/hub/account-broker.mjs +256 -60
  23. package/hub/adaptive-diagnostic.mjs +75 -48
  24. package/hub/adaptive-inject.mjs +95 -57
  25. package/hub/adaptive-memory.mjs +156 -42
  26. package/hub/adaptive.mjs +60 -31
  27. package/hub/assign-callbacks.mjs +67 -30
  28. package/hub/bridge.mjs +0 -1
  29. package/hub/cli-adapter-base.mjs +200 -48
  30. package/hub/codex-adapter.mjs +76 -96
  31. package/hub/codex-compat.mjs +3 -3
  32. package/hub/codex-preflight.mjs +63 -37
  33. package/hub/delegator/contracts.mjs +19 -23
  34. package/hub/delegator/index.mjs +3 -3
  35. package/hub/delegator/service.mjs +88 -64
  36. package/hub/delegator/tool-definitions.mjs +5 -5
  37. package/hub/fullcycle.mjs +33 -17
  38. package/hub/gemini-adapter.mjs +69 -94
  39. package/hub/hitl.mjs +89 -30
  40. package/hub/intent.mjs +161 -38
  41. package/hub/lib/cache-guard.mjs +43 -17
  42. package/hub/lib/mcp-response-cache.mjs +66 -32
  43. package/hub/lib/memory-store.mjs +285 -111
  44. package/hub/lib/path-utils.mjs +35 -37
  45. package/hub/lib/process-utils.mjs +106 -37
  46. package/hub/lib/spawn-trace.mjs +527 -0
  47. package/hub/lib/ssh-command.mjs +34 -4
  48. package/hub/lib/ssh-retry.mjs +5 -1
  49. package/hub/lib/uuidv7.mjs +4 -3
  50. package/hub/memory-doctor.mjs +266 -106
  51. package/hub/middleware/request-logger.mjs +61 -34
  52. package/hub/paths.mjs +9 -9
  53. package/hub/pipeline/gates/confidence.mjs +34 -15
  54. package/hub/pipeline/gates/consensus.mjs +27 -15
  55. package/hub/pipeline/gates/index.mjs +7 -3
  56. package/hub/pipeline/gates/selfcheck.mjs +57 -19
  57. package/hub/pipeline/index.mjs +77 -42
  58. package/hub/pipeline/state.mjs +10 -10
  59. package/hub/pipeline/transitions.mjs +40 -23
  60. package/hub/platform.mjs +57 -48
  61. package/hub/promote-penalties.mjs +25 -7
  62. package/hub/quality/deslop.mjs +70 -49
  63. package/hub/research.mjs +32 -25
  64. package/hub/router.mjs +240 -107
  65. package/hub/routing/complexity.mjs +132 -29
  66. package/hub/routing/index.mjs +17 -12
  67. package/hub/routing/q-learning.mjs +76 -28
  68. package/hub/server.mjs +4 -4
  69. package/hub/session-fingerprint.mjs +126 -60
  70. package/hub/state.mjs +84 -43
  71. package/hub/store-adapter.mjs +59 -26
  72. package/hub/store.mjs +356 -153
  73. package/hub/team/agent-map.json +22 -7
  74. package/hub/team/ansi.mjs +186 -122
  75. package/hub/team/backend.mjs +28 -10
  76. package/hub/team/cli/commands/attach.mjs +29 -9
  77. package/hub/team/cli/commands/control.mjs +29 -8
  78. package/hub/team/cli/commands/debug.mjs +32 -11
  79. package/hub/team/cli/commands/focus.mjs +38 -11
  80. package/hub/team/cli/commands/interrupt.mjs +18 -6
  81. package/hub/team/cli/commands/kill.mjs +16 -5
  82. package/hub/team/cli/commands/list.mjs +11 -4
  83. package/hub/team/cli/commands/send.mjs +19 -6
  84. package/hub/team/cli/commands/start/index.mjs +154 -31
  85. package/hub/team/cli/commands/start/parse-args.mjs +38 -11
  86. package/hub/team/cli/commands/start/start-headless.mjs +112 -36
  87. package/hub/team/cli/commands/start/start-in-process.mjs +12 -2
  88. package/hub/team/cli/commands/start/start-mux.mjs +70 -21
  89. package/hub/team/cli/commands/start/start-wt.mjs +29 -12
  90. package/hub/team/cli/commands/status.mjs +43 -14
  91. package/hub/team/cli/commands/stop.mjs +11 -4
  92. package/hub/team/cli/commands/task.mjs +8 -3
  93. package/hub/team/cli/commands/tasks.mjs +1 -1
  94. package/hub/team/cli/index.mjs +2 -2
  95. package/hub/team/cli/manifest.mjs +38 -8
  96. package/hub/team/cli/render.mjs +30 -8
  97. package/hub/team/cli/services/attach-fallback.mjs +31 -11
  98. package/hub/team/cli/services/hub-client.mjs +42 -14
  99. package/hub/team/cli/services/member-selector.mjs +11 -4
  100. package/hub/team/cli/services/native-control.mjs +48 -21
  101. package/hub/team/cli/services/runtime-mode.mjs +2 -1
  102. package/hub/team/cli/services/state-store.mjs +25 -8
  103. package/hub/team/cli/services/task-model.mjs +16 -6
  104. package/hub/team/conductor-mesh-bridge.mjs +24 -23
  105. package/hub/team/conductor.mjs +8 -4
  106. package/hub/team/dashboard-anchor.mjs +4 -5
  107. package/hub/team/dashboard-layout.mjs +3 -1
  108. package/hub/team/dashboard-open.mjs +41 -21
  109. package/hub/team/dashboard.mjs +76 -28
  110. package/hub/team/event-log.mjs +18 -10
  111. package/hub/team/handoff.mjs +31 -15
  112. package/hub/team/headless.mjs +2 -1
  113. package/hub/team/health-probe.mjs +69 -54
  114. package/hub/team/launcher-template.mjs +16 -13
  115. package/hub/team/native-supervisor.mjs +65 -21
  116. package/hub/team/native.mjs +74 -35
  117. package/hub/team/nativeProxy.mjs +184 -113
  118. package/hub/team/notify.mjs +119 -76
  119. package/hub/team/orchestrator.mjs +9 -4
  120. package/hub/team/pane.mjs +12 -7
  121. package/hub/team/process-cleanup.mjs +25 -16
  122. package/hub/team/psmux.mjs +491 -201
  123. package/hub/team/remote-probe.mjs +68 -52
  124. package/hub/team/remote-session.mjs +117 -59
  125. package/hub/team/remote-watcher.mjs +61 -33
  126. package/hub/team/routing.mjs +51 -25
  127. package/hub/team/runtime-strategy.mjs +3 -1
  128. package/hub/team/session.mjs +98 -34
  129. package/hub/team/staleState.mjs +72 -30
  130. package/hub/team/swarm-locks.mjs +15 -13
  131. package/hub/team/swarm-planner.mjs +32 -21
  132. package/hub/team/swarm-reconciler.mjs +48 -23
  133. package/hub/team/tui-lite.mjs +266 -68
  134. package/hub/team/tui-remote-adapter.mjs +14 -10
  135. package/hub/team/tui-viewer.mjs +99 -43
  136. package/hub/team/tui.mjs +708 -271
  137. package/hub/team/worktree-lifecycle.mjs +152 -58
  138. package/hub/team/wt-manager.mjs +24 -14
  139. package/hub/token-mode.mjs +71 -71
  140. package/hub/tray.mjs +66 -23
  141. package/hub/workers/claude-worker.mjs +162 -118
  142. package/hub/workers/codex-mcp.mjs +192 -141
  143. package/hub/workers/delegator-mcp.mjs +507 -333
  144. package/hub/workers/factory.mjs +8 -8
  145. package/hub/workers/gemini-worker.mjs +115 -84
  146. package/hub/workers/interface.mjs +6 -1
  147. package/hub/workers/worker-utils.mjs +21 -14
  148. package/hud/colors.mjs +27 -9
  149. package/hud/constants.mjs +162 -26
  150. package/hud/context-monitor.mjs +82 -41
  151. package/hud/hud-qos-status.mjs +129 -49
  152. package/hud/mission-board.mjs +6 -3
  153. package/hud/providers/claude.mjs +226 -115
  154. package/hud/providers/codex.mjs +62 -22
  155. package/hud/providers/gemini.mjs +168 -56
  156. package/hud/renderers.mjs +384 -119
  157. package/hud/terminal.mjs +101 -31
  158. package/hud/utils.mjs +78 -38
  159. package/mesh/index.mjs +11 -5
  160. package/mesh/mesh-budget.mjs +18 -9
  161. package/mesh/mesh-heartbeat.mjs +1 -1
  162. package/mesh/mesh-queue.mjs +3 -5
  163. package/mesh/mesh-router.mjs +5 -4
  164. package/package.json +2 -1
  165. package/scripts/__tests__/gen-skill-docs.test.mjs +36 -7
  166. package/scripts/__tests__/keyword-detector.test.mjs +77 -28
  167. package/scripts/__tests__/mcp-guard-engine.test.mjs +58 -20
  168. package/scripts/__tests__/remote-spawn-transfer.test.mjs +30 -19
  169. package/scripts/__tests__/remote-spawn.test.mjs +10 -4
  170. package/scripts/__tests__/session-start-fast.test.mjs +36 -0
  171. package/scripts/__tests__/skill-template.test.mjs +98 -50
  172. package/scripts/__tests__/smoke.test.mjs +1 -1
  173. package/scripts/__tests__/spawn-trace.test.mjs +102 -0
  174. package/scripts/__tests__/tfx-doctor-diagnose.test.mjs +48 -0
  175. package/scripts/cache-doctor.mjs +11 -4
  176. package/scripts/cache-warmup.mjs +96 -37
  177. package/scripts/claudemd-sync.mjs +27 -17
  178. package/scripts/codex-gateway-preflight.mjs +52 -37
  179. package/scripts/codex-mcp-gateway-sync.mjs +59 -39
  180. package/scripts/completions/tfx.bash +47 -47
  181. package/scripts/completions/tfx.fish +44 -44
  182. package/scripts/completions/tfx.zsh +83 -83
  183. package/scripts/config-audit.mjs +232 -0
  184. package/scripts/convert-to-tmpl.mjs +54 -0
  185. package/scripts/cross-review-gate.mjs +35 -12
  186. package/scripts/cross-review-tracker.mjs +21 -8
  187. package/scripts/demo.mjs +35 -17
  188. package/scripts/doctor-diagnose.mjs +284 -0
  189. package/scripts/gen-skill-docs.mjs +7 -2
  190. package/scripts/gen-skill-manifest.mjs +2 -1
  191. package/scripts/headless-guard.mjs +86 -48
  192. package/scripts/hub-ensure.mjs +45 -26
  193. package/scripts/keyword-detector.mjs +41 -20
  194. package/scripts/keyword-rules-expander.mjs +47 -30
  195. package/scripts/lib/claudemd-scanner.mjs +6 -1
  196. package/scripts/lib/context.mjs +3 -3
  197. package/scripts/lib/cross-review-utils.mjs +6 -3
  198. package/scripts/lib/env-probe.mjs +47 -28
  199. package/scripts/lib/gemini-profiles.mjs +44 -10
  200. package/scripts/lib/handoff.mjs +33 -17
  201. package/scripts/lib/hook-utils.mjs +8 -6
  202. package/scripts/lib/keyword-rules.mjs +43 -19
  203. package/scripts/lib/logger.mjs +24 -24
  204. package/scripts/lib/mcp-filter.mjs +377 -239
  205. package/scripts/lib/mcp-guard-engine.mjs +194 -79
  206. package/scripts/lib/mcp-manifest.mjs +23 -13
  207. package/scripts/lib/mcp-server-catalog.mjs +300 -63
  208. package/scripts/lib/psmux-info.mjs +11 -6
  209. package/scripts/lib/remote-spawn-transfer.mjs +44 -14
  210. package/scripts/lib/skill-template.mjs +30 -7
  211. package/scripts/mcp-check.mjs +58 -39
  212. package/scripts/mcp-gateway-config.mjs +83 -39
  213. package/scripts/mcp-gateway-ensure.mjs +43 -35
  214. package/scripts/mcp-gateway-integration-test.mjs +70 -58
  215. package/scripts/mcp-gateway-start.mjs +126 -60
  216. package/scripts/mcp-gateway-verify.mjs +24 -22
  217. package/scripts/mcp-safety-guard.mjs +44 -11
  218. package/scripts/notion-read.mjs +199 -84
  219. package/scripts/pack.mjs +94 -89
  220. package/scripts/preflight-cache.mjs +27 -10
  221. package/scripts/preinstall.mjs +42 -13
  222. package/scripts/remote-spawn.mjs +309 -94
  223. package/scripts/run.cjs +8 -5
  224. package/scripts/session-spawn-helper.mjs +130 -39
  225. package/scripts/session-stale-cleanup.mjs +123 -0
  226. package/scripts/setup.mjs +941 -492
  227. package/scripts/test-lock.mjs +20 -7
  228. package/scripts/test-tfx-route-no-claude-native.mjs +16 -12
  229. package/scripts/tfx-batch-stats.mjs +32 -11
  230. package/scripts/tfx-gate-activate.mjs +11 -4
  231. package/scripts/tfx-route-post.mjs +87 -20
  232. package/scripts/tfx-route-worker.mjs +57 -51
  233. package/scripts/tfx-route.sh +41 -124
  234. package/scripts/tmp-cleanup.mjs +21 -7
  235. package/scripts/token-snapshot.mjs +204 -85
  236. package/skills/.omc/state/agent-replay-8f0e10a9-9693-4410-96f5-a6b07e8ed995.jsonl +1 -0
  237. package/skills/.omc/state/idle-notif-cooldown.json +3 -0
  238. package/skills/.omc/state/last-tool-error.json +7 -0
  239. package/skills/.omc/state/subagent-tracking.json +7 -0
  240. package/skills/_templates/base.md +1 -6
  241. package/skills/merge-worktree/SKILL.md.tmpl +144 -0
  242. package/skills/shared/telemetry-segment.md +6 -0
  243. package/skills/star-prompt/SKILL.md.tmpl +222 -0
  244. package/skills/tfx-analysis/SKILL.md.tmpl +107 -0
  245. package/skills/tfx-analysis/skill.json +1 -6
  246. package/skills/tfx-auto/SKILL.md +1 -0
  247. package/skills/tfx-auto-codex/SKILL.md.tmpl +106 -0
  248. package/skills/tfx-auto-codex/skill.json +1 -3
  249. package/skills/tfx-autopilot/SKILL.md.tmpl +116 -0
  250. package/skills/tfx-autopilot/skill.json +1 -5
  251. package/skills/tfx-autoresearch/SKILL.md.tmpl +136 -0
  252. package/skills/tfx-autoroute/SKILL.md.tmpl +189 -0
  253. package/skills/tfx-autoroute/skill.json +1 -7
  254. package/skills/tfx-codex/SKILL.md +1 -0
  255. package/skills/tfx-codex/skill.json +1 -3
  256. package/skills/tfx-codex-swarm/SKILL.md.tmpl +16 -0
  257. package/skills/tfx-codex-swarm/evals/evals.json +1 -1
  258. package/skills/tfx-codex-swarm/skill.json +1 -4
  259. package/skills/tfx-codex-swarm-workspace/iteration-1/benchmark.json +54 -12
  260. package/skills/tfx-codex-swarm-workspace/iteration-1/full-swarm-all-prds/with_skill/grading.json +35 -7
  261. package/skills/tfx-codex-swarm-workspace/iteration-1/full-swarm-all-prds/without_skill/grading.json +35 -7
  262. package/skills/tfx-codex-swarm-workspace/iteration-1/implicit-swarm-no-keywords/with_skill/grading.json +25 -5
  263. package/skills/tfx-codex-swarm-workspace/iteration-1/implicit-swarm-no-keywords/without_skill/grading.json +25 -5
  264. package/skills/tfx-codex-swarm-workspace/iteration-1/selective-spawn-with-override/with_skill/grading.json +20 -4
  265. package/skills/tfx-codex-swarm-workspace/iteration-1/selective-spawn-with-override/without_skill/grading.json +16 -4
  266. package/skills/tfx-consensus/SKILL.md.tmpl +146 -0
  267. package/skills/tfx-debate/SKILL.md.tmpl +192 -0
  268. package/skills/tfx-debate/skill.json +1 -7
  269. package/skills/tfx-deep-analysis/SKILL.md.tmpl +228 -0
  270. package/skills/tfx-deep-analysis/skill.json +1 -5
  271. package/skills/tfx-deep-interview/SKILL.md.tmpl +203 -0
  272. package/skills/tfx-deep-plan/SKILL.md.tmpl +282 -0
  273. package/skills/tfx-deep-qa/SKILL.md.tmpl +165 -0
  274. package/skills/tfx-deep-qa/skill.json +1 -6
  275. package/skills/tfx-deep-research/SKILL.md.tmpl +217 -0
  276. package/skills/tfx-deep-review/SKILL.md.tmpl +179 -0
  277. package/skills/tfx-doctor/SKILL.md +21 -0
  278. package/skills/tfx-doctor/SKILL.md.tmpl +172 -0
  279. package/skills/tfx-doctor/skill.json +1 -3
  280. package/skills/tfx-find/SKILL.md +1 -0
  281. package/skills/tfx-forge/SKILL.md.tmpl +187 -0
  282. package/skills/tfx-fullcycle/SKILL.md.tmpl +286 -0
  283. package/skills/tfx-fullcycle/skill.json +1 -6
  284. package/skills/tfx-gemini/SKILL.md.tmpl +91 -0
  285. package/skills/tfx-gemini/skill.json +1 -3
  286. package/skills/tfx-hooks/SKILL.md.tmpl +216 -0
  287. package/skills/tfx-hooks/skill.json +1 -3
  288. package/skills/tfx-hub/SKILL.md.tmpl +212 -0
  289. package/skills/tfx-hub/skill.json +1 -3
  290. package/skills/tfx-index/SKILL.md +1 -0
  291. package/skills/tfx-index/skill.json +1 -6
  292. package/skills/tfx-interview/SKILL.md.tmpl +285 -0
  293. package/skills/tfx-multi/SKILL.md.tmpl +183 -0
  294. package/skills/tfx-multi/skill.json +1 -3
  295. package/skills/tfx-panel/SKILL.md.tmpl +189 -0
  296. package/skills/tfx-panel/skill.json +1 -7
  297. package/skills/tfx-persist/SKILL.md.tmpl +270 -0
  298. package/skills/tfx-persist/skill.json +1 -7
  299. package/skills/tfx-plan/SKILL.md +1 -0
  300. package/skills/tfx-plan/skill.json +1 -6
  301. package/skills/tfx-profile/SKILL.md.tmpl +239 -0
  302. package/skills/tfx-profile/skill.json +1 -3
  303. package/skills/tfx-prune/SKILL.md.tmpl +200 -0
  304. package/skills/tfx-prune/skill.json +1 -7
  305. package/skills/tfx-psmux-rules/SKILL.md.tmpl +326 -0
  306. package/skills/tfx-psmux-rules/skill.json +1 -4
  307. package/skills/tfx-qa/SKILL.md +1 -0
  308. package/skills/tfx-qa/skill.json +1 -6
  309. package/skills/tfx-ralph/SKILL.md.tmpl +28 -0
  310. package/skills/tfx-ralph/skill.json +1 -4
  311. package/skills/tfx-remote-setup/SKILL.md.tmpl +576 -0
  312. package/skills/tfx-remote-setup/skill.json +1 -3
  313. package/skills/tfx-remote-spawn/SKILL.md.tmpl +263 -0
  314. package/skills/tfx-remote-spawn/references/hosts.json +16 -0
  315. package/skills/tfx-remote-spawn/skill.json +1 -4
  316. package/skills/tfx-research/SKILL.md +1 -0
  317. package/skills/tfx-review/SKILL.md +1 -0
  318. package/skills/tfx-review/skill.json +1 -6
  319. package/skills/tfx-setup/SKILL.md.tmpl +504 -0
  320. package/skills/tfx-setup/skill.json +1 -3
  321. package/skills/tfx-swarm/SKILL.md +22 -0
  322. package/skills/tfx-swarm/SKILL.md.tmpl +218 -0
  323. package/tui/codex-profile.mjs +88 -33
  324. package/tui/core.mjs +45 -15
  325. package/tui/doctor.mjs +75 -28
  326. package/tui/gemini-profile.mjs +74 -29
  327. package/tui/monitor-data.mjs +8 -4
  328. package/tui/monitor.mjs +71 -27
  329. package/tui/setup.mjs +133 -42
@@ -1,79 +1,312 @@
1
- export const SEARCH_SERVER_ORDER = Object.freeze(['brave-search', 'tavily', 'exa']);
1
+ export const SEARCH_SERVER_ORDER = Object.freeze([
2
+ "brave-search",
3
+ "tavily",
4
+ "exa",
5
+ ]);
2
6
 
3
7
  export const MCP_SERVER_TOOL_CATALOG = Object.freeze({
4
- context7: Object.freeze(['resolve-library-id', 'query-docs']),
5
- 'brave-search': Object.freeze(['brave_web_search', 'brave_news_search']),
6
- exa: Object.freeze(['web_search_exa', 'get_code_context_exa']),
7
- tavily: Object.freeze(['tavily_search', 'tavily_extract']),
8
+ context7: Object.freeze(["resolve-library-id", "query-docs"]),
9
+ "brave-search": Object.freeze(["brave_web_search", "brave_news_search"]),
10
+ exa: Object.freeze(["web_search_exa", "get_code_context_exa"]),
11
+ tavily: Object.freeze(["tavily_search", "tavily_extract"]),
8
12
  playwright: Object.freeze([
9
- 'browser_navigate',
10
- 'browser_navigate_back',
11
- 'browser_snapshot',
12
- 'browser_take_screenshot',
13
- 'browser_wait_for',
13
+ "browser_navigate",
14
+ "browser_navigate_back",
15
+ "browser_snapshot",
16
+ "browser_take_screenshot",
17
+ "browser_wait_for",
14
18
  ]),
15
- 'sequential-thinking': Object.freeze(['sequentialthinking']),
19
+ "sequential-thinking": Object.freeze(["sequentialthinking"]),
16
20
  });
17
21
 
18
22
  export const MCP_SERVER_DOMAIN_TAGS = Object.freeze({
19
- context7: Object.freeze(['docs', 'reference', 'api', 'sdk', 'library']),
20
- 'brave-search': Object.freeze(['web', 'search', 'news', 'current']),
21
- exa: Object.freeze(['code', 'repository', 'examples', 'search']),
22
- tavily: Object.freeze(['research', 'search', 'news', 'verification', 'current']),
23
- playwright: Object.freeze(['browser', 'ui', 'visual', 'e2e']),
24
- 'sequential-thinking': Object.freeze(['analysis', 'planning', 'reasoning', 'security', 'review']),
23
+ context7: Object.freeze(["docs", "reference", "api", "sdk", "library"]),
24
+ "brave-search": Object.freeze(["web", "search", "news", "current"]),
25
+ exa: Object.freeze(["code", "repository", "examples", "search"]),
26
+ tavily: Object.freeze([
27
+ "research",
28
+ "search",
29
+ "news",
30
+ "verification",
31
+ "current",
32
+ ]),
33
+ playwright: Object.freeze(["browser", "ui", "visual", "e2e"]),
34
+ "sequential-thinking": Object.freeze([
35
+ "analysis",
36
+ "planning",
37
+ "reasoning",
38
+ "security",
39
+ "review",
40
+ ]),
25
41
  });
26
42
 
27
43
  export const DOMAIN_TAG_KEYWORDS = Object.freeze({
28
- docs: Object.freeze(['docs', 'documentation', 'manual', 'guide', '문서', '가이드', '매뉴얼']),
29
- reference: Object.freeze(['reference', 'spec', 'schema', 'official', '레퍼런스', '공식', '스펙', '스키마']),
30
- api: Object.freeze(['api', 'endpoint', 'interface', 'sdk', '호출', '엔드포인트']),
31
- sdk: Object.freeze(['sdk', 'library', 'package', 'framework', '라이브러리', '패키지', '프레임워크']),
32
- library: Object.freeze(['library', 'package', 'framework', 'module', '라이브러리', '패키지', '모듈']),
33
- web: Object.freeze(['web', 'site', 'article', 'forum', 'blog', 'reddit', '웹', '사이트', '기사', '포럼', '블로그']),
34
- search: Object.freeze(['search', 'browse', 'lookup', 'find', '검색', '조회', '탐색', '찾아']),
35
- news: Object.freeze(['latest', 'recent', 'news', 'today', 'release', 'announcement', '최신', '최근', '뉴스', '오늘', '릴리즈', '공지']),
36
- current: Object.freeze(['current', 'status', 'pricing', 'changelog', 'up-to-date', '현재', '상태', '가격', '변경사항']),
37
- research: Object.freeze(['research', 'verify', 'fact-check', 'investigate', '리서치', '검증', '조사']),
38
- verification: Object.freeze(['verify', 'validation', 'fact-check', 'audit', '검증', '확인', '감사']),
39
- code: Object.freeze(['code', 'repo', 'repository', 'source', 'implementation', 'bug', 'fix', 'test', 'snippet', 'cli', '코드', '리포', '저장소', '구현', '버그', '테스트', '예제', '스크립트']),
40
- repository: Object.freeze(['repo', 'repository', 'source', 'git', 'github', '리포', '저장소', '소스']),
41
- examples: Object.freeze(['example', 'examples', 'snippet', 'sample', '예제', '샘플']),
42
- browser: Object.freeze(['browser', 'page', 'dom', 'screenshot', 'render', '브라우저', '페이지', '스크린샷', '렌더']),
43
- ui: Object.freeze(['ui', 'ux', 'layout', 'responsive', 'css', 'html', '디자인', '레이아웃', '반응형']),
44
- visual: Object.freeze(['visual', 'screenshot', 'layout', 'render', 'screen', '화면', '시각', '스크린샷']),
45
- e2e: Object.freeze(['playwright', 'e2e', 'click', 'navigate', 'automation', 'playwright', '클릭', '이동', '자동화']),
46
- analysis: Object.freeze(['analysis', 'analyze', 'audit', 'compare', 'root cause', '분석', '검토', '비교', '원인']),
47
- planning: Object.freeze(['plan', 'planning', 'strategy', 'design', '계획', '전략', '설계']),
48
- reasoning: Object.freeze(['reason', 'reasoning', 'think', 'critique', '추론', '사고', '비평']),
49
- security: Object.freeze(['security', 'risk', 'threat', 'vulnerability', '보안', '위험', '취약점']),
50
- review: Object.freeze(['review', 'reviewer', 'inspect', '리뷰', '검수']),
44
+ docs: Object.freeze([
45
+ "docs",
46
+ "documentation",
47
+ "manual",
48
+ "guide",
49
+ "문서",
50
+ "가이드",
51
+ "매뉴얼",
52
+ ]),
53
+ reference: Object.freeze([
54
+ "reference",
55
+ "spec",
56
+ "schema",
57
+ "official",
58
+ "레퍼런스",
59
+ "공식",
60
+ "스펙",
61
+ "스키마",
62
+ ]),
63
+ api: Object.freeze([
64
+ "api",
65
+ "endpoint",
66
+ "interface",
67
+ "sdk",
68
+ "호출",
69
+ "엔드포인트",
70
+ ]),
71
+ sdk: Object.freeze([
72
+ "sdk",
73
+ "library",
74
+ "package",
75
+ "framework",
76
+ "라이브러리",
77
+ "패키지",
78
+ "프레임워크",
79
+ ]),
80
+ library: Object.freeze([
81
+ "library",
82
+ "package",
83
+ "framework",
84
+ "module",
85
+ "라이브러리",
86
+ "패키지",
87
+ "모듈",
88
+ ]),
89
+ web: Object.freeze([
90
+ "web",
91
+ "site",
92
+ "article",
93
+ "forum",
94
+ "blog",
95
+ "reddit",
96
+ "웹",
97
+ "사이트",
98
+ "기사",
99
+ "포럼",
100
+ "블로그",
101
+ ]),
102
+ search: Object.freeze([
103
+ "search",
104
+ "browse",
105
+ "lookup",
106
+ "find",
107
+ "검색",
108
+ "조회",
109
+ "탐색",
110
+ "찾아",
111
+ ]),
112
+ news: Object.freeze([
113
+ "latest",
114
+ "recent",
115
+ "news",
116
+ "today",
117
+ "release",
118
+ "announcement",
119
+ "최신",
120
+ "최근",
121
+ "뉴스",
122
+ "오늘",
123
+ "릴리즈",
124
+ "공지",
125
+ ]),
126
+ current: Object.freeze([
127
+ "current",
128
+ "status",
129
+ "pricing",
130
+ "changelog",
131
+ "up-to-date",
132
+ "현재",
133
+ "상태",
134
+ "가격",
135
+ "변경사항",
136
+ ]),
137
+ research: Object.freeze([
138
+ "research",
139
+ "verify",
140
+ "fact-check",
141
+ "investigate",
142
+ "리서치",
143
+ "검증",
144
+ "조사",
145
+ ]),
146
+ verification: Object.freeze([
147
+ "verify",
148
+ "validation",
149
+ "fact-check",
150
+ "audit",
151
+ "검증",
152
+ "확인",
153
+ "감사",
154
+ ]),
155
+ code: Object.freeze([
156
+ "code",
157
+ "repo",
158
+ "repository",
159
+ "source",
160
+ "implementation",
161
+ "bug",
162
+ "fix",
163
+ "test",
164
+ "snippet",
165
+ "cli",
166
+ "코드",
167
+ "리포",
168
+ "저장소",
169
+ "구현",
170
+ "버그",
171
+ "테스트",
172
+ "예제",
173
+ "스크립트",
174
+ ]),
175
+ repository: Object.freeze([
176
+ "repo",
177
+ "repository",
178
+ "source",
179
+ "git",
180
+ "github",
181
+ "리포",
182
+ "저장소",
183
+ "소스",
184
+ ]),
185
+ examples: Object.freeze([
186
+ "example",
187
+ "examples",
188
+ "snippet",
189
+ "sample",
190
+ "예제",
191
+ "샘플",
192
+ ]),
193
+ browser: Object.freeze([
194
+ "browser",
195
+ "page",
196
+ "dom",
197
+ "screenshot",
198
+ "render",
199
+ "브라우저",
200
+ "페이지",
201
+ "스크린샷",
202
+ "렌더",
203
+ ]),
204
+ ui: Object.freeze([
205
+ "ui",
206
+ "ux",
207
+ "layout",
208
+ "responsive",
209
+ "css",
210
+ "html",
211
+ "디자인",
212
+ "레이아웃",
213
+ "반응형",
214
+ ]),
215
+ visual: Object.freeze([
216
+ "visual",
217
+ "screenshot",
218
+ "layout",
219
+ "render",
220
+ "screen",
221
+ "화면",
222
+ "시각",
223
+ "스크린샷",
224
+ ]),
225
+ e2e: Object.freeze([
226
+ "playwright",
227
+ "e2e",
228
+ "click",
229
+ "navigate",
230
+ "automation",
231
+ "playwright",
232
+ "클릭",
233
+ "이동",
234
+ "자동화",
235
+ ]),
236
+ analysis: Object.freeze([
237
+ "analysis",
238
+ "analyze",
239
+ "audit",
240
+ "compare",
241
+ "root cause",
242
+ "분석",
243
+ "검토",
244
+ "비교",
245
+ "원인",
246
+ ]),
247
+ planning: Object.freeze([
248
+ "plan",
249
+ "planning",
250
+ "strategy",
251
+ "design",
252
+ "계획",
253
+ "전략",
254
+ "설계",
255
+ ]),
256
+ reasoning: Object.freeze([
257
+ "reason",
258
+ "reasoning",
259
+ "think",
260
+ "critique",
261
+ "추론",
262
+ "사고",
263
+ "비평",
264
+ ]),
265
+ security: Object.freeze([
266
+ "security",
267
+ "risk",
268
+ "threat",
269
+ "vulnerability",
270
+ "보안",
271
+ "위험",
272
+ "취약점",
273
+ ]),
274
+ review: Object.freeze(["review", "reviewer", "inspect", "리뷰", "검수"]),
51
275
  });
52
276
 
53
277
  export const SERVER_EXPLICIT_KEYWORDS = Object.freeze({
54
- context7: Object.freeze(['context7']),
55
- 'brave-search': Object.freeze(['brave', 'brave-search']),
56
- exa: Object.freeze(['exa']),
57
- tavily: Object.freeze(['tavily']),
58
- playwright: Object.freeze(['playwright']),
59
- 'sequential-thinking': Object.freeze(['sequential-thinking', 'sequential thinking']),
278
+ context7: Object.freeze(["context7"]),
279
+ "brave-search": Object.freeze(["brave", "brave-search"]),
280
+ exa: Object.freeze(["exa"]),
281
+ tavily: Object.freeze(["tavily"]),
282
+ playwright: Object.freeze(["playwright"]),
283
+ "sequential-thinking": Object.freeze([
284
+ "sequential-thinking",
285
+ "sequential thinking",
286
+ ]),
60
287
  });
61
288
 
62
289
  export function uniqueStrings(values = []) {
63
- return [...new Set(
64
- values
65
- .filter((value) => typeof value === 'string' && value.trim())
66
- .map((value) => value.trim()),
67
- )];
290
+ return [
291
+ ...new Set(
292
+ values
293
+ .filter((value) => typeof value === "string" && value.trim())
294
+ .map((value) => value.trim()),
295
+ ),
296
+ ];
68
297
  }
69
298
 
70
- export function inferDomainTagsFromText(text = '') {
71
- if (typeof text !== 'string' || !text.trim()) return [];
299
+ export function inferDomainTagsFromText(text = "") {
300
+ if (typeof text !== "string" || !text.trim()) return [];
72
301
  const normalized = text.toLocaleLowerCase();
73
302
  const matched = [];
74
303
 
75
304
  for (const [tag, keywords] of Object.entries(DOMAIN_TAG_KEYWORDS)) {
76
- if (keywords.some((keyword) => normalized.includes(String(keyword).toLocaleLowerCase()))) {
305
+ if (
306
+ keywords.some((keyword) =>
307
+ normalized.includes(String(keyword).toLocaleLowerCase()),
308
+ )
309
+ ) {
77
310
  matched.push(tag);
78
311
  }
79
312
  }
@@ -81,7 +314,7 @@ export function inferDomainTagsFromText(text = '') {
81
314
  return uniqueStrings(matched);
82
315
  }
83
316
 
84
- export function getDefaultServerMetadata(serverName = '') {
317
+ export function getDefaultServerMetadata(serverName = "") {
85
318
  const toolCount = MCP_SERVER_TOOL_CATALOG[serverName]?.length || 0;
86
319
  const domainTags = uniqueStrings([
87
320
  ...(MCP_SERVER_DOMAIN_TAGS[serverName] || []),
@@ -94,7 +327,7 @@ export function getDefaultServerMetadata(serverName = '') {
94
327
  };
95
328
  }
96
329
 
97
- export function normalizeServerMetadata(serverName = '', metadata = {}) {
330
+ export function normalizeServerMetadata(serverName = "", metadata = {}) {
98
331
  const fallback = getDefaultServerMetadata(serverName);
99
332
  const toolCount = Number.isFinite(metadata.tool_count)
100
333
  ? Math.max(0, Math.trunc(metadata.tool_count))
@@ -102,13 +335,17 @@ export function normalizeServerMetadata(serverName = '', metadata = {}) {
102
335
  const domainTags = uniqueStrings([
103
336
  ...fallback.domain_tags,
104
337
  ...(Array.isArray(metadata.domain_tags) ? metadata.domain_tags : []),
105
- ...inferDomainTagsFromText([
106
- serverName,
107
- typeof metadata.command === 'string' ? metadata.command : '',
108
- typeof metadata.url === 'string' ? metadata.url : '',
109
- ...(Array.isArray(metadata.args) ? metadata.args : []),
110
- ...(metadata.env && typeof metadata.env === 'object' ? Object.keys(metadata.env) : []),
111
- ].join(' ')),
338
+ ...inferDomainTagsFromText(
339
+ [
340
+ serverName,
341
+ typeof metadata.command === "string" ? metadata.command : "",
342
+ typeof metadata.url === "string" ? metadata.url : "",
343
+ ...(Array.isArray(metadata.args) ? metadata.args : []),
344
+ ...(metadata.env && typeof metadata.env === "object"
345
+ ? Object.keys(metadata.env)
346
+ : []),
347
+ ].join(" "),
348
+ ),
112
349
  ]);
113
350
 
114
351
  return {
@@ -8,9 +8,7 @@ export const PSMUX_REQUIRED_COMMANDS = [
8
8
  "capture-pane",
9
9
  ];
10
10
 
11
- export const PSMUX_OPTIONAL_COMMANDS = [
12
- "detach-client",
13
- ];
11
+ export const PSMUX_OPTIONAL_COMMANDS = ["detach-client"];
14
12
 
15
13
  export const PSMUX_INSTALL_COMMANDS = [
16
14
  "winget install marlocarlo.psmux",
@@ -26,7 +24,10 @@ export const PSMUX_UPDATE_COMMANDS = [
26
24
  "cargo install psmux --force",
27
25
  ];
28
26
 
29
- export function formatPsmuxCommandList(commands = PSMUX_INSTALL_COMMANDS, indent = "") {
27
+ export function formatPsmuxCommandList(
28
+ commands = PSMUX_INSTALL_COMMANDS,
29
+ indent = "",
30
+ ) {
30
31
  return commands.map((command) => `${indent}${command}`).join("\n");
31
32
  }
32
33
 
@@ -44,8 +45,12 @@ export function parsePsmuxVersion(output = "") {
44
45
  }
45
46
 
46
47
  export function compareSemver(a, b) {
47
- const left = String(a || "").split(".").map((part) => Number.parseInt(part, 10) || 0);
48
- const right = String(b || "").split(".").map((part) => Number.parseInt(part, 10) || 0);
48
+ const left = String(a || "")
49
+ .split(".")
50
+ .map((part) => Number.parseInt(part, 10) || 0);
51
+ const right = String(b || "")
52
+ .split(".")
53
+ .map((part) => Number.parseInt(part, 10) || 0);
49
54
  for (let index = 0; index < 3; index += 1) {
50
55
  if (left[index] > right[index]) return 1;
51
56
  if (left[index] < right[index]) return -1;
@@ -13,22 +13,37 @@ function normalizeMarkdownTarget(raw) {
13
13
  function sanitizeToken(raw) {
14
14
  let token = String(raw || "").trim();
15
15
  if (!token) return "";
16
- token = token.replace(/^[<(]+/u, "").replace(/[)>.,;:!?]+$/u, "").trim();
16
+ token = token
17
+ .replace(/^[<(]+/u, "")
18
+ .replace(/[)>.,;:!?]+$/u, "")
19
+ .trim();
17
20
  return token;
18
21
  }
19
22
 
20
23
  function isLikelyPathToken(token) {
21
24
  if (!token || URL_LIKE_RE.test(token)) return false;
22
- if (token.startsWith("app://") || token.startsWith("plugin://") || token.startsWith("mention://")) return false;
25
+ if (
26
+ token.startsWith("app://") ||
27
+ token.startsWith("plugin://") ||
28
+ token.startsWith("mention://")
29
+ )
30
+ return false;
23
31
  if (token === "~") return false;
24
32
 
25
33
  const hasPathSeparator = token.includes("/") || token.includes("\\");
26
- const hasDotPrefix = token.startsWith("./") || token.startsWith("../") || token.startsWith(".");
34
+ const hasDotPrefix =
35
+ token.startsWith("./") || token.startsWith("../") || token.startsWith(".");
27
36
  const isHomeRelative = token.startsWith("~/") || token.startsWith("~\\");
28
37
  const isWindowsAbs = WINDOWS_ABS_RE.test(token);
29
38
  const hasFileLikeSuffix = /\.[a-zA-Z0-9]{1,16}$/u.test(token);
30
39
 
31
- return hasPathSeparator || hasDotPrefix || isHomeRelative || isWindowsAbs || hasFileLikeSuffix;
40
+ return (
41
+ hasPathSeparator ||
42
+ hasDotPrefix ||
43
+ isHomeRelative ||
44
+ isWindowsAbs ||
45
+ hasFileLikeSuffix
46
+ );
32
47
  }
33
48
 
34
49
  export function extractExplicitFileTokens(text) {
@@ -67,7 +82,9 @@ function validateTransferFile(filePath, maxBytes) {
67
82
  throw new Error(`referenced path is not a file: ${filePath}`);
68
83
  }
69
84
  if (stats.size > maxBytes) {
70
- throw new Error(`referenced file too large: ${stats.size} bytes (max ${maxBytes}) for ${filePath}`);
85
+ throw new Error(
86
+ `referenced file too large: ${stats.size} bytes (max ${maxBytes}) for ${filePath}`,
87
+ );
71
88
  }
72
89
  return stats.size;
73
90
  }
@@ -132,16 +149,23 @@ export function buildRemoteTransferPlan(options = {}) {
132
149
  validateTransferFile(absoluteHandoffPath, maxBytes);
133
150
  const handoffContent = readFileSync(absoluteHandoffPath, "utf8").trim();
134
151
 
135
- const stagedHandoffPath = toRemotePath(remoteStageRoot, `handoff/${basename(absoluteHandoffPath)}`);
136
- const transfers = [{
137
- localPath: absoluteHandoffPath,
138
- remotePath: stagedHandoffPath,
139
- type: "handoff",
140
- }];
152
+ const stagedHandoffPath = toRemotePath(
153
+ remoteStageRoot,
154
+ `handoff/${basename(absoluteHandoffPath)}`,
155
+ );
156
+ const transfers = [
157
+ {
158
+ localPath: absoluteHandoffPath,
159
+ remotePath: stagedHandoffPath,
160
+ type: "handoff",
161
+ },
162
+ ];
141
163
 
142
164
  const tokens = extractExplicitFileTokens(handoffContent);
143
165
  if (tokens.length > maxReferenceFiles) {
144
- throw new Error(`too many referenced files: ${tokens.length} (max ${maxReferenceFiles})`);
166
+ throw new Error(
167
+ `too many referenced files: ${tokens.length} (max ${maxReferenceFiles})`,
168
+ );
145
169
  }
146
170
 
147
171
  const stagedByLocalPath = new Map();
@@ -166,7 +190,10 @@ export function buildRemoteTransferPlan(options = {}) {
166
190
  });
167
191
  }
168
192
 
169
- replacements.push({ token, stagedPath: stagedByLocalPath.get(resolvedPath) });
193
+ replacements.push({
194
+ token,
195
+ stagedPath: stagedByLocalPath.get(resolvedPath),
196
+ });
170
197
  }
171
198
 
172
199
  const replacementEntries = Array.from(
@@ -189,7 +216,10 @@ export function buildRemoteTransferPlan(options = {}) {
189
216
 
190
217
  return {
191
218
  prompt,
192
- replacements: replacementEntries.map(([token, stagedPath]) => ({ stagedPath, token })),
219
+ replacements: replacementEntries.map(([token, stagedPath]) => ({
220
+ stagedPath,
221
+ token,
222
+ })),
193
223
  stagedHandoffPath,
194
224
  transfers,
195
225
  };
@@ -1,5 +1,12 @@
1
1
  import { existsSync, readdirSync, readFileSync } from "node:fs";
2
- import { basename, extname, isAbsolute, join, relative, resolve } from "node:path";
2
+ import {
3
+ basename,
4
+ extname,
5
+ isAbsolute,
6
+ join,
7
+ relative,
8
+ resolve,
9
+ } from "node:path";
3
10
 
4
11
  const IF_TAG_RE = /{{\s*(#if\s+([A-Za-z0-9_.-]+)|\/if)\s*}}/g;
5
12
  const PARTIAL_RE = /{{>\s*([A-Za-z0-9_./-]+)\s*}}/g;
@@ -187,7 +194,8 @@ function resolveIncludeContent(includeName, options) {
187
194
  const fullPath = resolve(baseDir, normalizedName);
188
195
  const relativePath = relative(baseDir, fullPath);
189
196
  const isInsideBaseDir =
190
- relativePath === "" || (!relativePath.startsWith("..") && !isAbsolute(relativePath));
197
+ relativePath === "" ||
198
+ (!relativePath.startsWith("..") && !isAbsolute(relativePath));
191
199
 
192
200
  if (!isInsideBaseDir || !existsSync(fullPath)) {
193
201
  throw new Error(`Missing include: ${normalizedName}`);
@@ -223,9 +231,21 @@ function renderVariables(source, context) {
223
231
  });
224
232
  }
225
233
 
226
- function renderWithContext(source, context, partials, options, includeStack = []) {
234
+ function renderWithContext(
235
+ source,
236
+ context,
237
+ partials,
238
+ options,
239
+ includeStack = [],
240
+ ) {
227
241
  const afterIf = evaluateConditionals(source, context);
228
- const afterPartials = renderPartials(afterIf, context, partials, options, includeStack);
242
+ const afterPartials = renderPartials(
243
+ afterIf,
244
+ context,
245
+ partials,
246
+ options,
247
+ includeStack,
248
+ );
229
249
  const afterFileIncludes = renderFileIncludes(
230
250
  afterPartials,
231
251
  context,
@@ -239,8 +259,8 @@ function renderWithContext(source, context, partials, options, includeStack = []
239
259
  function readAllTemplateFiles(rootDir, currentDir = rootDir) {
240
260
  if (!rootDir || !existsSync(rootDir)) return [];
241
261
 
242
- const entries = readdirSync(currentDir, { withFileTypes: true }).sort((left, right) =>
243
- left.name.localeCompare(right.name),
262
+ const entries = readdirSync(currentDir, { withFileTypes: true }).sort(
263
+ (left, right) => left.name.localeCompare(right.name),
244
264
  );
245
265
  const files = [];
246
266
 
@@ -278,7 +298,10 @@ export function parseFrontmatter(source) {
278
298
  return { data, body };
279
299
  }
280
300
 
281
- export function buildSkillTemplateContext({ frontmatter = {}, skillDirName = "" } = {}) {
301
+ export function buildSkillTemplateContext({
302
+ frontmatter = {},
303
+ skillDirName = "",
304
+ } = {}) {
282
305
  const context = { ...frontmatter };
283
306
  const skillName = String(frontmatter.name || skillDirName || "").trim();
284
307
  const skillDescription = String(frontmatter.description || "").trim();