triflux 10.50.2 → 10.51.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.
- package/CLAUDE.md +41 -33
- package/README.ko.md +27 -20
- package/README.md +26 -19
- package/bin/triflux.mjs +22 -393
- package/cto/brief.mjs +0 -12
- package/cto/collect.mjs +0 -73
- package/cto/current.schema.json +0 -4
- package/cto/status.mjs +2 -50
- package/hooks/agy-session-hook.mjs +11 -56
- package/hooks/codex-session-hook.mjs +11 -101
- package/hub/bridge.mjs +1 -79
- package/hub/cli-adapter-base.mjs +12 -90
- package/hub/codex-adapter.mjs +0 -1
- package/hub/codex-preflight.mjs +5 -28
- package/hub/lib/known-errors.json +2 -2
- package/hub/lib/process-utils.mjs +0 -123
- package/hub/lib/spawn-trace.mjs +3 -2
- package/hub/lib/timeout-defaults.mjs +0 -1
- package/hub/role-contract.mjs +0 -2
- package/hub/team/agent-map.json +0 -1
- package/hub/team/ansi.mjs +1 -35
- package/hub/team/backend.mjs +9 -145
- package/hub/team/cli/commands/attach.mjs +1 -17
- package/hub/team/cli/commands/control.mjs +12 -38
- package/hub/team/cli/commands/debug.mjs +1 -37
- package/hub/team/cli/commands/focus.mjs +5 -31
- package/hub/team/cli/commands/interrupt.mjs +6 -25
- package/hub/team/cli/commands/kill.mjs +1 -30
- package/hub/team/cli/commands/list.mjs +0 -16
- package/hub/team/cli/commands/send.mjs +6 -26
- package/hub/team/cli/commands/start/index.mjs +41 -133
- package/hub/team/cli/commands/start/parse-args.mjs +15 -40
- package/hub/team/cli/commands/start/start-headless.mjs +138 -105
- package/hub/team/cli/commands/start/start-mux.mjs +0 -3
- package/hub/team/cli/commands/status.mjs +2 -57
- package/hub/team/cli/commands/stop.mjs +14 -19
- package/hub/team/cli/help.mjs +4 -5
- package/hub/team/cli/manifest.mjs +5 -1
- package/hub/team/cli/render.mjs +0 -12
- package/hub/team/cli/services/hub-client.mjs +2 -88
- package/hub/team/cli/services/runtime-mode.mjs +27 -98
- package/hub/team/handoff.mjs +3 -34
- package/hub/team/headless.mjs +13 -754
- package/hub/team/orchestrator.mjs +4 -30
- package/hub/team/pane.mjs +6 -28
- package/hub/team/psmux.mjs +0 -1
- package/hub/team/remote-session.mjs +1 -2
- package/hub/team/session.mjs +7 -91
- package/hub/team/swarm-intent.mjs +0 -198
- package/hub/team/tui-core.mjs +1 -1
- package/hub/team/tui-viewer.mjs +2 -2
- package/hub/team/tui.mjs +8 -269
- package/hub/team/wt-manager.mjs +2 -2
- package/hub/workers/factory.mjs +4 -37
- package/hub/workers/lib/jsonrpc-ws-uds.mjs +0 -2
- package/hud/cli-policy.mjs +0 -22
- package/hud/constants.mjs +11 -26
- package/hud/hud-qos-status.mjs +23 -51
- package/hud/providers/gemini.mjs +105 -20
- package/hud/renderers.mjs +50 -104
- package/hud/utils.mjs +2 -2
- package/package.json +6 -3
- package/scripts/__tests__/spawn-trace.test.mjs +16 -0
- package/scripts/cache-warmup.mjs +6 -34
- package/scripts/claude-login-detect.mjs +0 -1
- package/scripts/claudemd-sync.mjs +1 -28
- package/scripts/completions/tfx.bash +3 -12
- package/scripts/completions/tfx.fish +3 -6
- package/scripts/completions/tfx.zsh +4 -13
- package/scripts/lib/agent-route-policy.mjs +162 -14
- package/scripts/lib/claudemd-scanner.mjs +2 -199
- package/scripts/lib/cli-claude.mjs +0 -2
- package/scripts/lib/context.mjs +3 -19
- package/scripts/lib/env-probe.mjs +5 -64
- package/scripts/lib/gemini-profiles.mjs +2 -69
- package/scripts/lib/machine-profile.mjs +3 -17
- package/scripts/lib/mcp-filter.mjs +109 -53
- package/scripts/lib/mcp-health.mjs +2 -2
- package/scripts/lib/mcp-server-catalog.mjs +2 -2
- package/scripts/lib/psmux-info.mjs +11 -59
- package/scripts/lib/session-presence.mjs +1 -1
- package/scripts/lib/skill-template.mjs +0 -245
- package/scripts/pack.mjs +3 -26
- package/scripts/preflight-cache.mjs +5 -18
- package/scripts/release/check-packages-mirror.mjs +0 -1
- package/scripts/release/version-manifest.json +9 -1
- package/scripts/setup.mjs +69 -2
- package/scripts/tfx-route-post.mjs +5 -61
- package/scripts/tfx-route-worker.mjs +4 -79
- package/scripts/tfx-route.sh +161 -1427
- package/skills/tfx-auto/SKILL.md +122 -740
- package/skills/tfx-auto/references/consensus-schema.md +161 -0
- package/skills/tfx-auto/references/tmux-observation.md +97 -0
- package/skills/tfx-remote/SKILL.md +24 -87
- package/skills/tfx-research/SKILL.md +11 -11
- package/skills/tfx-review/SKILL.md +33 -35
- package/skills/tfx-ship/SKILL.md +6 -27
- package/skills/tfx-wt/SKILL.md +34 -68
- package/config/routing-policy.json +0 -124
- package/docs/assets/consensus-flow.svg +0 -125
- package/docs/assets/deep-vs-light.svg +0 -193
- package/docs/assets/demo-dark.gif +0 -0
- package/docs/assets/demo-light.gif +0 -0
- package/docs/assets/demo-psmux.gif +0 -0
- package/hub/dynamic-routing-engine.mjs +0 -511
- package/hub/lib/risk-tier.mjs +0 -53
- package/hub/lib/ssh-command.mjs +0 -231
- package/hub/lib/staged-file-detect.mjs +0 -43
- package/hub/lib/tfx-route-args.mjs +0 -353
- package/hub/routing-snapshot.mjs +0 -261
- package/hub/team/build-worker-prompt.mjs +0 -92
- package/hub/team/check-mcp-hub.mjs +0 -49
- package/hub/team/claude-native-bridge.mjs +0 -987
- package/hub/team/cli/commands/start/start-in-process.mjs +0 -50
- package/hub/team/cli/commands/start/start-wt.mjs +0 -86
- package/hub/team/cli/services/native-control.mjs +0 -145
- package/hub/team/codex-review.mjs +0 -520
- package/hub/team/conductor-mesh-bridge.mjs +0 -122
- package/hub/team/conductor.mjs +0 -1529
- package/hub/team/consensus-meta.mjs +0 -176
- package/hub/team/cto-pull.mjs +0 -31
- package/hub/team/daemon-pty-tmux-bridge.mjs +0 -146
- package/hub/team/dashboard.mjs +0 -322
- package/hub/team/event-log.mjs +0 -84
- package/hub/team/execution-mode.mjs +0 -324
- package/hub/team/extract-completion-payload.mjs +0 -110
- package/hub/team/headless-bridge-session.mjs +0 -17
- package/hub/team/health-probe.mjs +0 -435
- package/hub/team/interactive-native-launcher.mjs +0 -119
- package/hub/team/interactive-native-worker.mjs +0 -80
- package/hub/team/interactive-tui-transport.mjs +0 -479
- package/hub/team/launcher-template.mjs +0 -144
- package/hub/team/mcp-selector.mjs +0 -145
- package/hub/team/native-supervisor.mjs +0 -460
- package/hub/team/native.mjs +0 -727
- package/hub/team/recovery-store.mjs +0 -149
- package/hub/team/remote-probe.mjs +0 -292
- package/hub/team/remote-watcher.mjs +0 -506
- package/hub/team/runtime-strategy.mjs +0 -200
- package/hub/team/schemas/worker-completion.json +0 -39
- package/hub/team/sentinel-capture.mjs +0 -127
- package/hub/team/swarm-cli.mjs +0 -390
- package/hub/team/swarm-hypervisor.mjs +0 -2206
- package/hub/team/swarm-locks.mjs +0 -335
- package/hub/team/swarm-planner.mjs +0 -371
- package/hub/team/swarm-preflight.mjs +0 -366
- package/hub/team/swarm-reconciler.mjs +0 -242
- package/hub/team/tui-remote-adapter.mjs +0 -377
- package/hub/team/worker-completion-validator.mjs +0 -79
- package/hub/team/worktree-lifecycle.mjs +0 -639
- package/hub/team/wt-templates.json +0 -43
- package/hub/workers/antigravity-route-worker.mjs +0 -179
- package/mesh/index.mjs +0 -69
- package/mesh/mesh-budget.mjs +0 -137
- package/mesh/mesh-heartbeat.mjs +0 -100
- package/mesh/mesh-protocol.mjs +0 -96
- package/mesh/mesh-queue.mjs +0 -163
- package/mesh/mesh-registry.mjs +0 -78
- package/mesh/mesh-router.mjs +0 -77
- package/scripts/__tests__/skill-surface.test.mjs +0 -93
- package/scripts/demo.mjs +0 -197
- package/scripts/doctor-dynamic-routing.mjs +0 -87
- package/scripts/lib/dynamic-route-cli.mjs +0 -107
- package/skills/_templates/base.md +0 -4
- package/skills/_templates/deep.md +0 -6
- package/skills/shared/telemetry-segment.md +0 -6
package/bin/triflux.mjs
CHANGED
|
@@ -3,7 +3,6 @@ import { setTimeout as delay } from "node:timers/promises";
|
|
|
3
3
|
import { execFileSync, execSync, spawn } from "child_process";
|
|
4
4
|
// triflux CLI — setup, doctor, version
|
|
5
5
|
import {
|
|
6
|
-
appendFileSync,
|
|
7
6
|
chmodSync,
|
|
8
7
|
closeSync,
|
|
9
8
|
copyFileSync,
|
|
@@ -28,10 +27,6 @@ import {
|
|
|
28
27
|
checkNetworkAvailability,
|
|
29
28
|
validateRuntimeCachePaths,
|
|
30
29
|
} from "../hub/lib/cache-guard.mjs";
|
|
31
|
-
import {
|
|
32
|
-
decideDispatchMode,
|
|
33
|
-
parseArgs as parseRouteArgs,
|
|
34
|
-
} from "../hub/lib/tfx-route-args.mjs";
|
|
35
30
|
import { getPipelineStateDbPath } from "../hub/pipeline/state.mjs";
|
|
36
31
|
import { getVersionHash } from "../hub/state.mjs";
|
|
37
32
|
import {
|
|
@@ -71,6 +66,7 @@ import {
|
|
|
71
66
|
buildWindowsHubAutostartCommand,
|
|
72
67
|
ensureCodexHubServerConfig,
|
|
73
68
|
ensureCodexProfiles,
|
|
69
|
+
ensureTrifluxMods,
|
|
74
70
|
getVersion,
|
|
75
71
|
getWindowsHubAutostartStatus,
|
|
76
72
|
isLocalDevSkillDir,
|
|
@@ -108,10 +104,8 @@ const GREEN_BRIGHT = "\x1b[38;5;82m";
|
|
|
108
104
|
const RED_BRIGHT = "\x1b[38;5;196m";
|
|
109
105
|
|
|
110
106
|
// ── 브랜드 요소 ──
|
|
111
|
-
const _BRAND = `${AMBER}${BOLD}triflux${RESET}`;
|
|
112
107
|
const VER = `${DIM}v${PKG.version}${RESET}`;
|
|
113
108
|
const LINE = `${GRAY}${"─".repeat(48)}${RESET}`;
|
|
114
|
-
const _DOT = `${GRAY}·${RESET}`;
|
|
115
109
|
const STALE_TEAM_MAX_AGE_SEC = 3600;
|
|
116
110
|
const DEFAULT_TMUX_CLEANUP_PREFIX = "tfx-*";
|
|
117
111
|
const DEFAULT_TMUX_CLEANUP_AGE_MIN = 60;
|
|
@@ -119,7 +113,6 @@ const ANSI_PATTERN = /\x1B\[[0-?]*[ -/]*[@-~]/g;
|
|
|
119
113
|
const HUB_DEFAULT_PORT = 27888;
|
|
120
114
|
const DOCTOR_HUB_PID_FILE = join(CLAUDE_DIR, "cache", "tfx-hub", "hub.pid");
|
|
121
115
|
|
|
122
|
-
const _EXIT_SUCCESS = 0;
|
|
123
116
|
const EXIT_ERROR = 1;
|
|
124
117
|
const EXIT_ARG_ERROR = 2;
|
|
125
118
|
const EXIT_CLI_MISSING = 3;
|
|
@@ -131,43 +124,15 @@ const JSON_OUTPUT = RAW_ARGS.includes("--json");
|
|
|
131
124
|
const NORMALIZED_ARGS = RAW_ARGS.filter((arg) => arg !== "--json");
|
|
132
125
|
|
|
133
126
|
const CLI_COMMAND_SCHEMAS = Object.freeze({
|
|
134
|
-
|
|
135
|
-
usage:
|
|
136
|
-
|
|
137
|
-
description:
|
|
138
|
-
"tfx-auto 라우팅 결정을 CLI에서 미리보기/직렬화 (실행 skill front door와 같은 flag surface)",
|
|
127
|
+
setup: {
|
|
128
|
+
usage: "tfx setup [--dry-run] [--enable-hub-autostart] [--mods]",
|
|
129
|
+
description: "파일 동기화 + HUD/MCP 설정",
|
|
139
130
|
options: [
|
|
140
131
|
{
|
|
141
|
-
name: "--
|
|
142
|
-
type: "string",
|
|
143
|
-
description: "실행 lane 강제: auto|codex|antigravity|claude",
|
|
144
|
-
},
|
|
145
|
-
{
|
|
146
|
-
name: "--mode <name>",
|
|
147
|
-
type: "string",
|
|
148
|
-
description: "라우팅 모드: quick|deep|consensus|live",
|
|
149
|
-
},
|
|
150
|
-
{
|
|
151
|
-
name: "--rounds <N>",
|
|
152
|
-
type: "number",
|
|
153
|
-
description: "live peer 왕복 횟수 (기본 4, --mode live 전용)",
|
|
154
|
-
},
|
|
155
|
-
{
|
|
156
|
-
name: "--parallel <1|N|swarm>",
|
|
157
|
-
type: "string",
|
|
158
|
-
description: "단일/로컬 병렬/PRD swarm 라우팅 힌트",
|
|
159
|
-
},
|
|
160
|
-
{
|
|
161
|
-
name: "--json",
|
|
132
|
+
name: "--mods",
|
|
162
133
|
type: "boolean",
|
|
163
|
-
description: "
|
|
134
|
+
description: "Claude Code mods 설치 (2.1.287 이상)",
|
|
164
135
|
},
|
|
165
|
-
],
|
|
166
|
-
},
|
|
167
|
-
setup: {
|
|
168
|
-
usage: "tfx setup [--dry-run] [--enable-hub-autostart]",
|
|
169
|
-
description: "파일 동기화 + HUD/MCP 설정",
|
|
170
|
-
options: [
|
|
171
136
|
{
|
|
172
137
|
name: "--dry-run",
|
|
173
138
|
type: "boolean",
|
|
@@ -188,7 +153,7 @@ const CLI_COMMAND_SCHEMAS = Object.freeze({
|
|
|
188
153
|
},
|
|
189
154
|
doctor: {
|
|
190
155
|
usage:
|
|
191
|
-
"tfx doctor [--fix] [--reset] [--audit] [--diagnose] [--purge-logs] [--
|
|
156
|
+
"tfx doctor [--fix] [--reset] [--audit] [--diagnose] [--purge-logs] [--cleanup-stale-hubs --dry-run|--apply] [--cleanup-stale-tmux --prefix tfx-* --age-min N --dry-run|--apply] [--json]",
|
|
192
157
|
description: "설치 상태 진단 및 자동 복구",
|
|
193
158
|
options: [
|
|
194
159
|
{
|
|
@@ -218,12 +183,6 @@ const CLI_COMMAND_SCHEMAS = Object.freeze({
|
|
|
218
183
|
description:
|
|
219
184
|
"--fix 와 함께 사용. cli-issues.jsonl 에서 7일 초과 항목 물리 삭제 (#144)",
|
|
220
185
|
},
|
|
221
|
-
{
|
|
222
|
-
name: "--dynamic-routing",
|
|
223
|
-
type: "boolean",
|
|
224
|
-
description:
|
|
225
|
-
"Phase 1 dynamic routing 상태 진단 (env / policy / snapshot cache / preview decision)",
|
|
226
|
-
},
|
|
227
186
|
{
|
|
228
187
|
name: "--cleanup-stale-hubs",
|
|
229
188
|
type: "boolean",
|
|
@@ -397,46 +356,6 @@ const CLI_COMMAND_SCHEMAS = Object.freeze({
|
|
|
397
356
|
},
|
|
398
357
|
],
|
|
399
358
|
},
|
|
400
|
-
swarm: {
|
|
401
|
-
usage:
|
|
402
|
-
"tfx swarm [run|preflight] <prd-path> [--dry-run|--json|--filter <shard>]",
|
|
403
|
-
description: "PRD 기반 멀티모델 x 멀티기기 스웜 실행 (#93)",
|
|
404
|
-
subcommands: {
|
|
405
|
-
run: "tfx swarm run <prd-path> — verb 명시 실행 (기본 경로와 동일)",
|
|
406
|
-
preflight:
|
|
407
|
-
"tfx swarm preflight <prd-path> [--json] — 실행 전 go/no-go 리포트 출력",
|
|
408
|
-
plan: "tfx swarm plan <prd-path> [--json] — 실행 없이 계획만 출력",
|
|
409
|
-
list: "tfx swarm list [--json] — 활성 스웜 세션 조회 (synapse status)",
|
|
410
|
-
status: "tfx swarm status [--json] — list alias",
|
|
411
|
-
},
|
|
412
|
-
options: [
|
|
413
|
-
{
|
|
414
|
-
name: "--dry-run",
|
|
415
|
-
type: "boolean",
|
|
416
|
-
description: "PRD 분석만 수행, shard를 실행하지 않음",
|
|
417
|
-
},
|
|
418
|
-
{
|
|
419
|
-
name: "--json",
|
|
420
|
-
type: "boolean",
|
|
421
|
-
description: "구조화된 JSON 출력",
|
|
422
|
-
},
|
|
423
|
-
{
|
|
424
|
-
name: "--filter",
|
|
425
|
-
type: "string",
|
|
426
|
-
description: "특정 shard만 실행 (이름 매칭)",
|
|
427
|
-
},
|
|
428
|
-
{
|
|
429
|
-
name: "--max-restarts",
|
|
430
|
-
type: "number",
|
|
431
|
-
description: "shard별 최대 재시작 횟수 (기본 2)",
|
|
432
|
-
},
|
|
433
|
-
{
|
|
434
|
-
name: "--logs-dir",
|
|
435
|
-
type: "string",
|
|
436
|
-
description: "이벤트 로그 출력 디렉토리 오버라이드",
|
|
437
|
-
},
|
|
438
|
-
],
|
|
439
|
-
},
|
|
440
359
|
why: {
|
|
441
360
|
usage: "tfx why <path> [--json]",
|
|
442
361
|
description: "해당 경로의 마지막 커밋에서 X-Intent 트레일러 추출",
|
|
@@ -491,9 +410,9 @@ const CLI_COMMAND_SCHEMAS = Object.freeze({
|
|
|
491
410
|
description: "멀티-CLI 팀 모드",
|
|
492
411
|
options: [
|
|
493
412
|
{
|
|
494
|
-
name: "--
|
|
495
|
-
type: "
|
|
496
|
-
description: "
|
|
413
|
+
name: "--teammate-mode",
|
|
414
|
+
type: "string",
|
|
415
|
+
description: "실행 모드: auto|headless|tmux|psmux (Windows)",
|
|
497
416
|
},
|
|
498
417
|
{
|
|
499
418
|
name: "--no-dashboard",
|
|
@@ -574,33 +493,6 @@ const CLI_COMMAND_SCHEMAS = Object.freeze({
|
|
|
574
493
|
},
|
|
575
494
|
],
|
|
576
495
|
},
|
|
577
|
-
review: {
|
|
578
|
-
usage:
|
|
579
|
-
"tfx review [ref] [--base <ref>] [--timeout <seconds>] [--shard off|per-file] [--json]",
|
|
580
|
-
description: "Codex 기반 git diff review 실행",
|
|
581
|
-
options: [
|
|
582
|
-
{
|
|
583
|
-
name: "--base <ref>",
|
|
584
|
-
type: "string",
|
|
585
|
-
description: "비교 기준 ref",
|
|
586
|
-
},
|
|
587
|
-
{
|
|
588
|
-
name: "--timeout <seconds>",
|
|
589
|
-
type: "number",
|
|
590
|
-
description: "review 실행 timeout (기본 180)",
|
|
591
|
-
},
|
|
592
|
-
{
|
|
593
|
-
name: "--shard <mode>",
|
|
594
|
-
type: "string",
|
|
595
|
-
description: "off 또는 per-file",
|
|
596
|
-
},
|
|
597
|
-
{
|
|
598
|
-
name: "--json",
|
|
599
|
-
type: "boolean",
|
|
600
|
-
description: "review 결과 JSON 출력",
|
|
601
|
-
},
|
|
602
|
-
],
|
|
603
|
-
},
|
|
604
496
|
monitor: {
|
|
605
497
|
usage: "tfx monitor",
|
|
606
498
|
description: "터미널 TUI 모니터 실행",
|
|
@@ -2000,6 +1892,7 @@ function cmdSetup(options = {}) {
|
|
|
2000
1892
|
fromUpdate = false,
|
|
2001
1893
|
overrideVersion,
|
|
2002
1894
|
enableHubAutostart = false,
|
|
1895
|
+
mods = false,
|
|
2003
1896
|
} = options;
|
|
2004
1897
|
if (dryRun) {
|
|
2005
1898
|
printJson(buildSetupDryRunPlan());
|
|
@@ -2026,6 +1919,7 @@ function cmdSetup(options = {}) {
|
|
|
2026
1919
|
syncFile(target.src, target.dst, target.label);
|
|
2027
1920
|
}
|
|
2028
1921
|
reportSkillSync();
|
|
1922
|
+
ensureTrifluxMods({ install: mods, log: console.log, warn });
|
|
2029
1923
|
|
|
2030
1924
|
// ── psmux 기본 셸 자동 수정 (cmd.exe → PowerShell) ──
|
|
2031
1925
|
if (process.platform === "win32" && which("psmux")) {
|
|
@@ -3952,9 +3846,7 @@ async function cmdDoctor(options = {}) {
|
|
|
3952
3846
|
}
|
|
3953
3847
|
|
|
3954
3848
|
// ── Codex Config Health (BUG-H #132) ──
|
|
3955
|
-
//
|
|
3956
|
-
// ~/.codex/config.toml.pre-exec 가 남아 [mcp_servers.*] 섹션이 영구 손실된다.
|
|
3957
|
-
// orphan backup 을 감지하고 --fix 로 자동 복원한다.
|
|
3849
|
+
// 이전 버전의 swap이 남긴 백업을 감지하고 --fix로 복원한다.
|
|
3958
3850
|
section("Codex Config Health");
|
|
3959
3851
|
{
|
|
3960
3852
|
const codexConfig = join(CODEX_DIR, "config.toml");
|
|
@@ -4404,72 +4296,21 @@ async function cmdUpdate(args = []) {
|
|
|
4404
4296
|
console.log(`${GREEN}${BOLD}✓ 업데이트 완료${RESET}\n`);
|
|
4405
4297
|
}
|
|
4406
4298
|
|
|
4407
|
-
function readPackagedSkillMetadata(skillName) {
|
|
4408
|
-
const skillPath = join(PKG_ROOT, "skills", skillName, "SKILL.md");
|
|
4409
|
-
if (!existsSync(skillPath)) return null;
|
|
4410
|
-
const metadata = { name: skillName, deprecated: false, supersededBy: null };
|
|
4411
|
-
let inFrontmatter = false;
|
|
4412
|
-
for (const line of readFileSync(skillPath, "utf8").split(/\r?\n/)) {
|
|
4413
|
-
if (line.trim() === "---") {
|
|
4414
|
-
if (!inFrontmatter) {
|
|
4415
|
-
inFrontmatter = true;
|
|
4416
|
-
continue;
|
|
4417
|
-
}
|
|
4418
|
-
break;
|
|
4419
|
-
}
|
|
4420
|
-
if (!inFrontmatter) continue;
|
|
4421
|
-
const match = line.match(/^([A-Za-z0-9_-]+):\s*(.*)$/);
|
|
4422
|
-
if (!match) continue;
|
|
4423
|
-
const [, key, rawValue] = match;
|
|
4424
|
-
const value = rawValue.trim().replace(/^["']|["']$/g, "");
|
|
4425
|
-
if (key === "deprecated") metadata.deprecated = value === "true";
|
|
4426
|
-
if (key === "superseded-by") metadata.supersededBy = value || null;
|
|
4427
|
-
}
|
|
4428
|
-
return metadata;
|
|
4429
|
-
}
|
|
4430
|
-
|
|
4431
|
-
function listDeprecatedPackagedSkillAliases(pluginSkills, installedSkills) {
|
|
4432
|
-
if (!existsSync(pluginSkills)) return [];
|
|
4433
|
-
return readdirSync(pluginSkills)
|
|
4434
|
-
.sort()
|
|
4435
|
-
.map((name) => readPackagedSkillMetadata(name))
|
|
4436
|
-
.filter((metadata) => metadata?.deprecated)
|
|
4437
|
-
.map((metadata) => ({
|
|
4438
|
-
alias: metadata.name,
|
|
4439
|
-
source: metadata.supersededBy || "deprecated",
|
|
4440
|
-
installed: existsSync(join(installedSkills, metadata.name, "SKILL.md")),
|
|
4441
|
-
deprecated: true,
|
|
4442
|
-
}));
|
|
4443
|
-
}
|
|
4444
|
-
|
|
4445
4299
|
function cmdList(options = {}) {
|
|
4446
4300
|
const { json = false } = options;
|
|
4447
4301
|
const pluginSkills = join(PKG_ROOT, "skills");
|
|
4448
4302
|
const installedSkills = join(CLAUDE_DIR, "skills");
|
|
4449
4303
|
const packageSkills = [];
|
|
4450
4304
|
const userSkills = [];
|
|
4451
|
-
const skillAliases = listDeprecatedPackagedSkillAliases(
|
|
4452
|
-
pluginSkills,
|
|
4453
|
-
installedSkills,
|
|
4454
|
-
);
|
|
4455
|
-
const aliasNames = new Set([
|
|
4456
|
-
...SKILL_ALIASES.map(({ alias }) => alias),
|
|
4457
|
-
...skillAliases.map(({ alias }) => alias),
|
|
4458
|
-
]);
|
|
4459
4305
|
|
|
4460
4306
|
if (existsSync(pluginSkills)) {
|
|
4461
4307
|
for (const name of readdirSync(pluginSkills).sort()) {
|
|
4462
4308
|
const src = join(pluginSkills, name, "SKILL.md");
|
|
4463
4309
|
if (!existsSync(src)) continue;
|
|
4464
|
-
const metadata = readPackagedSkillMetadata(name);
|
|
4465
4310
|
const dst = join(installedSkills, name, "SKILL.md");
|
|
4466
4311
|
packageSkills.push({
|
|
4467
4312
|
name,
|
|
4468
4313
|
installed: existsSync(dst),
|
|
4469
|
-
...(metadata?.deprecated ? { deprecated: true } : {}),
|
|
4470
|
-
...(metadata?.supersededBy
|
|
4471
|
-
? { superseded_by: metadata.supersededBy }
|
|
4472
|
-
: {}),
|
|
4473
4314
|
});
|
|
4474
4315
|
}
|
|
4475
4316
|
}
|
|
@@ -4479,7 +4320,7 @@ function cmdList(options = {}) {
|
|
|
4479
4320
|
);
|
|
4480
4321
|
if (existsSync(installedSkills)) {
|
|
4481
4322
|
for (const name of readdirSync(installedSkills).sort()) {
|
|
4482
|
-
if (pkgNames.has(name)
|
|
4323
|
+
if (pkgNames.has(name)) continue;
|
|
4483
4324
|
const skill = join(installedSkills, name, "SKILL.md");
|
|
4484
4325
|
if (!existsSync(skill)) continue;
|
|
4485
4326
|
userSkills.push(name);
|
|
@@ -4489,7 +4330,6 @@ function cmdList(options = {}) {
|
|
|
4489
4330
|
if (json) {
|
|
4490
4331
|
printJson({
|
|
4491
4332
|
package_skills: packageSkills,
|
|
4492
|
-
skill_aliases: skillAliases,
|
|
4493
4333
|
user_skills: userSkills,
|
|
4494
4334
|
install_path: installedSkills,
|
|
4495
4335
|
});
|
|
@@ -4516,19 +4356,6 @@ function cmdList(options = {}) {
|
|
|
4516
4356
|
}
|
|
4517
4357
|
if (userSkills.length === 0) console.log(` ${GRAY}없음${RESET}`);
|
|
4518
4358
|
|
|
4519
|
-
if (skillAliases.length > 0) {
|
|
4520
|
-
section("호환 alias");
|
|
4521
|
-
for (const entry of skillAliases) {
|
|
4522
|
-
const icon = entry.installed
|
|
4523
|
-
? `${GREEN_BRIGHT}↳${RESET}`
|
|
4524
|
-
: `${RED_BRIGHT}↳${RESET}`;
|
|
4525
|
-
const status = entry.installed ? "" : ` ${GRAY}(미설치)${RESET}`;
|
|
4526
|
-
console.log(
|
|
4527
|
-
` ${icon} ${BOLD}${entry.alias}${RESET} ${GRAY}→ ${entry.source}${RESET}${entry.deprecated ? ` ${YELLOW}(deprecated)${RESET}` : ""}${status}`,
|
|
4528
|
-
);
|
|
4529
|
-
}
|
|
4530
|
-
}
|
|
4531
|
-
|
|
4532
4359
|
console.log(`\n ${LINE}`);
|
|
4533
4360
|
console.log(` ${GRAY}${installedSkills}${RESET}\n`);
|
|
4534
4361
|
}
|
|
@@ -5021,11 +4848,11 @@ ${updateNotice}
|
|
|
5021
4848
|
|
|
5022
4849
|
${WHITE_BRIGHT}tfx setup${RESET} ${GRAY}파일 동기화 + HUD 설정${RESET}
|
|
5023
4850
|
${DIM} --dry-run${RESET} ${GRAY}변경 예정 작업을 JSON으로 미리보기${RESET}
|
|
4851
|
+
${DIM} --mods${RESET} ${GRAY}Claude Code mods 설치 (2.1.287 이상)${RESET}
|
|
5024
4852
|
${WHITE_BRIGHT}tfx doctor${RESET} ${GRAY}CLI 진단 + 이슈 확인${RESET}
|
|
5025
4853
|
${DIM} --fix${RESET} ${GRAY}진단 + 자동 수정${RESET}
|
|
5026
4854
|
${DIM} --reset${RESET} ${GRAY}캐시 전체 초기화${RESET}
|
|
5027
4855
|
${DIM} --json${RESET} ${GRAY}구조화된 진단 결과 JSON 출력${RESET}
|
|
5028
|
-
${WHITE_BRIGHT}tfx auto${RESET} ${GRAY}tfx-auto 라우팅 결정 미리보기 (--cli codex|antigravity|claude)${RESET}
|
|
5029
4856
|
${WHITE_BRIGHT}tfx stealth-fetch${RESET} ${GRAY}cloakbrowser 기반 URL fetch (JSON stdout)${RESET}
|
|
5030
4857
|
${WHITE_BRIGHT}tfx mcp${RESET} ${GRAY}MCP registry 관리 (list/sync/add/remove)${RESET}
|
|
5031
4858
|
${WHITE_BRIGHT}tfx update${RESET} ${GRAY}최신 안정 버전으로 업데이트${RESET}
|
|
@@ -5035,9 +4862,7 @@ ${updateNotice}
|
|
|
5035
4862
|
${WHITE_BRIGHT}tfx schema${RESET} ${GRAY}CLI/Hub schema JSON 출력${RESET}
|
|
5036
4863
|
${WHITE_BRIGHT}tfx hub${RESET} ${GRAY}MCP 메시지 버스 관리 (start/stop/status)${RESET}
|
|
5037
4864
|
${WHITE_BRIGHT}tfx multi${RESET} ${GRAY}멀티-CLI 팀 모드 (tmux + Hub)${RESET}
|
|
5038
|
-
${WHITE_BRIGHT}tfx swarm${RESET} ${GRAY}PRD 기반 worktree 격리 병렬 실행 (run/plan/list)${RESET}
|
|
5039
4865
|
${WHITE_BRIGHT}tfx synapse${RESET} ${GRAY}스웜 세션 registry 조회 / lease 관리${RESET}
|
|
5040
|
-
${WHITE_BRIGHT}tfx review${RESET} ${GRAY}Codex 기반 git diff review${RESET}
|
|
5041
4866
|
${WHITE_BRIGHT}tfx why${RESET} ${GRAY}경로의 마지막 커밋 X-Intent 트레일러 추출${RESET}
|
|
5042
4867
|
${WHITE_BRIGHT}tfx codex-team${RESET} ${GRAY}Codex 전용 팀 모드 (기본 lead/agents: codex)${RESET}
|
|
5043
4868
|
${WHITE_BRIGHT}tfx notion-read${RESET} ${GRAY}Notion 페이지 → 마크다운 (Codex/Gemini MCP)${RESET}
|
|
@@ -5045,7 +4870,7 @@ ${updateNotice}
|
|
|
5045
4870
|
|
|
5046
4871
|
${BOLD}Skills${RESET} ${GRAY}(Claude Code 슬래시 커맨드)${RESET}
|
|
5047
4872
|
|
|
5048
|
-
${AMBER}/tfx-auto${RESET} ${GRAY}자동 분류 + 병렬 실행 (--cli codex|antigravity|claude, --parallel N
|
|
4873
|
+
${AMBER}/tfx-auto${RESET} ${GRAY}자동 분류 + 병렬 실행 (--cli codex|antigravity|claude, --parallel N)${RESET}
|
|
5049
4874
|
${AMBER}/tfx-setup${RESET} ${GRAY}HUD 설정 + 진단${RESET}
|
|
5050
4875
|
${YELLOW}/tfx-doctor${RESET} ${GRAY}진단 + 수리 + 캐시 초기화${RESET}
|
|
5051
4876
|
|
|
@@ -5920,31 +5745,6 @@ function parsePositiveIntegerOption(args, name, fallback) {
|
|
|
5920
5745
|
return parsed;
|
|
5921
5746
|
}
|
|
5922
5747
|
|
|
5923
|
-
function applyAutoDispatchDecision(parsedArgs, decision = null) {
|
|
5924
|
-
const resolved = decision || decideDispatchMode(parsedArgs);
|
|
5925
|
-
if (resolved.warning) {
|
|
5926
|
-
process.stderr.write(`${resolved.warning}\n`);
|
|
5927
|
-
}
|
|
5928
|
-
if (resolved.escalated) {
|
|
5929
|
-
const logLine = `${JSON.stringify({
|
|
5930
|
-
at: new Date().toISOString(),
|
|
5931
|
-
issue: 281,
|
|
5932
|
-
from: "multi",
|
|
5933
|
-
to: "swarm",
|
|
5934
|
-
tasksCount: Array.isArray(parsedArgs.tasks)
|
|
5935
|
-
? parsedArgs.tasks.length
|
|
5936
|
-
: (parsedArgs.tasks ?? null),
|
|
5937
|
-
reason: resolved.reason,
|
|
5938
|
-
})}\n`;
|
|
5939
|
-
try {
|
|
5940
|
-
appendFileSync(".omc/state/auto-escalation.log", logLine, "utf8");
|
|
5941
|
-
} catch {
|
|
5942
|
-
// Fresh checkouts may not have .omc/state yet; dispatch should continue.
|
|
5943
|
-
}
|
|
5944
|
-
}
|
|
5945
|
-
return resolved;
|
|
5946
|
-
}
|
|
5947
|
-
|
|
5948
5748
|
async function main() {
|
|
5949
5749
|
const cmd = NORMALIZED_ARGS[0] || "help";
|
|
5950
5750
|
const cmdArgs = NORMALIZED_ARGS.slice(1);
|
|
@@ -5954,20 +5754,6 @@ async function main() {
|
|
|
5954
5754
|
}).catch(() => {});
|
|
5955
5755
|
|
|
5956
5756
|
switch (cmd) {
|
|
5957
|
-
case "auto": {
|
|
5958
|
-
if (cmdArgs.some(isHelpArg)) {
|
|
5959
|
-
printCommandHelp("auto");
|
|
5960
|
-
return;
|
|
5961
|
-
}
|
|
5962
|
-
const parsedArgs = parseRouteArgs(cmdArgs);
|
|
5963
|
-
const decision = applyAutoDispatchDecision(parsedArgs);
|
|
5964
|
-
if (JSON_OUTPUT) {
|
|
5965
|
-
printJson({ args: parsedArgs, dispatch: decision });
|
|
5966
|
-
} else {
|
|
5967
|
-
process.stdout.write(`${decision.mode}\n`);
|
|
5968
|
-
}
|
|
5969
|
-
return;
|
|
5970
|
-
}
|
|
5971
5757
|
case "setup":
|
|
5972
5758
|
if (cmdArgs.some(isHelpArg)) {
|
|
5973
5759
|
printCommandHelp("setup");
|
|
@@ -5977,6 +5763,7 @@ async function main() {
|
|
|
5977
5763
|
dryRun: cmdArgs.includes("--dry-run"),
|
|
5978
5764
|
fromUpdate: cmdArgs.includes("--from-update"),
|
|
5979
5765
|
enableHubAutostart: cmdArgs.includes("--enable-hub-autostart"),
|
|
5766
|
+
mods: cmdArgs.includes("--mods"),
|
|
5980
5767
|
});
|
|
5981
5768
|
return;
|
|
5982
5769
|
case "stealth-fetch":
|
|
@@ -6028,45 +5815,6 @@ async function main() {
|
|
|
6028
5815
|
}
|
|
6029
5816
|
return;
|
|
6030
5817
|
}
|
|
6031
|
-
if (cmdArgs.includes("--dynamic-routing")) {
|
|
6032
|
-
const { diagnoseDynamicRouting } = await import(
|
|
6033
|
-
"../scripts/doctor-dynamic-routing.mjs"
|
|
6034
|
-
);
|
|
6035
|
-
const report = await diagnoseDynamicRouting();
|
|
6036
|
-
if (JSON_OUTPUT) {
|
|
6037
|
-
console.log(JSON.stringify(report, null, 2));
|
|
6038
|
-
} else {
|
|
6039
|
-
const mark = (b) =>
|
|
6040
|
-
b ? `${GREEN_BRIGHT}✓${RESET}` : `${RED}✗${RESET}`;
|
|
6041
|
-
console.log(
|
|
6042
|
-
`\n ${AMBER}${BOLD}⬡ triflux doctor — dynamic routing${RESET}\n`,
|
|
6043
|
-
);
|
|
6044
|
-
console.log(
|
|
6045
|
-
` ${mark(report.enabled)} enabled: ${report.enabled} (TRIFLUX_DYNAMIC_ROUTING=${report.envFlag ?? "미설정"})`,
|
|
6046
|
-
);
|
|
6047
|
-
console.log(
|
|
6048
|
-
` ${mark(report.policyLoaded)} policy loaded: ${report.policyLoaded} (scenarios=${report.policyScenarios.length})`,
|
|
6049
|
-
);
|
|
6050
|
-
console.log(
|
|
6051
|
-
` ${mark(report.snapshotCached)} snapshot cache: ${
|
|
6052
|
-
report.snapshotCached
|
|
6053
|
-
? `hit (age=${report.snapshotAgeMs}ms)`
|
|
6054
|
-
: "miss"
|
|
6055
|
-
}`,
|
|
6056
|
-
);
|
|
6057
|
-
if (report.previewDecision) {
|
|
6058
|
-
const d = report.previewDecision;
|
|
6059
|
-
console.log(
|
|
6060
|
-
` ${GREEN_BRIGHT}→${RESET} preview decision: scenario=${d.scenario}, mode=${d.mode}, lane=${d.lane}, shards[0].cli=${d.shards?.[0]?.cli ?? "?"}`,
|
|
6061
|
-
);
|
|
6062
|
-
}
|
|
6063
|
-
if (report.error) {
|
|
6064
|
-
console.log(` ${RED}✗${RESET} error: ${report.error}`);
|
|
6065
|
-
}
|
|
6066
|
-
console.log("");
|
|
6067
|
-
}
|
|
6068
|
-
return;
|
|
6069
|
-
}
|
|
6070
5818
|
const fix = cmdArgs.includes("--fix");
|
|
6071
5819
|
const reset = cmdArgs.includes("--reset");
|
|
6072
5820
|
const purgeLogs = cmdArgs.includes("--purge-logs");
|
|
@@ -6166,7 +5914,11 @@ async function main() {
|
|
|
6166
5914
|
case "multi": {
|
|
6167
5915
|
const subcommand = cmdArgs[0] || "";
|
|
6168
5916
|
if (cmdArgs.some(isHelpArg)) {
|
|
6169
|
-
|
|
5917
|
+
const { pathToFileURL } = await import("node:url");
|
|
5918
|
+
const { renderTeamHelp } = await import(
|
|
5919
|
+
pathToFileURL(join(PKG_ROOT, "hub", "team", "cli", "help.mjs")).href
|
|
5920
|
+
);
|
|
5921
|
+
renderTeamHelp();
|
|
6170
5922
|
return;
|
|
6171
5923
|
}
|
|
6172
5924
|
if (JSON_OUTPUT) process.env.TFX_OUTPUT_JSON = "1";
|
|
@@ -6240,129 +5992,6 @@ async function main() {
|
|
|
6240
5992
|
await cmdSynapseStatus(cmdArgs.slice(1), { json: JSON_OUTPUT });
|
|
6241
5993
|
return;
|
|
6242
5994
|
}
|
|
6243
|
-
case "review": {
|
|
6244
|
-
if (cmdArgs.some(isHelpArg)) {
|
|
6245
|
-
printCommandHelp("review");
|
|
6246
|
-
return;
|
|
6247
|
-
}
|
|
6248
|
-
const ref =
|
|
6249
|
-
cmdArgs[0] && !cmdArgs[0].startsWith("--") ? cmdArgs[0] : "HEAD";
|
|
6250
|
-
const baseIdx = cmdArgs.indexOf("--base");
|
|
6251
|
-
const base = baseIdx >= 0 ? cmdArgs[baseIdx + 1] : undefined;
|
|
6252
|
-
const timeoutIdx = cmdArgs.indexOf("--timeout");
|
|
6253
|
-
const timeoutMs =
|
|
6254
|
-
timeoutIdx >= 0 ? Number(cmdArgs[timeoutIdx + 1]) * 1000 : 180_000;
|
|
6255
|
-
const shardIdx = cmdArgs.indexOf("--shard");
|
|
6256
|
-
const shard = shardIdx >= 0 ? cmdArgs[shardIdx + 1] : "off";
|
|
6257
|
-
|
|
6258
|
-
if (shard === "per-file") {
|
|
6259
|
-
const { runCodexReviewSharded } = await import(
|
|
6260
|
-
"../hub/team/codex-review.mjs"
|
|
6261
|
-
);
|
|
6262
|
-
const result = await runCodexReviewSharded({
|
|
6263
|
-
ref,
|
|
6264
|
-
base,
|
|
6265
|
-
timeoutMs,
|
|
6266
|
-
onFileStart: ({ file, index, total }) => {
|
|
6267
|
-
if (!JSON_OUTPUT) {
|
|
6268
|
-
process.stderr.write(
|
|
6269
|
-
`[${index + 1}/${total}] reviewing ${file}\n`,
|
|
6270
|
-
);
|
|
6271
|
-
}
|
|
6272
|
-
},
|
|
6273
|
-
});
|
|
6274
|
-
if (JSON_OUTPUT) {
|
|
6275
|
-
console.log(JSON.stringify(result, null, 2));
|
|
6276
|
-
} else {
|
|
6277
|
-
console.log(
|
|
6278
|
-
`=== per-file review (${result.files.length} files, range=${result.range}) ===`,
|
|
6279
|
-
);
|
|
6280
|
-
for (const r of result.perFile) {
|
|
6281
|
-
console.log("");
|
|
6282
|
-
console.log(
|
|
6283
|
-
`--- ${r.file} (${r.diffBytes}b, verdict=${r.verdict || "n/a"}${r.skipped ? ", skipped" : ""}) ---`,
|
|
6284
|
-
);
|
|
6285
|
-
if (r.error) console.log(` error: ${r.error}`);
|
|
6286
|
-
if (r.stdout) process.stdout.write(r.stdout);
|
|
6287
|
-
}
|
|
6288
|
-
console.log("");
|
|
6289
|
-
console.log(
|
|
6290
|
-
`Aggregate: files=${result.files.length} verdict=${result.verdict}`,
|
|
6291
|
-
);
|
|
6292
|
-
if (result.error) console.log(`error: ${result.error}`);
|
|
6293
|
-
}
|
|
6294
|
-
process.exit(result.ok ? 0 : 1);
|
|
6295
|
-
}
|
|
6296
|
-
|
|
6297
|
-
const { runCodexReview } = await import("../hub/team/codex-review.mjs");
|
|
6298
|
-
const result = await runCodexReview({ ref, base, timeoutMs });
|
|
6299
|
-
if (JSON_OUTPUT) {
|
|
6300
|
-
console.log(JSON.stringify(result, null, 2));
|
|
6301
|
-
} else {
|
|
6302
|
-
if (result.stdout) process.stdout.write(result.stdout);
|
|
6303
|
-
if (result.stderr) process.stderr.write(result.stderr);
|
|
6304
|
-
console.log("");
|
|
6305
|
-
console.log(
|
|
6306
|
-
`range=${result.range || ref} diffBytes=${result.diffBytes} verdict=${result.verdict || "n/a"}`,
|
|
6307
|
-
);
|
|
6308
|
-
if (result.error) console.log(`error: ${result.error}`);
|
|
6309
|
-
}
|
|
6310
|
-
process.exit(result.ok ? 0 : 1);
|
|
6311
|
-
return;
|
|
6312
|
-
}
|
|
6313
|
-
case "swarm": {
|
|
6314
|
-
const sub = cmdArgs[0] || "";
|
|
6315
|
-
if (sub === "help" || sub === "--help" || sub === "-h") {
|
|
6316
|
-
const s = CLI_COMMAND_SCHEMAS.swarm;
|
|
6317
|
-
console.log(`
|
|
6318
|
-
${AMBER}${BOLD}⬡ tfx swarm${RESET}
|
|
6319
|
-
|
|
6320
|
-
${GRAY}${s.description}${RESET}
|
|
6321
|
-
|
|
6322
|
-
${BOLD}Usage${RESET}
|
|
6323
|
-
${WHITE_BRIGHT}${s.usage}${RESET}
|
|
6324
|
-
|
|
6325
|
-
${BOLD}Subcommands${RESET}
|
|
6326
|
-
${WHITE_BRIGHT}tfx swarm run <prd>${RESET} ${GRAY}${s.subcommands.run}${RESET}
|
|
6327
|
-
${WHITE_BRIGHT}tfx swarm preflight <prd>${RESET} ${GRAY}${s.subcommands.preflight}${RESET}
|
|
6328
|
-
${WHITE_BRIGHT}tfx swarm plan <prd>${RESET} ${GRAY}${s.subcommands.plan}${RESET}
|
|
6329
|
-
${WHITE_BRIGHT}tfx swarm list${RESET} ${GRAY}${s.subcommands.list}${RESET}
|
|
6330
|
-
${WHITE_BRIGHT}tfx swarm status${RESET} ${GRAY}${s.subcommands.status}${RESET}
|
|
6331
|
-
|
|
6332
|
-
${BOLD}Options${RESET}
|
|
6333
|
-
${s.options.map((o) => ` ${DIM}${o.name.padEnd(16)}${RESET} ${GRAY}${o.description}${RESET}`).join("\n")}
|
|
6334
|
-
`);
|
|
6335
|
-
return;
|
|
6336
|
-
}
|
|
6337
|
-
await checkHubRunning();
|
|
6338
|
-
const { cmdSwarmRun, cmdSwarmPlan, cmdSwarmList, cmdSwarmPreflight } =
|
|
6339
|
-
await import("../hub/team/swarm-cli.mjs");
|
|
6340
|
-
if (sub === "list" || sub === "status") {
|
|
6341
|
-
await cmdSwarmList(cmdArgs.slice(1), { json: JSON_OUTPUT });
|
|
6342
|
-
return;
|
|
6343
|
-
}
|
|
6344
|
-
if (sub === "plan") {
|
|
6345
|
-
await cmdSwarmPlan(cmdArgs.slice(1), { json: JSON_OUTPUT });
|
|
6346
|
-
return;
|
|
6347
|
-
}
|
|
6348
|
-
if (sub === "preflight") {
|
|
6349
|
-
await cmdSwarmPreflight(cmdArgs.slice(1), { json: JSON_OUTPUT });
|
|
6350
|
-
return;
|
|
6351
|
-
}
|
|
6352
|
-
if (sub === "run") {
|
|
6353
|
-
await cmdSwarmRun(cmdArgs.slice(1), { json: JSON_OUTPUT });
|
|
6354
|
-
return;
|
|
6355
|
-
}
|
|
6356
|
-
if (!sub || sub.startsWith("--")) {
|
|
6357
|
-
throw createCliError("PRD 경로가 필요합니다", {
|
|
6358
|
-
exitCode: EXIT_ARG_ERROR,
|
|
6359
|
-
reason: "argError",
|
|
6360
|
-
fix: "tfx swarm [run] <prd-path> [--dry-run|--json|--filter <shard>]",
|
|
6361
|
-
});
|
|
6362
|
-
}
|
|
6363
|
-
await cmdSwarmRun(cmdArgs, { json: JSON_OUTPUT });
|
|
6364
|
-
return;
|
|
6365
|
-
}
|
|
6366
5995
|
case "why": {
|
|
6367
5996
|
if (cmdArgs.some(isHelpArg)) {
|
|
6368
5997
|
printCommandHelp("why");
|
package/cto/brief.mjs
CHANGED
|
@@ -27,13 +27,6 @@ function formatGoal(goal) {
|
|
|
27
27
|
return `- ${id} ${status}: ${title}`;
|
|
28
28
|
}
|
|
29
29
|
|
|
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
30
|
function formatEvent(event) {
|
|
38
31
|
const ts = oneLine(event?.ts, "unknown_ts");
|
|
39
32
|
const name = oneLine(event?.event, "event");
|
|
@@ -61,9 +54,6 @@ export function renderBrief(current) {
|
|
|
61
54
|
const activeGoals = Array.isArray(summary.active_goals)
|
|
62
55
|
? summary.active_goals.slice(0, 3)
|
|
63
56
|
: [];
|
|
64
|
-
const swarmShards = Array.isArray(summary.swarm_shards)
|
|
65
|
-
? summary.swarm_shards.slice(0, 2)
|
|
66
|
-
: [];
|
|
67
57
|
const recentEvents = Array.isArray(current?.ledger_tail)
|
|
68
58
|
? current.ledger_tail.slice(-2)
|
|
69
59
|
: [];
|
|
@@ -75,8 +65,6 @@ export function renderBrief(current) {
|
|
|
75
65
|
`summary: ${oneLine(summary.repo_state, "no repo summary")}`,
|
|
76
66
|
"active_goals",
|
|
77
67
|
...(activeGoals.length > 0 ? activeGoals.map(formatGoal) : ["- none"]),
|
|
78
|
-
"swarm_shards",
|
|
79
|
-
...(swarmShards.length > 0 ? swarmShards.map(formatShard) : ["- none"]),
|
|
80
68
|
"hub_status",
|
|
81
69
|
`status: ${oneLine(hub.status, "unknown")} available: ${hub.available === true} detail: ${compactDetail(hub.detail)}`,
|
|
82
70
|
"recent_events",
|