triflux 9.5.1 → 9.6.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-plugin/plugin.json +1 -1
- package/bin/triflux.mjs +109 -0
- package/hub/team/headless.mjs +8 -1
- package/hub/team/psmux.mjs +24 -4
- package/package.json +1 -1
- package/scripts/headless-guard.mjs +1 -1
- package/scripts/setup.mjs +13 -0
- package/scripts/tfx-route.sh +17 -5
- package/skills/tfx-analysis/SKILL.md +4 -0
- package/skills/tfx-auto/SKILL.md +4 -0
- package/skills/tfx-auto-codex/SKILL.md +4 -0
- package/skills/tfx-autopilot/SKILL.md +4 -0
- package/skills/tfx-autoresearch/SKILL.md +4 -0
- package/skills/tfx-autoroute/SKILL.md +4 -0
- package/skills/tfx-codex/SKILL.md +4 -0
- package/skills/tfx-codex-swarm/SKILL.md +33 -2
- package/skills/tfx-consensus/SKILL.md +4 -0
- package/skills/tfx-debate/SKILL.md +4 -0
- package/skills/tfx-deep-analysis/SKILL.md +4 -0
- package/skills/tfx-deep-interview/SKILL.md +4 -0
- package/skills/tfx-deep-plan/SKILL.md +4 -0
- package/skills/tfx-deep-qa/SKILL.md +4 -0
- package/skills/tfx-deep-research/SKILL.md +4 -0
- package/skills/tfx-deep-review/SKILL.md +4 -0
- package/skills/tfx-doctor/SKILL.md +3 -0
- package/skills/tfx-find/SKILL.md +4 -0
- package/skills/tfx-forge/SKILL.md +4 -0
- package/skills/tfx-fullcycle/SKILL.md +4 -0
- package/skills/tfx-gemini/SKILL.md +4 -0
- package/skills/tfx-hub/SKILL.md +4 -0
- package/skills/tfx-index/SKILL.md +4 -0
- package/skills/tfx-interview/SKILL.md +4 -0
- package/skills/tfx-multi/SKILL.md +4 -0
- package/skills/tfx-panel/SKILL.md +4 -0
- package/skills/tfx-persist/SKILL.md +4 -0
- package/skills/tfx-plan/SKILL.md +4 -0
- package/skills/tfx-prune/SKILL.md +4 -0
- package/skills/tfx-qa/SKILL.md +4 -0
- package/skills/tfx-ralph/SKILL.md +4 -0
- package/skills/tfx-remote-setup/SKILL.md +4 -0
- package/skills/tfx-remote-spawn/SKILL.md +4 -0
- package/skills/tfx-research/SKILL.md +4 -0
- package/skills/tfx-review/SKILL.md +4 -0
package/bin/triflux.mjs
CHANGED
|
@@ -1766,6 +1766,115 @@ async function cmdDoctor(options = {}) {
|
|
|
1766
1766
|
ok("잔존 팀 없음");
|
|
1767
1767
|
}
|
|
1768
1768
|
|
|
1769
|
+
// ── Docs 동기화 상태 ──
|
|
1770
|
+
section("Docs Sync");
|
|
1771
|
+
{
|
|
1772
|
+
const docsDirs = ["docs/design", "docs/research"];
|
|
1773
|
+
const missingDocs = [];
|
|
1774
|
+
for (const dir of docsDirs) {
|
|
1775
|
+
const src = join(PKG_ROOT, dir);
|
|
1776
|
+
const dest = join(CLAUDE_DIR, dir);
|
|
1777
|
+
if (existsSync(src)) {
|
|
1778
|
+
const srcFiles = readdirSync(src).filter(f => f.endsWith(".md"));
|
|
1779
|
+
if (!existsSync(dest)) {
|
|
1780
|
+
missingDocs.push({ dir, missing: srcFiles.length, detail: "디렉토리 없음" });
|
|
1781
|
+
} else {
|
|
1782
|
+
const destFiles = readdirSync(dest).filter(f => f.endsWith(".md"));
|
|
1783
|
+
const missing = srcFiles.filter(f => !destFiles.includes(f));
|
|
1784
|
+
if (missing.length > 0) missingDocs.push({ dir, missing: missing.length, detail: missing.join(", ") });
|
|
1785
|
+
}
|
|
1786
|
+
}
|
|
1787
|
+
}
|
|
1788
|
+
if (missingDocs.length === 0) {
|
|
1789
|
+
addDoctorCheck(report, { name: "docs-sync", status: "ok" });
|
|
1790
|
+
ok("레퍼런스 문서 동기화 정상");
|
|
1791
|
+
} else {
|
|
1792
|
+
addDoctorCheck(report, { name: "docs-sync", status: "issues", missingDocs, fix: "tfx setup" });
|
|
1793
|
+
warn(`${missingDocs.reduce((s, d) => s + d.missing, 0)}개 레퍼런스 미동기화`);
|
|
1794
|
+
for (const d of missingDocs) info(`${d.dir}: ${d.detail}`);
|
|
1795
|
+
if (fix) {
|
|
1796
|
+
for (const dir of docsDirs) {
|
|
1797
|
+
const src = join(PKG_ROOT, dir);
|
|
1798
|
+
const dest = join(CLAUDE_DIR, dir);
|
|
1799
|
+
if (existsSync(src)) {
|
|
1800
|
+
mkdirSync(dest, { recursive: true });
|
|
1801
|
+
for (const f of readdirSync(src).filter(f => f.endsWith(".md"))) {
|
|
1802
|
+
copyFileSync(join(src, f), join(dest, f));
|
|
1803
|
+
}
|
|
1804
|
+
}
|
|
1805
|
+
}
|
|
1806
|
+
ok("레퍼런스 동기화 완료");
|
|
1807
|
+
} else {
|
|
1808
|
+
issues += missingDocs.length;
|
|
1809
|
+
}
|
|
1810
|
+
}
|
|
1811
|
+
}
|
|
1812
|
+
|
|
1813
|
+
// ── Gemini MCP 안전성 ──
|
|
1814
|
+
section("Gemini MCP Safety");
|
|
1815
|
+
{
|
|
1816
|
+
const geminiSettings = join(homedir(), ".gemini", "settings.json");
|
|
1817
|
+
if (existsSync(geminiSettings)) {
|
|
1818
|
+
try {
|
|
1819
|
+
const gs = JSON.parse(readFileSync(geminiSettings, "utf8"));
|
|
1820
|
+
const mcpServers = gs.mcpServers || {};
|
|
1821
|
+
const dangerousServers = Object.keys(mcpServers).filter(name => {
|
|
1822
|
+
const s = mcpServers[name];
|
|
1823
|
+
return s.command && !s.url && name !== "tfx-hub";
|
|
1824
|
+
});
|
|
1825
|
+
if (dangerousServers.length === 0) {
|
|
1826
|
+
addDoctorCheck(report, { name: "gemini-mcp-safety", status: "ok" });
|
|
1827
|
+
ok("stdio MCP 없음 (spawn EPERM 안전)");
|
|
1828
|
+
} else {
|
|
1829
|
+
addDoctorCheck(report, { name: "gemini-mcp-safety", status: "warning", servers: dangerousServers, fix: "~/.gemini/settings.json에서 stdio MCP 제거" });
|
|
1830
|
+
warn(`${dangerousServers.length}개 stdio MCP 감지 — Gemini stall 위험`);
|
|
1831
|
+
for (const s of dangerousServers) info(` ${s}`);
|
|
1832
|
+
issues++;
|
|
1833
|
+
}
|
|
1834
|
+
} catch {
|
|
1835
|
+
addDoctorCheck(report, { name: "gemini-mcp-safety", status: "ok" });
|
|
1836
|
+
ok("설정 파일 파싱 불가 — 건너뜀");
|
|
1837
|
+
}
|
|
1838
|
+
} else {
|
|
1839
|
+
addDoctorCheck(report, { name: "gemini-mcp-safety", status: "ok" });
|
|
1840
|
+
ok("Gemini 설정 없음 (정상)");
|
|
1841
|
+
}
|
|
1842
|
+
}
|
|
1843
|
+
|
|
1844
|
+
// ── Route Script 정합성 ──
|
|
1845
|
+
section("Route Script Sync");
|
|
1846
|
+
{
|
|
1847
|
+
const srcRoute = join(PKG_ROOT, "scripts", "tfx-route.sh");
|
|
1848
|
+
const destRoute = join(CLAUDE_DIR, "scripts", "tfx-route.sh");
|
|
1849
|
+
if (existsSync(srcRoute) && existsSync(destRoute)) {
|
|
1850
|
+
const srcHash = readFileSync(srcRoute, "utf8").length;
|
|
1851
|
+
const destHash = readFileSync(destRoute, "utf8").length;
|
|
1852
|
+
const srcContent = readFileSync(srcRoute, "utf8");
|
|
1853
|
+
const destContent = readFileSync(destRoute, "utf8");
|
|
1854
|
+
if (srcContent === destContent) {
|
|
1855
|
+
addDoctorCheck(report, { name: "route-sync", status: "ok" });
|
|
1856
|
+
ok("프로젝트 소스와 설치본 일치");
|
|
1857
|
+
} else {
|
|
1858
|
+
addDoctorCheck(report, { name: "route-sync", status: "issues", fix: "tfx setup" });
|
|
1859
|
+
warn("tfx-route.sh 프로젝트 소스와 설치본 불일치");
|
|
1860
|
+
info(`소스: ${srcRoute} (${srcHash}B) / 설치: ${destRoute} (${destHash}B)`);
|
|
1861
|
+
if (fix) {
|
|
1862
|
+
copyFileSync(srcRoute, destRoute);
|
|
1863
|
+
ok("tfx-route.sh 동기화 완료");
|
|
1864
|
+
} else {
|
|
1865
|
+
issues++;
|
|
1866
|
+
}
|
|
1867
|
+
}
|
|
1868
|
+
} else if (existsSync(srcRoute) && !existsSync(destRoute)) {
|
|
1869
|
+
addDoctorCheck(report, { name: "route-sync", status: "missing", fix: "tfx setup" });
|
|
1870
|
+
fail("설치본 없음");
|
|
1871
|
+
issues++;
|
|
1872
|
+
} else {
|
|
1873
|
+
addDoctorCheck(report, { name: "route-sync", status: "ok" });
|
|
1874
|
+
ok("소스 없음 (npm 패키지 모드)");
|
|
1875
|
+
}
|
|
1876
|
+
}
|
|
1877
|
+
|
|
1769
1878
|
// 결과
|
|
1770
1879
|
console.log(`\n ${LINE}`);
|
|
1771
1880
|
if (issues === 0) {
|
package/hub/team/headless.mjs
CHANGED
|
@@ -243,10 +243,12 @@ function dispatchBatch(sessionName, assignments, opts = {}) {
|
|
|
243
243
|
* @returns {Promise<Array<{d, completion, output}>>}
|
|
244
244
|
*/
|
|
245
245
|
async function awaitAll(sessionName, dispatches, timeoutSec, safeProgress, progressIntervalSec) {
|
|
246
|
+
const ac = new AbortController();
|
|
247
|
+
|
|
246
248
|
// 병렬 대기 (Promise.all — 모든 pane 동시 폴링, 총 시간 = max(개별 시간))
|
|
247
249
|
return Promise.all(dispatches.map(async (d) => {
|
|
248
250
|
// onPoll → onProgress 변환 (throttle by progressIntervalSec)
|
|
249
|
-
const pollOpts = {};
|
|
251
|
+
const pollOpts = { signal: ac.signal };
|
|
250
252
|
if (safeProgress && progressIntervalSec > 0) {
|
|
251
253
|
let lastProgressAt = 0;
|
|
252
254
|
const intervalMs = progressIntervalSec * 1000;
|
|
@@ -268,6 +270,11 @@ async function awaitAll(sessionName, dispatches, timeoutSec, safeProgress, progr
|
|
|
268
270
|
if (d.logPath) pollOpts.logPath = d.logPath;
|
|
269
271
|
const completion = await waitForCompletion(sessionName, d.paneId || d.paneName, d.token, timeoutSec, pollOpts);
|
|
270
272
|
|
|
273
|
+
// 세션 사망 감지 시 나머지 워커 폴링 즉시 중단
|
|
274
|
+
if (completion.sessionDead && !ac.signal.aborted) {
|
|
275
|
+
ac.abort();
|
|
276
|
+
}
|
|
277
|
+
|
|
271
278
|
const output = completion.matched
|
|
272
279
|
? readResult(d.resultFile, d.paneId)
|
|
273
280
|
: "";
|
package/hub/team/psmux.mjs
CHANGED
|
@@ -570,7 +570,7 @@ function killOrphanPipeHelpers(sessionName) {
|
|
|
570
570
|
const safeSession = sanitizePathPart(sessionName);
|
|
571
571
|
try {
|
|
572
572
|
const output = childProcess.execSync(
|
|
573
|
-
`powershell -NoProfile -WindowStyle Hidden -Command "$ErrorActionPreference='SilentlyContinue'; Get-CimInstance Win32_Process | Where-Object { $_.CommandLine -match 'pipe-pane-capture' -and $_.CommandLine -match '${safeSession}' } | Select-Object -ExpandProperty ProcessId"`,
|
|
573
|
+
`powershell -NoProfile -WindowStyle Hidden -Command "$ErrorActionPreference='SilentlyContinue'; Get-CimInstance Win32_Process | Where-Object { $_.CommandLine -match 'pipe-pane-capture' -and $_.CommandLine -match 'tfx-headless[/\\\\]${safeSession}' } | Select-Object -ExpandProperty ProcessId"`,
|
|
574
574
|
{ encoding: "utf8", timeout: 8000, stdio: ["pipe", "pipe", "pipe"], windowsHide: true },
|
|
575
575
|
);
|
|
576
576
|
const pids = output.split(/\r?\n/).map((l) => Number.parseInt(l.trim(), 10)).filter((p) => Number.isFinite(p) && p > 0);
|
|
@@ -605,7 +605,7 @@ function killOrphanMcpProcesses(sessionName) {
|
|
|
605
605
|
try {
|
|
606
606
|
// 세션 결과 디렉토리 패턴으로 MCP 서버 프로세스 식별
|
|
607
607
|
const output = childProcess.execSync(
|
|
608
|
-
`powershell -NoProfile -WindowStyle Hidden -Command "$ErrorActionPreference='SilentlyContinue'; Get-CimInstance Win32_Process | Where-Object { $_.Name -eq 'node.exe' -and $_.CommandLine -match '${safeSession}' } | Select-Object -ExpandProperty ProcessId"`,
|
|
608
|
+
`powershell -NoProfile -WindowStyle Hidden -Command "$ErrorActionPreference='SilentlyContinue'; Get-CimInstance Win32_Process | Where-Object { $_.Name -eq 'node.exe' -and $_.CommandLine -match 'tfx-headless[/\\\\]${safeSession}' } | Select-Object -ExpandProperty ProcessId"`,
|
|
609
609
|
{ encoding: "utf8", timeout: 8000, stdio: ["pipe", "pipe", "pipe"], windowsHide: true },
|
|
610
610
|
);
|
|
611
611
|
const pids = output.split(/\r?\n/).map((l) => Number.parseInt(l.trim(), 10)).filter((p) => Number.isFinite(p) && p > 0 && p !== hubPid);
|
|
@@ -632,6 +632,9 @@ export function killPsmuxSession(sessionName) {
|
|
|
632
632
|
}
|
|
633
633
|
disableAllPipeCaptures(sessionName, paneIds);
|
|
634
634
|
|
|
635
|
+
// pipe-pane reader가 EOF를 처리하고 정상 종료할 시간 확보
|
|
636
|
+
sleepMs(500);
|
|
637
|
+
|
|
635
638
|
// 2. pane 프로세스 트리 강제 종료 (MCP 서버 포함)
|
|
636
639
|
const pids = collectPanePids(sessionName);
|
|
637
640
|
for (const pid of pids) {
|
|
@@ -856,7 +859,8 @@ export function dispatchCommand(sessionName, paneNameOrTarget, commandText) {
|
|
|
856
859
|
* @param {number} timeoutSec
|
|
857
860
|
* @param {object} [opts]
|
|
858
861
|
* @param {(snapshot: {content: string, paneId: string, paneName: string, elapsed: number}) => void} [opts.onPoll] — 각 폴링 주기마다 호출
|
|
859
|
-
* @
|
|
862
|
+
* @param {AbortSignal} [opts.signal] — 외부에서 폴링 중단 요청 시 사용
|
|
863
|
+
* @returns {{ matched: boolean, paneId: string, paneName: string, logPath: string, match: string|null, aborted?: boolean }}
|
|
860
864
|
*/
|
|
861
865
|
export async function waitForPattern(sessionName, paneNameOrTarget, pattern, timeoutSec = 300, opts = {}) {
|
|
862
866
|
ensurePsmuxInstalled();
|
|
@@ -892,7 +896,14 @@ export async function waitForPattern(sessionName, paneNameOrTarget, pattern, tim
|
|
|
892
896
|
const deadline = startTime + Math.max(0, Math.trunc(timeoutSec * 1000));
|
|
893
897
|
const regex = toPatternRegExp(pattern);
|
|
894
898
|
|
|
899
|
+
if (opts?.signal?.aborted) {
|
|
900
|
+
return { matched: false, paneId: pane.paneId, paneName, logPath, match: null, aborted: true };
|
|
901
|
+
}
|
|
902
|
+
|
|
895
903
|
while (Date.now() <= deadline) {
|
|
904
|
+
if (opts?.signal?.aborted) {
|
|
905
|
+
return { matched: false, paneId: pane.paneId, paneName, logPath, match: null, aborted: true };
|
|
906
|
+
}
|
|
896
907
|
// E4 크래시 복구: capture 실패 시 세션 생존 체크
|
|
897
908
|
try {
|
|
898
909
|
if (opts.logPath) {
|
|
@@ -940,6 +951,9 @@ export async function waitForPattern(sessionName, paneNameOrTarget, pattern, tim
|
|
|
940
951
|
break;
|
|
941
952
|
}
|
|
942
953
|
await sleepMsAsync(POLL_INTERVAL_MS);
|
|
954
|
+
if (opts?.signal?.aborted) {
|
|
955
|
+
return { matched: false, paneId: pane.paneId, paneName, logPath, match: null, aborted: true };
|
|
956
|
+
}
|
|
943
957
|
}
|
|
944
958
|
|
|
945
959
|
return {
|
|
@@ -1112,7 +1126,13 @@ export function killWorker(sessionName, workerName) {
|
|
|
1112
1126
|
// send-keys 실패 무시
|
|
1113
1127
|
}
|
|
1114
1128
|
|
|
1115
|
-
|
|
1129
|
+
try {
|
|
1130
|
+
psmuxExec(["send-keys", "-t", paneId, "exit", "Enter"]);
|
|
1131
|
+
} catch {
|
|
1132
|
+
// send-keys 실패 무시
|
|
1133
|
+
}
|
|
1134
|
+
|
|
1135
|
+
sleepMs(2000);
|
|
1116
1136
|
|
|
1117
1137
|
try {
|
|
1118
1138
|
psmuxExec(["kill-pane", "-t", paneId]);
|
package/package.json
CHANGED
|
@@ -193,7 +193,7 @@ async function main() {
|
|
|
193
193
|
}
|
|
194
194
|
|
|
195
195
|
// codex/gemini 직접 CLI 호출 → deny
|
|
196
|
-
if (/\bcodex\
|
|
196
|
+
if (/\bcodex\b.*\bexec\b/.test(cmd) || /\bgemini\s+(-p|--prompt)\b/.test(cmd)) {
|
|
197
197
|
deny(
|
|
198
198
|
"[headless-guard] codex/gemini 직접 호출은 spawn-session에서 차단됩니다. " +
|
|
199
199
|
`승인된 경로: ${HEADLESS_FALLBACK_COMMAND}. ` +
|
package/scripts/setup.mjs
CHANGED
|
@@ -569,6 +569,19 @@ if (existsSync(skillsSrc)) {
|
|
|
569
569
|
}
|
|
570
570
|
}
|
|
571
571
|
|
|
572
|
+
// ── docs 동기화 ──
|
|
573
|
+
const docsDirs = ['docs/design', 'docs/research'];
|
|
574
|
+
for (const dir of docsDirs) {
|
|
575
|
+
const src = join(PLUGIN_ROOT, dir);
|
|
576
|
+
const dest = join(CLAUDE_DIR, dir);
|
|
577
|
+
if (existsSync(src)) {
|
|
578
|
+
mkdirSync(dest, { recursive: true });
|
|
579
|
+
for (const f of readdirSync(src).filter(f => f.endsWith('.md'))) {
|
|
580
|
+
copyFileSync(join(src, f), join(dest, f));
|
|
581
|
+
}
|
|
582
|
+
}
|
|
583
|
+
}
|
|
584
|
+
|
|
572
585
|
// ── settings.json 통합 R/W ──
|
|
573
586
|
// 3개 섹션(statusLine, agentTeams, hooks)을 1회 read → 일괄 수정 → 1회 write
|
|
574
587
|
|
package/scripts/tfx-route.sh
CHANGED
|
@@ -76,9 +76,13 @@ if [[ "${1:-}" == "--job-status" ]]; then
|
|
|
76
76
|
fi
|
|
77
77
|
elif [[ -f "$job_dir/pid" ]]; then
|
|
78
78
|
pid=$(cat "$job_dir/pid")
|
|
79
|
+
if [[ "$pid" == "starting" ]]; then
|
|
80
|
+
echo "starting"
|
|
81
|
+
exit 0
|
|
82
|
+
fi
|
|
79
83
|
if kill -0 "$pid" 2>/dev/null; then
|
|
80
84
|
# 진행 상황 힌트
|
|
81
|
-
local_bytes=$(wc -c < "$job_dir/
|
|
85
|
+
local_bytes=$(wc -c < "$job_dir/result.log" 2>/dev/null | tr -d ' ' || echo 0)
|
|
82
86
|
elapsed=$(( $(date +%s) - $(cat "$job_dir/start_time" 2>/dev/null || date +%s) ))
|
|
83
87
|
echo "running elapsed=${elapsed}s output=${local_bytes}B"
|
|
84
88
|
else
|
|
@@ -98,7 +102,12 @@ if [[ "${1:-}" == "--job-result" ]]; then
|
|
|
98
102
|
[[ -d "$job_dir" ]] || { echo "error: job not found"; exit 1; }
|
|
99
103
|
[[ -f "$job_dir/done" ]] || { echo "error: job still running"; exit 1; }
|
|
100
104
|
|
|
101
|
-
|
|
105
|
+
result_bytes=$(wc -c < "$job_dir/result.log" 2>/dev/null | tr -d ' ' || echo 0)
|
|
106
|
+
if [[ "$result_bytes" -eq 0 ]] && [[ -s "$job_dir/stderr.log" ]]; then
|
|
107
|
+
cat "$job_dir/stderr.log" 2>/dev/null
|
|
108
|
+
else
|
|
109
|
+
cat "$job_dir/result.log" 2>/dev/null
|
|
110
|
+
fi
|
|
102
111
|
exit_code=$(cat "$job_dir/exit_code" 2>/dev/null || echo 1)
|
|
103
112
|
exit "$exit_code"
|
|
104
113
|
fi
|
|
@@ -1362,6 +1371,8 @@ gemini_with_retry() {
|
|
|
1362
1371
|
attempt=$(( attempt + 1 ))
|
|
1363
1372
|
if (( attempt < max_retries )); then
|
|
1364
1373
|
echo "[tfx-route] Gemini 429 감지. ${delay}초 후 재시도 ($attempt/$max_retries)..." >&2
|
|
1374
|
+
kill "$pid" 2>/dev/null
|
|
1375
|
+
wait "$pid" 2>/dev/null
|
|
1365
1376
|
sleep "$delay"
|
|
1366
1377
|
delay=$(( delay * 2 ))
|
|
1367
1378
|
: > "$STDOUT_LOG"
|
|
@@ -1476,7 +1487,7 @@ run_codex_exec() {
|
|
|
1476
1487
|
fi
|
|
1477
1488
|
|
|
1478
1489
|
if [[ -s "$STDOUT_LOG" ]]; then
|
|
1479
|
-
echo "[tfx-route] 경고: codex stdout 비어있음, stderr에서 응답 복구 ($(wc -c < "$STDOUT_LOG") bytes)" >&2
|
|
1490
|
+
echo "[tfx-route] 경고: codex stdout 비어있음, stderr에서 응답 복구 ($(wc -c < "$STDOUT_LOG" | tr -d ' ') bytes)" >&2
|
|
1480
1491
|
else
|
|
1481
1492
|
echo "[tfx-route] 경고: codex stdout 비어있음, stderr 복구도 실패" >&2
|
|
1482
1493
|
fi
|
|
@@ -1875,11 +1886,12 @@ if [[ "$TFX_ASYNC_MODE" -eq 1 ]]; then
|
|
|
1875
1886
|
date +%s > "$JOB_DIR/start_time"
|
|
1876
1887
|
|
|
1877
1888
|
# 백그라운드 서브쉘: main 실행 → 결과 저장
|
|
1889
|
+
echo "starting" > "$JOB_DIR/pid"
|
|
1878
1890
|
(
|
|
1879
1891
|
set +e # main 내부 에러가 exit_code 기록 전에 서브쉘을 죽이는 것 방지
|
|
1880
1892
|
exec > "$JOB_DIR/result.log" 2>"$JOB_DIR/stderr.log"
|
|
1881
|
-
main
|
|
1882
|
-
echo
|
|
1893
|
+
main; _ec=$?
|
|
1894
|
+
echo "$_ec" > "$JOB_DIR/exit_code"
|
|
1883
1895
|
touch "$JOB_DIR/done"
|
|
1884
1896
|
) &
|
|
1885
1897
|
bg_pid=$!
|
|
@@ -11,6 +11,10 @@ argument-hint: "<분석 대상 — 파일, 디렉토리, 또는 주제>"
|
|
|
11
11
|
|
|
12
12
|
# tfx-analysis — Light Code Analysis
|
|
13
13
|
|
|
14
|
+
> **ARGUMENTS 처리**: 이 스킬이 `ARGUMENTS: <값>`과 함께 호출되면, 해당 값을 사용자 입력으로 취급하여
|
|
15
|
+
> 워크플로우의 첫 단계 입력으로 사용한다. ARGUMENTS가 비어있거나 없으면 기존 절차대로 사용자에게 입력을 요청한다.
|
|
16
|
+
|
|
17
|
+
|
|
14
18
|
> **Deep 버전**: tfx-deep-analysis. "제대로/꼼꼼히" 수정자로 자동 에스컬레이션.
|
|
15
19
|
> Codex 단일 분석으로 빠른 인사이트. SuperClaude sc:analyze 영감.
|
|
16
20
|
|
package/skills/tfx-auto/SKILL.md
CHANGED
|
@@ -29,6 +29,10 @@ argument-hint: "<command|task> [args...]"
|
|
|
29
29
|
|
|
30
30
|
# tfx-auto — 통합 CLI 오케스트레이터
|
|
31
31
|
|
|
32
|
+
> **ARGUMENTS 처리**: 이 스킬이 `ARGUMENTS: <값>`과 함께 호출되면, 해당 값을 사용자 입력으로 취급하여
|
|
33
|
+
> 워크플로우의 첫 단계 입력으로 사용한다. ARGUMENTS가 비어있거나 없으면 기존 절차대로 사용자에게 입력을 요청한다.
|
|
34
|
+
|
|
35
|
+
|
|
32
36
|
> **MANDATORY RULES**
|
|
33
37
|
>
|
|
34
38
|
> 1. **실행**: CLI 에이전트는 반드시 `Bash("bash ~/.claude/scripts/tfx-route.sh ...")`. Claude 네이티브(explore/verifier/test-engineer/qa-tester)만 `Agent()`.
|
|
@@ -10,6 +10,10 @@ argument-hint: "\"작업 설명\" | N:agent_type \"작업 설명\""
|
|
|
10
10
|
|
|
11
11
|
# tfx-auto-codex — Codex 리드형 tfx-auto
|
|
12
12
|
|
|
13
|
+
> **ARGUMENTS 처리**: 이 스킬이 `ARGUMENTS: <값>`과 함께 호출되면, 해당 값을 사용자 입력으로 취급하여
|
|
14
|
+
> 워크플로우의 첫 단계 입력으로 사용한다. ARGUMENTS가 비어있거나 없으면 기존 절차대로 사용자에게 입력을 요청한다.
|
|
15
|
+
|
|
16
|
+
|
|
13
17
|
> **래퍼**: tfx-auto의 Codex 전용 바로가기. TFX_NO_CLAUDE_NATIVE=1.
|
|
14
18
|
> 목적: 기존 `tfx-auto`의 오케스트레이션 패턴을 유지하면서
|
|
15
19
|
> Claude 네이티브 역할(`explore`, `verifier`, `test-engineer`, `qa-tester`)을
|
|
@@ -10,6 +10,10 @@ argument-hint: "<구현할 작업 설명>"
|
|
|
10
10
|
|
|
11
11
|
# tfx-autopilot — Light Autonomous Execution
|
|
12
12
|
|
|
13
|
+
> **ARGUMENTS 처리**: 이 스킬이 `ARGUMENTS: <값>`과 함께 호출되면, 해당 값을 사용자 입력으로 취급하여
|
|
14
|
+
> 워크플로우의 첫 단계 입력으로 사용한다. ARGUMENTS가 비어있거나 없으면 기존 절차대로 사용자에게 입력을 요청한다.
|
|
15
|
+
|
|
16
|
+
|
|
13
17
|
> Codex 직접 구현 → Claude 검증. 최소 토큰으로 빠른 자율 실행.
|
|
14
18
|
|
|
15
19
|
## 용도
|
|
@@ -19,6 +19,10 @@ source: GAP 분석 P2 #8
|
|
|
19
19
|
|
|
20
20
|
# tfx-autoresearch — 자율 웹 리서치
|
|
21
21
|
|
|
22
|
+
> **ARGUMENTS 처리**: 이 스킬이 `ARGUMENTS: <값>`과 함께 호출되면, 해당 값을 사용자 입력으로 취급하여
|
|
23
|
+
> 워크플로우의 첫 단계 입력으로 사용한다. ARGUMENTS가 비어있거나 없으면 기존 절차대로 사용자에게 입력을 요청한다.
|
|
24
|
+
|
|
25
|
+
|
|
22
26
|
> 주제를 받아 자동으로 웹을 검색하고, 결과를 분석하여 구조화된 리서치 보고서를 생성합니다.
|
|
23
27
|
> "조사는 AI가, 판단은 사람이."
|
|
24
28
|
|
|
@@ -12,6 +12,10 @@ argument-hint: "<작업 설명>"
|
|
|
12
12
|
|
|
13
13
|
# tfx-autoroute — Auto-Routing Autonomous Executor
|
|
14
14
|
|
|
15
|
+
> **ARGUMENTS 처리**: 이 스킬이 `ARGUMENTS: <값>`과 함께 호출되면, 해당 값을 사용자 입력으로 취급하여
|
|
16
|
+
> 워크플로우의 첫 단계 입력으로 사용한다. ARGUMENTS가 비어있거나 없으면 기존 절차대로 사용자에게 입력을 요청한다.
|
|
17
|
+
|
|
18
|
+
|
|
15
19
|
> oh-my-openagent Sisyphus agent 오마주. 바위는 멈추지 않는다 — 그리고 올바른 산을 고른다.
|
|
16
20
|
> "실패하면 더 강한 모델로. 성공할 때까지."
|
|
17
21
|
|
|
@@ -10,6 +10,10 @@ argument-hint: "\"작업 설명\" | N:codex \"작업 설명\""
|
|
|
10
10
|
|
|
11
11
|
# tfx-codex — Codex-Only 오케스트레이터
|
|
12
12
|
|
|
13
|
+
> **ARGUMENTS 처리**: 이 스킬이 `ARGUMENTS: <값>`과 함께 호출되면, 해당 값을 사용자 입력으로 취급하여
|
|
14
|
+
> 워크플로우의 첫 단계 입력으로 사용한다. ARGUMENTS가 비어있거나 없으면 기존 절차대로 사용자에게 입력을 요청한다.
|
|
15
|
+
|
|
16
|
+
|
|
13
17
|
> **래퍼**: tfx-auto의 Codex 전용 바로가기. TFX_CLI_MODE=codex.
|
|
14
18
|
> **HARD RULE**: Claude는 이 스킬에서 Edit/Write를 사용하면 안 된다. 모든 코드 수정은 Codex CLI를 통해 수행한다.
|
|
15
19
|
> Codex CLI만 사용하여 모든 외부 CLI 작업을 라우팅합니다.
|
|
@@ -5,6 +5,10 @@ description: OMX 스킬을 활용하는 Codex 다중 세션 스폰 오케스트
|
|
|
5
5
|
|
|
6
6
|
# tfx-codex-swarm — Codex 다중 세션 스폰 오케스트레이터
|
|
7
7
|
|
|
8
|
+
> **ARGUMENTS 처리**: 이 스킬이 `ARGUMENTS: <값>`과 함께 호출되면, 해당 값을 사용자 입력으로 취급하여
|
|
9
|
+
> 워크플로우의 첫 단계 입력으로 사용한다. ARGUMENTS가 비어있거나 없으면 기존 절차대로 사용자에게 입력을 요청한다.
|
|
10
|
+
|
|
11
|
+
|
|
8
12
|
> PRD/태스크 파일 N개를 각각 독립 worktree + psmux 세션으로 Codex full-auto 실행.
|
|
9
13
|
> AskUserQuestion 기반 인터랙티브 설정. 미지정 시 하네스가 자동 판단.
|
|
10
14
|
|
|
@@ -300,9 +304,9 @@ cp {PRD_PATH} .codex-swarm/wt-issue-{N}/{PRD_PATH}
|
|
|
300
304
|
> bash 문법을 `send-keys`로 직접 전달하면 경로 오류 + 인자 파싱 실패가 발생한다.
|
|
301
305
|
> **반드시 `.sh` 런처 파일을 생성하고, PowerShell 구문으로 bash.exe 전체 경로를 호출해야 한다.**
|
|
302
306
|
|
|
303
|
-
**실행 방식
|
|
307
|
+
**실행 방식 3가지 (택 1):**
|
|
304
308
|
|
|
305
|
-
**A) .sh 런처 + send-keys
|
|
309
|
+
**A) .sh 런처 + send-keys**
|
|
306
310
|
```bash
|
|
307
311
|
psmux new-session -s "codex-swarm-{id}" -d
|
|
308
312
|
|
|
@@ -339,6 +343,33 @@ Get-Content 'C:\path\.codex-swarm\prompts\prompt-{id}.md' -Raw | codex
|
|
|
339
343
|
# Get-Content 'prompt.md' -Raw | codex -c 'model="gpt-5.3-codex"' -c 'model_reasoning_effort="high"'
|
|
340
344
|
```
|
|
341
345
|
|
|
346
|
+
**C) tfx-route.sh 경유 (권장)**
|
|
347
|
+
```bash
|
|
348
|
+
psmux new-session -s "codex-swarm-{id}" -d
|
|
349
|
+
|
|
350
|
+
BASH_WIN='C:\\Program Files\\Git\\bin\\bash.exe'
|
|
351
|
+
LAUNCH_DIR='C:\\path\\to\\.codex-swarm'
|
|
352
|
+
psmux send-keys -t "codex-swarm-{id}" \
|
|
353
|
+
"& '$BASH_WIN' '$LAUNCH_DIR\\launch-{id}.sh'" Enter
|
|
354
|
+
```
|
|
355
|
+
|
|
356
|
+
launch-{id}.sh:
|
|
357
|
+
```bash
|
|
358
|
+
#!/bin/bash
|
|
359
|
+
cd /c/path/.codex-swarm/wt-issue-{N} || exit 1
|
|
360
|
+
|
|
361
|
+
# tfx-route.sh가 MCP 프로필, 타임아웃, 에이전트 역할을 자동 관리
|
|
362
|
+
# 프롬프트는 인자로 전달 (stdin 불필요 → TTY 문제 없음)
|
|
363
|
+
~/.claude/scripts/tfx-route.sh executor \
|
|
364
|
+
"$(cat /c/path/.codex-swarm/prompts/prompt-{id}.md)" \
|
|
365
|
+
"{profile}" 900
|
|
366
|
+
```
|
|
367
|
+
|
|
368
|
+
장점:
|
|
369
|
+
- TTY 문제 없음 — stdin 파이프 미사용
|
|
370
|
+
- MCP 프로필 자동 관리 (tfx-route.sh가 처리)
|
|
371
|
+
- 타임아웃 통합 (마지막 인자 = 초 단위)
|
|
372
|
+
|
|
342
373
|
> **금지 패턴** (절대 사용하지 말 것):
|
|
343
374
|
> ```bash
|
|
344
375
|
> # WRONG — bash 문법을 PowerShell 세션에 직접 전달
|
|
@@ -9,6 +9,10 @@ argument-hint: "<분석 주제 또는 컨텍스트> (Deep 스킬 내부 자동
|
|
|
9
9
|
|
|
10
10
|
# tfx-consensus — Tri-CLI Consensus Engine
|
|
11
11
|
|
|
12
|
+
> **ARGUMENTS 처리**: 이 스킬이 `ARGUMENTS: <값>`과 함께 호출되면, 해당 값을 사용자 입력으로 취급하여
|
|
13
|
+
> 워크플로우의 첫 단계 입력으로 사용한다. ARGUMENTS가 비어있거나 없으면 기존 절차대로 사용자에게 입력을 요청한다.
|
|
14
|
+
|
|
15
|
+
|
|
12
16
|
> **인프라**: 다른 스킬이 내부적으로 사용. 직접 호출할 필요 없음.
|
|
13
17
|
> 모든 Deep 스킬의 공통 기반. 3개 CLI의 독립 결과를 교차검증하여 합의 도출.
|
|
14
18
|
|
|
@@ -12,6 +12,10 @@ argument-hint: "<토론 주제 또는 질문>"
|
|
|
12
12
|
|
|
13
13
|
# tfx-debate — Tri-CLI Structured Debate
|
|
14
14
|
|
|
15
|
+
> **ARGUMENTS 처리**: 이 스킬이 `ARGUMENTS: <값>`과 함께 호출되면, 해당 값을 사용자 입력으로 취급하여
|
|
16
|
+
> 워크플로우의 첫 단계 입력으로 사용한다. ARGUMENTS가 비어있거나 없으면 기존 절차대로 사용자에게 입력을 요청한다.
|
|
17
|
+
|
|
18
|
+
|
|
15
19
|
> 3개 CLI가 독립 분석 → 교차검증 → 합의 도출. Anti-herding으로 편향 없는 결론.
|
|
16
20
|
|
|
17
21
|
## 용도
|
|
@@ -10,6 +10,10 @@ argument-hint: "<분석 대상 — 파일, 디렉토리, 또는 주제>"
|
|
|
10
10
|
|
|
11
11
|
# tfx-deep-analysis — Tri-CLI Deep Analysis
|
|
12
12
|
|
|
13
|
+
> **ARGUMENTS 처리**: 이 스킬이 `ARGUMENTS: <값>`과 함께 호출되면, 해당 값을 사용자 입력으로 취급하여
|
|
14
|
+
> 워크플로우의 첫 단계 입력으로 사용한다. ARGUMENTS가 비어있거나 없으면 기존 절차대로 사용자에게 입력을 요청한다.
|
|
15
|
+
|
|
16
|
+
|
|
13
17
|
> **Light 버전**: tfx-analysis. 기본값. 깊이 수정자 없으면 Light 선택.
|
|
14
18
|
> Claude(아키텍처) + Codex(구현/보안) + Gemini(UX/문서화) → Tri-Debate → 합의.
|
|
15
19
|
> 3자 전문 관점의 편향 없는 분석.
|
|
@@ -14,6 +14,10 @@ argument-hint: "<topic>"
|
|
|
14
14
|
|
|
15
15
|
# tfx-deep-interview — 소크라테스식 깊이 탐색
|
|
16
16
|
|
|
17
|
+
> **ARGUMENTS 처리**: 이 스킬이 `ARGUMENTS: <값>`과 함께 호출되면, 해당 값을 사용자 입력으로 취급하여
|
|
18
|
+
> 워크플로우의 첫 단계 입력으로 사용한다. ARGUMENTS가 비어있거나 없으면 기존 절차대로 사용자에게 입력을 요청한다.
|
|
19
|
+
|
|
20
|
+
|
|
17
21
|
> 구현 전에 질문을 통해 요구사항의 깊이를 탐색합니다.
|
|
18
22
|
> "좋은 답은 좋은 질문에서 나온다."
|
|
19
23
|
|
|
@@ -13,6 +13,10 @@ argument-hint: "<구현할 기능 설명>"
|
|
|
13
13
|
|
|
14
14
|
# tfx-deep-plan — Tri-Model Consensus Planning
|
|
15
15
|
|
|
16
|
+
> **ARGUMENTS 처리**: 이 스킬이 `ARGUMENTS: <값>`과 함께 호출되면, 해당 값을 사용자 입력으로 취급하여
|
|
17
|
+
> 워크플로우의 첫 단계 입력으로 사용한다. ARGUMENTS가 비어있거나 없으면 기존 절차대로 사용자에게 입력을 요청한다.
|
|
18
|
+
|
|
19
|
+
|
|
16
20
|
> **Light 버전**: tfx-plan. 기본값. 깊이 수정자 없으면 Light 선택.
|
|
17
21
|
3개 모델(Opus 4.6 · GPT 5.4 · Gemini)이 독립 설계 후 교차검증하여 합의된 계획을 도출한다.
|
|
18
22
|
|
|
@@ -11,6 +11,10 @@ argument-hint: "[테스트 대상 경로 또는 기능 설명]"
|
|
|
11
11
|
|
|
12
12
|
# tfx-deep-qa — Tri-CLI Deep Verification
|
|
13
13
|
|
|
14
|
+
> **ARGUMENTS 처리**: 이 스킬이 `ARGUMENTS: <값>`과 함께 호출되면, 해당 값을 사용자 입력으로 취급하여
|
|
15
|
+
> 워크플로우의 첫 단계 입력으로 사용한다. ARGUMENTS가 비어있거나 없으면 기존 절차대로 사용자에게 입력을 요청한다.
|
|
16
|
+
|
|
17
|
+
|
|
14
18
|
> **Light 버전**: tfx-qa. 기본값. 깊이 수정자 없으면 Light 선택.
|
|
15
19
|
> 3-CLI 독립 검증 → 교차검증 → 2+ 합의 항목만 보고. false-positive 87% 감소.
|
|
16
20
|
|
|
@@ -14,6 +14,10 @@ argument-hint: "[--depth quick|standard|deep] <리서치 주제>"
|
|
|
14
14
|
|
|
15
15
|
# tfx-deep-research — Multi-Source Deep Research with Tri-CLI Consensus
|
|
16
16
|
|
|
17
|
+
> **ARGUMENTS 처리**: 이 스킬이 `ARGUMENTS: <값>`과 함께 호출되면, 해당 값을 사용자 입력으로 취급하여
|
|
18
|
+
> 워크플로우의 첫 단계 입력으로 사용한다. ARGUMENTS가 비어있거나 없으면 기존 절차대로 사용자에게 입력을 요청한다.
|
|
19
|
+
|
|
20
|
+
|
|
17
21
|
> **Light 버전**: tfx-research. 기본값. 깊이 수정자 없으면 Light 선택.
|
|
18
22
|
> 쿼리 분해 → 3-CLI 독립 병렬 검색 → 교차검증 → 합의 기반 종합 보고서.
|
|
19
23
|
> STORM(Stanford) perspective-guided + GPT-Researcher recursive tree + Tavily deep research pipeline 영감.
|
|
@@ -12,6 +12,10 @@ argument-hint: "[파일 경로 또는 변경 설명]"
|
|
|
12
12
|
|
|
13
13
|
# tfx-deep-review — Tri-CLI Deep Code Review
|
|
14
14
|
|
|
15
|
+
> **ARGUMENTS 처리**: 이 스킬이 `ARGUMENTS: <값>`과 함께 호출되면, 해당 값을 사용자 입력으로 취급하여
|
|
16
|
+
> 워크플로우의 첫 단계 입력으로 사용한다. ARGUMENTS가 비어있거나 없으면 기존 절차대로 사용자에게 입력을 요청한다.
|
|
17
|
+
|
|
18
|
+
|
|
15
19
|
> **Light 버전**: tfx-review. 기본값. 깊이 수정자 없으면 Light 선택.
|
|
16
20
|
> 3-CLI 독립 리뷰 → 교차검증 → 2+ 합의 항목만 보고. Diffray + Calimero 영감.
|
|
17
21
|
|
|
@@ -152,6 +152,9 @@ options:
|
|
|
152
152
|
- MCP 인벤토리 캐시
|
|
153
153
|
- Phase 1 웜업 캐시 무결성 (`node scripts/cache-doctor.mjs`)
|
|
154
154
|
- 잔존 팀(orphan teams) 감지
|
|
155
|
+
- **Docs 동기화** — `docs/design/`, `docs/research/` → `~/.claude/docs/` 레퍼런스 문서 동기화 상태
|
|
156
|
+
- **Gemini MCP 안전성** — `~/.gemini/settings.json`의 stdio MCP 감지 (spawn EPERM 방지)
|
|
157
|
+
- **Route Script 정합성** — 프로젝트 소스 `scripts/tfx-route.sh`와 `~/.claude/scripts/tfx-route.sh` 일치 여부
|
|
155
158
|
|
|
156
159
|
## 에러 처리
|
|
157
160
|
|
package/skills/tfx-find/SKILL.md
CHANGED
|
@@ -12,6 +12,10 @@ argument-hint: "<검색 패턴 또는 질문>"
|
|
|
12
12
|
|
|
13
13
|
# tfx-find — Fast Codebase Explorer
|
|
14
14
|
|
|
15
|
+
> **ARGUMENTS 처리**: 이 스킬이 `ARGUMENTS: <값>`과 함께 호출되면, 해당 값을 사용자 입력으로 취급하여
|
|
16
|
+
> 워크플로우의 첫 단계 입력으로 사용한다. ARGUMENTS가 비어있거나 없으면 기존 절차대로 사용자에게 입력을 요청한다.
|
|
17
|
+
|
|
18
|
+
|
|
15
19
|
> OMC explore agent 오마주. Haiku의 속도 + Glob/Grep/Read의 정밀도.
|
|
16
20
|
> "찾는 건 빠르게, 읽는 건 정확하게."
|
|
17
21
|
|
|
@@ -12,6 +12,10 @@ argument-hint: "[스킬 이름 또는 설명]"
|
|
|
12
12
|
|
|
13
13
|
# tfx-forge — Skill Authoring Meta-Skill
|
|
14
14
|
|
|
15
|
+
> **ARGUMENTS 처리**: 이 스킬이 `ARGUMENTS: <값>`과 함께 호출되면, 해당 값을 사용자 입력으로 취급하여
|
|
16
|
+
> 워크플로우의 첫 단계 입력으로 사용한다. ARGUMENTS가 비어있거나 없으면 기존 절차대로 사용자에게 입력을 요청한다.
|
|
17
|
+
|
|
18
|
+
|
|
15
19
|
> Superpowers skill authoring 오마주. 스킬을 만드는 스킬.
|
|
16
20
|
> "메타 레벨에서 자동화하라."
|
|
17
21
|
|
|
@@ -11,6 +11,10 @@ argument-hint: "<구현할 기능 전체 설명>"
|
|
|
11
11
|
|
|
12
12
|
# tfx-fullcycle — Full Development Pipeline with Tri-CLI Consensus
|
|
13
13
|
|
|
14
|
+
> **ARGUMENTS 처리**: 이 스킬이 `ARGUMENTS: <값>`과 함께 호출되면, 해당 값을 사용자 입력으로 취급하여
|
|
15
|
+
> 워크플로우의 첫 단계 입력으로 사용한다. ARGUMENTS가 비어있거나 없으면 기존 절차대로 사용자에게 입력을 요청한다.
|
|
16
|
+
|
|
17
|
+
|
|
14
18
|
> 5-Phase 파이프라인: Expansion → Planning → Execution → QA → Validation.
|
|
15
19
|
> OMC autopilot + Superpowers TDD + MetaGPT SOP 영감. 처음부터 끝까지 자율 실행.
|
|
16
20
|
|
|
@@ -10,6 +10,10 @@ argument-hint: "\"작업 설명\" | N:gemini \"작업 설명\""
|
|
|
10
10
|
|
|
11
11
|
# tfx-gemini — Gemini-Only 오케스트레이터
|
|
12
12
|
|
|
13
|
+
> **ARGUMENTS 처리**: 이 스킬이 `ARGUMENTS: <값>`과 함께 호출되면, 해당 값을 사용자 입력으로 취급하여
|
|
14
|
+
> 워크플로우의 첫 단계 입력으로 사용한다. ARGUMENTS가 비어있거나 없으면 기존 절차대로 사용자에게 입력을 요청한다.
|
|
15
|
+
|
|
16
|
+
|
|
13
17
|
> **래퍼**: tfx-auto의 Gemini 전용 바로가기. TFX_CLI_MODE=gemini.
|
|
14
18
|
> Gemini CLI만 사용하여 모든 외부 CLI 작업을 라우팅합니다.
|
|
15
19
|
> Codex CLI가 없는 환경에서 사용합니다.
|
package/skills/tfx-hub/SKILL.md
CHANGED
|
@@ -11,6 +11,10 @@ argument-hint: "<start|stop|status|자유형 작업 설명>"
|
|
|
11
11
|
|
|
12
12
|
# tfx-hub — MCP 메시지 버스 관리 + 개방형 작업
|
|
13
13
|
|
|
14
|
+
> **ARGUMENTS 처리**: 이 스킬이 `ARGUMENTS: <값>`과 함께 호출되면, 해당 값을 사용자 입력으로 취급하여
|
|
15
|
+
> 워크플로우의 첫 단계 입력으로 사용한다. ARGUMENTS가 비어있거나 없으면 기존 절차대로 사용자에게 입력을 요청한다.
|
|
16
|
+
|
|
17
|
+
|
|
14
18
|
> **인프라**: 다른 스킬이 내부적으로 사용. 직접 호출할 필요 없음.
|
|
15
19
|
> CLI 에이전트(Codex/Gemini/Claude) 간 실시간 메시지 허브를 관리합니다.
|
|
16
20
|
> **커맨드 매칭 + fallthrough**: start/stop/status에 매칭되면 즉시 실행,
|
|
@@ -11,6 +11,10 @@ argument-hint: "[--update] [경로]"
|
|
|
11
11
|
|
|
12
12
|
# tfx-index — Project Indexing (94% Token Reduction)
|
|
13
13
|
|
|
14
|
+
> **ARGUMENTS 처리**: 이 스킬이 `ARGUMENTS: <값>`과 함께 호출되면, 해당 값을 사용자 입력으로 취급하여
|
|
15
|
+
> 워크플로우의 첫 단계 입력으로 사용한다. ARGUMENTS가 비어있거나 없으면 기존 절차대로 사용자에게 입력을 요청한다.
|
|
16
|
+
|
|
17
|
+
|
|
14
18
|
> SuperClaude index-repo 오마주. 1회 2K 토큰으로 인덱스 생성, 이후 세션마다 55K 토큰 절감.
|
|
15
19
|
|
|
16
20
|
> **Gemini 위임**: 스캔 + 인덱스 생성 작업은 Gemini CLI에 위임한다. Claude는 모드 선택(Step 0)과 파일 쓰기만 담당. Claude 토큰 소비 ~500 tokens으로 줄어든다.
|
|
@@ -12,6 +12,10 @@ argument-hint: "<구현할 주제 또는 요구사항>"
|
|
|
12
12
|
|
|
13
13
|
# tfx-interview — Quantified Socratic Requirements Exploration
|
|
14
14
|
|
|
15
|
+
> **ARGUMENTS 처리**: 이 스킬이 `ARGUMENTS: <값>`과 함께 호출되면, 해당 값을 사용자 입력으로 취급하여
|
|
16
|
+
> 워크플로우의 첫 단계 입력으로 사용한다. ARGUMENTS가 비어있거나 없으면 기존 절차대로 사용자에게 입력을 요청한다.
|
|
17
|
+
|
|
18
|
+
|
|
15
19
|
> OMC deep-interview + ouroboros 오마주. 모호성을 숫자로 측정하고 20% 미만까지 질문한다.
|
|
16
20
|
> "측정할 수 없으면 개선할 수 없다."
|
|
17
21
|
>
|
|
@@ -11,6 +11,10 @@ argument-hint: '"작업 설명" | --agents codex,gemini "작업" | --tmux "작
|
|
|
11
11
|
|
|
12
12
|
# tfx-multi v3 — 파이프라인 기반 멀티-CLI 팀 오케스트레이터
|
|
13
13
|
|
|
14
|
+
> **ARGUMENTS 처리**: 이 스킬이 `ARGUMENTS: <값>`과 함께 호출되면, 해당 값을 사용자 입력으로 취급하여
|
|
15
|
+
> 워크플로우의 첫 단계 입력으로 사용한다. ARGUMENTS가 비어있거나 없으면 기존 절차대로 사용자에게 입력을 요청한다.
|
|
16
|
+
|
|
17
|
+
|
|
14
18
|
> **인프라**: 다른 스킬이 내부적으로 사용. 직접 호출할 필요 없음.
|
|
15
19
|
> Claude Code Native Teams의 Shift+Down 네비게이션을 복원한다.
|
|
16
20
|
> Codex/Gemini 워커마다 최소 프롬프트(~100 토큰)의 슬림 Agent 래퍼를 spawn하여 네비게이션에 등록하고,
|
|
@@ -12,6 +12,10 @@ argument-hint: "<토론 주제>"
|
|
|
12
12
|
|
|
13
13
|
# tfx-panel — Virtual Expert Panel Simulation
|
|
14
14
|
|
|
15
|
+
> **ARGUMENTS 처리**: 이 스킬이 `ARGUMENTS: <값>`과 함께 호출되면, 해당 값을 사용자 입력으로 취급하여
|
|
16
|
+
> 워크플로우의 첫 단계 입력으로 사용한다. ARGUMENTS가 비어있거나 없으면 기존 절차대로 사용자에게 입력을 요청한다.
|
|
17
|
+
|
|
18
|
+
|
|
15
19
|
> SuperClaude spec-panel + business-panel 오마주. 실제 전문가 5-10명의 관점을 시뮬레이션하여 다각적 분석.
|
|
16
20
|
> "한 사람의 시야는 좁다. 패널의 시야는 넓다."
|
|
17
21
|
|
|
@@ -12,6 +12,10 @@ argument-hint: "<완료할 작업 설명>"
|
|
|
12
12
|
|
|
13
13
|
# tfx-persist — Tri-Verified Persistence Loop
|
|
14
14
|
|
|
15
|
+
> **ARGUMENTS 처리**: 이 스킬이 `ARGUMENTS: <값>`과 함께 호출되면, 해당 값을 사용자 입력으로 취급하여
|
|
16
|
+
> 워크플로우의 첫 단계 입력으로 사용한다. ARGUMENTS가 비어있거나 없으면 기존 절차대로 사용자에게 입력을 요청한다.
|
|
17
|
+
|
|
18
|
+
|
|
15
19
|
> OMC ralph 오마주. 핵심 차별점: 검증자가 단일 agent가 아니라 **3-CLI consensus**.
|
|
16
20
|
> The boulder never stops — but it stops being wrong.
|
|
17
21
|
|
package/skills/tfx-plan/SKILL.md
CHANGED
|
@@ -11,6 +11,10 @@ argument-hint: "<구현할 기능 설명>"
|
|
|
11
11
|
|
|
12
12
|
# tfx-plan — Light Implementation Plan
|
|
13
13
|
|
|
14
|
+
> **ARGUMENTS 처리**: 이 스킬이 `ARGUMENTS: <값>`과 함께 호출되면, 해당 값을 사용자 입력으로 취급하여
|
|
15
|
+
> 워크플로우의 첫 단계 입력으로 사용한다. ARGUMENTS가 비어있거나 없으면 기존 절차대로 사용자에게 입력을 요청한다.
|
|
16
|
+
|
|
17
|
+
|
|
14
18
|
> **Deep 버전**: tfx-deep-plan. "제대로/꼼꼼히" 수정자로 자동 에스컬레이션.
|
|
15
19
|
> Gemini 위임 빠른 계획 — Claude는 컨텍스트 수집·출력 포맷만, 핵심 계획 수립은 Gemini에 위임.
|
|
16
20
|
|
|
@@ -12,6 +12,10 @@ argument-hint: "[파일 경로 또는 git diff 범위]"
|
|
|
12
12
|
|
|
13
13
|
# tfx-prune — Tri-Verified AI Slop Remover
|
|
14
14
|
|
|
15
|
+
> **ARGUMENTS 처리**: 이 스킬이 `ARGUMENTS: <값>`과 함께 호출되면, 해당 값을 사용자 입력으로 취급하여
|
|
16
|
+
> 워크플로우의 첫 단계 입력으로 사용한다. ARGUMENTS가 비어있거나 없으면 기존 절차대로 사용자에게 입력을 요청한다.
|
|
17
|
+
|
|
18
|
+
|
|
15
19
|
> OMC ai-slop-cleaner 오마주. 핵심 차별점: 단일 판단이 아닌 **3자 독립 감지 + 합의** 기반 제거.
|
|
16
20
|
> "AI가 만든 슬롭은 AI 3명이 합의해야 슬롭이다."
|
|
17
21
|
|
package/skills/tfx-qa/SKILL.md
CHANGED
|
@@ -11,6 +11,10 @@ argument-hint: "[테스트 명령 또는 파일 경로]"
|
|
|
11
11
|
|
|
12
12
|
# tfx-qa — Light Test-Fix Cycle
|
|
13
13
|
|
|
14
|
+
> **ARGUMENTS 처리**: 이 스킬이 `ARGUMENTS: <값>`과 함께 호출되면, 해당 값을 사용자 입력으로 취급하여
|
|
15
|
+
> 워크플로우의 첫 단계 입력으로 사용한다. ARGUMENTS가 비어있거나 없으면 기존 절차대로 사용자에게 입력을 요청한다.
|
|
16
|
+
|
|
17
|
+
|
|
14
18
|
> **Deep 버전**: tfx-deep-qa. "제대로/꼼꼼히" 수정자로 자동 에스컬레이션.
|
|
15
19
|
> 테스트 실행 → 실패 분석 → 자동 수정 → 재실행. 최대 3회. OMC ultraqa 영감.
|
|
16
20
|
|
|
@@ -11,6 +11,10 @@ triggers:
|
|
|
11
11
|
|
|
12
12
|
# tfx-ralph — tfx-persist 별칭
|
|
13
13
|
|
|
14
|
+
> **ARGUMENTS 처리**: 이 스킬이 `ARGUMENTS: <값>`과 함께 호출되면, 해당 값을 사용자 입력으로 취급하여
|
|
15
|
+
> 워크플로우의 첫 단계 입력으로 사용한다. ARGUMENTS가 비어있거나 없으면 기존 절차대로 사용자에게 입력을 요청한다.
|
|
16
|
+
|
|
17
|
+
|
|
14
18
|
이 스킬은 `tfx-persist`와 동일합니다. `/tfx-persist` 스킬을 호출하세요.
|
|
15
19
|
|
|
16
20
|
## 동작
|
|
@@ -12,6 +12,10 @@ argument-hint: "[--add|--edit|--probe-all|--diagnose]"
|
|
|
12
12
|
|
|
13
13
|
# tfx-remote-setup — 원격 호스트 설정 위저드
|
|
14
14
|
|
|
15
|
+
> **ARGUMENTS 처리**: 이 스킬이 `ARGUMENTS: <값>`과 함께 호출되면, 해당 값을 사용자 입력으로 취급하여
|
|
16
|
+
> 워크플로우의 첫 단계 입력으로 사용한다. ARGUMENTS가 비어있거나 없으면 기존 절차대로 사용자에게 입력을 요청한다.
|
|
17
|
+
|
|
18
|
+
|
|
15
19
|
> 원격 세션(tfx-remote-spawn)을 쓰기 전에 호스트를 설정합니다.
|
|
16
20
|
> Tailscale 네트워크 자동 감지 → SSH 연결 → Claude 프로브 → hosts.json 등록을 한번에.
|
|
17
21
|
|
|
@@ -15,6 +15,10 @@ argument-hint: "[호스트] [프롬프트] 또는 자연어"
|
|
|
15
15
|
|
|
16
16
|
# tfx-remote-spawn — 원격/로컬 Claude 세션 관리
|
|
17
17
|
|
|
18
|
+
> **ARGUMENTS 처리**: 이 스킬이 `ARGUMENTS: <값>`과 함께 호출되면, 해당 값을 사용자 입력으로 취급하여
|
|
19
|
+
> 워크플로우의 첫 단계 입력으로 사용한다. ARGUMENTS가 비어있거나 없으면 기존 절차대로 사용자에게 입력을 요청한다.
|
|
20
|
+
|
|
21
|
+
|
|
18
22
|
> psmux 세션 기반으로 Claude를 원격/로컬에서 실행하고 관리합니다.
|
|
19
23
|
> AskUserQuestion 기반 인터랙티브 메뉴로 다중 호출 없이 한번에 처리.
|
|
20
24
|
|
|
@@ -13,6 +13,10 @@ argument-hint: "<검색 주제>"
|
|
|
13
13
|
|
|
14
14
|
# tfx-research — Light Web Research
|
|
15
15
|
|
|
16
|
+
> **ARGUMENTS 처리**: 이 스킬이 `ARGUMENTS: <값>`과 함께 호출되면, 해당 값을 사용자 입력으로 취급하여
|
|
17
|
+
> 워크플로우의 첫 단계 입력으로 사용한다. ARGUMENTS가 비어있거나 없으면 기존 절차대로 사용자에게 입력을 요청한다.
|
|
18
|
+
|
|
19
|
+
|
|
16
20
|
> **Deep 버전**: tfx-deep-research. "제대로/꼼꼼히" 수정자로 자동 에스컬레이션.
|
|
17
21
|
> 빠른 단일 소스 검색 + 요약. **검색 자체를 Gemini에 위임**해 Claude 토큰 최소화. Gemini CLI의 네이티브 Google Search로 검색+요약을 한 번에 처리.
|
|
18
22
|
|
|
@@ -11,6 +11,10 @@ argument-hint: "[파일 경로 또는 변경 설명]"
|
|
|
11
11
|
|
|
12
12
|
# tfx-review — Light Code Review
|
|
13
13
|
|
|
14
|
+
> **ARGUMENTS 처리**: 이 스킬이 `ARGUMENTS: <값>`과 함께 호출되면, 해당 값을 사용자 입력으로 취급하여
|
|
15
|
+
> 워크플로우의 첫 단계 입력으로 사용한다. ARGUMENTS가 비어있거나 없으면 기존 절차대로 사용자에게 입력을 요청한다.
|
|
16
|
+
|
|
17
|
+
|
|
14
18
|
> **Deep 버전**: tfx-deep-review. "제대로/꼼꼼히" 수정자로 자동 에스컬레이션.
|
|
15
19
|
> **HARD RULE**: 리뷰 결과를 생성할 때 Claude가 직접 git log/diff를 실행하지 마라. Codex code-reviewer에게 위임하라.
|
|
16
20
|
> Codex 단일 리뷰로 빠른 피드백. 토큰 최소화.
|