You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
설계 조사. 1.0.0 acceptance 필수는 아니다 — north star의 천장을 정확히 측정하고 그 안에서의 최선 경로를 고정하는 게 목적이다.
north star (사용자 결정): ".mcp.json(MCP 서버)만 설정하면 나머지는 알아서 진행된다" — 사용자가 config를 hand-wire하지 않고 도구가 흐름을 몬다.
직접 동기: Dep ②(#425, merged)·Dep ③(#424, merged)로 vite.config tunnel 옵션 indirection·env-var hand-off를 제거해 config 의존을 줄여왔다. 남은 질문은 "그 줄이기의 끝은 어디인가 — MCP 데몬이 dev 서버까지 띄울 수 있나?"다.
결론 먼저 (TL;DR)
env-2 live-dev에서 "MCP만 설정" north star는 구조적으로 도달 불가다. 세 후보 접근(A/B/C)을 코드 근거로 평가하고 adversarial 검증으로 천장을 확정했다. 진짜 레버는 "script/config 제거"가 아니라 앱 번들을 누가 서빙하느냐이고, 그건 제거할 수 없다 — 옮길 수 있을 뿐이다.
권고: 접근 B (agent-plugin skill 부트스트랩). devtools 변경 0, install-graph 불변식 보존, fix-env2-cdp-tunnel-seam changeset의 자연스러운 연속, 사용자 intent 충족. 별도로 접근 C2(relay-manager)는 #420 orphan 문제를 구조적으로 푸는 아키텍처 개선이라 독립 트래킹 후보로 남긴다.
확정된 천장 (adversarial 검증 완료)
env-2(실기기 PWA가 cloudflared 터널로 미니앱 로드)에는 독립된 두 터널이 있다:
tunnel#1 → Vite dev server — httpServer.address()로 잡은 Vite 바인드 포트(src/unplugin/index.ts:252-266)를 노출. 런처 PWA iframe이 앱 자산(HTML/JS) 을 로드하는 채널.
src/mcp/chii-relay.ts:117-170startChiiRelay는 순수 CDP 브리지(target WS + client WS)다 — 앱 HTML/JS를 서빙하지 않는다. 데몬·relay 어디에도 정적 파일 서빙 모드는 없다.
→ env-2 live-dev에는 무언가가 앱 번들을 서빙해야 하고, 그게 Vite dev server다. MCP relay는 이걸 대체 못 한다. 따라서 "MCP만 설정하면 앱이 뜬다"는 live-dev에서 불가능하다(static build를 서빙하면 가능하지만 HMR을 죽여 env-2의 존재 이유를 없앤다).
검증으로 무너진 전제: "install-graph 불변식이 데몬의 relay 기동을 막는다"는 틀렸다. scripts/check-mcp-react-free.sh:20-23의 grep PATTERN은 react/react-dom 전용이고 chii/cloudflared/ws는 스캔하지 않는다. 이들은 이미 package.jsondependencies이자 tsdown.config.ts:121의 external이며, 데몬은 이미 env3/4에서 bootRelayFamily(debug-server.ts:1684+, startChiiRelay+startQuickTunnel 호출)로 직접 relay+tunnel을 띄운다. env-2만 bootExternalRelayFamily(debug-server.ts:1795, attach-only)로 unplugin에 위임한다. 즉 데몬의 relay 기동 능력은 이미 있고, 천장은 relay가 아니라 앱 서버다.
세 접근 평가
A. MCP 데몬이 Vite dev server를 child process로 spawn
FEASIBLE-WITH-CAVEATS.child_process.spawn은 이미 데몬 번들에서 쓰임(src/mcp/local-launcher.ts:29 정적 import) → install-graph 불변식(react 전용) 위반 아님. 새 tool start_dev_server({projectRoot, script?})가 pnpm dev:phone:cdp를 consumer cwd에서 spawn.
최대 리스크 둘:
.ait_urls write race: unplugin이 터널 resolve 후 async로 파일을 씀(5-15s, src/unplugin/index.ts:329-334). 데몬엔 대기 메커니즘이 없어 start_dev_server가 .ait_urls readiness까지 poll해야 함.
남는 consumer-side irreducible: vite.config의 unplugin 등록(tunnel:{cdp:true} 또는 AIT_TUNNEL), 알려진 pnpm script 이름. .mcp.json만으론 불충분 — 데몬은 vite.config를 만들 수 없다.
B. agent-plugin skill이 dev+attach를 한 번에 부트스트랩 ★권고
FEASIBLE. agent-plugin이 100% 소유, devtools 변경 0. /ait debug skill(shared/skills/debug/SKILL.md)이 env-2를 소유하나 현재는 dev 서버가 떠 있다고 가정(SKILL.md:61). skill이 직접: (1) pnpm dev:phone:cdp를 background Bash로 기동, (2) <projectRoot>/.ait_urls 출현까지 poll, (3) start_debug({mode:'relay-sandbox', projectRoot}) 호출.
.ait_urls 발견 seam(#424/relay-url-store.ts)이 정확히 이 자동화를 위해 설계됨 — unplugin이 쓰고 데몬이 lazy fallback으로 읽음(debug-server.ts:1888). fix-env2-cdp-tunnel-seam changeset이 이미 setup-phone-preview → debug seam 절벽을 제거했고, B는 "사용자가 pnpm dev:phone:cdp를 직접 쳐라"를 "skill이 대신 친다"로 잇는 자연스러운 다음 걸음.
install-graph 불변식 보존(데몬에 vite/react를 안 끌어들임) + 사용자 intent("내가 hand-wire 안 함, 도구가 몬다") 충족. .mcp.json만이 유일 config는 아니지만(skill이 오케스트레이터), 런타임 호출 단계는 자동화됨.
활성 버그 발견 (B와 무관하게 선결): debug/SKILL.md:212-220이 mode:'mobile'/'relay-dev'를 호출하는데 실제 start_debug enum은 ['local-browser','relay-sandbox','relay-staging','relay-live'](tools.ts:423)다. 에이전트가 mode:'mobile'로 호출하면 실패한다 — 정합 결함, 먼저 고친다.
C. relay+tunnel을 Vite 밖 독립 프로세스로 분리
C1 (데몬이 dynamic import로 relay+tunnel 기동): FEASIBLE-WITH-CAVEATS이나 north star 근접도는 A보다 낮다. 데몬이 app tunnel을 띄우려면 앱 포트를 알아야 하는데(AIT_DEVTOOLS_URL 수동 설정), .ait_urls IPC 채널을 우회해 수동 env 설정을 재도입. 여전히 pnpm dev 필요.
C2 (standalone relay-manager CLI): FEASIBLE-WITH-CAVEATS. cli.ts flat dispatch에 4번째 target으로 자연스럽게 들어감. unplugin 터널 경로에 orphan parent-watcher 부재 — vite 고아화 시 cloudflared 좀비 잔존 (#347 사각) #420 SIGKILL/orphan 문제를 구조적으로 해결(relay+tunnel 수명이 Vite와 분리) — 이게 진짜 가치. .mcp.json에 relay-manager를 등록하면 Claude Code가 자동 기동, 사용자는 plain pnpm dev만. 단 앱 서버는 여전히 사용자 몫이라 north star 거리는 A/B와 동일.
배경 / 성격
설계 조사. 1.0.0 acceptance 필수는 아니다 — north star의 천장을 정확히 측정하고 그 안에서의 최선 경로를 고정하는 게 목적이다.
north star (사용자 결정): "
.mcp.json(MCP 서버)만 설정하면 나머지는 알아서 진행된다" — 사용자가 config를 hand-wire하지 않고 도구가 흐름을 몬다.직접 동기: Dep ②(#425, merged)·Dep ③(#424, merged)로 vite.config tunnel 옵션 indirection·env-var hand-off를 제거해 config 의존을 줄여왔다. 남은 질문은 "그 줄이기의 끝은 어디인가 — MCP 데몬이 dev 서버까지 띄울 수 있나?"다.
결론 먼저 (TL;DR)
env-2 live-dev에서 "MCP만 설정" north star는 구조적으로 도달 불가다. 세 후보 접근(A/B/C)을 코드 근거로 평가하고 adversarial 검증으로 천장을 확정했다. 진짜 레버는 "script/config 제거"가 아니라 앱 번들을 누가 서빙하느냐이고, 그건 제거할 수 없다 — 옮길 수 있을 뿐이다.
권고: 접근 B (agent-plugin skill 부트스트랩). devtools 변경 0, install-graph 불변식 보존,
fix-env2-cdp-tunnel-seamchangeset의 자연스러운 연속, 사용자 intent 충족. 별도로 접근 C2(relay-manager)는 #420 orphan 문제를 구조적으로 푸는 아키텍처 개선이라 독립 트래킹 후보로 남긴다.확정된 천장 (adversarial 검증 완료)
env-2(실기기 PWA가 cloudflared 터널로 미니앱 로드)에는 독립된 두 터널이 있다:
httpServer.address()로 잡은 Vite 바인드 포트(src/unplugin/index.ts:252-266)를 노출. 런처 PWA iframe이 앱 자산(HTML/JS) 을 로드하는 채널.startChiiRelay(port 0) →startQuickTunnel(relay.port)(src/unplugin/index.ts:304). CDP 디버깅 채널일 뿐.src/mcp/chii-relay.ts:117-170startChiiRelay는 순수 CDP 브리지(target WS + client WS)다 — 앱 HTML/JS를 서빙하지 않는다. 데몬·relay 어디에도 정적 파일 서빙 모드는 없다.→ env-2 live-dev에는 무언가가 앱 번들을 서빙해야 하고, 그게 Vite dev server다. MCP relay는 이걸 대체 못 한다. 따라서 "MCP만 설정하면 앱이 뜬다"는 live-dev에서 불가능하다(static build를 서빙하면 가능하지만 HMR을 죽여 env-2의 존재 이유를 없앤다).
검증으로 무너진 전제: "install-graph 불변식이 데몬의 relay 기동을 막는다"는 틀렸다.
scripts/check-mcp-react-free.sh:20-23의 grep PATTERN은 react/react-dom 전용이고 chii/cloudflared/ws는 스캔하지 않는다. 이들은 이미package.jsondependencies이자tsdown.config.ts:121의external이며, 데몬은 이미 env3/4에서bootRelayFamily(debug-server.ts:1684+,startChiiRelay+startQuickTunnel호출)로 직접 relay+tunnel을 띄운다. env-2만bootExternalRelayFamily(debug-server.ts:1795, attach-only)로 unplugin에 위임한다. 즉 데몬의 relay 기동 능력은 이미 있고, 천장은 relay가 아니라 앱 서버다.세 접근 평가
A. MCP 데몬이 Vite dev server를 child process로 spawn
FEASIBLE-WITH-CAVEATS.
child_process.spawn은 이미 데몬 번들에서 쓰임(src/mcp/local-launcher.ts:29정적 import) → install-graph 불변식(react 전용) 위반 아님. 새 toolstart_dev_server({projectRoot, script?})가pnpm dev:phone:cdp를 consumer cwd에서 spawn.최대 리스크 둘:
.ait_urlswrite race: unplugin이 터널 resolve 후 async로 파일을 씀(5-15s,src/unplugin/index.ts:329-334). 데몬엔 대기 메커니즘이 없어start_dev_server가.ait_urlsreadiness까지 poll해야 함.shutdown()(debug-server.ts:2308-2324)에서child.kill()필요한데 그 개념이 현재 없음. SIGKILL 시 orphan 보호는 unplugin parentWatcher(unplugin 터널 경로에 orphan parent-watcher 부재 — vite 고아화 시 cloudflared 좀비 잔존 (#347 사각) #420)의 5초 poll에만 의존.남는 consumer-side irreducible: vite.config의 unplugin 등록(
tunnel:{cdp:true}또는AIT_TUNNEL), 알려진 pnpm script 이름..mcp.json만으론 불충분 — 데몬은 vite.config를 만들 수 없다.B. agent-plugin skill이 dev+attach를 한 번에 부트스트랩 ★권고
FEASIBLE. agent-plugin이 100% 소유, devtools 변경 0.
/ait debugskill(shared/skills/debug/SKILL.md)이 env-2를 소유하나 현재는 dev 서버가 떠 있다고 가정(SKILL.md:61). skill이 직접: (1)pnpm dev:phone:cdp를 background Bash로 기동, (2)<projectRoot>/.ait_urls출현까지 poll, (3)start_debug({mode:'relay-sandbox', projectRoot})호출..ait_urls발견 seam(#424/relay-url-store.ts)이 정확히 이 자동화를 위해 설계됨 — unplugin이 쓰고 데몬이 lazy fallback으로 읽음(debug-server.ts:1888).fix-env2-cdp-tunnel-seamchangeset이 이미setup-phone-preview → debugseam 절벽을 제거했고, B는 "사용자가pnpm dev:phone:cdp를 직접 쳐라"를 "skill이 대신 친다"로 잇는 자연스러운 다음 걸음.install-graph 불변식 보존(데몬에 vite/react를 안 끌어들임) + 사용자 intent("내가 hand-wire 안 함, 도구가 몬다") 충족.
.mcp.json만이 유일 config는 아니지만(skill이 오케스트레이터), 런타임 호출 단계는 자동화됨.활성 버그 발견 (B와 무관하게 선결):
debug/SKILL.md:212-220이mode:'mobile'/'relay-dev'를 호출하는데 실제start_debugenum은['local-browser','relay-sandbox','relay-staging','relay-live'](tools.ts:423)다. 에이전트가mode:'mobile'로 호출하면 실패한다 — 정합 결함, 먼저 고친다.C. relay+tunnel을 Vite 밖 독립 프로세스로 분리
AIT_DEVTOOLS_URL수동 설정),.ait_urlsIPC 채널을 우회해 수동 env 설정을 재도입. 여전히pnpm dev필요.relay-managerCLI): FEASIBLE-WITH-CAVEATS.cli.tsflat dispatch에 4번째 target으로 자연스럽게 들어감. unplugin 터널 경로에 orphan parent-watcher 부재 — vite 고아화 시 cloudflared 좀비 잔존 (#347 사각) #420 SIGKILL/orphan 문제를 구조적으로 해결(relay+tunnel 수명이 Vite와 분리) — 이게 진짜 가치..mcp.json에 relay-manager를 등록하면 Claude Code가 자동 기동, 사용자는 plainpnpm dev만. 단 앱 서버는 여전히 사용자 몫이라 north star 거리는 A/B와 동일.비교 / 권고
pnpm dev제거권고:
/ait debug에 env-2 부트스트랩(background dev 기동 +.ait_urlspoll + attach) 추가. devtools 무변경, 최소 비용, intent 충족. (선결: skill의mode:'mobile'enum 버그 정정.)pnpm dev한 줄 제거)이 B 대비 낮다.천장은 명확히 고정: env-2 live-dev에서 앱 서버(Vite)는 누군가 띄워야 하고, 그 "누군가"를 사람→skill로 옮기는 게(접근 B) 도달 가능한 최선이다. 완전 무인은 비목표.
연관
.ait_urls파일 발견) — B의 readiness 신호 채널. merged.meta/three-environments-fidelity.md로 가리킴 →four-environments-fidelity.md로 정정 필요(별도).fix-env2-cdp-tunnel-seamchangeset — B가 잇는 seam 작업.acceptance (이 issue의 종료 조건)
mode:'mobile'enum 버그 정정 포함)