triflux 4.2.10 → 5.0.1

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/README.ko.md CHANGED
@@ -40,17 +40,23 @@
40
40
 
41
41
  ---
42
42
 
43
- ## v4의 새로운 기능
44
-
45
- **triflux v4**는 단순한 라우터를 넘어 **고성능 오케스트레이션 허브**로 진화했습니다. 상주형(resident) 서비스, 네임드 파이프(Named Pipe) IPC, 그리고 고도화된 태스크 파이프라인을 통해 [Claude Code](https://claude.ai/code) 환경에서 가장 안정적인 멀티모델 경험을 제공합니다.
46
-
47
- ### 주요 특징
48
-
49
- - **Hub IPC 아키텍처** Named Pipe HTTP MCP 브리지를 활용한 초고속 상주형 허브 서버.
50
- - **파이프라인 `--thorough`** — `plan` `prd` `exec` `verify` `fix`로 이어지는 다단계 작업 생명주기.
51
- - **위임(Delegator) MCP** 에이전트와 유연하게 상호작용할 있는 전용 MCP 도구(`delegate`, `reply`, `status`).
52
- - **psmux / Windows 네이티브** `tmux` (WSL)와 `psmux` (Windows Terminal 네이티브)를 모두 지원하는 하이브리드 세션 관리.
53
- - **QoS 대시보드**AIMD 기반 동적 배치 사이징 실시간 상태 모니터링.
43
+ ## v5의 새로운 기능
44
+
45
+ **triflux v5**는 v4의 오케스트레이션 기반을 유지하면서 파이프라인을 똑똑하고, phase-aware하게, 협업적으로 발전시켰습니다. 멀티태스크 오케스트레이션에서는 이제 `--thorough`가 기본 경로이므로, 계획, 승인, 검증, 복구가 기본값으로 활성화됩니다.
46
+
47
+ ### 주요 특징
48
+
49
+ - **`--thorough` 기본화**멀티태스크 오케스트레이션은 기본적으로 `plan` `prd` `exec` `verify` → `fix` 전체 파이프라인을 실행합니다. 경량 경로가 필요할 때만 `--quick`을 명시합니다.
50
+ - **Opus × Codex Scout 계획 협업** — `plan` 단계에서 Opus가 설계를 주도하고 Codex scout 워커가 코드베이스를 병렬 탐색한 최종 계획에 반영합니다.
51
+ - **DAG 기반 라우팅 휴리스틱** `dag_width`와 `complexity`를 함께 반영해 `quick_single`, `thorough_single`, `quick_team`, `thorough_team`, `batch_single` 전략 중 하나를 선택합니다.
52
+ - **피드백 루프 복원**워커는 여러 차례 재실행될 있고, 최종 완료 리드의 피드백을 다시 받아 반영할 수 있습니다.
53
+ - **HITL 승인 게이트** `pipeline_advance_gated`를 통해 단계 전이 전에 사람 승인 체크포인트를 삽입합니다.
54
+ - **Phase-aware MCP 필터링** — 파이프라인 단계에 따라 MCP 노출을 조정해 `plan`, `prd`, `verify`는 읽기 중심으로 유지하고 `exec`는 더 넓은 도구 세트를 사용합니다.
55
+ - **Plan 파일 영속화** — 최종 계획 Markdown을 `.tfx/plans/{team}-plan.md`에 저장하고 파이프라인 artifact로 추적합니다.
56
+ - **Hub IPC 아키텍처** — Named Pipe 및 HTTP MCP 브리지를 활용한 초고속 상주형 허브 서버.
57
+ - **위임(Delegator) MCP** — 에이전트와 유연하게 상호작용할 수 있는 전용 MCP 도구(`delegate`, `reply`, `status`).
58
+ - **psmux / Windows 네이티브** — `tmux` (WSL)와 `psmux` (Windows Terminal 네이티브)를 모두 지원하는 하이브리드 세션 관리.
59
+ - **QoS 대시보드** — AIMD 기반 동적 배치 사이징 및 실시간 상태 모니터링.
54
60
  - **21종 이상의 전문 에이전트** — `scientist-deep`부터 `spark_fast`까지, 작업에 최적화된 에이전트 라인업.
55
61
 
56
62
  ---
@@ -95,35 +101,39 @@ npm install -g triflux
95
101
  tfx setup
96
102
  ```
97
103
 
98
- ### 3. 사용 방법
99
-
100
- ```bash
101
- # 자동 모드 — 허브를 통한 병렬 실행
102
- /tfx-auto "인증 리팩터링 + UI 업데이트 + 테스트 추가"
103
-
104
- # 파이프라인 모드 — 정밀한 다단계 실행
105
- /tfx-auto --thorough "복잡한 데이터 마이그레이션 구현"
106
-
107
- # 직접 위임
108
- /tfx-delegate "최신 React 패턴 조사" --provider gemini
109
- ```
110
-
111
- ---
112
-
113
- ## 파이프라인: `--thorough` 모드
114
-
115
- v4 파이프라인은 복잡한 엔지니어링 작업을 위해 설계된 강력한 실행 루프를 제공합니다.
116
-
117
- | 단계 | 설명 |
118
- |------|------|
119
- | **plan** | 해결책을 설계하고 의존성을 식별합니다. |
120
- | **prd** | 상세한 기술 명세서(Technical Spec / PRD)를 생성합니다. |
121
- | **exec** | 실제 코드 구현을 수행합니다. |
122
- | **verify** | 테스트를 실행하고 구현 결과가 PRD 일치하는지 검증합니다. |
123
- | **fix** | (루프) 검증 단계에서 발견된 실패를 자동으로 수정합니다 (최대 3회). |
124
- | **ralph** | (재시작) 수정 루프 실패 시, 새로운 통찰을 바탕으로 `plan`부터 다시 시작합니다 (최대 10회). |
125
-
126
- ---
104
+ ### 3. 사용 방법
105
+
106
+ ```bash
107
+ # 자동 모드 — 허브를 통한 thorough 멀티태스크 오케스트레이션
108
+ /tfx-auto "인증 리팩터링 + UI 업데이트 + 테스트 추가"
109
+
110
+ # quick 모드 — 전체 계획/검증 루프 생략
111
+ /tfx-auto --quick "작은 회귀 버그 수정"
112
+
113
+ # 직접 위임
114
+ /tfx-delegate "최신 React 패턴 조사" --provider gemini
115
+ ```
116
+
117
+ v5에서는 멀티태스크 오케스트레이션이 기본적으로 `--thorough`로 실행되며, 더 가벼운 경로가 필요할 때 `--quick`을 사용합니다.
118
+
119
+ ---
120
+
121
+ ## 파이프라인: `--thorough` 모드
122
+
123
+ v5 파이프라인은 복잡한 엔지니어링 작업에서 기본이 되는 thorough 실행 루프입니다. Plan 산출물은 영속화되고, PRD 핸드오프에는 사람 승인 게이트를 둘 수 있으며, verify/fix 단계는 워커 피드백 루프를 복원합니다.
124
+
125
+ | 단계 | 설명 |
126
+ |------|------|
127
+ | **plan** | Opus가 설계를 주도하고 Codex scout가 병렬 탐색을 수행하며, 계획 산출물을 파일로 영속화합니다. |
128
+ | **prd** | 상세한 기술 명세서(Technical Spec / PRD)를 생성하고 승인 체크포인트를 준비합니다. |
129
+ | **exec** | 실제 코드 구현을 수행합니다. |
130
+ | **verify** | 테스트를 실행하고 구현 결과가 PRD와 일치하는지 검증합니다. |
131
+ | **fix** | (루프) 검증 단계에서 발견된 실패를 리드 피드백과 함께 재실행하여 수정합니다 (최대 3회). |
132
+ | **ralph** | (재시작) 수정 루프 실패 시, 새로운 통찰을 바탕으로 `plan`부터 다시 시작합니다 (최대 10회). |
133
+
134
+ Phase-aware MCP 필터링으로 `plan`, `prd`, `verify`는 읽기 중심으로 제한되며, `prd` → `exec` 전이는 `pipeline_advance_gated`로 승인 대기를 걸 수 있습니다.
135
+
136
+ ---
127
137
 
128
138
  ## 위임(Delegator) MCP
129
139
 
@@ -155,9 +165,9 @@ MCP 도구를 통해 허브와 직접 상호작용하세요.
155
165
 
156
166
  ---
157
167
 
158
- ## 보안
159
-
160
- triflux v4는 안전한 전문 개발 환경을 위해 설계되었습니다.
168
+ ## 보안
169
+
170
+ triflux v5는 안전한 전문 개발 환경을 위해 설계되었습니다.
161
171
 
162
172
  - **허브 토큰 인증** — `TFX_HUB_TOKEN`을 이용한 보안 IPC (Bearer 인증).
163
173
  - **Localhost 전용** — 허브가 기본적으로 `127.0.0.1`에만 바인딩되어 외부 접근을 차단합니다.
package/README.md CHANGED
@@ -40,17 +40,23 @@
40
40
 
41
41
  ---
42
42
 
43
- ## What's New in v4?
44
-
45
- **triflux v4** evolves from a simple router into a **high-performance orchestration hub**. It introduces resident services, named-pipe IPC, and advanced task pipelines to provide the most stable multi-model experience for [Claude Code](https://claude.ai/code).
46
-
47
- ### Key Features
48
-
49
- - **Hub IPC Architecture** — Lightning-fast resident Hub server with Named Pipe & HTTP MCP bridge.
50
- - **Pipeline `--thorough`** Multi-phase task lifecycle: `plan` `prd` `exec` `verify` `fix`.
51
- - **Delegator MCP** — Native MCP tools (`delegate`, `reply`, `status`) for seamless agent interaction.
52
- - **psmux / Windows Native** — Hybrid support for `tmux` (WSL) and `psmux` (Windows Terminal native).
53
- - **QoS Dashboard** — Real-time health monitoring with AIMD-based dynamic batch sizing.
43
+ ## What's New in v5?
44
+
45
+ **triflux v5** keeps the v4 orchestration foundation intact while making the pipeline smarter, more phase-aware, and more collaborative. For multi-task orchestration, `--thorough` is now the default path, so planning, approval, verification, and recovery stay on by default instead of being bolted on later.
46
+
47
+ ### Key Features
48
+
49
+ - **`--thorough` by Default** — Multi-task orchestration now defaults to the full `plan` `prd` → `exec` → `verify` → `fix` pipeline. Reach for `--quick` only when you explicitly want the lighter path.
50
+ - **Opus × Codex Scout Planning** In `plan`, Opus leads architecture decisions while Codex scout workers explore the codebase in parallel and feed findings back into the final plan.
51
+ - **DAG-based Routing Heuristics** — Routing now considers both `dag_width` and `complexity` to choose between `quick_single`, `thorough_single`, `quick_team`, `thorough_team`, and `batch_single`.
52
+ - **Restored Feedback Loop** — Workers can be re-run for multiple iterations and receive lead feedback before final completion.
53
+ - **HITL Approval Gate** — `pipeline_advance_gated` inserts a human approval checkpoint before gated phase transitions.
54
+ - **Phase-aware MCP Filtering** — MCP exposure changes by pipeline phase so `plan`, `prd`, and `verify` stay read-focused while `exec` keeps broader tooling.
55
+ - **Persistent Plan Files** — Final plan markdown is saved to `.tfx/plans/{team}-plan.md` and tracked as a pipeline artifact.
56
+ - **Hub IPC Architecture** — Lightning-fast resident Hub server with Named Pipe & HTTP MCP bridge.
57
+ - **Delegator MCP** — Native MCP tools (`delegate`, `reply`, `status`) for seamless agent interaction.
58
+ - **psmux / Windows Native** — Hybrid support for `tmux` (WSL) and `psmux` (Windows Terminal native).
59
+ - **QoS Dashboard** — Real-time health monitoring with AIMD-based dynamic batch sizing.
54
60
  - **21+ specialized agents** — From `scientist-deep` to `spark_fast`, each optimized for specific tasks.
55
61
 
56
62
  ---
@@ -95,35 +101,39 @@ Synchronize scripts, register skills to Claude Code, and configure the HUD.
95
101
  tfx setup
96
102
  ```
97
103
 
98
- ### 3. Usage
99
-
100
- ```bash
101
- # Auto mode — Parallel execution via Hub
102
- /tfx-auto "refactor auth + update UI + add tests"
103
-
104
- # Pipeline mode — Thorough multi-phase execution
105
- /tfx-auto --thorough "implement complex data migration"
106
-
107
- # Direct Delegation
108
- /tfx-delegate "research latest React patterns" --provider gemini
109
- ```
110
-
111
- ---
112
-
113
- ## Pipeline: `--thorough` Mode
114
-
115
- The v4 Pipeline provides a robust execution loop designed for complex engineering tasks.
116
-
117
- | Phase | Description |
118
- |-------|-------------|
119
- | **plan** | Architect the solution and identify dependencies. |
120
- | **prd** | Generate a detailed Technical Specification / PRD. |
121
- | **exec** | Perform the actual code implementation. |
122
- | **verify** | Run tests and verify the implementation against the PRD. |
123
- | **fix** | (Loop) Automatically fix failures identified in the verify phase (Max 3). |
124
- | **ralph** | (Reset) If the fix loop fails, restart from `plan` with new insights (Max 10). |
125
-
126
- ---
104
+ ### 3. Usage
105
+
106
+ ```bash
107
+ # Auto mode — Thorough multi-task orchestration via Hub
108
+ /tfx-auto "refactor auth + update UI + add tests"
109
+
110
+ # Quick mode — Skip the full planning/verification loop
111
+ /tfx-auto --quick "fix a small regression"
112
+
113
+ # Direct Delegation
114
+ /tfx-delegate "research latest React patterns" --provider gemini
115
+ ```
116
+
117
+ In v5, multi-task orchestration defaults to `--thorough`; use `--quick` when you explicitly want the lighter path.
118
+
119
+ ---
120
+
121
+ ## Pipeline: `--thorough` Mode
122
+
123
+ The v5 pipeline is the default thorough execution loop for complex engineering work. Plan artifacts are persisted, PRD handoff can be gated by human approval, and verify/fix restores the worker feedback loop.
124
+
125
+ | Phase | Description |
126
+ |-------|-------------|
127
+ | **plan** | Opus-led solution design with parallel Codex scout exploration and a persisted plan artifact. |
128
+ | **prd** | Generate a detailed Technical Specification / PRD and prepare the approval checkpoint. |
129
+ | **exec** | Perform the actual code implementation. |
130
+ | **verify** | Run tests and verify the implementation against the PRD. |
131
+ | **fix** | (Loop) Re-run workers with lead feedback to fix failures identified in the verify phase (Max 3). |
132
+ | **ralph** | (Reset) If the fix loop fails, restart from `plan` with new insights (Max 10). |
133
+
134
+ Phase-aware MCP filtering keeps `plan`, `prd`, and `verify` read-heavy, while the `prd` → `exec` handoff can be gated through `pipeline_advance_gated`.
135
+
136
+ ---
127
137
 
128
138
  ## Delegator MCP
129
139
 
@@ -155,9 +165,9 @@ Interact with the Hub directly through MCP tools.
155
165
 
156
166
  ---
157
167
 
158
- ## Security
159
-
160
- triflux v4 is designed for secure, professional environments:
168
+ ## Security
169
+
170
+ triflux v5 is designed for secure, professional environments:
161
171
 
162
172
  - **Hub Token Auth** — Secure IPC using `TFX_HUB_TOKEN` (Bearer Auth).
163
173
  - **Localhost Only** — Default Hub binding to `127.0.0.1` prevents external access.
@@ -1,4 +1,4 @@
1
- #!/usr/bin/env node
1
+ #!/usr/bin/env node
2
2
  // tfx-doctor — triflux doctor 바로가기
3
3
  import { dirname } from "path";
4
4
  import { fileURLToPath } from "url";
package/bin/tfx-setup.mjs CHANGED
@@ -1,4 +1,4 @@
1
- #!/usr/bin/env node
1
+ #!/usr/bin/env node
2
2
  // tfx-setup — triflux setup 바로가기
3
3
  import { dirname } from "path";
4
4
  import { fileURLToPath } from "url";
package/bin/triflux.mjs CHANGED
@@ -1,4 +1,4 @@
1
- #!/usr/bin/env node
1
+ #!/usr/bin/env node
2
2
  // triflux CLI — setup, doctor, version
3
3
  import { copyFileSync, existsSync, readFileSync, writeFileSync, mkdirSync, chmodSync, readdirSync, unlinkSync, rmSync, statSync, openSync, closeSync } from "fs";
4
4
  import { join, dirname } from "path";
@@ -2,6 +2,9 @@
2
2
  //
3
3
  // 상태(state.mjs) + 전이(transitions.mjs) 통합 인터페이스
4
4
 
5
+ import { writeFileSync, mkdirSync } from 'node:fs';
6
+ import { join, resolve } from 'node:path';
7
+
5
8
  import { canTransition, transitionPhase, ralphRestart, TERMINAL } from './transitions.mjs';
6
9
  import {
7
10
  ensurePipelineTable,
@@ -92,6 +95,22 @@ export function createPipeline(db, teamName, opts = {}) {
92
95
  state = updatePipelineState(db, teamName, { artifacts });
93
96
  },
94
97
 
98
+ /**
99
+ * Plan 파일을 .tfx/plans/{teamName}-plan.md 에 기록하고
100
+ * artifact('plan_path')에 절대 경로를 저장한다.
101
+ * @param {string} content - Plan markdown 내용
102
+ * @returns {string} 절대 경로
103
+ */
104
+ writePlanFile(content) {
105
+ const safeName = teamName.replace(/[<>:"/\\|?*\x00-\x1f]/g, '_');
106
+ const planDir = resolve(process.cwd(), '.tfx', 'plans');
107
+ mkdirSync(planDir, { recursive: true });
108
+ const planPath = join(planDir, `${safeName}-plan.md`);
109
+ writeFileSync(planPath, content, 'utf8');
110
+ this.setArtifact('plan_path', planPath);
111
+ return planPath;
112
+ },
113
+
95
114
  /**
96
115
  * 터미널 상태 여부
97
116
  */
@@ -10,9 +10,17 @@ import * as fs from "node:fs/promises";
10
10
  import os from "node:os";
11
11
  import path from "node:path";
12
12
 
13
- const ROUTE_SCRIPT = "~/.claude/scripts/tfx-route.sh";
14
- export const SLIM_WRAPPER_SUBAGENT_TYPE = "slim-wrapper";
15
- const ROUTE_LOG_RE = /\[tfx-route\]/i;
13
+ const ROUTE_SCRIPT = "~/.claude/scripts/tfx-route.sh";
14
+ export const SLIM_WRAPPER_SUBAGENT_TYPE = "slim-wrapper";
15
+ /** scout 역할 기본 설정 — read-only 탐색 전용 */
16
+ export const SCOUT_ROLE_CONFIG = {
17
+ cli: "codex",
18
+ role: "scientist",
19
+ mcp_profile: "analyze",
20
+ maxIterations: 2,
21
+ readOnly: true,
22
+ };
23
+ const ROUTE_LOG_RE = /\[tfx-route\]/i;
16
24
  const ROUTE_COMMAND_RE = /(?:^|[\s"'`])(?:bash\s+)?(?:[^"'`\s]*\/)?tfx-route\.sh\b/i;
17
25
  const ROUTE_PROMPT_RE = /tfx-route\.sh/i;
18
26
  const DIRECT_TOOL_BYPASS_RE = /\b(?:Read|Edit|Write)\s*\(/;
@@ -143,9 +151,10 @@ function getRouteTimeout(role, _mcpProfile) {
143
151
  * @param {number} [opts.workerIndex] — 검색 힌트 회전에 사용할 워커 인덱스(1-based)
144
152
  * @param {string} [opts.searchTool] — 전용 검색 도구 힌트(brave-search|tavily|exa)
145
153
  * @param {number} [opts.bashTimeout] — (deprecated, async에서는 무시됨)
154
+ * @param {number} [opts.maxIterations=3] — 피드백 루프 최대 반복 횟수
146
155
  * @returns {string} 슬림 래퍼 프롬프트
147
156
  */
148
- export function buildSlimWrapperPrompt(cli, opts = {}) {
157
+ export function buildSlimWrapperPrompt(cli, opts = {}) {
149
158
  const {
150
159
  subtask,
151
160
  role = "executor",
@@ -157,30 +166,36 @@ export function buildSlimWrapperPrompt(cli, opts = {}) {
157
166
  workerIndex,
158
167
  searchTool = "",
159
168
  pipelinePhase = "",
169
+ maxIterations = 3,
160
170
  } = opts;
161
171
 
162
172
  const routeTimeoutSec = getRouteTimeout(role, mcp_profile);
163
173
  const escaped = subtask.replace(/'/g, "'\\''");
164
- const pipelineHint = pipelinePhase
165
- ? `\n파이프라인 단계: ${pipelinePhase}`
166
- : '';
167
- const routeEnvPrefix = buildRouteEnvPrefix(agentName, workerIndex, searchTool);
174
+ const pipelineHint = pipelinePhase
175
+ ? `\n파이프라인 단계: ${pipelinePhase}`
176
+ : '';
177
+ const routeEnvPrefix = buildRouteEnvPrefix(agentName, workerIndex, searchTool);
178
+ const scoutConstraint = (role === "scout" || role === "scientist")
179
+ ? "\n이 워커는 scout(탐색 전용)이다. 코드를 수정하거나 파일을 생성하지 마라. 기존 코드를 읽고 분석하여 보고만 하라."
180
+ : "";
168
181
 
169
182
  // Bash 도구 timeout (모두 600초 이내)
170
183
  const launchTimeoutMs = 15000; // Step 1: fork + job_id 반환
171
184
  const waitTimeoutMs = 570000; // Step 2: 내부 폴링 (540초 대기 + 여유)
172
185
  const resultTimeoutMs = 30000; // Step 3: 결과 읽기
173
186
 
174
- return `실행 프로토콜 (subagent_type="${SLIM_WRAPPER_SUBAGENT_TYPE}", async):
175
- 1. --async로 백그라운드 시작 → JOB_ID 수신
176
- 2. --job-wait로 완료 대기 (내부 15초 간격 폴링, 최대 540초)
177
- 3. "still_running"이면 Step 2 반복, "done"이면 --job-result로 결과 수집
178
- 4. TaskUpdate + SendMessage → 종료${pipelineHint}
187
+ return `실행 프로토콜 (subagent_type="${SLIM_WRAPPER_SUBAGENT_TYPE}", async + feedback):
188
+ MAX_ITERATIONS = ${maxIterations}
189
+ ITERATION = 0${pipelineHint}
179
190
 
180
- [HARD CONSTRAINT] 허용 도구: Bash, TaskUpdate, TaskGet, TaskList, SendMessage만 사용한다.
181
- Read, Edit, Write, Grep, Glob, Agent, WebSearch, WebFetch 등 다른 모든 도구 사용을 금지한다.
182
- 코드를 직접 읽거나 수정하면 된다. 반드시 아래 Bash 명령(tfx-route.sh)을 통해 Codex/Gemini에 위임하라.
183
- 이 규칙을 위반하면 작업 실패로 간주한다.
191
+ Step 0 시작 보고 (턴 경계 생성):
192
+ TaskUpdate(taskId: "${taskId}", status: "in_progress")
193
+ SendMessage(type: "message", recipient: "${leadName}", content: "작업 시작: ${agentName}", summary: "task ${taskId} started")
194
+
195
+ [HARD CONSTRAINT] 허용 도구: Bash, TaskUpdate, TaskGet, TaskList, SendMessage만 사용한다.
196
+ Read, Edit, Write, Grep, Glob, Agent, WebSearch, WebFetch 등 다른 모든 도구 사용을 금지한다.
197
+ 코드를 직접 읽거나 수정하면 안 된다. 반드시 아래 Bash 명령(tfx-route.sh)을 통해 Codex/Gemini에 위임하라.
198
+ 이 규칙을 위반하면 작업 실패로 간주한다.${scoutConstraint}
184
199
 
185
200
  gemini/codex를 직접 호출하지 마라. 반드시 tfx-route.sh를 거쳐야 한다.
186
201
  프롬프트를 파일로 저장하지 마라. tfx-route.sh가 인자로 받는다.
@@ -193,29 +208,64 @@ Step 2 — 완료 대기 (내부 폴링, 최대 540초):
193
208
  Bash(command: 'bash ${ROUTE_SCRIPT} --job-wait JOB_ID 540', timeout: ${waitTimeoutMs})
194
209
  → 주기적 "waiting elapsed=Ns progress=NB" 출력 후 최종 상태:
195
210
  "done" → Step 3으로
196
- "timeout" 또는 "failed ..." → Step 4로 (실패 보고)
211
+ "timeout" 또는 "failed ..." → Step 4로 (실패 상태로)
197
212
  "still_running ..." → Step 2 반복 (같은 명령 재실행)
198
213
 
199
214
  Step 3 — 결과 수집:
200
215
  Bash(command: 'bash ${ROUTE_SCRIPT} --job-result JOB_ID', timeout: ${resultTimeoutMs})
201
- 출력이 워커 실행 결과이다.
216
+ RESULT에 저장.
202
217
 
203
- Step 4 — Claude Code 태스크 동기화 (반드시 실행):
218
+ Step 4 — 결과 보고 (턴 경계 생성, TaskUpdate 하지 않음):
204
219
  "done"이면:
205
- TaskUpdate(taskId: "${taskId}", status: "completed", metadata: {result: "success"})
206
- SendMessage(type: "message", recipient: "${leadName}", content: "완료: ${agentName}", summary: "task ${taskId} success")
220
+ SendMessage(type: "message", recipient: "${leadName}", content: "결과 (iteration ITERATION): ${agentName} 성공\\n{결과 요약}", summary: "task ${taskId} iteration ITERATION done")
207
221
  "timeout" 또는 "failed"이면:
208
- TaskUpdate(taskId: "${taskId}", status: "completed", metadata: {result: "failed", error: "상태 메시지"})
209
- SendMessage(type: "message", recipient: "${leadName}", content: "실패: ${agentName} (상태)", summary: "task ${taskId} failed")
222
+ SendMessage(type: "message", recipient: "${leadName}", content: "결과 (iteration ITERATION): ${agentName} 실패\\n{에러 요약}", summary: "task ${taskId} iteration ITERATION failed")
210
223
  TFX_NEEDS_FALLBACK 출력 감지 시:
211
- TaskUpdate(taskId: "${taskId}", status: "completed", metadata: {result: "fallback", reason: "claude-native"})
212
- SendMessage(type: "message", recipient: "${leadName}", content: "fallback 필요: ${agentName} — claude-native 역할은 Claude Agent로 위임 필요", summary: "task ${taskId} fallback")
213
-
214
- Step 5 — TaskUpdate + SendMessage 후 즉시 종료. 추가 도구 호출 금지.`;
215
- }
216
-
217
- /**
218
- * v3 하이브리드 래퍼 프롬프트 생성
224
+ Step 6으로 즉시 이동 (fallback 재실행 불가)
225
+
226
+ Step 5 — 피드백 대기:
227
+ SendMessage 후 너는 IDLE 상태가 된다. 리드의 응답을 기다려라.
228
+ 수신 메시지에 따라:
229
+ - "재실행:" 포함 → ITERATION++ → ITERATION < MAX_ITERATIONS이면 메시지의 지시를 반영하여 Step 1로. ITERATION >= MAX_ITERATIONS이면 Step 6으로 (반복 한도 초과)
230
+ - "승인" 또는 기타 → Step 6으로
231
+ - 메시지 없이 팀이 삭제되면 자동 종료 (처리 불필요)
232
+
233
+ Step 6 — 최종 종료 (반드시 실행):
234
+ TaskUpdate(taskId: "${taskId}", status: "completed", metadata: {result: "success"|"failed"|"fallback", iterations: ITERATION})
235
+ SendMessage(type: "message", recipient: "${leadName}", content: "최종 완료: ${agentName} (ITERATION회 실행)", summary: "task ${taskId} final")
236
+ → 종료. 이후 추가 도구 호출 금지.`;
237
+ }
238
+
239
+ /**
240
+ * scout 파견용 프롬프트 생성
241
+ * @param {object} opts
242
+ * @param {string} opts.question — 탐색 질문
243
+ * @param {string} [opts.scope] — 탐색 범위 힌트 (파일 패턴)
244
+ * @param {string} [opts.teamName] — 팀 이름
245
+ * @param {string} [opts.taskId] — 태스크 ID
246
+ * @param {string} [opts.agentName] — 에이전트 이름
247
+ * @param {string} [opts.leadName] — 리드 이름
248
+ * @returns {string} slim wrapper 프롬프트
249
+ */
250
+ export function buildScoutDispatchPrompt(opts = {}) {
251
+ const { question, scope = "", teamName, taskId, agentName, leadName } = opts;
252
+ const subtask = scope
253
+ ? `${question} 탐색 범위: ${scope}`
254
+ : question;
255
+ return buildSlimWrapperPrompt("codex", {
256
+ subtask,
257
+ role: "scientist",
258
+ teamName,
259
+ taskId,
260
+ agentName,
261
+ leadName,
262
+ mcp_profile: "analyze",
263
+ maxIterations: SCOUT_ROLE_CONFIG.maxIterations,
264
+ });
265
+ }
266
+
267
+ /**
268
+ * v3 하이브리드 래퍼 프롬프트 생성
219
269
  * psmux pane 기반 비동기 실행 + polling 패턴.
220
270
  * Agent가 idle 상태를 유지하여 인터럽트 수신이 가능하다.
221
271
  *
@@ -0,0 +1,154 @@
1
+ /**
2
+ * 라우팅 결정 함수
3
+ * @param {object} opts
4
+ * @param {Array<{id:string, description?:string, agent?:string, depends_on?:string[], complexity?:string}>} opts.subtasks
5
+ * @param {string} opts.graph_type - "INDEPENDENT" | "SEQUENTIAL" | "DAG"
6
+ * @param {boolean} opts.thorough - thorough 모드 여부
7
+ * @returns {{
8
+ * strategy: "quick_single" | "thorough_single" | "quick_team" | "thorough_team" | "batch_single",
9
+ * reason: string,
10
+ * dag_width: number,
11
+ * max_complexity: string
12
+ * }}
13
+ */
14
+ export function resolveRoutingStrategy({ subtasks, graph_type, thorough }) {
15
+ const N = subtasks.length;
16
+ if (N === 0) {
17
+ return { strategy: 'quick_single', reason: 'empty_subtasks', dag_width: 0, max_complexity: 'S' };
18
+ }
19
+
20
+ const dag_width = computeDagWidth(subtasks, graph_type);
21
+ const max_complexity = getMaxComplexity(subtasks);
22
+ const isHighComplexity = ['L', 'XL'].includes(max_complexity);
23
+ const allSameAgent = new Set(subtasks.map((s) => s.agent)).size === 1;
24
+ const allSmall = subtasks.every((s) => normalizeComplexity(s.complexity) === 'S');
25
+
26
+ // N==1: 단일 태스크
27
+ if (N === 1) {
28
+ if (thorough || isHighComplexity) {
29
+ return {
30
+ strategy: 'thorough_single',
31
+ reason: 'single_high_complexity',
32
+ dag_width,
33
+ max_complexity,
34
+ };
35
+ }
36
+ return {
37
+ strategy: 'quick_single',
38
+ reason: 'single_low_complexity',
39
+ dag_width,
40
+ max_complexity,
41
+ };
42
+ }
43
+
44
+ // dag_width==1: 사실상 순차 -> single
45
+ if (dag_width === 1) {
46
+ if (thorough || isHighComplexity) {
47
+ return {
48
+ strategy: 'thorough_single',
49
+ reason: 'sequential_chain',
50
+ dag_width,
51
+ max_complexity,
52
+ };
53
+ }
54
+ return {
55
+ strategy: 'quick_single',
56
+ reason: 'sequential_chain',
57
+ dag_width,
58
+ max_complexity,
59
+ };
60
+ }
61
+
62
+ // 동일 에이전트 + 모두 S: 프롬프트 병합 -> batch single
63
+ if (allSameAgent && allSmall) {
64
+ return {
65
+ strategy: 'batch_single',
66
+ reason: 'same_agent_small_batch',
67
+ dag_width,
68
+ max_complexity,
69
+ };
70
+ }
71
+
72
+ // dag_width >= 2: 팀
73
+ if (thorough || isHighComplexity) {
74
+ return {
75
+ strategy: 'thorough_team',
76
+ reason: 'parallel_high_complexity',
77
+ dag_width,
78
+ max_complexity,
79
+ };
80
+ }
81
+ return {
82
+ strategy: 'quick_team',
83
+ reason: 'parallel_low_complexity',
84
+ dag_width,
85
+ max_complexity,
86
+ };
87
+ }
88
+
89
+ /**
90
+ * DAG 폭 계산 - 레벨별 최대 병렬 태스크 수
91
+ * @param {Array<{id:string, depends_on?:string[]}>} subtasks
92
+ * @param {string} graph_type
93
+ * @returns {number}
94
+ */
95
+ function computeDagWidth(subtasks, graph_type) {
96
+ if (graph_type === 'SEQUENTIAL') return 1;
97
+ if (graph_type === 'INDEPENDENT') return subtasks.length;
98
+
99
+ // DAG: 레벨별 계산 (순환 의존 방어)
100
+ const levels = {};
101
+ const visiting = new Set();
102
+
103
+ function getLevel(task) {
104
+ if (levels[task.id] !== undefined) return levels[task.id];
105
+ if (visiting.has(task.id)) {
106
+ levels[task.id] = 0; // 순환 끊기
107
+ return 0;
108
+ }
109
+ if (!task.depends_on || task.depends_on.length === 0) {
110
+ levels[task.id] = 0;
111
+ return 0;
112
+ }
113
+ visiting.add(task.id);
114
+ const depLevels = task.depends_on.map((depId) => {
115
+ const dep = subtasks.find((s) => s.id === depId);
116
+ return dep ? getLevel(dep) : 0;
117
+ });
118
+ visiting.delete(task.id);
119
+ levels[task.id] = Math.max(...depLevels) + 1;
120
+ return levels[task.id];
121
+ }
122
+
123
+ subtasks.forEach(getLevel);
124
+
125
+ const levelCounts = {};
126
+ for (const level of Object.values(levels)) {
127
+ levelCounts[level] = (levelCounts[level] || 0) + 1;
128
+ }
129
+ return Math.max(...Object.values(levelCounts), 1);
130
+ }
131
+
132
+ /**
133
+ * 최대 복잡도 추출
134
+ * @param {Array<{complexity?:string}>} subtasks
135
+ * @returns {"S" | "M" | "L" | "XL"}
136
+ */
137
+ function getMaxComplexity(subtasks) {
138
+ const order = { S: 0, M: 1, L: 2, XL: 3 };
139
+ let max = 'S';
140
+ for (const s of subtasks) {
141
+ const complexity = normalizeComplexity(s.complexity);
142
+ if (order[complexity] > order[max]) max = complexity;
143
+ }
144
+ return max;
145
+ }
146
+
147
+ /**
148
+ * complexity 기본값 보정
149
+ * @param {string | undefined} complexity
150
+ * @returns {"S" | "M" | "L" | "XL"}
151
+ */
152
+ function normalizeComplexity(complexity) {
153
+ return ['S', 'M', 'L', 'XL'].includes(complexity) ? complexity : 'M';
154
+ }
package/hub/tools.mjs CHANGED
@@ -472,7 +472,72 @@ export function createTools(store, router, hitl, pipe = null) {
472
472
  }),
473
473
  },
474
474
 
475
- // ── 19. pipeline_list ──
475
+ // ── 19. pipeline_advance_gated (HITL 승인 게이트) ──
476
+ {
477
+ name: 'pipeline_advance_gated',
478
+ description: 'HITL 승인 게이트가 포함된 파이프라인 전이. 지정 단계로의 전이 전 사용자 승인을 요청하고, 승인 후 전이를 실행합니다. deadline 초과 시 default_action에 따라 자동 처리됩니다.',
479
+ inputSchema: {
480
+ type: 'object',
481
+ required: ['team_name', 'phase'],
482
+ properties: {
483
+ team_name: { type: 'string', pattern: '^[a-z0-9][a-z0-9-]*$' },
484
+ phase: { type: 'string', enum: ['plan', 'prd', 'exec', 'verify', 'fix', 'complete', 'failed'] },
485
+ prompt: { type: 'string', description: '사용자에게 표시할 승인 요청 메시지' },
486
+ deadline_ms: { type: 'integer', minimum: 5000, maximum: 600000, default: 120000 },
487
+ default_action: { type: 'string', enum: ['timeout_continue', 'timeout_abort'], default: 'timeout_continue' },
488
+ requester_agent: { type: 'string', description: '요청자 에이전트 이름' },
489
+ },
490
+ },
491
+ handler: wrap('PIPELINE_ADVANCE_GATED_FAILED', (args) => {
492
+ ensurePipelineTable(store.db);
493
+ const pipeline = createPipeline(store.db, args.team_name);
494
+
495
+ // 전이 가능 여부 사전 확인
496
+ if (!pipeline.canAdvance(args.phase)) {
497
+ const current = pipeline.getState();
498
+ return {
499
+ ok: false,
500
+ error: {
501
+ code: 'TRANSITION_BLOCKED',
502
+ message: `전이 불가: ${current.phase} → ${args.phase}`,
503
+ },
504
+ };
505
+ }
506
+
507
+ // HITL 승인 요청 생성
508
+ const approvalPrompt = args.prompt || `파이프라인 ${args.team_name}: ${pipeline.getState().phase} → ${args.phase} 전이를 승인하시겠습니까?`;
509
+ const deadlineMs = args.deadline_ms || 120000;
510
+ const now = Date.now();
511
+
512
+ const hitlResult = hitl.requestHumanInput({
513
+ requester_agent: args.requester_agent || `pipeline:${args.team_name}`,
514
+ kind: 'approval',
515
+ prompt: approvalPrompt,
516
+ deadline_ms: now + deadlineMs,
517
+ default_action: args.default_action || 'timeout_continue',
518
+ });
519
+
520
+ if (!hitlResult.ok) {
521
+ return hitlResult;
522
+ }
523
+
524
+ return {
525
+ ok: true,
526
+ data: {
527
+ pending: true,
528
+ request_id: hitlResult.data.request_id,
529
+ team_name: args.team_name,
530
+ target_phase: args.phase,
531
+ current_phase: pipeline.getState().phase,
532
+ deadline_ms: now + deadlineMs,
533
+ default_action: args.default_action || 'timeout_continue',
534
+ message: `승인 대기 중. ID: ${hitlResult.data.request_id}. ${Math.round(deadlineMs / 1000)}초 후 ${args.default_action || 'timeout_continue'} 자동 실행.`,
535
+ },
536
+ };
537
+ }),
538
+ },
539
+
540
+ // ── 20. pipeline_list ──
476
541
  {
477
542
  name: 'pipeline_list',
478
543
  description: '활성 파이프라인 목록을 조회합니다',
@@ -1046,15 +1046,15 @@ function expireStaleCodexBuckets(buckets) {
1046
1046
  // ============================================================================
1047
1047
  // Codex 세션 JSONL에서 실제 rate limits 추출
1048
1048
  // 한계: rate_limits는 세션별 스냅샷이므로 여러 세션 간 토큰 합산은 불가.
1049
- // 오늘 날짜의 모든 세션 파일을 스캔해 가장 최신 rate_limits 버킷을 수집한다.
1050
- // (단일 파일 즉시 return 방식에서 당일 전체 스캔 후 최신 데이터 우선 병합으로 변경)
1049
+ // 최근 7일간 세션 파일을 스캔해 가장 최신 rate_limits 버킷을 수집한다.
1050
+ // 합성 버킷(token_count 기반)은 2일 이내 데이터만 허용하여 stale 방지.
1051
1051
  // ============================================================================
1052
1052
  function getCodexRateLimits() {
1053
1053
  const now = new Date();
1054
- let syntheticBucket = null; // 오늘 token_count에서 합성 (행 활성화 + 토큰 데이터용)
1054
+ let syntheticBucket = null; // 최근 token_count에서 합성 (행 활성화 + 토큰 데이터용)
1055
1055
 
1056
- // 2일간 스캔: 실제 rate_limits 우선, 합성 버킷은 폴백
1057
- for (let dayOffset = 0; dayOffset <= 1; dayOffset++) {
1056
+ // 7일간 스캔: 실제 rate_limits 우선, 합성 버킷은 폴백
1057
+ for (let dayOffset = 0; dayOffset <= 6; dayOffset++) {
1058
1058
  const d = new Date(now.getTime() - dayOffset * 86_400_000);
1059
1059
  const sessDir = join(
1060
1060
  homedir(), ".codex", "sessions",
@@ -1086,8 +1086,8 @@ function getCodexRateLimits() {
1086
1086
  contextWindow: evt.payload?.info?.model_context_window,
1087
1087
  timestamp: evt.timestamp,
1088
1088
  };
1089
- } else if (dayOffset === 0 && !rl && evt?.payload?.info?.total_token_usage && !syntheticBucket) {
1090
- // 오늘 token_count: 합성 버킷 (rate_limits가 null일 때 행 활성화용)
1089
+ } else if (dayOffset <= 1 && !rl && evt?.payload?.info?.total_token_usage && !syntheticBucket) {
1090
+ // 2일 이내 token_count: 합성 버킷 (rate_limits가 null일 때 행 활성화용, stale 방지)
1091
1091
  syntheticBucket = {
1092
1092
  limitId: "codex", limitName: "codex-session",
1093
1093
  primary: null, secondary: null,
@@ -1102,7 +1102,7 @@ function getCodexRateLimits() {
1102
1102
  }
1103
1103
  } catch { /* 파일 읽기 실패 무시 */ }
1104
1104
  }
1105
- // 실제 rate_limits 발견 → 오늘 토큰 데이터 병합 후 즉시 반환
1105
+ // 실제 rate_limits 발견 → 토큰 데이터 병합 후 즉시 반환
1106
1106
  if (Object.keys(mergedBuckets).length > 0) {
1107
1107
  if (syntheticBucket) {
1108
1108
  const main = mergedBuckets.codex || mergedBuckets[Object.keys(mergedBuckets)[0]];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "triflux",
3
- "version": "4.2.10",
3
+ "version": "5.0.1",
4
4
  "description": "CLI-first multi-model orchestrator for Claude Code — route tasks to Codex, Gemini, and Claude",
5
5
  "type": "module",
6
6
  "bin": {
@@ -127,6 +127,31 @@ const PROFILE_DEFINITIONS = Object.freeze({
127
127
  }),
128
128
  });
129
129
 
130
+ /**
131
+ * 파이프라인 단계별 MCP 서버/도구 제한 (post-filter).
132
+ * role-based 프로필 위에 추가 적용. 빈 배열 = 전체 차단, 미정의 = 제한 없음.
133
+ */
134
+ export const PHASE_OVERRIDES = Object.freeze({
135
+ plan: Object.freeze({
136
+ description: '계획 단계: 읽기 전용 탐색만 허용',
137
+ allowedServers: Object.freeze(['context7']),
138
+ blockedServers: Object.freeze(['playwright', 'tavily', 'exa']),
139
+ }),
140
+ prd: Object.freeze({
141
+ description: 'PRD 단계: 읽기 전용 탐색 + 문서 조회',
142
+ allowedServers: Object.freeze(['context7', 'brave-search']),
143
+ blockedServers: Object.freeze(['playwright']),
144
+ }),
145
+ exec: Object.freeze({
146
+ description: '실행 단계: 프로필 기반 전체 허용 (제한 없음)',
147
+ }),
148
+ verify: Object.freeze({
149
+ description: '검증 단계: 읽기 전용 + 분석 도구',
150
+ allowedServers: Object.freeze(['context7', 'brave-search', 'exa']),
151
+ blockedServers: Object.freeze(['playwright']),
152
+ }),
153
+ });
154
+
130
155
  export const LEGACY_PROFILE_ALIASES = Object.freeze({
131
156
  implement: 'executor',
132
157
  analyze: 'analyze',
@@ -553,13 +578,23 @@ export function buildMcpPolicy(options = {}) {
553
578
  const inventoryIndex = buildInventoryIndex(inventory);
554
579
  const resolvedOptions = { ...options, inventory, inventoryIndex };
555
580
  const resolvedProfile = resolveMcpProfile(options.agentType, options.requestedProfile);
556
- const allowedServers = resolveAllowedServers(resolvedOptions);
581
+ let allowedServers = resolveAllowedServers(resolvedOptions);
557
582
  const hint = buildPromptHint(resolvedOptions);
583
+
584
+ // Phase-aware post-filter: 파이프라인 단계별 서버 제한 적용
585
+ const phase = options.phase;
586
+ const phaseOverride = phase && PHASE_OVERRIDES[phase];
587
+ if (phaseOverride && phaseOverride.blockedServers) {
588
+ const blocked = new Set(phaseOverride.blockedServers);
589
+ allowedServers = allowedServers.filter((s) => !blocked.has(s));
590
+ }
591
+
558
592
  return {
559
593
  requestedProfile: typeof options.requestedProfile === 'string' && options.requestedProfile
560
594
  ? options.requestedProfile
561
595
  : 'auto',
562
596
  resolvedProfile,
597
+ resolvedPhase: phase || null,
563
598
  allowedServers,
564
599
  hint,
565
600
  geminiAllowedServers: getGeminiAllowedServers(resolvedOptions),
@@ -577,14 +612,18 @@ function shellArray(name, values) {
577
612
  }
578
613
 
579
614
  export function toShellExports(policy) {
580
- return [
615
+ const lines = [
581
616
  `MCP_PROFILE_REQUESTED=${shellEscape(policy.requestedProfile)}`,
582
617
  `MCP_RESOLVED_PROFILE=${shellEscape(policy.resolvedProfile)}`,
583
618
  `MCP_HINT=${shellEscape(policy.hint)}`,
584
619
  shellArray('GEMINI_ALLOWED_SERVERS', policy.geminiAllowedServers),
585
620
  shellArray('CODEX_CONFIG_FLAGS', policy.codexConfigOverrides.flatMap((override) => ['-c', override])),
586
621
  `CODEX_CONFIG_JSON=${shellEscape(JSON.stringify(policy.codexConfig))}`,
587
- ].join('\n');
622
+ ];
623
+ if (policy.resolvedPhase) {
624
+ lines.push(`MCP_PIPELINE_PHASE=${shellEscape(policy.resolvedPhase)}`);
625
+ }
626
+ return lines.join('\n');
588
627
  }
589
628
 
590
629
  function parseCliArgs(argv) {
@@ -636,6 +675,9 @@ function parseCliArgs(argv) {
636
675
  case '--worker-index':
637
676
  args.workerIndex = Number.parseInt(next(), 10);
638
677
  break;
678
+ case '--phase':
679
+ args.phase = next();
680
+ break;
639
681
  default:
640
682
  throw new Error(`알 수 없는 옵션: ${token}`);
641
683
  }
@@ -32,14 +32,20 @@ argument-hint: "<command|task> [args...]"
32
32
  > 2. **비용**: Codex 우선 → Gemini → Claude 최후 수단. `claude` 선택 전 "Codex로 가능한가?" 재확인.
33
33
  > 3. **DAG**: SEQUENTIAL/DAG이면 레벨 기반 순차 실행. `.omc/context/{sid}/` 생성, context_output 저장, 실패 시 후속 SKIP.
34
34
  > 4. **트리아지**: Codex `--full-auto` 분류 + Opus 인라인 분해. Agent 스폰 금지.
35
+ > 5. **thorough**: `-t`/`--thorough` 시 파이프라인 init 필수. 커맨드 숏컷은 항상 quick.
35
36
 
36
37
  ## 모드
37
38
 
38
39
  | 입력 형식 | 모드 | 트리아지 |
39
40
  |-----------|------|----------|
40
- | `/implement JWT 추가` | 커맨드 숏컷 | 없음 (즉시 실행) |
41
- | `/tfx-auto "리팩터링 + UI"` | 자동 | Codex 분류 → Opus 분해 |
42
- | `/tfx-auto 3:codex "리뷰"` | 수동 | Opus 분해만 |
41
+ | `/implement JWT 추가` | 커맨드 숏컷 (quick) | 없음 (즉시 실행) |
42
+ | `/tfx-auto "리팩터링 + UI"` | 자동 (quick) | Codex 분류 → Opus 분해 |
43
+ | `/tfx-auto -t "리팩터링 + UI"` | 자동 (thorough) | Codex 분류 → Opus 분해 → Pipeline |
44
+ | `/tfx-auto --thorough "리팩터링"` | 자동 (thorough) | `-t` 동일 |
45
+ | `/tfx-auto 3:codex "리뷰"` | 수동 (quick) | Opus 분해만 |
46
+
47
+ > **tfx-auto는 `--quick`이 기본.** 커맨드 숏컷·단일 실행에서 plan/verify 오버헤드가 불필요하기 때문.
48
+ > 멀티 태스크 시 tfx-multi로 전환되면 tfx-multi의 기본값(`--thorough`)이 적용된다.
43
49
 
44
50
  ## 커맨드 숏컷
45
51
 
@@ -100,25 +106,77 @@ argument-hint: "<command|task> [args...]"
100
106
 
101
107
  **수동 모드 (`N:agent_type`):** Codex 분류 건너뜀 → Opus가 N개 서브태스크 분해. N > 10 거부.
102
108
 
109
+ ## --thorough 모드
110
+
111
+ `-t` 또는 `--thorough` 플래그 시 파이프라인 기반 실행. 커맨드 숏컷에서는 무시된다.
112
+
113
+ ```
114
+ 분기점은 "실행 전략"이지 "계획"이 아님:
115
+
116
+ TRIAGE
117
+
118
+ ├─ [thorough] → PIPELINE INIT(plan) → PLAN → PRD → [APPROVAL]
119
+ │ │
120
+ │ ┌───────────────┤
121
+ │ │ │
122
+ │ [1 task] [2+ tasks]
123
+ │ │ │
124
+ │ AUTO 직접 실행 TEAM EXEC (multi Phase 3)
125
+ │ │ │
126
+ │ └───────┬───────┘
127
+ │ │
128
+ │ VERIFY → FIX loop → COMPLETE
129
+
130
+ └─ [quick] → [1 task] → fire-and-forget
131
+ [2+ tasks] → TEAM EXEC → COLLECT → CLEANUP
132
+ ```
133
+
134
+ ### 단일 태스크 thorough
135
+
136
+ 1. `Bash("node hub/bridge.mjs pipeline-init --team ${sid}")` — 파이프라인 초기화 (phase: plan)
137
+ 2. Plan: Codex architect → 결과를 `pipeline.writePlanFile()` 저장
138
+ 3. PRD: Codex analyst → acceptance criteria 확정
139
+ 4. `pipeline_advance_gated` → [Approval Gate] → 사용자 승인 대기
140
+ 5. Exec: tfx-auto 직접 실행 (아래 "실행" 섹션)
141
+ 6. Verify: Codex verifier → 검증
142
+ 7. 실패 시 Fix loop (최대 3회) → Exec 재실행
143
+ 8. Complete
144
+
145
+ ### 멀티 태스크 thorough
146
+
147
+ Plan/PRD/Approval은 tfx-auto에서 실행, 그 후 tfx-multi Phase 3로 전환.
148
+ 서브태스크 배열 + `thorough: true` 신호를 함께 전달하여 multi 측에서 verify/fix를 수행.
149
+
103
150
  ## 멀티 태스크 라우팅 (트리아지 후)
104
151
 
105
- > **트리아지 결과 서브태스크가 2개 이상이면 tfx-multi Native Teams 모드로 자동 전환한다.**
152
+ > **트리아지 결과에 따라 실행 경로 결정.**
106
153
 
107
- | 서브태스크 | 실행 경로 | 이유 |
108
- |--------------|----------|------|
109
- | 1개 | tfx-auto 직접 실행 (아래 "실행" 섹션) | 팀 오버헤드 불필요, 경량 fire-and-forget |
110
- | 2개+ | **tfx-multi Phase 3** (TeamCreate TaskCreate → Agent 래퍼) | Shift+Down 네비게이션, 상태 추적, fallback |
154
+ | 조건 | 실행 경로 | 이유 |
155
+ |------|----------|------|
156
+ | 1개 + quick | tfx-auto 직접 실행 (fire-and-forget) | 팀 오버헤드 불필요 |
157
+ | 1개 + thorough | tfx-auto 직접 실행 + verify/fix loop | plan→exec→verify 단일 경로 |
158
+ | 2개+ + quick | tfx-multi Phase 3 (TeamCreate 직행) | Shift+Down, 상태 추적 |
159
+ | 2개+ + thorough | Plan/PRD/Approval 후 → tfx-multi Phase 3 + verify/fix | 전체 파이프라인 |
111
160
 
112
- **전환 방법:** 트리아지 완료 후 서브태스크 배열을 그대로 tfx-multi Phase 3에 전달한다.
113
- tfx-multi의 Phase 2(트리아지)는 건너뛰고 Phase 3a(TeamCreate)부터 시작한다.
161
+ **전환 방법:** 트리아지 완료 후 서브태스크 배열 + thorough 플래그를 tfx-multi Phase 3에 전달.
162
+ tfx-multi의 Phase 2(트리아지)는 건너뛰고, thorough 시 Phase 2.5-2.6도 건너뛴다 (auto에서 이미 수행).
114
163
 
115
164
  ```
165
+ thorough = args에 -t 또는 --thorough 포함
166
+
116
167
  if subtasks.length >= 2:
117
- tfx-multi Phase 3 실행 (트리아지 결과 재사용)
118
- TeamCreateTaskCreate × NAgent 래퍼 spawn (Phase 3a~3c)
119
- → Phase 4 결과 수집 Phase 5 정리
168
+ if thorough:
169
+ Pipeline init Plan PRDApproval (tfx-auto에서 수행)
170
+ tfx-multi Phase 3 실행 ({ subtasks, thorough: true })
171
+ → Phase 3.5 verify → Phase 3.6 fix loop → Phase 5 정리
172
+ else:
173
+ → tfx-multi Phase 3 실행 ({ subtasks, thorough: false })
174
+ → Phase 4 결과 수집 → Phase 5 정리
120
175
  else:
121
- tfx-auto 직접 실행 (아래)
176
+ if thorough:
177
+ → Pipeline init → Plan → PRD → Approval → 직접 실행 → Verify → Fix loop
178
+ else:
179
+ → tfx-auto 직접 실행 (아래)
122
180
  ```
123
181
 
124
182
  ## 실행
@@ -11,7 +11,7 @@ argument-hint: '"작업 설명" | --agents codex,gemini "작업" | --tmux "작
11
11
  > Claude Code Native Teams의 Shift+Down 네비게이션을 복원한다.
12
12
  > Codex/Gemini 워커마다 최소 프롬프트(~100 토큰)의 슬림 Agent 래퍼를 spawn하여 네비게이션에 등록하고,
13
13
  > 실제 작업은 `tfx-route.sh`가 수행한다. task 상태는 `team_task_list`를 truth source로 검증한다.
14
- > v3 — `--quick`(기본) + `--thorough`(전체 파이프라인: plan→prd→exec→verify→fix loop).
14
+ > v3 — `--thorough`(기본: plan→prd→exec→verify→fix loop) + `--quick`(경량 모드).
15
15
 
16
16
  > **Lead 고토큰 MCP 직접 사용 금지**
17
17
  > Lead(Claude Opus)는 웹 서치(brave-search, exa, tavily), 외부 서비스(Notion, Jira/Confluence, Calendar, Gmail),
@@ -21,8 +21,8 @@ argument-hint: '"작업 설명" | --agents codex,gemini "작업" | --tmux "작
21
21
  ## 사용법
22
22
 
23
23
  ```
24
- /tfx-multi "인증 리팩터링 + UI 개선 + 보안 리뷰" # --quick (기본)
25
- /tfx-multi --thorough "인증 리팩터링 + UI 개선 + 보안 리뷰" # 전체 파이프라인
24
+ /tfx-multi "인증 리팩터링 + UI 개선 + 보안 리뷰" # --thorough (기본)
25
+ /tfx-multi --quick "인증 리팩터링 + UI 개선 + 보안 리뷰" # 경량 모드 (plan/verify 생략)
26
26
  /tfx-multi --agents codex,gemini "프론트+백엔드"
27
27
  /tfx-multi --tmux "작업" # 레거시 tmux 모드
28
28
  /tfx-multi status
@@ -48,11 +48,17 @@ preflight와 Agent 생성을 병렬로 실행하여 사용자 체감 지연을
48
48
  ```
49
49
  ""(빈 문자열) → 사용자에게 작업 입력 요청
50
50
  "3:codex 리뷰" → 수동 모드: N=3, agent=codex
51
- "인증 + UI + 테스트" → 자동 모드: Codex 분류 → Opus 분해
51
+ "인증 + UI + 테스트" → 자동 모드 (--thorough 기본): Codex 분류 → Opus 분해 → Pipeline
52
+ "--quick 인증 + UI" → 경량 모드: plan/verify 생략, 즉시 실행
52
53
  "--tmux 인증 + UI" → Phase 3-mux 분기
53
54
  "status" / "stop" → Bash("node bin/triflux.mjs multi {cmd}") 직행
54
55
  ```
55
56
 
57
+ **모드 결정:**
58
+ - `--quick` 명시 → quick 모드 (Phase 2.5-2.6, 3.5-3.7 생략)
59
+ - `--thorough` 명시 또는 플래그 없음 → thorough 모드 (기본, 전체 파이프라인)
60
+ - 커맨드 숏컷 (tfx-auto 경유 단일 실행) → quick 유지 (오버헤드 불필요)
61
+
56
62
  ### Phase 2: 트리아지 (tfx-auto와 동일)
57
63
 
58
64
  **자동 모드:**
@@ -62,9 +68,9 @@ preflight와 Agent 생성을 병렬로 실행하여 사용자 체감 지연을
62
68
 
63
69
  **수동 모드:** Codex 분류 건너뜀 → Opus가 직접 N개 서브태스크 분해.
64
70
 
65
- ### Phase 2.5–2.6 + 3.5–3.7: `--thorough` 파이프라인
71
+ ### Phase 2.5–2.6 + 3.5–3.7: 파이프라인 (기본)
66
72
 
67
- > `--quick`(기본)에서는 건너뛴다. `--thorough` 모드에서만 실행.
73
+ > `--thorough`(기본) 모드에서 실행된다. `--quick` 플래그 시 건너뛴다.
68
74
  > 상세는 → [`references/thorough-pipeline.md`](references/thorough-pipeline.md) 참조.
69
75
 
70
76
  ### Phase 3: Native Teams 실행
@@ -1,24 +1,63 @@
1
- # --thorough 파이프라인 상세
1
+ # 파이프라인 상세 (thorough 기본)
2
2
 
3
- > `--quick`(기본) 모드에서는 파일의 내용이 적용되지 않는다.
4
- > `--thorough` 모드에서만 Phase 2.5-2.6과 Phase 3.5-3.7이 실행된다.
3
+ > `--thorough`(기본) 모드에서 Phase 2.5-2.6과 Phase 3.5-3.7이 실행된다.
4
+ > `--quick` 플래그 파일의 내용은 적용되지 않는다.
5
+ > tfx-auto 경유 시: `-t`/`--thorough` 플래그가 있을 때만 파이프라인이 활성화된다.
5
6
 
6
- ## Phase 2.5: Plan (Codex architect)
7
+ ## Phase 2.5: Plan (Opus Lead + Codex Scout 협업)
7
8
 
8
- 1. Hub pipeline 초기화:
9
- ```bash
10
- Bash("node hub/bridge.mjs pipeline-advance --team ${teamName} --status plan")
11
- ```
12
- — 또는 createPipeline(db, teamName) 직접 호출
13
- 2. Codex architect로 작업 분석 + 접근법 설계:
14
- ```bash
15
- bash ~/.claude/scripts/tfx-route.sh architect "${task}" analyze
16
- ```
17
- 3. 결과를 파이프라인 artifact에 저장:
18
- ```
19
- pipeline.setArtifact('plan_path', planOutputPath)
20
- ```
21
- 4. pipeline advance: plan → prd
9
+ > 기존: Codex architect(단독, one-shot)
10
+ > 변경: Opus 설계 주도 + Codex scout(병렬 탐색) → 합산 판단 → 최종 계획
11
+
12
+ ### Step 2.5.1: Opus 과제 분석 → 탐색 목록 생성
13
+
14
+ Lead(Opus)가 과제를 분석하고, 설계에 필요한 정보 탐색 목록을 인라인 생성한다:
15
+
16
+ ```json
17
+ {
18
+ "questions": [
19
+ { "id": "q1", "question": "현재 인증 미들웨어 구조와 세션 관리 방식", "scope": "src/middleware/auth*" },
20
+ { "id": "q2", "question": "DB 스키마와 마이그레이션 현황", "scope": "db/migrations/" }
21
+ ]
22
+ }
23
+ ```
24
+
25
+ 탐색 목록은 3-7개 항목 권장. 과도하면 Codex 비용이 아닌 Lead 컨텍스트가 팽창.
26
+
27
+ ### Step 2.5.2: Codex Scout 병렬 파견
28
+
29
+ 각 탐색 항목마다 Codex scout를 파견하여 코드베이스 탐색:
30
+
31
+ ```bash
32
+ # 각 question마다 병렬 실행
33
+ for each question:
34
+ bash ~/.claude/scripts/tfx-route.sh scientist "${question.question}. 탐색 범위: ${question.scope}" analyze
35
+ ```
36
+
37
+ **scout 실행 규칙:**
38
+ - scout는 **read-only** — 코드 수정 금지, 탐색+보고만
39
+ - 병렬 실행 (run_in_background=true)
40
+ - scope 힌트로 탐색 범위를 제한하여 정확도 향상
41
+ - MCP 프로필: `analyze` (읽기 전용 도구만)
42
+ - 팀 모드 시: slim wrapper Agent로 spawn (Shift+Down 네비게이션)
43
+ - 단일 모드 시: tfx-route.sh 직접 호출
44
+
45
+ ### Step 2.5.3: Opus 종합 판단 → 최종 계획 작성
46
+
47
+ Lead(Opus)가 scout 보고를 종합하고, 전략적 설계 결정을 내린다:
48
+
49
+ 1. scout 결과 수집 (모든 scout 완료 대기)
50
+ 2. 아키텍처 선택, 트레이드오프 판단, 리스크 평가
51
+ 3. 최종 계획 작성
52
+ 4. `pipeline.writePlanFile(planContent)` 저장
53
+ 5. pipeline advance: plan → prd
54
+
55
+ ### Step 2.5.4: 추가 질의 루프 (선택)
56
+
57
+ 계획 작성 중 추가 정보 필요 시:
58
+ - 팀 모드: 피드백 루프(Phase 0 구현)를 활용하여 scout에 "재실행:" 메시지 전송
59
+ - 단일 모드: 추가 tfx-route.sh 호출
60
+ - maxIterations 내에서 반복 가능 (기본 2회)
22
61
 
23
62
  ## Phase 2.6: PRD (Codex analyst)
24
63