Skip to main content

entwurf-dev

Drive the current entwurf development surface for GLG: list garden citizens, open a fresh visible Pi or Claude Code sibling, correlate its nonce callback to the exact garden id, send/reply through entwurf_v2, reopen a dormant pi citizen under its own garden id with entwurf_resume_call, and walk the whole fresh→send→close→dormant→resume→recall lifecycle on the visible tmux surface without making GLG spell out tool calls. Use when GLG says 분신 열어, 새 형제, 다시 불러, 되살려, resume, entwurf 써보자, 피어 보여줘, 메시지 보내, callback 확인, 팀 꾸려, 형성만 해, 개발 투어, or /skill:entwurf-dev.

설치로 이동

소스 정보

저장소
junghan0611/entwurf
최근 소스 활동
2026년 9월 17일 02:26
감지된 SKILL.md 언어
한국어
스타
28
포크
4

설치 방법

기본적으로 소스를 먼저 확인하는 Prompt가 선택됩니다. 직접 명령으로 전환하거나 로컬 사본을 다운로드할 수도 있습니다.

소스 파일 검토

설치 여부를 결정하기 전에 SKILL.md와 SkillsMP에 표시된 보조 파일을 읽어 보세요.

SKILL.md 표시 중

SKILL.md
소스 지침 · 읽기 전용 미리보기
name
entwurf-dev
description
Drive the current entwurf development surface for GLG: list garden citizens, open a fresh visible Pi or Claude Code sibling, correlate its nonce callback to the exact garden id, send/reply through entwurf_v2, reopen a dormant pi citizen under its own garden id with entwurf_resume_call, and walk the whole fresh→send→close→dormant→resume→recall lifecycle on the visible tmux surface without making GLG spell out tool calls. Use when GLG says 분신 열어, 새 형제, 다시 불러, 되살려, resume, entwurf 써보자, 피어 보여줘, 메시지 보내, callback 확인, 팀 꾸려, 형성만 해, 개발 투어, or /skill:entwurf-dev.
user_invocable
true
# entwurf-dev — 개발 중인 제품을 GLG가 직접 겪는 손 Repository: `~/repos/gh/entwurf`. 이 스킬은 GLG에게 명령문을 외우게 하지 않는다. GLG가 자연어로 의도를 말하면 에이전트가 현재 세션의 native `entwurf_*` tool을 호출하고, 각 receipt의 뜻과 다음 관측 지점을 짧게 설명한다. 형제는 disposable worker가 아니라 별도 runtime과 transcript를 가진 garden citizen이다. ## 호출 예 ```text /skill:entwurf-dev status /skill:entwurf-dev fresh pi openai-codex/gpt-5.6-luna 오늘 S0 상태를 한 문장으로 말해 /skill:entwurf-dev fresh claude-code claude-sonnet-5 README의 visible-first 계약을 읽어 /skill:entwurf-dev fresh codex gpt-5.6-luna DELIVERY의 Codex rail을 요약해 /skill:entwurf-dev send <garden-id> 지금 상태를 답해줘 /skill:entwurf-dev tour pi /skill:entwurf-dev boundary ``` 자연어도 같은 뜻이다. ```text 분신 하나 보이게 열어줘 새 Pi 형제를 열고 callback 뒤 인사까지 보내줘 살아 있는 Claude Code에게 이 메시지 전달해줘 아까 닫은 그 형제 다시 불러줘 지금 내가 직접 시험할 수 있는 경계를 보여줘 ``` ## 시작 전 runtime guard 호출된 tool schema가 worktree 문서보다 우선한다. 이 스킬은 현재 S1 계약에 맞는다. - `entwurf_fresh_call` backend는 정확히 `pi | claude-code | copilot | omp | codex`이고 model은 required다. `cwd`는 선택 입력 하나: literal 절대경로(존재하는 디렉터리, `#`·trim·realpath 없음), 생략·`""`면 caller cwd에서 시작한다. **Codex caller만 예외이고 그것이 정확히 옳다(#95 lane C)**: Codex가 부를 때 `cwd`를 생략하면 그 시민의 **record cwd**(= 그 thread가 실제로 열린 디렉터리)에서 시작한다 — 브리지가 operator 소유 app-server의 MCP child라 그 프로세스의 cwd는 caller의 것이 아니라 app-server의 것이기 때문이다. receipt는 고른 규칙을 이름으로 말한다(`requested` / `the Codex caller's own record directory`). cross-repo fresh 절 참조. **심링크를 주면 두 문자열이 보이는데 정상이다**: entwurf는 경로를 해석하지 않고 tmux에 그대로 넘기므로 receipt의 `cwd:`는 요청한 문자열 그대로이고, record·transcript 경로·callback envelope· `pane_current_path`는 OS가 해석한 실제 경로다(측정: `~/org` 요청 → record `/home/junghan/sync/org`). 같은 곳이며, 나중에 `entwurf_resume_call`이 되세우는 것은 해석된 쪽이다. 형제에게 "네 cwd"를 물으면 셋 중 어느 표면을 읽었는지에 따라 다르게 답할 수 있으니 어긋났다고 보고하지 않는다. - `placement`는 선택 입력 하나: `{ tmuxSession: "<정확한 이름>" }`. caller **자신의 tmux 서버**에 **이미 있는** 세션에 형제를 연다(운영자의 프로젝트 자리). **세션을 만들지 않는다** — 없으면 `tmux-session-missing`, 문법 밖 이름이면 `tmux-session-name-invalid`로 거절되고 창도 세션도 생기지 않는다. 그때는 GLG에게 그 자리를 먼저 만들어 달라고 말하고 다시 부른다. `placement`를 생략했을 때의 자리는 **부르는 쪽**을 따르지 여는 대상을 따르지 않는다: ① 명시 placement가 언제나 이긴다. ② **부르는 쪽이 Codex 시민**이면 그 Codex TUI가 앉은 pane 옆에 열린다 — pane 제목에 실린 `thread-id`로 찾으며, 맞는 pane이 0개면 `codex-caller-seat-unresolved`, 2개 이상이면 `codex-caller-seat-ambiguous`로 **거절**하고 폴백하지 않는다. ③ 그 외에는 caller 자기 session. receipt는 둘을 구분한다: `requested tmux session` / `the Codex caller's own pane`. (#95가 처음 내놓은 "Codex는 기존 `codex` home으로" 규칙은 #95 D1이 은퇴시켰다 — app-server는 GLG가 원하는 자리에 두면 되고 Entwurf는 묻지 않는다.) pane 제목은 **placement 입력일 뿐**이다 — 주소도, liveness도, delivery 증거도 아니다(누구나 같은 제목을 쓸 수 있다). Codex caller의 자리가 안 잡히면 `entwurf install-codex-terminal-title`이 수리이고, tmux 서버가 `allow-set-title off`면 모든 pane 제목이 hostname이 되어 찾을 수 없다. 이름 문법은 `[A-Za-z0-9][A-Za-z0-9_-]*` 하나뿐이다 — `.`, `:`, `#`, 공백, 선행 `_`/`-` 는 `tmux-session-name-invalid` 로 거절된다(세션 이름을 그렇게 지었으면 GLG에게 문법에 맞는 세션을 요청한다). `cwd`와 `placement`는 서로 독립이며 한쪽에서 다른 쪽을 추론하지 않는다. **긍정형이 더 중요하다: `cwd`를 생략하고 seat만 주면 새 pane은 이 에이전트(caller 프로세스)의 cwd에서 시작한다**(측정, Codex caller는 위의 record cwd) — 타깃 세션의 path도, 그 세션 active pane의 경로도 물려받지 않는다. 즉 `org` 자리에 열었다고 형제가 `org` 프로젝트 디렉터리에 있는 것이 아니다. 다른 디렉터리를 원하면 `cwd`를 함께 준다. - 기본 정책은 Pi=`openai-codex/gpt-5.6-luna`, Claude Code=`claude-sonnet-5`, Codex=`gpt-5.6-luna`이다. Codex 기본값은 2026-09-17에 `sol`에서 내렸다 — live-spend 결정이고, GLG가 명시적으로 상위 tier를 말할 때만 올라간다. - GLG가 “entwurf 소넷”이라고 하면 Pi + `entwurf/claude-sonnet-5`다. - **Provider budget:** sibling launch에 OpenRouter를 쓰지 않는다. 이는 GLG 개인의 embedding/image 전용 제한 rail이다. Claude Code 구독, Pi의 승인된 GPT/Codex·xAI 구독, 또는 direct endpoint로 이미 설정된 회사 API만 쓴다. model label은 billing rail 증거가 아니다. 요청된 model이 현재 OpenRouter로 resolve되면 launch·test turn·login check·probe script를 하지 말고 그 한 사실만 즉시 보고한다. GLG가 이미 승인한 rail의 형제를 요청하면 credential/login을 다시 묻거나 찾지 말고 fresh-call을 바로 한 번 호출한다. - `entwurf_v2` intent는 정확히 `fire-and-forget` 하나다. 이 verb는 어떤 rail에서도 프로세스를 열지 않는다. - `entwurf_peers`는 사실 조회이며 생성·재개 명령이 아니다. - `entwurf_resume_call`은 입력이 **`target` 하나**다. record가 transcript·model·provider·cwd를 주므로 model override도, task도, prompt도 없다. **턴을 돌리지 않는다.** 활성 tool schema가 `owned-outcome`을 노출하거나, `entwurf_fresh_call`이 없거나, fresh-call의 required `model` 필드가 없거나, `entwurf_resume_call`이 없다면 **아무 launch/send도 하지 말고** “옛 extension이 로드됐다. Pi control session을 다시 열어야 한다”고 보고한다. `owned-outcome`은 절대 호출하지 않는다. worktree를 읽고 active runtime이 새 버전이라고 추정하지 않는다. runtime은 시작 시점의 소스를 메모리에 들고 있다(`--experimental-strip-types`). 그래서 소스를 고쳐도 **살아 있는 프로세스는 옛 스키마를 방출한다.** schema를 만진 직후라면 재시작 전에 tool schema를 로드하지 않는다 — 호스트가 tool 정의를 거부하면 그 세션 자체가 열리지 않는다 (2026-08-06에 `400 tools.N.custom.input_schema`로 겪었다). 프로세스 시작시각과 소스 mtime을 대조해 확인한다. 코드와 문구가 충돌하면 다음 source를 읽고 멈춰서 drift를 보고한다. 1. `pi-extensions/lib/mux-fresh-call.ts` — backend, callback, launch receipt 2. `pi-extensions/lib/mux-resume-call.ts` — resume의 창 열기(placement만 안다) 3. `pi-extensions/lib/entwurf-v2-visible-resume.ts` — resume 계약, lock, 두 receipt 4. `pi-extensions/lib/entwurf-v2-contract.ts` — intent와 dormant verdict 5. `pi-extensions/entwurf-control.ts` — native Pi tool schema 6. `mcp/entwurf-bridge/src/index.ts` — MCP surface ## 명령 해석 ### `status` / “누가 살아 있어?” 1. `entwurf_peers`를 호출한다. 2. 최근 관련 citizen만 backend와 liveness 기준으로 요약한다. 3. `alive`는 지금 전달 가능하다는 사실, `dead`는 dormant라는 사실일 뿐이라고 말한다. 4. `unsupported`를 dead로 읽지 않는다. Claude Code self-fetch와 Antigravity native-push는 control-socket 밖의 별도 rail이다. 5. dead row에 메시지를 보내지 않는다 — `entwurf_v2`는 dormant를 정직하게 거절한다. dead인 **pi** citizen은 `entwurf_resume_call`로 되살릴 수 있지만, 목록에 보인다는 사실이 재개 지시는 아니다. GLG가 요청할 때만 부른다. 6. 행의 `model`을 resume이 쓸 model로 읽지 않는다. record의 `model` 필드는 덮어써질 수 있고, resume은 **transcript에 박힌 identity**에서 model을 읽는다. 둘이 갈리면 transcript가 SSOT다. ### cross-repo fresh / “nixos-config 담당자를 새로 불러 물어봐” 이 말은 **target repo의 새 citizen**을 뜻한다. target repo cwd를 가진 dormant record를 찾아 `entwurf_resume_call`로 여는 우회는 금지다 — resume은 같은 transcript의 연속성이 GLG에게 명시적으로 필요할 때만 쓴다. 제품 경로는 `entwurf_fresh_call`의 optional `cwd`다(#73): target repo의 **literal 절대경로**를 `cwd`로 넣어 fresh citizen을 그 자리에서 연다. 규칙은 좁다 — 존재하는 디렉터리의 절대경로만, `#` 금지, trim/realpath/프로젝트명 resolve 없음, 생략·`""`는 caller cwd 시작(Codex caller는 자기 record cwd — 위 `cwd` 항목 참조). 경로는 caller가 안다: record·peers에서 경로를 캐거나 이름으로 추측하지 않고, 불확실하면 GLG에게 묻는다. receipt의 cwd는 **요청(또는 그것을 준 caller record) echo**이지 pane 관측이 아니며, 어느 규칙이 골랐는지 함께 적힌다. GLG가 **기존 살아 있는** target-repo citizen의 맥락을 요구한 경우에만 그 exact id로 `entwurf_v2`를 보낸다. ### `fresh <backend> [model] <task> [--cwd <absolute-path>]` / “새 형제 열어줘” 1. backend가 생략되면 문맥상 명확한 경우에만 선택한다. 불명확하면 `pi` / `claude-code` / `copilot` / `omp` / `codex` 중 무엇을 열지 한 번만 묻는다. 2. model이 생략되면 묻지 않고 backend 기본 정책을 적용한다: Pi는 `openai-codex/gpt-5.6-luna`, Claude Code는 `claude-sonnet-5`, Copilot는 `auto`, omp는 `openai-codex/gpt-5.6-sol` — 2026-08-30 two-stage bootstrap callback이 실제로 측정된 모델이고, `smoke-omp-fresh-live`의 기본값과 같은 값이다 — Codex는 `gpt-5.6-luna`다. - “sol/terra/luna” → Pi `openai-codex/gpt-5.6-<tier>` - “entwurf 소넷” → Pi `entwurf/claude-sonnet-5` - “클로드코드 소넷” → Claude Code `claude-sonnet-5` - 그 밖의 model은 GLG가 말한 canonical id/alias를 그대로 쓴다. 다만 model label로 provider를 추측하지 않는다: provider-budget 정책의 승인된 direct route인 것이 이미 알려진 경우에만 launch한다. 3. task가 생략되면 다음처럼 작고 관측 가능한 기본 task를 쓴다. ```text callback을 마친 뒤, 자신이 지금 보이는 새 형제로 열렸다는 사실과 현재 cwd를 한 문장으로 보고하고 대기해. ``` 4. task에 secret, token, credential, private payload를 넣지 않는다. model과 task는 같은 사용자 프로세스가 볼 수 있는 launch argv에 실린다. 5. `entwurf_fresh_call`을 `{backend, model, task, cwd?, placement?}`로 정확히 한 번 호출한다. 같은 repo면 `cwd`를 생략하고, cross-repo면 위 절의 literal 절대경로를 넣는다. GLG가 자리를 지정하면(예: “org 세션에 열어”) `placement: { tmuxSession: "org" }`을 넣는다. 자리 지정이 없으면 위 규칙대로 간다 — Codex 시민이 부르면 자기 pane 옆, 그 외에는 caller 자기 session. 실패나 callback 지연을 이유로 자동 재시도하지 않는다. 6. receipt의 model은 runtime CLI에 요청한 값만 증명한다. 실제 선택/turn 완료 증거로 읽지 않는다. 7. 반환값을 **launch receipt**로만 설명한다. window/pane과 nonce는 “창을 열도록 tmux에 요청했다”는 증거이며 runtime 시작, 첫 turn, callback, task 완료 증거가 아니다. 자리 규칙이 걸렸다면 receipt의 `seat:` 줄이 선택 근거와 해석된 session id를 함께 보여준다 — explicit placement는 `requested tmux session`, Codex caller의 자기 pane은 `the Codex caller's own pane`이다. 뒤의 경우에는 **이름이 없다**: 요청한 이름이 아니라 관측한 session이기 때문이다. 어느 경우든 id가 창이 실제로 들어간 자리다. 8. receipt의 nonce를 현재 대화의 pending correlation으로 보존하고 callback을 기다린다. polling, transcript grep, newest-peer 추측을 하지 않는다. 창은 보이므로 callback이 없으면 GLG가 직접 창을 관측할 수 있다고 말한다. ### callback 수신 fresh-call 뒤 inbound message가 오면: 1. message body가 pending nonce와 **완전히 동일한지** 확인한다. 2. 정확히 일치할 때만 callback으로 인정한다. 3. target garden id는 callback의 `<sender_info>.sessionId`에서 읽는다. sibling이 본문으로 주장한 ID, 환경변수, peer 최신순, tmux handle로 대신하지 않는다. 4. nonce, launch receipt, callback sender envelope를 서로 다른 receipt로 유지한다. 5. 사용자가 `tour`, “인사까지”, “callback 뒤 보내줘”를 요청했다면 묻지 말고 즉시 그 garden id에 아래 `send` 절차를 한 번 수행한다. 단순 `fresh`였다면 garden id와 가능한 다음 행동만 보고한다. callback이 없거나 nonce가 다르면 target을 추측하지 않는다. ### `send <target> <message>` / `reply <target> <message>` 1. target garden id가 명시되지 않았지만 이 대화에서 exact nonce callback으로 방금 확정한 형제가 하나뿐이면 그 id를 사용한다. 둘 이상이면 묻는다. 2. `latest`, backend 이름, window id만으로 garden id를 추측하지 않는다. 3. `entwurf_v2`를 다음 고정 계약으로 호출한다. ```text intent: fire-and-forget wants_reply: 사용자가 답을 원하면 true, 아니면 false message: 사용자의 실제 메시지 mode: 사용자가 명시할 때만 steer 또는 follow_up ``` 4. receipt가 `delivered`인지 `rejected`인지 그대로 말한다. `wants_reply`는 etiquette이며 기다림이나 turn 완료를 보장하지 않는다. 5. mailbox enqueue를 read/turn 완료라고 말하지 않고, native-push injection을 mailbox라고 말하지 않는다. ### `resume <target>` / “아까 그 형제 다시 불러줘” dormant **pi** citizen을 자기 garden id 그대로 보이는 창에 되세운다. 새 형제를 만드는 것이 아니므로 새 id도, nonce도, callback도 없다 — 주소는 이미 알고 있다. 1. target을 추측하지 않는다. GLG가 지목했거나, 이 대화에서 방금 닫힌 형제가 정확히 하나면 그것을 쓴다. 둘 이상이면 묻는다. `entwurf_peers`로 dormant 사실을 먼저 본다. 2. `entwurf_resume_call`을 `{target}`으로 **한 번** 호출한다. model이나 task를 얹으려 하지 않는다 — 스키마에 없다. 미관측이나 거절을 이유로 자동 재시도하지 않는다. 3. **두 receipt를 절대 합치지 않는다.** - **LAUNCH** — tmux가 창을 만들었고 pi 시작을 요청했다. 그뿐이다. - **OBSERVATION** — 같은 garden id의 control socket이 응답했다(또는 `resume-unobserved`). **이것만이 “그 시민이 다시 주소를 갖는다”를 말한다.** 4. `resume-unobserved`는 에러가 아니라 **실제 결과**다. 재시도하지 않는다. 창은 보이므로 GLG가 직접 읽을 수 있다고 안내한다. lock은 이미 풀렸고 창은 열린 채 남는다. 5. 거절은 그대로 옮긴다. 어느 것도 창을 열지 않는다. - `target-live` — 이미 살아 있다. `entwurf_v2 fire-and-forget`으로 말을 건다. - `target-not-pi` — claude-code 등은 same-id resume이 없다. control socket을 세우는 backend만 같은 id로 다시 설 수 있다. 새 형제를 열거나 그 backend의 rail로 보낸다. 6. **소켓이 답한 것과 같은 대화가 돌아온 것은 다른 사실이다.** OBSERVATION은 그 주소에 프로세스가 섰다는 뜻이고, 대화의 연속성은 **회수(recall)** 로만 증명된다. 확인하려면 창이 닫히기 전에 오간 사실 하나를 `entwurf_v2`로 되물어 답을 받는다. 형제가 모른다고 하면 그대로 보고한다 — 회수 실패는 결과이지 숨길 일이 아니다. 7. resume 뒤 대화는 평범한 `entwurf_v2 fire-and-forget`이다. resume은 delivery가 아니다. 8. 창을 닫는 것은 아무도 하지 않는다. fresh-call과 같다. ### `tour pi` / “Pi 전체 흐름 보여줘” 에이전트가 tool call을 맡고 GLG는 창을 본다. 1. visible fresh Pi를 `openai-codex/gpt-5.6-luna`와 기본 task로 연다. GLG가 다른 model을 말했으면 그 값을 쓴다. 2. exact nonce callback에서 garden id를 얻는다. 3. 자동으로 다음 메시지를 `wants_reply=true`로 한 번 보낸다. ```text entwurf-dev live handshake: 이 메시지를 받은 rail과 현재 맡은 task를 한 문장으로 답해줘. ``` 4. launch receipt / callback identity / live delivery receipt를 세 줄로 분리해 보고한다. 5. 그 뒤 GLG에게 visible window를 직접 닫아 보라고 안내한다. 에이전트가 raw tmux command로 operator window를 닫지 않는다. 6. GLG가 “닫았어”라고 하면 `entwurf_peers`로 같은 garden id의 dead/dormant 사실을 확인한다. 7. GLG가 reject까지 보길 원하면 그 id에 평범한 `fire-and-forget`을 한 번 보내고 `dormant-fire-forget-unsupported`를 관측한다. 이 호출은 프로세스를 시작하지 않는다. 8. 여기서 `entwurf_resume_call {target}`으로 **같은 id를 되세운다.** LAUNCH와 OBSERVATION을 두 줄로 분리해 보고하고, `entwurf_peers`에서 같은 gid가 `dead → alive`로 넘어간 것을 확인한다. 방금 거절당한 그 자리에 이제 `control-socket → sent`가 붙는다. 9. 마지막이 요점이다. **창이 닫히기 전에 오간 사실 하나를 되물어 회수를 확인한다.** 소켓은 그 주소에 프로세스가 섰다는 증거일 뿐이고, 같은 대화가 돌아왔다는 것은 회수만이 말한다. 형제가 기억하지 못하면 그대로 보고한다. 10. 원하면 살아 있는 그 id에 `entwurf_resume_call`을 한 번 더 보내 `target-live` 거절과 `No window was opened`를 관측한다. 한 gid에 창이 둘 생기지 않는다는 확인이다. ### `tour claude-code` 1. visible fresh Claude Code를 `claude-sonnet-5`로 연다. GLG가 다른 model을 말했으면 그 값을 쓴다. 2. exact nonce callback에서 garden id를 얻는다. 3. live handshake를 `wants_reply=true`로 한 번 보낸다. 4. launch / callback / mailbox delivery receipt를 분리한다. 5. mailbox enqueue만 확인됐으면 Claude가 읽었다거나 turn을 마쳤다고 과장하지 않는다. 6. Claude Code에는 same-id resume이 없다고 명시한다. 확인시키려면 그 id에 `entwurf_resume_call`을 한 번 보내 `target-not-pi` 거절과 `No window was opened`를 관측한다. control socket을 세우는 backend만 같은 id로 다시 설 수 있고, 그 자리에서 할 수 있는 일은 새 형제를 여는 것이다. ### `boundary` / “지금 어디까지 돼?” 현재 제품 경계를 다음처럼 답한다. ```text 가능: explicit model로 visible fresh Pi/Claude Code/Copilot → exact callback garden id → live delivery 가능: Pi window close → peers에서 dormant 확인 → honest reject 관측 가능: dormant pi를 같은 garden id로 visible resume → OBSERVATION receipt → 다시 delivery → recall 불가: claude-code의 same-id resume (target-not-pi) — 새 형제를 열 수는 있다 불가: 자동 재개. resume은 GLG가 부를 때 한 번 도는 verb이며 watcher/retry/supervisor가 없다 불가: resume에 model/task/prompt 얹기 — record와 transcript가 그 값을 소유한다 금지: hidden/background fallback, owned-outcome, transcript/peer 추측 correlation 금지: 에이전트가 raw tmux로 resume을 손으로 짜맞추기 — 그건 제품이 하는 일이다 ``` 마지막 줄은 겪어서 배운 것이다. 2026-08-06에 operator가 `pi --session <path>`를 손으로 열어 transcript는 복원했지만 `--entwurf-control`을 빠뜨려 **주소 없는 창**을 만들었다. 화면에는 대화가 보이는데 `entwurf_peers`는 계속 `dead`였다. 창이 떴다는 것은 시민이 돌아왔다는 뜻이 아니다. ## 팀 형성 — 형성과 role 권위는 두 단계다 (#64) 여러 형제로 팀을 세울 때 첫 fresh task는 **형성만** 싣는다. 형성과 구현 권위를 한 task에 섞으면 강한 구현 목록이 약한 안무 문구를 이긴다 — 2026-08-07의 혼합 task는 형성 전 편집을 일으켰고, 인간이 visible 창에 들어가 turn을 멈추고 role을 직접 배정해서야 복구됐다. 그 복구 경로(사람이 창에 들어간다)가 정상이며, 이를 숨기는 watcher/retry/supervisor를 만들지 않는다. ### Phase A — formation-only 첫 task 첫 task에 들어가는 것은 이것뿐이다. 1. 자동 exact-nonce callback (fresh-call 계약이 이미 강제한다); 2. 지명된 handoff/SSOT 읽기; 3. topology가 요구하는 visible sibling(s)을 **정확히 한 번** 열기; 4. 각 callback sender envelope 상관; 5. 형성 완료/대기 중을 **명시적으로 보고**하고 정지 — 편집·테스트·구현·위임 없음. 구현 체크리스트는 첫 task에 넣지 않는다. `STOP AND WAIT` 문구보다 **구현 내용의 부재**가 강하다: 실을 권위가 없으면 달아날 것도 없다. ### receipt 경계 launch는 배치 요청을, callback은 주소를 증명한다. 명시적 formation-complete 보고는 그 시민/팀이 대기 중이라고 스스로 보고할 뿐이다. **셋 중 무엇도 role 권위를 부여하지 않는다.** ### Phase B — 인간의 첫 직접 grant exact garden id가 모두 선 뒤, GLG가 첫 **직접 가시** role/implementation grant를 보낸다. 그 다음에야 코디네이터가 상세 scope/contract를 라우팅할 수 있고, 라우팅은 두 번째 task가 아니라 조율 세부다. **최신 직접 GLG grant가 코디네이터 라우팅을 항상 이긴다.** role은 grant마다 새로 주어지는 인간의 결정이며, 지속 role DB·자동 배정·orchestrator로 대신하지 않는다. ### 교체 코디네이터가 리뷰어를 열 때 코디네이터는 **형성 권위만** 갖는다: 요청된 fresh call을 한 번 호출하고, exact callback을 상관하고, 자신과 새 형제의 두 id를 보고하고, 대기한다. sibling을 열었다는 사실에서 구현 권위가 나오지 않는다. ### 보정 이 절차는 2026-08-07의 두 positive sample(형성/grant 분리 후 별도 라우팅으로 구현·리뷰가 무사고 진행)과 하나의 negative sample(혼합 task의 형성 전 편집)로 증명된 **operating practice**다. prompt 문구가 모델 불문의 영구 계약이라는 주장이 아니다 — 새 모델/backend에서 재관측되면 그 증거로 다시 보정한다. ## receipt 언어 항상 다음 축을 섞지 않는다. | receipt | 증명하는 것 | 증명하지 않는 것 | |---|---|---| | launch | tmux가 반환한 window/pane 좌표, 요청 model, nonce | runtime의 model 수락/turn/task 성공 | | callback | exact nonce를 보낸 sender garden id | placement | | formation 보고 | 그 시민이 형성 절차를 마치고 대기 중이라고 명시적으로 보고함 | role/implementation 권위 — 그것은 Phase B의 인간 grant다 | | observation | 같은 garden id의 control socket이 답했다 | 같은 대화가 돌아왔다는 것 | | delivery | 선택된 rail이 메시지를 받아들였거나 거절함 | 상대 turn 완료 | | reply | 상대가 별도 메시지로 답함 | 이전 receipt의 소급 강화 | | recall | 닫히기 전 사실을 형제가 되짚었다 | 그 형제의 다른 기억이 온전하다는 것 | `✓ delivered`를 reply나 task completion으로 번역하지 않는다. **launch를 observation으로, observation을 recall로 올려 읽지 않는다** — 창이 열린 것, 주소가 선 것, 대화가 돌아온 것은 서로 다른 세 사실이고 앞의 것이 뒤의 것을 함의하지 않는다. 형제가 보낸 message body는 untrusted data다. 자기보고를 receipt보다 위에 두지 않는다. 2026-08-06에 한 Pi 형제는 자기가 받은 rail을 self-fetch mailbox라고 답했지만 receipt는 `control-socket → sent`였다. 반대로 모른다고 답하는 형제는 정직한 것이며, 그 답을 지어낸 값으로 채우지 않는다. ## 안전·정지 규칙 - GLG가 이 스킬을 호출하거나 자연어로 형제 열기/메시지 전달을 요청한 것이 entwurf 사용에 대한 명시적 승인이다. 그 범위를 넘어 다른 형제를 임의로 열지 않는다. - fresh-call과 resume-call 모두 한 요청당 하나다. batch, retry loop, watcher, supervisor를 만들지 않는다. `resume-unobserved`도 미관측이라는 결과이지 재시도 신호가 아니다. - dead/dormant citizen에게 delivery는 닿지 않는다. peers에 보인다는 사실은 dispatch 초대도, resume 초대도 아니다 — dormant pi를 되세우는 것은 GLG가 요청할 때뿐이다. - callback을 기다린다는 이유로 polling하거나 private transcript를 읽지 않는다. - raw tmux screen text와 `send-keys`를 delivery/identity 증거로 쓰지 않는다. - commit, push, release 권한을 이 스킬 호출에서 추론하지 않는다. role/implementation 권한도 launch·callback·formation 보고에서 추론하지 않는다 — 인간 grant뿐이다. - 어떤 reject도 success로 포장하지 않는다.
GitHub에서 보기