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,8 +1,14 @@
1
- import { existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from 'node:fs';
2
- import { homedir } from 'node:os';
3
- import { join } from 'node:path';
1
+ import {
2
+ existsSync,
3
+ mkdirSync,
4
+ readFileSync,
5
+ rmSync,
6
+ writeFileSync,
7
+ } from "node:fs";
8
+ import { homedir } from "node:os";
9
+ import { join } from "node:path";
4
10
 
5
- const SESSION_FILE = 'adaptive-session.json';
11
+ const SESSION_FILE = "adaptive-session.json";
6
12
  const DEFAULT_CONFIDENCE = 0.5;
7
13
  const TIER2_DECAY_STEP = 0.2;
8
14
  const TIER2_DECAY_INTERVAL = 5;
@@ -11,24 +17,67 @@ const TIER3_WARN_THRESHOLD = 10;
11
17
  const TIER3_REMOVE_THRESHOLD = 20;
12
18
 
13
19
  const clone = (v) => (v == null ? v : JSON.parse(JSON.stringify(v)));
14
- const clamp01 = (v) => { const n = Number(v); return Number.isFinite(n) ? Number(Math.max(0, Math.min(1, n)).toFixed(4)) : DEFAULT_CONFIDENCE; };
15
- const toDate = (v = Date.now()) => { const d = new Date(v); return Number.isNaN(d.getTime()) ? new Date().toISOString().slice(0, 10) : d.toISOString().slice(0, 10); };
16
- const uniq = (arr) => [...new Set(arr.filter((s) => typeof s === 'string' && s.trim()))];
17
- const slugify = (v) => String(v || '').trim().toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-+|-+$/g, '').slice(0, 80);
18
- const buildId = (r) => { const e = slugify(r.id); if (e) return e; const p = slugify(r.pattern); return p || `adaptive-${Date.now()}`; };
19
- const readJson = (f, fb) => { if (!existsSync(f)) return clone(fb); try { return { ...clone(fb), ...JSON.parse(readFileSync(f, 'utf8')) }; } catch { return clone(fb); } };
20
- const writeJson = (f, v) => writeFileSync(f, `${JSON.stringify(v, null, 2)}\n`, 'utf8');
21
- const strip = (r) => { if (!r) return null; const { sessionIds, ...pub } = r; return clone(pub); };
22
- const sortRules = (list) => [...list].sort((a, b) => a.tier - b.tier || b.confidence - a.confidence || a.id.localeCompare(b.id));
20
+ const clamp01 = (v) => {
21
+ const n = Number(v);
22
+ return Number.isFinite(n)
23
+ ? Number(Math.max(0, Math.min(1, n)).toFixed(4))
24
+ : DEFAULT_CONFIDENCE;
25
+ };
26
+ const toDate = (v = Date.now()) => {
27
+ const d = new Date(v);
28
+ return Number.isNaN(d.getTime())
29
+ ? new Date().toISOString().slice(0, 10)
30
+ : d.toISOString().slice(0, 10);
31
+ };
32
+ const uniq = (arr) => [
33
+ ...new Set(arr.filter((s) => typeof s === "string" && s.trim())),
34
+ ];
35
+ const slugify = (v) =>
36
+ String(v || "")
37
+ .trim()
38
+ .toLowerCase()
39
+ .replace(/[^a-z0-9]+/g, "-")
40
+ .replace(/^-+|-+$/g, "")
41
+ .slice(0, 80);
42
+ const buildId = (r) => {
43
+ const e = slugify(r.id);
44
+ if (e) return e;
45
+ const p = slugify(r.pattern);
46
+ return p || `adaptive-${Date.now()}`;
47
+ };
48
+ const readJson = (f, fb) => {
49
+ if (!existsSync(f)) return clone(fb);
50
+ try {
51
+ return { ...clone(fb), ...JSON.parse(readFileSync(f, "utf8")) };
52
+ } catch {
53
+ return clone(fb);
54
+ }
55
+ };
56
+ const writeJson = (f, v) =>
57
+ writeFileSync(f, `${JSON.stringify(v, null, 2)}\n`, "utf8");
58
+ const strip = (r) => {
59
+ if (!r) return null;
60
+ const { sessionIds, ...pub } = r;
61
+ return clone(pub);
62
+ };
63
+ const sortRules = (list) =>
64
+ [...list].sort(
65
+ (a, b) =>
66
+ a.tier - b.tier ||
67
+ b.confidence - a.confidence ||
68
+ a.id.localeCompare(b.id),
69
+ );
23
70
  const upsert = (list, r) => [...list.filter((x) => x.id !== r.id), r];
24
71
  const without = (list, id) => list.filter((x) => x.id !== id);
25
72
 
26
73
  function toRule(rule, tier, sessionId, existing = null) {
27
74
  return {
28
75
  id: existing?.id || buildId(rule),
29
- pattern: String(rule.pattern || existing?.pattern || ''),
30
- rootCause: String(rule.rootCause || rule.root_cause || existing?.rootCause || ''),
31
- rule: String(rule.rule || existing?.rule || ''),
76
+ pattern: String(rule.pattern || existing?.pattern || ""),
77
+ rootCause: String(
78
+ rule.rootCause || rule.root_cause || existing?.rootCause || "",
79
+ ),
80
+ rule: String(rule.rule || existing?.rule || ""),
32
81
  confidence: clamp01(rule.confidence ?? existing?.confidence),
33
82
  occurrences: Math.max(1, Number(existing?.occurrences || 0) + 1),
34
83
  firstSeen: existing?.firstSeen || toDate(rule.timestamp),
@@ -42,10 +91,10 @@ function toRule(rule, tier, sessionId, existing = null) {
42
91
 
43
92
  export function createAdaptiveMemory(opts = {}) {
44
93
  const projectSlug = slugify(opts.projectSlug);
45
- if (!projectSlug) throw new Error('projectSlug is required');
94
+ if (!projectSlug) throw new Error("projectSlug is required");
46
95
 
47
- const sessionDir = opts.sessionDir || join(process.cwd(), '.omc', 'state');
48
- const globalDir = opts.globalDir || join(homedir(), '.triflux', 'adaptive');
96
+ const sessionDir = opts.sessionDir || join(process.cwd(), ".omc", "state");
97
+ const globalDir = opts.globalDir || join(homedir(), ".triflux", "adaptive");
49
98
  const sessionFile = join(sessionDir, SESSION_FILE);
50
99
  const projectFile = join(globalDir, `${projectSlug}.json`);
51
100
 
@@ -53,34 +102,58 @@ export function createAdaptiveMemory(opts = {}) {
53
102
  mkdirSync(globalDir, { recursive: true });
54
103
 
55
104
  let ss = readJson(sessionFile, { projectSlug, sessionId: null, rules: [] });
56
- let ps = readJson(projectFile, { projectSlug, history: {}, tier2: [], tier3: [] });
105
+ let ps = readJson(projectFile, {
106
+ projectSlug,
107
+ history: {},
108
+ tier2: [],
109
+ tier3: [],
110
+ });
57
111
 
58
112
  function saveSession() {
59
- if (ss.rules.length === 0) { rmSync(sessionFile, { force: true }); return; }
113
+ if (ss.rules.length === 0) {
114
+ rmSync(sessionFile, { force: true });
115
+ return;
116
+ }
60
117
  writeJson(sessionFile, ss);
61
118
  }
62
119
 
63
120
  function saveProject() {
64
- const has = Object.keys(ps.history).length > 0 || ps.tier2.length > 0 || ps.tier3.length > 0;
65
- if (!has) { rmSync(projectFile, { force: true }); return; }
121
+ const has =
122
+ Object.keys(ps.history).length > 0 ||
123
+ ps.tier2.length > 0 ||
124
+ ps.tier3.length > 0;
125
+ if (!has) {
126
+ rmSync(projectFile, { force: true });
127
+ return;
128
+ }
66
129
  writeJson(projectFile, ps);
67
130
  }
68
131
 
69
- const saveAll = () => { saveSession(); saveProject(); };
132
+ const saveAll = () => {
133
+ saveSession();
134
+ saveProject();
135
+ };
70
136
 
71
137
  function getSessionId(id) {
72
- const next = String(id || ss.sessionId || 'session-current');
138
+ const next = String(id || ss.sessionId || "session-current");
73
139
  ss = { ...ss, sessionId: next };
74
140
  return next;
75
141
  }
76
142
 
77
- const getDurable = (id) => ps.tier3.find((r) => r.id === id) || ps.tier2.find((r) => r.id === id) || null;
143
+ const getDurable = (id) =>
144
+ ps.tier3.find((r) => r.id === id) ||
145
+ ps.tier2.find((r) => r.id === id) ||
146
+ null;
78
147
 
79
148
  function promote(ruleId) {
80
149
  const t2 = ps.tier2.find((r) => r.id === ruleId);
81
150
  if (t2 && t2.occurrences >= 3 && t2.confidence >= 0.8) {
82
151
  const next = { ...t2, tier: 3, sessionsWithout: 0 };
83
- ps = { ...ps, tier2: without(ps.tier2, ruleId), tier3: upsert(ps.tier3, next) };
152
+ ps = {
153
+ ...ps,
154
+ tier2: without(ps.tier2, ruleId),
155
+ tier3: upsert(ps.tier3, next),
156
+ };
84
157
  saveProject();
85
158
  return { rule: strip(next), promoted: true, fromTier: 2, toTier: 3 };
86
159
  }
@@ -94,44 +167,80 @@ export function createAdaptiveMemory(opts = {}) {
94
167
  return { rule: strip(next), promoted: true, fromTier: 1, toTier: 2 };
95
168
  }
96
169
  const cur = getDurable(ruleId) || ps.history[ruleId] || null;
97
- return { rule: strip(cur), promoted: false, fromTier: cur?.tier ?? null, toTier: cur?.tier ?? null };
170
+ return {
171
+ rule: strip(cur),
172
+ promoted: false,
173
+ fromTier: cur?.tier ?? null,
174
+ toTier: cur?.tier ?? null,
175
+ };
98
176
  }
99
177
 
100
178
  function record(rule = {}) {
101
- if (!rule.pattern) return { rule: null, promoted: false, fromTier: null, toTier: null };
179
+ if (!rule.pattern)
180
+ return { rule: null, promoted: false, fromTier: null, toTier: null };
102
181
  const sessionId = getSessionId(rule.sessionId);
103
182
  const ruleId = buildId(rule);
104
183
  const durable = getDurable(ruleId);
105
184
  if (durable) {
106
185
  const next = toRule(rule, durable.tier, sessionId, durable);
107
- ps = durable.tier === 3 ? { ...ps, tier3: upsert(ps.tier3, next) } : { ...ps, tier2: upsert(ps.tier2, next) };
186
+ ps =
187
+ durable.tier === 3
188
+ ? { ...ps, tier3: upsert(ps.tier3, next) }
189
+ : { ...ps, tier2: upsert(ps.tier2, next) };
108
190
  saveProject();
109
191
  const res = promote(ruleId);
110
- return res.promoted ? res : { rule: strip(next), promoted: false, fromTier: durable.tier, toTier: durable.tier };
192
+ return res.promoted
193
+ ? res
194
+ : {
195
+ rule: strip(next),
196
+ promoted: false,
197
+ fromTier: durable.tier,
198
+ toTier: durable.tier,
199
+ };
111
200
  }
112
201
  const cand = toRule(rule, 1, sessionId, ps.history[ruleId]);
113
202
  ps = { ...ps, history: { ...ps.history, [ruleId]: cand } };
114
203
  ss = { ...ss, rules: upsert(ss.rules, { ...cand, tier: 1 }) };
115
204
  saveAll();
116
205
  const res = promote(ruleId);
117
- return res.promoted ? res : { rule: strip(cand), promoted: false, fromTier: 1, toTier: 1 };
206
+ return res.promoted
207
+ ? res
208
+ : { rule: strip(cand), promoted: false, fromTier: 1, toTier: 1 };
118
209
  }
119
210
 
120
211
  function decay(sessionId) {
121
212
  const nextId = String(sessionId || `session-${Date.now()}`);
122
- if (ss.sessionId === nextId) return { sessionId: nextId, tier1Cleared: 0, updated: [], warned: [], removed: [] };
123
- const warned = [], removed = [], updated = [];
213
+ if (ss.sessionId === nextId)
214
+ return {
215
+ sessionId: nextId,
216
+ tier1Cleared: 0,
217
+ updated: [],
218
+ warned: [],
219
+ removed: [],
220
+ };
221
+ const warned = [],
222
+ removed = [],
223
+ updated = [];
124
224
  const tier1Cleared = ss.rules.length;
125
225
  const tier2 = ps.tier2.flatMap((r) => {
126
226
  const sw = Number(r.sessionsWithout || 0) + 1;
127
- const conf = sw % TIER2_DECAY_INTERVAL === 0 ? clamp01(r.confidence - TIER2_DECAY_STEP) : r.confidence;
128
- if (conf < TIER2_REMOVE_THRESHOLD) { removed.push(r.id); return []; }
227
+ const conf =
228
+ sw % TIER2_DECAY_INTERVAL === 0
229
+ ? clamp01(r.confidence - TIER2_DECAY_STEP)
230
+ : r.confidence;
231
+ if (conf < TIER2_REMOVE_THRESHOLD) {
232
+ removed.push(r.id);
233
+ return [];
234
+ }
129
235
  updated.push(r.id);
130
236
  return [{ ...r, sessionsWithout: sw, confidence: conf }];
131
237
  });
132
238
  const tier3 = ps.tier3.flatMap((r) => {
133
239
  const sw = Number(r.sessionsWithout || 0) + 1;
134
- if (sw >= TIER3_REMOVE_THRESHOLD) { removed.push(r.id); return []; }
240
+ if (sw >= TIER3_REMOVE_THRESHOLD) {
241
+ removed.push(r.id);
242
+ return [];
243
+ }
135
244
  if (sw === TIER3_WARN_THRESHOLD) warned.push(r.id);
136
245
  updated.push(r.id);
137
246
  return [{ ...r, sessionsWithout: sw }];
@@ -142,17 +251,22 @@ export function createAdaptiveMemory(opts = {}) {
142
251
  return { sessionId: nextId, tier1Cleared, updated, warned, removed };
143
252
  }
144
253
 
145
- function getRule(id) { return strip(ss.rules.find((r) => r.id === id) || getDurable(id)); }
254
+ function getRule(id) {
255
+ return strip(ss.rules.find((r) => r.id === id) || getDurable(id));
256
+ }
146
257
  function getTier(tier) {
147
258
  if (tier === 1) return sortRules(ss.rules).map(strip);
148
259
  if (tier === 2) return sortRules(ps.tier2).map(strip);
149
260
  if (tier === 3) return sortRules(ps.tier3).map(strip);
150
261
  return [];
151
262
  }
152
- function getAllRules() { return sortRules([...ss.rules, ...ps.tier2, ...ps.tier3]).map(strip); }
153
- function reset(target = 'all') {
154
- const rs = target === 'all' || target === 1 || target === 'session';
155
- const rp = target === 'all' || target === 2 || target === 3 || target === 'project';
263
+ function getAllRules() {
264
+ return sortRules([...ss.rules, ...ps.tier2, ...ps.tier3]).map(strip);
265
+ }
266
+ function reset(target = "all") {
267
+ const rs = target === "all" || target === 1 || target === "session";
268
+ const rp =
269
+ target === "all" || target === 2 || target === 3 || target === "project";
156
270
  if (rs) ss = { ...ss, rules: [] };
157
271
  if (rp) ps = { ...ps, history: {}, tier2: [], tier3: [] };
158
272
  saveAll();
package/hub/adaptive.mjs CHANGED
@@ -1,10 +1,9 @@
1
- import { randomUUID } from 'node:crypto';
2
- import { join } from 'node:path';
3
-
4
- import { createAdaptiveMemory } from './adaptive-memory.mjs';
5
- import { createDiagnosticPipeline } from './adaptive-diagnostic.mjs';
6
- import { createAdaptiveInjector } from './adaptive-inject.mjs';
7
- import { createAdaptiveFingerprintService } from './session-fingerprint.mjs';
1
+ import { randomUUID } from "node:crypto";
2
+ import { join } from "node:path";
3
+ import { createDiagnosticPipeline } from "./adaptive-diagnostic.mjs";
4
+ import { createAdaptiveInjector } from "./adaptive-inject.mjs";
5
+ import { createAdaptiveMemory } from "./adaptive-memory.mjs";
6
+ import { createAdaptiveFingerprintService } from "./session-fingerprint.mjs";
8
7
 
9
8
  let singletonEngine = null;
10
9
 
@@ -17,36 +16,55 @@ function toRuleList(value) {
17
16
  }
18
17
 
19
18
  function resolveTierCount(memory, tier) {
20
- if (typeof memory.getTier === 'function') {
19
+ if (typeof memory.getTier === "function") {
21
20
  const rules = memory.getTier(tier);
22
21
  return Array.isArray(rules) ? rules.length : 0;
23
22
  }
24
- return toRuleList(memory.getAllRules?.()).filter((rule) => Number(rule?.tier) === tier).length;
23
+ return toRuleList(memory.getAllRules?.()).filter(
24
+ (rule) => Number(rule?.tier) === tier,
25
+ ).length;
25
26
  }
26
27
 
27
28
  function resolveActiveRuleIds(memory, decayResult) {
28
- if (Array.isArray(decayResult?.activeRuleIds)) return [...decayResult.activeRuleIds];
29
- return toRuleList(memory.getAllRules?.()).map((rule) => rule.id).filter(Boolean);
29
+ if (Array.isArray(decayResult?.activeRuleIds))
30
+ return [...decayResult.activeRuleIds];
31
+ return toRuleList(memory.getAllRules?.())
32
+ .map((rule) => rule.id)
33
+ .filter(Boolean);
30
34
  }
31
35
 
32
36
  function resolveRecordedRule(recordResult) {
33
- if (recordResult?.rule) return { rule: recordResult.rule, promoted: Boolean(recordResult.promoted) };
37
+ if (recordResult?.rule)
38
+ return {
39
+ rule: recordResult.rule,
40
+ promoted: Boolean(recordResult.promoted),
41
+ };
34
42
  return { rule: recordResult || null, promoted: false };
35
43
  }
36
44
 
37
45
  function createEngineInstance(opts = {}) {
38
46
  const repoRoot = opts.repoRoot || process.cwd();
39
- const claudeMdPath = opts.claudeMdPath || join(repoRoot, 'CLAUDE.md');
40
- const projectSlug = String(opts.projectSlug || 'default').trim() || 'default';
47
+ const claudeMdPath = opts.claudeMdPath || join(repoRoot, "CLAUDE.md");
48
+ const projectSlug = String(opts.projectSlug || "default").trim() || "default";
41
49
  const now = opts.now || (() => Date.now());
42
50
  const sessionIdFactory = opts.sessionIdFactory || (() => randomUUID());
43
51
 
44
- const memory = opts.memory || opts.memoryFactory?.(opts) || createAdaptiveMemory({ projectSlug, ...opts.memoryOptions });
45
- const diagnostic = opts.diagnostic || opts.diagnosticFactory?.(opts) || createDiagnosticPipeline(opts.diagnosticOptions);
46
- const injector = opts.injector || opts.injectorFactory?.(opts) || createAdaptiveInjector({ claudeMdPath, ...opts.injectorOptions });
47
- const fingerprintService = opts.fingerprintService
48
- || opts.fingerprintFactory?.(opts)
49
- || createAdaptiveFingerprintService(opts.fingerprintOptions);
52
+ const memory =
53
+ opts.memory ||
54
+ opts.memoryFactory?.(opts) ||
55
+ createAdaptiveMemory({ projectSlug, ...opts.memoryOptions });
56
+ const diagnostic =
57
+ opts.diagnostic ||
58
+ opts.diagnosticFactory?.(opts) ||
59
+ createDiagnosticPipeline(opts.diagnosticOptions);
60
+ const injector =
61
+ opts.injector ||
62
+ opts.injectorFactory?.(opts) ||
63
+ createAdaptiveInjector({ claudeMdPath, ...opts.injectorOptions });
64
+ const fingerprintService =
65
+ opts.fingerprintService ||
66
+ opts.fingerprintFactory?.(opts) ||
67
+ createAdaptiveFingerprintService(opts.fingerprintOptions);
50
68
 
51
69
  let started = false;
52
70
  let currentSessionId = null;
@@ -57,12 +75,12 @@ function createEngineInstance(opts = {}) {
57
75
  };
58
76
 
59
77
  function refreshFingerprint() {
60
- if (typeof fingerprintService.computeFingerprint !== 'function') return;
78
+ if (typeof fingerprintService.computeFingerprint !== "function") return;
61
79
  const fingerprint = fingerprintService.computeFingerprint({
62
80
  scope: projectSlug,
63
81
  cwd: repoRoot,
64
82
  filePath: claudeMdPath,
65
- workType: 'adaptive',
83
+ workType: "adaptive",
66
84
  timestamp: now(),
67
85
  });
68
86
  lastFingerprintId = fingerprint?.fingerprint_id || lastFingerprintId;
@@ -71,7 +89,10 @@ function createEngineInstance(opts = {}) {
71
89
  function startSession() {
72
90
  if (started) return;
73
91
  currentSessionId = sessionIdFactory();
74
- const decayResult = typeof memory.decay === 'function' ? memory.decay(currentSessionId) : null;
92
+ const decayResult =
93
+ typeof memory.decay === "function"
94
+ ? memory.decay(currentSessionId)
95
+ : null;
75
96
  injector.cleanup?.(resolveActiveRuleIds(memory, decayResult));
76
97
  refreshFingerprint();
77
98
  started = true;
@@ -91,13 +112,15 @@ function createEngineInstance(opts = {}) {
91
112
  }
92
113
 
93
114
  counters.diagnosedErrors += 1;
94
- const { rule: recordedRule, promoted } = resolveRecordedRule(memory.record({
95
- ...diagnosis.rule,
96
- confidence: diagnosis.confidence,
97
- dnaFactor: diagnosis.dnaFactor,
98
- sessionId: currentSessionId,
99
- lastSeen: new Date(now()).toISOString().slice(0, 10),
100
- }));
115
+ const { rule: recordedRule, promoted } = resolveRecordedRule(
116
+ memory.record({
117
+ ...diagnosis.rule,
118
+ confidence: diagnosis.confidence,
119
+ dnaFactor: diagnosis.dnaFactor,
120
+ sessionId: currentSessionId,
121
+ lastSeen: new Date(now()).toISOString().slice(0, 10),
122
+ }),
123
+ );
101
124
 
102
125
  const nextRule = clone(recordedRule || diagnosis.rule);
103
126
  if (nextRule?.tier >= 3 && promoted) {
@@ -127,7 +150,13 @@ function createEngineInstance(opts = {}) {
127
150
  });
128
151
  }
129
152
 
130
- return Object.freeze({ handleError, startSession, endSession, getStats, __lastFingerprintId: () => lastFingerprintId });
153
+ return Object.freeze({
154
+ handleError,
155
+ startSession,
156
+ endSession,
157
+ getStats,
158
+ __lastFingerprintId: () => lastFingerprintId,
159
+ });
131
160
  }
132
161
 
133
162
  export function createAdaptiveEngine(opts = {}) {
@@ -1,11 +1,11 @@
1
1
  // hub/assign-callbacks.mjs — assign job 상태 변경용 Named Pipe/Unix socket 브로드캐스터
2
2
 
3
- import net from 'node:net';
4
- import { existsSync, unlinkSync } from 'node:fs';
5
- import { IS_WINDOWS, pipePath } from './platform.mjs';
3
+ import { existsSync, unlinkSync } from "node:fs";
4
+ import net from "node:net";
5
+ import { IS_WINDOWS, pipePath } from "./platform.mjs";
6
6
 
7
7
  export function getAssignCallbackPipePath(sessionId = process.pid) {
8
- return pipePath('triflux-assign-callback', sessionId);
8
+ return pipePath("triflux-assign-callback", sessionId);
9
9
  }
10
10
 
11
11
  function buildAssignCallbackEvent(event = {}, row = null) {
@@ -14,42 +14,71 @@ function buildAssignCallbackEvent(event = {}, row = null) {
14
14
  const createdAtMs = Number(source.created_at_ms);
15
15
  const timestampMs = Number.isFinite(updatedAtMs)
16
16
  ? updatedAtMs
17
- : (Number.isFinite(createdAtMs) ? createdAtMs : Date.now());
17
+ : Number.isFinite(createdAtMs)
18
+ ? createdAtMs
19
+ : Date.now();
18
20
 
19
21
  return {
20
- event: 'assign_job_status',
22
+ event: "assign_job_status",
21
23
  job_id: source.job_id || event.job_id || null,
22
24
  supervisor_agent: source.supervisor_agent || null,
23
25
  worker_agent: source.worker_agent || null,
24
26
  topic: source.topic || null,
25
27
  task: source.task || null,
26
28
  status: source.status || event.status || null,
27
- attempt: Number.isFinite(Number(source.attempt)) ? Number(source.attempt) : null,
28
- retry_count: Number.isFinite(Number(source.retry_count)) ? Number(source.retry_count) : null,
29
- max_retries: Number.isFinite(Number(source.max_retries)) ? Number(source.max_retries) : null,
30
- priority: Number.isFinite(Number(source.priority)) ? Number(source.priority) : null,
31
- ttl_ms: Number.isFinite(Number(source.ttl_ms)) ? Number(source.ttl_ms) : null,
32
- timeout_ms: Number.isFinite(Number(source.timeout_ms)) ? Number(source.timeout_ms) : null,
33
- deadline_ms: Number.isFinite(Number(source.deadline_ms)) ? Number(source.deadline_ms) : null,
29
+ attempt: Number.isFinite(Number(source.attempt))
30
+ ? Number(source.attempt)
31
+ : null,
32
+ retry_count: Number.isFinite(Number(source.retry_count))
33
+ ? Number(source.retry_count)
34
+ : null,
35
+ max_retries: Number.isFinite(Number(source.max_retries))
36
+ ? Number(source.max_retries)
37
+ : null,
38
+ priority: Number.isFinite(Number(source.priority))
39
+ ? Number(source.priority)
40
+ : null,
41
+ ttl_ms: Number.isFinite(Number(source.ttl_ms))
42
+ ? Number(source.ttl_ms)
43
+ : null,
44
+ timeout_ms: Number.isFinite(Number(source.timeout_ms))
45
+ ? Number(source.timeout_ms)
46
+ : null,
47
+ deadline_ms: Number.isFinite(Number(source.deadline_ms))
48
+ ? Number(source.deadline_ms)
49
+ : null,
34
50
  trace_id: source.trace_id || null,
35
51
  correlation_id: source.correlation_id || null,
36
52
  last_message_id: source.last_message_id || null,
37
- result: Object.hasOwn(source, 'result')
53
+ result: Object.hasOwn(source, "result")
38
54
  ? source.result
39
- : (Object.hasOwn(event, 'result') ? event.result : null),
40
- error: Object.hasOwn(source, 'error')
55
+ : Object.hasOwn(event, "result")
56
+ ? event.result
57
+ : null,
58
+ error: Object.hasOwn(source, "error")
41
59
  ? source.error
42
- : (Object.hasOwn(event, 'error') ? event.error : null),
60
+ : Object.hasOwn(event, "error")
61
+ ? event.error
62
+ : null,
43
63
  created_at_ms: Number.isFinite(createdAtMs) ? createdAtMs : null,
44
64
  updated_at_ms: Number.isFinite(updatedAtMs) ? updatedAtMs : null,
45
- started_at_ms: Number.isFinite(Number(source.started_at_ms)) ? Number(source.started_at_ms) : null,
46
- completed_at_ms: Number.isFinite(Number(source.completed_at_ms)) ? Number(source.completed_at_ms) : null,
47
- last_retry_at_ms: Number.isFinite(Number(source.last_retry_at_ms)) ? Number(source.last_retry_at_ms) : null,
65
+ started_at_ms: Number.isFinite(Number(source.started_at_ms))
66
+ ? Number(source.started_at_ms)
67
+ : null,
68
+ completed_at_ms: Number.isFinite(Number(source.completed_at_ms))
69
+ ? Number(source.completed_at_ms)
70
+ : null,
71
+ last_retry_at_ms: Number.isFinite(Number(source.last_retry_at_ms))
72
+ ? Number(source.last_retry_at_ms)
73
+ : null,
48
74
  timestamp: new Date(timestampMs).toISOString(),
49
75
  };
50
76
  }
51
77
 
52
- export function createAssignCallbackServer({ store = null, sessionId = process.pid } = {}) {
78
+ export function createAssignCallbackServer({
79
+ store = null,
80
+ sessionId = process.pid,
81
+ } = {}) {
53
82
  const pipePath = getAssignCallbackPipePath(sessionId);
54
83
  const clients = new Set();
55
84
  let server = null;
@@ -58,7 +87,9 @@ export function createAssignCallbackServer({ store = null, sessionId = process.p
58
87
  function removeSocket(socket) {
59
88
  if (!socket) return;
60
89
  clients.delete(socket);
61
- try { socket.destroy(); } catch {}
90
+ try {
91
+ socket.destroy();
92
+ } catch {}
62
93
  }
63
94
 
64
95
  function broadcast(event) {
@@ -87,20 +118,22 @@ export function createAssignCallbackServer({ store = null, sessionId = process.p
87
118
  async start() {
88
119
  if (server) return { path: pipePath };
89
120
  if (!IS_WINDOWS && existsSync(pipePath)) {
90
- try { unlinkSync(pipePath); } catch {}
121
+ try {
122
+ unlinkSync(pipePath);
123
+ } catch {}
91
124
  }
92
125
 
93
126
  server = net.createServer((socket) => {
94
127
  clients.add(socket);
95
- socket.setEncoding('utf8');
96
- socket.on('error', () => removeSocket(socket));
97
- socket.on('close', () => removeSocket(socket));
128
+ socket.setEncoding("utf8");
129
+ socket.on("error", () => removeSocket(socket));
130
+ socket.on("close", () => removeSocket(socket));
98
131
  });
99
132
 
100
133
  await new Promise((resolve, reject) => {
101
- server.once('error', reject);
134
+ server.once("error", reject);
102
135
  server.listen(pipePath, () => {
103
- server?.off('error', reject);
136
+ server?.off("error", reject);
104
137
  resolve();
105
138
  });
106
139
  });
@@ -115,7 +148,9 @@ export function createAssignCallbackServer({ store = null, sessionId = process.p
115
148
  },
116
149
  async stop() {
117
150
  if (detachStoreListener) {
118
- try { detachStoreListener(); } catch {}
151
+ try {
152
+ detachStoreListener();
153
+ } catch {}
119
154
  detachStoreListener = null;
120
155
  }
121
156
  if (!server) return;
@@ -125,7 +160,9 @@ export function createAssignCallbackServer({ store = null, sessionId = process.p
125
160
  await new Promise((resolve) => server.close(resolve));
126
161
  server = null;
127
162
  if (!IS_WINDOWS && existsSync(pipePath)) {
128
- try { unlinkSync(pipePath); } catch {}
163
+ try {
164
+ unlinkSync(pipePath);
165
+ } catch {}
129
166
  }
130
167
  },
131
168
  broadcast,
package/hub/bridge.mjs CHANGED
@@ -342,7 +342,6 @@ async function pipeQuery(action, payload, timeoutMs = 3000) {
342
342
  export function parseArgs(argv) {
343
343
  const { values, positionals } = nodeParseArgs({
344
344
  args: argv,
345
- allowPositionals: true,
346
345
  options: {
347
346
  agent: { type: "string" },
348
347
  cli: { type: "string" },