triflux 10.9.19 → 10.9.21
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 +212 -0
- package/hub/lib/bash-path.mjs +73 -0
- package/hub/team/dashboard-open.mjs +1 -68
- package/hub/team/native-supervisor.mjs +9 -2
- package/hub/team/psmux.mjs +5 -13
- package/hub/team/session.mjs +6 -26
- package/hub/team/swarm-hypervisor.mjs +205 -27
- package/hub/team/synapse-http.mjs +1 -0
- package/hub/team/tui-core.mjs +292 -0
- package/hub/team/tui-lite.mjs +20 -154
- package/hub/team/tui-synapse.mjs +213 -0
- package/hub/team/tui-widgets.mjs +262 -0
- package/hub/team/tui.mjs +159 -255
- package/hub/workers/delegator-mcp.mjs +2 -2
- package/package.json +21 -62
- package/references/hosts.json +46 -0
- package/scripts/__tests__/keyword-detector.test.mjs +4 -4
- package/scripts/cross-review-gate.mjs +13 -0
- package/scripts/remote-spawn.mjs +11 -46
- package/scripts/session-spawn-helper.mjs +8 -21
- package/scripts/test-tfx-route-no-claude-native.mjs +4 -2
- package/scripts/tfx-route.sh +13 -0
- package/skills/tfx-deep-interview/SKILL.md +6 -6
- package/skills/tfx-deep-interview/SKILL.md.tmpl +6 -6
- package/skills/tfx-index/SKILL.md +1 -1
- package/skills/tfx-index/SKILL.md.tmpl +1 -1
- package/skills/tfx-interview/SKILL.md +9 -9
- package/skills/tfx-interview/SKILL.md.tmpl +9 -9
- package/skills/tfx-plan/SKILL.md +1 -1
- package/skills/tfx-plan/SKILL.md.tmpl +1 -1
- package/skills/tfx-research/SKILL.md +1 -1
- package/skills/tfx-research/SKILL.md.tmpl +1 -1
- package/skills/tfx-workspace/async-tests/run-tests.sh +203 -0
- package/skills/tfx-workspace/evals/evals.json +79 -0
- package/skills/tfx-workspace/iteration-1/benchmark.json +524 -0
- package/skills/tfx-workspace/iteration-1/codex-gemini-remap/eval_metadata.json +11 -0
- package/skills/tfx-workspace/iteration-1/codex-gemini-remap/old_skill/grading.json +25 -0
- package/skills/tfx-workspace/iteration-1/codex-gemini-remap/old_skill/outputs/analysis.md +154 -0
- package/skills/tfx-workspace/iteration-1/codex-gemini-remap/old_skill/timing.json +5 -0
- package/skills/tfx-workspace/iteration-1/codex-gemini-remap/with_skill/grading.json +25 -0
- package/skills/tfx-workspace/iteration-1/codex-gemini-remap/with_skill/outputs/analysis.md +126 -0
- package/skills/tfx-workspace/iteration-1/codex-gemini-remap/with_skill/timing.json +5 -0
- package/skills/tfx-workspace/iteration-1/doctor-diagnosis/eval_metadata.json +11 -0
- package/skills/tfx-workspace/iteration-1/doctor-diagnosis/old_skill/grading.json +25 -0
- package/skills/tfx-workspace/iteration-1/doctor-diagnosis/old_skill/outputs/analysis.md +119 -0
- package/skills/tfx-workspace/iteration-1/doctor-diagnosis/old_skill/timing.json +5 -0
- package/skills/tfx-workspace/iteration-1/doctor-diagnosis/with_skill/grading.json +25 -0
- package/skills/tfx-workspace/iteration-1/doctor-diagnosis/with_skill/outputs/analysis.md +115 -0
- package/skills/tfx-workspace/iteration-1/doctor-diagnosis/with_skill/timing.json +5 -0
- package/skills/tfx-workspace/iteration-1/hub-start-sequence/eval_metadata.json +10 -0
- package/skills/tfx-workspace/iteration-1/hub-start-sequence/old_skill/grading.json +20 -0
- package/skills/tfx-workspace/iteration-1/hub-start-sequence/old_skill/outputs/analysis.md +86 -0
- package/skills/tfx-workspace/iteration-1/hub-start-sequence/old_skill/timing.json +5 -0
- package/skills/tfx-workspace/iteration-1/hub-start-sequence/with_skill/grading.json +20 -0
- package/skills/tfx-workspace/iteration-1/hub-start-sequence/with_skill/outputs/analysis.md +81 -0
- package/skills/tfx-workspace/iteration-1/hub-start-sequence/with_skill/timing.json +5 -0
- package/skills/tfx-workspace/iteration-1/multi-team-creation/eval_metadata.json +12 -0
- package/skills/tfx-workspace/iteration-1/multi-team-creation/old_skill/grading.json +30 -0
- package/skills/tfx-workspace/iteration-1/multi-team-creation/old_skill/outputs/analysis.md +316 -0
- package/skills/tfx-workspace/iteration-1/multi-team-creation/old_skill/timing.json +5 -0
- package/skills/tfx-workspace/iteration-1/multi-team-creation/with_skill/grading.json +30 -0
- package/skills/tfx-workspace/iteration-1/multi-team-creation/with_skill/outputs/analysis.md +352 -0
- package/skills/tfx-workspace/iteration-1/multi-team-creation/with_skill/timing.json +5 -0
- package/skills/tfx-workspace/iteration-1/review.html +1325 -0
- package/skills/tfx-workspace/iteration-1/routing-implement-shortcut/eval_metadata.json +12 -0
- package/skills/tfx-workspace/iteration-1/routing-implement-shortcut/old_skill/grading.json +30 -0
- package/skills/tfx-workspace/iteration-1/routing-implement-shortcut/old_skill/outputs/analysis.md +97 -0
- package/skills/tfx-workspace/iteration-1/routing-implement-shortcut/old_skill/timing.json +5 -0
- package/skills/tfx-workspace/iteration-1/routing-implement-shortcut/with_skill/grading.json +30 -0
- package/skills/tfx-workspace/iteration-1/routing-implement-shortcut/with_skill/outputs/analysis.md +94 -0
- package/skills/tfx-workspace/iteration-1/routing-implement-shortcut/with_skill/timing.json +5 -0
- package/skills/tfx-workspace/iteration-1/routing-multi-task-triage/eval_metadata.json +12 -0
- package/skills/tfx-workspace/iteration-1/routing-multi-task-triage/old_skill/grading.json +30 -0
- package/skills/tfx-workspace/iteration-1/routing-multi-task-triage/old_skill/outputs/analysis.md +209 -0
- package/skills/tfx-workspace/iteration-1/routing-multi-task-triage/old_skill/timing.json +5 -0
- package/skills/tfx-workspace/iteration-1/routing-multi-task-triage/with_skill/grading.json +30 -0
- package/skills/tfx-workspace/iteration-1/routing-multi-task-triage/with_skill/outputs/analysis.md +193 -0
- package/skills/tfx-workspace/iteration-1/routing-multi-task-triage/with_skill/timing.json +5 -0
- package/skills/tfx-workspace/iteration-2/benchmark.json +144 -0
- package/skills/tfx-workspace/iteration-2/multi-team-creation-refactored/eval_metadata.json +13 -0
- package/skills/tfx-workspace/iteration-2/multi-team-creation-refactored/old_skill/grading.json +35 -0
- package/skills/tfx-workspace/iteration-2/multi-team-creation-refactored/old_skill/outputs/analysis.md +382 -0
- package/skills/tfx-workspace/iteration-2/multi-team-creation-refactored/old_skill/timing.json +5 -0
- package/skills/tfx-workspace/iteration-2/multi-team-creation-refactored/with_skill/grading.json +35 -0
- package/skills/tfx-workspace/iteration-2/multi-team-creation-refactored/with_skill/outputs/analysis.md +333 -0
- package/skills/tfx-workspace/iteration-2/multi-team-creation-refactored/with_skill/timing.json +5 -0
- package/skills/tfx-workspace/iteration-2/review.html +1325 -0
- package/skills/tfx-workspace/skill-snapshot/tfx-auto/SKILL.md +217 -0
- package/skills/tfx-workspace/skill-snapshot/tfx-auto-codex/SKILL.md +77 -0
- package/skills/tfx-workspace/skill-snapshot/tfx-codex/SKILL.md +65 -0
- package/skills/tfx-workspace/skill-snapshot/tfx-doctor/SKILL.md +94 -0
- package/skills/tfx-workspace/skill-snapshot/tfx-gemini/SKILL.md +82 -0
- package/skills/tfx-workspace/skill-snapshot/tfx-hub/SKILL.md +133 -0
- package/skills/tfx-workspace/skill-snapshot/tfx-multi/SKILL.md +426 -0
- package/skills/tfx-workspace/skill-snapshot/tfx-setup/SKILL.md +101 -0
- package/.claude-plugin/marketplace.json +0 -34
- package/.claude-plugin/plugin.json +0 -22
- package/config/mcp-registry.json +0 -29
- package/scripts/__tests__/release-governance.test.mjs +0 -148
- package/scripts/release/bump-version.mjs +0 -77
- package/scripts/release/check-sync.mjs +0 -51
- package/scripts/release/lib.mjs +0 -303
- package/scripts/release/prepare.mjs +0 -85
- package/scripts/release/publish.mjs +0 -87
- package/scripts/release/verify.mjs +0 -81
- package/scripts/release/version-manifest.json +0 -26
- package/tui/codex-profile.mjs +0 -457
- package/tui/core.mjs +0 -266
- package/tui/doctor.mjs +0 -375
- package/tui/gemini-profile.mjs +0 -299
- package/tui/monitor-data.mjs +0 -152
- package/tui/monitor.mjs +0 -339
- package/tui/setup.mjs +0 -598
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
{
|
|
2
|
+
"hosts": {
|
|
3
|
+
"ultra4": {
|
|
4
|
+
"description": "Windows 데스크탑 (22코어/64GB RAM)",
|
|
5
|
+
"aliases": ["울트라", "울트라4", "데스크탑"],
|
|
6
|
+
"default_dir": "~/Desktop/Projects/cli/triflux",
|
|
7
|
+
"tailscale": {
|
|
8
|
+
"ip": "100.110.136.64",
|
|
9
|
+
"dns": "ultra-book-4-1",
|
|
10
|
+
"ssh_mode": "ssh-over-vpn"
|
|
11
|
+
},
|
|
12
|
+
"ssh_user": "SSAFY",
|
|
13
|
+
"os": "windows",
|
|
14
|
+
"specs": {
|
|
15
|
+
"cores": 22,
|
|
16
|
+
"ram_gb": 64,
|
|
17
|
+
"codex": "0.118.0",
|
|
18
|
+
"node": "24.14.0"
|
|
19
|
+
},
|
|
20
|
+
"capabilities": ["codex", "claude", "high-memory"]
|
|
21
|
+
},
|
|
22
|
+
"m2": {
|
|
23
|
+
"description": "MacBook Air M2 (8코어/16GB RAM)",
|
|
24
|
+
"aliases": ["맥", "맥북", "m2"],
|
|
25
|
+
"default_dir": "~/Desktop/Projects/triflux",
|
|
26
|
+
"tailscale": {
|
|
27
|
+
"ip": "100.104.61.126",
|
|
28
|
+
"dns": "tellang의-macbook-air",
|
|
29
|
+
"ssh_mode": "ssh-over-vpn"
|
|
30
|
+
},
|
|
31
|
+
"ssh_user": "tellang",
|
|
32
|
+
"os": "darwin",
|
|
33
|
+
"specs": {
|
|
34
|
+
"cores": 8,
|
|
35
|
+
"ram_gb": 16,
|
|
36
|
+
"claude": "2.1.89",
|
|
37
|
+
"codex": "0.114.0",
|
|
38
|
+
"gemini": "0.33.1",
|
|
39
|
+
"node": "25.9.0"
|
|
40
|
+
},
|
|
41
|
+
"capabilities": ["codex", "claude", "gemini"]
|
|
42
|
+
}
|
|
43
|
+
},
|
|
44
|
+
"default_host": "m2",
|
|
45
|
+
"triggers": ["원격에서", "다른 머신에서", "다른 컴퓨터에서"]
|
|
46
|
+
}
|
|
@@ -34,7 +34,7 @@ const { extractPrompt, sanitizeForKeywordDetection } = detectorModule;
|
|
|
34
34
|
|
|
35
35
|
function loadCompiledRules() {
|
|
36
36
|
const rules = loadRules(rulesPath);
|
|
37
|
-
assert.
|
|
37
|
+
assert.equal(rules.length, 32);
|
|
38
38
|
return compileRules(rules);
|
|
39
39
|
}
|
|
40
40
|
|
|
@@ -108,8 +108,8 @@ test("sanitizeForKeywordDetection: 코드블록/URL/파일경로/XML 태그 제
|
|
|
108
108
|
|
|
109
109
|
test("loadRules: 유효한 JSON 로드", () => {
|
|
110
110
|
const rules = loadRules(rulesPath);
|
|
111
|
-
assert.
|
|
112
|
-
assert.
|
|
111
|
+
assert.equal(rules.length, 32);
|
|
112
|
+
assert.equal(rules.filter((rule) => rule.skill).length, 18);
|
|
113
113
|
assert.equal(rules.filter((rule) => rule.mcp_route).length, 10);
|
|
114
114
|
});
|
|
115
115
|
|
|
@@ -130,7 +130,7 @@ test("loadRules: 잘못된 파일 처리", () => {
|
|
|
130
130
|
test("compileRules: 정규식 컴파일 성공", () => {
|
|
131
131
|
const rules = loadRules(rulesPath);
|
|
132
132
|
const compiled = compileRules(rules);
|
|
133
|
-
assert.equal(compiled.length,
|
|
133
|
+
assert.equal(compiled.length, 32);
|
|
134
134
|
for (const rule of compiled) {
|
|
135
135
|
assert.ok(Array.isArray(rule.compiledPatterns));
|
|
136
136
|
assert.ok(rule.compiledPatterns.length > 0);
|
|
@@ -38,6 +38,11 @@ function isGitCommitCommand(command) {
|
|
|
38
38
|
return /\bgit\s+commit\b/i.test(command);
|
|
39
39
|
}
|
|
40
40
|
|
|
41
|
+
function hasCoAuthoredByTrailer(command) {
|
|
42
|
+
if (typeof command !== "string") return false;
|
|
43
|
+
return /co-authored-by\s*:/i.test(command);
|
|
44
|
+
}
|
|
45
|
+
|
|
41
46
|
function summarizePending(entries) {
|
|
42
47
|
return entries
|
|
43
48
|
.map((item) => {
|
|
@@ -64,6 +69,14 @@ async function main() {
|
|
|
64
69
|
if (toolName !== "Bash") process.exit(0);
|
|
65
70
|
if (!isGitCommitCommand(toolInput.command || "")) process.exit(0);
|
|
66
71
|
|
|
72
|
+
// ISSUE-9: Co-Authored-By 트레일러 차단
|
|
73
|
+
if (hasCoAuthoredByTrailer(toolInput.command || "")) {
|
|
74
|
+
deny(
|
|
75
|
+
"[co-author-guard] Co-Authored-By 트레일러가 감지되었습니다. " +
|
|
76
|
+
"커밋 메시지에서 Co-Authored-By 줄을 제거하세요.",
|
|
77
|
+
);
|
|
78
|
+
}
|
|
79
|
+
|
|
67
80
|
// cwd 전파: tracker와 동일한 resolveBaseDir 사용
|
|
68
81
|
const baseDir = resolveBaseDir(payload);
|
|
69
82
|
const statePath = join(baseDir, STATE_REL_PATH);
|
package/scripts/remote-spawn.mjs
CHANGED
|
@@ -606,27 +606,19 @@ function spawnLocalFallback(args, claudePath, prompt) {
|
|
|
606
606
|
return;
|
|
607
607
|
}
|
|
608
608
|
|
|
609
|
-
const wtArgs = ["new-tab", "-d", dir, "--"];
|
|
610
609
|
const claudeForward = claudePath.replace(/\\/g, "/");
|
|
610
|
+
let command;
|
|
611
611
|
|
|
612
612
|
if (prompt) {
|
|
613
613
|
const psQuoted = `'${prompt.replace(/'/g, "''")}'`;
|
|
614
|
-
|
|
615
|
-
"pwsh",
|
|
616
|
-
"-NoProfile",
|
|
617
|
-
"-Command",
|
|
618
|
-
`& '${claudeForward}' ${getPermissionFlag().join(" ")} ${psQuoted}`,
|
|
619
|
-
);
|
|
614
|
+
command = `pwsh -NoProfile -Command "& '${claudeForward}' ${getPermissionFlag().join(" ")} ${psQuoted}"`;
|
|
620
615
|
} else {
|
|
621
|
-
|
|
616
|
+
command = `${claudeForward} ${getPermissionFlag().join(" ")}`;
|
|
622
617
|
}
|
|
623
618
|
|
|
624
619
|
try {
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
stdio: "ignore",
|
|
628
|
-
windowsHide: false,
|
|
629
|
-
}).unref();
|
|
620
|
+
const wt = (await import("../hub/team/wt-manager.mjs")).createWtManager();
|
|
621
|
+
await wt.createTab({ title: "Claude", command, cwd: dir });
|
|
630
622
|
console.log(`spawned local Claude in WT tab → ${dir}`);
|
|
631
623
|
} catch (error) {
|
|
632
624
|
console.error("wt.exe spawn failed:", error.message);
|
|
@@ -717,23 +709,9 @@ function spawnRemoteFallback(args, promptContext) {
|
|
|
717
709
|
const remoteCmd = `pwsh -NoExit -File ${remoteScript}`;
|
|
718
710
|
|
|
719
711
|
if (IS_WINDOWS_LOCAL) {
|
|
720
|
-
const wtArgs = [
|
|
721
|
-
"new-tab",
|
|
722
|
-
"--title",
|
|
723
|
-
`Claude@${host}`,
|
|
724
|
-
"--",
|
|
725
|
-
"ssh",
|
|
726
|
-
"-t",
|
|
727
|
-
"--",
|
|
728
|
-
host,
|
|
729
|
-
remoteCmd,
|
|
730
|
-
];
|
|
731
712
|
try {
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
stdio: "ignore",
|
|
735
|
-
windowsHide: false,
|
|
736
|
-
}).unref();
|
|
713
|
+
const wt = (await import("../hub/team/wt-manager.mjs")).createWtManager();
|
|
714
|
+
await wt.createTab({ title: `Claude@${host}`, command: `ssh -t -- ${host} ${remoteCmd}` });
|
|
737
715
|
console.log(`spawned remote Claude → ${host}:${dir}`);
|
|
738
716
|
} catch (error) {
|
|
739
717
|
console.error("wt.exe spawn failed:", error.message);
|
|
@@ -1024,23 +1002,10 @@ function listSpawnSessions() {
|
|
|
1024
1002
|
function openAttachTab(sessionName, title = null) {
|
|
1025
1003
|
if (IS_WINDOWS_LOCAL) {
|
|
1026
1004
|
const wtArgs = title
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
"--suppressApplicationTitle",
|
|
1032
|
-
"--",
|
|
1033
|
-
"psmux",
|
|
1034
|
-
"attach",
|
|
1035
|
-
"-t",
|
|
1036
|
-
sessionName,
|
|
1037
|
-
]
|
|
1038
|
-
: ["new-tab", "--", "psmux", "attach", "-t", sessionName];
|
|
1039
|
-
spawn("wt.exe", wtArgs, {
|
|
1040
|
-
detached: true,
|
|
1041
|
-
stdio: "ignore",
|
|
1042
|
-
windowsHide: false,
|
|
1043
|
-
}).unref();
|
|
1005
|
+
try {
|
|
1006
|
+
const wt = (await import("../hub/team/wt-manager.mjs")).createWtManager();
|
|
1007
|
+
await wt.createTab({ title: title || sessionName, command: `psmux attach -t ${sessionName}` });
|
|
1008
|
+
} catch { /* fallback below */ }
|
|
1044
1009
|
return;
|
|
1045
1010
|
}
|
|
1046
1011
|
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { execFileSync } from "node:child_process";
|
|
3
3
|
import { spawn } from "../hub/lib/spawn-trace.mjs";
|
|
4
|
+
import { createWtManager } from "../hub/team/wt-manager.mjs";
|
|
4
5
|
|
|
5
6
|
const SESSION_PREFIX = "tfx-isolated";
|
|
6
7
|
const DEFAULT_ATTACH_PROFILE = "triflux";
|
|
@@ -103,31 +104,17 @@ export function createIsolatedSession(options = {}) {
|
|
|
103
104
|
return { sessionName };
|
|
104
105
|
}
|
|
105
106
|
|
|
106
|
-
export function attachWithWindowsTerminal(sessionName, options = {}) {
|
|
107
|
+
export async function attachWithWindowsTerminal(sessionName, options = {}) {
|
|
107
108
|
const profile = options.profile || DEFAULT_ATTACH_PROFILE;
|
|
108
109
|
const title = options.title || sessionName;
|
|
109
|
-
const spawnFn = options.spawnFn || spawn;
|
|
110
110
|
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
"
|
|
114
|
-
"-p",
|
|
115
|
-
profile,
|
|
116
|
-
"--title",
|
|
111
|
+
const wt = createWtManager();
|
|
112
|
+
await wt.splitPane({
|
|
113
|
+
direction: "H",
|
|
117
114
|
title,
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
"attach-session",
|
|
121
|
-
"-t",
|
|
122
|
-
sessionName,
|
|
123
|
-
];
|
|
124
|
-
const child = spawnFn("wt.exe", wtArgs, {
|
|
125
|
-
detached: true,
|
|
126
|
-
stdio: "ignore",
|
|
127
|
-
windowsHide: false,
|
|
115
|
+
profile,
|
|
116
|
+
command: `psmux attach-session -t ${sessionName}`,
|
|
128
117
|
});
|
|
129
|
-
child.unref();
|
|
130
|
-
return wtArgs;
|
|
131
118
|
}
|
|
132
119
|
|
|
133
120
|
export function waitForCompletion(sessionName, opts = {}) {
|
|
@@ -252,7 +239,7 @@ async function main() {
|
|
|
252
239
|
process.stdout.write(`[session-spawn] 세션 생성: ${sessionName}\n`);
|
|
253
240
|
|
|
254
241
|
if (args.attach) {
|
|
255
|
-
attachWithWindowsTerminal(sessionName);
|
|
242
|
+
await attachWithWindowsTerminal(sessionName);
|
|
256
243
|
process.stdout.write(`[session-spawn] WT split-pane attach 완료\n`);
|
|
257
244
|
}
|
|
258
245
|
|
|
@@ -4,12 +4,14 @@ import { spawnSync } from "node:child_process";
|
|
|
4
4
|
import { dirname, resolve } from "node:path";
|
|
5
5
|
import test from "node:test";
|
|
6
6
|
import { fileURLToPath } from "node:url";
|
|
7
|
+
import { resolveBashExecutable } from "../hub/lib/bash-path.mjs";
|
|
7
8
|
|
|
8
9
|
const SCRIPT_DIR = dirname(fileURLToPath(import.meta.url));
|
|
9
10
|
const PROJECT_ROOT = resolve(SCRIPT_DIR, "..");
|
|
11
|
+
const BASH_EXE = resolveBashExecutable();
|
|
10
12
|
|
|
11
13
|
function runBash(command) {
|
|
12
|
-
return spawnSync(
|
|
14
|
+
return spawnSync(BASH_EXE, ["-lc", command], {
|
|
13
15
|
cwd: PROJECT_ROOT,
|
|
14
16
|
encoding: "utf8",
|
|
15
17
|
env: {
|
|
@@ -39,7 +41,7 @@ test("gemini 모드에서는 no-claude-native 강제 치환이 적용되지 않
|
|
|
39
41
|
|
|
40
42
|
test("auto 모드 + no-claude-native=1이면 explore가 codex로 치환된다", () => {
|
|
41
43
|
const result = runBash(
|
|
42
|
-
"TFX_CLI_MODE=auto TFX_NO_CLAUDE_NATIVE=1 CODEX_BIN=
|
|
44
|
+
"TFX_CLI_MODE=auto TFX_NO_CLAUDE_NATIVE=1 CODEX_BIN=echo bash scripts/tfx-route.sh explore 'test-case' minimal 5",
|
|
43
45
|
);
|
|
44
46
|
|
|
45
47
|
assert.equal(result.status, 0, out(result));
|
package/scripts/tfx-route.sh
CHANGED
|
@@ -104,6 +104,19 @@ if [[ -f "$_CODEX_CONFIG" ]] && awk '
|
|
|
104
104
|
_CODEX_HAS_SANDBOX="1"
|
|
105
105
|
fi
|
|
106
106
|
|
|
107
|
+
# ── MCP tool approval_mode stall 방지 (ISSUE-4) ──
|
|
108
|
+
# oh-my-codex 업데이트가 MCP tool 블록의 approval_mode를 "approve"로 복원함.
|
|
109
|
+
# codex exec는 non-TTY subprocess이므로 interactive 승인 대기 = output 0B stall.
|
|
110
|
+
# 실행 전 자동으로 "full-auto"로 교체한다.
|
|
111
|
+
if [[ -f "$_CODEX_CONFIG" ]] && grep -q 'approval_mode = "approve"' "$_CODEX_CONFIG" 2>/dev/null; then
|
|
112
|
+
_approve_count=$(grep -c 'approval_mode = "approve"' "$_CODEX_CONFIG" 2>/dev/null || echo 0)
|
|
113
|
+
if [[ "$_approve_count" -gt 0 ]]; then
|
|
114
|
+
cp "$_CODEX_CONFIG" "${_CODEX_CONFIG}.bak-$(date +%Y%m%d-%H%M%S)" 2>/dev/null || true
|
|
115
|
+
sed -i 's/approval_mode = "approve"/approval_mode = "full-auto"/g' "$_CODEX_CONFIG"
|
|
116
|
+
echo "[tfx-route] MCP tool approval_mode stall 방지: ${_approve_count}개 블록 approve→full-auto 자동 수정" >&2
|
|
117
|
+
fi
|
|
118
|
+
fi
|
|
119
|
+
|
|
107
120
|
build_codex_base() {
|
|
108
121
|
# codex exec는 항상 non-TTY subprocess에서 실행되므로 --dangerously-bypass 필수.
|
|
109
122
|
# --dangerously-bypass는 config.toml의 approval_mode/sandbox와 충돌하지 않음
|
|
@@ -60,7 +60,7 @@ Claude 토큰을 절약하기 위해 분석 작업은 Gemini CLI에 위임합니
|
|
|
60
60
|
**단계 진입 시 Gemini 위임:**
|
|
61
61
|
|
|
62
62
|
```
|
|
63
|
-
Bash("bash scripts/tfx-route.sh gemini exec 'Deep interview Stage 1: Clarify. Topic: {topic}. Previous answers: none. Generate 3 probing questions for this stage and analyze prior responses. Return JSON: {analysis, questions, key_insights}'")
|
|
63
|
+
Bash("bash ~/.claude/scripts/tfx-route.sh gemini exec 'Deep interview Stage 1: Clarify. Topic: {topic}. Previous answers: none. Generate 3 probing questions for this stage and analyze prior responses. Return JSON: {analysis, questions, key_insights}'")
|
|
64
64
|
```
|
|
65
65
|
|
|
66
66
|
Gemini가 반환한 `questions` 배열을 AskUserQuestion으로 사용자에게 제시합니다.
|
|
@@ -80,7 +80,7 @@ Gemini가 반환한 `questions` 배열을 AskUserQuestion으로 사용자에게
|
|
|
80
80
|
**단계 진입 시 Gemini 위임:**
|
|
81
81
|
|
|
82
82
|
```
|
|
83
|
-
Bash("bash scripts/tfx-route.sh gemini exec 'Deep interview Stage 2: Decompose. Topic: {topic}. Previous answers: {stage1_answers}. Generate 3 probing questions for this stage and analyze prior responses. Return JSON: {analysis, questions, key_insights}'")
|
|
83
|
+
Bash("bash ~/.claude/scripts/tfx-route.sh gemini exec 'Deep interview Stage 2: Decompose. Topic: {topic}. Previous answers: {stage1_answers}. Generate 3 probing questions for this stage and analyze prior responses. Return JSON: {analysis, questions, key_insights}'")
|
|
84
84
|
```
|
|
85
85
|
|
|
86
86
|
Gemini가 반환한 `questions` 배열을 AskUserQuestion으로 사용자에게 제시합니다.
|
|
@@ -100,7 +100,7 @@ Gemini가 반환한 `questions` 배열을 AskUserQuestion으로 사용자에게
|
|
|
100
100
|
**단계 진입 시 Gemini 위임:**
|
|
101
101
|
|
|
102
102
|
```
|
|
103
|
-
Bash("bash scripts/tfx-route.sh gemini exec 'Deep interview Stage 3: Challenge. Topic: {topic}. Previous answers: {stage1_answers} {stage2_answers}. Generate 3 probing questions for this stage and analyze prior responses. Return JSON: {analysis, questions, key_insights}'")
|
|
103
|
+
Bash("bash ~/.claude/scripts/tfx-route.sh gemini exec 'Deep interview Stage 3: Challenge. Topic: {topic}. Previous answers: {stage1_answers} {stage2_answers}. Generate 3 probing questions for this stage and analyze prior responses. Return JSON: {analysis, questions, key_insights}'")
|
|
104
104
|
```
|
|
105
105
|
|
|
106
106
|
Gemini가 반환한 `questions` 배열을 AskUserQuestion으로 사용자에게 제시합니다.
|
|
@@ -120,7 +120,7 @@ Gemini가 반환한 `questions` 배열을 AskUserQuestion으로 사용자에게
|
|
|
120
120
|
**단계 진입 시 Gemini 위임:**
|
|
121
121
|
|
|
122
122
|
```
|
|
123
|
-
Bash("bash scripts/tfx-route.sh gemini exec 'Deep interview Stage 4: Alternatives. Topic: {topic}. Previous answers: {stage1_answers} {stage2_answers} {stage3_answers}. Generate 3 probing questions for this stage and analyze prior responses. Return JSON: {analysis, questions, key_insights}'")
|
|
123
|
+
Bash("bash ~/.claude/scripts/tfx-route.sh gemini exec 'Deep interview Stage 4: Alternatives. Topic: {topic}. Previous answers: {stage1_answers} {stage2_answers} {stage3_answers}. Generate 3 probing questions for this stage and analyze prior responses. Return JSON: {analysis, questions, key_insights}'")
|
|
124
124
|
```
|
|
125
125
|
|
|
126
126
|
Gemini가 반환한 `questions` 배열을 AskUserQuestion으로 사용자에게 제시합니다.
|
|
@@ -140,7 +140,7 @@ Gemini가 반환한 `questions` 배열을 AskUserQuestion으로 사용자에게
|
|
|
140
140
|
**단계 진입 시 Gemini 위임:**
|
|
141
141
|
|
|
142
142
|
```
|
|
143
|
-
Bash("bash scripts/tfx-route.sh gemini exec 'Deep interview Stage 5: Synthesize. Topic: {topic}. Previous answers: {stage1_answers} {stage2_answers} {stage3_answers} {stage4_answers}. Generate 3 probing questions for this stage and analyze prior responses. Return JSON: {analysis, questions, key_insights}'")
|
|
143
|
+
Bash("bash ~/.claude/scripts/tfx-route.sh gemini exec 'Deep interview Stage 5: Synthesize. Topic: {topic}. Previous answers: {stage1_answers} {stage2_answers} {stage3_answers} {stage4_answers}. Generate 3 probing questions for this stage and analyze prior responses. Return JSON: {analysis, questions, key_insights}'")
|
|
144
144
|
```
|
|
145
145
|
|
|
146
146
|
Gemini가 반환한 `questions` 배열을 AskUserQuestion으로 사용자에게 제시합니다.
|
|
@@ -158,7 +158,7 @@ Gemini가 반환한 `questions` 배열을 AskUserQuestion으로 사용자에게
|
|
|
158
158
|
**산출물 생성 Gemini 위임:**
|
|
159
159
|
|
|
160
160
|
```
|
|
161
|
-
Bash("bash scripts/tfx-route.sh gemini exec 'Deep interview complete. Topic: {topic}. All answers: {all_answers}. Generate a structured requirements document draft. Return the full markdown document.'")
|
|
161
|
+
Bash("bash ~/.claude/scripts/tfx-route.sh gemini exec 'Deep interview complete. Topic: {topic}. All answers: {all_answers}. Generate a structured requirements document draft. Return the full markdown document.'")
|
|
162
162
|
```
|
|
163
163
|
|
|
164
164
|
Gemini 실패 시 Claude가 직접 아래 형식으로 문서를 작성합니다.
|
|
@@ -60,7 +60,7 @@ Claude 토큰을 절약하기 위해 분석 작업은 Gemini CLI에 위임합니
|
|
|
60
60
|
**단계 진입 시 Gemini 위임:**
|
|
61
61
|
|
|
62
62
|
```
|
|
63
|
-
Bash("bash scripts/tfx-route.sh gemini exec 'Deep interview Stage 1: Clarify. Topic: {topic}. Previous answers: none. Generate 3 probing questions for this stage and analyze prior responses. Return JSON: {analysis, questions, key_insights}'")
|
|
63
|
+
Bash("bash ~/.claude/scripts/tfx-route.sh gemini exec 'Deep interview Stage 1: Clarify. Topic: {topic}. Previous answers: none. Generate 3 probing questions for this stage and analyze prior responses. Return JSON: {analysis, questions, key_insights}'")
|
|
64
64
|
```
|
|
65
65
|
|
|
66
66
|
Gemini가 반환한 `questions` 배열을 AskUserQuestion으로 사용자에게 제시합니다.
|
|
@@ -80,7 +80,7 @@ Gemini가 반환한 `questions` 배열을 AskUserQuestion으로 사용자에게
|
|
|
80
80
|
**단계 진입 시 Gemini 위임:**
|
|
81
81
|
|
|
82
82
|
```
|
|
83
|
-
Bash("bash scripts/tfx-route.sh gemini exec 'Deep interview Stage 2: Decompose. Topic: {topic}. Previous answers: {stage1_answers}. Generate 3 probing questions for this stage and analyze prior responses. Return JSON: {analysis, questions, key_insights}'")
|
|
83
|
+
Bash("bash ~/.claude/scripts/tfx-route.sh gemini exec 'Deep interview Stage 2: Decompose. Topic: {topic}. Previous answers: {stage1_answers}. Generate 3 probing questions for this stage and analyze prior responses. Return JSON: {analysis, questions, key_insights}'")
|
|
84
84
|
```
|
|
85
85
|
|
|
86
86
|
Gemini가 반환한 `questions` 배열을 AskUserQuestion으로 사용자에게 제시합니다.
|
|
@@ -100,7 +100,7 @@ Gemini가 반환한 `questions` 배열을 AskUserQuestion으로 사용자에게
|
|
|
100
100
|
**단계 진입 시 Gemini 위임:**
|
|
101
101
|
|
|
102
102
|
```
|
|
103
|
-
Bash("bash scripts/tfx-route.sh gemini exec 'Deep interview Stage 3: Challenge. Topic: {topic}. Previous answers: {stage1_answers} {stage2_answers}. Generate 3 probing questions for this stage and analyze prior responses. Return JSON: {analysis, questions, key_insights}'")
|
|
103
|
+
Bash("bash ~/.claude/scripts/tfx-route.sh gemini exec 'Deep interview Stage 3: Challenge. Topic: {topic}. Previous answers: {stage1_answers} {stage2_answers}. Generate 3 probing questions for this stage and analyze prior responses. Return JSON: {analysis, questions, key_insights}'")
|
|
104
104
|
```
|
|
105
105
|
|
|
106
106
|
Gemini가 반환한 `questions` 배열을 AskUserQuestion으로 사용자에게 제시합니다.
|
|
@@ -120,7 +120,7 @@ Gemini가 반환한 `questions` 배열을 AskUserQuestion으로 사용자에게
|
|
|
120
120
|
**단계 진입 시 Gemini 위임:**
|
|
121
121
|
|
|
122
122
|
```
|
|
123
|
-
Bash("bash scripts/tfx-route.sh gemini exec 'Deep interview Stage 4: Alternatives. Topic: {topic}. Previous answers: {stage1_answers} {stage2_answers} {stage3_answers}. Generate 3 probing questions for this stage and analyze prior responses. Return JSON: {analysis, questions, key_insights}'")
|
|
123
|
+
Bash("bash ~/.claude/scripts/tfx-route.sh gemini exec 'Deep interview Stage 4: Alternatives. Topic: {topic}. Previous answers: {stage1_answers} {stage2_answers} {stage3_answers}. Generate 3 probing questions for this stage and analyze prior responses. Return JSON: {analysis, questions, key_insights}'")
|
|
124
124
|
```
|
|
125
125
|
|
|
126
126
|
Gemini가 반환한 `questions` 배열을 AskUserQuestion으로 사용자에게 제시합니다.
|
|
@@ -140,7 +140,7 @@ Gemini가 반환한 `questions` 배열을 AskUserQuestion으로 사용자에게
|
|
|
140
140
|
**단계 진입 시 Gemini 위임:**
|
|
141
141
|
|
|
142
142
|
```
|
|
143
|
-
Bash("bash scripts/tfx-route.sh gemini exec 'Deep interview Stage 5: Synthesize. Topic: {topic}. Previous answers: {stage1_answers} {stage2_answers} {stage3_answers} {stage4_answers}. Generate 3 probing questions for this stage and analyze prior responses. Return JSON: {analysis, questions, key_insights}'")
|
|
143
|
+
Bash("bash ~/.claude/scripts/tfx-route.sh gemini exec 'Deep interview Stage 5: Synthesize. Topic: {topic}. Previous answers: {stage1_answers} {stage2_answers} {stage3_answers} {stage4_answers}. Generate 3 probing questions for this stage and analyze prior responses. Return JSON: {analysis, questions, key_insights}'")
|
|
144
144
|
```
|
|
145
145
|
|
|
146
146
|
Gemini가 반환한 `questions` 배열을 AskUserQuestion으로 사용자에게 제시합니다.
|
|
@@ -158,7 +158,7 @@ Gemini가 반환한 `questions` 배열을 AskUserQuestion으로 사용자에게
|
|
|
158
158
|
**산출물 생성 Gemini 위임:**
|
|
159
159
|
|
|
160
160
|
```
|
|
161
|
-
Bash("bash scripts/tfx-route.sh gemini exec 'Deep interview complete. Topic: {topic}. All answers: {all_answers}. Generate a structured requirements document draft. Return the full markdown document.'")
|
|
161
|
+
Bash("bash ~/.claude/scripts/tfx-route.sh gemini exec 'Deep interview complete. Topic: {topic}. All answers: {all_answers}. Generate a structured requirements document draft. Return the full markdown document.'")
|
|
162
162
|
```
|
|
163
163
|
|
|
164
164
|
Gemini 실패 시 Claude가 직접 아래 형식으로 문서를 작성합니다.
|
|
@@ -63,7 +63,7 @@ AskUserQuestion:
|
|
|
63
63
|
Claude는 프로젝트 경로와 모드를 Gemini에 전달하고, Gemini가 파일 트리 스캔·메타데이터 추출·인덱스 생성을 모두 수행한다.
|
|
64
64
|
|
|
65
65
|
```
|
|
66
|
-
Bash("bash scripts/tfx-route.sh gemini exec 'Scan the project at {path}. For each source file, extract: exports, imports, line count, file type. Exclude node_modules/, .git/, dist/, build/, coverage/, *.lock, *.log, *.map. Generate both PROJECT_INDEX.md and PROJECT_INDEX.json following this format:
|
|
66
|
+
Bash("bash ~/.claude/scripts/tfx-route.sh gemini exec 'Scan the project at {path}. For each source file, extract: exports, imports, line count, file type. Exclude node_modules/, .git/, dist/, build/, coverage/, *.lock, *.log, *.map. Generate both PROJECT_INDEX.md and PROJECT_INDEX.json following this format:
|
|
67
67
|
|
|
68
68
|
PROJECT_INDEX.md:
|
|
69
69
|
# PROJECT_INDEX.md
|
|
@@ -53,7 +53,7 @@ AskUserQuestion:
|
|
|
53
53
|
Claude는 프로젝트 경로와 모드를 Gemini에 전달하고, Gemini가 파일 트리 스캔·메타데이터 추출·인덱스 생성을 모두 수행한다.
|
|
54
54
|
|
|
55
55
|
```
|
|
56
|
-
Bash("bash scripts/tfx-route.sh gemini exec 'Scan the project at {path}. For each source file, extract: exports, imports, line count, file type. Exclude node_modules/, .git/, dist/, build/, coverage/, *.lock, *.log, *.map. Generate both PROJECT_INDEX.md and PROJECT_INDEX.json following this format:
|
|
56
|
+
Bash("bash ~/.claude/scripts/tfx-route.sh gemini exec 'Scan the project at {path}. For each source file, extract: exports, imports, line count, file type. Exclude node_modules/, .git/, dist/, build/, coverage/, *.lock, *.log, *.map. Generate both PROJECT_INDEX.md and PROJECT_INDEX.json following this format:
|
|
57
57
|
|
|
58
58
|
PROJECT_INDEX.md:
|
|
59
59
|
# PROJECT_INDEX.md
|
|
@@ -21,7 +21,7 @@ argument-hint: "<구현할 주제 또는 요구사항>"
|
|
|
21
21
|
> "측정할 수 없으면 개선할 수 없다."
|
|
22
22
|
>
|
|
23
23
|
> **Gemini 위임**: 분석·점수 계산·산출물 초안은 Gemini CLI에 위임하여 Claude 토큰을 절약한다.
|
|
24
|
-
> 위임 패턴: `Bash("bash scripts/tfx-route.sh gemini exec '{prompt}'")`
|
|
24
|
+
> 위임 패턴: `Bash("bash ~/.claude/scripts/tfx-route.sh gemini exec '{prompt}'")`
|
|
25
25
|
|
|
26
26
|
## 위임 패턴
|
|
27
27
|
|
|
@@ -34,7 +34,7 @@ Claude와 Gemini의 역할을 분리하여 토큰을 최적화한다.
|
|
|
34
34
|
|
|
35
35
|
```bash
|
|
36
36
|
# 위임 호출 형태
|
|
37
|
-
Bash("bash scripts/tfx-route.sh gemini exec '{prompt}'")
|
|
37
|
+
Bash("bash ~/.claude/scripts/tfx-route.sh gemini exec '{prompt}'")
|
|
38
38
|
```
|
|
39
39
|
|
|
40
40
|
Gemini 실패 시 Fallback: Claude Opus가 분석을 직접 처리한다.
|
|
@@ -76,7 +76,7 @@ ambiguity = 1 - (goal × 0.40 + constraints × 0.30 + criteria × 0.30)
|
|
|
76
76
|
|
|
77
77
|
```bash
|
|
78
78
|
# Claude → Gemini 위임
|
|
79
|
-
Bash("bash scripts/tfx-route.sh gemini exec 'Analyze the following requirement and calculate ambiguity score. Return JSON: {goal, constraints, criteria, ambiguity, suggested_questions}: {user_input}'")
|
|
79
|
+
Bash("bash ~/.claude/scripts/tfx-route.sh gemini exec 'Analyze the following requirement and calculate ambiguity score. Return JSON: {goal, constraints, criteria, ambiguity, suggested_questions}: {user_input}'")
|
|
80
80
|
```
|
|
81
81
|
|
|
82
82
|
Gemini가 반환한 JSON에서 점수를 읽어 사용자에게 표시한다:
|
|
@@ -107,7 +107,7 @@ Gemini가 반환한 JSON에서 점수를 읽어 사용자에게 표시한다:
|
|
|
107
107
|
|
|
108
108
|
```bash
|
|
109
109
|
# 응답 수집 후 Gemini에 분석 위임
|
|
110
|
-
Bash("bash scripts/tfx-route.sh gemini exec 'Stage 1 response analysis. Previous context: {context}. User answer: {answer}. Calculate updated ambiguity score and generate next stage questions. Return JSON.'")
|
|
110
|
+
Bash("bash ~/.claude/scripts/tfx-route.sh gemini exec 'Stage 1 response analysis. Previous context: {context}. User answer: {answer}. Calculate updated ambiguity score and generate next stage questions. Return JSON.'")
|
|
111
111
|
```
|
|
112
112
|
|
|
113
113
|
```
|
|
@@ -125,7 +125,7 @@ Bash("bash scripts/tfx-route.sh gemini exec 'Stage 1 response analysis. Previous
|
|
|
125
125
|
|
|
126
126
|
```bash
|
|
127
127
|
# 응답 수집 후 Gemini에 분석 위임
|
|
128
|
-
Bash("bash scripts/tfx-route.sh gemini exec 'Stage 2 response analysis. Previous context: {context}. User answer: {answer}. Calculate updated ambiguity score and generate next stage questions. Return JSON.'")
|
|
128
|
+
Bash("bash ~/.claude/scripts/tfx-route.sh gemini exec 'Stage 2 response analysis. Previous context: {context}. User answer: {answer}. Calculate updated ambiguity score and generate next stage questions. Return JSON.'")
|
|
129
129
|
```
|
|
130
130
|
|
|
131
131
|
```
|
|
@@ -143,7 +143,7 @@ Bash("bash scripts/tfx-route.sh gemini exec 'Stage 2 response analysis. Previous
|
|
|
143
143
|
|
|
144
144
|
```bash
|
|
145
145
|
# 응답 수집 후 Gemini에 분석 위임
|
|
146
|
-
Bash("bash scripts/tfx-route.sh gemini exec 'Stage 3 response analysis. Previous context: {context}. User answer: {answer}. Calculate updated ambiguity score and generate next stage questions. Return JSON.'")
|
|
146
|
+
Bash("bash ~/.claude/scripts/tfx-route.sh gemini exec 'Stage 3 response analysis. Previous context: {context}. User answer: {answer}. Calculate updated ambiguity score and generate next stage questions. Return JSON.'")
|
|
147
147
|
```
|
|
148
148
|
|
|
149
149
|
```
|
|
@@ -161,7 +161,7 @@ Bash("bash scripts/tfx-route.sh gemini exec 'Stage 3 response analysis. Previous
|
|
|
161
161
|
|
|
162
162
|
```bash
|
|
163
163
|
# 응답 수집 후 Gemini에 분석 위임
|
|
164
|
-
Bash("bash scripts/tfx-route.sh gemini exec 'Stage 4 response analysis. Previous context: {context}. User answer: {answer}. Calculate updated ambiguity score and generate next stage questions. Return JSON.'")
|
|
164
|
+
Bash("bash ~/.claude/scripts/tfx-route.sh gemini exec 'Stage 4 response analysis. Previous context: {context}. User answer: {answer}. Calculate updated ambiguity score and generate next stage questions. Return JSON.'")
|
|
165
165
|
```
|
|
166
166
|
|
|
167
167
|
```
|
|
@@ -179,7 +179,7 @@ Bash("bash scripts/tfx-route.sh gemini exec 'Stage 4 response analysis. Previous
|
|
|
179
179
|
|
|
180
180
|
```bash
|
|
181
181
|
# 응답 수집 후 Gemini에 최종 분석 위임
|
|
182
|
-
Bash("bash scripts/tfx-route.sh gemini exec 'Stage 5 response analysis. Previous context: {context}. User answer: {answer}. Calculate updated ambiguity score and generate next stage questions. Return JSON.'")
|
|
182
|
+
Bash("bash ~/.claude/scripts/tfx-route.sh gemini exec 'Stage 5 response analysis. Previous context: {context}. User answer: {answer}. Calculate updated ambiguity score and generate next stage questions. Return JSON.'")
|
|
183
183
|
```
|
|
184
184
|
|
|
185
185
|
```
|
|
@@ -207,7 +207,7 @@ Gemini가 인터뷰 전체 컨텍스트를 바탕으로 구조화된 문서 초
|
|
|
207
207
|
|
|
208
208
|
```bash
|
|
209
209
|
# Gemini에 산출물 초안 생성 위임
|
|
210
|
-
Bash("bash scripts/tfx-route.sh gemini exec 'Generate a structured interview output document based on the following interview context: {full_context}. Return the complete markdown document.'")
|
|
210
|
+
Bash("bash ~/.claude/scripts/tfx-route.sh gemini exec 'Generate a structured interview output document based on the following interview context: {full_context}. Return the complete markdown document.'")
|
|
211
211
|
```
|
|
212
212
|
|
|
213
213
|
Claude는 Gemini가 반환한 마크다운을 Write 도구로 저장한다.
|
|
@@ -21,7 +21,7 @@ argument-hint: "<구현할 주제 또는 요구사항>"
|
|
|
21
21
|
> "측정할 수 없으면 개선할 수 없다."
|
|
22
22
|
>
|
|
23
23
|
> **Gemini 위임**: 분석·점수 계산·산출물 초안은 Gemini CLI에 위임하여 Claude 토큰을 절약한다.
|
|
24
|
-
> 위임 패턴: `Bash("bash scripts/tfx-route.sh gemini exec '{prompt}'")`
|
|
24
|
+
> 위임 패턴: `Bash("bash ~/.claude/scripts/tfx-route.sh gemini exec '{prompt}'")`
|
|
25
25
|
|
|
26
26
|
## 위임 패턴
|
|
27
27
|
|
|
@@ -34,7 +34,7 @@ Claude와 Gemini의 역할을 분리하여 토큰을 최적화한다.
|
|
|
34
34
|
|
|
35
35
|
```bash
|
|
36
36
|
# 위임 호출 형태
|
|
37
|
-
Bash("bash scripts/tfx-route.sh gemini exec '{prompt}'")
|
|
37
|
+
Bash("bash ~/.claude/scripts/tfx-route.sh gemini exec '{prompt}'")
|
|
38
38
|
```
|
|
39
39
|
|
|
40
40
|
Gemini 실패 시 Fallback: Claude Opus가 분석을 직접 처리한다.
|
|
@@ -76,7 +76,7 @@ ambiguity = 1 - (goal × 0.40 + constraints × 0.30 + criteria × 0.30)
|
|
|
76
76
|
|
|
77
77
|
```bash
|
|
78
78
|
# Claude → Gemini 위임
|
|
79
|
-
Bash("bash scripts/tfx-route.sh gemini exec 'Analyze the following requirement and calculate ambiguity score. Return JSON: {goal, constraints, criteria, ambiguity, suggested_questions}: {user_input}'")
|
|
79
|
+
Bash("bash ~/.claude/scripts/tfx-route.sh gemini exec 'Analyze the following requirement and calculate ambiguity score. Return JSON: {goal, constraints, criteria, ambiguity, suggested_questions}: {user_input}'")
|
|
80
80
|
```
|
|
81
81
|
|
|
82
82
|
Gemini가 반환한 JSON에서 점수를 읽어 사용자에게 표시한다:
|
|
@@ -107,7 +107,7 @@ Gemini가 반환한 JSON에서 점수를 읽어 사용자에게 표시한다:
|
|
|
107
107
|
|
|
108
108
|
```bash
|
|
109
109
|
# 응답 수집 후 Gemini에 분석 위임
|
|
110
|
-
Bash("bash scripts/tfx-route.sh gemini exec 'Stage 1 response analysis. Previous context: {context}. User answer: {answer}. Calculate updated ambiguity score and generate next stage questions. Return JSON.'")
|
|
110
|
+
Bash("bash ~/.claude/scripts/tfx-route.sh gemini exec 'Stage 1 response analysis. Previous context: {context}. User answer: {answer}. Calculate updated ambiguity score and generate next stage questions. Return JSON.'")
|
|
111
111
|
```
|
|
112
112
|
|
|
113
113
|
```
|
|
@@ -125,7 +125,7 @@ Bash("bash scripts/tfx-route.sh gemini exec 'Stage 1 response analysis. Previous
|
|
|
125
125
|
|
|
126
126
|
```bash
|
|
127
127
|
# 응답 수집 후 Gemini에 분석 위임
|
|
128
|
-
Bash("bash scripts/tfx-route.sh gemini exec 'Stage 2 response analysis. Previous context: {context}. User answer: {answer}. Calculate updated ambiguity score and generate next stage questions. Return JSON.'")
|
|
128
|
+
Bash("bash ~/.claude/scripts/tfx-route.sh gemini exec 'Stage 2 response analysis. Previous context: {context}. User answer: {answer}. Calculate updated ambiguity score and generate next stage questions. Return JSON.'")
|
|
129
129
|
```
|
|
130
130
|
|
|
131
131
|
```
|
|
@@ -143,7 +143,7 @@ Bash("bash scripts/tfx-route.sh gemini exec 'Stage 2 response analysis. Previous
|
|
|
143
143
|
|
|
144
144
|
```bash
|
|
145
145
|
# 응답 수집 후 Gemini에 분석 위임
|
|
146
|
-
Bash("bash scripts/tfx-route.sh gemini exec 'Stage 3 response analysis. Previous context: {context}. User answer: {answer}. Calculate updated ambiguity score and generate next stage questions. Return JSON.'")
|
|
146
|
+
Bash("bash ~/.claude/scripts/tfx-route.sh gemini exec 'Stage 3 response analysis. Previous context: {context}. User answer: {answer}. Calculate updated ambiguity score and generate next stage questions. Return JSON.'")
|
|
147
147
|
```
|
|
148
148
|
|
|
149
149
|
```
|
|
@@ -161,7 +161,7 @@ Bash("bash scripts/tfx-route.sh gemini exec 'Stage 3 response analysis. Previous
|
|
|
161
161
|
|
|
162
162
|
```bash
|
|
163
163
|
# 응답 수집 후 Gemini에 분석 위임
|
|
164
|
-
Bash("bash scripts/tfx-route.sh gemini exec 'Stage 4 response analysis. Previous context: {context}. User answer: {answer}. Calculate updated ambiguity score and generate next stage questions. Return JSON.'")
|
|
164
|
+
Bash("bash ~/.claude/scripts/tfx-route.sh gemini exec 'Stage 4 response analysis. Previous context: {context}. User answer: {answer}. Calculate updated ambiguity score and generate next stage questions. Return JSON.'")
|
|
165
165
|
```
|
|
166
166
|
|
|
167
167
|
```
|
|
@@ -179,7 +179,7 @@ Bash("bash scripts/tfx-route.sh gemini exec 'Stage 4 response analysis. Previous
|
|
|
179
179
|
|
|
180
180
|
```bash
|
|
181
181
|
# 응답 수집 후 Gemini에 최종 분석 위임
|
|
182
|
-
Bash("bash scripts/tfx-route.sh gemini exec 'Stage 5 response analysis. Previous context: {context}. User answer: {answer}. Calculate updated ambiguity score and generate next stage questions. Return JSON.'")
|
|
182
|
+
Bash("bash ~/.claude/scripts/tfx-route.sh gemini exec 'Stage 5 response analysis. Previous context: {context}. User answer: {answer}. Calculate updated ambiguity score and generate next stage questions. Return JSON.'")
|
|
183
183
|
```
|
|
184
184
|
|
|
185
185
|
```
|
|
@@ -207,7 +207,7 @@ Gemini가 인터뷰 전체 컨텍스트를 바탕으로 구조화된 문서 초
|
|
|
207
207
|
|
|
208
208
|
```bash
|
|
209
209
|
# Gemini에 산출물 초안 생성 위임
|
|
210
|
-
Bash("bash scripts/tfx-route.sh gemini exec 'Generate a structured interview output document based on the following interview context: {full_context}. Return the complete markdown document.'")
|
|
210
|
+
Bash("bash ~/.claude/scripts/tfx-route.sh gemini exec 'Generate a structured interview output document based on the following interview context: {full_context}. Return the complete markdown document.'")
|
|
211
211
|
```
|
|
212
212
|
|
|
213
213
|
Claude는 Gemini가 반환한 마크다운을 Write 도구로 저장한다.
|
package/skills/tfx-plan/SKILL.md
CHANGED
|
@@ -41,7 +41,7 @@ Claude는 최소 컨텍스트만 수집한다.
|
|
|
41
41
|
|
|
42
42
|
수집 후 Gemini에 위임:
|
|
43
43
|
```
|
|
44
|
-
Bash("bash scripts/tfx-route.sh gemini exec '소프트웨어 아키텍트로서 다음 기능의 구현 계획을 수립하라.\n기능: {feature}\n프로젝트 컨텍스트: {context}\n관련 파일: {file_list}\n\n출력 형식:\n1. 영향 범위 (수정할 파일 목록)\n2. 태스크 분해 (순서대로, 각 태스크에 검증 방법 포함)\n3. 리스크 및 의존성\n4. 예상 복잡도 (low/medium/high)'")
|
|
44
|
+
Bash("bash ~/.claude/scripts/tfx-route.sh gemini exec '소프트웨어 아키텍트로서 다음 기능의 구현 계획을 수립하라.\n기능: {feature}\n프로젝트 컨텍스트: {context}\n관련 파일: {file_list}\n\n출력 형식:\n1. 영향 범위 (수정할 파일 목록)\n2. 태스크 분해 (순서대로, 각 태스크에 검증 방법 포함)\n3. 리스크 및 의존성\n4. 예상 복잡도 (low/medium/high)'")
|
|
45
45
|
```
|
|
46
46
|
|
|
47
47
|
Claude는 Gemini 출력을 받아 아래 출력 형식으로 포맷팅만 수행한다.
|
|
@@ -31,7 +31,7 @@ Claude는 최소 컨텍스트만 수집한다.
|
|
|
31
31
|
|
|
32
32
|
수집 후 Gemini에 위임:
|
|
33
33
|
```
|
|
34
|
-
Bash("bash scripts/tfx-route.sh gemini exec '소프트웨어 아키텍트로서 다음 기능의 구현 계획을 수립하라.\n기능: {feature}\n프로젝트 컨텍스트: {context}\n관련 파일: {file_list}\n\n출력 형식:\n1. 영향 범위 (수정할 파일 목록)\n2. 태스크 분해 (순서대로, 각 태스크에 검증 방법 포함)\n3. 리스크 및 의존성\n4. 예상 복잡도 (low/medium/high)'")
|
|
34
|
+
Bash("bash ~/.claude/scripts/tfx-route.sh gemini exec '소프트웨어 아키텍트로서 다음 기능의 구현 계획을 수립하라.\n기능: {feature}\n프로젝트 컨텍스트: {context}\n관련 파일: {file_list}\n\n출력 형식:\n1. 영향 범위 (수정할 파일 목록)\n2. 태스크 분해 (순서대로, 각 태스크에 검증 방법 포함)\n3. 리스크 및 의존성\n4. 예상 복잡도 (low/medium/high)'")
|
|
35
35
|
```
|
|
36
36
|
|
|
37
37
|
Claude는 Gemini 출력을 받아 아래 출력 형식으로 포맷팅만 수행한다.
|
|
@@ -71,7 +71,7 @@ AskUserQuestion:
|
|
|
71
71
|
최적화된 쿼리를 Gemini CLI로 전달한다. Gemini는 네이티브 Google Search를 사용해 검색과 요약을 모두 수행한다:
|
|
72
72
|
|
|
73
73
|
```
|
|
74
|
-
Bash("bash scripts/tfx-route.sh gemini 'Research the following topic. Use Google Search to find current information. Return a structured markdown summary with sources: {optimized_query}' auto 120")
|
|
74
|
+
Bash("bash ~/.claude/scripts/tfx-route.sh gemini 'Research the following topic. Use Google Search to find current information. Return a structured markdown summary with sources: {optimized_query}' auto 120")
|
|
75
75
|
```
|
|
76
76
|
|
|
77
77
|
Gemini가 반환하는 결과에는 검색 결과, 출처 URL, 핵심 요약이 포함된다. Claude는 이 단계에서 토큰을 소비하지 않는다.
|
|
@@ -61,7 +61,7 @@ AskUserQuestion:
|
|
|
61
61
|
최적화된 쿼리를 Gemini CLI로 전달한다. Gemini는 네이티브 Google Search를 사용해 검색과 요약을 모두 수행한다:
|
|
62
62
|
|
|
63
63
|
```
|
|
64
|
-
Bash("bash scripts/tfx-route.sh gemini 'Research the following topic. Use Google Search to find current information. Return a structured markdown summary with sources: {optimized_query}' auto 120")
|
|
64
|
+
Bash("bash ~/.claude/scripts/tfx-route.sh gemini 'Research the following topic. Use Google Search to find current information. Return a structured markdown summary with sources: {optimized_query}' auto 120")
|
|
65
65
|
```
|
|
66
66
|
|
|
67
67
|
Gemini가 반환하는 결과에는 검색 결과, 출처 URL, 핵심 요약이 포함된다. Claude는 이 단계에서 토큰을 소비하지 않는다.
|