triflux 10.0.0 → 10.0.2

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 (426) hide show
  1. package/CLAUDE.md +171 -0
  2. package/README.md +32 -15
  3. package/bin/triflux.mjs +62 -5
  4. package/hooks/agent-route-guard.mjs +109 -0
  5. package/hooks/cross-review-tracker.mjs +122 -0
  6. package/hooks/error-context.mjs +148 -0
  7. package/hooks/hook-adaptive-collector.mjs +86 -0
  8. package/hooks/hook-manager.mjs +365 -0
  9. package/hooks/hook-orchestrator.mjs +312 -0
  10. package/hooks/hook-registry.json +246 -0
  11. package/hooks/hooks.json +89 -0
  12. package/hooks/keyword-rules.json +574 -0
  13. package/hooks/lib/resolve-root.mjs +59 -0
  14. package/hooks/mcp-config-watcher.mjs +80 -0
  15. package/hooks/pipeline-stop.mjs +76 -0
  16. package/hooks/safety-guard.mjs +169 -0
  17. package/hooks/subagent-verifier.mjs +80 -0
  18. package/hub/account-broker.mjs +251 -0
  19. package/hub/adaptive-diagnostic.mjs +323 -0
  20. package/hub/adaptive-inject.mjs +186 -0
  21. package/hub/adaptive-memory.mjs +163 -0
  22. package/hub/adaptive.mjs +143 -0
  23. package/hub/assign-callbacks.mjs +133 -0
  24. package/hub/bridge.mjs +799 -0
  25. package/hub/cli-adapter-base.mjs +280 -0
  26. package/hub/codex-adapter.mjs +199 -0
  27. package/hub/codex-compat.mjs +11 -0
  28. package/hub/codex-preflight.mjs +166 -0
  29. package/hub/delegator/contracts.mjs +37 -0
  30. package/hub/delegator/index.mjs +14 -0
  31. package/hub/delegator/schema/delegator-tools.schema.json +250 -0
  32. package/hub/delegator/service.mjs +307 -0
  33. package/hub/delegator/tool-definitions.mjs +35 -0
  34. package/hub/fullcycle.mjs +96 -0
  35. package/hub/gemini-adapter.mjs +180 -0
  36. package/hub/hitl.mjs +143 -0
  37. package/hub/intent.mjs +193 -0
  38. package/hub/lib/cache-guard.mjs +114 -0
  39. package/hub/lib/known-errors.json +72 -0
  40. package/hub/lib/memory-store.mjs +748 -0
  41. package/hub/lib/process-utils.mjs +361 -0
  42. package/hub/lib/ssh-command.mjs +211 -0
  43. package/hub/lib/ssh-retry.mjs +59 -0
  44. package/hub/lib/uuidv7.mjs +44 -0
  45. package/hub/memory-doctor.mjs +480 -0
  46. package/hub/middleware/request-logger.mjs +161 -0
  47. package/hub/paths.mjs +30 -0
  48. package/hub/pipe.mjs +664 -0
  49. package/hub/pipeline/gates/confidence.mjs +56 -0
  50. package/hub/pipeline/gates/consensus.mjs +94 -0
  51. package/hub/pipeline/gates/index.mjs +5 -0
  52. package/hub/pipeline/gates/selfcheck.mjs +82 -0
  53. package/hub/pipeline/index.mjs +318 -0
  54. package/hub/pipeline/state.mjs +191 -0
  55. package/hub/pipeline/transitions.mjs +124 -0
  56. package/hub/platform.mjs +225 -0
  57. package/hub/public/dashboard.html +355 -0
  58. package/hub/public/tray-icon.ico +0 -0
  59. package/hub/public/tray-icon.png +0 -0
  60. package/hub/quality/deslop.mjs +253 -0
  61. package/hub/reflexion.mjs +372 -0
  62. package/hub/research.mjs +146 -0
  63. package/hub/router.mjs +791 -0
  64. package/hub/routing/complexity.mjs +166 -0
  65. package/hub/routing/index.mjs +117 -0
  66. package/hub/routing/q-learning.mjs +336 -0
  67. package/hub/schema.sql +148 -0
  68. package/hub/server.mjs +1264 -0
  69. package/hub/session-fingerprint.mjs +352 -0
  70. package/hub/state.mjs +258 -0
  71. package/hub/store-adapter.mjs +118 -0
  72. package/hub/store.mjs +857 -0
  73. package/hub/team/agent-map.json +11 -0
  74. package/hub/team/ansi.mjs +379 -0
  75. package/hub/team/backend.mjs +90 -0
  76. package/hub/team/cli/commands/attach.mjs +37 -0
  77. package/hub/team/cli/commands/control.mjs +43 -0
  78. package/hub/team/cli/commands/debug.mjs +74 -0
  79. package/hub/team/cli/commands/focus.mjs +53 -0
  80. package/hub/team/cli/commands/interrupt.mjs +36 -0
  81. package/hub/team/cli/commands/kill.mjs +37 -0
  82. package/hub/team/cli/commands/list.mjs +24 -0
  83. package/hub/team/cli/commands/send.mjs +37 -0
  84. package/hub/team/cli/commands/start/index.mjs +106 -0
  85. package/hub/team/cli/commands/start/parse-args.mjs +130 -0
  86. package/hub/team/cli/commands/start/start-headless.mjs +109 -0
  87. package/hub/team/cli/commands/start/start-in-process.mjs +40 -0
  88. package/hub/team/cli/commands/start/start-mux.mjs +73 -0
  89. package/hub/team/cli/commands/start/start-wt.mjs +69 -0
  90. package/hub/team/cli/commands/status.mjs +87 -0
  91. package/hub/team/cli/commands/stop.mjs +31 -0
  92. package/hub/team/cli/commands/task.mjs +30 -0
  93. package/hub/team/cli/commands/tasks.mjs +13 -0
  94. package/hub/team/cli/help.mjs +42 -0
  95. package/hub/team/cli/index.mjs +41 -0
  96. package/hub/team/cli/manifest.mjs +29 -0
  97. package/hub/team/cli/render.mjs +30 -0
  98. package/hub/team/cli/services/attach-fallback.mjs +54 -0
  99. package/hub/team/cli/services/hub-client.mjs +227 -0
  100. package/hub/team/cli/services/member-selector.mjs +30 -0
  101. package/hub/team/cli/services/native-control.mjs +117 -0
  102. package/hub/team/cli/services/runtime-mode.mjs +62 -0
  103. package/hub/team/cli/services/state-store.mjs +48 -0
  104. package/hub/team/cli/services/task-model.mjs +30 -0
  105. package/hub/team/conductor-mesh-bridge.mjs +121 -0
  106. package/hub/team/conductor.mjs +671 -0
  107. package/hub/team/dashboard-anchor.mjs +14 -0
  108. package/hub/team/dashboard-layout.mjs +33 -0
  109. package/hub/team/dashboard-open.mjs +153 -0
  110. package/hub/team/dashboard.mjs +274 -0
  111. package/hub/team/event-log.mjs +76 -0
  112. package/hub/team/handoff.mjs +303 -0
  113. package/hub/team/headless.mjs +1156 -0
  114. package/hub/team/health-probe.mjs +272 -0
  115. package/hub/team/launcher-template.mjs +95 -0
  116. package/hub/team/lead-control.mjs +104 -0
  117. package/hub/team/native-supervisor.mjs +392 -0
  118. package/hub/team/native.mjs +649 -0
  119. package/hub/team/nativeProxy.mjs +688 -0
  120. package/hub/team/notify.mjs +293 -0
  121. package/hub/team/orchestrator.mjs +161 -0
  122. package/hub/team/pane.mjs +153 -0
  123. package/hub/team/process-cleanup.mjs +342 -0
  124. package/hub/team/psmux.mjs +1354 -0
  125. package/hub/team/remote-probe.mjs +276 -0
  126. package/hub/team/remote-session.mjs +299 -0
  127. package/hub/team/remote-watcher.mjs +478 -0
  128. package/hub/team/routing.mjs +223 -0
  129. package/hub/team/session-sync.mjs +169 -0
  130. package/hub/team/session.mjs +611 -0
  131. package/hub/team/shared.mjs +13 -0
  132. package/hub/team/staleState.mjs +361 -0
  133. package/hub/team/swarm-hypervisor.mjs +589 -0
  134. package/hub/team/swarm-locks.mjs +204 -0
  135. package/hub/team/swarm-planner.mjs +260 -0
  136. package/hub/team/swarm-reconciler.mjs +137 -0
  137. package/hub/team/tui-lite.mjs +380 -0
  138. package/hub/team/tui-remote-adapter.mjs +393 -0
  139. package/hub/team/tui-viewer.mjs +463 -0
  140. package/hub/team/tui.mjs +1449 -0
  141. package/hub/team/worktree-lifecycle.mjs +193 -0
  142. package/hub/team/wt-manager.mjs +407 -0
  143. package/hub/team/wt-templates.json +43 -0
  144. package/hub/team-bridge.mjs +27 -0
  145. package/hub/token-mode.mjs +224 -0
  146. package/hub/tools.mjs +636 -0
  147. package/hub/tray.mjs +376 -0
  148. package/hub/workers/claude-worker.mjs +475 -0
  149. package/hub/workers/codex-mcp.mjs +507 -0
  150. package/hub/workers/delegator-mcp.mjs +1076 -0
  151. package/hub/workers/factory.mjs +21 -0
  152. package/hub/workers/gemini-worker.mjs +374 -0
  153. package/hub/workers/interface.mjs +52 -0
  154. package/hub/workers/worker-utils.mjs +104 -0
  155. package/hud/colors.mjs +88 -0
  156. package/hud/constants.mjs +88 -0
  157. package/hud/context-monitor.mjs +403 -0
  158. package/hud/hud-qos-status.mjs +210 -0
  159. package/hud/providers/claude.mjs +314 -0
  160. package/hud/providers/codex.mjs +151 -0
  161. package/hud/providers/gemini.mjs +320 -0
  162. package/hud/renderers.mjs +442 -0
  163. package/hud/terminal.mjs +140 -0
  164. package/hud/utils.mjs +313 -0
  165. package/mesh/index.mjs +63 -0
  166. package/mesh/mesh-budget.mjs +128 -0
  167. package/mesh/mesh-heartbeat.mjs +100 -0
  168. package/mesh/mesh-protocol.mjs +96 -0
  169. package/mesh/mesh-queue.mjs +165 -0
  170. package/mesh/mesh-registry.mjs +78 -0
  171. package/mesh/mesh-router.mjs +76 -0
  172. package/package.json +8 -1
  173. package/references/hosts.json +33 -0
  174. package/scripts/__tests__/gen-skill-docs.test.mjs +87 -0
  175. package/scripts/__tests__/keyword-detector.test.mjs +234 -0
  176. package/scripts/__tests__/mcp-guard-engine.test.mjs +118 -0
  177. package/scripts/__tests__/remote-spawn-transfer.test.mjs +117 -0
  178. package/scripts/__tests__/remote-spawn.test.mjs +92 -0
  179. package/scripts/__tests__/skill-template.test.mjs +193 -0
  180. package/scripts/__tests__/smoke.test.mjs +34 -0
  181. package/scripts/cache-buildup.mjs +30 -0
  182. package/scripts/cache-doctor.mjs +149 -0
  183. package/scripts/cache-warmup.mjs +557 -0
  184. package/scripts/claudemd-sync.mjs +148 -0
  185. package/scripts/cli-route.sh +3 -0
  186. package/scripts/completions/tfx.bash +47 -0
  187. package/scripts/completions/tfx.fish +44 -0
  188. package/scripts/completions/tfx.zsh +83 -0
  189. package/scripts/cross-review-gate.mjs +126 -0
  190. package/scripts/cross-review-tracker.mjs +238 -0
  191. package/scripts/gen-skill-docs.mjs +111 -0
  192. package/scripts/headless-guard-fast.sh +21 -0
  193. package/scripts/headless-guard.mjs +360 -0
  194. package/scripts/hub-ensure.mjs +120 -0
  195. package/scripts/keyword-detector.mjs +272 -0
  196. package/scripts/keyword-rules-expander.mjs +521 -0
  197. package/scripts/lib/claudemd-scanner.mjs +218 -0
  198. package/scripts/lib/context.mjs +67 -0
  199. package/scripts/lib/cross-review-utils.mjs +51 -0
  200. package/scripts/lib/env-probe.mjs +241 -0
  201. package/scripts/lib/gemini-profiles.mjs +85 -0
  202. package/scripts/lib/handoff.mjs +171 -0
  203. package/scripts/lib/hook-utils.mjs +14 -0
  204. package/scripts/lib/keyword-rules.mjs +166 -0
  205. package/scripts/lib/logger.mjs +105 -0
  206. package/scripts/lib/mcp-filter.mjs +739 -0
  207. package/scripts/lib/mcp-guard-engine.mjs +954 -0
  208. package/scripts/lib/mcp-manifest.mjs +79 -0
  209. package/scripts/lib/mcp-server-catalog.mjs +118 -0
  210. package/scripts/lib/psmux-info.mjs +119 -0
  211. package/scripts/lib/remote-spawn-transfer.mjs +196 -0
  212. package/scripts/lib/skill-template.mjs +326 -0
  213. package/scripts/mcp-check.mjs +237 -0
  214. package/scripts/mcp-cleanup.ps1 +17 -0
  215. package/scripts/mcp-gateway-config.mjs +207 -0
  216. package/scripts/mcp-gateway-ensure.mjs +85 -0
  217. package/scripts/mcp-gateway-integration-test.mjs +228 -0
  218. package/scripts/mcp-gateway-start.mjs +226 -0
  219. package/scripts/mcp-gateway-start.ps1 +141 -0
  220. package/scripts/mcp-gateway-verify.mjs +77 -0
  221. package/scripts/mcp-safety-guard.mjs +44 -0
  222. package/scripts/notion-read.mjs +556 -0
  223. package/scripts/pack.mjs +295 -0
  224. package/scripts/preflight-cache.mjs +69 -0
  225. package/scripts/preinstall.mjs +96 -0
  226. package/scripts/remote-spawn.mjs +1376 -0
  227. package/scripts/run.cjs +79 -0
  228. package/scripts/session-spawn-helper.mjs +185 -0
  229. package/scripts/setup.mjs +1178 -0
  230. package/scripts/test-lock.mjs +71 -0
  231. package/scripts/test-tfx-route-no-claude-native.mjs +57 -0
  232. package/scripts/tfx-batch-stats.mjs +96 -0
  233. package/scripts/tfx-gate-activate.mjs +89 -0
  234. package/scripts/tfx-route-post.mjs +505 -0
  235. package/scripts/tfx-route-worker.mjs +223 -0
  236. package/scripts/tfx-route.sh +2014 -0
  237. package/scripts/tmp-cleanup.mjs +103 -0
  238. package/scripts/token-snapshot.mjs +575 -0
  239. package/skills/tfx-auto/SKILL.md.tmpl +2 -3
  240. package/skills/tfx-autoresearch/SKILL.md +6 -5
  241. package/skills/tfx-codex/SKILL.md.tmpl +2 -3
  242. package/skills/tfx-codex-swarm-workspace/iteration-1/benchmark.json +33 -0
  243. package/skills/tfx-codex-swarm-workspace/iteration-1/full-swarm-all-prds/eval_metadata.json +42 -0
  244. package/skills/tfx-codex-swarm-workspace/iteration-1/full-swarm-all-prds/with_skill/grading.json +11 -0
  245. package/skills/tfx-codex-swarm-workspace/iteration-1/full-swarm-all-prds/with_skill/outputs/analysis.md +87 -0
  246. package/skills/tfx-codex-swarm-workspace/iteration-1/full-swarm-all-prds/with_skill/outputs/classification.md +35 -0
  247. package/skills/tfx-codex-swarm-workspace/iteration-1/full-swarm-all-prds/with_skill/outputs/commands.sh +275 -0
  248. package/skills/tfx-codex-swarm-workspace/iteration-1/full-swarm-all-prds/with_skill/outputs/routing.md +56 -0
  249. package/skills/tfx-codex-swarm-workspace/iteration-1/full-swarm-all-prds/with_skill/timing.json +5 -0
  250. package/skills/tfx-codex-swarm-workspace/iteration-1/full-swarm-all-prds/without_skill/grading.json +11 -0
  251. package/skills/tfx-codex-swarm-workspace/iteration-1/full-swarm-all-prds/without_skill/outputs/analysis.md +92 -0
  252. package/skills/tfx-codex-swarm-workspace/iteration-1/full-swarm-all-prds/without_skill/outputs/classification.md +71 -0
  253. package/skills/tfx-codex-swarm-workspace/iteration-1/full-swarm-all-prds/without_skill/outputs/commands.sh +264 -0
  254. package/skills/tfx-codex-swarm-workspace/iteration-1/full-swarm-all-prds/without_skill/outputs/routing.md +113 -0
  255. package/skills/tfx-codex-swarm-workspace/iteration-1/full-swarm-all-prds/without_skill/timing.json +5 -0
  256. package/skills/tfx-codex-swarm-workspace/iteration-1/implicit-swarm-no-keywords/eval_metadata.json +32 -0
  257. package/skills/tfx-codex-swarm-workspace/iteration-1/implicit-swarm-no-keywords/with_skill/grading.json +9 -0
  258. package/skills/tfx-codex-swarm-workspace/iteration-1/implicit-swarm-no-keywords/with_skill/outputs/analysis.md +96 -0
  259. package/skills/tfx-codex-swarm-workspace/iteration-1/implicit-swarm-no-keywords/with_skill/outputs/classification.md +38 -0
  260. package/skills/tfx-codex-swarm-workspace/iteration-1/implicit-swarm-no-keywords/with_skill/outputs/commands.sh +151 -0
  261. package/skills/tfx-codex-swarm-workspace/iteration-1/implicit-swarm-no-keywords/with_skill/outputs/routing.md +51 -0
  262. package/skills/tfx-codex-swarm-workspace/iteration-1/implicit-swarm-no-keywords/with_skill/timing.json +5 -0
  263. package/skills/tfx-codex-swarm-workspace/iteration-1/implicit-swarm-no-keywords/without_skill/grading.json +9 -0
  264. package/skills/tfx-codex-swarm-workspace/iteration-1/implicit-swarm-no-keywords/without_skill/outputs/analysis.md +127 -0
  265. package/skills/tfx-codex-swarm-workspace/iteration-1/implicit-swarm-no-keywords/without_skill/outputs/classification.md +57 -0
  266. package/skills/tfx-codex-swarm-workspace/iteration-1/implicit-swarm-no-keywords/without_skill/outputs/commands.sh +129 -0
  267. package/skills/tfx-codex-swarm-workspace/iteration-1/implicit-swarm-no-keywords/without_skill/outputs/routing.md +84 -0
  268. package/skills/tfx-codex-swarm-workspace/iteration-1/implicit-swarm-no-keywords/without_skill/timing.json +5 -0
  269. package/skills/tfx-codex-swarm-workspace/iteration-1/selective-spawn-with-override/eval_metadata.json +27 -0
  270. package/skills/tfx-codex-swarm-workspace/iteration-1/selective-spawn-with-override/with_skill/grading.json +8 -0
  271. package/skills/tfx-codex-swarm-workspace/iteration-1/selective-spawn-with-override/with_skill/outputs/analysis.md +98 -0
  272. package/skills/tfx-codex-swarm-workspace/iteration-1/selective-spawn-with-override/with_skill/outputs/classification.md +65 -0
  273. package/skills/tfx-codex-swarm-workspace/iteration-1/selective-spawn-with-override/with_skill/outputs/commands.sh +123 -0
  274. package/skills/tfx-codex-swarm-workspace/iteration-1/selective-spawn-with-override/with_skill/outputs/routing.md +66 -0
  275. package/skills/tfx-codex-swarm-workspace/iteration-1/selective-spawn-with-override/with_skill/timing.json +5 -0
  276. package/skills/tfx-codex-swarm-workspace/iteration-1/selective-spawn-with-override/without_skill/grading.json +8 -0
  277. package/skills/tfx-codex-swarm-workspace/iteration-1/selective-spawn-with-override/without_skill/outputs/analysis.md +88 -0
  278. package/skills/tfx-codex-swarm-workspace/iteration-1/selective-spawn-with-override/without_skill/outputs/classification.md +40 -0
  279. package/skills/tfx-codex-swarm-workspace/iteration-1/selective-spawn-with-override/without_skill/outputs/commands.sh +130 -0
  280. package/skills/tfx-codex-swarm-workspace/iteration-1/selective-spawn-with-override/without_skill/outputs/routing.md +61 -0
  281. package/skills/tfx-codex-swarm-workspace/iteration-1/selective-spawn-with-override/without_skill/timing.json +5 -0
  282. package/skills/tfx-deep-interview/SKILL.md +1 -2
  283. package/skills/tfx-plan/SKILL.md.tmpl +2 -3
  284. package/skills/tfx-psmux-rules/SKILL.md +11 -2
  285. package/skills/tfx-qa/SKILL.md.tmpl +2 -3
  286. package/skills/tfx-remote-spawn/SKILL.md +8 -11
  287. package/skills/tfx-research/SKILL.md.tmpl +2 -3
  288. package/skills/tfx-review/SKILL.md.tmpl +2 -3
  289. package/skills/tfx-workspace/async-tests/run-tests.sh +203 -0
  290. package/skills/tfx-workspace/evals/evals.json +79 -0
  291. package/skills/tfx-workspace/iteration-1/benchmark.json +162 -0
  292. package/skills/tfx-workspace/iteration-1/codex-gemini-remap/eval_metadata.json +11 -0
  293. package/skills/tfx-workspace/iteration-1/codex-gemini-remap/old_skill/grading.json +9 -0
  294. package/skills/tfx-workspace/iteration-1/codex-gemini-remap/old_skill/outputs/analysis.md +154 -0
  295. package/skills/tfx-workspace/iteration-1/codex-gemini-remap/old_skill/timing.json +5 -0
  296. package/skills/tfx-workspace/iteration-1/codex-gemini-remap/with_skill/grading.json +9 -0
  297. package/skills/tfx-workspace/iteration-1/codex-gemini-remap/with_skill/outputs/analysis.md +126 -0
  298. package/skills/tfx-workspace/iteration-1/codex-gemini-remap/with_skill/timing.json +5 -0
  299. package/skills/tfx-workspace/iteration-1/doctor-diagnosis/eval_metadata.json +11 -0
  300. package/skills/tfx-workspace/iteration-1/doctor-diagnosis/old_skill/grading.json +9 -0
  301. package/skills/tfx-workspace/iteration-1/doctor-diagnosis/old_skill/outputs/analysis.md +119 -0
  302. package/skills/tfx-workspace/iteration-1/doctor-diagnosis/old_skill/timing.json +5 -0
  303. package/skills/tfx-workspace/iteration-1/doctor-diagnosis/with_skill/grading.json +9 -0
  304. package/skills/tfx-workspace/iteration-1/doctor-diagnosis/with_skill/outputs/analysis.md +115 -0
  305. package/skills/tfx-workspace/iteration-1/doctor-diagnosis/with_skill/timing.json +5 -0
  306. package/skills/tfx-workspace/iteration-1/hub-start-sequence/eval_metadata.json +10 -0
  307. package/skills/tfx-workspace/iteration-1/hub-start-sequence/old_skill/grading.json +8 -0
  308. package/skills/tfx-workspace/iteration-1/hub-start-sequence/old_skill/outputs/analysis.md +86 -0
  309. package/skills/tfx-workspace/iteration-1/hub-start-sequence/old_skill/timing.json +5 -0
  310. package/skills/tfx-workspace/iteration-1/hub-start-sequence/with_skill/grading.json +8 -0
  311. package/skills/tfx-workspace/iteration-1/hub-start-sequence/with_skill/outputs/analysis.md +81 -0
  312. package/skills/tfx-workspace/iteration-1/hub-start-sequence/with_skill/timing.json +5 -0
  313. package/skills/tfx-workspace/iteration-1/multi-team-creation/eval_metadata.json +12 -0
  314. package/skills/tfx-workspace/iteration-1/multi-team-creation/old_skill/grading.json +10 -0
  315. package/skills/tfx-workspace/iteration-1/multi-team-creation/old_skill/outputs/analysis.md +316 -0
  316. package/skills/tfx-workspace/iteration-1/multi-team-creation/old_skill/timing.json +5 -0
  317. package/skills/tfx-workspace/iteration-1/multi-team-creation/with_skill/grading.json +10 -0
  318. package/skills/tfx-workspace/iteration-1/multi-team-creation/with_skill/outputs/analysis.md +352 -0
  319. package/skills/tfx-workspace/iteration-1/multi-team-creation/with_skill/timing.json +5 -0
  320. package/skills/tfx-workspace/iteration-1/review.html +1325 -0
  321. package/skills/tfx-workspace/iteration-1/routing-implement-shortcut/eval_metadata.json +12 -0
  322. package/skills/tfx-workspace/iteration-1/routing-implement-shortcut/old_skill/grading.json +10 -0
  323. package/skills/tfx-workspace/iteration-1/routing-implement-shortcut/old_skill/outputs/analysis.md +97 -0
  324. package/skills/tfx-workspace/iteration-1/routing-implement-shortcut/old_skill/timing.json +5 -0
  325. package/skills/tfx-workspace/iteration-1/routing-implement-shortcut/with_skill/grading.json +10 -0
  326. package/skills/tfx-workspace/iteration-1/routing-implement-shortcut/with_skill/outputs/analysis.md +94 -0
  327. package/skills/tfx-workspace/iteration-1/routing-implement-shortcut/with_skill/timing.json +5 -0
  328. package/skills/tfx-workspace/iteration-1/routing-multi-task-triage/eval_metadata.json +12 -0
  329. package/skills/tfx-workspace/iteration-1/routing-multi-task-triage/old_skill/grading.json +10 -0
  330. package/skills/tfx-workspace/iteration-1/routing-multi-task-triage/old_skill/outputs/analysis.md +209 -0
  331. package/skills/tfx-workspace/iteration-1/routing-multi-task-triage/old_skill/timing.json +5 -0
  332. package/skills/tfx-workspace/iteration-1/routing-multi-task-triage/with_skill/grading.json +10 -0
  333. package/skills/tfx-workspace/iteration-1/routing-multi-task-triage/with_skill/outputs/analysis.md +193 -0
  334. package/skills/tfx-workspace/iteration-1/routing-multi-task-triage/with_skill/timing.json +5 -0
  335. package/skills/tfx-workspace/iteration-2/benchmark.json +62 -0
  336. package/skills/tfx-workspace/iteration-2/multi-team-creation-refactored/eval_metadata.json +13 -0
  337. package/skills/tfx-workspace/iteration-2/multi-team-creation-refactored/old_skill/grading.json +11 -0
  338. package/skills/tfx-workspace/iteration-2/multi-team-creation-refactored/old_skill/outputs/analysis.md +382 -0
  339. package/skills/tfx-workspace/iteration-2/multi-team-creation-refactored/old_skill/timing.json +5 -0
  340. package/skills/tfx-workspace/iteration-2/multi-team-creation-refactored/with_skill/grading.json +11 -0
  341. package/skills/tfx-workspace/iteration-2/multi-team-creation-refactored/with_skill/outputs/analysis.md +333 -0
  342. package/skills/tfx-workspace/iteration-2/multi-team-creation-refactored/with_skill/timing.json +5 -0
  343. package/skills/tfx-workspace/iteration-2/review.html +1325 -0
  344. package/skills/tfx-workspace/skill-snapshot/tfx-auto/SKILL.md +217 -0
  345. package/skills/{tfx-auto-codex/SKILL.md.tmpl → tfx-workspace/skill-snapshot/tfx-auto-codex/SKILL.md} +3 -31
  346. package/skills/tfx-workspace/skill-snapshot/tfx-codex/SKILL.md +65 -0
  347. package/skills/tfx-workspace/skill-snapshot/tfx-doctor/SKILL.md +94 -0
  348. package/skills/{tfx-gemini/SKILL.md.tmpl → tfx-workspace/skill-snapshot/tfx-gemini/SKILL.md} +6 -14
  349. package/skills/tfx-workspace/skill-snapshot/tfx-hub/SKILL.md +133 -0
  350. package/skills/tfx-workspace/skill-snapshot/tfx-multi/SKILL.md +426 -0
  351. package/skills/tfx-workspace/skill-snapshot/tfx-setup/SKILL.md +101 -0
  352. package/skills/merge-worktree/SKILL.md.tmpl +0 -144
  353. package/skills/shared/arguments-processing.md +0 -2
  354. package/skills/shared/mandatory-rules.md +0 -6
  355. package/skills/shared/telemetry-segment.md +0 -6
  356. package/skills/star-prompt/SKILL.md.tmpl +0 -122
  357. package/skills/tfx-analysis/SKILL.md.tmpl +0 -106
  358. package/skills/tfx-analysis/skill.json +0 -11
  359. package/skills/tfx-auto/skill.json +0 -26
  360. package/skills/tfx-auto-codex/skill.json +0 -8
  361. package/skills/tfx-autopilot/SKILL.md.tmpl +0 -115
  362. package/skills/tfx-autopilot/skill.json +0 -10
  363. package/skills/tfx-autoresearch/SKILL.md.tmpl +0 -135
  364. package/skills/tfx-autoresearch/skill.json +0 -14
  365. package/skills/tfx-autoroute/SKILL.md.tmpl +0 -188
  366. package/skills/tfx-autoroute/skill.json +0 -12
  367. package/skills/tfx-codex/skill.json +0 -8
  368. package/skills/tfx-codex-swarm/SKILL.md.tmpl +0 -16
  369. package/skills/tfx-codex-swarm/skill.json +0 -5
  370. package/skills/tfx-consensus/SKILL.md.tmpl +0 -145
  371. package/skills/tfx-consensus/skill.json +0 -8
  372. package/skills/tfx-debate/SKILL.md.tmpl +0 -191
  373. package/skills/tfx-debate/skill.json +0 -12
  374. package/skills/tfx-deep-analysis/SKILL.md.tmpl +0 -227
  375. package/skills/tfx-deep-analysis/skill.json +0 -10
  376. package/skills/tfx-deep-interview/SKILL.md.tmpl +0 -203
  377. package/skills/tfx-deep-interview/skill.json +0 -12
  378. package/skills/tfx-deep-plan/SKILL.md.tmpl +0 -281
  379. package/skills/tfx-deep-plan/skill.json +0 -13
  380. package/skills/tfx-deep-qa/SKILL.md.tmpl +0 -164
  381. package/skills/tfx-deep-qa/skill.json +0 -11
  382. package/skills/tfx-deep-research/SKILL.md.tmpl +0 -216
  383. package/skills/tfx-deep-research/skill.json +0 -14
  384. package/skills/tfx-deep-review/SKILL.md.tmpl +0 -178
  385. package/skills/tfx-deep-review/skill.json +0 -12
  386. package/skills/tfx-doctor/SKILL.md.tmpl +0 -172
  387. package/skills/tfx-doctor/skill.json +0 -8
  388. package/skills/tfx-find/skill.json +0 -12
  389. package/skills/tfx-forge/SKILL.md.tmpl +0 -187
  390. package/skills/tfx-forge/skill.json +0 -12
  391. package/skills/tfx-fullcycle/SKILL.md.tmpl +0 -285
  392. package/skills/tfx-fullcycle/skill.json +0 -11
  393. package/skills/tfx-gemini/skill.json +0 -8
  394. package/skills/tfx-hooks/SKILL.md.tmpl +0 -216
  395. package/skills/tfx-hooks/skill.json +0 -8
  396. package/skills/tfx-hub/SKILL.md.tmpl +0 -212
  397. package/skills/tfx-hub/skill.json +0 -8
  398. package/skills/tfx-index/skill.json +0 -11
  399. package/skills/tfx-interview/SKILL.md.tmpl +0 -284
  400. package/skills/tfx-interview/skill.json +0 -12
  401. package/skills/tfx-multi/SKILL.md.tmpl +0 -183
  402. package/skills/tfx-multi/skill.json +0 -8
  403. package/skills/tfx-panel/SKILL.md.tmpl +0 -188
  404. package/skills/tfx-panel/skill.json +0 -12
  405. package/skills/tfx-persist/SKILL.md.tmpl +0 -269
  406. package/skills/tfx-persist/skill.json +0 -12
  407. package/skills/tfx-plan/skill.json +0 -11
  408. package/skills/tfx-profile/SKILL.md.tmpl +0 -239
  409. package/skills/tfx-profile/skill.json +0 -8
  410. package/skills/tfx-prune/SKILL.md.tmpl +0 -199
  411. package/skills/tfx-prune/skill.json +0 -12
  412. package/skills/tfx-psmux-rules/SKILL.md.tmpl +0 -317
  413. package/skills/tfx-psmux-rules/skill.json +0 -8
  414. package/skills/tfx-qa/skill.json +0 -11
  415. package/skills/tfx-ralph/SKILL.md.tmpl +0 -27
  416. package/skills/tfx-ralph/skill.json +0 -8
  417. package/skills/tfx-remote-setup/SKILL.md.tmpl +0 -576
  418. package/skills/tfx-remote-setup/skill.json +0 -8
  419. package/skills/tfx-remote-spawn/SKILL.md.tmpl +0 -263
  420. package/skills/tfx-remote-spawn/skill.json +0 -9
  421. package/skills/tfx-research/skill.json +0 -13
  422. package/skills/tfx-review/skill.json +0 -11
  423. package/skills/tfx-setup/SKILL.md.tmpl +0 -380
  424. package/skills/tfx-setup/skill.json +0 -8
  425. package/skills/tfx-swarm/SKILL.md.tmpl +0 -154
  426. package/skills/tfx-swarm/skill.json +0 -5
@@ -0,0 +1,149 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { existsSync, readFileSync } from "node:fs";
4
+ import { fileURLToPath } from "node:url";
5
+
6
+ import {
7
+ CACHE_TARGETS,
8
+ checkSearchEngines,
9
+ extractProjectMeta,
10
+ probeTierEnvironment,
11
+ resolveTargetPath,
12
+ scanCodexSkills,
13
+ } from "./cache-warmup.mjs";
14
+
15
+ const TARGET_PAYLOAD_BUILDERS = Object.freeze({
16
+ codexSkills: scanCodexSkills,
17
+ tierEnvironment: probeTierEnvironment,
18
+ projectMeta: extractProjectMeta,
19
+ searchEngines: checkSearchEngines,
20
+ });
21
+
22
+ const VOLATILE_KEYS = new Set([
23
+ "timestamp",
24
+ "scanned_at",
25
+ "probed_at",
26
+ "extracted_at",
27
+ "checked_at",
28
+ "generated_at",
29
+ "built_at",
30
+ ]);
31
+
32
+ function normalizeValue(value) {
33
+ if (Array.isArray(value)) {
34
+ return value.map((item) => normalizeValue(item));
35
+ }
36
+ if (value && typeof value === "object") {
37
+ const normalized = {};
38
+ for (const key of Object.keys(value).sort()) {
39
+ if (VOLATILE_KEYS.has(key)) continue;
40
+ normalized[key] = normalizeValue(value[key]);
41
+ }
42
+ return normalized;
43
+ }
44
+ return value;
45
+ }
46
+
47
+ function inspectTarget(target, options = {}) {
48
+ const filePath = resolveTargetPath(target, options);
49
+ if (!existsSync(filePath)) {
50
+ return { target, status: "missing", file: filePath };
51
+ }
52
+
53
+ let parsed;
54
+ try {
55
+ parsed = JSON.parse(readFileSync(filePath, "utf8"));
56
+ } catch (error) {
57
+ return {
58
+ target,
59
+ status: "invalid",
60
+ file: filePath,
61
+ error: error.message,
62
+ };
63
+ }
64
+
65
+ const expected = TARGET_PAYLOAD_BUILDERS[target](options);
66
+ const currentComparable = JSON.stringify(normalizeValue(parsed));
67
+ const expectedComparable = JSON.stringify(normalizeValue(expected));
68
+
69
+ if (currentComparable !== expectedComparable) {
70
+ return {
71
+ target,
72
+ status: "mismatch",
73
+ file: filePath,
74
+ };
75
+ }
76
+
77
+ return {
78
+ target,
79
+ status: "ok",
80
+ file: filePath,
81
+ };
82
+ }
83
+
84
+ export function verifyCaches(options = {}) {
85
+ const targets = options.targets?.length ? options.targets : Object.keys(CACHE_TARGETS);
86
+ const results = targets.map((target) => inspectTarget(target, options));
87
+ const issueCount = results.filter((result) => result.status !== "ok").length;
88
+
89
+ return {
90
+ ok: issueCount === 0,
91
+ issue_count: issueCount,
92
+ results,
93
+ };
94
+ }
95
+
96
+ export async function fixCaches(options = {}) {
97
+ const verification = options.verification || verifyCaches(options);
98
+ const brokenTargets = verification.results
99
+ .filter((result) => result.status !== "ok")
100
+ .map((result) => result.target);
101
+
102
+ if (brokenTargets.length === 0) {
103
+ return {
104
+ ok: true,
105
+ fixed: [],
106
+ summary: { ok: true, built: 0, skipped: 0, failed: 0, results: [] },
107
+ };
108
+ }
109
+
110
+ const warmup = await import("./cache-warmup.mjs");
111
+ const summary = warmup.buildAll({
112
+ ...options,
113
+ force: true,
114
+ targets: brokenTargets,
115
+ });
116
+
117
+ return {
118
+ ok: summary.ok,
119
+ fixed: brokenTargets,
120
+ summary,
121
+ };
122
+ }
123
+
124
+ function formatVerificationSummary(verification) {
125
+ const label = verification.ok ? "cache-doctor: ok" : "cache-doctor: issues";
126
+ const details = verification.results.map((result) => `${result.target}:${result.status}`);
127
+ return `${label} (${details.join(", ")})`;
128
+ }
129
+
130
+ async function main() {
131
+ const shouldFix = process.argv.includes("--fix");
132
+ const verification = verifyCaches();
133
+
134
+ if (!shouldFix) {
135
+ console.log(formatVerificationSummary(verification));
136
+ if (!verification.ok) process.exitCode = 1;
137
+ return;
138
+ }
139
+
140
+ const repair = await fixCaches({ verification });
141
+ const repaired = repair.fixed.length > 0 ? `fixed:${repair.fixed.join(",")}` : "fixed:none";
142
+ const suffix = repair.summary.results.map((result) => `${result.target}:${result.status}`).join(", ");
143
+ console.log(`cache-doctor: fix (${repaired}${suffix ? `, ${suffix}` : ""})`);
144
+ if (!repair.ok) process.exitCode = 1;
145
+ }
146
+
147
+ if (process.argv[1] && fileURLToPath(import.meta.url) === process.argv[1]) {
148
+ await main();
149
+ }
@@ -0,0 +1,557 @@
1
+ #!/usr/bin/env node
2
+
3
+ import {
4
+ existsSync,
5
+ mkdirSync,
6
+ readFileSync,
7
+ readdirSync,
8
+ statSync,
9
+ writeFileSync,
10
+ } from "node:fs";
11
+ import { execSync } from "node:child_process";
12
+ import { join, basename, dirname } from "node:path";
13
+ import { homedir } from "node:os";
14
+ import { fileURLToPath } from "node:url";
15
+
16
+ import { readPreflightCache } from "./preflight-cache.mjs";
17
+ import { checkCliSync, checkHub, detectCodexAuthState } from "./lib/env-probe.mjs";
18
+ import { SEARCH_SERVER_ORDER, MCP_SERVER_DOMAIN_TAGS } from "./lib/mcp-server-catalog.mjs";
19
+
20
+ export const DEFAULT_CACHE_TTL_MS = 5 * 60 * 1000;
21
+ const WARMUP_METADATA_FILE = ["state", "warmup-metadata.json"];
22
+ const AUTH_SENSITIVE_TARGETS = new Set(["codexSkills", "tierEnvironment", "searchEngines"]);
23
+
24
+ export const CACHE_TARGETS = Object.freeze({
25
+ codexSkills: Object.freeze({
26
+ key: "codexSkills",
27
+ file: ["cache", "codex-skills.json"],
28
+ }),
29
+ tierEnvironment: Object.freeze({
30
+ key: "tierEnvironment",
31
+ file: ["state", "tier-environment.json"],
32
+ }),
33
+ projectMeta: Object.freeze({
34
+ key: "projectMeta",
35
+ file: ["cache", "project-meta.json"],
36
+ }),
37
+ searchEngines: Object.freeze({
38
+ key: "searchEngines",
39
+ file: ["state", "search-engines.json"],
40
+ }),
41
+ });
42
+
43
+ const ROLE_KEYWORDS = {
44
+ plan: ["plan", "계획", "decompos", "strategy", "설계"],
45
+ auto: ["autonomous", "자율", "auto-execute", "autopilot", "full auto"],
46
+ persist: ["loop", "반복", "completion", "persist", "until", "끝까지"],
47
+ investigate: ["investigate", "research", "조사", "분석", "analysis"],
48
+ review: ["review", "리뷰", "inspect", "검수"],
49
+ };
50
+
51
+ function resolveHomeDir(homeDir = homedir()) {
52
+ return homeDir;
53
+ }
54
+
55
+ function resolveRootDirs(cwd = process.cwd()) {
56
+ const omcDir = join(cwd, ".omc");
57
+ return {
58
+ cwd,
59
+ omcDir,
60
+ cacheDir: join(omcDir, "cache"),
61
+ stateDir: join(omcDir, "state"),
62
+ };
63
+ }
64
+
65
+ function ensureDir(dirPath) {
66
+ mkdirSync(dirPath, { recursive: true });
67
+ }
68
+
69
+ function writeJSON(filePath, payload) {
70
+ ensureDir(dirname(filePath));
71
+ writeFileSync(filePath, `${JSON.stringify(payload, null, 2)}\n`, "utf8");
72
+ }
73
+
74
+ function normalizeTargets(targets) {
75
+ if (!targets?.length) return Object.keys(CACHE_TARGETS);
76
+ const allowed = new Set(Object.keys(CACHE_TARGETS));
77
+ return [...new Set(targets)].filter((target) => allowed.has(target));
78
+ }
79
+
80
+ export function resolveTargetPath(target, { cwd = process.cwd() } = {}) {
81
+ const spec = CACHE_TARGETS[target];
82
+ if (!spec) throw new Error(`unknown cache target: ${target}`);
83
+
84
+ const { omcDir } = resolveRootDirs(cwd);
85
+ return join(omcDir, ...spec.file);
86
+ }
87
+
88
+ function resolveWarmupMetadataPath({ cwd = process.cwd() } = {}) {
89
+ const { omcDir } = resolveRootDirs(cwd);
90
+ return join(omcDir, ...WARMUP_METADATA_FILE);
91
+ }
92
+
93
+ function readWarmupMetadata(options = {}) {
94
+ const metadataPath = resolveWarmupMetadataPath(options);
95
+ if (!existsSync(metadataPath)) return null;
96
+ try {
97
+ return JSON.parse(readFileSync(metadataPath, "utf8"));
98
+ } catch {
99
+ return null;
100
+ }
101
+ }
102
+
103
+ function resolveTtlMs(target, options = {}) {
104
+ if (Number.isFinite(options.ttlByTarget?.[target])) {
105
+ return Math.max(0, Math.trunc(options.ttlByTarget[target]));
106
+ }
107
+ if (Number.isFinite(options.ttlMs)) {
108
+ return Math.max(0, Math.trunc(options.ttlMs));
109
+ }
110
+ return DEFAULT_CACHE_TTL_MS;
111
+ }
112
+
113
+ function isFresh(target, options = {}) {
114
+ const filePath = resolveTargetPath(target, options);
115
+ if (!existsSync(filePath)) return false;
116
+
117
+ try {
118
+ const ttlMs = resolveTtlMs(target, options);
119
+ const now = options.now ?? Date.now();
120
+ const stat = statSync(filePath);
121
+ return ttlMs > 0 && (now - stat.mtimeMs) < ttlMs;
122
+ } catch {
123
+ return false;
124
+ }
125
+ }
126
+
127
+ function classifyRole(description) {
128
+ const lower = (description || "").toLowerCase();
129
+ for (const [role, keywords] of Object.entries(ROLE_KEYWORDS)) {
130
+ if (keywords.some((keyword) => lower.includes(keyword))) return role;
131
+ }
132
+ return "general";
133
+ }
134
+
135
+ function parseSkillFrontmatter(content) {
136
+ const match = content.match(/^---\s*\n([\s\S]*?)\n---/);
137
+ if (!match) return null;
138
+
139
+ const frontmatter = match[1];
140
+ const name = frontmatter.match(/^name:\s*(.+)$/m)?.[1]?.trim() || null;
141
+ const description = frontmatter.match(/^description:\s*(.+)$/m)?.[1]?.trim() || null;
142
+ return name ? { name, description } : null;
143
+ }
144
+
145
+ export function scanCodexSkills(options = {}) {
146
+ const homeDir = resolveHomeDir(options.homeDir);
147
+ const codexSkillsDir = join(homeDir, ".codex", "skills");
148
+ const skills = [];
149
+
150
+ if (existsSync(codexSkillsDir)) {
151
+ for (const entry of readdirSync(codexSkillsDir, { withFileTypes: true })) {
152
+ if (!entry.isDirectory()) continue;
153
+
154
+ const skillMd = join(codexSkillsDir, entry.name, "SKILL.md");
155
+ if (!existsSync(skillMd)) continue;
156
+
157
+ try {
158
+ const content = readFileSync(skillMd, "utf8");
159
+ const frontmatter = parseSkillFrontmatter(content);
160
+ const name = frontmatter?.name || entry.name;
161
+ const description = frontmatter?.description || "";
162
+ skills.push({
163
+ name,
164
+ role: classifyRole(description),
165
+ description: description.slice(0, 200),
166
+ source: "custom",
167
+ path: skillMd,
168
+ });
169
+ } catch {
170
+ skills.push({
171
+ name: entry.name,
172
+ role: "general",
173
+ description: "",
174
+ source: "custom",
175
+ path: skillMd,
176
+ });
177
+ }
178
+ }
179
+ }
180
+
181
+ const builtinSkills = [
182
+ { name: "web-clone", role: "general", description: "Clone and analyze web pages" },
183
+ { name: "help", role: "general", description: "Show available commands" },
184
+ { name: "note", role: "general", description: "Save notes during session" },
185
+ { name: "worker", role: "auto", description: "Spawn background worker for tasks" },
186
+ ];
187
+
188
+ for (const builtin of builtinSkills) {
189
+ if (skills.some((skill) => skill.name === builtin.name)) continue;
190
+ if (existsSync(join(codexSkillsDir, builtin.name))) continue;
191
+ skills.push({ ...builtin, source: "builtin" });
192
+ }
193
+
194
+ skills.sort((left, right) => left.name.localeCompare(right.name));
195
+
196
+ return {
197
+ scanned_at: new Date(options.now ?? Date.now()).toISOString(),
198
+ codex_skills_dir: codexSkillsDir,
199
+ total: skills.length,
200
+ skills,
201
+ };
202
+ }
203
+
204
+ export function probeTierEnvironment(options = {}) {
205
+ const homeDir = resolveHomeDir(options.homeDir);
206
+ const preflight = options.preflight ?? readPreflightCache();
207
+ const execSyncFn = options.execSyncFn || execSync;
208
+ const codexAuth = preflight?.codex_plan ?? detectCodexAuthState({ homeDir });
209
+
210
+ const codexCheck = preflight?.codex || checkCliSync("codex", { whichCommandFn: options.whichCommandFn });
211
+ const geminiCheck = preflight?.gemini || checkCliSync("gemini", { whichCommandFn: options.whichCommandFn });
212
+ const hubCheck = preflight?.hub || checkHub({
213
+ pkgRoot: options.pkgRoot,
214
+ restart: options.hubRestart === true,
215
+ requestTimeoutMs: options.hubTimeoutMs ?? 1000,
216
+ pollAttempts: options.hubRestart === true ? 8 : 0,
217
+ execSyncFn,
218
+ });
219
+ const checks = {
220
+ psmux: false,
221
+ hub: !!hubCheck?.ok,
222
+ codex: !!codexCheck?.ok,
223
+ gemini: !!geminiCheck?.ok,
224
+ wt: false,
225
+ };
226
+
227
+ try {
228
+ execSyncFn("psmux --version", {
229
+ stdio: "ignore",
230
+ timeout: 2000,
231
+ windowsHide: true,
232
+ });
233
+ checks.psmux = true;
234
+ } catch {}
235
+
236
+ if (process.platform === "win32") {
237
+ try {
238
+ execSyncFn("where wt.exe", {
239
+ stdio: "ignore",
240
+ timeout: 2000,
241
+ windowsHide: true,
242
+ });
243
+ checks.wt = true;
244
+ } catch {}
245
+ }
246
+
247
+ let tier = "minimal";
248
+ if (checks.codex || checks.gemini) tier = "standard";
249
+ if (checks.psmux && checks.hub && (checks.codex || checks.gemini)) tier = "full";
250
+
251
+ const agents = ["claude"];
252
+ if (checks.codex) agents.push("codex");
253
+ if (checks.gemini) agents.push("gemini");
254
+
255
+ return {
256
+ probed_at: new Date(options.now ?? Date.now()).toISOString(),
257
+ tier,
258
+ checks,
259
+ available_agents: agents,
260
+ codex_plan: codexAuth.source == null
261
+ ? { plan: codexAuth.plan }
262
+ : { plan: codexAuth.plan, source: codexAuth.source },
263
+ source: {
264
+ preflight: !!preflight,
265
+ home_dir: homeDir,
266
+ hub_state: hubCheck?.state || "unknown",
267
+ },
268
+ };
269
+ }
270
+
271
+ function getCodexAuthFingerprint(options = {}) {
272
+ if (typeof options.preflight?.codex_plan?.fingerprint === "string") {
273
+ return options.preflight.codex_plan.fingerprint;
274
+ }
275
+ return detectCodexAuthState({ homeDir: resolveHomeDir(options.homeDir) }).fingerprint;
276
+ }
277
+
278
+ function hasAuthFingerprintChanged(target, options = {}) {
279
+ if (!AUTH_SENSITIVE_TARGETS.has(target)) return false;
280
+ const nextFingerprint = getCodexAuthFingerprint(options);
281
+ const previousFingerprint = readWarmupMetadata(options)?.codex_auth_fingerprint || null;
282
+ if (previousFingerprint === null) return false;
283
+ return previousFingerprint !== nextFingerprint;
284
+ }
285
+
286
+ export function extractProjectMeta(options = {}) {
287
+ const cwd = options.cwd || process.cwd();
288
+ const execSyncFn = options.execSyncFn || execSync;
289
+
290
+ let name = basename(cwd);
291
+ let description = "";
292
+ let lang = "unknown";
293
+ let testCmd = null;
294
+ let isGit = false;
295
+
296
+ try {
297
+ const toplevel = execSyncFn("git rev-parse --show-toplevel", {
298
+ encoding: "utf8",
299
+ timeout: 3000,
300
+ windowsHide: true,
301
+ cwd,
302
+ stdio: ["pipe", "pipe", "ignore"],
303
+ }).trim();
304
+ name = basename(toplevel);
305
+ isGit = true;
306
+ } catch {}
307
+
308
+ const packageJsonPath = join(cwd, "package.json");
309
+ if (existsSync(packageJsonPath)) {
310
+ try {
311
+ const pkg = JSON.parse(readFileSync(packageJsonPath, "utf8"));
312
+ name = pkg.name || name;
313
+ description = pkg.description || "";
314
+ testCmd = pkg.scripts?.test || null;
315
+ lang = "JavaScript/ESM (Node.js)";
316
+ } catch {}
317
+ } else if (existsSync(join(cwd, "pyproject.toml")) || existsSync(join(cwd, "setup.py"))) {
318
+ lang = "Python";
319
+ } else if (existsSync(join(cwd, "Cargo.toml"))) {
320
+ lang = "Rust";
321
+ } else if (existsSync(join(cwd, "go.mod"))) {
322
+ lang = "Go";
323
+ }
324
+
325
+ return {
326
+ extracted_at: new Date(options.now ?? Date.now()).toISOString(),
327
+ name,
328
+ description: description.slice(0, 300),
329
+ lang,
330
+ test_cmd: testCmd,
331
+ is_git: isGit,
332
+ };
333
+ }
334
+
335
+ function loadMcpInventory(options = {}) {
336
+ const inventoryPath = join(resolveHomeDir(options.homeDir), ".claude", "cache", "mcp-inventory.json");
337
+ try {
338
+ return JSON.parse(readFileSync(inventoryPath, "utf8"));
339
+ } catch {
340
+ return null;
341
+ }
342
+ }
343
+
344
+ function loadMcpConfigs(options = {}) {
345
+ const cwd = options.cwd || process.cwd();
346
+ const homeDir = resolveHomeDir(options.homeDir);
347
+ const configPaths = [
348
+ join(homeDir, ".claude", "settings.json"),
349
+ join(homeDir, ".claude", "settings.local.json"),
350
+ join(cwd, ".claude", "mcp.json"),
351
+ join(cwd, ".mcp.json"),
352
+ ];
353
+
354
+ const servers = {};
355
+
356
+ for (const configPath of configPaths) {
357
+ try {
358
+ const data = JSON.parse(readFileSync(configPath, "utf8"));
359
+ const mcpServers = data.mcpServers || {};
360
+ for (const [name, config] of Object.entries(mcpServers)) {
361
+ servers[name] = {
362
+ configured: true,
363
+ source: basename(configPath),
364
+ ...config,
365
+ };
366
+ }
367
+ } catch {}
368
+ }
369
+
370
+ return servers;
371
+ }
372
+
373
+ export function checkSearchEngines(options = {}) {
374
+ const inventory = options.inventory ?? loadMcpInventory(options);
375
+ const configuredServers = options.configuredServers ?? loadMcpConfigs(options);
376
+ const engines = [];
377
+
378
+ const knownSearchServers = [...SEARCH_SERVER_ORDER, "context7"];
379
+ const allServerNames = new Set(knownSearchServers);
380
+
381
+ if (inventory) {
382
+ for (const scope of ["codex", "gemini", "claude"]) {
383
+ const scopeData = inventory[scope];
384
+ if (!scopeData?.servers) continue;
385
+ for (const server of scopeData.servers) {
386
+ const tags = server.domain_tags || MCP_SERVER_DOMAIN_TAGS[server.name] || [];
387
+ if (tags.includes("search") || tags.includes("web") || tags.includes("research")) {
388
+ allServerNames.add(server.name);
389
+ }
390
+ }
391
+ }
392
+ }
393
+
394
+ for (const name of Object.keys(configuredServers)) {
395
+ const tags = MCP_SERVER_DOMAIN_TAGS[name] || [];
396
+ if (tags.includes("search") || tags.includes("web") || knownSearchServers.includes(name)) {
397
+ allServerNames.add(name);
398
+ }
399
+ }
400
+
401
+ for (const name of allServerNames) {
402
+ const configured = !!configuredServers[name];
403
+ const tags = MCP_SERVER_DOMAIN_TAGS[name] || [];
404
+
405
+ let inventoryStatus = null;
406
+ if (inventory) {
407
+ for (const scope of ["codex", "gemini", "claude"]) {
408
+ const server = inventory[scope]?.servers?.find((item) => item.name === name);
409
+ if (server) {
410
+ inventoryStatus = {
411
+ scope,
412
+ status: server.status,
413
+ tool_count: server.tool_count,
414
+ };
415
+ break;
416
+ }
417
+ }
418
+ }
419
+
420
+ let status = "unavailable";
421
+ if (inventoryStatus?.status === "enabled" || inventoryStatus?.status === "configured") {
422
+ status = "available";
423
+ } else if (configured) {
424
+ status = "configured";
425
+ }
426
+
427
+ engines.push({
428
+ name,
429
+ status,
430
+ domain_tags: tags,
431
+ configured,
432
+ inventory: inventoryStatus,
433
+ source: configuredServers[name]?.source || null,
434
+ });
435
+ }
436
+
437
+ engines.sort((left, right) => {
438
+ const leftIndex = SEARCH_SERVER_ORDER.indexOf(left.name);
439
+ const rightIndex = SEARCH_SERVER_ORDER.indexOf(right.name);
440
+ if (leftIndex !== -1 && rightIndex !== -1) return leftIndex - rightIndex;
441
+ if (leftIndex !== -1) return -1;
442
+ if (rightIndex !== -1) return 1;
443
+ return left.name.localeCompare(right.name);
444
+ });
445
+
446
+ const available = engines.filter((engine) => engine.status === "available");
447
+
448
+ return {
449
+ checked_at: new Date(options.now ?? Date.now()).toISOString(),
450
+ primary_engine: available[0]?.name || null,
451
+ available_count: available.length,
452
+ total_count: engines.length,
453
+ engines,
454
+ };
455
+ }
456
+
457
+ function buildTarget(target, options = {}) {
458
+ const filePath = resolveTargetPath(target, options);
459
+ if (!options.force && isFresh(target, options) && !hasAuthFingerprintChanged(target, options)) {
460
+ return { target, status: "skipped", file: filePath, reason: "fresh" };
461
+ }
462
+
463
+ let payload;
464
+ if (target === "codexSkills") payload = scanCodexSkills(options);
465
+ else if (target === "tierEnvironment") payload = probeTierEnvironment(options);
466
+ else if (target === "projectMeta") payload = extractProjectMeta(options);
467
+ else if (target === "searchEngines") payload = checkSearchEngines(options);
468
+ else throw new Error(`unknown cache target: ${target}`);
469
+
470
+ writeJSON(filePath, payload);
471
+ return { target, status: "built", file: filePath, payload };
472
+ }
473
+
474
+ export function buildCodexSkills(options = {}) {
475
+ return buildTarget("codexSkills", options);
476
+ }
477
+
478
+ export function buildTierEnvironment(options = {}) {
479
+ return buildTarget("tierEnvironment", options);
480
+ }
481
+
482
+ export function buildProjectMeta(options = {}) {
483
+ return buildTarget("projectMeta", options);
484
+ }
485
+
486
+ export function buildSearchEngines(options = {}) {
487
+ return buildTarget("searchEngines", options);
488
+ }
489
+
490
+ export function buildAll(options = {}) {
491
+ const targets = normalizeTargets(options.targets);
492
+ const dirs = resolveRootDirs(options.cwd);
493
+ ensureDir(dirs.cacheDir);
494
+ ensureDir(dirs.stateDir);
495
+
496
+ const results = [];
497
+ for (const target of targets) {
498
+ try {
499
+ results.push(buildTarget(target, options));
500
+ } catch (error) {
501
+ results.push({
502
+ target,
503
+ status: "failed",
504
+ file: resolveTargetPath(target, options),
505
+ error: error.message,
506
+ });
507
+ }
508
+ }
509
+
510
+ const built = results.filter((result) => result.status === "built").length;
511
+ const skipped = results.filter((result) => result.status === "skipped").length;
512
+ const failed = results.filter((result) => result.status === "failed").length;
513
+ const authFingerprint = getCodexAuthFingerprint(options);
514
+
515
+ if (failed === 0) {
516
+ writeJSON(resolveWarmupMetadataPath(options), {
517
+ updated_at: new Date(options.now ?? Date.now()).toISOString(),
518
+ codex_auth_fingerprint: authFingerprint,
519
+ targets,
520
+ });
521
+ }
522
+
523
+ return {
524
+ ok: failed === 0,
525
+ built,
526
+ skipped,
527
+ failed,
528
+ results,
529
+ };
530
+ }
531
+
532
+ export function formatBuildSummary(summary, { label = "cache-warmup" } = {}) {
533
+ const details = summary.results
534
+ .filter((result) => result.status !== "failed")
535
+ .map((result) => `${result.target}:${result.status}`);
536
+
537
+ if (summary.failed > 0) {
538
+ const errors = summary.results
539
+ .filter((result) => result.status === "failed")
540
+ .map((result) => `${result.target}:failed`);
541
+ return `${label}: partial (${[...details, ...errors].join(", ")})`;
542
+ }
543
+
544
+ return `${label}: ok (${details.join(", ")})`;
545
+ }
546
+
547
+ export async function runCli(options = {}) {
548
+ const force = options.force ?? process.argv.includes("--force");
549
+ const summary = buildAll({ ...options, force });
550
+ console.log(formatBuildSummary(summary));
551
+ if (!summary.ok) process.exitCode = 1;
552
+ return summary;
553
+ }
554
+
555
+ if (process.argv[1] && fileURLToPath(import.meta.url) === process.argv[1]) {
556
+ await runCli();
557
+ }