@triflux/remote 10.51.0 → 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 (59) hide show
  1. package/cto/brief.mjs +0 -8
  2. package/cto/collect.mjs +1 -127
  3. package/cto/current.schema.json +2 -19
  4. package/cto/hygiene.mjs +2 -61
  5. package/cto/lake-root.mjs +0 -56
  6. package/cto/status.mjs +5 -139
  7. package/hub/index.mjs +0 -9
  8. package/hub/team/agents-row-attach.py +120 -0
  9. package/hub/team/agents-row.mjs +200 -0
  10. package/hub/team/claude-daemon-control.mjs +1 -2
  11. package/hub/team/claude-session-projection.mjs +5 -73
  12. package/hub/team/cli/commands/debug.mjs +1 -2
  13. package/hub/team/cli/commands/start/index.mjs +2 -1
  14. package/hub/team/cli/commands/start/start-mux.mjs +2 -4
  15. package/hub/team/cli/services/state-store.mjs +5 -20
  16. package/hub/team/headless.mjs +96 -543
  17. package/hub/team/psmux.mjs +3 -33
  18. package/hub/team/session-context.mjs +1 -1
  19. package/hub/team/tui-viewer.mjs +9 -56
  20. package/hub/team/tui.mjs +0 -37
  21. package/hub/team/uds-orchestrator.mjs +2 -580
  22. package/hub/workers/factory.mjs +6 -51
  23. package/hub/workers/interface.mjs +1 -7
  24. package/hub/workers/lib/jsonrpc-core.mjs +11 -0
  25. package/hub/workers/lib/jsonrpc-ws-uds.mjs +5 -6
  26. package/package.json +3 -8
  27. package/scripts/lib/agent-route-policy.mjs +0 -67
  28. package/scripts/lib/cli-claude.mjs +0 -12
  29. package/scripts/lib/env-probe.mjs +0 -70
  30. package/scripts/lib/legacy-mcp-cleanup.mjs +283 -0
  31. package/scripts/lib/mcp-guard-engine.mjs +40 -98
  32. package/hub/hub-lifecycle.mjs +0 -248
  33. package/hub/pipe.mjs +0 -825
  34. package/hub/promote-penalties.mjs +0 -138
  35. package/hub/public/dashboard.html +0 -416
  36. package/hub/schema.sql +0 -209
  37. package/hub/server.mjs +0 -3048
  38. package/hub/store-adapter.mjs +0 -182
  39. package/hub/store.mjs +0 -1736
  40. package/hub/team/cli/services/hub-client.mjs +0 -178
  41. package/hub/team/conductor-registry.mjs +0 -121
  42. package/hub/team/cto-auto-collect.mjs +0 -115
  43. package/hub/team/lead-control.mjs +0 -191
  44. package/hub/team/session-sync.mjs +0 -316
  45. package/hub/team/swarm-intent.mjs +0 -18
  46. package/hub/team/synapse-cli.mjs +0 -458
  47. package/hub/team/synapse-http.mjs +0 -311
  48. package/hub/team/synapse-registry.mjs +0 -618
  49. package/hub/team/tui-synapse.mjs +0 -223
  50. package/hub/team/worker-sandbox.mjs +0 -125
  51. package/hub/tools.mjs +0 -900
  52. package/hub/workers/codex-app-server-worker.mjs +0 -1067
  53. package/hub/workers/delegator-mcp.mjs +0 -1098
  54. package/hub/workers/lib/jsonrpc-stdio.mjs +0 -204
  55. package/scripts/lib/claudemd-scanner.mjs +0 -26
  56. package/scripts/lib/context.mjs +0 -51
  57. package/scripts/lib/handoff.mjs +0 -187
  58. package/scripts/lib/logger.mjs +0 -122
  59. package/scripts/lib/stealth-fetch.mjs +0 -176
@@ -931,22 +931,8 @@ function killOrphanPipeHelpers(sessionName) {
931
931
  */
932
932
  function killOrphanMcpProcesses(sessionName) {
933
933
  if (!IS_WINDOWS) {
934
- // macOS/Linux: 세션별 스코핑 + Hub PID 보호
934
+ // macOS/Linux: 세션별 스코핑
935
935
  const safeSessionUnix = sanitizePathPart(sessionName);
936
- let hubPidUnix = 0;
937
- try {
938
- const hubPidFile = join(
939
- homedir(),
940
- ".claude",
941
- "cache",
942
- "tfx-hub",
943
- "hub.pid",
944
- );
945
- if (existsSync(hubPidFile)) {
946
- const info = JSON.parse(readFileSync(hubPidFile, "utf8"));
947
- hubPidUnix = Number(info.pid) || 0;
948
- }
949
- } catch {}
950
936
  try {
951
937
  // MCP/result files live under `tfx-headless/<session>-<pane>.txt`, so
952
938
  // match `tfx-headless/<session>` with a trailing boundary to avoid
@@ -963,7 +949,7 @@ function killOrphanMcpProcesses(sessionName) {
963
949
  if (pids) {
964
950
  for (const p of pids.split("\n").filter(Boolean)) {
965
951
  const numPid = Number(p);
966
- if (numPid === hubPidUnix || numPid <= 0) continue;
952
+ if (numPid <= 0) continue;
967
953
  try {
968
954
  process.kill(numPid, "SIGTERM");
969
955
  } catch {}
@@ -975,22 +961,6 @@ function killOrphanMcpProcesses(sessionName) {
975
961
  // Windows: escape + trailing boundary (mirror of the macOS branch).
976
962
  const safeSession = escapeRegex(sanitizePathPart(sessionName));
977
963
 
978
- // Hub PID 보호 — Hub 프로세스를 고아로 잘못 식별하지 않도록
979
- let hubPid = null;
980
- try {
981
- const hubPidPath = join(
982
- homedir(),
983
- ".claude",
984
- "cache",
985
- "tfx-hub",
986
- "hub.pid",
987
- );
988
- if (existsSync(hubPidPath)) {
989
- const hubInfo = JSON.parse(readFileSync(hubPidPath, "utf8"));
990
- hubPid = Number(hubInfo?.pid);
991
- }
992
- } catch {}
993
-
994
964
  try {
995
965
  // 세션 결과 디렉토리 패턴으로 MCP 서버 프로세스 식별
996
966
  const output = childProcess.execSync(
@@ -1005,7 +975,7 @@ function killOrphanMcpProcesses(sessionName) {
1005
975
  const pids = output
1006
976
  .split(/\r?\n/)
1007
977
  .map((l) => Number.parseInt(l.trim(), 10))
1008
- .filter((p) => Number.isFinite(p) && p > 0 && p !== hubPid);
978
+ .filter((p) => Number.isFinite(p) && p > 0);
1009
979
  for (const pid of pids) {
1010
980
  killProcessTree(pid);
1011
981
  }
@@ -96,7 +96,7 @@ export function contextGuard(
96
96
  : {};
97
97
  }
98
98
 
99
- async function findCodexRollout(threadId) {
99
+ export async function findCodexRollout(threadId) {
100
100
  if (!/^[a-zA-Z0-9-]+$/u.test(threadId || "")) return null;
101
101
  const root = path.join(
102
102
  process.env.CODEX_HOME || path.join(homedir(), ".codex"),
@@ -25,12 +25,7 @@ function argVal(flag) {
25
25
  const SESSION = argVal("--session");
26
26
  const RESULT_DIR = argVal("--result-dir") ?? join(tmpdir(), "tfx-headless");
27
27
  const LAYOUT = argVal("--layout") ?? "single";
28
- const SOURCE = argVal("--source") === "files" ? "files" : "mux";
29
28
  const LEAD_PANE = argVal("--lead-pane");
30
- const parsedWorkerCount = Number.parseInt(argVal("--workers") || "0", 10);
31
- const WORKER_COUNT = Number.isFinite(parsedWorkerCount)
32
- ? Math.min(64, Math.max(0, parsedWorkerCount))
33
- : 0;
34
29
  const MUX_BIN = getMultiplexerType();
35
30
 
36
31
  if (!SESSION || !/^[a-zA-Z0-9_-]+$/u.test(SESSION)) {
@@ -39,22 +34,15 @@ if (!SESSION || !/^[a-zA-Z0-9_-]+$/u.test(SESSION)) {
39
34
  );
40
35
  process.exit(1);
41
36
  }
42
- if (SOURCE === "files" && WORKER_COUNT === 0) {
43
- process.stderr.write("ERROR: --source files requires --workers <count>\n");
37
+ try {
38
+ execFileSync(MUX_BIN, ["-V"], { encoding: "utf8", timeout: 2000 });
39
+ } catch {
40
+ process.stderr.write(
41
+ `ERROR: primary multiplexer 미설치. 설치 방법:\n${formatPsmuxInstallGuidance(" ")}\n`,
42
+ );
44
43
  process.exit(1);
45
44
  }
46
45
 
47
- if (SOURCE === "mux") {
48
- try {
49
- execFileSync(MUX_BIN, ["-V"], { encoding: "utf8", timeout: 2000 });
50
- } catch {
51
- process.stderr.write(
52
- `ERROR: primary multiplexer 미설치. 설치 방법:\n${formatPsmuxInstallGuidance(" ")}\n`,
53
- );
54
- process.exit(1);
55
- }
56
- }
57
-
58
46
  // ── 메모리 보호 상수 ──
59
47
  const MAX_BODY_BYTES = 10240;
60
48
 
@@ -182,13 +170,6 @@ function estimateProgress(lines, context = {}) {
182
170
 
183
171
  // ── psmux 래퍼 ──
184
172
  function listPanes() {
185
- if (SOURCE === "files") {
186
- return Array.from({ length: WORKER_COUNT }, (_, index) => ({
187
- index: index + 1,
188
- title: `worker-${index + 1} (daemon)`,
189
- pid: "",
190
- }));
191
- }
192
173
  try {
193
174
  const out = execFileSync(
194
175
  MUX_BIN,
@@ -215,32 +196,6 @@ function listPanes() {
215
196
  }
216
197
 
217
198
  function capturePane(paneIdx, lines = 20) {
218
- if (SOURCE === "files") {
219
- const base = join(RESULT_DIR, `${SESSION}-worker-${paneIdx}.txt`);
220
- const artifacts = [
221
- { path: base, label: "output" },
222
- { path: `${base}.partial`, label: "daemon" },
223
- { path: `${base}.err`, label: "stderr" },
224
- ];
225
- const snapshots = [];
226
- for (const artifact of artifacts) {
227
- try {
228
- const content = readFileSync(artifact.path, "utf8").trim();
229
- if (!content) continue;
230
- snapshots.push(
231
- `[${artifact.label}]\n${content.split("\n").slice(-lines).join("\n")}`,
232
- );
233
- } catch {
234
- /* artifact is optional while the daemon job is starting */
235
- }
236
- }
237
- return (
238
- snapshots.join("\n") ||
239
- `worker-${paneIdx} daemon active · waiting for output · ${Math.round(
240
- (Date.now() - startTime) / 1000,
241
- )}s`
242
- );
243
- }
244
199
  try {
245
200
  return execFileSync(
246
201
  MUX_BIN,
@@ -417,7 +372,7 @@ function ingest() {
417
372
  const tokens = extractTokenLabel(snapshot);
418
373
  const elapsed = Math.round((Date.now() - startTime) / 1000);
419
374
 
420
- if (SOURCE !== "files" && (resultSize > 10 || shellReturned)) {
375
+ if (resultSize > 10 || shellReturned) {
421
376
  const resultContent = existsSync(resultFile)
422
377
  ? readFileSync(resultFile, "utf8")
423
378
  : snapshot;
@@ -459,10 +414,8 @@ function ingest() {
459
414
  // 진행 중
460
415
  const progress = estimateProgress(lines, {
461
416
  tokens,
462
- // daemon output files grow while the job is still running; file size is
463
- // activity evidence, not a completion signal in read-only file mode.
464
- resultSize: SOURCE === "files" ? 0 : resultSize,
465
- shellReturned: SOURCE === "files" ? false : shellReturned,
417
+ resultSize,
418
+ shellReturned,
466
419
  done: false,
467
420
  });
468
421
  const verdict = lastLine;
package/hub/team/tui.mjs CHANGED
@@ -44,11 +44,6 @@ import {
44
44
  wrapLine,
45
45
  wrapText as wrapTextAll,
46
46
  } from "./tui-core.mjs";
47
- import {
48
- createMetricsCollector,
49
- createSynapseEventStream,
50
- renderMetricsTier1,
51
- } from "./tui-synapse.mjs";
52
47
  import {
53
48
  createPanelResizer,
54
49
  createSearchState,
@@ -934,19 +929,6 @@ export function createLogDashboard(opts = {}) {
934
929
  initialRatio: focus === "detail" ? 0.2 : 0.3,
935
930
  });
936
931
 
937
- // Synapse 실시간 관제 (Phase 3)
938
- const synapseMetrics = deps.synapseMetrics || createMetricsCollector();
939
- const synapseStream =
940
- deps.synapseStream ||
941
- createSynapseEventStream({
942
- onEvent(event) {
943
- synapseMetrics.ingest(event);
944
- },
945
- fetchImpl: deps.synapseFetch,
946
- });
947
- // Synapse 자동 시작 (옵트인: deps.enableSynapse)
948
- if (deps.enableSynapse) synapseStream.start();
949
-
950
932
  // virtual row buffer (altScreen 전용)
951
933
  const rowBuf = new RowBuffer();
952
934
 
@@ -1017,7 +999,6 @@ export function createLogDashboard(opts = {}) {
1017
999
  function doClose() {
1018
1000
  if (closed) return;
1019
1001
  if (timer) clearInterval(timer);
1020
- synapseStream.stop();
1021
1002
  if (inputAttached && typeof input?.off === "function")
1022
1003
  input.off("data", handleInput);
1023
1004
  if (rawModeEnabled && typeof input?.setRawMode === "function")
@@ -1369,13 +1350,6 @@ export function createLogDashboard(opts = {}) {
1369
1350
  truncate(` ${color("▸", MOCHA.green)} ${flashMessage}`, totalCols),
1370
1351
  );
1371
1352
  }
1372
- // Synapse 실시간 메트릭 (활성 시)
1373
- if (synapseStream.isRunning) {
1374
- const metricsSnap = synapseMetrics.snapshot();
1375
- tier1.push(
1376
- truncate(renderMetricsTier1(metricsSnap, totalCols), totalCols),
1377
- );
1378
- }
1379
1353
  // 검색 프롬프트 (/ 모드)
1380
1354
  const searchPrompt = searchState.renderPrompt(totalCols);
1381
1355
  if (searchPrompt) {
@@ -1659,17 +1633,6 @@ export function createLogDashboard(opts = {}) {
1659
1633
  return attachToSession(w);
1660
1634
  },
1661
1635
 
1662
- // Synapse 관제 API
1663
- startSynapse() {
1664
- synapseStream.start();
1665
- },
1666
- stopSynapse() {
1667
- synapseStream.stop();
1668
- },
1669
- getSynapseMetrics() {
1670
- return synapseMetrics.snapshot();
1671
- },
1672
-
1673
1636
  close() {
1674
1637
  doClose();
1675
1638
  },