triflux 10.50.2 → 10.52.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 (263) hide show
  1. package/CLAUDE.md +57 -41
  2. package/README.ko.md +41 -45
  3. package/README.md +41 -45
  4. package/adapters/codex/skills/tfx-live/SKILL.md +25 -11
  5. package/bin/tfx-live.mjs +341 -104
  6. package/bin/triflux.mjs +147 -2624
  7. package/config/mcp-registry.json +3 -12
  8. package/cto/brief.mjs +0 -20
  9. package/cto/collect.mjs +1 -200
  10. package/cto/current.schema.json +2 -23
  11. package/cto/hygiene.mjs +2 -61
  12. package/cto/lake-root.mjs +0 -56
  13. package/cto/status.mjs +5 -187
  14. package/hooks/agy-session-hook.mjs +11 -56
  15. package/hooks/codex-session-hook.mjs +11 -101
  16. package/hub/bridge.mjs +65 -1250
  17. package/hub/cli-adapter-base.mjs +12 -90
  18. package/hub/codex-adapter.mjs +0 -1
  19. package/hub/codex-preflight.mjs +5 -28
  20. package/hub/lib/process-utils.mjs +1 -156
  21. package/hub/lib/spawn-trace.mjs +3 -2
  22. package/hub/lib/timeout-defaults.mjs +0 -1
  23. package/hub/team/agent-map.json +0 -1
  24. package/hub/team/agents-row-attach.py +120 -0
  25. package/hub/team/agents-row.mjs +200 -0
  26. package/hub/team/ansi.mjs +1 -35
  27. package/hub/team/backend.mjs +9 -145
  28. package/hub/team/claude-daemon-control.mjs +1 -2
  29. package/hub/team/claude-session-projection.mjs +5 -73
  30. package/hub/team/cli/commands/attach.mjs +1 -17
  31. package/hub/team/cli/commands/control.mjs +12 -38
  32. package/hub/team/cli/commands/debug.mjs +2 -39
  33. package/hub/team/cli/commands/focus.mjs +5 -31
  34. package/hub/team/cli/commands/interrupt.mjs +6 -25
  35. package/hub/team/cli/commands/kill.mjs +1 -30
  36. package/hub/team/cli/commands/list.mjs +0 -16
  37. package/hub/team/cli/commands/send.mjs +6 -26
  38. package/hub/team/cli/commands/start/index.mjs +42 -133
  39. package/hub/team/cli/commands/start/parse-args.mjs +15 -40
  40. package/hub/team/cli/commands/start/start-headless.mjs +138 -105
  41. package/hub/team/cli/commands/start/start-mux.mjs +2 -7
  42. package/hub/team/cli/commands/status.mjs +2 -57
  43. package/hub/team/cli/commands/stop.mjs +14 -19
  44. package/hub/team/cli/help.mjs +4 -5
  45. package/hub/team/cli/manifest.mjs +5 -1
  46. package/hub/team/cli/render.mjs +0 -12
  47. package/hub/team/cli/services/runtime-mode.mjs +27 -98
  48. package/hub/team/cli/services/state-store.mjs +5 -20
  49. package/hub/team/codex-queue.mjs +385 -0
  50. package/hub/team/handoff.mjs +3 -34
  51. package/hub/team/headless.mjs +108 -1296
  52. package/hub/team/orchestrator.mjs +4 -30
  53. package/hub/team/pane.mjs +6 -28
  54. package/hub/team/psmux.mjs +3 -34
  55. package/hub/team/remote-session.mjs +1 -2
  56. package/hub/team/session-context.mjs +1 -1
  57. package/hub/team/session.mjs +7 -91
  58. package/hub/team/tui-core.mjs +1 -1
  59. package/hub/team/tui-viewer.mjs +11 -58
  60. package/hub/team/tui.mjs +8 -306
  61. package/hub/team/uds-orchestrator.mjs +2 -580
  62. package/hub/team/wt-manager.mjs +2 -2
  63. package/hub/workers/factory.mjs +6 -84
  64. package/hub/workers/interface.mjs +1 -7
  65. package/hub/workers/lib/jsonrpc-core.mjs +11 -0
  66. package/hub/workers/lib/jsonrpc-ws-uds.mjs +5 -8
  67. package/hud/cli-policy.mjs +0 -22
  68. package/hud/constants.mjs +13 -26
  69. package/hud/hud-qos-status.mjs +42 -54
  70. package/hud/providers/gemini.mjs +125 -20
  71. package/hud/renderers.mjs +101 -122
  72. package/hud/utils.mjs +10 -6
  73. package/package.json +7 -12
  74. package/scripts/__tests__/mcp-guard-engine-http-headers.test.mjs +6 -6
  75. package/scripts/__tests__/mcp-guard-engine-policy-sync.test.mjs +1 -4
  76. package/scripts/__tests__/mcp-guard-engine-proactive-sync.test.mjs +16 -21
  77. package/scripts/__tests__/mcp-guard-engine-stdio-sync.test.mjs +1 -1
  78. package/scripts/__tests__/mcp-guard-engine-sync-http-headers.test.mjs +2 -2
  79. package/scripts/__tests__/mcp-guard-engine.test.mjs +56 -63
  80. package/scripts/__tests__/spawn-trace.test.mjs +16 -0
  81. package/scripts/check-codex-config-stable.mjs +4 -37
  82. package/scripts/claude-login-detect.mjs +0 -1
  83. package/scripts/claudemd-sync.mjs +1 -28
  84. package/scripts/lib/agent-route-policy.mjs +143 -62
  85. package/scripts/lib/cli-claude.mjs +0 -14
  86. package/scripts/lib/env-probe.mjs +2 -131
  87. package/scripts/lib/gemini-profiles.mjs +2 -69
  88. package/scripts/lib/legacy-mcp-cleanup.mjs +283 -0
  89. package/scripts/lib/machine-profile.mjs +3 -17
  90. package/scripts/lib/mcp-filter.mjs +109 -53
  91. package/scripts/lib/mcp-guard-engine.mjs +40 -98
  92. package/scripts/lib/mcp-health.mjs +2 -2
  93. package/scripts/lib/mcp-server-catalog.mjs +2 -2
  94. package/scripts/lib/psmux-info.mjs +11 -59
  95. package/scripts/lib/session-presence.mjs +2 -100
  96. package/scripts/lib/skill-template.mjs +0 -245
  97. package/scripts/pack.mjs +8 -83
  98. package/scripts/preflight-cache.mjs +5 -18
  99. package/scripts/release/check-packages-mirror.mjs +2 -8
  100. package/scripts/release/version-manifest.json +9 -1
  101. package/scripts/setup.mjs +100 -417
  102. package/scripts/test-lock.mjs +0 -1
  103. package/scripts/tfx-route-post.mjs +5 -69
  104. package/scripts/tfx-route-worker.mjs +4 -79
  105. package/scripts/tfx-route.sh +169 -1495
  106. package/scripts/wt-cli.mjs +1 -2
  107. package/skills/tfx-auto/SKILL.md +123 -741
  108. package/skills/tfx-auto/references/consensus-schema.md +161 -0
  109. package/skills/tfx-auto/references/tmux-observation.md +97 -0
  110. package/skills/tfx-doctor/SKILL.md +5 -6
  111. package/skills/tfx-lead/SKILL.md +195 -0
  112. package/skills/tfx-live/SKILL.md +25 -11
  113. package/skills/tfx-remote/SKILL.md +24 -87
  114. package/skills/tfx-research/SKILL.md +13 -20
  115. package/skills/tfx-review/SKILL.md +33 -35
  116. package/skills/tfx-setup/SKILL.md +1 -1
  117. package/skills/tfx-ship/SKILL.md +6 -27
  118. package/skills/tfx-wt/SKILL.md +34 -68
  119. package/bin/tfx-doctor-tui.mjs +0 -7
  120. package/bin/tfx-setup-tui.mjs +0 -7
  121. package/config/routing-policy.json +0 -124
  122. package/docs/assets/consensus-flow.svg +0 -125
  123. package/docs/assets/deep-vs-light.svg +0 -193
  124. package/docs/assets/demo-dark.gif +0 -0
  125. package/docs/assets/demo-light.gif +0 -0
  126. package/docs/assets/demo-psmux.gif +0 -0
  127. package/hub/adaptive-diagnostic.mjs +0 -350
  128. package/hub/adaptive-inject.mjs +0 -224
  129. package/hub/adaptive-memory.mjs +0 -277
  130. package/hub/adaptive.mjs +0 -172
  131. package/hub/assign-callbacks.mjs +0 -170
  132. package/hub/delegator/contracts.mjs +0 -38
  133. package/hub/delegator/index.mjs +0 -14
  134. package/hub/delegator/schema/delegator-tools.schema.json +0 -250
  135. package/hub/delegator/service.mjs +0 -336
  136. package/hub/delegator/tool-definitions.mjs +0 -35
  137. package/hub/dynamic-routing-engine.mjs +0 -511
  138. package/hub/hitl.mjs +0 -202
  139. package/hub/hub-lifecycle.mjs +0 -248
  140. package/hub/lib/known-errors.json +0 -72
  141. package/hub/lib/memory-store.mjs +0 -1001
  142. package/hub/lib/phase-manager.mjs +0 -493
  143. package/hub/lib/risk-tier.mjs +0 -53
  144. package/hub/lib/ssh-command.mjs +0 -231
  145. package/hub/lib/staged-file-detect.mjs +0 -43
  146. package/hub/lib/state-snapshot.mjs +0 -293
  147. package/hub/lib/tfx-route-args.mjs +0 -353
  148. package/hub/lib/trace-recorder.mjs +0 -153
  149. package/hub/lib/uuidv7.mjs +0 -45
  150. package/hub/memory-doctor.mjs +0 -640
  151. package/hub/middleware/quota-middleware.mjs +0 -70
  152. package/hub/middleware/request-logger.mjs +0 -191
  153. package/hub/paths.mjs +0 -24
  154. package/hub/pipe.mjs +0 -825
  155. package/hub/pipeline/index.mjs +0 -163
  156. package/hub/pipeline/state.mjs +0 -191
  157. package/hub/pipeline/transitions.mjs +0 -131
  158. package/hub/promote-penalties.mjs +0 -138
  159. package/hub/public/dashboard.html +0 -416
  160. package/hub/reflexion.mjs +0 -290
  161. package/hub/role-contract.mjs +0 -314
  162. package/hub/router.mjs +0 -2026
  163. package/hub/routing-snapshot.mjs +0 -261
  164. package/hub/schema.sql +0 -209
  165. package/hub/server.mjs +0 -3048
  166. package/hub/session-fingerprint.mjs +0 -418
  167. package/hub/state.mjs +0 -300
  168. package/hub/store-adapter.mjs +0 -182
  169. package/hub/store.mjs +0 -1736
  170. package/hub/team/build-worker-prompt.mjs +0 -92
  171. package/hub/team/check-mcp-hub.mjs +0 -49
  172. package/hub/team/claude-native-bridge.mjs +0 -987
  173. package/hub/team/cli/commands/start/start-in-process.mjs +0 -50
  174. package/hub/team/cli/commands/start/start-wt.mjs +0 -86
  175. package/hub/team/cli/services/hub-client.mjs +0 -264
  176. package/hub/team/cli/services/native-control.mjs +0 -145
  177. package/hub/team/codex-review.mjs +0 -520
  178. package/hub/team/conductor-mesh-bridge.mjs +0 -122
  179. package/hub/team/conductor-registry.mjs +0 -121
  180. package/hub/team/conductor.mjs +0 -1529
  181. package/hub/team/consensus-meta.mjs +0 -176
  182. package/hub/team/cto-auto-collect.mjs +0 -115
  183. package/hub/team/cto-pull.mjs +0 -31
  184. package/hub/team/daemon-pty-tmux-bridge.mjs +0 -146
  185. package/hub/team/dashboard.mjs +0 -322
  186. package/hub/team/event-log.mjs +0 -84
  187. package/hub/team/execution-mode.mjs +0 -324
  188. package/hub/team/extract-completion-payload.mjs +0 -110
  189. package/hub/team/headless-bridge-session.mjs +0 -17
  190. package/hub/team/health-probe.mjs +0 -435
  191. package/hub/team/interactive-native-launcher.mjs +0 -119
  192. package/hub/team/interactive-native-worker.mjs +0 -80
  193. package/hub/team/interactive-tui-transport.mjs +0 -479
  194. package/hub/team/launcher-template.mjs +0 -144
  195. package/hub/team/lead-control.mjs +0 -191
  196. package/hub/team/mcp-selector.mjs +0 -145
  197. package/hub/team/native-supervisor.mjs +0 -460
  198. package/hub/team/native.mjs +0 -727
  199. package/hub/team/recovery-store.mjs +0 -149
  200. package/hub/team/remote-probe.mjs +0 -292
  201. package/hub/team/remote-watcher.mjs +0 -506
  202. package/hub/team/runtime-strategy.mjs +0 -200
  203. package/hub/team/schemas/worker-completion.json +0 -39
  204. package/hub/team/sentinel-capture.mjs +0 -127
  205. package/hub/team/session-sync.mjs +0 -316
  206. package/hub/team/swarm-cli.mjs +0 -390
  207. package/hub/team/swarm-hypervisor.mjs +0 -2206
  208. package/hub/team/swarm-intent.mjs +0 -216
  209. package/hub/team/swarm-locks.mjs +0 -335
  210. package/hub/team/swarm-planner.mjs +0 -371
  211. package/hub/team/swarm-preflight.mjs +0 -366
  212. package/hub/team/swarm-reconciler.mjs +0 -242
  213. package/hub/team/synapse-cli.mjs +0 -458
  214. package/hub/team/synapse-http.mjs +0 -311
  215. package/hub/team/synapse-registry.mjs +0 -618
  216. package/hub/team/tui-remote-adapter.mjs +0 -377
  217. package/hub/team/tui-synapse.mjs +0 -223
  218. package/hub/team/worker-completion-validator.mjs +0 -79
  219. package/hub/team/worker-sandbox.mjs +0 -125
  220. package/hub/team/worktree-lifecycle.mjs +0 -639
  221. package/hub/team/wt-templates.json +0 -43
  222. package/hub/team-bridge.mjs +0 -27
  223. package/hub/tools.mjs +0 -900
  224. package/hub/workers/antigravity-route-worker.mjs +0 -179
  225. package/hub/workers/codex-app-server-worker.mjs +0 -1067
  226. package/hub/workers/delegator-mcp.mjs +0 -1098
  227. package/hub/workers/lib/jsonrpc-stdio.mjs +0 -204
  228. package/mesh/index.mjs +0 -69
  229. package/mesh/mesh-budget.mjs +0 -137
  230. package/mesh/mesh-heartbeat.mjs +0 -100
  231. package/mesh/mesh-protocol.mjs +0 -96
  232. package/mesh/mesh-queue.mjs +0 -163
  233. package/mesh/mesh-registry.mjs +0 -78
  234. package/mesh/mesh-router.mjs +0 -77
  235. package/scripts/__tests__/skill-surface.test.mjs +0 -93
  236. package/scripts/cache-doctor.mjs +0 -156
  237. package/scripts/cache-warmup.mjs +0 -630
  238. package/scripts/completions/tfx.bash +0 -74
  239. package/scripts/completions/tfx.fish +0 -57
  240. package/scripts/completions/tfx.zsh +0 -98
  241. package/scripts/demo.mjs +0 -197
  242. package/scripts/doctor-dynamic-routing.mjs +0 -87
  243. package/scripts/hub-ensure.mjs +0 -842
  244. package/scripts/hub-watchdog.mjs +0 -90
  245. package/scripts/lib/claudemd-scanner.mjs +0 -223
  246. package/scripts/lib/context.mjs +0 -67
  247. package/scripts/lib/dynamic-route-cli.mjs +0 -107
  248. package/scripts/lib/handoff.mjs +0 -187
  249. package/scripts/lib/logger.mjs +0 -122
  250. package/scripts/lib/stealth-fetch.mjs +0 -176
  251. package/scripts/notion-read.mjs +0 -686
  252. package/scripts/snapshot-codex-state.mjs +0 -37
  253. package/scripts/snapshot-gemini-state.mjs +0 -37
  254. package/scripts/sync-codex-auth.mjs +0 -71
  255. package/scripts/sync-hub-mcp-settings.mjs +0 -697
  256. package/skills/_templates/base.md +0 -4
  257. package/skills/_templates/deep.md +0 -6
  258. package/skills/shared/telemetry-segment.md +0 -6
  259. package/tui/core.mjs +0 -266
  260. package/tui/doctor.mjs +0 -375
  261. package/tui/monitor-data.mjs +0 -152
  262. package/tui/monitor.mjs +0 -318
  263. package/tui/setup.mjs +0 -506
@@ -3,25 +3,16 @@
3
3
  "version": 1,
4
4
  "description": "MCP 서버 중앙 레지스트리 — 진실의 원천",
5
5
  "defaults": {
6
- "transport": "hub-url",
7
- "hub_base": "http://127.0.0.1:27888"
6
+ "transport": "http"
8
7
  },
9
8
  "policy_notes": {
10
9
  "policy": "Hosted servers use URL and optional headers; stdio servers use command, args, and optional env.",
11
- "transport": "Server transport accepts \"hub-url\" for triflux Hub URL flow, \"http\" for direct Streamable HTTP MCP endpoints, or \"stdio\" for directly launched MCP servers.",
10
+ "transport": "Server transport accepts \"http\" for direct Streamable HTTP MCP endpoints, or \"stdio\" for directly launched MCP servers.",
12
11
  "headers": "Optional headers are allowed only for HTTP-compatible transports. Each header value must be a descriptor: {\"value\":\"literal\"} for non-secret static values, {\"env\":\"ENV_VAR_NAME\"} for secrets resolved at sync/runtime, or {\"env\":\"ENV_VAR_NAME\",\"prefix\":\"Bearer \"} for common authorization formats.",
13
12
  "secret_safety": "Resolved secret values must not be written back to this registry file. Missing env vars warn during sync and do not emit empty secret headers.",
14
- "sync_denylist": "Array of client:server strings skipped by proactive registry sync, for example gemini:tfx-hub."
13
+ "sync_denylist": "Array of client:server strings skipped by proactive registry sync, for example gemini:context7."
15
14
  },
16
15
  "servers": {
17
- "tfx-hub": {
18
- "policy": "hosted",
19
- "transport": "hub-url",
20
- "url": "http://127.0.0.1:27888/mcp",
21
- "safe": true,
22
- "targets": ["claude", "gemini", "codex", "antigravity"],
23
- "description": "triflux Hub MCP 서버"
24
- },
25
16
  "context7": {
26
17
  "policy": "hosted",
27
18
  "transport": "http",
package/cto/brief.mjs CHANGED
@@ -12,11 +12,6 @@ function oneLine(value, fallback = "n/a") {
12
12
  return String(text).replace(/\s+/g, " ").trim() || fallback;
13
13
  }
14
14
 
15
- function compactDetail(value) {
16
- const text = oneLine(value);
17
- return text.length > 140 ? `${text.slice(0, 137)}...` : text;
18
- }
19
-
20
15
  function formatGoal(goal) {
21
16
  const id = oneLine(goal?.id, "goal");
22
17
  const status = oneLine(goal?.status, "unknown");
@@ -27,13 +22,6 @@ function formatGoal(goal) {
27
22
  return `- ${id} ${status}: ${title}`;
28
23
  }
29
24
 
30
- function formatShard(shard) {
31
- const id = oneLine(shard?.id || shard?.name || shard?.sessionId, "shard");
32
- const status = oneLine(shard?.status || shard?.state, "unknown");
33
- const detail = oneLine(shard?.summary || shard?.objective || shard?.task, "");
34
- return detail ? `- ${id} ${status}: ${detail}` : `- ${id} ${status}`;
35
- }
36
-
37
25
  function formatEvent(event) {
38
26
  const ts = oneLine(event?.ts, "unknown_ts");
39
27
  const name = oneLine(event?.event, "event");
@@ -57,13 +45,9 @@ function enforceCap(text) {
57
45
  export function renderBrief(current) {
58
46
  const repo = current?.repo || {};
59
47
  const summary = current?.summary || {};
60
- const hub = current?.sources?.tfx_hub || {};
61
48
  const activeGoals = Array.isArray(summary.active_goals)
62
49
  ? summary.active_goals.slice(0, 3)
63
50
  : [];
64
- const swarmShards = Array.isArray(summary.swarm_shards)
65
- ? summary.swarm_shards.slice(0, 2)
66
- : [];
67
51
  const recentEvents = Array.isArray(current?.ledger_tail)
68
52
  ? current.ledger_tail.slice(-2)
69
53
  : [];
@@ -75,10 +59,6 @@ export function renderBrief(current) {
75
59
  `summary: ${oneLine(summary.repo_state, "no repo summary")}`,
76
60
  "active_goals",
77
61
  ...(activeGoals.length > 0 ? activeGoals.map(formatGoal) : ["- none"]),
78
- "swarm_shards",
79
- ...(swarmShards.length > 0 ? swarmShards.map(formatShard) : ["- none"]),
80
- "hub_status",
81
- `status: ${oneLine(hub.status, "unknown")} available: ${hub.available === true} detail: ${compactDetail(hub.detail)}`,
82
62
  "recent_events",
83
63
  ...(recentEvents.length > 0 ? recentEvents.map(formatEvent) : ["- none"]),
84
64
  "generated_at",
package/cto/collect.mjs CHANGED
@@ -6,14 +6,12 @@ import {
6
6
  readFileSync,
7
7
  statSync,
8
8
  } from "node:fs";
9
- import { homedir } from "node:os";
10
9
  import { join, relative } from "node:path";
11
10
  import { fileURLToPath } from "node:url";
12
11
 
13
12
  import { renderBrief } from "./brief.mjs";
14
13
  import { appendCtoEvent } from "./events.mjs";
15
14
  import {
16
- firstExisting,
17
15
  readJsonLines,
18
16
  resolveLakeRootDir,
19
17
  writeAtomic,
@@ -27,30 +25,6 @@ const SOURCE_REGISTRY = [
27
25
  probe: "git rev-parse, git branch, git status",
28
26
  enabled: true,
29
27
  },
30
- {
31
- id: "tfx_hub",
32
- kind: "triflux-runtime-artifact",
33
- probe: ".triflux/hub/status.json or host tfx-hub cache",
34
- enabled: true,
35
- },
36
- {
37
- id: "tfx_swarm",
38
- kind: "triflux-runtime-artifact",
39
- probe: ".triflux/swarm-locks.json or .triflux/swarm/*.json",
40
- enabled: true,
41
- },
42
- {
43
- id: "tfx_team",
44
- kind: "triflux-runtime-artifact",
45
- probe: ".triflux/team-state.json or host tfx-hub team cache",
46
- enabled: true,
47
- },
48
- {
49
- id: "tfx_synapse",
50
- kind: "triflux-runtime-artifact",
51
- probe: ".triflux/synapse registry or host tfx-hub synapse cache",
52
- enabled: true,
53
- },
54
28
  {
55
29
  id: "ultragoal_omx",
56
30
  kind: "durable-goal-artifact",
@@ -127,14 +101,6 @@ function listDirFiles(dirPath, rootDir, limit = 10) {
127
101
  }
128
102
  }
129
103
 
130
- function safeSummary(value) {
131
- if (value === null || value === undefined) return null;
132
- if (Array.isArray(value)) return { type: "array", count: value.length };
133
- if (typeof value === "object")
134
- return { type: "object", keys: Object.keys(value).slice(0, 20) };
135
- return String(value).slice(0, 200);
136
- }
137
-
138
104
  function execGit(args, rootDir, execFileSyncFn) {
139
105
  return execFileSyncFn("git", args, {
140
106
  cwd: rootDir,
@@ -189,45 +155,6 @@ function collectGit(rootDir, collectedAt, execFileSyncFn) {
189
155
  }
190
156
  }
191
157
 
192
- function collectJsonArtifact(
193
- id,
194
- candidates,
195
- rootDir,
196
- collectedAt,
197
- summarize = safeSummary,
198
- ) {
199
- const filePath = firstExisting(candidates);
200
- if (!filePath) {
201
- return missingSource(
202
- "no_shell_readable_artifact",
203
- "no durable artifact found",
204
- collectedAt,
205
- );
206
- }
207
- try {
208
- const parsed = readJson(filePath);
209
- return sourceState(
210
- true,
211
- "ok",
212
- {
213
- path: relPath(rootDir, filePath),
214
- summary: summarize(parsed),
215
- },
216
- collectedAt,
217
- );
218
- } catch (error) {
219
- return sourceState(
220
- true,
221
- "read_error",
222
- {
223
- path: relPath(rootDir, filePath),
224
- error: error?.message || `${id} artifact read failed`,
225
- },
226
- collectedAt,
227
- );
228
- }
229
- }
230
-
231
158
  function normalizeGoals(parsed) {
232
159
  const rawGoals = Array.isArray(parsed?.goals)
233
160
  ? parsed.goals
@@ -306,70 +233,6 @@ function collectUltragoal(dirPath, rootDir, collectedAt) {
306
233
  }
307
234
  }
308
235
 
309
- export function collectSwarm(rootDir, collectedAt) {
310
- const locksPath = join(rootDir, ".triflux", "swarm-locks.json");
311
- const logsDir = join(rootDir, ".triflux", "swarm-logs");
312
- if (!existsSync(locksPath) && !existsSync(logsDir)) {
313
- return missingSource(
314
- "no_shell_readable_artifact",
315
- "no swarm locks or logs found",
316
- collectedAt,
317
- );
318
- }
319
- try {
320
- const detail = { locks_path: null, locks: null, shards: [], log_runs: [] };
321
- if (existsSync(locksPath)) {
322
- const locks = readJson(locksPath);
323
- detail.locks_path = relPath(rootDir, locksPath);
324
- detail.locks = safeSummary(locks);
325
- if (Array.isArray(locks?.shards)) detail.shards = locks.shards;
326
- else if (Array.isArray(locks)) detail.shards = locks;
327
- else if (locks && typeof locks === "object") {
328
- // 실제 producer(hub/team/swarm-locks.mjs persist)는
329
- // { "<file>": { workerId, leaseType, sessionMeta } } 형태의 lock map 을 쓴다.
330
- // workerId 가 곧 shard.name 이다 — swarm-hypervisor 가
331
- // acquire(shard.name, shard.files) 로 잠그기 때문(swarm-hypervisor.mjs:753).
332
- // workerId 별로 묶어 active shard row 로 환원한다. (expired lock 정밀 필터는
333
- // hub snapshot() 의 책임이라, 여기서는 persist 된 보유 lock 전부를 active 로 본다.)
334
- const byWorker = new Map();
335
- for (const entry of Object.values(locks)) {
336
- const workerId =
337
- entry && typeof entry.workerId === "string" ? entry.workerId : null;
338
- if (!workerId) continue;
339
- let row = byWorker.get(workerId);
340
- if (!row) {
341
- row = { shard_name: workerId, phase: "active", members: [] };
342
- byWorker.set(workerId, row);
343
- }
344
- const host = entry?.sessionMeta?.host;
345
- if (typeof host === "string" && host && !row.members.includes(host)) {
346
- row.members.push(host);
347
- }
348
- }
349
- detail.shards = [...byWorker.values()];
350
- }
351
- }
352
- if (existsSync(logsDir)) {
353
- detail.log_runs = readdirSync(logsDir, { withFileTypes: true })
354
- .filter((entry) => entry.isDirectory() && entry.name.startsWith("run-"))
355
- .map((entry) => {
356
- const path = join(logsDir, entry.name);
357
- return { id: entry.name, mtime: statSync(path).mtime.toISOString() };
358
- })
359
- .sort((a, b) => b.mtime.localeCompare(a.mtime))
360
- .slice(0, 5);
361
- }
362
- return sourceState(true, "ok", detail, collectedAt);
363
- } catch (error) {
364
- return sourceState(
365
- true,
366
- "read_error",
367
- error?.message || "swarm read failed",
368
- collectedAt,
369
- );
370
- }
371
- }
372
-
373
236
  function collectHandoffs(rootDir, collectedAt) {
374
237
  const dirPath = join(rootDir, ".omx", "handoffs");
375
238
  const files = listDirFiles(dirPath, rootDir, 10);
@@ -392,7 +255,6 @@ function buildSummary(current) {
392
255
  const repo = current.repo;
393
256
  const omxGoals = current.sources.ultragoal_omx.detail?.active_goals || [];
394
257
  const omcGoals = current.sources.ultragoal_omc.detail?.active_goals || [];
395
- const swarmShards = current.sources.tfx_swarm.detail?.shards || [];
396
258
  const availableSources = Object.values(current.sources).filter(
397
259
  (source) => source.available,
398
260
  ).length;
@@ -400,8 +262,6 @@ function buildSummary(current) {
400
262
  return {
401
263
  repo_state: `branch ${repo.branch || "unknown"} at ${repo.head || "unknown"} is ${repo.dirty ? "dirty" : "clean"}`,
402
264
  active_goals: [...omxGoals, ...omcGoals].slice(0, 5),
403
- swarm_shards: Array.isArray(swarmShards) ? swarmShards.slice(0, 5) : [],
404
- hub_status: current.sources.tfx_hub.status,
405
265
  available_sources: availableSources,
406
266
  missing_sources: SOURCE_IDS.length - availableSources,
407
267
  };
@@ -539,68 +399,10 @@ function validateCurrent(current) {
539
399
  }
540
400
  }
541
401
 
542
- function collectSources(rootDir, collectedAt, execFileSyncFn, opts = {}) {
543
- const home = homedir();
544
- const hostArtifactCandidates =
545
- opts.includeHostArtifacts === false
546
- ? {
547
- hub: [],
548
- team: [],
549
- synapse: [],
550
- }
551
- : {
552
- hub: [
553
- join(home, ".claude", "cache", "tfx-hub", "hub.pid"),
554
- join(home, ".claude", "cache", "tfx-hub", "hub-state.json"),
555
- ],
556
- team: [
557
- join(
558
- home,
559
- ".claude",
560
- "cache",
561
- "tfx-hub",
562
- `team-state-${process.env.CLAUDE_SESSION_ID || ""}.json`,
563
- ),
564
- join(home, ".claude", "cache", "tfx-hub", "team-state.json"),
565
- ],
566
- synapse: [
567
- join(home, ".claude", "cache", "tfx-hub", "synapse-registry.json"),
568
- join(home, ".claude", "cache", "tfx-hub", "synapse-sessions.json"),
569
- ],
570
- };
402
+ function collectSources(rootDir, collectedAt, execFileSyncFn) {
571
403
  const git = collectGit(rootDir, collectedAt, execFileSyncFn);
572
404
  const sources = {
573
405
  git: git.source,
574
- tfx_hub: collectJsonArtifact(
575
- "tfx_hub",
576
- [
577
- join(rootDir, ".triflux", "hub", "status.json"),
578
- join(rootDir, ".triflux", "hub-state.json"),
579
- ...hostArtifactCandidates.hub,
580
- ],
581
- rootDir,
582
- collectedAt,
583
- ),
584
- tfx_swarm: collectSwarm(rootDir, collectedAt),
585
- tfx_team: collectJsonArtifact(
586
- "tfx_team",
587
- [
588
- join(rootDir, ".triflux", "team-state.json"),
589
- ...hostArtifactCandidates.team,
590
- ],
591
- rootDir,
592
- collectedAt,
593
- ),
594
- tfx_synapse: collectJsonArtifact(
595
- "tfx_synapse",
596
- [
597
- join(rootDir, ".triflux", "synapse-registry.json"),
598
- join(rootDir, ".triflux", "synapse", "registry.json"),
599
- ...hostArtifactCandidates.synapse,
600
- ],
601
- rootDir,
602
- collectedAt,
603
- ),
604
406
  ultragoal_omx: collectUltragoal(
605
407
  join(rootDir, ".omx", "ultragoal"),
606
408
  rootDir,
@@ -641,7 +443,6 @@ export async function runCollect(args = [], opts = {}) {
641
443
  rootDir,
642
444
  generatedAt,
643
445
  execFileSyncFn,
644
- opts,
645
446
  );
646
447
  const current = {
647
448
  schema_version: SCHEMA_VERSION,
@@ -46,32 +46,11 @@
46
46
  "type": "object",
47
47
  "description": "Durable artifact source states only. A source reports available:false when no shell-readable durable artifact exists.",
48
48
  "additionalProperties": false,
49
- "required": [
50
- "git",
51
- "tfx_hub",
52
- "tfx_swarm",
53
- "tfx_team",
54
- "tfx_synapse",
55
- "ultragoal_omx",
56
- "ultragoal_omc",
57
- "handoffs"
58
- ],
49
+ "required": ["git", "ultragoal_omx", "ultragoal_omc", "handoffs"],
59
50
  "properties": {
60
51
  "git": {
61
52
  "$ref": "#/$defs/sourceState"
62
53
  },
63
- "tfx_hub": {
64
- "$ref": "#/$defs/sourceState"
65
- },
66
- "tfx_swarm": {
67
- "$ref": "#/$defs/sourceState"
68
- },
69
- "tfx_team": {
70
- "$ref": "#/$defs/sourceState"
71
- },
72
- "tfx_synapse": {
73
- "$ref": "#/$defs/sourceState"
74
- },
75
54
  "ultragoal_omx": {
76
55
  "$ref": "#/$defs/sourceState"
77
56
  },
@@ -85,7 +64,7 @@
85
64
  },
86
65
  "summary": {
87
66
  "type": "object",
88
- "description": "Human-oriented synthesized authority summary derived from durable artifacts and live Triflux synapse session status. Phase 1 may add source-derived fields here without changing the top-level contract.",
67
+ "description": "Human-oriented synthesized authority summary derived from durable artifacts. Phase 1 may add source-derived fields here without changing the top-level contract.",
89
68
  "additionalProperties": true
90
69
  },
91
70
  "ledger_tail": {
package/cto/hygiene.mjs CHANGED
@@ -1,11 +1,6 @@
1
1
  import { existsSync, readFileSync } from "node:fs";
2
2
  import { join } from "node:path";
3
- import {
4
- normalizeLiveSession,
5
- readJsonLines,
6
- readSynapseSnapshot,
7
- resolveLakeRootDir,
8
- } from "./lake-root.mjs";
3
+ import { readJsonLines, resolveLakeRootDir } from "./lake-root.mjs";
9
4
 
10
5
  const COUNT_KEYS = [
11
6
  "active_tasks",
@@ -28,37 +23,6 @@ function readJson(filePath) {
28
23
  return JSON.parse(readFileSync(filePath, "utf8"));
29
24
  }
30
25
 
31
- function normalizeOverlay(value) {
32
- const sessions = Array.isArray(value)
33
- ? value
34
- : Array.isArray(value?.sessions)
35
- ? value.sessions
36
- : Array.isArray(value?.live_sessions)
37
- ? value.live_sessions
38
- : [];
39
- return {
40
- live_sessions: sessions
41
- .map(normalizeLiveSession)
42
- .filter((session) => session.sessionId),
43
- };
44
- }
45
-
46
- async function readLiveOverlay(opts = {}) {
47
- if (opts.overlay) return normalizeOverlay(opts.overlay);
48
- try {
49
- const reader = opts.synapseReader || readSynapseSnapshot;
50
- return normalizeOverlay(
51
- await reader({
52
- rootDir: opts.rootDir,
53
- lakeRoot: opts.lakeRoot,
54
- synapsePersistPath: opts.synapsePersistPath,
55
- }),
56
- );
57
- } catch {
58
- return { live_sessions: [] };
59
- }
60
- }
61
-
62
26
  function eventTime(entry) {
63
27
  return typeof entry?.ts === "string" ? entry.ts : "";
64
28
  }
@@ -157,11 +121,7 @@ export function compactHygieneCounts(projection) {
157
121
  return Object.fromEntries(COUNT_KEYS.map((key) => [key, counts[key] || 0]));
158
122
  }
159
123
 
160
- export function projectCtoHygiene({
161
- current = {},
162
- ledger = null,
163
- overlay = {},
164
- } = {}) {
124
+ export function projectCtoHygiene({ current = {}, ledger = null } = {}) {
165
125
  const events = Array.isArray(ledger)
166
126
  ? ledger
167
127
  : Array.isArray(current?.ledger_tail)
@@ -270,23 +230,6 @@ export function projectCtoHygiene({
270
230
  );
271
231
  }
272
232
 
273
- for (const session of overlay?.live_sessions || []) {
274
- const phase = String(session?.phase || session?.status || "").toLowerCase();
275
- if (phase !== "stale") continue;
276
- const sessionId = String(
277
- session?.sessionId || session?.session_id || "",
278
- ).trim();
279
- if (!sessionId || staleSessions.has(sessionId)) continue;
280
- rows.push({
281
- kind: "session",
282
- id: sessionId,
283
- status: "stale",
284
- last_event_at: session?.started_at || null,
285
- action: "archive_or_resume_session",
286
- owner: session?.agent_id ? undefined : "unknown",
287
- });
288
- }
289
-
290
233
  for (const [key, item] of worktrees) {
291
234
  if (item.entry?.event === "worktree_removed") continue;
292
235
  const status = statusOf(item.ref, "active");
@@ -363,11 +306,9 @@ export async function runHygiene(args = [], opts = {}) {
363
306
  const currentPath = join(lakeRoot, "current.json");
364
307
  const current = existsSync(currentPath) ? readJson(currentPath) : {};
365
308
  const ledger = readJsonLines(join(lakeRoot, "ledger.jsonl"));
366
- const overlay = await readLiveOverlay({ ...opts, rootDir, lakeRoot });
367
309
  const projection = projectCtoHygiene({
368
310
  current,
369
311
  ledger: ledger.length ? ledger : null,
370
- overlay,
371
312
  });
372
313
  if (opts.json === true || hasFlag(args, "--json"))
373
314
  writeJson(stdout, projection);
package/cto/lake-root.mjs CHANGED
@@ -6,7 +6,6 @@ import {
6
6
  renameSync,
7
7
  writeFileSync,
8
8
  } from "node:fs";
9
- import { homedir } from "node:os";
10
9
  import { basename, dirname, join, parse } from "node:path";
11
10
 
12
11
  const MAX_DEPTH = 64;
@@ -77,10 +76,6 @@ export function resolveLakeRootDir(cwd, opts = {}) {
77
76
  return cwd;
78
77
  }
79
78
 
80
- export function firstExisting(paths) {
81
- return paths.filter(Boolean).find((path) => defaultExistsSync(path)) || null;
82
- }
83
-
84
79
  export function toIsoTime(value) {
85
80
  if (typeof value === "string" && value.trim()) return value;
86
81
  if (value instanceof Date) return value.toISOString();
@@ -106,57 +101,6 @@ export function pathLabel(value) {
106
101
  return segments[segments.length - 1] || "";
107
102
  }
108
103
 
109
- export function normalizeLiveSession(session) {
110
- return {
111
- sessionId: String(session?.sessionId || session?.session_id || ""),
112
- agent_id:
113
- typeof session?.agent_id === "string"
114
- ? session.agent_id
115
- : typeof session?.agentId === "string"
116
- ? session.agentId
117
- : null,
118
- phase:
119
- typeof session?.phase === "string"
120
- ? session.phase
121
- : typeof session?.status === "string"
122
- ? session.status
123
- : "active",
124
- started_at: toIsoTime(
125
- session?.started_at ?? session?.startedAt ?? session?.lastHeartbeat,
126
- ),
127
- };
128
- }
129
-
130
- export async function readSynapseSnapshot(opts = {}) {
131
- const rootDir = opts.rootDir || process.cwd();
132
- const persistPath = firstExisting([
133
- opts.synapsePersistPath,
134
- join(rootDir, ".triflux", "synapse-registry.json"),
135
- join(rootDir, ".triflux", "synapse", "registry.json"),
136
- join(homedir(), ".claude", "cache", "tfx-hub", "synapse-sessions.json"),
137
- join(homedir(), ".claude", "cache", "tfx-hub", "synapse-registry.json"),
138
- ]);
139
- if (!persistPath) return { sessions: [], active_shards: [] };
140
- const data = JSON.parse(readFileSync(persistPath, "utf8"));
141
- // 상태 전이는 hub 소유이며 조회는 저장된 live 상태만 읽는다.
142
- const sessions = Object.entries(data).flatMap(([key, session]) => {
143
- const sessionId = String(session?.sessionId ?? key).trim();
144
- if (!sessionId || ["stale", "expired"].includes(session?.status)) return [];
145
- return [
146
- {
147
- ...session,
148
- sessionId,
149
- status: session?.status === "idle" ? "idle" : "active",
150
- lastHeartbeat:
151
- typeof session?.lastHeartbeat === "number"
152
- ? session.lastHeartbeat
153
- : Date.now(),
154
- },
155
- ];
156
- });
157
- return { sessions, active_shards: [] };
158
- }
159
-
160
104
  export function readJsonLines(filePath, limit = Infinity) {
161
105
  if (!defaultExistsSync(filePath)) return [];
162
106
  const lines = readFileSync(filePath, "utf8")