[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M6DM01ZTDMEMW1PCTS4F78TZ":3,"skill-same:01M6DM01ZTDMEMW1PCTS4F78TZ":67},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":16,"categories":17,"keywords":28,"publishedAt":34,"linkOnly":35,"markdownContent":36,"markdownBody":37,"frontMatter":38,"refName":47,"commitSha":48,"skillDirectory":49,"forksCount":50,"repositoryHtmlUrl":51,"repositoryHomepageUrl":6,"ownerHtmlUrl":52,"ownerBlogUrl":6,"ownerDescription":6,"updatedAt":53,"install":54,"resources":66},"01M6DM01ZTDMEMW1PCTS4F78TZ","design",null,"에이전트 팀을 활용한 기능 설계 토론 진행","Nharu\u002Fcc-cmds","Nharu","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F14357133?v=4","01M6DKV0D72FEBQABDAGSZ021P","nano","01M6DKV0TVG5GV22WQZBNRZ3ZT",3,"MIT","https:\u002F\u002Fgithub.com\u002FNharu\u002Fcc-cmds\u002Fblob\u002Fmaster\u002Fplugins\u002Fcc-cmds\u002Fskills\u002Fdesign\u002FSKILL.md",[18,23],{"categoryNo":19,"categoryName":20,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000015","视觉设计","SCENARIO","使用场景",{"categoryNo":24,"categoryName":25,"taxonomyType":26,"taxonomyTypeDesc":27},"01JBSEEDCAT000000000000032","设计师","PROFESSION","适用职业",[5,29,30,31,32,33],"cc","task","true","한국어","텍스트","2026-11-10 10:12:30",false,"---\nname: design\ndescription: 에이전트 팀을 활용한 기능 설계 토론 진행\nwhen_to_use: 사용자가 새 기능 설계\u002F아키텍처 결정\u002F다관점 검토가 필요한 설계 논의를 요청할 때\ndisable-model-invocation: true\nusage: \"\u002Fcc-cmds:design \u003Ctask>\"\noptions:\n    - name: \"\u003Ctask>\"\n      kind: positional\n      required: true\n      summary: \"설계 토론을 진행할 작업 주제 (자유형 한국어\u002F영문 텍스트).\"\n---\n\nConduct a design discussion using an agent team for the given task.\nAll team discussions and inter-agent communication should be in English to optimize token usage.\nUser-facing communication (interviews, final presentation) and saved documentation should be in Korean.\n\n## Control-Flow Invariants\n\nThese phase-transition rules govern turn-yielding and MUST stay near the top of\nthis file. Post-compaction reattaches only the first ~5K tokens with priority;\na summarized-away transition rule causes silent mis-transition — waiting for the\nuser where the skill must auto-advance, or prompting where it must yield.\n\n### CFI-1a — Leg dispatch is a turn-ending act\nAfter the user approves the Step 2 composition, the seat (this conversation)\nwrites the interview brief, launches the discussion leg — the sibling skill\n`design-discuss-unattended`, which runs Step 3 and Step 4 through the save in\nits own session — records the pending leg in `leg.json`, and then YIELDS the\nturn. Nothing downstream of Step 4 runs at dispatch time. The dispatch form is\npart of this invariant: it is a **harness-tracked background call**, never a\ndetached form (`nohup`, a bare `&`) and never a foreground call — only the\ntracked form wakes the seat, and a foreground call the harness later moves to\nthe background dies with the seat. Yielding is safe here and fatal in a\nprint-mode shard: a conversational seat survives its own yield and receives the\nnext wake-up, whereas a print-mode process (`autopilot-router-shift` and its\nkind) ends at the yield — so do not rewrite this yield as a hold.\n\n### CFI-1b — The leg's completion wake-up is not a turn-ending act\nThe wake-up is a hint, never the channel: push completion signals drop,\nduplicate, mis-route, and after a seat restart the background handle is an\norphan nobody re-arms. The **pull-check that is the first act of every turn**\n(Step 2, `Leg pull-check`) is by construction the only channel. **The check is\nactive exactly while `$STATE\u002Fleg.json` exists and its `state` is `pending` or\n`parked`** — this sentence is the one definition of that condition, and every\nother mention points here. `done` is written by the seat alone, when it\nconsumes a completion artifact, so a consumed completion switches the check off\ninstead of being read a second time. What completes depends on the marker's\n`phase`. On `discuss`, when the check finds the leg's **artifact predicate**\ntrue — the design document exists, its ledger parses, every non-aborted roster\nrow is `done`, and `presentation.md` exists with a matching header version (an\nexit code is not part of the predicate) — the seat renders the three\n`presentation.md` blocks verbatim, moves the file aside, and continues **in the\nsame turn** into Step 5 (Unresolved Issue Walkthrough), without yielding and\nwithout any user prompt. Rendering the results is NOT a turn-ending action. On\n`resume`, completion is `coherence.md` with a matching header, and it returns\nthe seat to Step 7 — never to Step 5, which CFI-3c forbids once Step 7 has\nbegun. When the predicate is false the seat goes to recovery and does not enter\nStep 5.\n\n### CFI-2 — Step 6 entry: automatic arrival, then notice-and-yield\n(a) ARRIVAL (transition): reaching Step 6 (Plan Refinement) is automatic —\n    Step 5 → Step 6 needs no user prompt. Do not stop on the way in.\n(b) FIRST ACTION: once at Step 6, the lead emits ONE short Korean notice that\n    refinement is starting (inviting the user's input), then YIELDS the turn and\n    waits for the user to speak first. At Step 6 ENTRY do NOT call\n    AskUserQuestion to open the discussion or manufacture a refinement question\n    — no question tool, no options menu, no \"무엇을 다듬을까요?\" prompt; Step 6\n    opens as a plain yield.\n(c) SCOPE: this prohibition is the ENTRY moment ONLY; it does NOT restrict\n    AskUserQuestion elsewhere — the Step 6 state-check's slug-ambiguity prompt\n    (fires before the entry notice, during pre-entry cleanup) and Step 6's later\n    \"propose a new team\" approval path remain valid, as do all Step 4\u002FStep 5\n    AskUserQuestion uses.\n\n### CFI-3 — Step 6 exit → Step 7 is automatic; the Class C pass is single-pass and terminal\n(a) EXIT (transition): Step 6 ends when the user signals the plan is\n    satisfactory (lead judgment on the reply, no regex — the same class of\n    read as Step 5's abort detection). That signal enters Step 7 (Class C\n    Coherence Pass & Freeze) in the SAME turn: no prompt, no AskUserQuestion,\n    no turn-ending \"완료했습니다\". Ending the turn on the satisfaction signal is\n    a mis-transition — Step 7 would never run and an un-cohered document would\n    reach the downstream audit.\n(b) NON-RECURSION: Step 7 runs the coherence pass EXACTLY ONCE over the final\n    text. Its own corrections are never re-submitted for another pass.\n    Re-running it, or looping it until \"clean\", reproduces inside `design` the\n    unbounded review loop this pipeline removed.\n(c) FREEZE \u002F TERMINAL: when Step 7 completes the document is FROZEN — `design`\n    makes no further edits to it, and there is no path back to Step 5 or Step 6.\n    Further refinement is a new `\u002Fcc-cmds:design` invocation, which runs its own\n    Step 7 before freezing again. Every post-freeze edit re-opens the induced-\n    defect rate that the downstream Class S audit's guarantee rests on.\n(d) NOT A ROUND CAP: this invariant fixes the freeze and the non-recursion\n    discipline. It carries no numeric round budget — do not add one here.\n\n### CFI-4 — A seat whose next duty another SESSION owns may only wait or recover\nWhile `leg.json` names a leg that has neither completed (artifact predicate\nfalse) nor parked (no `park.md`), the seat's only lawful actions are to wait or\nto run the recovery ladder of the pull-check. It never re-dispatches (two legs\non one ledger) and never enters Step 5. The owner is a **session**, not a\nprocess: the leg parks and exits, so no process existing while the duty stands\nis the normal state.\n\n## Workflow\n\n### Step 1: Requirements Interview & Codebase Exploration (Korean)\n\n- Do NOT create a team yet. First, interview the user to understand requirements. **Read `${CLAUDE_SKILL_DIR}\u002F..\u002F_common\u002Frequirements-interview.md`** and follow it for the whole interview — the depth, the discipline, issue-originated design, reproduction-first, verification-first and the closing read-back all live there. The bullets below are this skill's own wiring of that interview into the steps that follow.\n- **Reproduction hand-off.** When the lead judges that reproduction should not be done inline, it is delegated to a Step 3 reproduction agent — proposed as the reproduction agent role in Step 2, which drives Step 3's Round 0.\n- **Reproduction data points feed Step 4.** The four reproduction data points carry the same labels as the `## 재현·근본원인` section schema in Step 4, so Step 4 can fill that section verbatim.\n- **Tier-2 feeds Step 4.** Tier-2 of the reproduction fallback (and only Tier-2) triggers the lead to create an unresolved-issue pointer during Step 4 synthesis (see Step 4).\n- **Delivery shape (five questions only the user can answer).** Ask these during the interview whenever the work could land as more than one pull request or touch more than one repository: **which repositories** the change lands in (remote slug, not a path — paths differ per machine and per worktree); **how many slices** it should land as; **where an apply happens**, if anywhere; **who runs that apply** — the pipeline or a person; and **what parks** if an apply fails (the blast radius, which defaults to the whole repository and may only be narrowed). These five are knowledge the user holds and nothing in the codebase does, and this interview is the only place a human is present to give them. Their answers become the `## 구현 슬라이싱` section of Step 4's document, which downstream orchestration parses **mechanically** rather than inferring — so an unanswered question here is not a gap that gets filled later, it is a section that never exists and a plan that silently falls back to being re-derived by a model.\n- **Base design suggestion.** When the interview shows the request splitting into pieces that each still need their own design judgment — the same criterion the autopilot entry judgment uses for a base run — show one Korean note proposing `\u002Fcc-cmds:design-base` (a base design: the contracts between the pieces and a ticket split, each ticket designed later on its own) and let the person choose: `AskUserQuestion` with `이대로 단일 설계 계속` ← 추천 · `중단 — \u002Fcc-cmds:design-base 로 다시 시작` (등급 2 — the scope of the work is the person's to decide). Nothing switches or calls automatically; on the second option end the workflow with that command line.\n- **Base linkage.** When the argument or the interview points at a ticket of a base design (`\u003C문서>.md#T\u003Cn>`, or a tracker reference the registry knows), **read `${CLAUDE_SKILL_DIR}\u002F..\u002F_common\u002Fbase-linkage.md`** and resolve it as it says — asking the person where it resolves to 「찾지 못함」 or 「재앵커링 불가」 or the hash disagrees. A resolved ticket puts a `## 베이스 제약` section into the Step 4 document, before `## 합의된 아키텍처`, with the ticket block and its contract blocks copied verbatim, and puts as the first line of `## 합의된 아키텍처` the fixed sentence 「이 문서의 `## 베이스 제약` 절에 옮긴 티켓 블록과 계약 블록은 이 절의 결정과 똑같이 구현을 구속한다.」 — that is what binds the section for the attended `implement`, whose binding tier is named by section and does not list it; the design never changes that section. Step 4 runs in the leg, which writes that section only when the brief names the ticket, so a resolved ticket goes into the brief as three lines (dispatch item 1 below).\n- **Verification profile feeds Step 2.** A verifiable claim that cannot be settled during the interview is kept for residual encoding at Step 4 synthesis. If Step 1 reveals a verification-heavy profile (multiple (c) external facts, expected (d)\u002F(e) experiments, feasibility questions already visible), flag it so Step 2 can seed a dedicated verification agent.\n- **The read-back and the issue merge feed the brief.** The confirmed closing read-back and any issue-merge decision are what the brief's `## 요구사항` block carries to the discussion leg (dispatch item 1 below).\n\n### Step 2: Team Composition Proposal (Korean)\n\n- Based on interview results and codebase exploration, propose a team composition to the user.\n- **How many roles**: bounded by `_common\u002Fagent-team-protocol.md`'s `### Team size budget`. Read the ceiling **and its coordinator-class carve-out** there — this step deliberately states no number of its own, so the budget cannot drift into two values.\n- Specify each teammate's role, exploration scope, and model (use short aliases: `\"opus\"`, `\"sonnet\"`, `\"haiku\"`). Propose `sonnet` for every teammate by default. Propose `opus` only when the work that teammate takes on needs it, and write that reason on the teammate's own line of the Korean proposal, so the approval is given with the reason in view. The reason is about the work; the size or importance of the task is not a reason. The person may change any model when approving, and a second opinion on promotion stays with `\u002Fcc-cmds:design-upgrade`.\n- **Reproduction agent role (optional, issue\u002Fbug tasks)**: if the reproduction-first filter test (Step 1) is YES and the lead judges a dedicated reproducer is better than reproducing inline, propose a **reproduction agent** as one of the roles. Its scope is: reproduce the symptom, emit the same four data points + `근거 등급` as Step 1, and — as a precondition of broadcasting — clean up and verify the tree (revert instrumentation, delete out-of-tree artifacts, confirm `git status --porcelain` == baseline) *before* findings leave it. This agent drives Step 3's Round 0 (below).\n- **Verification agent role (default on, parallel to the reproduction agent)**: propose a **verification agent** as one of the roles by default, not only when Step 1 anticipated a verification-heavy profile. The seat is not a domain perspective — it is the seat that settles claims against reality. On the small row selected by the gate below it **replaces** the second domain seat (domain 1 + verification 1); on larger rows it is an **addition**. **It is counted, not carved out** — the carve-out in `_common\u002Fagent-team-protocol.md` is for orchestration roles, and this seat's job is measurement. So the seat occupies a roster row like any other, and the largest row is **three domain seats plus the verification seat** — four rows, not five. When three domain perspectives are genuinely not enough, do **not** fold a domain into the verification seat (it would do both jobs worse); take the scope back to the user, as the budget rule does above its own ceiling. Its scope is: settle assigned verifiable claims per `_common\u002Fverification.md`, pre-register each claim's `주장` + `기대 결과` before running, and — as a precondition of broadcasting a verdict — clean up and verify the tree (the two-command boundary gate; for (e), `git worktree remove --force` + `git worktree prune` + the record check of `_common\u002Fverification.md` §6.2 — every recorded path gone and no entry carrying this team's owner token) *before* the verdict leaves it. The Quality Gate can hold a gated proposal and route its claims to this agent. Same cleanup-before-findings-leave precondition + worktree-teardown duty as the reproduction agent.\n- **Disclose the leg's permission posture in the proposal, so the approval covers it.** The leg runs under `--permission-mode bypassPermissions` — a human decision already taken for this skill, not a per-run question — but the seat is granting that posture to a child process nobody watches, so the proposal carries one Korean line naming the posture and its blast radius, verbatim: *\"승인하시면 설계 토론(Step 3·4)은 별도 헤드리스 세션에서 권한 확인 없이(`bypassPermissions`) 실행됩니다 — 그 세션과 팀원은 이 계정이 쓸 수 있는 모든 경로에 쓰고 Bash·의존성 설치·웹 조회·에이전트 생성을 확인 없이 실행하며, 파이프라인 게이트는 걸리지 않고 코드 무수정 규칙은 지시문으로만 지켜집니다.\"* An approval of a proposal that lacked this line is not an approval of the posture, and the dispatch below does not proceed on it. The approval time is recorded in `leg.json` (item 3 of the dispatch block).\n- Only create the team after the user approves the composition. **On the normal path the seat does not create the team itself** — it hands the approved composition to the discussion leg below, and the leg spawns the team inside its own session.\n\n#### Leg dispatch (after approval — the seat launches the discussion leg)\n\nStep 3 and Step 4 through the save run in a separate headless session, the **leg**, because the Step 3 rounds and the Step 4 fidelity pass dispatch into the same ledger rows and a same-key resume of a live member (a send-back, a nudge, Case 1 or Case 3) is addressable only from the session that dispatched it, so Step 3 and the pass must share one session, and the seat's own context is what the split keeps below the compaction threshold. The seat hands the leg everything Step 1 and Step 2 produced that is on disk nowhere else, then yields (CFI-1a).\n\n1. **Write the interview brief.** Read `${CLAUDE_SKILL_DIR}\u002F..\u002F_common\u002Fsidecar.md` `## 1` and write `\u003Cbase>\u002Fdocs\u002Fdesign-brief\u002F{slug}.md`, where `{slug}` is the folded document key of §1.1 for the document this workflow will save (`docs\u002F{topic-slug}.md` → `docs-{topic-slug}`; the document need not exist yet — the key is derived from the path) and `\u003Cbase>` is the main worktree root. Line 1 is an H1; line 2 is the machine header, verbatim: `\u003C!-- cc-design-brief v1; writer=design; reader=design-discuss-unattended; owner-doc=\u003Cdocument key>; NOT a design doc; mechanism-local, never staged by a skill -->`. Then exactly these eight blocks, in this order, each a `## ` heading: `## 요구사항` (the interview's requirements and any issue-merge decision; when Step 1's base linkage resolved a ticket, also three field lines — `**베이스 문서**: \u003Cbase document path>`, `**티켓**: T\u003Cn>`, `**베이스 sha256**: \u003Cwhole-file sha256 of the base document, measured at resolution>` — which are what the leg re-measures before it spawns and what makes it write `## 베이스 제약`; without them the section is not written and nothing warns) · `## 제약` · `## 배포 형상` (the five delivery-shape answers as five field lines — `**레포**`, `**슬라이스 수**`, `**적용 위치**`, `**적용 주체**`, `**실패 시 파킹**` — writing `없음` where an answer does not apply; an omitted line and a negative answer are different facts, so no line is omitted) · `## 탐색 결과` (codebase exploration findings) · `## 재현` (the four reproduction data points and `근거 등급`, or `없음`) · `## 팀 구성` (the approved roster: role, scope, model per member) · `## 기준선` (the pre-workflow `git status --porcelain -z` output, verbatim — assertion 1 of the two-command boundary gate compares against this and the leg cannot re-derive it once the tree has moved) · `## 대상` (five field lines: `**topic-slug**`, `**문서 키**`, `**접힌 슬러그**`, `**docs 대상 디렉터리**`, `**검증 편중 프로필**`). The file's last non-empty line is the terminator `\u003C!-- cc-design-brief: end -->`. Write it with the atomic form of `sidecar.md` §1.3 (same-directory `mktemp`, whole-file `mv`). **Never stage it** — the brief stays out of the index by this skill's discipline, not by a `.gitignore` edit.\n2. **Prepare the state root.** `STATE=\"${XDG_STATE_HOME:-$HOME\u002F.local\u002Fstate}\u002Fcc-cmds\u002Fdesign\u002F{slug}\"`; `mkdir -p \"$STATE\"`. If `$STATE\u002Fleg.json` already exists, compare its `brief_sha256` with the sha256 of the brief just written: different means a stale marker from an earlier workflow — move it aside to `$STATE\u002Fleg.stale.\u003CISO8601>.json` and continue (CFI-4 does not apply to a stale marker); identical means a leg for this very brief is already pending — do not dispatch, go to the pull-check below (CFI-4).\n3. **Mint the session id and write `leg.json` first.** `LEG_SID=$(uuidgen | tr 'A-Z' 'a-z')`, then write `$STATE\u002Fleg.json` (atomic form) **before** launching: `{ \"slug\", \"session_id\", \"phase\": \"discuss\", \"state\": \"pending\", \"dispatched_at\", \"heartbeat_at\", \"redispatch_count\": 0, \"brief_sha256\", \"leg_out\": \"$STATE\u002Fleg.\u003Csession_id>.out\", \"leg_err\": \"$STATE\u002Fleg.\u003Csession_id>.err\", \"prior_session_ids\": [], \"transcript_bytes\": 0, \"leg_json_mtime_at_dispatch\", \"permission_posture\": \"bypassPermissions\", \"posture_approved_at\" }`. `permission_posture` and `posture_approved_at` (the time of the Step 2 approval whose proposal carried the posture line) record that the posture was approved rather than assumed; a marker lacking either names a leg dispatched without that decision. The progress baseline (transcript size 0, this file's own mtime) is written in the same write so the first pull-check has something to compare against. Spelling rule: a harness-owned identifier keeps the harness spelling (`session_id`, as the `-p` result object names it); fields this design coined are snake_case. **No pid is recorded** — the liveness oracle below carries it.\n4. **The launch line.** Every preflight line is a hard stop, because every failure it catches otherwise presents as `exit 0` · `subtype success` · no artifact — the one shape nobody can debug afterwards. Fill nothing in by hand except what the seat computes above; the block carries no placeholders.\n\n    ```bash\n    mkdir -p \"$STATE\"          # leg.json is written here first, so this comes first\n    : \"${CLAUDE_CONFIG_DIR:?CLAUDE_CONFIG_DIR is unset - refusing to launch the leg}\"\n    CLAUDE_CODE_PRINT_BG_WAIT_CEILING_MS=14400000\n    CLI=$(type -P claude)      # absolute path: a bare `claude` is intercepted by this machine's shell guard\n    PLUGIN_DIR=\"${CLAUDE_PLUGIN_ROOT:-$(cd \"${CLAUDE_SKILL_DIR}\u002F..\u002F..\" && pwd)}\"\n    [ -x \"$CLI\" ]        || { echo \"leg: CLI not executable: $CLI\" >&2; exit 2; }\n    [ -d \"$PLUGIN_DIR\" ] || { echo \"leg: plugin dir missing: $PLUGIN_DIR\" >&2; exit 2; }\n    [ -n \"$LEG_SID\" ]    || { echo \"leg: no session id minted\" >&2; exit 2; }\n    [ -n \"$CLAUDE_CODE_PRINT_BG_WAIT_CEILING_MS\" ] \\\n                         || { echo \"leg: wait ceiling unset - the team would be killed at 600s\" >&2; exit 2; }\n\n    CLAUDE_CONFIG_DIR=\"$CLAUDE_CONFIG_DIR\" \\\n    CLAUDE_CODE_PRINT_BG_WAIT_CEILING_MS=\"$CLAUDE_CODE_PRINT_BG_WAIT_CEILING_MS\" \\\n    \"$CLI\" \\\n      --plugin-dir \"$PLUGIN_DIR\" \\\n      --session-id \"$LEG_SID\" \\\n      --model opus \\\n      --effort high \\\n      --permission-mode bypassPermissions \\\n      --dangerously-skip-permissions \\\n      --output-format json \\\n      --strict-mcp-config \\\n      -p \"\u002Fcc-cmds:design-discuss-unattended docs\u002Fdesign-brief\u002F{slug}.md\" \\\n      >> \"$STATE\u002Fleg.$LEG_SID.out\" 2>> \"$STATE\u002Fleg.$LEG_SID.err\" \u003C \u002Fdev\u002Fnull\n    ```\n\n    Why each element is there:\n\n    | element | failure without it |\n    | --- | --- |\n    | `$CLI` absolute path | this machine's shell guard intercepts a bare `claude`, exits 1 and creates no session at all — the only non-zero phenotype |\n    | `CLAUDE_CONFIG_DIR:?` | an empty value lands in an account-less config dir, and the liveness oracle below can only see legs launched under the same config dir |\n    | the wait ceiling | print-mode wind-down kills the team at the default 600 s ceiling and exits 0 |\n    | `--plugin-dir` | the slash command resolves to nothing: exit 0 · `subtype success` · `num_turns 0` · `Unknown command:` |\n    | a fresh `--session-id` per dispatch | the transcript is the progress oracle and must be findable; a reused id is refused |\n    | `--output-format json` | the only source of `permission_denials`, `subagent_stats.killed.system`, `num_turns` |\n    | `--strict-mcp-config` | the leg needs no MCP server; loading them costs startup time and context |\n    | both streams into `$STATE`, per-attempt file names | the ceiling marker is on stderr, every other marker on stdout; after a seat restart these two files are the only evidence, and appending attempts into one file makes every attribution predicate match the previous attempt's bytes |\n\n    **Flags that must not appear**: `--setting-sources \"\"` (silently cuts the settings chain) · `--settings \u003Cfile>` (`-p` silently ignores a settings file that fails validation) · `--restricted` (removes Bash, which the two-command boundary gate uses) · `--continue` \u002F `-c` (inherits the seat's conversation) · `--fork-session` (mints a new id on resume and destroys the handle `leg.json` holds) · `--bg` (no push wake-up, so CFI-1b does not hold). The permission posture is a human decision already taken, and checkably so — disclosed with its blast radius in the Step 2 proposal the user approved, and recorded in `leg.json` as `permission_posture` and `posture_approved_at` (item 3). Without a posture the leg fails its first `docs\u002F{slug}.md` write and **reports success** — exit 0, `subtype success`, `is_error false`, a file never written.\n5. **Dispatch as a harness-tracked background Bash call** (`run_in_background: true`) — never detached, never foreground (CFI-1a). Immediately after dispatch emit one Korean notice — *\"설계 토론을 별도 프로세스로 파견했습니다. 진행은 매 턴 시작 시 확인합니다.\"* — and yield the turn.\n6. **The resume line** is the same environment, the same flags and the same stream redirections with `--session-id \"$LEG_SID\"` replaced by `-r \"$LEG_SID\"` and the `-p` prompt replaced by the message. \"Same flags\" includes the two redirections — without them a resumed leg writes to neither file and the attribution step has no input. **The message is never inlined on the command line.** Every message the seat resumes with carries backticks — the park answer template names its site in them, and the Step 7 notes are Markdown — and inside a double-quoted argument the shell runs each backtick span and `$( )` as a command, so the message would arrive silently rewritten while the leg still exits 0. The seat therefore writes the message with the Write tool to a same-directory temporary file and `mv`s it to `$STATE\u002Fresume.\u003CISO8601>.txt` (the atomic form of `sidecar.md` §1.3), sets `RESUME_MSG` to that path, guards it with `[ -s \"$RESUME_MSG\" ]`, and passes it as `-p \"$(cat \"$RESUME_MSG\")\"` — the output of a command substitution is not expanded again, so the bytes arrive as written. The file stays in `$STATE` as the record of what was sent. A resume keeps the session id and therefore keeps the team; a re-dispatch mints a new id and loses it. **Resume whenever the session is usable.**\n\n#### Leg pull-check (the first act of every turn while the check is active — CFI-1b)\n\nThe seat reads `$STATE\u002Fleg.json` before anything else, every turn, for as long as the check is active (CFI-1b defines when). The user's next message is the guaranteed wake-up; there is no watcher process and no push channel (CFI-1b).\n\n- **0 — Park.** If `$STATE\u002Fpark.md` exists and its header line matches `\u003C!-- cc-design-park v1; ` exactly, the leg is parked: render the record's `질문 문면`, its `선택지` labels and descriptions **verbatim** to `AskUserQuestion` — `등급 2` — composing nothing (the seat holds none of the discussion, so it cannot author options; the `_common\u002Faskuserquestion.md` conformance check is the seat's, as the tool's caller). In the same turn as the question, **consume the record**: move it to `$STATE\u002Fpark.answered.\u003CISO8601>.md` and set `leg.json` `state` back to `pending` (never delete it — the verbatim question must survive for tests and later readers). Without this consumption a parked leg never finishes: the predicate is file existence, so the same question would go out again next turn. When the answer arrives, write the neutral operational message to a resume file and resume the leg through the resume line (dispatch item 6 — never inlined) *\"park 질문 `\u003C자리 id>` 에 대한 사용자의 답은 다음과 같다: …\"* — neutral wording, because a \"remember this secret\"-shaped prompt is refused as injection while still exiting 0 — and classify the resumed turn as an artifact turn, not a terminal state.\n- **1 — Complete, branched on `leg.json` `phase`.** **`discuss`** — if the artifact predicate holds (CFI-1b; the header the predicate matches is `\u003C!-- cc-design-presentation v1; writer=design-discuss-unattended; reader=design; slug=\u003Cslug> -->`), render the three blocks of `$STATE\u002Fpresentation.md` — `## 고지`, `## 검증 집계`, `## 결과` — verbatim, **consume the record** the way step 0 consumes `park.md` — move it to `$STATE\u002Fpresentation.rendered.\u003CISO8601>.md`, never delete it — set `state: done`, and continue into Step 5 in the same turn. **`resume`** — complete when `$STATE\u002Fcoherence.md` exists and its first line is `\u003C!-- cc-design-coherence v1; writer=design-discuss-unattended; reader=design; slug=\u003Cslug> -->`; set `state: done` and continue Step 7 at its triage step (6) in the same turn. On this phase `presentation.md` is never consulted: it belongs to the discuss phase, and completing on it would re-enter Step 5 after Step 7 has begun, which CFI-3c forbids. **This step alone** separates real completion from a permission refusal or an injection refusal, which are indistinguishable from success in every machine-readable field.\n- **Three readings, none a substitute for another.** ⓐ **Artifact** (steps 0–1) decides success and is positive-only. ⓑ **Progress** — the leg transcript's size (`${CLAUDE_CONFIG_DIR}\u002Fprojects\u002F*\u002F\u003Csession_id>.jsonl`, globbed by session id; never re-derive the project key) plus `leg.json`'s mtime — decides whether anything is happening. ⓒ **Liveness** — `claude agents --json` queried **by `sessionId` only** (never by `kind`: a `-p` leg is listed as `\"interactive\"`, so a `kind == \"background\"` filter silently misses every leg), under the same `CLAUDE_CONFIG_DIR`; absence is not a death verdict. Liveness answers identity, not progress, so its duty is to **withhold writes**, never to suppress an alarm.\n- **2 — Progress reading.** Compare transcript size and `leg.json` mtime with the previous turn's record. **2a** either grew → record the new reading and do nothing this turn. **2b** both still, fewer than two consecutive turns → record and stop. **2c** both still for two or more consecutive turns → query the liveness oracle first: an entry means a process is alive in that session — neither resume nor attribute; no entry means the leg exited — go to attribution. **2d** still *and* alive for four or more turns → `AskUserQuestion` — `등급 2` — with exactly two options, **더 기다림** and **포기** (on 포기 the pid comes from the oracle entry just read — the design records none); this is not a park, because a park exists only where the questioner has no question tool.\n- **Attribution, 3–8 (launch-line defect vs. death).** The exit code carries one bit (zero \u002F non-zero) and nothing more; inside `exit 0` never branch on the exit code or on `subtype`. In order: **3 ceiling kill** — `leg.err` matches `Background tasks still running after`, or `subagent_stats.killed.system > 0` → raise the ceiling and `--resume` the **same session** (nothing is lost) · **4 unresolved slash** — `result` contains `Unknown command:` → fix `--plugin-dir`, launch with a **new `session_id`** · **5 permission starvation** — the transcript (session-id glob) carries `Claude requested permissions to … but you haven't granted it yet`; a non-empty `permission_denials` in `leg.out` is the same fact and, under the fixed posture, a canary that the posture did not take → fix the posture, new id · **6 the leg spent turns and declined** — `num_turns > 0`, `result` present, none of the signals above, **and `result` states a refusal or abort reason in words** (the known class is injection refusal) → fix the prompt wording, new id; **a `result` that states no reason, or a reason outside that class, is step 8, not step 6** · **7 no session at all** — exit 1, the shell-guard line → call the absolute path · **8 death** — no `result` object, or `is_error: true`, or the process vanished without a terminal state → read the transcript tail by session-id glob; a `rate_limit` \u002F 429 tail sets a wait before repair and changes nothing else. **Accounting**: 3–7 are launch-line defects, and re-entering after one does **not** increment `redispatch_count`; only step 8 descends the ladder. **Mint a new id only after attribution is finished** (a fresh id written first makes the session-id glob resolve to an empty session), and keep the previous id in `prior_session_ids`.\n- **The ladder (entered from step 8 only).** **Rung 1** — the session is usable → `claude -r \u003Csession_id>` (team preserved, counter unchanged). **Rung 1r — on `phase: discuss` only** — the transcript is missing or unusable → re-dispatch with a new `session_id`, the team is lost, the roster is rebuilt from the durable witness corpus (`$STATE\u002Fwitness\u002F`) — `INDEX.md`'s `lead`\u002F`sweep` row and `SWEEP.md` are not member roles and stay off it — `redispatch_count += 1`. The leg this launches finds the dead dispatch's early ledger stub, and that skill's target-document guard passes a stub while parking a saved document — which is what leaves this rung reachable in the states its purpose needs, since the corpus fills only as rows flip to `done` and rows exist only once a spawn has already written that stub. **On `phase: resume` rung 1r is forbidden.** By then `docs\u002F{topic-slug}.md` carries Step 5's walkthrough decisions and Step 6's refinements; a re-dispatched leg runs Step 1 through Step 4 from the start and saves over them, and the leg's boundary gate cannot catch it, because that skill's Step 2 exempts this exact path — an accidental re-save and a legitimate first save look identical to every assertion it makes. The new leg also knows no `phase`, so it writes `presentation.md` while the `resume` branch of step 1 above waits for `coherence.md`: the seat waits on an artifact nobody will write, and the bytes it was waiting to protect are already gone. Take Step 7's fallback (3') instead — the Step 3 roles respawned fresh at a new `epoch` from the durable witness corpus, the brief and the final document **by path**, with no save and no new leg; Step 7's precondition step names this as its second trigger. **The `brief_sha256` identical guard of dispatch item 2 does not reach this ladder.** It governs the Step 2 dispatch preparation, and nothing here re-runs item 2, so a rung-1r re-dispatch proceeds on an unchanged brief rather than being blocked by it. **What keeps a re-dispatch away from a saved document is neither the phase guard alone nor the leg's guard alone.** The phase guard forbids rung 1r on `phase: resume`, where a saved document exists by construction and no file need be consulted; on `phase: discuss` the leg's target-document guard is the one that looks at the file, and it parks on a saved document while passing an early stub. Neither stands in for the other — the phase guard reads no file, and the leg's guard reads no `phase`. **And a re-dispatch prompt is not the first dispatch's prompt.** Item 4's *no placeholders* fixes the **first** dispatch's block; a rung-1r prompt additionally names the corpus path (`$STATE\u002Fwitness\u002F`) and the recovery context — the prior `session_id`s and the incremented `redispatch_count` — because a leg told none of this rebuilds nothing and composes a fresh roster in place of the approved one. **Rung 2 — the floor.** At most **one** re-dispatch per design; a second rung-1r failure is **not** a question to the user but a demotion: the seat runs Step 3 and Step 4 itself, at today's cost from a worse starting point (Step 1, Step 2, N pull-check turns and at least one attribution already spent). The demoted seat's execution text is Step 3 and Step 4 of **this file**, read as the interactive procedure they are.\n\n#### Small-work gate (evaluated once on entering this step)\n\nA single-surface change with no contract change does not need a full design team. Evaluate this before composing, from the **Step 1 interview product** — this skill receives no entry-plan (the kickoff hands over a command string, nothing more), so the three inputs are read from what the interview settled: the surface count and any contract\u002Fschema change from the requirements and constraints, and the target-repository count from the delivery-shape answers. The inputs are defined the same way as the kickoff's tier judgment, so the tier and the roster cannot disagree on what they measure; when the user invokes this skill directly without a kickoff, the gate fires on the same inputs.\n\n**Risk indicators outrank the size row.** If any indicator fires — a public contract or shared schema change, a public API surface, a DB schema, auth\u002Fauthorization, an external service integration, async\u002Fconcurrency — compose for that risk no matter how small the surface is, and this gate does not narrow the team.\n\n**When it fires**: no risk indicator fired **and** the work is a single surface in a single target repository. Compose from the small row — **one domain seat plus the verification seat** (two roster rows, the same roster `design-lite` runs; the budget counts one domain perspective here, and the budget has no floor) — instead of a larger default row, and state the narrowing in one line of the Korean proposal so the user sees it rather than discovering a thinner team.\n\n**Floor.** This gate selects among composed rows that each carry at least two roster rows — one domain seat and the verification seat — so it cannot yield an empty roster; an empty roster is not a saving but a hard stop, because the ledger stub is created at spawn time and every resume path fail-closes on a missing or unparseable ledger. The floor belongs to the roster contract in `_common\u002Fagent-team-protocol.md` alongside the team-size ceiling; do not write a second floor rule here.\n\nThe kickoff's design tier is `solo` or `team-4`. A `team-4` plan whose `design_path` is `discuss-audit` is dispatched with this roster as `design-discuss-unattended`, and one whose `design_path` is `solo-audit` goes to `design-solo-unattended`, with no roster; `solo` is not a row of it — it is `design-solo-unattended`, a headless lead with no team, and it is only named here so that nobody builds it as a zero-member team.\n\n### Step 3: Design Discussion (English, internal only)\n\n**Executed by the leg, not the seat, on the normal path.** After the dispatch block above the seat yields (CFI-1a); Steps 3 and 4 through the save run inside `design-discuss-unattended`, which Reads these two steps from this file and applies its own park substitution. The seat runs them itself only at the recovery ladder's floor.\n\n**Before assigning any team work, Read `${CLAUDE_SKILL_DIR}\u002F..\u002F_common\u002Fagent-team-protocol.md`.** Apply the completion-signal instruction and facilitator rules from that file throughout this step. When you dispatch or resume each member, embed the **task-assignment header** from `_common\u002Fagent-team-protocol.md` verbatim at the top of each dispatch\u002Fresume prompt. Every new `round\u002Fphase` key — each discussion round, the Step 4 fidelity pass, the Step 7 coherence pass — is a fresh background `Agent` dispatch carrying what the protocol's `## Multi-round` lists for a boundary dispatch; only a re-request inside one key resumes the same `agentId`.\n\n**Re-entry notes.** This skill opts in to the protocol's `### Parameter — re-entry notes (opt-in)`; append this clause verbatim after the task-assignment header in every member prompt:\n\n**Re-entry notes (MUST)**: directly above your `peer-read:` lines (directly above your sentinel when you have none), put a section that starts with the heading `## Re-entry notes`, at most 20 lines and 2,000 bytes, one entry per line — `path:line — why` for a place you would open first if you came back to this work, or one command you would re-run. No findings and no verdicts in it. The next dispatch of your role reads it as the starting point of its re-exploration.\n\n- Spawn each approved member as a nameless background task — `Agent({ subagent_type: \"claude\", run_in_background: true, prompt: \u003Cself-contained assignment> })` — and record each returned `agentId` in the ledger immediately. **Stamp `epoch`** (`max(disk epoch, 0)+1`, re-derived from the on-disk ledger — never an in-context counter; this Step-3 discussion team is the first team → `epoch 1`) **and the round-1 `witnessNonce`** on every one of its rows in the same at-spawn recording window as `agentId`\u002F`scratchDir`, per the protocol Spawn section. The `{topic-slug}` is no longer a harness team name, but it remains the output doc filename (`docs\u002F{topic-slug}.md`) and the ledger key (e.g., `auth-flow`, `payment-system`).\n- **Early ledger stub (at spawn time)**: create the output doc `docs\u002F{topic-slug}.md` as an early stub — an H1 title plus the ledger HTML-comment block `\u003C!-- cc-design-ledger v3 … -->` placed right after the H1 and before the first `##`. Each ledger entry is behavior-bearing. Entry schema — the column list, the `state` domain, the per-row transient set and its terminal-strip rule (including the `epoch` exemption) — is defined once in `_common\u002Fagent-team-protocol.md`'s Role↔agentId ledger v3 and is not restated here. `scratchDir` is the member's out-of-tree witness directory, recorded at spawn with the same immediacy as `agentId`. Update it on every state change. This uses the same `docs\u002F{topic-slug}.md` path as the Step 4 save (the two-command worktree gate already exempts that path — no baseline re-capture needed). **On entering any later phase (synthesis fidelity pass, Step 5, Step 6, Step 7 coherence pass), re-read the ledger from disk** — do not trust in-context copies; a missing or unparseable block is fail-closed via `AskUserQuestion`. The ledger block is **off-limits to synthesis and fidelity-pass content Edits** (whose targets are the enumerated canonical SOTs — `근거 등급` \u002F `검증 기록` `관측 결과` \u002F `## 재현·근본원인` `관측된 증상` — never the comment block); only ledger-state mutations (running→done\u002Faborted, round, thinReturns) write to it.\n- **Witness scratch dir (parameters for `_common\u002Fagent-team-protocol.md`)**: before the first spawn, run the protocol's `## Spawn` command — `\u003Cplugin root>\u002Forchestrator\u002Fcc-team-witness-init.sh {topic-slug}` (no `bash` in front — see the protocol's note) — and record the **printed path, literally** (not `$WITNESS_DIR`) as each member's `scratchDir` in the ledger at spawn time. Each member publishes its round product as `${scratchDir}\u002F{role-slug}.{round\u002Fphase}.md` per the protocol's write discipline (atomic `mv -n` + sentinel\u002Fnonce). **Witnessed surfaces** — explicitly: every Step-3 discussion round (`{role-slug}.round-N.md`), the Step-4 synthesis fidelity pass (`{role-slug}.fidelity.md`), the Step-7 Class C coherence pass (`{role-slug}.coherence.md`), and each Step-5 walkthrough \u002F Step-6 refinement **fresh** team (each fresh team gets its **own** directory from a fresh run of the `## Spawn` command above — never a hand-written `mktemp -d`, which the protocol forbids — recorded in its rows' `scratchDir`). Entirely lead-local phases (lead-only doc Edits, the pre-save sweep) are exempt; the sweep leaves no witness, and the lead writes only `SWEEP.md` into the corpus itself (Step 4 `**Pre-save sweep**`).\n- All inter-agent discussion and reasoning should be conducted in English.\n- NO code modifications allowed. Design discussion only.\n  - (observation & verification carve-out: running the unmodified app\u002Ftests, and out-of-tree \u002F isolated-worktree experiments, are not modifications — see `## Constraints` → \"Observation & verification carve-out\".)\n- **The lead acts as a facilitator**, actively driving multi-round discussion. Do NOT passively wait for results and move on.\n\n#### Discussion Protocol (rounds per the shared Round budget)\n\n0. **Round 0 — Reproduction grounding pass** (only when a reproduction agent is on the team): the reproduction agent reproduces the symptom (with artifacts present), captures the observation in its report text, then **reverts\u002Fdeletes the artifacts → verifies `git status` is pristine → and only then broadcasts** the grounding report to the whole team. Cleanup-and-verify is a *precondition* of the broadcast (findings must be clean before they leave the producer). Round 0 is a grounding pass and **does NOT count against the shared `### Round budget`** (`_common\u002Fagent-team-protocol.md`). The reproduction agent stays active through Cross-Review, challenging whether each proposal actually addresses the reproduced cause, and converges by returning like any member.\n   - **Round 0 failure path**: if the reproduction agent fails to reproduce, it broadcasts a `가설(추측)` grounding report with `재현 차단요인` filled. Tier-1\u002FTier-2 escalation is owned by the **lead** (the agent cannot call AskUserQuestion — it only surfaces the blocker; the lead decides whether to ask the user for help and, on Tier-2, creates the Step 4 unresolved-issue pointer). The Quality Gate's \"hypothesis + blocker → proceed\" branch (below) is exactly this failure-acceptance path.\n1. **Round 1 — Initial Proposals**: Spawn each member with their design scope. Confirm each member's round-1 witness via `witness_present`, then read the witness (never the return), before proceeding — a member's proposal is delivered by its witness, not its return text.\n2. **Quality Gate**: Before proceeding to cross-review, verify each proposal meets minimum depth:\n   - References specific files, modules, or patterns from the actual codebase (not generic advice)\n   - Includes concrete design decisions with rationale (not just listing options)\n   - If a proposal is too shallow or generic, send it back with specific questions asking for deeper analysis\n   - **Reproduction addendum** (when a reproduction agent is present): Round 1 proceeds only after the Round 0 grounding report carries a `근거 등급` (either `확인됨(재현·관측)` with observed evidence, OR `가설(추측)` with `재현 차단요인`) **and** the tree is pristine-verified. Reject a grounding report that is a code-reading guess with no attempt-to-run, or one that left artifacts in the tree.\n   - **Verification addendum** (sister to the Reproduction addendum; applies on Round 1 and every Round 2+ revision forward). Reject (send back) on ANY of: (1) a load-bearing claim passes the filter test but carries no `검증 등급` tag (a tripwire-phrase hit counts); (2) a `미검증`-tagged claim reaching cross-review (disposition: send back \"verify or re-justify the reclassification\", or hold + route to the verification agent); (3) a `검증됨(통과)`\u002F`반증됨(실패)` tag with no recipe + observed value — a verification claim without evidence (isomorphic to the existing \"code-reading guess with no attempt-to-run\" rejection); (4) a clearly-filter-passing claim tagged `구현 시 검증` — the misclassification escape hatch (audit: `잔여 사유` token present + `차단 사유` specificity (\"ran out of time\" inadmissible) + on `구현 필요`, re-apply the filter test).\n3. **Cross-Review**: Dispatch each teammate afresh for the cross-review round with its own past witnesses and its peers' proposal witnesses named **by path** (`_common\u002Fagent-team-protocol.md` `## Multi-round` — the member Reads each whole; the lead does not restate them). Explicitly ask them to identify gaps, risks, contradictions, and alternative approaches. Each cross-review witness (`{role-slug}.round-2.md`) ends, above its sentinel, with exactly one **round-3 declaration** line on a line of its own: `round-3: none`, or `round-3: measure — \u003Cone measurement not yet run, and the disputed claim it would settle>`. That line is where a member names a measurement — the first entry to round 3 in the shared `### Round budget`. Ask each member, in the same dispatch, to revise its own proposal — its round-1 witness is among the own past witnesses the dispatch names — in the light of what it found and to state its final position in that witness: this one dispatch is both the cross-review and the convergence dispatch.\n   - **The shared convergence dispatch is folded into Round 2.** `_common\u002Fagent-team-protocol.md` `## Convergence` sends a separate convergence dispatch after cross-review; this procedure folds it into the Round 2 dispatch above, so the design team's convergence round\u002Fphase token is `round-2` and no separate convergence dispatch is sent. The folded dispatch carries no current-consensus or open-conflicts text, because the lead holds no consensus after Round 1: the peers' Round 1 witnesses named by path stand in that place.\n   - **A sweep refutation does not open Round 3 in this procedure.** The second entry path of the shared `### Round budget` (the lead's pre-save sweep refuting a claim) is carried out here as the author-only re-convergence of Step 4 `**Pre-save sweep**` (a focused exchange with the one affected author, once per claim), and the same holds in a team whose Round 3 a named measurement has already opened.\n4. **Round 3 (conditional)**: Confirm each member's cross-review witness via `witness_present` and read it (never the return). **Before deciding whether Round 3 opens, once every cross-review witness is in, check each one's declaration**: its last line that is exactly `round-3: none` or starts `round-3: measure — `, chosen across both forms. A witness with neither is a Case 3 non-conforming witness (`_common\u002Fagent-team-protocol.md`): re-instruct that member and take its `round-2-rev\u003Ck>` revision before going on. This check runs whether Round 3 opens or not. Then open Round 3 only when at least one Round 2 witness's declaration has the `round-3: measure — ` form. When it opens, dispatch every member's role once afresh for `round-3` with its own past witnesses and its peers' Round 2 witnesses named **by path** — together every Round 2 witness — (`_common\u002Fagent-team-protocol.md` `## Multi-round`), and ask each to run the measurements named and state its final position. How many rounds a team may drive follows the shared `### Round budget` and is not restated here. A sweep refutation reaches the second entry path through Step 4 `**Pre-save sweep**` instead: the sweep runs after synthesis and the fidelity pass, when Step 3 is already behind, and a new transition that re-dispatches the whole team would add back, at another point, the dispatch cost this procedure removes. That re-convergence stays as it is, and the corpus file `SWEEP.md` and the `스윕 반박` field of the `토론 패스` ledger row count it on an axis apart from Round 3.\n5. **Convergence Check**: Proceed to Step 4 when every member's last-round witness — Round 2 when Round 3 stayed closed, Round 3 when it opened — is `witness_present`. The declaration check and its Case 3 re-assignment already ran before the opening decision in item 4.\n\n**Evidence-grade label (`근거 등급`)**: for reproducible issue\u002Fbug tasks, the root cause carries a binary evidence grade — `확인됨(재현·관측)` (the recipe was actually run and the symptom observed) or `가설(추측)` (anything unrun\u002Funattempted\u002Fblocked). The field key is `근거 등급`, deliberately distinct from `상태` (the walkthrough's state field). The single source of truth is the `근거 등급` field of the saved doc's `## 재현·근본원인` section, **computed once at the reproduction discovery point** (Step 1 lead-driven OR Round 0 agent-driven — whichever path reproduced); every other location only *references* it. When a teammate's proposal builds on the reproduced cause, it carries a `[근거 등급: …]` prefix — this is label-only (it travels with the proposal as context), NOT a hard gate: a `가설(추측)` proposal is still discussable.\n\n**Verification discipline (`검증 등급`)**: parallel to the evidence grade, applied to any load-bearing claim the design rests on (the contract is `_common\u002Fverification.md`). The authoring teammate runs the severity pre-filter, then the single filter test, on each dependent assertion and attaches an inline `[검증 등급: …]` tag (same pattern as `[근거 등급: …]`; **inter-agent messages only** — saved-document marking uses the token-free anchor-reference convention `(§검증 기록 V\u003Cn>)`). A verifiable claim must reach `검증됨(통과)`\u002F`반증됨(실패)`, backed by a re-runnable recipe + an observed value, before it is carried into synthesis; a genuinely implementation-time-only claim is encoded as a residual item (`잔여 사유: 구현 필요`). **Linguistic tripwire**: a hedge on a decidable fact (\"should exist\", \"presumably\", \"구현 시 확인\u002F검증 필요\") is a confessed-unverified claim. **Routing (lead's delegated judgment, not a fence)**: the author verifies cheap one-command (a)\u002F(b) at proposal time; the Step 2 verification agent takes (c)-heavy \u002F expected (d)\u002F(e) \u002F feasibility questions; **all *failing* verifications and expensive (c)\u002F(d)\u002F(e) go back through re-convergence, never lead-solo** (a refutation changes the design after convergence). Claims discovered *mid-experiment* are recorded only (tagged `미검증` in discussion, routed at the next Quality Gate) — never auto-verified inline; the lead may allow one in-session re-entry per discovered claim, and a claim discovered while verifying a re-entered claim is residual-only (`잔여 사유: 검증 차단`, blocked reason \"recursion depth\").\n\n### Step 4: Result Synthesis & Documentation (Korean)\n\n- The lead synthesizes all discussion results into a structured Korean document:\n    - 재현·근본원인 (이슈·버그 수정 과제에 한해 최상단에 포함; 기능 설계 과제에서는 생략)\n    - 합의된 아키텍처\n    - 주요 결정사항과 근거\n    - 검증 기록 (세션 내 검증을 수행한 경우에 한해 포함; 수행이 없으면 생략)\n    - 미해결 이슈 \u002F 트레이드오프\n    - 구현 시 검증 항목 (잔여 검증 클레임이 있는 경우에 한해 포함; 없으면 생략)\n    - 테스트 설계 (대상 프로젝트에 테스트 환경과 기존 테스트 파일이 있는 경우 필수 포함; 둘 중 하나라도 없으면 생략)\n    - 구현 슬라이싱 (Step 1의 배포 형상 답변이 있는 경우에 한해 포함; 없으면 생략) — 이 표제를 쓰면 `권장 구현 순서`는 쓰지 않는다\n    - 권장 구현 순서 (구현 슬라이싱을 쓰지 않는 경우)\n- **Open entries carry `**구현 처분**`.** Every entry synthesis writes into `## 미해결 이슈 \u002F 트레이드오프` carries `**구현 처분**` and its companion field, chosen and written by `${CLAUDE_SKILL_DIR}\u002F..\u002F_common\u002Funresolved-closure.md` (`## 값 고르는 기준`, `## 작성자 꼴`); an entry the implementation would otherwise decide by itself is `구현 전 결정`.\n- **Runtime classification default.** If a runtime point in the product being designed maps unstructured input to a closed set of outcomes, Read `${CLAUDE_SKILL_DIR}\u002F..\u002F_common\u002Fruntime-classification.md` and apply it before finishing this step — it fixes the predicate, the two exits, and where the decision, the UR entry, and the R-item land. The predicate excludes judgment this same session makes about its own pipeline or design work (topology test, not this-repository test) — see the file.\n- **`## 재현·근본원인` section** (issue\u002Fbug tasks only — omitted for feature-design tasks). The section records the reproduction findings produced in Step 1 or Round 0 so the design rests on an observed cause, not a guess.\n    - **Placement & heading**: at the **very top** of the document, before 합의된 아키텍처 (for a bug fix the root cause is upstream of architecture and decisions). The heading is exactly `## 재현·근본원인` with **no leading section number** — `## 0.` \u002F `## 1.` etc. is forbidden because the fixed anchor `§재현·근본원인` (used by the Tier-2 pointer below) would dangle.\n    - **Fields**: `재현 절차` (a re-runnable recipe — literal commands or an inline fenced script, **no `\u002Ftmp` paths** since those are deleted, plus a `tracked-source 무변경 확인` note; if the observation depended on an out-of-tree driver\u002Finstrumentation, write that logic *inline as a fenced script* so the recorded recipe is self-contained and re-runnable) \u002F `관측된 증상` (\"미관측\" when only hypothesized) \u002F `근본 원인` (grade-neutral field name — whether it is confirmed lives in `근거 등급`, not here) \u002F `근거 등급` \u002F `재현 차단요인` (only when the hypothesis is due to a reproduction failure; carries `차단 사유` + `필요한 것`).\n    - **Grade acquisition**: `확인됨(재현·관측)` is earned ONLY when the recipe was actually run and `관측된 증상` observed; unrun\u002Funattempted\u002Fblocked is `가설(추측)`.\n    - **Multi-claim & mixed tasks**: if one section holds more than one reproduction claim, repeat each claim as a self-contained `### ` sub-block (each with its own `재현 절차`\u002F`관측된 증상`\u002F`근본 원인`\u002F`근거 등급` — the source of truth is per-claim), and a Tier-2 pointer targets that claim's sub-block anchor. A mixed task (bug fix + new feature) includes the section per-reproducible-claim: if any part of the task is a reproducible existing-misbehavior claim, the section is included (scoped to that part).\n    - **Grade propagation (one-way)**: the reproduction discovery point is the origin; Step 3 proposals carry a `[근거 등급: …]` prefix (label-only); `주요 결정사항과 근거` points at the grade by **referencing `§재현·근본원인`** (do NOT restate the literal grade token — no stored copy, prevents divergence); the grade is written once, in `## 재현·근본원인`.\n- **Tier-2 → unresolved-issue pointer**: only when reproduction hit Tier-2 (proceeding on a `가설(추측)` root cause) does the lead create an unresolved-issue pointer in the `## 미해결 이슈 \u002F 트레이드오프` section during this synthesis (the synthesis-terminal rule permits lead-driven Edits). Encode it to match that section's existing form (mixed-form prohibited; fresh-section default = sub-section). Sub-section example: `### N.x 재현 미확인 — 가설 근본원인 채택 여부` + `**상태**: 대기` + `**Category**: UR` + `**Surfaced-at**: Step 4 synthesis` + a body line referencing the `§재현·근본원인` anchor. The pointer holds its own `상태` (default `대기`) and the anchor, but **does NOT hold `근거 등급`** (that lives only in the canonical section, to avoid duplication\u002Fdivergence). This makes Step 5's walkthrough consciously ask the user whether to accept the hypothesized cause.\n- **`## 검증 기록` section** (verification ledger; unnumbered heading) — placed after `## 주요 결정사항과 근거`, before `## 미해결 이슈 \u002F 트레이드오프`. Holds `### V\u003Cn>.` sub-blocks per the V-ledger schema in `_common\u002Fverification.md` (the SOT — do NOT restate the field list here). The ledger accepts only performed verifications (`검증됨(통과)`\u002F`반증됨(실패)`, every entry carrying an observation). If no verification was performed, omit the whole section (the pre-save sweep makes the absence meaningful). Body claims reference an entry by the token-free anchor `(§검증 기록 V\u003Cn>)`; the ledger is the single SOT and `주요 결정사항과 근거` does not restate tokens. **Field-line rendering**: copy the CANON rendering example in `_common\u002Fverification.md` §4 byte-for-byte (bold key `**…**:`, no leading bullet `- `, one ASCII space after the colon) — do not choose your own bullet\u002Fbold style.\n- **`## 구현 시 검증 항목` section** (residual items; unnumbered heading) — placed after `## 미해결 이슈 \u002F 트레이드오프`, before `## 권장 구현 순서`. The two new sections straddle the unresolved-issues section without touching its parse region; neither new heading contains `미해결`\u002F`이슈`, so neither can match the walkthrough parse regex. Holds `### R\u003Cn>.` sub-blocks per the Residual-item contract in `_common\u002Fverification.md`. The lead performs the **transformation move** (that file) to convert each in-session-unsettleable claim into an R-item; a residual item is born by exactly the three paths of the contract (filter NO → `구현 필요`; verification-attempt exit → `검증 차단`; audit-reconciliation deferral → `검증 차단`). 0 items → omit the section. **Field-line rendering**: copy the CANON rendering example in `_common\u002Fverification.md` §5 byte-for-byte (bold key `**…**:`, no leading bullet `- `, one ASCII space after the colon) — do not choose your own bullet\u002Fbold style.\n- **`## 구현 슬라이싱` section** (workflow declaration; unnumbered heading) — placed after `## 구현 시 검증 항목`, and it **replaces** `## 권장 구현 순서` rather than joining it: the two say the same thing at different grades, and a document carrying both invites them to diverge. Write it when Step 1's delivery-shape answers exist; omit it otherwise (a single-repo, single-PR change needs no declaration and the omission is meaningful, not lazy). **The heading is matched as a whole line, exactly** — `^## 구현 슬라이싱$`, no leading space and no trailing text; a heading with a parenthetical tail is read as *not* a declaration at all and the document falls back to model-derived grouping.\n    - **Blocks and fields**: one `### 슬라이스 \u003Cid>` per slice (`\u003Cid>` is `[A-Za-z0-9]+`; the convention is `### 슬라이스 A`, `### 슬라이스 B`, and a trailing ` — \u003C제목>` after the id is fine). Field lines follow the same CANON rendering as everything else (`**키**: 값`, bold key, no leading bullet, one ASCII space after the colon); a list value is separated by **comma + space**. Required in every block: `**스킬**` (one of `design`·`design-audit`·`implement`·`review`·`apply` — the stage this slice *enters*), `**레포**` (the remote slug `\u003Cowner>\u002F\u003Cname>`, never a path — paths differ per machine and per worktree, and the slug is what the driver passes to `gh -R`), `**선언 파일**` (repo-relative paths in backticks; slices **may** overlap here — that is the point, and sequencing is what makes it safe), `**선행**` (a `슬라이스 \u003Cid>` list, or the literal `없음` — `없음` is a positive statement of independence and an omitted line is not the same thing; it means **implementation precedence**: this slice's branch is cut from a base on which every slice it names has already landed), `**절단점**` (a cutpoint token verbatim). Then, only when the slice has an apply: `**적용 명령**` (a one-line backticked literal — **the presence of this field is the declaration that an apply exists**, and it, not the cutpoint, decides whether the next two fields are required), `**적용 주체**` (`파이프라인` or `사람`; `사람` means the pipeline stops at merge and the command is copied verbatim into the morning report as an opaque string for the person to run), and — only when the actor is `파이프라인` — `**폭발 반경**` (what parks if the apply fails: `레포`, `런`, or a `슬라이스 \u003Cid>` list; the default is `레포` and it may only be narrowed).\n    - **`**머지 순서**` is the second kind of ordering, and every block you write carries it** — a `슬라이스 \u003Cid>` list, or the literal `없음`. It means **merge order**: the slice is planned, implemented and reviewed concurrently with the slices it names, cut from the current base, and only its merge waits until each of them has landed. The parser reads an absent line as `없음`, which is what keeps frozen documents meaning what they meant; a new block still writes the line, `없음` included. A `머지 순서` token names only a slice declared **earlier** in the section (`선행` carries no such rule, and adding one would park frozen documents that point at a later slice), and one token never sits in both lists of the same block. A slice joined to others only by merge order still writes `**선행**: 없음` — the gate refuses a missing `선행` in a repository with two or more segments, and that floor does not count `머지 순서`.\n    - **`**선행 사유**` and `**머지 순서 사유**` say why each kind was chosen.** Each is one line of prose and neither enters the declaration digest. A block that carries a `**머지 순서**` line is a new-grammar block, and in it every list that is not `없음` requires its own reason field: `**선행 사유**` for a non-empty `선행`, `**머지 순서 사유**` for a non-empty `머지 순서`. A block without the line is old grammar and owes no reason, so frozen documents stay valid.\n    - **Choosing the kind is the design's judgment, and the reason field records it.** Choose implementation precedence when the successor needs the predecessor's content in its own tree — it builds on it, calls it, tests against it, or a file overlaps within the closure below. Choose merge order when only the landing order matters and the closure is disjoint — the producer must land last, the slice is a release slice, or an intermediate state must not spread to the installed copy. Disjoint declared files do not by themselves prove the code independent, which is why the choice is a judgment and not a mechanical lowering.\n    - **Closure disjointness.** For a slice S, let M(S) be every slice reachable from S along `선행 ∪ 머지 순서` edges, and P(S) every slice reachable along a path whose first hop is a `선행` edge. S's declared files must be prefix-disjoint from every slice in M(S) \\ P(S): a slice in P(S) has landed before S is cut and is already in S's base, while a slice in M(S) \\ P(S) lands after S is cut and before S merges, so S never saw its change. `README.md`, `plugin.json` and `CHANGELOG.md` are **not** exempt — two bases' hunks in a generated index can conflict, or merge cleanly into something the generator would not produce. A violation is a defect owned by that slice, and it parks only that slice and the slices bound to it by either kind.\n    - **The writer and the reader ship in one release.** A parser older than this field ignores the `**머지 순서**` line and reads that edge as no edge at all, so a document using it must not run on a tree whose gate, shift and driver have not learned it.\n    - **`**잔여 항목**` is optional** — the verbatim headings of the `## 구현 시 검증 항목` items this implement slice owns, each wrapped in 「」 and separated by `, ` (`**잔여 항목**: 「### R4. …」, 「### R5. …」`), or the single word `없음` for a slice that owns none — the same spelling `**선행**` uses for an empty list. Every element is a `### R\u003Cn>. ` heading that the residual section carries verbatim; any other value refuses the whole segment plan. It is what the driver reads as this slice's residual share when it checks that an implement stage's last turn left a result line on each owned item: with one implement slice the share is every item and the field is not needed; with two or more, a slice that omits it owns none.\n    - **`**화면**` is optional, and it says which approved screens the slice waits for** — the literal `없음`, or a list of screen ids (`[a-z0-9-]+` each, separated by `, `) naming `### 화면 \u003Cid>` entries of the document's visual sidecar. A slice whose `**화면**` field is `없음` waits for no screen and is dispatched the night it is planned; a slice that lists screen ids covers those screens only. **An omitted field is not `없음`**: when the run plan has a visual stage or the document has a visual sidecar, a slice without the line waits for every screen of the document. Both checkers (the driver's and the gate's slicing check) read only the shape — a value that is neither `없음` nor such a list refuses the whole segment plan — and never whether an id exists; the dispatch site and `visual-unattended` look up the ids. **Write the field on every slice** when the interview record's `## 시각 방향` is not `없음`, so that a slice touching no screen says so rather than waiting the night out. The two shapes, verbatim:\n      ```text\n      **화면**: 없음\n      **화면**: order-list, order-detail\n      ```\n    - **`**크기 사유**` and `**권한 혼합 사유**` are optional, and each names the one coupling that a split would break** — one line of prose apiece, written only when rule (f) or (g) of the Step 7 slicing self-check asks for it: `**크기 사유**` on a block over the size baseline that stays whole, `**권한 혼합 사유**` on an implement block whose permission profiles mix and stay mixed. A sentence that names no coupling (\"it is large\") is not a reason. When the person gave the `슬라이스 수` answer, the reason quotes that answer instead of a coupling, because then the answer is what holds the block together. Neither enters the declaration digest, and neither the driver nor the gate reads whether it is present. The two shapes, verbatim:\n      ```text\n      **크기 사유**: 생성기와 그 픽스처가 한 형식을 함께 바꿔, 나누면 중간 커밋의 생성기 검사가 깨진다\n      **권한 혼합 사유**: 배포 설정 한 줄의 쓰기가 API 계약 변경과 같은 커밋에 있어야 둘이 어긋난 배포가 생기지 않는다\n      ```\n    - **`**리뷰 정책**` is optional and its default is `선리뷰후머지`** (values: `선리뷰후머지` \\| `선머지후리뷰` \\| `리뷰없음`). It exists because the cutpoint says *how far* a slice may go and cannot say *when review happens* — a slice may be authorized to merge and still owe its review afterwards, and those are two axes rather than two readings of one. `선머지후리뷰` does **not** remove the obligation, it defers it: the gate leaves a review-obligation row and the run cannot terminate while one is unfulfilled. `리뷰없음` is expressible only when **that target's `리뷰 정책 상한` in the run manifest is itself `리뷰없음`**, which is what stops a stage from choosing it for itself. The ceiling is the whole predicate: a slice may declare no looser than the target it runs against, and the ceiling was frozen at kickoff while a person was present. One real cost belongs with the field rather than in a footnote: post-merge review is by definition review against a base that has already moved, so the review anchor is the merge commit rather than a PR head — and what closes the obligation is **a review covering that obligation's merge commit**, not merely some later review of that segment. A review of the segment that does not contain the commit that was merged leaves the merge unreviewed while looking as though it did not.\n    - **`**라벨 인정**` is optional and an absent line reads as `없음`** — the names of the checks this slice expects to fail and to have answered by a label, separated by `, ` and each written exactly as the PR's check list prints it, or the single word `없음`. Write it only when the slice deliberately changes the surface such a check guards **and** the run manifest carries a `라벨 인정` row for that check under the slice's target — the target whose `원격 슬러그` is the slice's `레포`. Without both, leave it out: a person decided at kickoff which checks a label may answer, and this field only binds that decision to the slice that needs it. Every name it gives must equal the `체크` of one of those rows; a name no row carries, an empty element, whitespace around an element, a `|`, or `없음` beside a name parks this slice alone, not the whole plan. A value other than `없음` enters the declaration digest; an absent line or `없음` adds nothing, so documents without the field keep their digests.\n    - **A section-level `**슬라이스 수**: \u003CN>` is a checksum, not an input** — it must equal the number of blocks whose cutpoint is `PR` or later (so `커밋`\u002F`브랜치` slices are not counted). A mismatch means the declaration was truncated or misnumbered, and it is worth stopping for.\n    - **Two slices are declared as one by default, and only when the person left the count to the design.** The default applies only when the delivery-shape `슬라이스 수` answer — the brief's `## 배포 형상` line, or the autopilot interview record's — is `없음` or delegated to design (`설계에 위임`, with or without its `— 문 \u003Cn>` tail). A count or a chain the person gave binds the declaration: it is itself a positive reason to keep apart the slices it separates, and this rule never folds them. Where the default applies, merge two slices into a single block when all five hold:\n        1. they are joined by a `선행` edge that fans out on neither side — the predecessor has no other successor and the successor has no other predecessor. Only `선행` edges count here: a pair joined only by `머지 순서` does not meet this condition and is never merged. Both blocks' `머지 순서` must also be `없음` — a merged block has no rule for folding the two lists into one, so a pair either side of which carries a merge-order edge stays apart and that edge stays where the checks read it;\n        2. their `선언 파일` sets still overlap after setting aside the files every change touches regardless of content — generated indexes, version and release files, the repository-wide test runner or build manifest;\n        3. `레포`, `스킬`, `절단점` and `리뷰 정책` are equal, an omitted `리뷰 정책` reading as its default `선리뷰후머지`;\n        4. neither declares `적용 명령` — a block holds one `적용 주체` and one `폭발 반경`, so two applies cannot share one, and a merge that dropped either would switch off the park it declared without any check noticing;\n        5. the merged block passes rules (f) and (g) of the Step 7 slicing self-check without a reason field — its declared file count is at or below the size baseline, and it holds one permission profile. A `**크기 사유**` or `**권한 혼합 사유**` line either block still carries is not moved into the merged block; it is deleted.\n\n        Keep them apart only when the block prose gives a positive reason: a `슬라이스 수` answer the person gave, a baseline that must be measured on the tree before the other part lands, a release slice, or a conflict surface with in-flight work that the other part does not share. File order alone is not a reason. The rule governs new declarations only; a repair segment is not a declared slice and this rule does not fold it. Merging removes a boundary, not a review — the merged slice is reviewed under the same `리뷰 정책`, tier table and P0\u002FP1 gate.\n\n        A merge is finished only when all five of these hold. The driver reads every `선행` token and the checksum at kickoff and stops on a stale one, but it records a `폭발 반경` id without checking that the id exists and parks by exact match, so a radius that still names a retired slice parks nothing. It also runs the blocks once in section order without sorting them and parks a block whose `선행` has not finished, so where the merged block stands decides whether it runs:\n        1. the predecessor's `\u003Cid>` survives and the successor's is retired; the merged block's `선언 파일` is the union of both;\n        2. every other block's `선행`, `머지 순서` and `폭발 반경` that names the retired id names the surviving one instead, listed once;\n        3. the merged block's `선행` is the predecessor's `선행`, its `머지 순서` is `없음`, and its `선행 사유` is the predecessor's — condition 1 leaves the successor no other `선행` edge and neither block a `머지 순서` edge;\n        4. the section's `**슬라이스 수**` drops by one when the shared cutpoint is `PR` or later, and is unchanged when it is `커밋` or `브랜치`, which the checksum does not count;\n        5. the merged block takes the successor's position in the section, after every block its `선행` names — left at the predecessor's position it runs ahead of the blocks that stood between the two, and a block among them whose `폭발 반경` named the successor then parks nothing if its apply fails, because the merged block has already run.\n\n        Keep every prose line here and in a slice block from beginning with a bold field key followed by a colon: the slicing parser reads the first such line in a block as that field.\n    - **There is no `적용 순서` field.** Apply order is derived from `선행 ∪ 머지 순서` restricted to the apply-declaring slices; two orderings that cannot be written separately cannot disagree.\n- **`## 테스트 설계` section** (unnumbered heading) — placed after `## 구현 시 검증 항목`, before `## 구현 슬라이싱`. **Required** whenever the target project has a test environment (jest, vitest, pytest, go test, …) **and** existing test files (`*.spec.ts`, `*.test.tsx`, `*_test.go`, …); omit it when the project lacks either one. It holds the test design for the module\u002Ffeature being designed — unit-test scenarios and E2E test cases — so implementation inherits a test surface instead of inventing one. This is a section of the design document itself, not a follow-up task.\n- **UR escalation pointer (lead's delegated judgment, Tier-2 isomorphic)**: if a residual claim is load-bearing enough that the user should consciously accept building on it, the lead creates a UR pointer in `## 미해결 이슈 \u002F 트레이드오프` — `상태`\u002F`Category`\u002F`Surfaced-at` + a `§구현 시 검증 항목 R\u003Cn>` body reference only; it **never** includes the `검증 등급` key, token, or recipe (predicate check). Per-item mandatory pointers are rejected (the dual backstop already validated the deferral; N pointers = N friction prompts).\n- **Synthesis write economy (lead-local, inside the synthesis-terminal window).** What synthesis costs is mostly how many responses it is spread across, each one re-reading the lead's whole history (`_common\u002Fagent-team-protocol.md` `## Turn economy`). So the lead writes the document in as few responses as its content allows; the author, the inputs and every check of this step stay as they are.\n    - **Marks.** At three points the lead appends one line `\u003Cevent> \u003CUTC time> \u003Cstage id>` to `$STATE\u002Fsynthesis-marks.txt` with the file-edit tool, creating the file when absent: `enter` as the first act after the last convergence witness is recorded, `draft` once the whole draft is in the document and before the fidelity pass begins, and `save` at the synthesis terminal, after the last document write. The time is the output of `date -u +%Y-%m-%dT%H:%M:%SZ`, issued in the same response as other independent calls (inside a gated run through `gate.sh exec … --surface 읽기`); the stage id is `CC_PIPELINE_STAGE_ID` read by name, or `-` when it is unset. A mark that comes again after a re-attachment is appended, never rewritten. The marks are measurement, not a gate: a missing mark leaves the window unmeasured and changes nothing else.\n    - **Compose whole, insert once.** Compose the whole draft, in this step's section order, before writing any of it. Insert it with one Edit whose `old_string` is the ledger block's closing line — with the line before it when the closing line alone is not unique in the stub — and whose `new_string` is those same bytes followed by a blank line and the draft. When one response cannot carry the whole draft, split only at `## ` boundaries and anchor each continuation the same way as the first insertion: the last line of the previous insertion, together with as many lines before it as make the string unique in the document — section endings repeat (every verification entry ends on the same hygiene line), so the last line alone is often not unique. Never write the draft section by section or field by field, and never Write the whole file over the stub: the ledger block changes only by its own single-row Edits. After the last insertion, confirm with one read that the last `## ` heading of the planned order is in the document.\n    - **Inserting is not saving.** The draft in the document before the fidelity pass is not the save of `Synthesis terminal`: the save is this step's last document write, after the pre-save sweep, and the `save` mark follows it. Fidelity-pass dispatches and re-convergence messages before that write stay inside the window that rule leaves open before the first save.\n    - **Batch fixes by source.** Once every finding of one source is in hand — every fidelity witness read, every sweep check run — apply all fixes that do not depend on one another as several Edits in one response, each anchored on text unique in the document. Only a fix whose anchor another fix rewrites waits for the next response.\n    - **Batch the sweep's reads.** The sweep's checks and the two boundary-gate commands do not depend on one another; issue them in one response (inside a gated run, within `## Turn economy`'s digest-sharing bound).\n    - Not a CFI, on the same basis as the pre-save sweep: skipping it brings back today's cost, not a mis-transition.\n- **Synthesis fidelity pass (team-driven, inside the synthesis-terminal window, after the full draft is synthesized and immediately before the pre-save sweep)**: before the lead's solo pre-save sweep, the Step 3 team's roles (dispatched afresh for the `fidelity` phase into their ledger rows) check draft↔discussion fidelity — the lossy-synthesis class of defect that only an original-context holder can catch, and that any fresh, context-free reader — which re-reads only the saved doc and holds none of the discussion — can never reach. Emit once, inline at entry (one-way notice, not a question): *\"팀이 설계 초안의 충실도를 점검하고 있습니다.\"* **Ordering rationale**: before the sweep, so the sweep also covers the fidelity Edits. **Not a CFI** (same basis as the pre-save sweep — it rides the existing \"clarify before the first save\" window, adds no new turn-yield semantics; a skipped pass degrades to a quality loss, not a mis-transition; nothing is added above the `## Control-Flow Invariants` heading).\n    - **Subject & input**: reuse the existing Step 3 team's roles — dispatch each role afresh into its ledger row for the `fidelity` phase (reproduction\u002Fverification specialists included — they check their own output sections, the high-trust grade\u002Fverdict data implement consumes verbatim). The dispatch names the member's own round witnesses by path, so what the member contributed is read from disk rather than from a retained context — the pass's sensitivity is bounded by what those witnesses recorded. Hand each member the **whole draft by path** — the dispatch names the document's path, the line number of its first `## ` heading and the draft's last `## ` heading, and the member Reads from that line to the end of the file, in consecutive `offset`\u002F`limit` ranges whenever one Read cannot return the rest (not a section slice — whole-cloth omissions have no home section and surface only against the full draft). The member's witness quotes the last `## ` heading it read as a receipt. A witness without that receipt, or with a different heading, did not cover the whole draft: the lead treats it as a Case 3 non-conforming witness and re-assigns that member once with the whole draft quoted in the resume, the one case in which the lead emits the draft. Otherwise the lead's dispatch text never carries the draft itself. The ledger block above the first heading is not part of the draft, so the member does not read it. **Scope**: each teammate checks **only their own contribution** — this pass asks *\"did synthesis distort or drop what I said?\"*, which only the contributor can answer. Document-wide coherence and completeness are **not** delegated away: they are the subject of the **Step 7 Class C coherence pass**, which dispatches this same team's roles afresh against the final text.\n    - **Two fidelity classes**:\n        - **Interpretive** (root-cause framing, recipe prose, recommendations, concerns): fidelity = **accounted-for** — adopted (meaning preserved; paraphrase passes) OR rejected with rationale recorded in the doc. A point rejected-with-rationale passes (not re-litigation). Vanished without a trace = fail.\n        - **Transcription** (observation tokens: `근거 등급`, each `검증 등급` verdict + its backing observation field): **byte-identical or flag**. Grades\u002Fverdicts are recorded once at discovery and propagate one-way; synthesis only transcribes (the lead is read-only to them). No rationale justifies recording an observed `확인됨(재현·관측)` as `가설(추측)`, or a performed verdict as weaker. Any divergence MUST be flagged by the specialist.\n    - **Completion contract**: each member publishes its fidelity check as its **witness** `${scratchDir}\u002F{role-slug}.fidelity.md` (sentinel\u002Fnonce-terminated per `_common\u002Fagent-team-protocol.md`; the return text is only an early-wake hint, and the lead reconciles the witness — never the return). The witness body is either `Fidelity confirmed — all my contributions accounted for.` (clean) or one discrepancy block per finding:\n        ```\n        - type: omission | distortion | grade-distortion | decision-reopen\n        - contribution: \u003C원래 논점 \u002F 토큰, 1줄>\n        - location: \u003C초안 섹션\u002Fanchor, 또는 \"absent\">\n        - evidence:\n            omission        → 어디에도 없음\n            distortion      → 초안은 X, 나는 Y (의미 변경; paraphrase는 finding 아님)\n            grade-distortion→ draft token=X | my broadcast value=Y (BYTE 비교; 의미 latitude 없음; 그대로 복원, 판정 금지)\n            decision-reopen → 기록된 rationale 자체가 틀렸거나 unsafe한 이유\n        ```\n        Either form ends, above its sentinel, with one line of its own `findings: \u003Cn>` — the number of discrepancy blocks, `findings: 0` beside the clean sentence. A fidelity witness without that line is a Case 3 non-conforming witness (`_common\u002Fagent-team-protocol.md`): re-instruct the member and take its `fidelity-rev\u003Ck>` revision. The count is the line's value; it is not checked against the blocks.\n        A published witness is the completed check — \"check done,\" not \"no issues\"; a discrepancy report is a completed check. The \"collect all witnesses\" gate (`witness_present` for each member, then read the witness) is satisfied by either form. A thin or empty witness (no fidelity verdict) is a Case-1 thin\u002Fempty witness, not a completed check (see No-response below).\n    - **Triage (lead authority)**: the `type` is the teammate's read; the lead routes by one test — **\"does fixing this contradict a converged decision?\"**\n        - **NO → lead Edits immediately**: re-reflect the omission \u002F correct the distortion \u002F restore the byte-true grade\u002Fobservation to its **canonical SOT** (the `근거 등급` field, the `검증 기록` V-entry's `관측 결과`, or `## 재현·근본원인`'s `관측된 증상` — never a downstream token-free `(§…)` reference). No team cycle.\n        - **YES → decision-reopen → reuse the pre-save sweep's 1-cycle re-convergence** (author SendMessage → focused exchange → mini cross-review if cross-cutting → update draft → re-check → 2nd failure → AskUserQuestion). In the decision-reopen context the three options are re-read as \"adopt the lead's recorded rejection rationale over the teammate's objection \u002F defer the reopened decision to Step 6 redesign \u002F abort\" (a challenge to a converged decision, not a verification claim). The 1-cycle counter binds to the **reopened decision** (not a grade token), per failing item; it is an **orthogonal axis** to the Case-1 thin-return counter below and they never co-increment.\n        - **Restore, never re-grade**: a `grade-distortion` fix may restore **only the value already present in the specialist's Step-3 broadcast**. A third value Z differing from both draft and broadcast is a new observation, not a fidelity discrepancy — this read-only pass cannot physically earn a new grade (no recipe run, no tree change), so it is inadmissible and bounces to re-convergence (the specialist must actually re-run and re-broadcast). Two locks make this unsmugglable: transcript reference-equality + the pass's read-only nature.\n    - **No-response — Case 1 \u002F Case 2 handling** (per `_common\u002Fagent-team-protocol.md` escalation): a thin\u002Fempty fidelity witness and a never-returning member are the two failure phenotypes.\n        - **Case 1 — thin\u002Fempty witness** (counter): a member publishes a witness with no fidelity verdict (empty or substanceless). 1st → re-scope + resume once (hard prompt: \"no empty witness — deliver your fidelity verdict or name a concrete blocker in one line\"); 2nd consecutive thin\u002Fempty witness → `AskUserQuestion`. The fidelity-scope prompt variant: (a) \"save contributor X's already-reflected contribution without a fidelity check\" (→ the emit-only coverage-gap path below — the contribution is already in the draft, only the self-check is missing), (b) re-scope once more, (c) abort save\u002Fworkflow. On option (a), land on the emit-only path (do NOT apply document-metadata convergence-exclusion marking — see Exclusion is emit-only below).\n        - **Case 2 — never-returns** (binary, not a counter): a fidelity-pass dispatch never returns (runaway\u002Fwedge) and the protocol's reconcile-ladder death verdict fires. The recovery is `TaskStop` + a **same-round respawn** with the same fidelity assignment (new `agentId`, with the ledger row's `agentId` \u002F `outputFile` updated and its `stallMark` reset per the protocol). If the respawn also dies → `AskUserQuestion` (same fidelity-scope variant as Case 1).\n        - The decision-reopen re-convergence 1-cycle counter (Triage above) is an orthogonal axis to the Case-1 thin-return counter and they never co-increment.\n        - **No implicit-confirm** — a missing witness is never read as \"no objection.\"\n    - **Exclusion is emit-only**: when a Case-1 option-(a) user decision excludes a teammate, do **not** apply the escalation's document-metadata convergence-exclusion marking — the teammate already converged in Step 3 (substantive input is in the doc, only self-verification is missing), there is nothing to stamp, and stamping would violate the no-trace invariant. Instead, at save time, emit **once per excluded contributor** (Korean, mandatory — \"no silent caps\"): *\"기여자 X의 기여 내용은 충실도 점검 없이 저장됩니다.\"* ATP's Case-1 option-(a) document-metadata marking — and the `state=aborted` ledger routing that a genuine Case-1 drop applies to remove a member from the dispatch-completeness roster — are both restricted to **genuine Step-3 synthesis-convergence exclusion**. This fidelity scoped skip drops only the member's current self-check, not the member: it **stays in the `state ≠ aborted` roster and is not set to `aborted`**, so a later decision-reopen re-convergence correctly re-dispatches it (desired participation, not resurrection).\n    - **Visibility — 3 emit points**: (1) on entry — *\"팀이 설계 초안의 충실도를 점검하고 있습니다.\"* once (one-way notice, placed inline above; not re-emitted in re-convergence, which is silent by its own spec); (2) clean termination — no emit (a clean pass emits nothing beyond the on-entry notice and the existing save notice — fixes are indistinguishable from ordinary synthesis); (3) exclusion — *\"기여자 X의 기여 내용은 충실도 점검 없이 저장됩니다.\"* once per contributor at save time. All three are one-way progress-class notices, not ATP \"surface\" events, and touch no escalation gate. All `*\"...\"*` italic Korean, matching the existing Step 4 emit convention.\n    - **No-trace invariant**: a clean pass leaves no mark in **either the document or the user channel** (beyond the on-entry notice) — fixes appear only as the corrected body itself. The coverage-gap emit is the sole exception, and even it is an ephemeral user notice, not a document write (the saved-document no-trace invariant is preserved).\n- **Pre-save sweep (lead backstop, inside the synthesis-terminal window, before the first save — so re-convergence is always still possible)**: scope is the entire synthesis **draft**, decisively including assertions the lead introduced during synthesis (the only class that never passed the Quality Gate — the sweep's unique coverage). **Pass conditions**: the four conditions of `_common\u002Fverification.md` §10 (the shared sweep predicate) — do NOT restate them here; that section is the single definition and this skill cites it. **Late finds**: cheap (a)\u002F(b) → the lead verifies immediately and records it in the ledger; expensive\u002Ffailing → **re-convergence** (SendMessage the affected author → focused verify\u002Ffix exchange → mini cross-review if cross-cutting → update draft → re-sweep the changed part → save). **Sweep record**: for every refutation that opens such a re-convergence, append one line `round-3: sweep — \u003Cthe refuted claim, one line>` to the durable corpus file `$STATE\u002Fwitness\u002FSWEEP.md` with the file-edit tool, the way `INDEX.md` is written; when a sweep refutes nothing, still create the file (empty) as the sweep ends, so \"no refutation\" and \"no record\" stay apart. Each time a sweep ends (a re-sweep of the changed part included), rewrite `INDEX.md`'s lead row — role-slug `lead`, round\u002Fphase `sweep` — with `SWEEP.md`'s byte count and `sha256` at that moment. This re-convergence does not open round 3; it stays the author-only cycle above, and a fidelity `decision-reopen` that borrows it is not written to this file. This rides on the existing \"clarify before the first save\" sentence — no new turn-yield semantics, **not a CFI** (a missed sweep degrades to today's quality baseline, not a mis-transition). **Re-convergence limit**: at most 1 cycle per failing claim; a second failure of the same claim → `AskUserQuestion` (accept residual with refutation evidence \u002F route to Step 6 redesign \u002F abort) rather than a silent round. **Visibility tripwire**: at ~5 in-session worktree experiments the lead emits a status note (visibility, not a gate).\n- **Synthesis terminal**: All teammate clarifications must be completed before saving the design document. Once the file is saved, the synthesis phase is over — no further teammate messages are permitted. Do NOT save a partial document, send a teammate message, then save again; clarify before the first save. The sequence save → cleanup → presentation is atomic. Step 5 (walkthrough) and Step 6 (refinement) are new editing phases governed by their own state-check + cleanup rules. The synthesis-terminal rule bars further Step 3 team messages but does NOT bar lead-driven Edits to the saved doc.\n- Save the design document to the project's `docs\u002F` directory. **File naming convention**: use `docs\u002F{topic-slug}.md` where `{topic-slug}` matches the Step 3 team's topic slug exactly (e.g., Step 3 team `design-auth-flow` → saved doc `docs\u002Fauth-flow.md`). This filename-to-slug binding is the local state used by Step 5's entry state-check to recover the slug without relying on lead memory. **Interrupted-save case**: if the save itself was interrupted (partial write, permission error, etc.), the state-check cannot recover the slug from the filename. In this case the lead must either (a) recover the slug from the original task input or interview output that started the workflow (from in-session conversation history, including slash-command `$ARGUMENTS` if invoked that way), or (b) treat the workflow as ambiguous and prompt the user via `AskUserQuestion` before any cleanup action.\n- **Document location, plan derivation, and post-implementation update** — the three duties that outlive this step.\n    - **Location**: the spec \u002F design document is saved under the **project root's `docs\u002F` directory**. In a workspace that nests several repositories under one root, it is `docs\u002F\u003Crepo>\u002F` — the repository the design targets, not the workspace. This is a different layer from the filename rule above — that rule fixes the file name, this one fixes the directory — so whether the directory is `docs\u002F` or `docs\u002F\u003Crepo>\u002F`, the file is still named `{topic-slug}.md` and the filename-to-slug binding above holds unchanged.\n    - **Plan derivation**: the implementation plan is written **from the saved document**, never from in-context memory of the discussion. The document is the input to planning, not a record of it.\n    - **Post-implementation update**: once implementation is finished, the document MUST be updated to match what was actually built. Leaving a design document unrevised after its implementation diverged makes it a wrong document, not a historical one.\n- **On the normal path the three user-facing lines below are rendered by the seat from `presentation.md` (CFI-1b), verbatim; the leg composes them and never emits them.**\n- Notify the user in Korean: *\"설계 문서 저장을 완료했습니다. 팀을 정리한 뒤 결과를 공유드리겠습니다.\"*\n- **Before presenting results to the user, Read `${CLAUDE_SKILL_DIR}\u002F..\u002F_common\u002Fteam-cleanup.md`** and apply it — normal completion is a no-op (returned tasks already self-terminated), abort is `TaskStop` on any `state=running` agentId, plus ledger hygiene.\n- **Verification aggregate line**: if the `## 구현 시 검증 항목` section is non-empty, include in the Step 4 presentation one Korean line — *\"구현 시 검증 항목 N건이 기록되었습니다 — \u002Fimplement 시작 시 우선 검증됩니다.\"* (queue impact 0).\n- Present the results to the user in Korean. Do NOT yield the turn here — the presentation and Step 5's entry are one continuous turn. Immediately continue into Step 5 below in this SAME turn, with no stop, no wait, and no user prompt. (CFI-1b)\n\n### Step 5: Unresolved Issue Walkthrough\n\nThis step runs automatically right after Step 4 (CFI-1b). Its purpose is to drive every unresolved issue in the saved design document to a decision **without waiting for an unprompted user request**, scoped strictly to *issues that cannot be resolved without user input*. Mechanical gaps, false positives, and auto-decidable items are NOT this step's responsibility — the **Surface Depth router** below gives each of them a named destination: the Step 7 Class C coherence pass, a post-implementation `\u002Fcc-cmds:review` carrying a `design-conformance` tag, or an explicit recorded drop. User-facing communication in this step is Korean; the normative prose below is English.\n\n> \"Walkthrough-spawned teams (Step 5) and refinement teams (Step 6) are both just fresh nameless-task spawns recorded in the ledger — there is no shared team namespace or monotonic counter — but they still differ in scope and lifetime: a walkthrough-spawned team is bounded to a single unresolved issue's decision debate (user-initiated when auto-investigation findings alone don't yield a clear decision) and its members self-terminate at that issue's resolution; a refinement team handles a user-initiated multi-turn refinement and its roles live (one fresh dispatch per round) until the user is satisfied. They are not competing entry points — they are the same entry point (user-confirmed spawn of nameless background tasks for a single bounded scope) invoked at two different lifecycle moments. The lead never extends a walkthrough-spawned team into a refinement team or vice versa — the `self-terminate → next spawn` contract is enforced unchanged.\"\n\nTerminology: throughout this skill use **\"walkthrough-spawned team\"** (not \"walkthrough investigation team\"). \"Investigation\" refers strictly to the lead-only, read-only activity defined below.\n\n#### Trigger & Queue Initialization\n\n- Parse the saved doc's `## 미해결 이슈 \u002F 트레이드오프` section to initialize the issue queue. **Parse contract**: match the heading with the regex `^##\\s+(?:[0-9]+\\.\\s+)?미해결\\s+이슈(?:\\s*\u002F\\s*트레이드오프)?\\s*$` — an optional leading section number (`6. `, `10. `, any digit count) and an optional `\u002F 트레이드오프` suffix are both allowed. On **multi-match**, use the LAST match (synthesis is written top-down, so the deepest occurrence is canonical).\n- `등급 1` On **0-match**, surface via `AskUserQuestion` with three options: (a) **add the section and proceed** — the lead creates a `## 미해결 이슈` heading via doc Edit (sub-section form by default, per the encoding rules below), re-parses the doc to rebuild the queue; entries the user pre-added are processed as-is, and 0 entries cascade naturally into the 0-issue path; (b) **skip the walkthrough** and proceed to Step 6; (c) **abort** — the entire design workflow terminates and Step 6 is NOT entered.\n- **0 issues**: emit the Korean notice *\"미해결 이슈가 없어 곧바로 플랜 리파인먼트 단계로 이동합니다.\"* and proceed directly to Step 6. (CFI-2)\n- **1+ issues**: emit *\"설계 문서에 미해결 이슈 N건이 확인되었습니다. 하나씩 검토하며 정리하겠습니다.\"* and enter the walkthrough proper.\n- **Depth-2 promotion on queue init**: any entry carrying both `상태: 보류` and a `(깊이: 2)` marker is auto-promoted to depth-1 — the lead Edits the doc to change `상태: 보류 → 상태: 대기` and `(깊이: 2) → (깊이: 1)` together (the `Parent` field is preserved as historical metadata), then appends it to the queue. Plain `상태: 보류` entries (no depth marker, or `(깊이: 1)`) are NOT promoted — those are deliberate user deferrals.\n- **Drop-uncertain promotion on queue init**: any `상태: 보류` entry whose `사유:` text contains the substring `drop 미확정` (produced by the abort-during-drop-prompt path below) is also promoted — change to `상태: 대기`, clear the `사유` field, append to the queue. This applies regardless of any depth marker, and re-surfaces issues whose drop confirmation was never completed.\n- **Queue order**: doc-order, top-to-bottom. Depth-1 items that surface mid-pass are appended to the *end* of the queue (not inserted right after the current issue) and are reached only after all pre-existing items are processed. No per-category priority ordering.\n- After the walkthrough finishes, emit *\"미해결 이슈 워크스루를 종료했습니다. 이어서 플랜 리파인먼트를 시작하겠습니다.\"* and enter Step 6 automatically. (CFI-2)\n- If the user aborts mid-walkthrough, batch-mark the remaining items `상태: 보류` (see Abort Semantics below) and move to Step 6. (CFI-2)\n\n#### Issue Sources & Categories\n\nThe issue queue has two sources:\n\n1. The saved doc's `## 미해결 이슈 \u002F 트레이드오프` section (the Step 4 output).\n2. Items the lead surfaces while re-reviewing the doc — but these must be **doc-first**: record the item in that section via Edit *before* appending it to the in-memory queue (idempotency). Items found during the bulk re-review at walkthrough entry are queued as `(깊이: 1)`; items found incidentally during a depth-1 issue's auto-investigation or team discussion are recorded doc-only as `(깊이: 2)` and do NOT enter the queue (see Depth Management below).\n\nEach issue is classified into one of four categories:\n\n| Category | Code | Definition | Auto-investigation default |\n| --- | --- | --- | --- |\n| Decision-needed | UD | A value\u002Fchoice the synthesis left undecided or set to a default | None — user value judgment |\n| Clarification-needed | UC | Whether an assumption the synthesis adopted matches user intent | `grep` the codebase convention first |\n| Alternative-to-evaluate | UA | The doc presents multiple paths and the user must pick | Read each option's affected files + cost estimate |\n| Risk-acknowledgment | UR | A deliberate tradeoff the user must consciously accept | None — surface the tradeoff framing only |\n\n#### Surface Depth (3-arm router)\n\nWhile re-reviewing the doc, the lead routes each candidate issue to exactly one of four destinations. The walkthrough surfaces only what the user must decide; everything else gets a **named owner** or is dropped **on the record**. Nothing is left unrouted.\n\n> **Arm 0 — surface here (this step's own scope).** *\"Does resolving this require user input — a value judgment, an intent confirmation, a choice among alternatives, or a conscious risk acceptance?\"* YES → the walkthrough surfaces it now, per the per-category flow below. NO → route to arm 1, 2, or 3.\n>\n> **Arm 1 — coherence \u002F completeness → QUEUE it for the Step 7 Class C pass.** Cross-section field or contract mismatch, a decision contradicting another section, spelling and formatting, any internal inconsistency the document itself can settle.\n>\n> **Arm 2 — an item the design deliberately left to implementation → `\u002Fcc-cmds:review` carrying a `design-conformance` tag.** Missing standard error handling, an unimplemented item, anything whose real question is *\"did the code end up matching the design?\"* That question is unanswerable before code exists, so its destination is post-implementation review rather than this step.\n>\n> **Arm 3 — everything else → EXPLICIT DROP.** A false positive already resolved in the doc body, a hypothetical unrelated to real risk, an item outside the design scope, an item the lead's own auto-investigation alone resolves. Dropping is a decision, so it is recorded rather than silent — the pre-queue filter below is its mechanism.\n\n**Arm 1's timing is load-bearing — do NOT run anything there.** The walkthrough is Step 5; the Class C pass runs after Step 6. Arm 1 is therefore **queue-loading for the terminal window**, not execution: the lead records the item as a one-line doc-body note tagged `[Step 7 정합 점검 대상]` and moves on. Reading this arm as *\"run the enlarged pass now\"* means editing the document **before the freeze**, and the downstream audit's whole guarantee rests on nothing changing between the freeze and the reads. Arm 2 fires after implementation and arm 3 is immediate and final, so neither has a timing hazard.\n\n**Mapping of the previously-non-surfaced classes** to their arms:\n\n| Class | Arm |\n| --- | --- |\n| spelling, formatting, cross-section field\u002Fcontract mismatch | 1 |\n| missing standard error handling | 2 |\n| items already resolved in the doc body (false positives) | 3 |\n| hypothetical items unrelated to real risk | 3 |\n| items outside the design scope | 3 |\n| items the lead's own auto-investigation alone can resolve | 3 |\n\n**Pre-queue filter** (arm 3's mechanism): this happens *before* queue initialization — while the lead re-reviews the doc, any candidate it judges a false positive gets only a short lead note in the doc body (e.g., *\"lead 자동 조사 결과: 코드베이스 컨벤션 X와 일치 — false positive\"*) and does NOT enter the queue. No state-machine transition occurs, so this is unrelated to the state machine; it is *triage*, not a *decision*, and does not conflict with the user-confirmation rule for decisions. It applies to all four categories.\n\n#### State Machine (5 + 1, doc-anchored)\n\nEach issue follows this state machine (5 non-terminal + 1 transient-remove):\n\n```\npending → investigating → awaiting-decision → resolved\n                                           ↘ deferred\n                                           ↘ dropped\n\nUD\u002FUR shortcut: pending → awaiting-decision (skips investigating)\n```\n\n- `investigating` \u002F `awaiting-decision` are **ephemeral by default** (lead memory). If a transition is mid-flight when a turn ends, checkpoint-write it to the doc so the next session can recover. The checkpoint format is the encoding convention below — sub-section form prepends a `**상태**: 조사중` or `**상태**: 결정대기` line; table form updates the `상태` column value.\n- **Per-category transition shortcut**: UD (user value judgment) and UR (tradeoff acknowledgment) have no auto-investigation, so they go `pending → awaiting-decision`, skipping `investigating`. UC\u002FUA follow the full transition.\n- **Checkpoint recovery**: when a new walkthrough invocation parses the doc and finds a `상태: 조사중` or `상태: 결정대기` entry, the prior session's transient memory is lost, so the lead (i) **Edits the doc to overwrite the marker with `상태: 대기`**, then (ii) appends it to the in-memory queue as `대기` so it is re-investigated in natural doc-order. The doc marker and queue state must always agree, so an in-memory reset alone is not sufficient. The checkpoint only guards against doc-state loss; it does not recover in-memory investigation findings.\n- `resolved` \u002F `deferred` are **terminal** — written to the doc immediately.\n- `dropped` is **terminal-remove** — right after user confirmation the entry itself is deleted from the doc (the doc reflection is an entry removal, not an annotation write; see the dropped branch below).\n\n#### Doc Encoding (tolerate both forms + 상태 marker)\n\nExisting design docs use two encodings: **table form** (columns `항목 | 내용 | 우선순위 | 비고`) and **sub-section form** (`### N.x \u003C항목명>` headings + prose body). The walkthrough tolerates both and adds an inline `상태` marker.\n\n- **Table form**: append a `상태` column to the right of the existing columns. Additional fields (Category, Reason, 자동조사 요약, Surfaced-at, Parent) attach as extra columns. **Field definitions**: `Surfaced-at` = the walkthrough invocation that surfaced the entry (format `walkthrough pass \u003CN>`, or `Step 4 synthesis` meaning an original design output item). **N counter**: a monotonic walkthrough-invocation counter starting at 1, +1 each invocation; not stored separately but derived as `max(existing Surfaced-at entries) + 1` (the same doc-anchored, no-lead-memory doctrine as file-system enumeration); if the doc has no entries on the first call, N=1. `Parent` = a depth-2 entry's parent depth-1 issue (format `\"issue title (§anchor)\"`). The other fields are defined elsewhere in this step. **Last-row removal edge case**: if a `dropped` removal leaves the table with 0 data rows (only header + alignment), the lead removes the entire table and replaces it with the one-line note *\"이번 walkthrough에서 모든 미해결 이슈가 해소되었습니다.\"* The `## 미해결 이슈` heading itself is kept (needed by the parse contract and future walkthrough invocations).\n- **Sub-section form**: prepend `**상태**: \u003Cvalue>` to the first line of each sub-section body. Additional fields are added as prose lines: `**Category**: \u003Cvalue>`, `**Surfaced-at**: walkthrough pass \u003CN>`, `**Parent**: \u003Cissue title> (§\u003Canchor>)`, `**Reason**: \u003Ctext>`, `**자동조사 요약**: \u003Ctext>`. **Field definitions are form-agnostic**: the table-form definitions above (N counter derived as max+1, etc.) apply identically — the forms differ only in notation, the field semantics are single. **Last-entry removal edge case**: if a `dropped` removal deletes the last `### N.x` sub-section, leaving 0 entries under `## 미해결 이슈`, the lead inserts the one-line note *\"이번 walkthrough에서 모든 미해결 이슈가 해소되었습니다.\"* as prose right after the heading. The heading itself is kept.\n\n`상태` values (5+1 states → 6-value Korean vocabulary):\n\n| Internal state | Korean value | Meaning |\n| --- | --- | --- |\n| pending | `대기` | discovered, unprocessed |\n| investigating | `조사중` | auto-investigation in progress (ephemeral) |\n| awaiting-decision | `결정대기` | investigation done, awaiting user input (ephemeral) |\n| resolved | `해결` | decision applied, reflected in the doc body |\n| deferred | `보류` | deferred via per-issue defer or abort |\n| dropped | `제외` | judged a non-issue by auto-investigation — **transient classification only** (the `제외` judgment exists in lead memory only; right after user confirmation the entry is deleted from the doc, and no `상태: 제외` annotation remains) |\n\nAdditional invariants:\n\n- **Mixed-form prohibition**: within a single doc's `## 미해결 이슈` section, do not mix table form and sub-section form. The doc keeps whatever form Step 4 chose; the walkthrough never converts forms. This binds this skill only when it writes the section anew: an audit or a re-convergence adds an entry carrying `**구현 처분**` below a table in sub-section form, by `${CLAUDE_SKILL_DIR}\u002F..\u002F_common\u002Funresolved-closure.md` (`## 작성자 꼴`).\n- **Entries left open carry `**구현 처분**`**: before the freeze, every entry left at a `상태` other than `해결` — `보류` above all — carries `**구현 처분**` and its companion field, chosen and written by `${CLAUDE_SKILL_DIR}\u002F..\u002F_common\u002Funresolved-closure.md` (`## 값 고르는 기준`, `## 작성자 꼴`).\n- **Fresh section default**: if the Step 4 output has no `## 미해결 이슈` section (synthesis judged 0 issues), the walkthrough uses **sub-section form** by default when creating the section (avoids table layout overhead at 0 rows).\n- **Marker absence → `상태: 대기`**: if an entry exists but has no `상태` marker, the walkthrough interprets it implicitly as `상태: 대기`. A marker is written to the doc only at the moment of a user decision; there is no retroactive bulk-write. This is the migration policy for pre-existing docs written without markers.\n\n#### Depth Management (single section + inline marker)\n\nRe-review and auto-investigation can surface new issues. Depth markers prevent infinite recursion:\n\n- **`(깊이: 1)`** — an item the lead surfaced independently during walkthrough re-review. doc-first Edit → queue-append → handled in the current walkthrough pass.\n- **`(깊이: 2)`** — an item surfaced during a depth-1 issue's **auto-investigation or team discussion**. doc-first Edit (default `상태: 보류` + `사유: depth-2 follow-up (parent \u003Cissue title> §\u003Canchor>)` + a `Parent: \u003Cissue title> (§\u003Canchor>)` field — `사유` is the short citation, `Parent` is the structured follow-up field; both render the parent as \"issue title + §anchor\") → NOT queue-appended → re-enters as `(깊이: 1)` on the next walkthrough invocation.\n- **`(깊이: 3)` and beyond is structurally impossible** — a `(깊이: 2)` item never enters the current queue, so nothing can surface during its investigation.\n- **Marker conversion on re-entry**: when a depth-2 item enters as depth-1 on the next walkthrough invocation, the doc's `(깊이: 2)` marker becomes `(깊이: 1)` and `상태: 보류` becomes `상태: 대기` together (keeping doc state and queue state in agreement). The `Parent` field is preserved as historical metadata so a later user can trace the discovery context. **Original Step 4 output items (no depth marker) are treated as implicit depth-1** — no marker need be attached.\n\nDo **not** create a separate sub-section (`## 워크스루 후속 항목`). All items stay integrated in the existing `## 미해결 이슈 \u002F 트레이드오프` section as a single source of truth; downstream tools parse just that one section.\n\n**Announce timing**: right after a parent depth-1 issue enters a terminal state (resolved\u002Fdeferred\u002Fdropped), announce in Korean — in **one combined message** — all depth-2 items identified while processing that issue (both lead auto-investigation and team discussion sources). Example form: `? parent \u003Cissue title> 처리 중 depth-2 N건 식별 — 다음 walkthrough에서 자동 표면화: [\u003Ctitle>, \u003Ctitle>, ...]`. depth-2 items are default-deferred, so no user decision input is required (announce only). If there are 0 depth-2 items, skip the announce.\n\n#### Per-issue Processing Flow (hybrid)\n\n> **One issue per question (invariant)**: every question in this step carries **exactly one issue** — one question of a `mcp__cc-cmds__question_form` form, or one `AskUserQuestion` call on the fallback path. On the form path a round's form carries every issue now in `awaiting-decision`, one question each, with that issue's full per-category menu; the form has no option cap, so **Cap-handling** below does not fire there. On the AUQ fallback path each call still carries exactly one issue, the up-to-4-questions capacity is never used to bundle issues, and the 4-option cap and **Cap-handling** apply unchanged. The per-issue mechanisms — auto-investigation, the `← 추천` recommendation, the UC `더 논의` follow-up loop, the dropped-confirm prompt and mid-flight reclassification — are per question: investigation finishes before the form opens; a non-terminal answer (`더 논의`, `그래도 유지`, an approved `팀 토론 진행`'s composition question, 미답) carries its issue to the next round's form; team spawns stay one issue at a time.\n>\n> > **Old heading** (for re-deriving citations): \"One issue per surface (invariant)\" - one form carries many questions, so the unit of the invariant is the question\n\nFor each issue:\n\n1. **Auto-investigation (lead-only, read-only + reproducible)**:\n    - UD: Read doc context only.\n    - UC: `grep` for the assumed convention in the project's primary source tree (e.g. `src\u002F**`, `plugins\u002F**`, `app\u002F**` — the lead adapts to the project's convention); optional `make test`.\n    - UA: Read each option's affected files + cost estimate (line-count delta, etc.).\n    - UR: Read the tradeoff framing only. **Reproduction pointer (Surfaced-at: Step 4 synthesis, body references `§재현·근본원인`)**: when surfacing it, the Why-it-matters \u002F framing text must **quote** the canonical section's `근거 등급: 가설(추측)` value (read-only reference, not a stored copy) so the user sees the hypothesis grade at decision time without manually following the anchor.\n    - Hard limits: stop as inconclusive if `grep` returns >50 hits; stop if `make test` exceeds 2 min. If the result is inconclusive, surface it as *\"조사 inconclusive — 사용자 판단 필요\"*.\n2. `등급 2` **Surface as that issue's question in the round's form (one `AskUserQuestion` call on the fallback path), Korean** with: a one-line Title; a Category tag (UD\u002FUC\u002FUA\u002FUR — fits the 12-char `header` chip limit); Why-it-matters (1-2 lines); the auto-investigation summary (the findings, or *\"조사 불필요\"*); Options (the per-category menu below — also apply the recommendation rendering check from the **Lead recommendation policy** paragraph: when auto-investigation is confident, move the recommended option to position 1 with `← 추천` and place the rationale in its `description`); and a Doc reference (`§ anchor`).\n3. **Apply the user's decision**:\n    - Direct resolution → mark `상태: 해결` + reflect the decision in the doc body. A UC \"다르게 수정\" response also maps here (the lead Edits the doc body per the user's correction + `상태: 해결`).\n    - Defer → `상태: 보류` + record a reason (format `사유: 사용자 결정 보류 (\u003Cdate YYYY-MM-DD>)`).\n    - Drop (the dropped branch, UC only) → after user confirmation the entry is REMOVED from the doc. **Trigger condition**: branches only in the UC category when the lead's auto-investigation finds the issue is a false positive (already resolved in the doc body \u002F codebase convention matches the assumption). **User-confirmation mechanism**: surface the false-positive finding as that issue's question, which carries the dropped-confirm menu instead of the UC menu (a **separate `AskUserQuestion`** on the fallback path) — body *\"이 항목은 §X에서 이미 다뤄지고 있어 미해결 이슈에서 제거하려 합니다.\"*, options *\"확인 \u002F 그래도 유지 \u002F 보류\"* (each option carries a 1-line `description` per the **Description requirements** subsection below — `확인` uses the hybrid `\u003Cstatic semantics> — 근거: \u003Cfalse-positive evidence> (\u003Cpath:line>)` form, `그래도 유지` and `보류` use static descriptions). On user confirm, Edit the doc to delete the entry — removed immediately, no `상태: 제외` annotation. On \"그래도 유지\", enter the normal UC menu (맞음 \u002F 다르게 수정 \u002F 더 논의 \u002F 팀 토론 진행). UD\u002FUA\u002FUR have no dropped branch — they require user value judgment, so a false-positive verdict is impossible.\n    - Redesign (a UR option) → `상태: 보류` + `사유: 재설계 필요 — Step 6 refinement에서 처리`. The walkthrough does not redesign directly; it defers.\n    - Discuss further (a UC option) → the issue returns in the next round's form with the lead's reply in `detail` and the person's in the note (an `AskUserQuestion` follow-up on the fallback path); the lead continues the dialogue until the user picks one terminal option among \"맞음\" \u002F \"다르게 수정\" \u002F \"보류\" \u002F \"팀 토론 진행\". It has no terminal state of its own.\n    - Run a team discussion → the spawn flow below.\n    - No answer (`미답`, form path) → the issue rides in the next round's form unchanged. When the same issue comes back `미답` twice in a row → `상태: 보류` + `사유: 사용자 미답 (\u003Cdate YYYY-MM-DD>)`.\n\n#### Per-category Option Menu + Team Spawn\n\nEvery option in a per-category menu carries a 1-line `description` field. For options recommended via `← 추천`, the description follows the format `\u003Csemantics> — 추천 근거: \u003Cevidence>` with citation tokens per the **Lead recommendation policy** paragraph; otherwise it is the per-label static text tabulated in the **Description requirements** subsection.\n\nEach category's user-facing options (Korean). **Default ordering**: direct-resolution options first, then `보류`, then `팀 토론 진행` (escalation gradient). **Recommendation override**: when the auto-investigation is confident, the recommended option moves to position 1 with `← 추천` appended; the remaining options preserve their relative ordering. **Conditional inclusion exception**: for UD\u002FUA menus with `K_pick ≥ 3`, structural-slot visibility (`보류`·`팀 토론 진행`) follows the branch (a)\u002F(b) layout in the **Lead recommendation policy** paragraph — both may be pinned (branch a) or hidden from the visible options array (branch b), with hidden items reachable via the AskUserQuestion `Other` channel. Default ordering applies only when conditional inclusion does **not** fire (UC\u002FUR menus, or UD\u002FUA with `K_pick ≤ 2`). Note the structural slots appear *where present, in the order `보류` → `팀 토론 진행`* — not every in-scope menu has both: the UC initial menu (`맞음 \u002F 다르게 수정 \u002F 더 논의 \u002F 팀 토론 진행`) has no `보류` slot and places `더 논의` before `팀 토론 진행`; the UR menu (`수용 \u002F 재설계 \u002F 보류 \u002F 팀 토론 진행`) and UC sub-loop (`맞음 \u002F 다르게 수정 \u002F 보류 \u002F 팀 토론 진행`) have both. The UC dropped-confirm confirmation dialog (`확인 \u002F 그래도 유지 \u002F 보류`, no `팀 토론 진행`) is **not** an escalation-gradient menu — it follows its own carve-out ordering and is excluded from this default-ordering rule. See the **Lead recommendation policy** paragraph below for the confidence criterion + cap-handling rules.\n\n| Category | Options |\n| --- | --- |\n| UD | (1-4 issue-specific concrete picks) + \"보류\" + \"팀 토론 진행\". A single concrete pick (binary confirm-only scenario) is also allowed — present the lone option as \"이대로 적용 \u002F 보류 \u002F 팀 토론 진행\". Picking a concrete pick maps to the \"direct resolution\" branch above. |\n| UA | (option A \u002F option B \u002F ...) + \"보류\" + \"팀 토론 진행\". The user's option choice maps to \"direct resolution\"; the lead records an alternatives-considered note when Editing the doc. |\n| UC | \"맞음 \u002F 다르게 수정 \u002F 더 논의 \u002F 팀 토론 진행\" (initial). **Mapping**: \"맞음\" → the \"direct resolution\" branch (the user confirms the lead's assumption interpretation; mark `상태: 해결` — the bare value, never with a note on the same line (`${CLAUDE_SKILL_DIR}\u002F..\u002F_common\u002Funresolved-closure.md`, `## 작성자 꼴`) — but do NOT add a `사유` field — `사유` is reserved for the `보류` state in this spec; instead add the inline note *\"사용자 confirm: 가정 정확.\"* at the end of the doc entry, with the body unchanged). \"다르게 수정\" → the same \"direct resolution\" branch. **UC's initial menu deliberately omits \"보류\"** — to prevent the user from skipping the issue without reviewing the auto-investigation summary; \"보류\" is reachable only inside the sub-loop after the user explicitly enters dialogue via \"더 논의\". On \"더 논의\" the sub-loop is entered, and its terminal option set is \"맞음 \u002F 다르게 수정 \u002F 보류 \u002F 팀 토론 진행\" — \"더 논의\" is replaced by \"보류\" to prevent infinite dialogue. |\n| UR | \"수용 \u002F 재설계 \u002F 보류 \u002F 팀 토론 진행\". Picking \"수용\" maps to the \"direct resolution\" branch (`상태: 해결` + a tradeoff-acceptance note in the doc body — `사용자 acknowledged tradeoff: \u003Coriginal tradeoff framing>`). |\n\nSee the **Description requirements** subsection below for per-option description format (recommended-option rationale form + per-label static descriptions).\n\n**Lead recommendation policy**: when the auto-investigation meets the per-category confident criterion — **UC**: grep returns 3–50 hits with ≥80% alignment to one verdict and no canonical-surface counter-example; **UA** (ANY of): cost delta ≥2× on line-count with affected-file count not inverted, OR one option has a hard blocker the other lacks, OR one option touches a doc-marked frozen\u002Fno-touch path the other doesn't; **UD** (ALL of): a parallel decision already committed elsewhere in this saved doc anchors the pick (cited as `§\u003Canchor>`) AND one of the offered options aligns with that committed pattern AND the doc records no \"this case is different\" rationale — never on lead taste; **UR**: blast radius scoped to ≤1 module with no concrete lower-cost alternative cited (→ `수용`), or ((blast radius ≥2 modules) OR (critical path: auth\u002Fpayment\u002Fdata integrity\u002Fpersistence schema\u002Fpublic API contract)) AND (a concrete cited alternative without prior rejection rationale) (→ `재설계`), or the tradeoff explicitly references cross-team coupling \u002F out-of-scope expertise AND ≥2 distinct expert roles would weigh in differently (→ `팀 토론 진행`), or the issue is downstream of a depth-1 parent currently in `상태: 대기` or `상태: 결정대기` (→ `보류`); **NONE-good case**: when the lead is confident no listed option fits because of a doc-cited gap (`§\u003Canchor>` constraint that all options miss, or a blocker absent in `\u003Cevidence path>` that all options require), force `팀 토론 진행 ← 추천` with the gap citation in the rationale — without a specific gap citation this case degrades to inconclusive.\n\n**Recommendation contract**: the lead applies the documented `AskUserQuestion` recommendation convention — append `← 추천` to the recommended option's label, force it to position 1, and place the rationale in that option's `description` field. The description follows the format `\u003Csemantics> — 추천 근거: \u003Cevidence>` where `\u003Csemantics>` is a brief (≤10 Korean syllable) action\u002Fresult summary (긴 UD\u002FUA pick label로 인해 ≤10 음절을 약간 초과해야 의미 보존이 가능한 경우 soft over-flow 허용 — semantic clarity가 우선) and `\u003Cevidence>` carries the rationale. The description MUST be ≤2 sentences, ≤140 chars, and `\u003Cevidence>` MUST carry at least one citation token (code path `:line`, `§\u003Canchor>`, a quantitative measurement such as `affected files: 4` \u002F `~4×` \u002F `12\u002F12 hits`, or a blocker fact `requires X, absent in \u003Cevidence path>`). Opinion phrases (`cleaner`, `simpler`, `idiomatic`, `common practice`, `I think`, `feels like`) are forbidden unless paired with a citation token in the same sentence; this citation\u002Fdenylist rule applies only to descriptions of options carrying `← 추천` — static descriptions on non-recommended options are display-only and exempt. All four options are eligible candidates — including `팀 토론 진행` and `보류` — provided their confidence criterion is met. When the criterion fails (grep results split outside 80\u002F20, cost delta within 1.5×, no parallel anchor for UD, mixed UR impact, NONE-good without a gap citation, any auto-investigation hard limit tripped), the lead refuses to recommend: Why-it-matters surfaces *\"조사 inconclusive — 사용자 판단 필요\"* and the menu renders in default order with no `← 추천` suffix. Why-it-matters never duplicates the rationale (that lives only in the recommended option's `description`); when confident it is framed as *\"결정만 내리면 적용 가능\"*.\n\n**UC sub-loop interaction**: the prior recommendation is suppressed by default on first sub-loop entry — re-computation is permitted only if (a) a new auto-investigation pass with materially different inputs still meets the confident criterion, or (b) the dialogue surfaces a previously-unrecorded fact that flips the alignment ratio; in both cases the description must cite the new evidence. \"Previously-unrecorded\" means the fact is absent from the original `AskUserQuestion` surface's auto-investigation summary text — the lead's in-session memory of earlier turns does NOT qualify.\n\n**Dropped-confirm prompt carve-out**: the UC false-positive prompt (body: *\"이 항목은 §X에서 이미 다뤄지고 있어…\"*) is structurally a confirmation dialog (binary accept \u002F override \u002F punt), not a pick-one-among-equals menu — `← 추천` is **NOT** applied to its `확인` option (the prompt body already asserts the lead's verdict; adding the suffix would double-signal and friction `그래도 유지`). Its `확인` option uses a hybrid description form `\u003Cstatic semantics> — 근거: \u003Cfalse-positive evidence> (\u003Cpath:line>)` (with `근거:` prefix, NOT `추천 근거:` — the segment is a fact statement, not a recommendation rationale); the citation\u002Fdenylist rules of this paragraph do NOT apply to that hybrid form. The hybrid form still respects the recommended-option ≤140 chars \u002F ≤2 sentences hard limits.\n\n**Cap-handling — conditional inclusion (category-agnostic)**: when concrete picks plus structural slots `보류`\u002F`팀 토론 진행` would exceed AskUserQuestion's 4-option cap (i.e., K_pick ≥ 3 in UD\u002FUA), the menu undergoes **conditional inclusion** rather than blanket collapse. **Branch (a) — when the recommended option is `보류` or `팀 토론 진행`**: both structural slots are pinned (recommended at position 1; the non-recommended structural is placed at the position it would occupy in the canonical order `[picks..., 보류, 팀 토론 진행]` after removing the recommended item and shifting remaining items up — typically position 4 since `팀 토론 진행` is canonical-last, and `보류` lands at position 4 when `팀 토론 진행` is recommended), and the `K_pick − 2` lowest-priority concrete picks are dropped per a worst-cascade rule (hard blocker → deprecated-path overlap → frozen-path overlap → largest line-count delta ≥1.5× → doc-order LAST tiebreaker; continue-on-tie within tied subset). The 2 surviving picks fill the visible pick slots in canonical relative order. **Branch (b) — when the recommended option is a concrete pick OR the result is inconclusive**: both structural slots are **hidden** from the options array but remain reachable via the AskUserQuestion `Other` channel — the user types `보류` or `팀 토론 진행` (NFC-normalized + whitespace-normalized including U+3000 → U+0020, exact-match against canonical Korean tokens) and the lead processes the input identically to a menu selection. Hide ≠ collapse: the decision path remains open via `Other`, so the *\"`보류`\u002F`팀 토론 진행` never collapse\"* commitment is preserved; only the visible slot is reassigned under cap pressure when no recommendation endorses them. K_pick ≤ 2 (option count ≤ 4) skips conditional inclusion entirely — both structural slots are always shown. **Disclosure**: when conditional inclusion fires, the Why-it-matters companion text discloses the dropped picks (branch a, format `옵션 캡(4)으로 \u003CK_pick>개 픽 중 \u003CX>건 생략 — 생략 픽: \u003Clabel1>, \u003Clabel2>, ...`) or the Other-channel reachability of `보류`\u002F`팀 토론 진행` (branch b, format `보류·팀 토론 진행은 Other 채널에 '보류' 또는 '팀 토론 진행' 입력 시 동일 처리.`) so the user audits the option-set difference. Branch (b) carries the Other-channel disclosure whenever conditional inclusion fires (`K_pick ≥ 3`), and additionally appends the dropped-picks disclosure when `K_pick > 4`. **Multi-session consistency**: the cascade is stateless — re-computed from scratch on each AskUserQuestion call, no drop-state persistence in the doc.\n\n**Mid-flight reclassification**: if auto-investigation reveals a category change (UC→UD\u002FUR, UA→UD), the lead Edits the doc's `Category` field, surfaces with the new menu, and re-applies the new category's confident criterion. **Investigation-time only**: once `AskUserQuestion` has entered `awaiting-decision`, the prompt is immutable; if reclassification surfaces late, the lead applies one of two fallbacks. **(i) Apply-then-defer** (when the user response is `보류` only): apply the user's 보류 as the resolution, Editing `Category` field first, then `상태: 보류 + 사유` where `사유` is always lead-generated in the canonical defer-branch form `사유: 사용자 결정 보류 (\u003Cdate YYYY-MM-DD>) (재분류됨: \u003Cold-cat> → \u003Cnew-cat>)` (no user-reason-collection branch — there is no free-text input channel on the `AskUserQuestion` fallback path, and on the form path the note is the user-reason channel; the `\u003Cdate>` stamp + `사용자 결정 보류` prefix are mandatory per the cross-issue defer convention). **(ii) Immediate-defer** (default for any other response, including `팀 토론 진행`): `상태: 보류` + `사유: 재분류 필요 — 다음 walkthrough에서 처리`; the user's response is discarded because original-category interpretation can be invalid under the new category (team-spawn flow especially is category-coupled and would synthesize under wrong category if (i) were used). The lead's text response discloses the reclassification to avoid silent doc mutation, with distinct messages per case — case (i): *\"방금 보류 결정을 적용했습니다. 참고로 이 이슈의 Category가 \u003Cold> → \u003Cnew>로 재분류되었습니다.\"*; case (ii) (the consequential one — a discarded user selection must be explained): *\"재분류(\u003Cold> → \u003Cnew>)이 발견되어 이 이슈는 다음 walkthrough에서 새 카테고리로 다시 surface됩니다. 방금 선택하신 응답은 새 카테고리의 메뉴 의미가 다를 수 있어 적용하지 않았습니다.\"*\n\n**Team-spawn coupling**: recommending `팀 토론 진행` does NOT preload the team composition into this `AskUserQuestion` prompt — the role\u002Fscope\u002Fmodel proposal remains the separate downstream step described in the Team Spawn Flow below, preserving the two-layer approval (entry into the team flow vs. composition approval). **Display-layer fence**: the entire recommendation mechanism is a display-layer concern on `awaiting-decision`: no new states, no doc markers, no transition edges, no checkpoint format changes.\n\n#### Description requirements\n\nEvery option in a per-category `AskUserQuestion` menu carries a 1-line `description`. For the recommended option (when present), the description follows the format `\u003Csemantics> — 추천 근거: \u003Cevidence with ≥1 citation token>` and must satisfy the citation-token allowlist + denylist rule defined in the **Lead recommendation policy** paragraph above. For all other options (non-recommended in a recommended menu, and all options in an inconclusive menu), the description is a static 1-line semantics text fixed per label as tabulated below. **This table is the single source of truth for static option semantics** — when the per-category option menu's decision branches (the menu table preceding this subsection) are amended, the static description for the affected label MUST be updated atomically in the same edit.\n\n| Label | Static description |\n| --- | --- |\n| 수용 | 현재 트레이드오프를 인정하고 해결됨으로 표시합니다. |\n| 재설계 | 보류 처리 후 Step 6 refinement에서 재설계합니다. |\n| 보류 | 지금 결정을 미루고 나중에 처리합니다. |\n| 팀 토론 진행 | 전문 팀을 구성해 이 이슈를 심층 논의합니다. |\n| 맞음 | 가정이 정확합니다. 해결됨으로 표시합니다. |\n| 다르게 수정 | 가정 내용을 직접 수정합니다. |\n| 더 논의 | 리드와 추가 대화를 진행한 뒤 결정합니다. |\n| 확인 | 이 항목을 문서에서 즉시 삭제합니다. |\n| 그래도 유지 | 이 항목을 유지하고 정상 UC 메뉴로 진행합니다. |\n| UD concrete picks | `\u003C해당 값>으로 확정합니다.` (dynamic — `\u003C해당 값>`은 이슈가 surface한 개별 pick 라벨) |\n| UA option picks | `\u003Coption name>으로 구현합니다.` (dynamic — `\u003Coption name>`은 이슈가 surface한 개별 alternative 라벨) |\n\n**Dynamic pick recommendation form** (UD\u002FUA concrete pick이 추천 옵션일 때): 위 dynamic static template (`...합니다.`)을 그대로 description에 쓰지 않고, `\u003Csemantics>` slot에 verb-stem 형태 (trailing `합니다.` 제거) 로 변환한 뒤 recommended-option format 적용한다. UD 예: `\u003C해당 값>으로 확정 — 추천 근거: \u003Cevidence>`. UA 예: `\u003Coption name>으로 구현 — 추천 근거: \u003Cevidence>`. trailing 마침표 제거는 em-dash separator의 명확성을 보존하기 위함이며, `\u003Csemantics>` slot의 ≤10 음절 budget 적용 (긴 `\u003C해당 값>` \u002F `\u003Coption name>` 라벨의 경우 ≤10 약간 초과 가능; 의미 명확성 우선).\n\n**Dropped-confirm prompt exception** (third description type): the UC false-positive prompt's `확인` option uses a hybrid format — `\u003Cstatic semantics> — 근거: \u003Cfalse-positive evidence> (\u003Cpath:line>)` — with the `근거:` prefix (not `추천 근거:`) signaling fact statement rather than recommendation. The citation\u002Fdenylist rules of the **Lead recommendation policy** paragraph do NOT apply (the `확인` label has no `← 추천` suffix per the dropped-confirm carve-out); the evidence segment is descriptive rather than rationale. The hybrid form inherits the recommended-option ≤140 chars \u002F ≤2 sentences hard limits; if the evidence path exceeds budget, prefer a shorter `§\u003Canchor>` citation or relative path over the absolute path.\n\n**Team spawn flow** (when the user picks \"팀 토론 진행\"):\n\n1. The lead proposes a role\u002Fscope\u002Fmodel composition for that issue in Korean → user approval. If the user rejects or asks to revise the composition, the lead either (i) re-proposes a revised composition (repeatable), or (ii) if the user withdraws \"팀 토론 진행\", returns to that category's normal terminal option menu (direct resolution \u002F defer \u002F (UC only) drop branch \u002F (UR only) redesign \u002F (UC only) discuss-further, per category). **UC exposes \"보류\" directly in this fallback**: the user already engaged the issue actively via the team-spawn proposal, so UC's initial-menu gate (forcing auto-investigation review) no longer applies — the fallback's \"보류\" is deliberately directly reachable.\n2. Spawn the approved members as fresh nameless background tasks (`Agent`, `subagent_type: \"claude\"`, `run_in_background: true`, no name) and record each `agentId` in the ledger. **Stamp `epoch`** (`max(disk epoch, 0)+1`, re-derived from the on-disk ledger — never an in-context counter; this fresh walkthrough team → `epoch 2` in the normal sequence) **and the round-1 `witnessNonce`** on every one of its rows in the same at-spawn recording window as `agentId`\u002F`scratchDir`, per the protocol Spawn section. Create this fresh team's **own** witness dir with a fresh run of the protocol's `## Spawn` command — `\u003Cplugin root>\u002Forchestrator\u002Fcc-team-witness-init.sh {issue-slug}` (no `bash` in front — see the protocol's note) — and record the **printed path, literally** (not `$WITNESS_DIR`) as each member's `scratchDir`; the issue-discussion rounds are witnessed per `_common\u002Fagent-team-protocol.md`.\n3. English discussion → synthesis → the lead Edits the doc to reflect the decision. **Team result → state mapping**: (a) team agrees on a single resolution → `상태: 해결` + decision reflected in the doc body; (b) team agrees on \"recommend deferral\" → `상태: 보류` + reason `팀 토론 결과 추가 검토 필요`; (c) team finds depth-2 items → the doc-first handling above (recorded as separate entries + accumulated in the parent's announce); (d) team agrees a UC issue is a false positive → route to the dropped-confirm prompt above (entry REMOVED after user confirmation). In all cases the doc Edit completes before the team-cleanup in step 4.\n4. **Before entering the next issue or ending the walkthrough**: Read `${CLAUDE_SKILL_DIR}\u002F..\u002F_common\u002Fteam-cleanup.md` and apply it (returned tasks already self-terminated — no-op; `TaskStop` any `state=running` agentId; ledger hygiene).\n5. Proceed to the next queue item.\n\n#### Abort Semantics\n\n- Abort is detected by lead judgment (no regex matching). Examples:\n    - Full abort: \"그만\", \"중단\", \"이만 됐어\", \"리파인먼트로 넘어가자\", \"skip rest\".\n    - Single-issue skip: \"이건 패스\", \"다음 이슈\", \"이건 나중에\". On a skip, mark only the current issue `상태: 보류` + `사유: 사용자 per-issue skip, \u003Cskip date YYYY-MM-DD>` (distinguishable from the full-abort reason) and proceed to the next queue item. **Active team handling**: if a walkthrough-spawned team is active at skip time, apply `_common\u002Fteam-cleanup.md` (`TaskStop` any `state=running` agentId + ledger hygiene) before entering the next queue item — the same cleanup obligation as the full-abort path (cleanup-anchor doctrine).\n- On full abort, in ONE batched Edit mark all remaining `대기` \u002F `조사중` \u002F `결정대기` items `상태: 보류` + `사유: 사용자 조기 종료, \u003Cabort date YYYY-MM-DD, runtime-generated>`, then enter Step 6. (CFI-2)\n- If a walkthrough-spawned team is active (spawned, cleanup not yet done) at abort time, clean it up via `_common\u002Fteam-cleanup.md` (`TaskStop` any `state=running` agentId + ledger hygiene) *before* the batch `보류` Edit. The issue in progress is included in the batch and marked `상태: 보류`.\n- If the user is viewing a UC dropped-confirmation prompt at abort time, the drop is auto-cancelled and that issue is kept in the doc, included in the batch as `상태: 보류` + `사유: 사용자 조기 종료 (drop 미확정, 재호출 시 재표면)`. No item is ever silently deleted without the user's explicit drop confirmation.\n\n### Step 6: Plan Refinement with User\n\n**State check on entry**: Re-read the ledger from disk (re-read — do not trust in-context copies; a missing\u002Funparseable block is fail-closed via `AskUserQuestion`). If the ledger has any residual `state=running` row (a Step 3 original-team member, any prior walkthrough-spawned member from Step 5, or any prior Step 6 refinement member still running), notify the user in Korean (*\"이전 단계의 팀이 아직 살아있어 정리 후 리파인먼트를 시작하겠습니다.\"*), then execute cleanup now (Read `${CLAUDE_SKILL_DIR}\u002F..\u002F_common\u002Fteam-cleanup.md` and apply it — `TaskStop` each `state=running` agentId, then ledger hygiene) before any Step 6 activity. A residual `state=running` row is the leftover-detection signal (it replaces the removed `teams\u002F` filesystem scan). The `\u003Cslug>` (the ledger key and `docs\u002F\u003Cslug>.md` filename) is recovered from the saved design document filename in `docs\u002F` (the filename encodes the topic slug per Step 4's save convention — local file-system state, not memory). **Preferred slug recovery**: the lead remembers the exact filename it saved in Step 4 (not mere \"most recent .md file\" — that may be unrelated to the design workflow if the project is actively edited elsewhere). If the lead cannot recall the exact filename, fall back to matching against `docs\u002F` modification times within a narrow window after Step 4, and if still ambiguous (multiple candidates), prompt the user via `AskUserQuestion` to confirm the target document. Never assume the most recently modified `docs\u002F*.md` is the design doc without validation. Because the ledger lives inside this workflow's own `docs\u002F\u003Cslug>.md`, every ledger row belongs to the current workflow's topic — there is no cross-matching of unrelated prior-session work. Any `state=running` row is treated as active and requires cleanup. Under normal flow, all prior members have already self-terminated and this step proceeds with the lead only. **Worktree gate (in-session verification cleanup)**: also run the two-command boundary gate (`_common\u002Fverification.md` §6) on entry, in full — assertion 1 and all three of 2a\u002F2b\u002F2c, not the `cc-design-exp-` count alone; force-remove (`git worktree remove --force`) + `git worktree prune` any mechanism-owned worktree that leaked from a prior step before proceeding.\n\n- On entering Step 6, emit ONE short Korean notice that the design document is ready for refinement and invite the user's input, then YIELD the turn and wait for the user's reply. At Step 6 ENTRY do NOT call `AskUserQuestion` to open the discussion or manufacture a refinement question (e.g. '무엇을 다듬을까요?'). Once the user replies, discuss the design document with them in Korean and refine the plan together. (CFI-2)\n- Lead-only by default: doc edits, user Q&A, and codebase re-exploration require no team.\n- If the user raises questions requiring deeper investigation that exceed lead-only capacity, verify the ledger shows no residual `state=running` row (if one remains, notify in Korean: *\"새 리파인먼트 팀을 만들기 전에 기존 팀을 먼저 정리하겠습니다.\"* and execute cleanup), then propose composing a **new** team for that specific investigation — mirror Step 2 (role\u002Fscope\u002Fmodel proposal → user approval → spawn the members as fresh nameless background tasks recorded in the ledger). **A Step 6 investigation team is always a NEW team — never a reused or restarted prior design team.** The closed list of prior-team re-convenings that *are* permitted anywhere in this skill is in `## Constraints` → **Permitted team resumes**; no Step 6 investigation is on it.\n- Only create a new team if the user approves. Otherwise, continue refining in the current session.\n- If a new team is created, spawn its members as fresh nameless background tasks (`Agent`, `subagent_type: \"claude\"`, `run_in_background: true`, no name) recorded in the ledger (**stamp `epoch` = `max(disk epoch, 0)+1`, re-derived from the on-disk ledger — never an in-context counter; this fresh refinement team → `epoch 3` in the normal sequence — and the round-1 `witnessNonce` on every row in the at-spawn recording window, per the protocol Spawn section**) — each fresh refinement team gets its **own** nested witness dir from a fresh run of the protocol's `## Spawn` command, recorded as the rows' `scratchDir`, and its rounds are witnessed per `_common\u002Fagent-team-protocol.md`. Conduct internal discussion in English. After discussion converges and results are synthesized, update the saved document in `docs\u002F`. Then notify the user in Korean: *\"리파인먼트 팀을 정리한 뒤 후속 논의를 이어가겠습니다.\"* **Before creating the next refinement team or returning to user discussion, Read `${CLAUDE_SKILL_DIR}\u002F..\u002F_common\u002Fteam-cleanup.md`** and apply it (returned members self-terminated — no-op; `TaskStop` any `state=running` agentId; ledger hygiene). Present the updated results to the user in Korean.\n- Repeat until the user is satisfied with the plan. That satisfaction signal is the ONLY exit from Step 6, and it enters Step 7 automatically in the same turn (CFI-3a).\n\n---\n\n### Step 7: Class C Coherence Pass & Freeze (document-wide, single-pass, non-recursive)\n\n**What this pass is.** ONE document-wide coherence-and-completeness check of the FINAL text, run by the **Step 3 discussion team**. It is not the Step 4 fidelity pass repeated — the two answer different questions. Fidelity asks *\"did synthesis distort or drop what I said?\"* and is meaningful only immediately after synthesis. This pass asks *\"is the whole document coherent and complete?\"* and is meaningful only on the final text, after Step 5's walkthrough decisions and Step 6's refinements have landed. Both passes exist; neither replaces the other. Because it runs on the final text, \"single-pass and non-recursive\" here means **once over what actually ships**.\n\n**Why the authoring team, and why it cannot be deferred.** Context-dependent defects — a Step 5 or Step 6 decision that contradicts a requirement confirmed in the Step 1 interview, an architecture point discussed but never written down — leave no evidence in the artifact. A fresh reader's sensitivity to them is structurally **zero**, not merely low, because the evidence it would need is not in the document. The authoring team is the only non-zero channel, and its context dies when `design` ends. So this pass cannot be handed to any later command; a downstream audit covers the complementary class, not this one.\n\n**Single-pass and NON-RECURSIVE (hard).** Exactly one pass over the final text. The lead does NOT re-submit the pass's own corrections for another round — reviewing its own output would reproduce, inside `design`, the generator this pipeline removed. (CFI-3b)\n\n**Roster scoping (mandatory, before any dispatch).** The Step 3 team is `epoch 1`, but Step 5 and Step 6 may have spawned fresh teams at `epoch 2`, `3`, … — and Step 6 loops, so the maximum is not statically knowable. Apply the protocol's **re-convened prior team — `epoch` re-stamp** (`_common\u002Fagent-team-protocol.md`, Spawn): re-derive `epoch := max(disk epoch, 0) + 1` from the on-disk ledger and write it onto **every Step-3 row**, one single-row Edit per row, all in one contiguous window, before the first `coherence` dispatch and alongside each row's `coherence` `witnessNonce`. **Never hard-code the value.** After the re-stamp the roster's `max(epoch)` over non-aborted rows resolves to exactly the Step 3 team; without it the roster resolves to the last fresh team and self-heal would consume a foreign-role member's output as this pass's product. The re-stamp is written by the leg, in the leg's session, because the leg is the session that dispatches into those rows and owns any same-key resume of the members it dispatches.\n\n**Procedure**\n\n1. **Re-read the ledger from disk** (never in-context copies; missing or unparseable is fail-closed via `AskUserQuestion`). If any `state=running` row survives from Step 5 or Step 6, Read `${CLAUDE_SKILL_DIR}\u002F..\u002F_common\u002Fteam-cleanup.md` and apply it first.\n2. **Precondition — does the leg's team still exist on disk?** `stat` `${CLAUDE_CONFIG_DIR}\u002Fprojects\u002F*\u002F\u003Csession_id>\u002Fsubagents\u002F`, globbed by the leg's `session_id` from `leg.json` (never re-derive the project key). Present → the primary path (3). Absent → that is the transcript loss, and it is one of exactly **two** triggers of the fallback (3'). The other is the pull-check ladder's step-8 death while `phase` is `resume`, where rung 1r is forbidden precisely because a re-dispatched leg would save over this document. There is no third trigger.\n3. **Primary path — the resumed leg dispatches its own team's roles afresh.** The seat writes `phase: resume` together with `state: pending` into `leg.json`, in one atomic write — the discuss-phase consumption left `state: done`, and without `pending` the pull-check that observes `coherence.md` never runs (CFI-1b). It then writes the coherence message — the final document's **path** plus every `[Step 7 정합 점검 대상]` note the Step 5 router queued (there may be none); the document is never embedded — to a resume file `$STATE\u002Fresume.\u003CISO8601>.txt` and sends it through the resume line of Step 2's dispatch block (item 6), which passes that file as `$(cat …)` command substitution and never inlines the message on the command line (the notes are backtick-heavy Markdown), and yields as in CFI-1a. Inside the leg: re-stamp the Step-3 rows' `epoch` per the paragraph above (a precondition of dispatch, not an optimization), write each row's `coherence` `witnessNonce` **before** the dispatch and flip the row (`agentId`, `outputFile`, `round\u002Fphase`, `state`, `stallMark`) **after** it, dispatching each Step 3 role afresh at the new `epoch` — a new key, so a new dispatch under `## Constraints` → **Permitted team resumes** — with phase token `coherence` (colon-free, per the protocol), the task-assignment header from `_common\u002Fagent-team-protocol.md` embedded verbatim, the member's own past witnesses by path, and the whole final document read by path. This is the same class of input as the fallback (3') — what was written to disk, no retained context — but not the same input: the fallback reads the whole durable corpus and the brief. **Serialization clause**: from the moment the coherence turn is dispatched until its artifact (`$STATE\u002Fcoherence.md`, header `\u003C!-- cc-design-coherence v1; writer=design-discuss-unattended; reader=design; slug=\u003Cslug> -->`) is observed, the seat does not edit the document; the leg writes the ledger block only and never writes prose. Two processes with no lock between them are otherwise concurrent writers of the very document being frozen.\n    - 3'. **Fallback (only on one of step 2's two triggers).** Respawn the Step 3 roles **fresh at a new `epoch`** from the durable witness corpus (`$STATE\u002Fwitness\u002F`: every round and phase witness, each member's rendered dispatch prompt, and `INDEX.md`), the brief, and the final document by path. `INDEX.md`'s `lead`\u002F`sweep` row and `SWEEP.md` are not member roles: neither is respawned nor put on the roster. Class C sensitivity here is partial, not zero: what was written anywhere is recovered — a Step 5\u002F6 decision contradicting a Step 1 requirement is *more* detectable than today, because the brief is the interview's durable record — and what was thought but never witnessed is not.\n4. Emit ONE one-way Korean notice at entry (not a question): *\"팀이 최종 문서의 전체 정합성을 점검하고 있습니다.\"*\n5. **Collect by witness** — each member publishes `${scratchDir}\u002F{role-slug}.coherence.md` (sentinel\u002Fnonce per the protocol; the return text is only an early-wake hint and the collector reconciles the witness, never the return). Case-1 (thin\u002Fempty witness) and Case-2 (never-returns) handling is identical to the Step 4 fidelity pass's, with `coherence` substituted for `fidelity`. The finding blocks keep a free shape, but each witness ends, above its sentinel, with one line of its own `findings: \u003Cn>` (`findings: 0` when it found nothing); a coherence witness without that line is a Case 3 non-conforming witness (`_common\u002Fagent-team-protocol.md`) — re-instruct the member and take its `coherence-rev\u003Ck>` revision. The count is the line's value; it is not checked against the blocks. A missing witness is NEVER read as \"no objection\". On the primary path the leg collects and returns its findings in `coherence.md`; the seat's pull-check observes that file.\n6. **Triage and apply — ONE time, by the seat, after the leg's turn has ended.** The lead applies corrections directly from `coherence.md`. A finding that contradicts a converged decision does **not** reuse the fidelity pass's re-convergence cycle. That cycle opens by messaging the affected author, and here nobody can: the authors' `coherence` dispatches belong to the leg, a same-key resume is addressable only from the session that dispatched the member, and the leg's turn has ended by the time this step runs — so the borrowed procedure's first step has no executor while only its terminus does. The seat raises such a finding to the user itself — `등급 2` — naming the finding, the converged decision it contradicts and what each answer costs, and applies the answer directly. That is the seat's only channel, not an abbreviation of the team cycle; Step 4's fidelity pass keeps its own cycle, which runs inside the leg where the authors are addressable. Do NOT re-dispatch the team over the corrected text. Clear each consumed `[Step 7 정합 점검 대상]` note as its item is disposed of, so no queue marker survives into the frozen bytes.\n7. **Cleanup** — Read `${CLAUDE_SKILL_DIR}\u002F..\u002F_common\u002Fteam-cleanup.md` and apply it.\n8. **Slicing self-check (only when the document has a `## 구현 슬라이싱` section; the lead runs it, no team).** Downstream orchestration parses this section mechanically and cannot ask anyone what was meant, so five composition rules and two split rules are checked here — the last moment the authors are still alive — rather than discovered as a broken build hours later. **(a) Declared ⊇ actual.** For each `### 슬라이스 \u003Cid>` block, the files it declares must include every file the slice's own description says it edits; a slice that describes an edit it did not declare fails. **(b) A `SKILL.md` frontmatter change implies `README.md`.** A slice that creates a `SKILL.md` or edits a `SKILL.md`'s frontmatter must also declare `README.md`, because this repository's README is generated from skill frontmatter and a slice that changes one without the other lands a tree whose generator gate fails. A slice whose description confines its `SKILL.md` edits to the body leaves README unchanged and need not declare it — the driver no longer refuses that declaration, and a slice that regenerates README after all is parked as an edit outside its declared files. When the description does not say which part it edits, declare `README.md`. **(c) Two or more implement slices declare their residual share.** When the section holds two or more blocks whose `**스킬**` is `implement` and the document has a `## 구현 시 검증 항목` section, each such block carries `**잔여 항목**` naming the items it owns, or `없음` when it owns none; without it the driver reads that slice's share as empty and never asks its implement stage for those items' result lines. **(d) A new-grammar block gives a reason per kind.** A block carrying a `**머지 순서**` line carries `**선행 사유**` when its `선행` is not `없음` and `**머지 순서 사유**` when its `머지 순서` is not `없음`; the gate and the driver park a slice that lacks one as a missing required field. **(e) Closure disjointness.** For each slice S, its declared files are prefix-disjoint from every slice in M(S) \\ P(S) as defined under **Blocks and fields**, with no exemption for `README.md`, `plugin.json` or `CHANGELOG.md`; an overlap is repaired by turning the edge that brings the other slice into M(S) \\ P(S) into a `선행`, or by moving the file, never by dropping it from the declaration. **(f) Slice size.** For each block, count its declared files: one element is one file; an element ending in `\u002F` counts as the number of files `git ls-files -- \u003Celement>` prints in the design-time working tree of the repository the block's `**레포**` names, and at least 1 (1 when the design stage cannot read that repository's working tree — no checkout on this machine, or none visible where the design runs); `README.md`, `plugin.json`, `CHANGELOG.md` and test files count like any other file. A block over the baseline of **20** declared files is split into smaller blocks or carries `**크기 사유**`. **(g) One permission profile per slice.** This rule applies only to blocks whose `**스킬**` is `implement`. A work's permission profile is the `--reach` token the act would honestly carry when declared to the gate, and the designer judges it — the gate derives a token only from an argv being run, never from a slice declaration — and when no single token can be decided at design time it is `미상`. The base profile, which every implement slice holds, is the in-worktree reads, writes, commits and tests the gate asks no reach declaration for (derived `-`), `런로컬` (an act that reaches only this run's directory or the stage's prototype namespace) and `협업` (the push, PR and merge the cutpoint allows); `기기전역`, `dev`, `prod`, `배포트리거` and `미상` are each a separate elevated profile. A remote-capable tool (`docker`, `playwright`, `psql` and the like) is judged by the token its gate declaration would honestly carry even when it serves a local test, and a command that reaches a checkout outside the worktree (`git pull` and the like) never carries `런로컬`. A block mixes when its implementation work needs the base profile together with an elevated one, or two or more elevated profiles; a declared `**적용 명령**` counts too — its profile is that command's reach judged the same way, it counts whatever `**적용 주체**` says, and an elevated one mixes with the block's base profile. Mixing is counted by elevated act unit: one elevated act (an apply command, a machine-global install, an external service write), the declared files that exist only for that act (the script it runs, a deploy config or install list only it reads) and those files' test files; the artifacts the act ships or deploys (source, migrations, screens) and any file other work (build, local run, tests) also uses are outside the unit. A block whose declared files all belong to one unit and that has no elevated act outside it does not mix, whatever the kind of act and whatever `**적용 주체**` says. A mixed block either splits the unit off into a block of its own or carries `**권한 혼합 사유**`. The split's `선행` follows the real order: the unit of an apply command names the implementation block it deploys as `선행`, and a block that uses the act's result names the unit block as `선행`. When several blocks declare the same `**적용 명령**`, each is a separate elevated act that runs after its own block's merge, so split each block's unit off on its own and never gather the unit blocks into one; a unit file the original block edited moves with that edit into the unit block split from it, and two unit blocks that declare the same unit file are joined by the `선행` repair of (e). A unit block takes no common file (`README.md`, `plugin.json`, `CHANGELOG.md` and the like): when the unit block's work must edit one, when the elevated work must sit in the same commit as work outside the unit, or when the act has no declared file of its own (an apply command such as `git pull`), do not split, and write `**권한 혼합 사유**` on the original block. Repair the declaration in place (this is still a document edit, so it happens **before** the freeze, not after). If a failure cannot be repaired without a decision the authors did not make — the slice's file set is genuinely unknown — `AskUserQuestion` rather than guess: a wrong declaration is worse than a missing section, because the driver trusts it.\n   - The disposition of the two split rules. A reason names the one coupling a split would break, and a sentence that names none is not a reason; when the person gave the `슬라이스 수` answer, nothing is split and the reason field quotes that answer instead.\n   - Neither split rule asks or stops. A split the designer can decide is made, and otherwise the reason field is written. A split is a new declaration, so run (a) through (g) again on every block it made and bring the section's `**슬라이스 수**` checksum back into line.\n   - Finish a split in this order. The original block's id is kept by one of the new blocks and every other new block takes a new id. A block whose `선행` named the original id is changed to name the block that holds the work it waited for. The new blocks stand where the original block stood, never appended at the section's end: each one after every block its `선행` or `머지 순서` names, and before every block that now names it in either list — the driver runs the blocks once in section order and parks a block whose `선행` has not finished, and a `머지 순서` token naming a block declared later is a defect of the slice that carries it. The original block's `**잔여 항목**` and `**적용 명령**` move to the block that holds the work they cover, and `**적용 주체**` and `**폭발 반경**` move with `**적용 명령**`. The original block's edit description is divided so that each new block describes only the files it declares — an edit description left behind for a moved file fails that block's (a). Files the new blocks declare together (`README.md`, `plugin.json`, `CHANGELOG.md`) follow the repair of (e), a `선행` edge; a unit block split off by (g) takes none of them. Each new block writes the required fields (`**스킬**`, `**레포**`, `**선언 파일**`, `**선행**`, `**절단점**`), and when the original block carried a `**머지 순서**` line every new block writes one too, because without it the block reads as old grammar and loses its reason obligation; the block that received `**적용 명령**` inherits the original `**절단점**`, each other block takes the cutpoint its own work calls for, and the remaining fields (`**리뷰 정책**`, `**라벨 인정**`, `**화면**` and the like) are written on each new block to fit its work. Another block's `**머지 순서**` or `**폭발 반경**` that names the original id is changed by the same standard as `선행` — a blast radius parks by exact string and never checks that the id exists, so a radius left on the block the apply moved away from parks nothing. A new-grammar block that gains a `선행` from the split writes `**선행 사유**` ((d)). When the split declaration cannot be made to pass (a) through (e) without a decision, the split is not made and the original block carries the reason field instead, which is why neither split rule reaches the decision this item's last sentence asks for.\n   - The item's last sentence, \"If a failure cannot be repaired without a decision the authors did not make …\", covers rules (a) through (e) only.\n9. **FREEZE.** Emit in Korean: *\"설계 문서를 동결했습니다. 이후 이 세션에서는 문서를 수정하지 않습니다.\"* When the document has a `## 구현 슬라이싱` section, add one line to that notice from `bash ${CLAUDE_SKILL_DIR}\u002F..\u002F..\u002Forchestrator\u002Fenforcement-surface-screen.sh -- \u003Cevery slice's declared files>`, which prints `\u003Cpath>\u003CTAB>\u003Cclass>` for each path an unattended run's hook refuses: `강제 표면: 슬라이스 \u003Cid> — \u003C경로> (\u003C분류>, \u003C좌석 적용 가능|사람 몫>), …`, slices separated by `; ` — `규칙카탈로그` and `지침파일` read `좌석 적용 가능`, the other two `사람 몫` — or `강제 표면: 없음`, or `강제 표면: 판정불가` when the screen exits 2. It is a notice: such a path stays declared, and the person learns now that a run implementing it will stop on that edit. From this point `design` performs no further document edits. This step is terminal — there is no path back to Step 5 or Step 6. (CFI-3c) At the freeze the seat deletes the state root's **control plane** — `leg.json`, `park.md`, `presentation.md`, `coherence.md`, `leg.*.out`, `leg.*.err` — and keeps `$STATE\u002Fwitness\u002F`: the corpus is the only durable copy of the round products, and deleting the whole root would destroy it at the moment of the freeze. A workflow that ends in an abort keeps everything.\n10. **Hand off — and the handoff has TWO destinations, so read which one you are in first.**\n\n    **If this invocation was asked for by an autopilot kickoff, the destination is that kickoff, not the audit.** Say so: the document is frozen, here is its path and its whole-file `sha256`, go back and resume the kickoff. The audit is already a stage in the run's approved step graph, so naming it here sends the person to run by hand a thing the run is about to dispatch — and if they follow it instead of returning, **the run is never created at all.** That failure leaves nothing behind: no manifest, no grant, no ledger, no report, so a kickoff abandoned at this exact line is indistinguishable from one that was never started. The handoff lands the moment the freeze happens, which is the moment the kickoff is waiting to be resumed, so this is the most conspicuous instruction at precisely the wrong time.\n\n    **Otherwise** — tell the user in Korean that the next step is `\u002Fcc-cmds:design-audit docs\u002F{topic-slug}.md`, the independent Class S audit over the now-frozen document. State its shape in one line so the freeze reads as purposeful rather than bureaucratic: **independent readers · 1 round · non-recursive · one coherence reconciliation, then stop.** It is a fixed budget with a mandatory residual disclosure, not a multi-round loop with a cap — the reader count lives in that skill's own control-flow invariants and is not restated here.\n\n## Constraints\n\n- NO code modifications. Design discussion only.\n- Inter-agent communication must be in English.\n- **Team members are nameless `Agent` sub-agents**: team members ARE `Agent` sub-agents — nameless background tasks (`subagent_type: \"claude\"`, `run_in_background: true`, **no `name`**), one dispatch per `(role, round\u002Fphase)` key and self-terminating on return. What the design discussion requires is NOT a special team primitive but **cross-review and convergence through the witnesses on disk** (debate, challenge, cross-validation across rounds, lead-mediated per `_common\u002Fagent-team-protocol.md`). Each new round or phase is a fresh dispatch of the role that reads its own past witnesses and its peers' witnesses by path; a re-request inside one key resumes the same `agentId`.\n- **Permitted team resumes (same key only).** A resume — `SendMessage` to a member's `agentId` — is permitted only inside the key that member was dispatched for: a send-back `P-rev\u003Ck>`, Case 1, Case 3, the re-assignment for a missing `peer-read:` receipt, and the witness nudge. A new `round\u002Fphase` key is always a fresh dispatch, never a resume. Step 6's ban targets *conscripting a team convened for a different purpose*. It does NOT target *asking a team about the coherence of its own output* — that follows from Class C defects (the context-dependent kind, whose evidence never reached the artifact) having non-zero sensitivity **only** in the authoring team. Exactly two re-convenings of a prior team's roles are permitted in this skill, each a fresh dispatch into that team's rows, and this list is closed: no other re-convening of a prior team is allowed, for any reason, anywhere.\n    1. **Step 3 → Step 4 synthesis fidelity pass** — the Step 3 roles dispatched afresh to check draft↔discussion fidelity. Phase token `fidelity`. Mandated by Step 4's \"Subject & input\" — executed inside the leg (`design-discuss-unattended`), which dispatches into the Step 3 team's rows and owns their same-key resumes.\n    2. **Step 3 → Step 7 Class C coherence pass** — the Step 3 roles dispatched afresh at a new `epoch` **inside the resumed leg**: the seat resumes the leg session (`claude -r \u003Csession_id>`, same flags and redirections) with the coherence message, and the leg dispatches its own team's roles. Phase token `coherence`. Mandated by Step 7. **Fallback** (only on one of Step 7's two triggers): the Step 3 roles are **dispatched fresh at a new `epoch`** by the seat from the durable witness corpus + the brief + the final document **by path** — the same pass with a different input, not a third re-convening.\n\n    Everything else spawns FRESH as a new team: the Step 5 walkthrough team, every Step 6 refinement team, and any re-composition. A walkthrough-spawned team is never extended into a refinement team or the reverse. A Step 5 or Step 6 **fresh** team is never re-convened for the Step 7 coherence pass — the Class C channel is the *authoring* team specifically, and a fresh team's sensitivity to it is structurally zero, so re-convening one would produce a confident answer from the one vantage that cannot see the defect. Every permitted re-convening of a team from an earlier generation carries the protocol's **`epoch` re-stamp** duty (`_common\u002Fagent-team-protocol.md`, Spawn).\n- **Deferred tool loading**: Before using AskUserQuestion, SendMessage, or TaskStop, you MUST first load them via ToolSearch. Run `ToolSearch` with query \"select:AskUserQuestion,mcp__cc-cmds__question_form\", \"select:SendMessage\", and \"select:TaskStop\" to load each tool. These are deferred tools and will NOT work unless loaded first. (`Agent` is a built-in primary tool — do NOT load it via ToolSearch. `SendMessage` to an `agentId` resumes a running member; `TaskStop` aborts one.) AskUserQuestion MUST be loaded before Step 1 (user interview). Before calling AskUserQuestion, Read `${CLAUDE_SKILL_DIR}\u002F..\u002F_common\u002Faskuserquestion.md` and apply its hard constraints to every AskUserQuestion call in this skill.\n\n### Observation & verification carve-out (running + experimenting ≠ modifying)\n\nThe \"NO code modifications\" rule above and in Step 3 is **absolute and unweakened** — but \"modification\" has a precise definition that makes both reproduction (running the unmodified app\u002Ftest suite) and in-session verification (out-of-tree experiments and isolated-worktree mini-implementations) fully compatible with it. This carve-out is a *definition*, not an exception: the two literal \"NO code modifications\" strings stay literally true everywhere. The full operating mechanics live in `${CLAUDE_SKILL_DIR}\u002F..\u002F_common\u002Fverification.md` §6 (Read it); the compression-critical core is restated here.\n\n- **What \"modification\" means**: a change that **persists in the session's main working tree**. (In git vocabulary an experiment worktree is also a \"working tree\", so the scope is the *main* tree specifically.) Running the app\u002Ftest suite as-is, an out-of-tree driver, or an isolated-worktree experiment that is torn down — none persists a change to the main tree, so none is a modification.\n- **FORBIDDEN**: editing any tracked source file **in the main working tree** — even transiently, even \"I'll revert it after.\" There is no in-tree print-logging exception.\n- **Two-command boundary gate** (scope is per-surface): at every team-discussion boundary run the gate exactly as `_common\u002Fverification.md` §6 defines it — assertion 1 (main tree `git status --porcelain` == the pre-workflow baseline, **within the caller's declared measurement surface** — `design` declares none, and §6.0's default for a caller that declares nothing is the whole tree, so here assertion 1 is whole-tree equality) and the three scoped worktree assertions 2a\u002F2b\u002F2c. The worktree half is a separate gate because porcelain does not see records inside `.git\u002Fworktrees\u002F` (the F1 blind spot), and it is **scoped rather than whole-output** because `git worktree list` is repository-global — a sibling worktree's commit is not a mismatch. Step 4's design-document save (`docs\u002F{slug}.md`) and the interview brief `docs\u002Fdesign-brief\u002F{slug}.md` written at leg dispatch are the skill's two sanctioned tracked-file writes and are NOT subject to this gate — the brief is exempted by path filter, never by staging or ignoring it.\n\n**Surface 1 — main working tree** (reproduction + categories a\u002Fb\u002Fc\u002Fd): today's rules, unweakened.\n\n- **ALLOWED**: executing the unmodified app, running the existing test suite, attaching a debugger, raising verbosity via existing flags\u002Flog levels, importing project modules from an out-of-tree driver, and (for category (c)) WebFetch \u002F WebSearch \u002F external CLI. All artifacts, drivers, and logging route to a `\u002Ftmp` sink or existing verbosity\u002FCLI flags — strictly outside the working tree.\n- **Cleanup boundary — \"before findings leave their producer\"**: whoever produces a finding or a verification verdict (the lead, the reproduction agent, or the verification agent) must, *before* it leaves in any form (whichever comes first: a broadcast, a verdict-citing SendMessage, a task return, or a doc Edit), revert all instrumentation, delete every out-of-tree artifact, and verify the two-command gate == baseline. There is no window in which the tree is dirty while a finding\u002Fverdict is visible to another agent. The lead is the backstop: re-verify before the Step 4 save (the pre-save sweep).\n- **Environment vs. working tree (lockfile checklist)**: the gate is scoped to tracked source only. Verification\u002Freproduction may install dependencies and produce build output: (1) gitignored build output (`node_modules`\u002F`dist`\u002F`.next`\u002F`build`) is out of scope — never appears in porcelain; (2) an install that rewrites a **tracked lockfile** (`package-lock.json`\u002F`poetry.lock`) or tracked codegen path must NOT persist — use a non-rewrite form (`npm ci`, `npm install --no-save`, venv) or revert before the boundary; (3) the pass\u002Ffail gate at every boundary is the two-command gate == baseline.\n\n**Surface 2 — isolated worktree (category (e) only)**: for a mini-implementation whose observation unavoidably requires changing tracked content *and* repo-faithful context (the α∧β condition in `_common\u002Fverification.md`). Compression-critical locks (full mechanics in `_common\u002Fverification.md` §6.2):\n\n- **Create** with `WT=$(mktemp -d \"${TMPDIR:-\u002Ftmp}\u002Fcc-design-exp-\u003Cowner-token>-\u003Cslug>.XXXXXX\")` then `git worktree add --detach \"$WT\" HEAD`. `mktemp` + `--detach` are MUST, and the **owner token** is the creating member's phase `witnessNonce` from its ledger row — it is what scopes assertion 2c to this team rather than to every caller of the mechanism on the machine. Append the created path, that token and a timestamp to the team's creation record under the member's `scratchDir`, **in the same Bash call** as the `git worktree add`; assertion 2a reads that record. **EnterWorktree is forbidden** (its only-if-unchanged auto-cleanup guarantees a leak for a changed worktree); the Agent-tool isolation form is forbidden.\n- **In-worktree FORBIDDEN**: no commit \u002F branch \u002F push \u002F tag \u002F `git config` write \u002F hook install \u002F gc·maintenance \u002F **stash** (`refs\u002Fstash` is a shared namespace — an in-worktree stash survives worktree removal in the main repo's `git stash list`, a porcelain-invisible leak).\n- **Lifetime**: from claim pre-registration to that claim's verdict broadcast; no persistence across re-convergence (regenerate from the recipe — deterministic since the main tree is frozen). One experiment = one worktree, never shared across agents.\n- **Final-run rule**: a verdict is backed only when the recorded recipe's patch, applied on a clean reset (`cd \"$WT\" && git checkout -- . && git clean -fd` — the single inseparable line; run from the wrong cwd it destroys the user's main-tree untracked files), is observed to match the recorded `관측 결과`.\n- **Cleanup**: `git worktree remove --force \"$WT\"` + `git worktree prune` + the record check (every path the creation record claims is absent from `git worktree list --porcelain`, and no entry carries this team's owner token), before the verdict ships. Lead backstop: the pre-save sweep and the Step 6 entry state-check add the two-command gate.\n\n- **CFI impact: none** — quality tier (a missed application is quality degradation, not a mis-transition). Nothing is added above the `## Control-Flow Invariants` heading.\n\nTask: $ARGUMENTS\n","Conduct a design discussion using an agent team for the given task.\nAll team discussions and inter-agent communication should be in English to optimize token usage.\nUser-facing communication (interviews, final presentation) and saved documentation should be in Korean.\n\n## Control-Flow Invariants\n\nThese phase-transition rules govern turn-yielding and MUST stay near the top of\nthis file. Post-compaction reattaches only the first ~5K tokens with priority;\na summarized-away transition rule causes silent mis-transition — waiting for the\nuser where the skill must auto-advance, or prompting where it must yield.\n\n### CFI-1a — Leg dispatch is a turn-ending act\nAfter the user approves the Step 2 composition, the seat (this conversation)\nwrites the interview brief, launches the discussion leg — the sibling skill\n`design-discuss-unattended`, which runs Step 3 and Step 4 through the save in\nits own session — records the pending leg in `leg.json`, and then YIELDS the\nturn. Nothing downstream of Step 4 runs at dispatch time. The dispatch form is\npart of this invariant: it is a **harness-tracked background call**, never a\ndetached form (`nohup`, a bare `&`) and never a foreground call — only the\ntracked form wakes the seat, and a foreground call the harness later moves to\nthe background dies with the seat. Yielding is safe here and fatal in a\nprint-mode shard: a conversational seat survives its own yield and receives the\nnext wake-up, whereas a print-mode process (`autopilot-router-shift` and its\nkind) ends at the yield — so do not rewrite this yield as a hold.\n\n### CFI-1b — The leg's completion wake-up is not a turn-ending act\nThe wake-up is a hint, never the channel: push completion signals drop,\nduplicate, mis-route, and after a seat restart the background handle is an\norphan nobody re-arms. The **pull-check that is the first act of every turn**\n(Step 2, `Leg pull-check`) is by construction the only channel. **The check is\nactive exactly while `$STATE\u002Fleg.json` exists and its `state` is `pending` or\n`parked`** — this sentence is the one definition of that condition, and every\nother mention points here. `done` is written by the seat alone, when it\nconsumes a completion artifact, so a consumed completion switches the check off\ninstead of being read a second time. What completes depends on the marker's\n`phase`. On `discuss`, when the check finds the leg's **artifact predicate**\ntrue — the design document exists, its ledger parses, every non-aborted roster\nrow is `done`, and `presentation.md` exists with a matching header version (an\nexit code is not part of the predicate) — the seat renders the three\n`presentation.md` blocks verbatim, moves the file aside, and continues **in the\nsame turn** into Step 5 (Unresolved Issue Walkthrough), without yielding and\nwithout any user prompt. Rendering the results is NOT a turn-ending action. On\n`resume`, completion is `coherence.md` with a matching header, and it returns\nthe seat to Step 7 — never to Step 5, which CFI-3c forbids once Step 7 has\nbegun. When the predicate is false the seat goes to recovery and does not enter\nStep 5.\n\n### CFI-2 — Step 6 entry: automatic arrival, then notice-and-yield\n(a) ARRIVAL (transition): reaching Step 6 (Plan Refinement) is automatic —\n    Step 5 → Step 6 needs no user prompt. Do not stop on the way in.\n(b) FIRST ACTION: once at Step 6, the lead emits ONE short Korean notice that\n    refinement is starting (inviting the user's input), then YIELDS the turn and\n    waits for the user to speak first. At Step 6 ENTRY do NOT call\n    AskUserQuestion to open the discussion or manufacture a refinement question\n    — no question tool, no options menu, no \"무엇을 다듬을까요?\" prompt; Step 6\n    opens as a plain yield.\n(c) SCOPE: this prohibition is the ENTRY moment ONLY; it does NOT restrict\n    AskUserQuestion elsewhere — the Step 6 state-check's slug-ambiguity prompt\n    (fires before the entry notice, during pre-entry cleanup) and Step 6's later\n    \"propose a new team\" approval path remain valid, as do all Step 4\u002FStep 5\n    AskUserQuestion uses.\n\n### CFI-3 — Step 6 exit → Step 7 is automatic; the Class C pass is single-pass and terminal\n(a) EXIT (transition): Step 6 ends when the user signals the plan is\n    satisfactory (lead judgment on the reply, no regex — the same class of\n    read as Step 5's abort detection). That signal enters Step 7 (Class C\n    Coherence Pass & Freeze) in the SAME turn: no prompt, no AskUserQuestion,\n    no turn-ending \"완료했습니다\". Ending the turn on the satisfaction signal is\n    a mis-transition — Step 7 would never run and an un-cohered document would\n    reach the downstream audit.\n(b) NON-RECURSION: Step 7 runs the coherence pass EXACTLY ONCE over the final\n    text. Its own corrections are never re-submitted for another pass.\n    Re-running it, or looping it until \"clean\", reproduces inside `design` the\n    unbounded review loop this pipeline removed.\n(c) FREEZE \u002F TERMINAL: when Step 7 completes the document is FROZEN — `design`\n    makes no further edits to it, and there is no path back to Step 5 or Step 6.\n    Further refinement is a new `\u002Fcc-cmds:design` invocation, which runs its own\n    Step 7 before freezing again. Every post-freeze edit re-opens the induced-\n    defect rate that the downstream Class S audit's guarantee rests on.\n(d) NOT A ROUND CAP: this invariant fixes the freeze and the non-recursion\n    discipline. It carries no numeric round budget — do not add one here.\n\n### CFI-4 — A seat whose next duty another SESSION owns may only wait or recover\nWhile `leg.json` names a leg that has neither completed (artifact predicate\nfalse) nor parked (no `park.md`), the seat's only lawful actions are to wait or\nto run the recovery ladder of the pull-check. It never re-dispatches (two legs\non one ledger) and never enters Step 5. The owner is a **session**, not a\nprocess: the leg parks and exits, so no process existing while the duty stands\nis the normal state.\n\n## Workflow\n\n### Step 1: Requirements Interview & Codebase Exploration (Korean)\n\n- Do NOT create a team yet. First, interview the user to understand requirements. **Read `${CLAUDE_SKILL_DIR}\u002F..\u002F_common\u002Frequirements-interview.md`** and follow it for the whole interview — the depth, the discipline, issue-originated design, reproduction-first, verification-first and the closing read-back all live there. The bullets below are this skill's own wiring of that interview into the steps that follow.\n- **Reproduction hand-off.** When the lead judges that reproduction should not be done inline, it is delegated to a Step 3 reproduction agent — proposed as the reproduction agent role in Step 2, which drives Step 3's Round 0.\n- **Reproduction data points feed Step 4.** The four reproduction data points carry the same labels as the `## 재현·근본원인` section schema in Step 4, so Step 4 can fill that section verbatim.\n- **Tier-2 feeds Step 4.** Tier-2 of the reproduction fallback (and only Tier-2) triggers the lead to create an unresolved-issue pointer during Step 4 synthesis (see Step 4).\n- **Delivery shape (five questions only the user can answer).** Ask these during the interview whenever the work could land as more than one pull request or touch more than one repository: **which repositories** the change lands in (remote slug, not a path — paths differ per machine and per worktree); **how many slices** it should land as; **where an apply happens**, if anywhere; **who runs that apply** — the pipeline or a person; and **what parks** if an apply fails (the blast radius, which defaults to the whole repository and may only be narrowed). These five are knowledge the user holds and nothing in the codebase does, and this interview is the only place a human is present to give them. Their answers become the `## 구현 슬라이싱` section of Step 4's document, which downstream orchestration parses **mechanically** rather than inferring — so an unanswered question here is not a gap that gets filled later, it is a section that never exists and a plan that silently falls back to being re-derived by a model.\n- **Base design suggestion.** When the interview shows the request splitting into pieces that each still need their own design judgment — the same criterion the autopilot entry judgment uses for a base run — show one Korean note proposing `\u002Fcc-cmds:design-base` (a base design: the contracts between the pieces and a ticket split, each ticket designed later on its own) and let the person choose: `AskUserQuestion` with `이대로 단일 설계 계속` ← 추천 · `중단 — \u002Fcc-cmds:design-base 로 다시 시작` (등급 2 — the scope of the work is the person's to decide). Nothing switches or calls automatically; on the second option end the workflow with that command line.\n- **Base linkage.** When the argument or the interview points at a ticket of a base design (`\u003C문서>.md#T\u003Cn>`, or a tracker reference the registry knows), **read `${CLAUDE_SKILL_DIR}\u002F..\u002F_common\u002Fbase-linkage.md`** and resolve it as it says — asking the person where it resolves to 「찾지 못함」 or 「재앵커링 불가」 or the hash disagrees. A resolved ticket puts a `## 베이스 제약` section into the Step 4 document, before `## 합의된 아키텍처`, with the ticket block and its contract blocks copied verbatim, and puts as the first line of `## 합의된 아키텍처` the fixed sentence 「이 문서의 `## 베이스 제약` 절에 옮긴 티켓 블록과 계약 블록은 이 절의 결정과 똑같이 구현을 구속한다.」 — that is what binds the section for the attended `implement`, whose binding tier is named by section and does not list it; the design never changes that section. Step 4 runs in the leg, which writes that section only when the brief names the ticket, so a resolved ticket goes into the brief as three lines (dispatch item 1 below).\n- **Verification profile feeds Step 2.** A verifiable claim that cannot be settled during the interview is kept for residual encoding at Step 4 synthesis. If Step 1 reveals a verification-heavy profile (multiple (c) external facts, expected (d)\u002F(e) experiments, feasibility questions already visible), flag it so Step 2 can seed a dedicated verification agent.\n- **The read-back and the issue merge feed the brief.** The confirmed closing read-back and any issue-merge decision are what the brief's `## 요구사항` block carries to the discussion leg (dispatch item 1 below).\n\n### Step 2: Team Composition Proposal (Korean)\n\n- Based on interview results and codebase exploration, propose a team composition to the user.\n- **How many roles**: bounded by `_common\u002Fagent-team-protocol.md`'s `### Team size budget`. Read the ceiling **and its coordinator-class carve-out** there — this step deliberately states no number of its own, so the budget cannot drift into two values.\n- Specify each teammate's role, exploration scope, and model (use short aliases: `\"opus\"`, `\"sonnet\"`, `\"haiku\"`). Propose `sonnet` for every teammate by default. Propose `opus` only when the work that teammate takes on needs it, and write that reason on the teammate's own line of the Korean proposal, so the approval is given with the reason in view. The reason is about the work; the size or importance of the task is not a reason. The person may change any model when approving, and a second opinion on promotion stays with `\u002Fcc-cmds:design-upgrade`.\n- **Reproduction agent role (optional, issue\u002Fbug tasks)**: if the reproduction-first filter test (Step 1) is YES and the lead judges a dedicated reproducer is better than reproducing inline, propose a **reproduction agent** as one of the roles. Its scope is: reproduce the symptom, emit the same four data points + `근거 등급` as Step 1, and — as a precondition of broadcasting — clean up and verify the tree (revert instrumentation, delete out-of-tree artifacts, confirm `git status --porcelain` == baseline) *before* findings leave it. This agent drives Step 3's Round 0 (below).\n- **Verification agent role (default on, parallel to the reproduction agent)**: propose a **verification agent** as one of the roles by default, not only when Step 1 anticipated a verification-heavy profile. The seat is not a domain perspective — it is the seat that settles claims against reality. On the small row selected by the gate below it **replaces** the second domain seat (domain 1 + verification 1); on larger rows it is an **addition**. **It is counted, not carved out** — the carve-out in `_common\u002Fagent-team-protocol.md` is for orchestration roles, and this seat's job is measurement. So the seat occupies a roster row like any other, and the largest row is **three domain seats plus the verification seat** — four rows, not five. When three domain perspectives are genuinely not enough, do **not** fold a domain into the verification seat (it would do both jobs worse); take the scope back to the user, as the budget rule does above its own ceiling. Its scope is: settle assigned verifiable claims per `_common\u002Fverification.md`, pre-register each claim's `주장` + `기대 결과` before running, and — as a precondition of broadcasting a verdict — clean up and verify the tree (the two-command boundary gate; for (e), `git worktree remove --force` + `git worktree prune` + the record check of `_common\u002Fverification.md` §6.2 — every recorded path gone and no entry carrying this team's owner token) *before* the verdict leaves it. The Quality Gate can hold a gated proposal and route its claims to this agent. Same cleanup-before-findings-leave precondition + worktree-teardown duty as the reproduction agent.\n- **Disclose the leg's permission posture in the proposal, so the approval covers it.** The leg runs under `--permission-mode bypassPermissions` — a human decision already taken for this skill, not a per-run question — but the seat is granting that posture to a child process nobody watches, so the proposal carries one Korean line naming the posture and its blast radius, verbatim: *\"승인하시면 설계 토론(Step 3·4)은 별도 헤드리스 세션에서 권한 확인 없이(`bypassPermissions`) 실행됩니다 — 그 세션과 팀원은 이 계정이 쓸 수 있는 모든 경로에 쓰고 Bash·의존성 설치·웹 조회·에이전트 생성을 확인 없이 실행하며, 파이프라인 게이트는 걸리지 않고 코드 무수정 규칙은 지시문으로만 지켜집니다.\"* An approval of a proposal that lacked this line is not an approval of the posture, and the dispatch below does not proceed on it. The approval time is recorded in `leg.json` (item 3 of the dispatch block).\n- Only create the team after the user approves the composition. **On the normal path the seat does not create the team itself** — it hands the approved composition to the discussion leg below, and the leg spawns the team inside its own session.\n\n#### Leg dispatch (after approval — the seat launches the discussion leg)\n\nStep 3 and Step 4 through the save run in a separate headless session, the **leg**, because the Step 3 rounds and the Step 4 fidelity pass dispatch into the same ledger rows and a same-key resume of a live member (a send-back, a nudge, Case 1 or Case 3) is addressable only from the session that dispatched it, so Step 3 and the pass must share one session, and the seat's own context is what the split keeps below the compaction threshold. The seat hands the leg everything Step 1 and Step 2 produced that is on disk nowhere else, then yields (CFI-1a).\n\n1. **Write the interview brief.** Read `${CLAUDE_SKILL_DIR}\u002F..\u002F_common\u002Fsidecar.md` `## 1` and write `\u003Cbase>\u002Fdocs\u002Fdesign-brief\u002F{slug}.md`, where `{slug}` is the folded document key of §1.1 for the document this workflow will save (`docs\u002F{topic-slug}.md` → `docs-{topic-slug}`; the document need not exist yet — the key is derived from the path) and `\u003Cbase>` is the main worktree root. Line 1 is an H1; line 2 is the machine header, verbatim: `\u003C!-- cc-design-brief v1; writer=design; reader=design-discuss-unattended; owner-doc=\u003Cdocument key>; NOT a design doc; mechanism-local, never staged by a skill -->`. Then exactly these eight blocks, in this order, each a `## ` heading: `## 요구사항` (the interview's requirements and any issue-merge decision; when Step 1's base linkage resolved a ticket, also three field lines — `**베이스 문서**: \u003Cbase document path>`, `**티켓**: T\u003Cn>`, `**베이스 sha256**: \u003Cwhole-file sha256 of the base document, measured at resolution>` — which are what the leg re-measures before it spawns and what makes it write `## 베이스 제약`; without them the section is not written and nothing warns) · `## 제약` · `## 배포 형상` (the five delivery-shape answers as five field lines — `**레포**`, `**슬라이스 수**`, `**적용 위치**`, `**적용 주체**`, `**실패 시 파킹**` — writing `없음` where an answer does not apply; an omitted line and a negative answer are different facts, so no line is omitted) · `## 탐색 결과` (codebase exploration findings) · `## 재현` (the four reproduction data points and `근거 등급`, or `없음`) · `## 팀 구성` (the approved roster: role, scope, model per member) · `## 기준선` (the pre-workflow `git status --porcelain -z` output, verbatim — assertion 1 of the two-command boundary gate compares against this and the leg cannot re-derive it once the tree has moved) · `## 대상` (five field lines: `**topic-slug**`, `**문서 키**`, `**접힌 슬러그**`, `**docs 대상 디렉터리**`, `**검증 편중 프로필**`). The file's last non-empty line is the terminator `\u003C!-- cc-design-brief: end -->`. Write it with the atomic form of `sidecar.md` §1.3 (same-directory `mktemp`, whole-file `mv`). **Never stage it** — the brief stays out of the index by this skill's discipline, not by a `.gitignore` edit.\n2. **Prepare the state root.** `STATE=\"${XDG_STATE_HOME:-$HOME\u002F.local\u002Fstate}\u002Fcc-cmds\u002Fdesign\u002F{slug}\"`; `mkdir -p \"$STATE\"`. If `$STATE\u002Fleg.json` already exists, compare its `brief_sha256` with the sha256 of the brief just written: different means a stale marker from an earlier workflow — move it aside to `$STATE\u002Fleg.stale.\u003CISO8601>.json` and continue (CFI-4 does not apply to a stale marker); identical means a leg for this very brief is already pending — do not dispatch, go to the pull-check below (CFI-4).\n3. **Mint the session id and write `leg.json` first.** `LEG_SID=$(uuidgen | tr 'A-Z' 'a-z')`, then write `$STATE\u002Fleg.json` (atomic form) **before** launching: `{ \"slug\", \"session_id\", \"phase\": \"discuss\", \"state\": \"pending\", \"dispatched_at\", \"heartbeat_at\", \"redispatch_count\": 0, \"brief_sha256\", \"leg_out\": \"$STATE\u002Fleg.\u003Csession_id>.out\", \"leg_err\": \"$STATE\u002Fleg.\u003Csession_id>.err\", \"prior_session_ids\": [], \"transcript_bytes\": 0, \"leg_json_mtime_at_dispatch\", \"permission_posture\": \"bypassPermissions\", \"posture_approved_at\" }`. `permission_posture` and `posture_approved_at` (the time of the Step 2 approval whose proposal carried the posture line) record that the posture was approved rather than assumed; a marker lacking either names a leg dispatched without that decision. The progress baseline (transcript size 0, this file's own mtime) is written in the same write so the first pull-check has something to compare against. Spelling rule: a harness-owned identifier keeps the harness spelling (`session_id`, as the `-p` result object names it); fields this design coined are snake_case. **No pid is recorded** — the liveness oracle below carries it.\n4. **The launch line.** Every preflight line is a hard stop, because every failure it catches otherwise presents as `exit 0` · `subtype success` · no artifact — the one shape nobody can debug afterwards. Fill nothing in by hand except what the seat computes above; the block carries no placeholders.\n\n    ```bash\n    mkdir -p \"$STATE\"          # leg.json is written here first, so this comes first\n    : \"${CLAUDE_CONFIG_DIR:?CLAUDE_CONFIG_DIR is unset - refusing to launch the leg}\"\n    CLAUDE_CODE_PRINT_BG_WAIT_CEILING_MS=14400000\n    CLI=$(type -P claude)      # absolute path: a bare `claude` is intercepted by this machine's shell guard\n    PLUGIN_DIR=\"${CLAUDE_PLUGIN_ROOT:-$(cd \"${CLAUDE_SKILL_DIR}\u002F..\u002F..\" && pwd)}\"\n    [ -x \"$CLI\" ]        || { echo \"leg: CLI not executable: $CLI\" >&2; exit 2; }\n    [ -d \"$PLUGIN_DIR\" ] || { echo \"leg: plugin dir missing: $PLUGIN_DIR\" >&2; exit 2; }\n    [ -n \"$LEG_SID\" ]    || { echo \"leg: no session id minted\" >&2; exit 2; }\n    [ -n \"$CLAUDE_CODE_PRINT_BG_WAIT_CEILING_MS\" ] \\\n                         || { echo \"leg: wait ceiling unset - the team would be killed at 600s\" >&2; exit 2; }\n\n    CLAUDE_CONFIG_DIR=\"$CLAUDE_CONFIG_DIR\" \\\n    CLAUDE_CODE_PRINT_BG_WAIT_CEILING_MS=\"$CLAUDE_CODE_PRINT_BG_WAIT_CEILING_MS\" \\\n    \"$CLI\" \\\n      --plugin-dir \"$PLUGIN_DIR\" \\\n      --session-id \"$LEG_SID\" \\\n      --model opus \\\n      --effort high \\\n      --permission-mode bypassPermissions \\\n      --dangerously-skip-permissions \\\n      --output-format json \\\n      --strict-mcp-config \\\n      -p \"\u002Fcc-cmds:design-discuss-unattended docs\u002Fdesign-brief\u002F{slug}.md\" \\\n      >> \"$STATE\u002Fleg.$LEG_SID.out\" 2>> \"$STATE\u002Fleg.$LEG_SID.err\" \u003C \u002Fdev\u002Fnull\n    ```\n\n    Why each element is there:\n\n    | element | failure without it |\n    | --- | --- |\n    | `$CLI` absolute path | this machine's shell guard intercepts a bare `claude`, exits 1 and creates no session at all — the only non-zero phenotype |\n    | `CLAUDE_CONFIG_DIR:?` | an empty value lands in an account-less config dir, and the liveness oracle below can only see legs launched under the same config dir |\n    | the wait ceiling | print-mode wind-down kills the team at the default 600 s ceiling and exits 0 |\n    | `--plugin-dir` | the slash command resolves to nothing: exit 0 · `subtype success` · `num_turns 0` · `Unknown command:` |\n    | a fresh `--session-id` per dispatch | the transcript is the progress oracle and must be findable; a reused id is refused |\n    | `--output-format json` | the only source of `permission_denials`, `subagent_stats.killed.system`, `num_turns` |\n    | `--strict-mcp-config` | the leg needs no MCP server; loading them costs startup time and context |\n    | both streams into `$STATE`, per-attempt file names | the ceiling marker is on stderr, every other marker on stdout; after a seat restart these two files are the only evidence, and appending attempts into one file makes every attribution predicate match the previous attempt's bytes |\n\n    **Flags that must not appear**: `--setting-sources \"\"` (silently cuts the settings chain) · `--settings \u003Cfile>` (`-p` silently ignores a settings file that fails validation) · `--restricted` (removes Bash, which the two-command boundary gate uses) · `--continue` \u002F `-c` (inherits the seat's conversation) · `--fork-session` (mints a new id on resume and destroys the handle `leg.json` holds) · `--bg` (no push wake-up, so CFI-1b does not hold). The permission posture is a human decision already taken, and checkably so — disclosed with its blast radius in the Step 2 proposal the user approved, and recorded in `leg.json` as `permission_posture` and `posture_approved_at` (item 3). Without a posture the leg fails its first `docs\u002F{slug}.md` write and **reports success** — exit 0, `subtype success`, `is_error false`, a file never written.\n5. **Dispatch as a harness-tracked background Bash call** (`run_in_background: true`) — never detached, never foreground (CFI-1a). Immediately after dispatch emit one Korean notice — *\"설계 토론을 별도 프로세스로 파견했습니다. 진행은 매 턴 시작 시 확인합니다.\"* — and yield the turn.\n6. **The resume line** is the same environment, the same flags and the same stream redirections with `--session-id \"$LEG_SID\"` replaced by `-r \"$LEG_SID\"` and the `-p` prompt replaced by the message. \"Same flags\" includes the two redirections — without them a resumed leg writes to neither file and the attribution step has no input. **The message is never inlined on the command line.** Every message the seat resumes with carries backticks — the park answer template names its site in them, and the Step 7 notes are Markdown — and inside a double-quoted argument the shell runs each backtick span and `$( )` as a command, so the message would arrive silently rewritten while the leg still exits 0. The seat therefore writes the message with the Write tool to a same-directory temporary file and `mv`s it to `$STATE\u002Fresume.\u003CISO8601>.txt` (the atomic form of `sidecar.md` §1.3), sets `RESUME_MSG` to that path, guards it with `[ -s \"$RESUME_MSG\" ]`, and passes it as `-p \"$(cat \"$RESUME_MSG\")\"` — the output of a command substitution is not expanded again, so the bytes arrive as written. The file stays in `$STATE` as the record of what was sent. A resume keeps the session id and therefore keeps the team; a re-dispatch mints a new id and loses it. **Resume whenever the session is usable.**\n\n#### Leg pull-check (the first act of every turn while the check is active — CFI-1b)\n\nThe seat reads `$STATE\u002Fleg.json` before anything else, every turn, for as long as the check is active (CFI-1b defines when). The user's next message is the guaranteed wake-up; there is no watcher process and no push channel (CFI-1b).\n\n- **0 — Park.** If `$STATE\u002Fpark.md` exists and its header line matches `\u003C!-- cc-design-park v1; ` exactly, the leg is parked: render the record's `질문 문면`, its `선택지` labels and descriptions **verbatim** to `AskUserQuestion` — `등급 2` — composing nothing (the seat holds none of the discussion, so it cannot author options; the `_common\u002Faskuserquestion.md` conformance check is the seat's, as the tool's caller). In the same turn as the question, **consume the record**: move it to `$STATE\u002Fpark.answered.\u003CISO8601>.md` and set `leg.json` `state` back to `pending` (never delete it — the verbatim question must survive for tests and later readers). Without this consumption a parked leg never finishes: the predicate is file existence, so the same question would go out again next turn. When the answer arrives, write the neutral operational message to a resume file and resume the leg through the resume line (dispatch item 6 — never inlined) *\"park 질문 `\u003C자리 id>` 에 대한 사용자의 답은 다음과 같다: …\"* — neutral wording, because a \"remember this secret\"-shaped prompt is refused as injection while still exiting 0 — and classify the resumed turn as an artifact turn, not a terminal state.\n- **1 — Complete, branched on `leg.json` `phase`.** **`discuss`** — if the artifact predicate holds (CFI-1b; the header the predicate matches is `\u003C!-- cc-design-presentation v1; writer=design-discuss-unattended; reader=design; slug=\u003Cslug> -->`), render the three blocks of `$STATE\u002Fpresentation.md` — `## 고지`, `## 검증 집계`, `## 결과` — verbatim, **consume the record** the way step 0 consumes `park.md` — move it to `$STATE\u002Fpresentation.rendered.\u003CISO8601>.md`, never delete it — set `state: done`, and continue into Step 5 in the same turn. **`resume`** — complete when `$STATE\u002Fcoherence.md` exists and its first line is `\u003C!-- cc-design-coherence v1; writer=design-discuss-unattended; reader=design; slug=\u003Cslug> -->`; set `state: done` and continue Step 7 at its triage step (6) in the same turn. On this phase `presentation.md` is never consulted: it belongs to the discuss phase, and completing on it would re-enter Step 5 after Step 7 has begun, which CFI-3c forbids. **This step alone** separates real completion from a permission refusal or an injection refusal, which are indistinguishable from success in every machine-readable field.\n- **Three readings, none a substitute for another.** ⓐ **Artifact** (steps 0–1) decides success and is positive-only. ⓑ **Progress** — the leg transcript's size (`${CLAUDE_CONFIG_DIR}\u002Fprojects\u002F*\u002F\u003Csession_id>.jsonl`, globbed by session id; never re-derive the project key) plus `leg.json`'s mtime — decides whether anything is happening. ⓒ **Liveness** — `claude agents --json` queried **by `sessionId` only** (never by `kind`: a `-p` leg is listed as `\"interactive\"`, so a `kind == \"background\"` filter silently misses every leg), under the same `CLAUDE_CONFIG_DIR`; absence is not a death verdict. Liveness answers identity, not progress, so its duty is to **withhold writes**, never to suppress an alarm.\n- **2 — Progress reading.** Compare transcript size and `leg.json` mtime with the previous turn's record. **2a** either grew → record the new reading and do nothing this turn. **2b** both still, fewer than two consecutive turns → record and stop. **2c** both still for two or more consecutive turns → query the liveness oracle first: an entry means a process is alive in that session — neither resume nor attribute; no entry means the leg exited — go to attribution. **2d** still *and* alive for four or more turns → `AskUserQuestion` — `등급 2` — with exactly two options, **더 기다림** and **포기** (on 포기 the pid comes from the oracle entry just read — the design records none); this is not a park, because a park exists only where the questioner has no question tool.\n- **Attribution, 3–8 (launch-line defect vs. death).** The exit code carries one bit (zero \u002F non-zero) and nothing more; inside `exit 0` never branch on the exit code or on `subtype`. In order: **3 ceiling kill** — `leg.err` matches `Background tasks still running after`, or `subagent_stats.killed.system > 0` → raise the ceiling and `--resume` the **same session** (nothing is lost) · **4 unresolved slash** — `result` contains `Unknown command:` → fix `--plugin-dir`, launch with a **new `session_id`** · **5 permission starvation** — the transcript (session-id glob) carries `Claude requested permissions to … but you haven't granted it yet`; a non-empty `permission_denials` in `leg.out` is the same fact and, under the fixed posture, a canary that the posture did not take → fix the posture, new id · **6 the leg spent turns and declined** — `num_turns > 0`, `result` present, none of the signals above, **and `result` states a refusal or abort reason in words** (the known class is injection refusal) → fix the prompt wording, new id; **a `result` that states no reason, or a reason outside that class, is step 8, not step 6** · **7 no session at all** — exit 1, the shell-guard line → call the absolute path · **8 death** — no `result` object, or `is_error: true`, or the process vanished without a terminal state → read the transcript tail by session-id glob; a `rate_limit` \u002F 429 tail sets a wait before repair and changes nothing else. **Accounting**: 3–7 are launch-line defects, and re-entering after one does **not** increment `redispatch_count`; only step 8 descends the ladder. **Mint a new id only after attribution is finished** (a fresh id written first makes the session-id glob resolve to an empty session), and keep the previous id in `prior_session_ids`.\n- **The ladder (entered from step 8 only).** **Rung 1** — the session is usable → `claude -r \u003Csession_id>` (team preserved, counter unchanged). **Rung 1r — on `phase: discuss` only** — the transcript is missing or unusable → re-dispatch with a new `session_id`, the team is lost, the roster is rebuilt from the durable witness corpus (`$STATE\u002Fwitness\u002F`) — `INDEX.md`'s `lead`\u002F`sweep` row and `SWEEP.md` are not member roles and stay off it — `redispatch_count += 1`. The leg this launches finds the dead dispatch's early ledger stub, and that skill's target-document guard passes a stub while parking a saved document — which is what leaves this rung reachable in the states its purpose needs, since the corpus fills only as rows flip to `done` and rows exist only once a spawn has already written that stub. **On `phase: resume` rung 1r is forbidden.** By then `docs\u002F{topic-slug}.md` carries Step 5's walkthrough decisions and Step 6's refinements; a re-dispatched leg runs Step 1 through Step 4 from the start and saves over them, and the leg's boundary gate cannot catch it, because that skill's Step 2 exempts this exact path — an accidental re-save and a legitimate first save look identical to every assertion it makes. The new leg also knows no `phase`, so it writes `presentation.md` while the `resume` branch of step 1 above waits for `coherence.md`: the seat waits on an artifact nobody will write, and the bytes it was waiting to protect are already gone. Take Step 7's fallback (3') instead — the Step 3 roles respawned fresh at a new `epoch` from the durable witness corpus, the brief and the final document **by path**, with no save and no new leg; Step 7's precondition step names this as its second trigger. **The `brief_sha256` identical guard of dispatch item 2 does not reach this ladder.** It governs the Step 2 dispatch preparation, and nothing here re-runs item 2, so a rung-1r re-dispatch proceeds on an unchanged brief rather than being blocked by it. **What keeps a re-dispatch away from a saved document is neither the phase guard alone nor the leg's guard alone.** The phase guard forbids rung 1r on `phase: resume`, where a saved document exists by construction and no file need be consulted; on `phase: discuss` the leg's target-document guard is the one that looks at the file, and it parks on a saved document while passing an early stub. Neither stands in for the other — the phase guard reads no file, and the leg's guard reads no `phase`. **And a re-dispatch prompt is not the first dispatch's prompt.** Item 4's *no placeholders* fixes the **first** dispatch's block; a rung-1r prompt additionally names the corpus path (`$STATE\u002Fwitness\u002F`) and the recovery context — the prior `session_id`s and the incremented `redispatch_count` — because a leg told none of this rebuilds nothing and composes a fresh roster in place of the approved one. **Rung 2 — the floor.** At most **one** re-dispatch per design; a second rung-1r failure is **not** a question to the user but a demotion: the seat runs Step 3 and Step 4 itself, at today's cost from a worse starting point (Step 1, Step 2, N pull-check turns and at least one attribution already spent). The demoted seat's execution text is Step 3 and Step 4 of **this file**, read as the interactive procedure they are.\n\n#### Small-work gate (evaluated once on entering this step)\n\nA single-surface change with no contract change does not need a full design team. Evaluate this before composing, from the **Step 1 interview product** — this skill receives no entry-plan (the kickoff hands over a command string, nothing more), so the three inputs are read from what the interview settled: the surface count and any contract\u002Fschema change from the requirements and constraints, and the target-repository count from the delivery-shape answers. The inputs are defined the same way as the kickoff's tier judgment, so the tier and the roster cannot disagree on what they measure; when the user invokes this skill directly without a kickoff, the gate fires on the same inputs.\n\n**Risk indicators outrank the size row.** If any indicator fires — a public contract or shared schema change, a public API surface, a DB schema, auth\u002Fauthorization, an external service integration, async\u002Fconcurrency — compose for that risk no matter how small the surface is, and this gate does not narrow the team.\n\n**When it fires**: no risk indicator fired **and** the work is a single surface in a single target repository. Compose from the small row — **one domain seat plus the verification seat** (two roster rows, the same roster `design-lite` runs; the budget counts one domain perspective here, and the budget has no floor) — instead of a larger default row, and state the narrowing in one line of the Korean proposal so the user sees it rather than discovering a thinner team.\n\n**Floor.** This gate selects among composed rows that each carry at least two roster rows — one domain seat and the verification seat — so it cannot yield an empty roster; an empty roster is not a saving but a hard stop, because the ledger stub is created at spawn time and every resume path fail-closes on a missing or unparseable ledger. The floor belongs to the roster contract in `_common\u002Fagent-team-protocol.md` alongside the team-size ceiling; do not write a second floor rule here.\n\nThe kickoff's design tier is `solo` or `team-4`. A `team-4` plan whose `design_path` is `discuss-audit` is dispatched with this roster as `design-discuss-unattended`, and one whose `design_path` is `solo-audit` goes to `design-solo-unattended`, with no roster; `solo` is not a row of it — it is `design-solo-unattended`, a headless lead with no team, and it is only named here so that nobody builds it as a zero-member team.\n\n### Step 3: Design Discussion (English, internal only)\n\n**Executed by the leg, not the seat, on the normal path.** After the dispatch block above the seat yields (CFI-1a); Steps 3 and 4 through the save run inside `design-discuss-unattended`, which Reads these two steps from this file and applies its own park substitution. The seat runs them itself only at the recovery ladder's floor.\n\n**Before assigning any team work, Read `${CLAUDE_SKILL_DIR}\u002F..\u002F_common\u002Fagent-team-protocol.md`.** Apply the completion-signal instruction and facilitator rules from that file throughout this step. When you dispatch or resume each member, embed the **task-assignment header** from `_common\u002Fagent-team-protocol.md` verbatim at the top of each dispatch\u002Fresume prompt. Every new `round\u002Fphase` key — each discussion round, the Step 4 fidelity pass, the Step 7 coherence pass — is a fresh background `Agent` dispatch carrying what the protocol's `## Multi-round` lists for a boundary dispatch; only a re-request inside one key resumes the same `agentId`.\n\n**Re-entry notes.** This skill opts in to the protocol's `### Parameter — re-entry notes (opt-in)`; append this clause verbatim after the task-assignment header in every member prompt:\n\n**Re-entry notes (MUST)**: directly above your `peer-read:` lines (directly above your sentinel when you have none), put a section that starts with the heading `## Re-entry notes`, at most 20 lines and 2,000 bytes, one entry per line — `path:line — why` for a place you would open first if you came back to this work, or one command you would re-run. No findings and no verdicts in it. The next dispatch of your role reads it as the starting point of its re-exploration.\n\n- Spawn each approved member as a nameless background task — `Agent({ subagent_type: \"claude\", run_in_background: true, prompt: \u003Cself-contained assignment> })` — and record each returned `agentId` in the ledger immediately. **Stamp `epoch`** (`max(disk epoch, 0)+1`, re-derived from the on-disk ledger — never an in-context counter; this Step-3 discussion team is the first team → `epoch 1`) **and the round-1 `witnessNonce`** on every one of its rows in the same at-spawn recording window as `agentId`\u002F`scratchDir`, per the protocol Spawn section. The `{topic-slug}` is no longer a harness team name, but it remains the output doc filename (`docs\u002F{topic-slug}.md`) and the ledger key (e.g., `auth-flow`, `payment-system`).\n- **Early ledger stub (at spawn time)**: create the output doc `docs\u002F{topic-slug}.md` as an early stub — an H1 title plus the ledger HTML-comment block `\u003C!-- cc-design-ledger v3 … -->` placed right after the H1 and before the first `##`. Each ledger entry is behavior-bearing. Entry schema — the column list, the `state` domain, the per-row transient set and its terminal-strip rule (including the `epoch` exemption) — is defined once in `_common\u002Fagent-team-protocol.md`'s Role↔agentId ledger v3 and is not restated here. `scratchDir` is the member's out-of-tree witness directory, recorded at spawn with the same immediacy as `agentId`. Update it on every state change. This uses the same `docs\u002F{topic-slug}.md` path as the Step 4 save (the two-command worktree gate already exempts that path — no baseline re-capture needed). **On entering any later phase (synthesis fidelity pass, Step 5, Step 6, Step 7 coherence pass), re-read the ledger from disk** — do not trust in-context copies; a missing or unparseable block is fail-closed via `AskUserQuestion`. The ledger block is **off-limits to synthesis and fidelity-pass content Edits** (whose targets are the enumerated canonical SOTs — `근거 등급` \u002F `검증 기록` `관측 결과` \u002F `## 재현·근본원인` `관측된 증상` — never the comment block); only ledger-state mutations (running→done\u002Faborted, round, thinReturns) write to it.\n- **Witness scratch dir (parameters for `_common\u002Fagent-team-protocol.md`)**: before the first spawn, run the protocol's `## Spawn` command — `\u003Cplugin root>\u002Forchestrator\u002Fcc-team-witness-init.sh {topic-slug}` (no `bash` in front — see the protocol's note) — and record the **printed path, literally** (not `$WITNESS_DIR`) as each member's `scratchDir` in the ledger at spawn time. Each member publishes its round product as `${scratchDir}\u002F{role-slug}.{round\u002Fphase}.md` per the protocol's write discipline (atomic `mv -n` + sentinel\u002Fnonce). **Witnessed surfaces** — explicitly: every Step-3 discussion round (`{role-slug}.round-N.md`), the Step-4 synthesis fidelity pass (`{role-slug}.fidelity.md`), the Step-7 Class C coherence pass (`{role-slug}.coherence.md`), and each Step-5 walkthrough \u002F Step-6 refinement **fresh** team (each fresh team gets its **own** directory from a fresh run of the `## Spawn` command above — never a hand-written `mktemp -d`, which the protocol forbids — recorded in its rows' `scratchDir`). Entirely lead-local phases (lead-only doc Edits, the pre-save sweep) are exempt; the sweep leaves no witness, and the lead writes only `SWEEP.md` into the corpus itself (Step 4 `**Pre-save sweep**`).\n- All inter-agent discussion and reasoning should be conducted in English.\n- NO code modifications allowed. Design discussion only.\n  - (observation & verification carve-out: running the unmodified app\u002Ftests, and out-of-tree \u002F isolated-worktree experiments, are not modifications — see `## Constraints` → \"Observation & verification carve-out\".)\n- **The lead acts as a facilitator**, actively driving multi-round discussion. Do NOT passively wait for results and move on.\n\n#### Discussion Protocol (rounds per the shared Round budget)\n\n0. **Round 0 — Reproduction grounding pass** (only when a reproduction agent is on the team): the reproduction agent reproduces the symptom (with artifacts present), captures the observation in its report text, then **reverts\u002Fdeletes the artifacts → verifies `git status` is pristine → and only then broadcasts** the grounding report to the whole team. Cleanup-and-verify is a *precondition* of the broadcast (findings must be clean before they leave the producer). Round 0 is a grounding pass and **does NOT count against the shared `### Round budget`** (`_common\u002Fagent-team-protocol.md`). The reproduction agent stays active through Cross-Review, challenging whether each proposal actually addresses the reproduced cause, and converges by returning like any member.\n   - **Round 0 failure path**: if the reproduction agent fails to reproduce, it broadcasts a `가설(추측)` grounding report with `재현 차단요인` filled. Tier-1\u002FTier-2 escalation is owned by the **lead** (the agent cannot call AskUserQuestion — it only surfaces the blocker; the lead decides whether to ask the user for help and, on Tier-2, creates the Step 4 unresolved-issue pointer). The Quality Gate's \"hypothesis + blocker → proceed\" branch (below) is exactly this failure-acceptance path.\n1. **Round 1 — Initial Proposals**: Spawn each member with their design scope. Confirm each member's round-1 witness via `witness_present`, then read the witness (never the return), before proceeding — a member's proposal is delivered by its witness, not its return text.\n2. **Quality Gate**: Before proceeding to cross-review, verify each proposal meets minimum depth:\n   - References specific files, modules, or patterns from the actual codebase (not generic advice)\n   - Includes concrete design decisions with rationale (not just listing options)\n   - If a proposal is too shallow or generic, send it back with specific questions asking for deeper analysis\n   - **Reproduction addendum** (when a reproduction agent is present): Round 1 proceeds only after the Round 0 grounding report carries a `근거 등급` (either `확인됨(재현·관측)` with observed evidence, OR `가설(추측)` with `재현 차단요인`) **and** the tree is pristine-verified. Reject a grounding report that is a code-reading guess with no attempt-to-run, or one that left artifacts in the tree.\n   - **Verification addendum** (sister to the Reproduction addendum; applies on Round 1 and every Round 2+ revision forward). Reject (send back) on ANY of: (1) a load-bearing claim passes the filter test but carries no `검증 등급` tag (a tripwire-phrase hit counts); (2) a `미검증`-tagged claim reaching cross-review (disposition: send back \"verify or re-justify the reclassification\", or hold + route to the verification agent); (3) a `검증됨(통과)`\u002F`반증됨(실패)` tag with no recipe + observed value — a verification claim without evidence (isomorphic to the existing \"code-reading guess with no attempt-to-run\" rejection); (4) a clearly-filter-passing claim tagged `구현 시 검증` — the misclassification escape hatch (audit: `잔여 사유` token present + `차단 사유` specificity (\"ran out of time\" inadmissible) + on `구현 필요`, re-apply the filter test).\n3. **Cross-Review**: Dispatch each teammate afresh for the cross-review round with its own past witnesses and its peers' proposal witnesses named **by path** (`_common\u002Fagent-team-protocol.md` `## Multi-round` — the member Reads each whole; the lead does not restate them). Explicitly ask them to identify gaps, risks, contradictions, and alternative approaches. Each cross-review witness (`{role-slug}.round-2.md`) ends, above its sentinel, with exactly one **round-3 declaration** line on a line of its own: `round-3: none`, or `round-3: measure — \u003Cone measurement not yet run, and the disputed claim it would settle>`. That line is where a member names a measurement — the first entry to round 3 in the shared `### Round budget`. Ask each member, in the same dispatch, to revise its own proposal — its round-1 witness is among the own past witnesses the dispatch names — in the light of what it found and to state its final position in that witness: this one dispatch is both the cross-review and the convergence dispatch.\n   - **The shared convergence dispatch is folded into Round 2.** `_common\u002Fagent-team-protocol.md` `## Convergence` sends a separate convergence dispatch after cross-review; this procedure folds it into the Round 2 dispatch above, so the design team's convergence round\u002Fphase token is `round-2` and no separate convergence dispatch is sent. The folded dispatch carries no current-consensus or open-conflicts text, because the lead holds no consensus after Round 1: the peers' Round 1 witnesses named by path stand in that place.\n   - **A sweep refutation does not open Round 3 in this procedure.** The second entry path of the shared `### Round budget` (the lead's pre-save sweep refuting a claim) is carried out here as the author-only re-convergence of Step 4 `**Pre-save sweep**` (a focused exchange with the one affected author, once per claim), and the same holds in a team whose Round 3 a named measurement has already opened.\n4. **Round 3 (conditional)**: Confirm each member's cross-review witness via `witness_present` and read it (never the return). **Before deciding whether Round 3 opens, once every cross-review witness is in, check each one's declaration**: its last line that is exactly `round-3: none` or starts `round-3: measure — `, chosen across both forms. A witness with neither is a Case 3 non-conforming witness (`_common\u002Fagent-team-protocol.md`): re-instruct that member and take its `round-2-rev\u003Ck>` revision before going on. This check runs whether Round 3 opens or not. Then open Round 3 only when at least one Round 2 witness's declaration has the `round-3: measure — ` form. When it opens, dispatch every member's role once afresh for `round-3` with its own past witnesses and its peers' Round 2 witnesses named **by path** — together every Round 2 witness — (`_common\u002Fagent-team-protocol.md` `## Multi-round`), and ask each to run the measurements named and state its final position. How many rounds a team may drive follows the shared `### Round budget` and is not restated here. A sweep refutation reaches the second entry path through Step 4 `**Pre-save sweep**` instead: the sweep runs after synthesis and the fidelity pass, when Step 3 is already behind, and a new transition that re-dispatches the whole team would add back, at another point, the dispatch cost this procedure removes. That re-convergence stays as it is, and the corpus file `SWEEP.md` and the `스윕 반박` field of the `토론 패스` ledger row count it on an axis apart from Round 3.\n5. **Convergence Check**: Proceed to Step 4 when every member's last-round witness — Round 2 when Round 3 stayed closed, Round 3 when it opened — is `witness_present`. The declaration check and its Case 3 re-assignment already ran before the opening decision in item 4.\n\n**Evidence-grade label (`근거 등급`)**: for reproducible issue\u002Fbug tasks, the root cause carries a binary evidence grade — `확인됨(재현·관측)` (the recipe was actually run and the symptom observed) or `가설(추측)` (anything unrun\u002Funattempted\u002Fblocked). The field key is `근거 등급`, deliberately distinct from `상태` (the walkthrough's state field). The single source of truth is the `근거 등급` field of the saved doc's `## 재현·근본원인` section, **computed once at the reproduction discovery point** (Step 1 lead-driven OR Round 0 agent-driven — whichever path reproduced); every other location only *references* it. When a teammate's proposal builds on the reproduced cause, it carries a `[근거 등급: …]` prefix — this is label-only (it travels with the proposal as context), NOT a hard gate: a `가설(추측)` proposal is still discussable.\n\n**Verification discipline (`검증 등급`)**: parallel to the evidence grade, applied to any load-bearing claim the design rests on (the contract is `_common\u002Fverification.md`). The authoring teammate runs the severity pre-filter, then the single filter test, on each dependent assertion and attaches an inline `[검증 등급: …]` tag (same pattern as `[근거 등급: …]`; **inter-agent messages only** — saved-document marking uses the token-free anchor-reference convention `(§검증 기록 V\u003Cn>)`). A verifiable claim must reach `검증됨(통과)`\u002F`반증됨(실패)`, backed by a re-runnable recipe + an observed value, before it is carried into synthesis; a genuinely implementation-time-only claim is encoded as a residual item (`잔여 사유: 구현 필요`). **Linguistic tripwire**: a hedge on a decidable fact (\"should exist\", \"presumably\", \"구현 시 확인\u002F검증 필요\") is a confessed-unverified claim. **Routing (lead's delegated judgment, not a fence)**: the author verifies cheap one-command (a)\u002F(b) at proposal time; the Step 2 verification agent takes (c)-heavy \u002F expected (d)\u002F(e) \u002F feasibility questions; **all *failing* verifications and expensive (c)\u002F(d)\u002F(e) go back through re-convergence, never lead-solo** (a refutation changes the design after convergence). Claims discovered *mid-experiment* are recorded only (tagged `미검증` in discussion, routed at the next Quality Gate) — never auto-verified inline; the lead may allow one in-session re-entry per discovered claim, and a claim discovered while verifying a re-entered claim is residual-only (`잔여 사유: 검증 차단`, blocked reason \"recursion depth\").\n\n### Step 4: Result Synthesis & Documentation (Korean)\n\n- The lead synthesizes all discussion results into a structured Korean document:\n    - 재현·근본원인 (이슈·버그 수정 과제에 한해 최상단에 포함; 기능 설계 과제에서는 생략)\n    - 합의된 아키텍처\n    - 주요 결정사항과 근거\n    - 검증 기록 (세션 내 검증을 수행한 경우에 한해 포함; 수행이 없으면 생략)\n    - 미해결 이슈 \u002F 트레이드오프\n    - 구현 시 검증 항목 (잔여 검증 클레임이 있는 경우에 한해 포함; 없으면 생략)\n    - 테스트 설계 (대상 프로젝트에 테스트 환경과 기존 테스트 파일이 있는 경우 필수 포함; 둘 중 하나라도 없으면 생략)\n    - 구현 슬라이싱 (Step 1의 배포 형상 답변이 있는 경우에 한해 포함; 없으면 생략) — 이 표제를 쓰면 `권장 구현 순서`는 쓰지 않는다\n    - 권장 구현 순서 (구현 슬라이싱을 쓰지 않는 경우)\n- **Open entries carry `**구현 처분**`.** Every entry synthesis writes into `## 미해결 이슈 \u002F 트레이드오프` carries `**구현 처분**` and its companion field, chosen and written by `${CLAUDE_SKILL_DIR}\u002F..\u002F_common\u002Funresolved-closure.md` (`## 값 고르는 기준`, `## 작성자 꼴`); an entry the implementation would otherwise decide by itself is `구현 전 결정`.\n- **Runtime classification default.** If a runtime point in the product being designed maps unstructured input to a closed set of outcomes, Read `${CLAUDE_SKILL_DIR}\u002F..\u002F_common\u002Fruntime-classification.md` and apply it before finishing this step — it fixes the predicate, the two exits, and where the decision, the UR entry, and the R-item land. The predicate excludes judgment this same session makes about its own pipeline or design work (topology test, not this-repository test) — see the file.\n- **`## 재현·근본원인` section** (issue\u002Fbug tasks only — omitted for feature-design tasks). The section records the reproduction findings produced in Step 1 or Round 0 so the design rests on an observed cause, not a guess.\n    - **Placement & heading**: at the **very top** of the document, before 합의된 아키텍처 (for a bug fix the root cause is upstream of architecture and decisions). The heading is exactly `## 재현·근본원인` with **no leading section number** — `## 0.` \u002F `## 1.` etc. is forbidden because the fixed anchor `§재현·근본원인` (used by the Tier-2 pointer below) would dangle.\n    - **Fields**: `재현 절차` (a re-runnable recipe — literal commands or an inline fenced script, **no `\u002Ftmp` paths** since those are deleted, plus a `tracked-source 무변경 확인` note; if the observation depended on an out-of-tree driver\u002Finstrumentation, write that logic *inline as a fenced script* so the recorded recipe is self-contained and re-runnable) \u002F `관측된 증상` (\"미관측\" when only hypothesized) \u002F `근본 원인` (grade-neutral field name — whether it is confirmed lives in `근거 등급`, not here) \u002F `근거 등급` \u002F `재현 차단요인` (only when the hypothesis is due to a reproduction failure; carries `차단 사유` + `필요한 것`).\n    - **Grade acquisition**: `확인됨(재현·관측)` is earned ONLY when the recipe was actually run and `관측된 증상` observed; unrun\u002Funattempted\u002Fblocked is `가설(추측)`.\n    - **Multi-claim & mixed tasks**: if one section holds more than one reproduction claim, repeat each claim as a self-contained `### ` sub-block (each with its own `재현 절차`\u002F`관측된 증상`\u002F`근본 원인`\u002F`근거 등급` — the source of truth is per-claim), and a Tier-2 pointer targets that claim's sub-block anchor. A mixed task (bug fix + new feature) includes the section per-reproducible-claim: if any part of the task is a reproducible existing-misbehavior claim, the section is included (scoped to that part).\n    - **Grade propagation (one-way)**: the reproduction discovery point is the origin; Step 3 proposals carry a `[근거 등급: …]` prefix (label-only); `주요 결정사항과 근거` points at the grade by **referencing `§재현·근본원인`** (do NOT restate the literal grade token — no stored copy, prevents divergence); the grade is written once, in `## 재현·근본원인`.\n- **Tier-2 → unresolved-issue pointer**: only when reproduction hit Tier-2 (proceeding on a `가설(추측)` root cause) does the lead create an unresolved-issue pointer in the `## 미해결 이슈 \u002F 트레이드오프` section during this synthesis (the synthesis-terminal rule permits lead-driven Edits). Encode it to match that section's existing form (mixed-form prohibited; fresh-section default = sub-section). Sub-section example: `### N.x 재현 미확인 — 가설 근본원인 채택 여부` + `**상태**: 대기` + `**Category**: UR` + `**Surfaced-at**: Step 4 synthesis` + a body line referencing the `§재현·근본원인` anchor. The pointer holds its own `상태` (default `대기`) and the anchor, but **does NOT hold `근거 등급`** (that lives only in the canonical section, to avoid duplication\u002Fdivergence). This makes Step 5's walkthrough consciously ask the user whether to accept the hypothesized cause.\n- **`## 검증 기록` section** (verification ledger; unnumbered heading) — placed after `## 주요 결정사항과 근거`, before `## 미해결 이슈 \u002F 트레이드오프`. Holds `### V\u003Cn>.` sub-blocks per the V-ledger schema in `_common\u002Fverification.md` (the SOT — do NOT restate the field list here). The ledger accepts only performed verifications (`검증됨(통과)`\u002F`반증됨(실패)`, every entry carrying an observation). If no verification was performed, omit the whole section (the pre-save sweep makes the absence meaningful). Body claims reference an entry by the token-free anchor `(§검증 기록 V\u003Cn>)`; the ledger is the single SOT and `주요 결정사항과 근거` does not restate tokens. **Field-line rendering**: copy the CANON rendering example in `_common\u002Fverification.md` §4 byte-for-byte (bold key `**…**:`, no leading bullet `- `, one ASCII space after the colon) — do not choose your own bullet\u002Fbold style.\n- **`## 구현 시 검증 항목` section** (residual items; unnumbered heading) — placed after `## 미해결 이슈 \u002F 트레이드오프`, before `## 권장 구현 순서`. The two new sections straddle the unresolved-issues section without touching its parse region; neither new heading contains `미해결`\u002F`이슈`, so neither can match the walkthrough parse regex. Holds `### R\u003Cn>.` sub-blocks per the Residual-item contract in `_common\u002Fverification.md`. The lead performs the **transformation move** (that file) to convert each in-session-unsettleable claim into an R-item; a residual item is born by exactly the three paths of the contract (filter NO → `구현 필요`; verification-attempt exit → `검증 차단`; audit-reconciliation deferral → `검증 차단`). 0 items → omit the section. **Field-line rendering**: copy the CANON rendering example in `_common\u002Fverification.md` §5 byte-for-byte (bold key `**…**:`, no leading bullet `- `, one ASCII space after the colon) — do not choose your own bullet\u002Fbold style.\n- **`## 구현 슬라이싱` section** (workflow declaration; unnumbered heading) — placed after `## 구현 시 검증 항목`, and it **replaces** `## 권장 구현 순서` rather than joining it: the two say the same thing at different grades, and a document carrying both invites them to diverge. Write it when Step 1's delivery-shape answers exist; omit it otherwise (a single-repo, single-PR change needs no declaration and the omission is meaningful, not lazy). **The heading is matched as a whole line, exactly** — `^## 구현 슬라이싱$`, no leading space and no trailing text; a heading with a parenthetical tail is read as *not* a declaration at all and the document falls back to model-derived grouping.\n    - **Blocks and fields**: one `### 슬라이스 \u003Cid>` per slice (`\u003Cid>` is `[A-Za-z0-9]+`; the convention is `### 슬라이스 A`, `### 슬라이스 B`, and a trailing ` — \u003C제목>` after the id is fine). Field lines follow the same CANON rendering as everything else (`**키**: 값`, bold key, no leading bullet, one ASCII space after the colon); a list value is separated by **comma + space**. Required in every block: `**스킬**` (one of `design`·`design-audit`·`implement`·`review`·`apply` — the stage this slice *enters*), `**레포**` (the remote slug `\u003Cowner>\u002F\u003Cname>`, never a path — paths differ per machine and per worktree, and the slug is what the driver passes to `gh -R`), `**선언 파일**` (repo-relative paths in backticks; slices **may** overlap here — that is the point, and sequencing is what makes it safe), `**선행**` (a `슬라이스 \u003Cid>` list, or the literal `없음` — `없음` is a positive statement of independence and an omitted line is not the same thing; it means **implementation precedence**: this slice's branch is cut from a base on which every slice it names has already landed), `**절단점**` (a cutpoint token verbatim). Then, only when the slice has an apply: `**적용 명령**` (a one-line backticked literal — **the presence of this field is the declaration that an apply exists**, and it, not the cutpoint, decides whether the next two fields are required), `**적용 주체**` (`파이프라인` or `사람`; `사람` means the pipeline stops at merge and the command is copied verbatim into the morning report as an opaque string for the person to run), and — only when the actor is `파이프라인` — `**폭발 반경**` (what parks if the apply fails: `레포`, `런`, or a `슬라이스 \u003Cid>` list; the default is `레포` and it may only be narrowed).\n    - **`**머지 순서**` is the second kind of ordering, and every block you write carries it** — a `슬라이스 \u003Cid>` list, or the literal `없음`. It means **merge order**: the slice is planned, implemented and reviewed concurrently with the slices it names, cut from the current base, and only its merge waits until each of them has landed. The parser reads an absent line as `없음`, which is what keeps frozen documents meaning what they meant; a new block still writes the line, `없음` included. A `머지 순서` token names only a slice declared **earlier** in the section (`선행` carries no such rule, and adding one would park frozen documents that point at a later slice), and one token never sits in both lists of the same block. A slice joined to others only by merge order still writes `**선행**: 없음` — the gate refuses a missing `선행` in a repository with two or more segments, and that floor does not count `머지 순서`.\n    - **`**선행 사유**` and `**머지 순서 사유**` say why each kind was chosen.** Each is one line of prose and neither enters the declaration digest. A block that carries a `**머지 순서**` line is a new-grammar block, and in it every list that is not `없음` requires its own reason field: `**선행 사유**` for a non-empty `선행`, `**머지 순서 사유**` for a non-empty `머지 순서`. A block without the line is old grammar and owes no reason, so frozen documents stay valid.\n    - **Choosing the kind is the design's judgment, and the reason field records it.** Choose implementation precedence when the successor needs the predecessor's content in its own tree — it builds on it, calls it, tests against it, or a file overlaps within the closure below. Choose merge order when only the landing order matters and the closure is disjoint — the producer must land last, the slice is a release slice, or an intermediate state must not spread to the installed copy. Disjoint declared files do not by themselves prove the code independent, which is why the choice is a judgment and not a mechanical lowering.\n    - **Closure disjointness.** For a slice S, let M(S) be every slice reachable from S along `선행 ∪ 머지 순서` edges, and P(S) every slice reachable along a path whose first hop is a `선행` edge. S's declared files must be prefix-disjoint from every slice in M(S) \\ P(S): a slice in P(S) has landed before S is cut and is already in S's base, while a slice in M(S) \\ P(S) lands after S is cut and before S merges, so S never saw its change. `README.md`, `plugin.json` and `CHANGELOG.md` are **not** exempt — two bases' hunks in a generated index can conflict, or merge cleanly into something the generator would not produce. A violation is a defect owned by that slice, and it parks only that slice and the slices bound to it by either kind.\n    - **The writer and the reader ship in one release.** A parser older than this field ignores the `**머지 순서**` line and reads that edge as no edge at all, so a document using it must not run on a tree whose gate, shift and driver have not learned it.\n    - **`**잔여 항목**` is optional** — the verbatim headings of the `## 구현 시 검증 항목` items this implement slice owns, each wrapped in 「」 and separated by `, ` (`**잔여 항목**: 「### R4. …」, 「### R5. …」`), or the single word `없음` for a slice that owns none — the same spelling `**선행**` uses for an empty list. Every element is a `### R\u003Cn>. ` heading that the residual section carries verbatim; any other value refuses the whole segment plan. It is what the driver reads as this slice's residual share when it checks that an implement stage's last turn left a result line on each owned item: with one implement slice the share is every item and the field is not needed; with two or more, a slice that omits it owns none.\n    - **`**화면**` is optional, and it says which approved screens the slice waits for** — the literal `없음`, or a list of screen ids (`[a-z0-9-]+` each, separated by `, `) naming `### 화면 \u003Cid>` entries of the document's visual sidecar. A slice whose `**화면**` field is `없음` waits for no screen and is dispatched the night it is planned; a slice that lists screen ids covers those screens only. **An omitted field is not `없음`**: when the run plan has a visual stage or the document has a visual sidecar, a slice without the line waits for every screen of the document. Both checkers (the driver's and the gate's slicing check) read only the shape — a value that is neither `없음` nor such a list refuses the whole segment plan — and never whether an id exists; the dispatch site and `visual-unattended` look up the ids. **Write the field on every slice** when the interview record's `## 시각 방향` is not `없음`, so that a slice touching no screen says so rather than waiting the night out. The two shapes, verbatim:\n      ```text\n      **화면**: 없음\n      **화면**: order-list, order-detail\n      ```\n    - **`**크기 사유**` and `**권한 혼합 사유**` are optional, and each names the one coupling that a split would break** — one line of prose apiece, written only when rule (f) or (g) of the Step 7 slicing self-check asks for it: `**크기 사유**` on a block over the size baseline that stays whole, `**권한 혼합 사유**` on an implement block whose permission profiles mix and stay mixed. A sentence that names no coupling (\"it is large\") is not a reason. When the person gave the `슬라이스 수` answer, the reason quotes that answer instead of a coupling, because then the answer is what holds the block together. Neither enters the declaration digest, and neither the driver nor the gate reads whether it is present. The two shapes, verbatim:\n      ```text\n      **크기 사유**: 생성기와 그 픽스처가 한 형식을 함께 바꿔, 나누면 중간 커밋의 생성기 검사가 깨진다\n      **권한 혼합 사유**: 배포 설정 한 줄의 쓰기가 API 계약 변경과 같은 커밋에 있어야 둘이 어긋난 배포가 생기지 않는다\n      ```\n    - **`**리뷰 정책**` is optional and its default is `선리뷰후머지`** (values: `선리뷰후머지` \\| `선머지후리뷰` \\| `리뷰없음`). It exists because the cutpoint says *how far* a slice may go and cannot say *when review happens* — a slice may be authorized to merge and still owe its review afterwards, and those are two axes rather than two readings of one. `선머지후리뷰` does **not** remove the obligation, it defers it: the gate leaves a review-obligation row and the run cannot terminate while one is unfulfilled. `리뷰없음` is expressible only when **that target's `리뷰 정책 상한` in the run manifest is itself `리뷰없음`**, which is what stops a stage from choosing it for itself. The ceiling is the whole predicate: a slice may declare no looser than the target it runs against, and the ceiling was frozen at kickoff while a person was present. One real cost belongs with the field rather than in a footnote: post-merge review is by definition review against a base that has already moved, so the review anchor is the merge commit rather than a PR head — and what closes the obligation is **a review covering that obligation's merge commit**, not merely some later review of that segment. A review of the segment that does not contain the commit that was merged leaves the merge unreviewed while looking as though it did not.\n    - **`**라벨 인정**` is optional and an absent line reads as `없음`** — the names of the checks this slice expects to fail and to have answered by a label, separated by `, ` and each written exactly as the PR's check list prints it, or the single word `없음`. Write it only when the slice deliberately changes the surface such a check guards **and** the run manifest carries a `라벨 인정` row for that check under the slice's target — the target whose `원격 슬러그` is the slice's `레포`. Without both, leave it out: a person decided at kickoff which checks a label may answer, and this field only binds that decision to the slice that needs it. Every name it gives must equal the `체크` of one of those rows; a name no row carries, an empty element, whitespace around an element, a `|`, or `없음` beside a name parks this slice alone, not the whole plan. A value other than `없음` enters the declaration digest; an absent line or `없음` adds nothing, so documents without the field keep their digests.\n    - **A section-level `**슬라이스 수**: \u003CN>` is a checksum, not an input** — it must equal the number of blocks whose cutpoint is `PR` or later (so `커밋`\u002F`브랜치` slices are not counted). A mismatch means the declaration was truncated or misnumbered, and it is worth stopping for.\n    - **Two slices are declared as one by default, and only when the person left the count to the design.** The default applies only when the delivery-shape `슬라이스 수` answer — the brief's `## 배포 형상` line, or the autopilot interview record's — is `없음` or delegated to design (`설계에 위임`, with or without its `— 문 \u003Cn>` tail). A count or a chain the person gave binds the declaration: it is itself a positive reason to keep apart the slices it separates, and this rule never folds them. Where the default applies, merge two slices into a single block when all five hold:\n        1. they are joined by a `선행` edge that fans out on neither side — the predecessor has no other successor and the successor has no other predecessor. Only `선행` edges count here: a pair joined only by `머지 순서` does not meet this condition and is never merged. Both blocks' `머지 순서` must also be `없음` — a merged block has no rule for folding the two lists into one, so a pair either side of which carries a merge-order edge stays apart and that edge stays where the checks read it;\n        2. their `선언 파일` sets still overlap after setting aside the files every change touches regardless of content — generated indexes, version and release files, the repository-wide test runner or build manifest;\n        3. `레포`, `스킬`, `절단점` and `리뷰 정책` are equal, an omitted `리뷰 정책` reading as its default `선리뷰후머지`;\n        4. neither declares `적용 명령` — a block holds one `적용 주체` and one `폭발 반경`, so two applies cannot share one, and a merge that dropped either would switch off the park it declared without any check noticing;\n        5. the merged block passes rules (f) and (g) of the Step 7 slicing self-check without a reason field — its declared file count is at or below the size baseline, and it holds one permission profile. A `**크기 사유**` or `**권한 혼합 사유**` line either block still carries is not moved into the merged block; it is deleted.\n\n        Keep them apart only when the block prose gives a positive reason: a `슬라이스 수` answer the person gave, a baseline that must be measured on the tree before the other part lands, a release slice, or a conflict surface with in-flight work that the other part does not share. File order alone is not a reason. The rule governs new declarations only; a repair segment is not a declared slice and this rule does not fold it. Merging removes a boundary, not a review — the merged slice is reviewed under the same `리뷰 정책`, tier table and P0\u002FP1 gate.\n\n        A merge is finished only when all five of these hold. The driver reads every `선행` token and the checksum at kickoff and stops on a stale one, but it records a `폭발 반경` id without checking that the id exists and parks by exact match, so a radius that still names a retired slice parks nothing. It also runs the blocks once in section order without sorting them and parks a block whose `선행` has not finished, so where the merged block stands decides whether it runs:\n        1. the predecessor's `\u003Cid>` survives and the successor's is retired; the merged block's `선언 파일` is the union of both;\n        2. every other block's `선행`, `머지 순서` and `폭발 반경` that names the retired id names the surviving one instead, listed once;\n        3. the merged block's `선행` is the predecessor's `선행`, its `머지 순서` is `없음`, and its `선행 사유` is the predecessor's — condition 1 leaves the successor no other `선행` edge and neither block a `머지 순서` edge;\n        4. the section's `**슬라이스 수**` drops by one when the shared cutpoint is `PR` or later, and is unchanged when it is `커밋` or `브랜치`, which the checksum does not count;\n        5. the merged block takes the successor's position in the section, after every block its `선행` names — left at the predecessor's position it runs ahead of the blocks that stood between the two, and a block among them whose `폭발 반경` named the successor then parks nothing if its apply fails, because the merged block has already run.\n\n        Keep every prose line here and in a slice block from beginning with a bold field key followed by a colon: the slicing parser reads the first such line in a block as that field.\n    - **There is no `적용 순서` field.** Apply order is derived from `선행 ∪ 머지 순서` restricted to the apply-declaring slices; two orderings that cannot be written separately cannot disagree.\n- **`## 테스트 설계` section** (unnumbered heading) — placed after `## 구현 시 검증 항목`, before `## 구현 슬라이싱`. **Required** whenever the target project has a test environment (jest, vitest, pytest, go test, …) **and** existing test files (`*.spec.ts`, `*.test.tsx`, `*_test.go`, …); omit it when the project lacks either one. It holds the test design for the module\u002Ffeature being designed — unit-test scenarios and E2E test cases — so implementation inherits a test surface instead of inventing one. This is a section of the design document itself, not a follow-up task.\n- **UR escalation pointer (lead's delegated judgment, Tier-2 isomorphic)**: if a residual claim is load-bearing enough that the user should consciously accept building on it, the lead creates a UR pointer in `## 미해결 이슈 \u002F 트레이드오프` — `상태`\u002F`Category`\u002F`Surfaced-at` + a `§구현 시 검증 항목 R\u003Cn>` body reference only; it **never** includes the `검증 등급` key, token, or recipe (predicate check). Per-item mandatory pointers are rejected (the dual backstop already validated the deferral; N pointers = N friction prompts).\n- **Synthesis write economy (lead-local, inside the synthesis-terminal window).** What synthesis costs is mostly how many responses it is spread across, each one re-reading the lead's whole history (`_common\u002Fagent-team-protocol.md` `## Turn economy`). So the lead writes the document in as few responses as its content allows; the author, the inputs and every check of this step stay as they are.\n    - **Marks.** At three points the lead appends one line `\u003Cevent> \u003CUTC time> \u003Cstage id>` to `$STATE\u002Fsynthesis-marks.txt` with the file-edit tool, creating the file when absent: `enter` as the first act after the last convergence witness is recorded, `draft` once the whole draft is in the document and before the fidelity pass begins, and `save` at the synthesis terminal, after the last document write. The time is the output of `date -u +%Y-%m-%dT%H:%M:%SZ`, issued in the same response as other independent calls (inside a gated run through `gate.sh exec … --surface 읽기`); the stage id is `CC_PIPELINE_STAGE_ID` read by name, or `-` when it is unset. A mark that comes again after a re-attachment is appended, never rewritten. The marks are measurement, not a gate: a missing mark leaves the window unmeasured and changes nothing else.\n    - **Compose whole, insert once.** Compose the whole draft, in this step's section order, before writing any of it. Insert it with one Edit whose `old_string` is the ledger block's closing line — with the line before it when the closing line alone is not unique in the stub — and whose `new_string` is those same bytes followed by a blank line and the draft. When one response cannot carry the whole draft, split only at `## ` boundaries and anchor each continuation the same way as the first insertion: the last line of the previous insertion, together with as many lines before it as make the string unique in the document — section endings repeat (every verification entry ends on the same hygiene line), so the last line alone is often not unique. Never write the draft section by section or field by field, and never Write the whole file over the stub: the ledger block changes only by its own single-row Edits. After the last insertion, confirm with one read that the last `## ` heading of the planned order is in the document.\n    - **Inserting is not saving.** The draft in the document before the fidelity pass is not the save of `Synthesis terminal`: the save is this step's last document write, after the pre-save sweep, and the `save` mark follows it. Fidelity-pass dispatches and re-convergence messages before that write stay inside the window that rule leaves open before the first save.\n    - **Batch fixes by source.** Once every finding of one source is in hand — every fidelity witness read, every sweep check run — apply all fixes that do not depend on one another as several Edits in one response, each anchored on text unique in the document. Only a fix whose anchor another fix rewrites waits for the next response.\n    - **Batch the sweep's reads.** The sweep's checks and the two boundary-gate commands do not depend on one another; issue them in one response (inside a gated run, within `## Turn economy`'s digest-sharing bound).\n    - Not a CFI, on the same basis as the pre-save sweep: skipping it brings back today's cost, not a mis-transition.\n- **Synthesis fidelity pass (team-driven, inside the synthesis-terminal window, after the full draft is synthesized and immediately before the pre-save sweep)**: before the lead's solo pre-save sweep, the Step 3 team's roles (dispatched afresh for the `fidelity` phase into their ledger rows) check draft↔discussion fidelity — the lossy-synthesis class of defect that only an original-context holder can catch, and that any fresh, context-free reader — which re-reads only the saved doc and holds none of the discussion — can never reach. Emit once, inline at entry (one-way notice, not a question): *\"팀이 설계 초안의 충실도를 점검하고 있습니다.\"* **Ordering rationale**: before the sweep, so the sweep also covers the fidelity Edits. **Not a CFI** (same basis as the pre-save sweep — it rides the existing \"clarify before the first save\" window, adds no new turn-yield semantics; a skipped pass degrades to a quality loss, not a mis-transition; nothing is added above the `## Control-Flow Invariants` heading).\n    - **Subject & input**: reuse the existing Step 3 team's roles — dispatch each role afresh into its ledger row for the `fidelity` phase (reproduction\u002Fverification specialists included — they check their own output sections, the high-trust grade\u002Fverdict data implement consumes verbatim). The dispatch names the member's own round witnesses by path, so what the member contributed is read from disk rather than from a retained context — the pass's sensitivity is bounded by what those witnesses recorded. Hand each member the **whole draft by path** — the dispatch names the document's path, the line number of its first `## ` heading and the draft's last `## ` heading, and the member Reads from that line to the end of the file, in consecutive `offset`\u002F`limit` ranges whenever one Read cannot return the rest (not a section slice — whole-cloth omissions have no home section and surface only against the full draft). The member's witness quotes the last `## ` heading it read as a receipt. A witness without that receipt, or with a different heading, did not cover the whole draft: the lead treats it as a Case 3 non-conforming witness and re-assigns that member once with the whole draft quoted in the resume, the one case in which the lead emits the draft. Otherwise the lead's dispatch text never carries the draft itself. The ledger block above the first heading is not part of the draft, so the member does not read it. **Scope**: each teammate checks **only their own contribution** — this pass asks *\"did synthesis distort or drop what I said?\"*, which only the contributor can answer. Document-wide coherence and completeness are **not** delegated away: they are the subject of the **Step 7 Class C coherence pass**, which dispatches this same team's roles afresh against the final text.\n    - **Two fidelity classes**:\n        - **Interpretive** (root-cause framing, recipe prose, recommendations, concerns): fidelity = **accounted-for** — adopted (meaning preserved; paraphrase passes) OR rejected with rationale recorded in the doc. A point rejected-with-rationale passes (not re-litigation). Vanished without a trace = fail.\n        - **Transcription** (observation tokens: `근거 등급`, each `검증 등급` verdict + its backing observation field): **byte-identical or flag**. Grades\u002Fverdicts are recorded once at discovery and propagate one-way; synthesis only transcribes (the lead is read-only to them). No rationale justifies recording an observed `확인됨(재현·관측)` as `가설(추측)`, or a performed verdict as weaker. Any divergence MUST be flagged by the specialist.\n    - **Completion contract**: each member publishes its fidelity check as its **witness** `${scratchDir}\u002F{role-slug}.fidelity.md` (sentinel\u002Fnonce-terminated per `_common\u002Fagent-team-protocol.md`; the return text is only an early-wake hint, and the lead reconciles the witness — never the return). The witness body is either `Fidelity confirmed — all my contributions accounted for.` (clean) or one discrepancy block per finding:\n        ```\n        - type: omission | distortion | grade-distortion | decision-reopen\n        - contribution: \u003C원래 논점 \u002F 토큰, 1줄>\n        - location: \u003C초안 섹션\u002Fanchor, 또는 \"absent\">\n        - evidence:\n            omission        → 어디에도 없음\n            distortion      → 초안은 X, 나는 Y (의미 변경; paraphrase는 finding 아님)\n            grade-distortion→ draft token=X | my broadcast value=Y (BYTE 비교; 의미 latitude 없음; 그대로 복원, 판정 금지)\n            decision-reopen → 기록된 rationale 자체가 틀렸거나 unsafe한 이유\n        ```\n        Either form ends, above its sentinel, with one line of its own `findings: \u003Cn>` — the number of discrepancy blocks, `findings: 0` beside the clean sentence. A fidelity witness without that line is a Case 3 non-conforming witness (`_common\u002Fagent-team-protocol.md`): re-instruct the member and take its `fidelity-rev\u003Ck>` revision. The count is the line's value; it is not checked against the blocks.\n        A published witness is the completed check — \"check done,\" not \"no issues\"; a discrepancy report is a completed check. The \"collect all witnesses\" gate (`witness_present` for each member, then read the witness) is satisfied by either form. A thin or empty witness (no fidelity verdict) is a Case-1 thin\u002Fempty witness, not a completed check (see No-response below).\n    - **Triage (lead authority)**: the `type` is the teammate's read; the lead routes by one test — **\"does fixing this contradict a converged decision?\"**\n        - **NO → lead Edits immediately**: re-reflect the omission \u002F correct the distortion \u002F restore the byte-true grade\u002Fobservation to its **canonical SOT** (the `근거 등급` field, the `검증 기록` V-entry's `관측 결과`, or `## 재현·근본원인`'s `관측된 증상` — never a downstream token-free `(§…)` reference). No team cycle.\n        - **YES → decision-reopen → reuse the pre-save sweep's 1-cycle re-convergence** (author SendMessage → focused exchange → mini cross-review if cross-cutting → update draft → re-check → 2nd failure → AskUserQuestion). In the decision-reopen context the three options are re-read as \"adopt the lead's recorded rejection rationale over the teammate's objection \u002F defer the reopened decision to Step 6 redesign \u002F abort\" (a challenge to a converged decision, not a verification claim). The 1-cycle counter binds to the **reopened decision** (not a grade token), per failing item; it is an **orthogonal axis** to the Case-1 thin-return counter below and they never co-increment.\n        - **Restore, never re-grade**: a `grade-distortion` fix may restore **only the value already present in the specialist's Step-3 broadcast**. A third value Z differing from both draft and broadcast is a new observation, not a fidelity discrepancy — this read-only pass cannot physically earn a new grade (no recipe run, no tree change), so it is inadmissible and bounces to re-convergence (the specialist must actually re-run and re-broadcast). Two locks make this unsmugglable: transcript reference-equality + the pass's read-only nature.\n    - **No-response — Case 1 \u002F Case 2 handling** (per `_common\u002Fagent-team-protocol.md` escalation): a thin\u002Fempty fidelity witness and a never-returning member are the two failure phenotypes.\n        - **Case 1 — thin\u002Fempty witness** (counter): a member publishes a witness with no fidelity verdict (empty or substanceless). 1st → re-scope + resume once (hard prompt: \"no empty witness — deliver your fidelity verdict or name a concrete blocker in one line\"); 2nd consecutive thin\u002Fempty witness → `AskUserQuestion`. The fidelity-scope prompt variant: (a) \"save contributor X's already-reflected contribution without a fidelity check\" (→ the emit-only coverage-gap path below — the contribution is already in the draft, only the self-check is missing), (b) re-scope once more, (c) abort save\u002Fworkflow. On option (a), land on the emit-only path (do NOT apply document-metadata convergence-exclusion marking — see Exclusion is emit-only below).\n        - **Case 2 — never-returns** (binary, not a counter): a fidelity-pass dispatch never returns (runaway\u002Fwedge) and the protocol's reconcile-ladder death verdict fires. The recovery is `TaskStop` + a **same-round respawn** with the same fidelity assignment (new `agentId`, with the ledger row's `agentId` \u002F `outputFile` updated and its `stallMark` reset per the protocol). If the respawn also dies → `AskUserQuestion` (same fidelity-scope variant as Case 1).\n        - The decision-reopen re-convergence 1-cycle counter (Triage above) is an orthogonal axis to the Case-1 thin-return counter and they never co-increment.\n        - **No implicit-confirm** — a missing witness is never read as \"no objection.\"\n    - **Exclusion is emit-only**: when a Case-1 option-(a) user decision excludes a teammate, do **not** apply the escalation's document-metadata convergence-exclusion marking — the teammate already converged in Step 3 (substantive input is in the doc, only self-verification is missing), there is nothing to stamp, and stamping would violate the no-trace invariant. Instead, at save time, emit **once per excluded contributor** (Korean, mandatory — \"no silent caps\"): *\"기여자 X의 기여 내용은 충실도 점검 없이 저장됩니다.\"* ATP's Case-1 option-(a) document-metadata marking — and the `state=aborted` ledger routing that a genuine Case-1 drop applies to remove a member from the dispatch-completeness roster — are both restricted to **genuine Step-3 synthesis-convergence exclusion**. This fidelity scoped skip drops only the member's current self-check, not the member: it **stays in the `state ≠ aborted` roster and is not set to `aborted`**, so a later decision-reopen re-convergence correctly re-dispatches it (desired participation, not resurrection).\n    - **Visibility — 3 emit points**: (1) on entry — *\"팀이 설계 초안의 충실도를 점검하고 있습니다.\"* once (one-way notice, placed inline above; not re-emitted in re-convergence, which is silent by its own spec); (2) clean termination — no emit (a clean pass emits nothing beyond the on-entry notice and the existing save notice — fixes are indistinguishable from ordinary synthesis); (3) exclusion — *\"기여자 X의 기여 내용은 충실도 점검 없이 저장됩니다.\"* once per contributor at save time. All three are one-way progress-class notices, not ATP \"surface\" events, and touch no escalation gate. All `*\"...\"*` italic Korean, matching the existing Step 4 emit convention.\n    - **No-trace invariant**: a clean pass leaves no mark in **either the document or the user channel** (beyond the on-entry notice) — fixes appear only as the corrected body itself. The coverage-gap emit is the sole exception, and even it is an ephemeral user notice, not a document write (the saved-document no-trace invariant is preserved).\n- **Pre-save sweep (lead backstop, inside the synthesis-terminal window, before the first save — so re-convergence is always still possible)**: scope is the entire synthesis **draft**, decisively including assertions the lead introduced during synthesis (the only class that never passed the Quality Gate — the sweep's unique coverage). **Pass conditions**: the four conditions of `_common\u002Fverification.md` §10 (the shared sweep predicate) — do NOT restate them here; that section is the single definition and this skill cites it. **Late finds**: cheap (a)\u002F(b) → the lead verifies immediately and records it in the ledger; expensive\u002Ffailing → **re-convergence** (SendMessage the affected author → focused verify\u002Ffix exchange → mini cross-review if cross-cutting → update draft → re-sweep the changed part → save). **Sweep record**: for every refutation that opens such a re-convergence, append one line `round-3: sweep — \u003Cthe refuted claim, one line>` to the durable corpus file `$STATE\u002Fwitness\u002FSWEEP.md` with the file-edit tool, the way `INDEX.md` is written; when a sweep refutes nothing, still create the file (empty) as the sweep ends, so \"no refutation\" and \"no record\" stay apart. Each time a sweep ends (a re-sweep of the changed part included), rewrite `INDEX.md`'s lead row — role-slug `lead`, round\u002Fphase `sweep` — with `SWEEP.md`'s byte count and `sha256` at that moment. This re-convergence does not open round 3; it stays the author-only cycle above, and a fidelity `decision-reopen` that borrows it is not written to this file. This rides on the existing \"clarify before the first save\" sentence — no new turn-yield semantics, **not a CFI** (a missed sweep degrades to today's quality baseline, not a mis-transition). **Re-convergence limit**: at most 1 cycle per failing claim; a second failure of the same claim → `AskUserQuestion` (accept residual with refutation evidence \u002F route to Step 6 redesign \u002F abort) rather than a silent round. **Visibility tripwire**: at ~5 in-session worktree experiments the lead emits a status note (visibility, not a gate).\n- **Synthesis terminal**: All teammate clarifications must be completed before saving the design document. Once the file is saved, the synthesis phase is over — no further teammate messages are permitted. Do NOT save a partial document, send a teammate message, then save again; clarify before the first save. The sequence save → cleanup → presentation is atomic. Step 5 (walkthrough) and Step 6 (refinement) are new editing phases governed by their own state-check + cleanup rules. The synthesis-terminal rule bars further Step 3 team messages but does NOT bar lead-driven Edits to the saved doc.\n- Save the design document to the project's `docs\u002F` directory. **File naming convention**: use `docs\u002F{topic-slug}.md` where `{topic-slug}` matches the Step 3 team's topic slug exactly (e.g., Step 3 team `design-auth-flow` → saved doc `docs\u002Fauth-flow.md`). This filename-to-slug binding is the local state used by Step 5's entry state-check to recover the slug without relying on lead memory. **Interrupted-save case**: if the save itself was interrupted (partial write, permission error, etc.), the state-check cannot recover the slug from the filename. In this case the lead must either (a) recover the slug from the original task input or interview output that started the workflow (from in-session conversation history, including slash-command `$ARGUMENTS` if invoked that way), or (b) treat the workflow as ambiguous and prompt the user via `AskUserQuestion` before any cleanup action.\n- **Document location, plan derivation, and post-implementation update** — the three duties that outlive this step.\n    - **Location**: the spec \u002F design document is saved under the **project root's `docs\u002F` directory**. In a workspace that nests several repositories under one root, it is `docs\u002F\u003Crepo>\u002F` — the repository the design targets, not the workspace. This is a different layer from the filename rule above — that rule fixes the file name, this one fixes the directory — so whether the directory is `docs\u002F` or `docs\u002F\u003Crepo>\u002F`, the file is still named `{topic-slug}.md` and the filename-to-slug binding above holds unchanged.\n    - **Plan derivation**: the implementation plan is written **from the saved document**, never from in-context memory of the discussion. The document is the input to planning, not a record of it.\n    - **Post-implementation update**: once implementation is finished, the document MUST be updated to match what was actually built. Leaving a design document unrevised after its implementation diverged makes it a wrong document, not a historical one.\n- **On the normal path the three user-facing lines below are rendered by the seat from `presentation.md` (CFI-1b), verbatim; the leg composes them and never emits them.**\n- Notify the user in Korean: *\"설계 문서 저장을 완료했습니다. 팀을 정리한 뒤 결과를 공유드리겠습니다.\"*\n- **Before presenting results to the user, Read `${CLAUDE_SKILL_DIR}\u002F..\u002F_common\u002Fteam-cleanup.md`** and apply it — normal completion is a no-op (returned tasks already self-terminated), abort is `TaskStop` on any `state=running` agentId, plus ledger hygiene.\n- **Verification aggregate line**: if the `## 구현 시 검증 항목` section is non-empty, include in the Step 4 presentation one Korean line — *\"구현 시 검증 항목 N건이 기록되었습니다 — \u002Fimplement 시작 시 우선 검증됩니다.\"* (queue impact 0).\n- Present the results to the user in Korean. Do NOT yield the turn here — the presentation and Step 5's entry are one continuous turn. Immediately continue into Step 5 below in this SAME turn, with no stop, no wait, and no user prompt. (CFI-1b)\n\n### Step 5: Unresolved Issue Walkthrough\n\nThis step runs automatically right after Step 4 (CFI-1b). Its purpose is to drive every unresolved issue in the saved design document to a decision **without waiting for an unprompted user request**, scoped strictly to *issues that cannot be resolved without user input*. Mechanical gaps, false positives, and auto-decidable items are NOT this step's responsibility — the **Surface Depth router** below gives each of them a named destination: the Step 7 Class C coherence pass, a post-implementation `\u002Fcc-cmds:review` carrying a `design-conformance` tag, or an explicit recorded drop. User-facing communication in this step is Korean; the normative prose below is English.\n\n> \"Walkthrough-spawned teams (Step 5) and refinement teams (Step 6) are both just fresh nameless-task spawns recorded in the ledger — there is no shared team namespace or monotonic counter — but they still differ in scope and lifetime: a walkthrough-spawned team is bounded to a single unresolved issue's decision debate (user-initiated when auto-investigation findings alone don't yield a clear decision) and its members self-terminate at that issue's resolution; a refinement team handles a user-initiated multi-turn refinement and its roles live (one fresh dispatch per round) until the user is satisfied. They are not competing entry points — they are the same entry point (user-confirmed spawn of nameless background tasks for a single bounded scope) invoked at two different lifecycle moments. The lead never extends a walkthrough-spawned team into a refinement team or vice versa — the `self-terminate → next spawn` contract is enforced unchanged.\"\n\nTerminology: throughout this skill use **\"walkthrough-spawned team\"** (not \"walkthrough investigation team\"). \"Investigation\" refers strictly to the lead-only, read-only activity defined below.\n\n#### Trigger & Queue Initialization\n\n- Parse the saved doc's `## 미해결 이슈 \u002F 트레이드오프` section to initialize the issue queue. **Parse contract**: match the heading with the regex `^##\\s+(?:[0-9]+\\.\\s+)?미해결\\s+이슈(?:\\s*\u002F\\s*트레이드오프)?\\s*$` — an optional leading section number (`6. `, `10. `, any digit count) and an optional `\u002F 트레이드오프` suffix are both allowed. On **multi-match**, use the LAST match (synthesis is written top-down, so the deepest occurrence is canonical).\n- `등급 1` On **0-match**, surface via `AskUserQuestion` with three options: (a) **add the section and proceed** — the lead creates a `## 미해결 이슈` heading via doc Edit (sub-section form by default, per the encoding rules below), re-parses the doc to rebuild the queue; entries the user pre-added are processed as-is, and 0 entries cascade naturally into the 0-issue path; (b) **skip the walkthrough** and proceed to Step 6; (c) **abort** — the entire design workflow terminates and Step 6 is NOT entered.\n- **0 issues**: emit the Korean notice *\"미해결 이슈가 없어 곧바로 플랜 리파인먼트 단계로 이동합니다.\"* and proceed directly to Step 6. (CFI-2)\n- **1+ issues**: emit *\"설계 문서에 미해결 이슈 N건이 확인되었습니다. 하나씩 검토하며 정리하겠습니다.\"* and enter the walkthrough proper.\n- **Depth-2 promotion on queue init**: any entry carrying both `상태: 보류` and a `(깊이: 2)` marker is auto-promoted to depth-1 — the lead Edits the doc to change `상태: 보류 → 상태: 대기` and `(깊이: 2) → (깊이: 1)` together (the `Parent` field is preserved as historical metadata), then appends it to the queue. Plain `상태: 보류` entries (no depth marker, or `(깊이: 1)`) are NOT promoted — those are deliberate user deferrals.\n- **Drop-uncertain promotion on queue init**: any `상태: 보류` entry whose `사유:` text contains the substring `drop 미확정` (produced by the abort-during-drop-prompt path below) is also promoted — change to `상태: 대기`, clear the `사유` field, append to the queue. This applies regardless of any depth marker, and re-surfaces issues whose drop confirmation was never completed.\n- **Queue order**: doc-order, top-to-bottom. Depth-1 items that surface mid-pass are appended to the *end* of the queue (not inserted right after the current issue) and are reached only after all pre-existing items are processed. No per-category priority ordering.\n- After the walkthrough finishes, emit *\"미해결 이슈 워크스루를 종료했습니다. 이어서 플랜 리파인먼트를 시작하겠습니다.\"* and enter Step 6 automatically. (CFI-2)\n- If the user aborts mid-walkthrough, batch-mark the remaining items `상태: 보류` (see Abort Semantics below) and move to Step 6. (CFI-2)\n\n#### Issue Sources & Categories\n\nThe issue queue has two sources:\n\n1. The saved doc's `## 미해결 이슈 \u002F 트레이드오프` section (the Step 4 output).\n2. Items the lead surfaces while re-reviewing the doc — but these must be **doc-first**: record the item in that section via Edit *before* appending it to the in-memory queue (idempotency). Items found during the bulk re-review at walkthrough entry are queued as `(깊이: 1)`; items found incidentally during a depth-1 issue's auto-investigation or team discussion are recorded doc-only as `(깊이: 2)` and do NOT enter the queue (see Depth Management below).\n\nEach issue is classified into one of four categories:\n\n| Category | Code | Definition | Auto-investigation default |\n| --- | --- | --- | --- |\n| Decision-needed | UD | A value\u002Fchoice the synthesis left undecided or set to a default | None — user value judgment |\n| Clarification-needed | UC | Whether an assumption the synthesis adopted matches user intent | `grep` the codebase convention first |\n| Alternative-to-evaluate | UA | The doc presents multiple paths and the user must pick | Read each option's affected files + cost estimate |\n| Risk-acknowledgment | UR | A deliberate tradeoff the user must consciously accept | None — surface the tradeoff framing only |\n\n#### Surface Depth (3-arm router)\n\nWhile re-reviewing the doc, the lead routes each candidate issue to exactly one of four destinations. The walkthrough surfaces only what the user must decide; everything else gets a **named owner** or is dropped **on the record**. Nothing is left unrouted.\n\n> **Arm 0 — surface here (this step's own scope).** *\"Does resolving this require user input — a value judgment, an intent confirmation, a choice among alternatives, or a conscious risk acceptance?\"* YES → the walkthrough surfaces it now, per the per-category flow below. NO → route to arm 1, 2, or 3.\n>\n> **Arm 1 — coherence \u002F completeness → QUEUE it for the Step 7 Class C pass.** Cross-section field or contract mismatch, a decision contradicting another section, spelling and formatting, any internal inconsistency the document itself can settle.\n>\n> **Arm 2 — an item the design deliberately left to implementation → `\u002Fcc-cmds:review` carrying a `design-conformance` tag.** Missing standard error handling, an unimplemented item, anything whose real question is *\"did the code end up matching the design?\"* That question is unanswerable before code exists, so its destination is post-implementation review rather than this step.\n>\n> **Arm 3 — everything else → EXPLICIT DROP.** A false positive already resolved in the doc body, a hypothetical unrelated to real risk, an item outside the design scope, an item the lead's own auto-investigation alone resolves. Dropping is a decision, so it is recorded rather than silent — the pre-queue filter below is its mechanism.\n\n**Arm 1's timing is load-bearing — do NOT run anything there.** The walkthrough is Step 5; the Class C pass runs after Step 6. Arm 1 is therefore **queue-loading for the terminal window**, not execution: the lead records the item as a one-line doc-body note tagged `[Step 7 정합 점검 대상]` and moves on. Reading this arm as *\"run the enlarged pass now\"* means editing the document **before the freeze**, and the downstream audit's whole guarantee rests on nothing changing between the freeze and the reads. Arm 2 fires after implementation and arm 3 is immediate and final, so neither has a timing hazard.\n\n**Mapping of the previously-non-surfaced classes** to their arms:\n\n| Class | Arm |\n| --- | --- |\n| spelling, formatting, cross-section field\u002Fcontract mismatch | 1 |\n| missing standard error handling | 2 |\n| items already resolved in the doc body (false positives) | 3 |\n| hypothetical items unrelated to real risk | 3 |\n| items outside the design scope | 3 |\n| items the lead's own auto-investigation alone can resolve | 3 |\n\n**Pre-queue filter** (arm 3's mechanism): this happens *before* queue initialization — while the lead re-reviews the doc, any candidate it judges a false positive gets only a short lead note in the doc body (e.g., *\"lead 자동 조사 결과: 코드베이스 컨벤션 X와 일치 — false positive\"*) and does NOT enter the queue. No state-machine transition occurs, so this is unrelated to the state machine; it is *triage*, not a *decision*, and does not conflict with the user-confirmation rule for decisions. It applies to all four categories.\n\n#### State Machine (5 + 1, doc-anchored)\n\nEach issue follows this state machine (5 non-terminal + 1 transient-remove):\n\n```\npending → investigating → awaiting-decision → resolved\n                                           ↘ deferred\n                                           ↘ dropped\n\nUD\u002FUR shortcut: pending → awaiting-decision (skips investigating)\n```\n\n- `investigating` \u002F `awaiting-decision` are **ephemeral by default** (lead memory). If a transition is mid-flight when a turn ends, checkpoint-write it to the doc so the next session can recover. The checkpoint format is the encoding convention below — sub-section form prepends a `**상태**: 조사중` or `**상태**: 결정대기` line; table form updates the `상태` column value.\n- **Per-category transition shortcut**: UD (user value judgment) and UR (tradeoff acknowledgment) have no auto-investigation, so they go `pending → awaiting-decision`, skipping `investigating`. UC\u002FUA follow the full transition.\n- **Checkpoint recovery**: when a new walkthrough invocation parses the doc and finds a `상태: 조사중` or `상태: 결정대기` entry, the prior session's transient memory is lost, so the lead (i) **Edits the doc to overwrite the marker with `상태: 대기`**, then (ii) appends it to the in-memory queue as `대기` so it is re-investigated in natural doc-order. The doc marker and queue state must always agree, so an in-memory reset alone is not sufficient. The checkpoint only guards against doc-state loss; it does not recover in-memory investigation findings.\n- `resolved` \u002F `deferred` are **terminal** — written to the doc immediately.\n- `dropped` is **terminal-remove** — right after user confirmation the entry itself is deleted from the doc (the doc reflection is an entry removal, not an annotation write; see the dropped branch below).\n\n#### Doc Encoding (tolerate both forms + 상태 marker)\n\nExisting design docs use two encodings: **table form** (columns `항목 | 내용 | 우선순위 | 비고`) and **sub-section form** (`### N.x \u003C항목명>` headings + prose body). The walkthrough tolerates both and adds an inline `상태` marker.\n\n- **Table form**: append a `상태` column to the right of the existing columns. Additional fields (Category, Reason, 자동조사 요약, Surfaced-at, Parent) attach as extra columns. **Field definitions**: `Surfaced-at` = the walkthrough invocation that surfaced the entry (format `walkthrough pass \u003CN>`, or `Step 4 synthesis` meaning an original design output item). **N counter**: a monotonic walkthrough-invocation counter starting at 1, +1 each invocation; not stored separately but derived as `max(existing Surfaced-at entries) + 1` (the same doc-anchored, no-lead-memory doctrine as file-system enumeration); if the doc has no entries on the first call, N=1. `Parent` = a depth-2 entry's parent depth-1 issue (format `\"issue title (§anchor)\"`). The other fields are defined elsewhere in this step. **Last-row removal edge case**: if a `dropped` removal leaves the table with 0 data rows (only header + alignment), the lead removes the entire table and replaces it with the one-line note *\"이번 walkthrough에서 모든 미해결 이슈가 해소되었습니다.\"* The `## 미해결 이슈` heading itself is kept (needed by the parse contract and future walkthrough invocations).\n- **Sub-section form**: prepend `**상태**: \u003Cvalue>` to the first line of each sub-section body. Additional fields are added as prose lines: `**Category**: \u003Cvalue>`, `**Surfaced-at**: walkthrough pass \u003CN>`, `**Parent**: \u003Cissue title> (§\u003Canchor>)`, `**Reason**: \u003Ctext>`, `**자동조사 요약**: \u003Ctext>`. **Field definitions are form-agnostic**: the table-form definitions above (N counter derived as max+1, etc.) apply identically — the forms differ only in notation, the field semantics are single. **Last-entry removal edge case**: if a `dropped` removal deletes the last `### N.x` sub-section, leaving 0 entries under `## 미해결 이슈`, the lead inserts the one-line note *\"이번 walkthrough에서 모든 미해결 이슈가 해소되었습니다.\"* as prose right after the heading. The heading itself is kept.\n\n`상태` values (5+1 states → 6-value Korean vocabulary):\n\n| Internal state | Korean value | Meaning |\n| --- | --- | --- |\n| pending | `대기` | discovered, unprocessed |\n| investigating | `조사중` | auto-investigation in progress (ephemeral) |\n| awaiting-decision | `결정대기` | investigation done, awaiting user input (ephemeral) |\n| resolved | `해결` | decision applied, reflected in the doc body |\n| deferred | `보류` | deferred via per-issue defer or abort |\n| dropped | `제외` | judged a non-issue by auto-investigation — **transient classification only** (the `제외` judgment exists in lead memory only; right after user confirmation the entry is deleted from the doc, and no `상태: 제외` annotation remains) |\n\nAdditional invariants:\n\n- **Mixed-form prohibition**: within a single doc's `## 미해결 이슈` section, do not mix table form and sub-section form. The doc keeps whatever form Step 4 chose; the walkthrough never converts forms. This binds this skill only when it writes the section anew: an audit or a re-convergence adds an entry carrying `**구현 처분**` below a table in sub-section form, by `${CLAUDE_SKILL_DIR}\u002F..\u002F_common\u002Funresolved-closure.md` (`## 작성자 꼴`).\n- **Entries left open carry `**구현 처분**`**: before the freeze, every entry left at a `상태` other than `해결` — `보류` above all — carries `**구현 처분**` and its companion field, chosen and written by `${CLAUDE_SKILL_DIR}\u002F..\u002F_common\u002Funresolved-closure.md` (`## 값 고르는 기준`, `## 작성자 꼴`).\n- **Fresh section default**: if the Step 4 output has no `## 미해결 이슈` section (synthesis judged 0 issues), the walkthrough uses **sub-section form** by default when creating the section (avoids table layout overhead at 0 rows).\n- **Marker absence → `상태: 대기`**: if an entry exists but has no `상태` marker, the walkthrough interprets it implicitly as `상태: 대기`. A marker is written to the doc only at the moment of a user decision; there is no retroactive bulk-write. This is the migration policy for pre-existing docs written without markers.\n\n#### Depth Management (single section + inline marker)\n\nRe-review and auto-investigation can surface new issues. Depth markers prevent infinite recursion:\n\n- **`(깊이: 1)`** — an item the lead surfaced independently during walkthrough re-review. doc-first Edit → queue-append → handled in the current walkthrough pass.\n- **`(깊이: 2)`** — an item surfaced during a depth-1 issue's **auto-investigation or team discussion**. doc-first Edit (default `상태: 보류` + `사유: depth-2 follow-up (parent \u003Cissue title> §\u003Canchor>)` + a `Parent: \u003Cissue title> (§\u003Canchor>)` field — `사유` is the short citation, `Parent` is the structured follow-up field; both render the parent as \"issue title + §anchor\") → NOT queue-appended → re-enters as `(깊이: 1)` on the next walkthrough invocation.\n- **`(깊이: 3)` and beyond is structurally impossible** — a `(깊이: 2)` item never enters the current queue, so nothing can surface during its investigation.\n- **Marker conversion on re-entry**: when a depth-2 item enters as depth-1 on the next walkthrough invocation, the doc's `(깊이: 2)` marker becomes `(깊이: 1)` and `상태: 보류` becomes `상태: 대기` together (keeping doc state and queue state in agreement). The `Parent` field is preserved as historical metadata so a later user can trace the discovery context. **Original Step 4 output items (no depth marker) are treated as implicit depth-1** — no marker need be attached.\n\nDo **not** create a separate sub-section (`## 워크스루 후속 항목`). All items stay integrated in the existing `## 미해결 이슈 \u002F 트레이드오프` section as a single source of truth; downstream tools parse just that one section.\n\n**Announce timing**: right after a parent depth-1 issue enters a terminal state (resolved\u002Fdeferred\u002Fdropped), announce in Korean — in **one combined message** — all depth-2 items identified while processing that issue (both lead auto-investigation and team discussion sources). Example form: `? parent \u003Cissue title> 처리 중 depth-2 N건 식별 — 다음 walkthrough에서 자동 표면화: [\u003Ctitle>, \u003Ctitle>, ...]`. depth-2 items are default-deferred, so no user decision input is required (announce only). If there are 0 depth-2 items, skip the announce.\n\n#### Per-issue Processing Flow (hybrid)\n\n> **One issue per question (invariant)**: every question in this step carries **exactly one issue** — one question of a `mcp__cc-cmds__question_form` form, or one `AskUserQuestion` call on the fallback path. On the form path a round's form carries every issue now in `awaiting-decision`, one question each, with that issue's full per-category menu; the form has no option cap, so **Cap-handling** below does not fire there. On the AUQ fallback path each call still carries exactly one issue, the up-to-4-questions capacity is never used to bundle issues, and the 4-option cap and **Cap-handling** apply unchanged. The per-issue mechanisms — auto-investigation, the `← 추천` recommendation, the UC `더 논의` follow-up loop, the dropped-confirm prompt and mid-flight reclassification — are per question: investigation finishes before the form opens; a non-terminal answer (`더 논의`, `그래도 유지`, an approved `팀 토론 진행`'s composition question, 미답) carries its issue to the next round's form; team spawns stay one issue at a time.\n>\n> > **Old heading** (for re-deriving citations): \"One issue per surface (invariant)\" - one form carries many questions, so the unit of the invariant is the question\n\nFor each issue:\n\n1. **Auto-investigation (lead-only, read-only + reproducible)**:\n    - UD: Read doc context only.\n    - UC: `grep` for the assumed convention in the project's primary source tree (e.g. `src\u002F**`, `plugins\u002F**`, `app\u002F**` — the lead adapts to the project's convention); optional `make test`.\n    - UA: Read each option's affected files + cost estimate (line-count delta, etc.).\n    - UR: Read the tradeoff framing only. **Reproduction pointer (Surfaced-at: Step 4 synthesis, body references `§재현·근본원인`)**: when surfacing it, the Why-it-matters \u002F framing text must **quote** the canonical section's `근거 등급: 가설(추측)` value (read-only reference, not a stored copy) so the user sees the hypothesis grade at decision time without manually following the anchor.\n    - Hard limits: stop as inconclusive if `grep` returns >50 hits; stop if `make test` exceeds 2 min. If the result is inconclusive, surface it as *\"조사 inconclusive — 사용자 판단 필요\"*.\n2. `등급 2` **Surface as that issue's question in the round's form (one `AskUserQuestion` call on the fallback path), Korean** with: a one-line Title; a Category tag (UD\u002FUC\u002FUA\u002FUR — fits the 12-char `header` chip limit); Why-it-matters (1-2 lines); the auto-investigation summary (the findings, or *\"조사 불필요\"*); Options (the per-category menu below — also apply the recommendation rendering check from the **Lead recommendation policy** paragraph: when auto-investigation is confident, move the recommended option to position 1 with `← 추천` and place the rationale in its `description`); and a Doc reference (`§ anchor`).\n3. **Apply the user's decision**:\n    - Direct resolution → mark `상태: 해결` + reflect the decision in the doc body. A UC \"다르게 수정\" response also maps here (the lead Edits the doc body per the user's correction + `상태: 해결`).\n    - Defer → `상태: 보류` + record a reason (format `사유: 사용자 결정 보류 (\u003Cdate YYYY-MM-DD>)`).\n    - Drop (the dropped branch, UC only) → after user confirmation the entry is REMOVED from the doc. **Trigger condition**: branches only in the UC category when the lead's auto-investigation finds the issue is a false positive (already resolved in the doc body \u002F codebase convention matches the assumption). **User-confirmation mechanism**: surface the false-positive finding as that issue's question, which carries the dropped-confirm menu instead of the UC menu (a **separate `AskUserQuestion`** on the fallback path) — body *\"이 항목은 §X에서 이미 다뤄지고 있어 미해결 이슈에서 제거하려 합니다.\"*, options *\"확인 \u002F 그래도 유지 \u002F 보류\"* (each option carries a 1-line `description` per the **Description requirements** subsection below — `확인` uses the hybrid `\u003Cstatic semantics> — 근거: \u003Cfalse-positive evidence> (\u003Cpath:line>)` form, `그래도 유지` and `보류` use static descriptions). On user confirm, Edit the doc to delete the entry — removed immediately, no `상태: 제외` annotation. On \"그래도 유지\", enter the normal UC menu (맞음 \u002F 다르게 수정 \u002F 더 논의 \u002F 팀 토론 진행). UD\u002FUA\u002FUR have no dropped branch — they require user value judgment, so a false-positive verdict is impossible.\n    - Redesign (a UR option) → `상태: 보류` + `사유: 재설계 필요 — Step 6 refinement에서 처리`. The walkthrough does not redesign directly; it defers.\n    - Discuss further (a UC option) → the issue returns in the next round's form with the lead's reply in `detail` and the person's in the note (an `AskUserQuestion` follow-up on the fallback path); the lead continues the dialogue until the user picks one terminal option among \"맞음\" \u002F \"다르게 수정\" \u002F \"보류\" \u002F \"팀 토론 진행\". It has no terminal state of its own.\n    - Run a team discussion → the spawn flow below.\n    - No answer (`미답`, form path) → the issue rides in the next round's form unchanged. When the same issue comes back `미답` twice in a row → `상태: 보류` + `사유: 사용자 미답 (\u003Cdate YYYY-MM-DD>)`.\n\n#### Per-category Option Menu + Team Spawn\n\nEvery option in a per-category menu carries a 1-line `description` field. For options recommended via `← 추천`, the description follows the format `\u003Csemantics> — 추천 근거: \u003Cevidence>` with citation tokens per the **Lead recommendation policy** paragraph; otherwise it is the per-label static text tabulated in the **Description requirements** subsection.\n\nEach category's user-facing options (Korean). **Default ordering**: direct-resolution options first, then `보류`, then `팀 토론 진행` (escalation gradient). **Recommendation override**: when the auto-investigation is confident, the recommended option moves to position 1 with `← 추천` appended; the remaining options preserve their relative ordering. **Conditional inclusion exception**: for UD\u002FUA menus with `K_pick ≥ 3`, structural-slot visibility (`보류`·`팀 토론 진행`) follows the branch (a)\u002F(b) layout in the **Lead recommendation policy** paragraph — both may be pinned (branch a) or hidden from the visible options array (branch b), with hidden items reachable via the AskUserQuestion `Other` channel. Default ordering applies only when conditional inclusion does **not** fire (UC\u002FUR menus, or UD\u002FUA with `K_pick ≤ 2`). Note the structural slots appear *where present, in the order `보류` → `팀 토론 진행`* — not every in-scope menu has both: the UC initial menu (`맞음 \u002F 다르게 수정 \u002F 더 논의 \u002F 팀 토론 진행`) has no `보류` slot and places `더 논의` before `팀 토론 진행`; the UR menu (`수용 \u002F 재설계 \u002F 보류 \u002F 팀 토론 진행`) and UC sub-loop (`맞음 \u002F 다르게 수정 \u002F 보류 \u002F 팀 토론 진행`) have both. The UC dropped-confirm confirmation dialog (`확인 \u002F 그래도 유지 \u002F 보류`, no `팀 토론 진행`) is **not** an escalation-gradient menu — it follows its own carve-out ordering and is excluded from this default-ordering rule. See the **Lead recommendation policy** paragraph below for the confidence criterion + cap-handling rules.\n\n| Category | Options |\n| --- | --- |\n| UD | (1-4 issue-specific concrete picks) + \"보류\" + \"팀 토론 진행\". A single concrete pick (binary confirm-only scenario) is also allowed — present the lone option as \"이대로 적용 \u002F 보류 \u002F 팀 토론 진행\". Picking a concrete pick maps to the \"direct resolution\" branch above. |\n| UA | (option A \u002F option B \u002F ...) + \"보류\" + \"팀 토론 진행\". The user's option choice maps to \"direct resolution\"; the lead records an alternatives-considered note when Editing the doc. |\n| UC | \"맞음 \u002F 다르게 수정 \u002F 더 논의 \u002F 팀 토론 진행\" (initial). **Mapping**: \"맞음\" → the \"direct resolution\" branch (the user confirms the lead's assumption interpretation; mark `상태: 해결` — the bare value, never with a note on the same line (`${CLAUDE_SKILL_DIR}\u002F..\u002F_common\u002Funresolved-closure.md`, `## 작성자 꼴`) — but do NOT add a `사유` field — `사유` is reserved for the `보류` state in this spec; instead add the inline note *\"사용자 confirm: 가정 정확.\"* at the end of the doc entry, with the body unchanged). \"다르게 수정\" → the same \"direct resolution\" branch. **UC's initial menu deliberately omits \"보류\"** — to prevent the user from skipping the issue without reviewing the auto-investigation summary; \"보류\" is reachable only inside the sub-loop after the user explicitly enters dialogue via \"더 논의\". On \"더 논의\" the sub-loop is entered, and its terminal option set is \"맞음 \u002F 다르게 수정 \u002F 보류 \u002F 팀 토론 진행\" — \"더 논의\" is replaced by \"보류\" to prevent infinite dialogue. |\n| UR | \"수용 \u002F 재설계 \u002F 보류 \u002F 팀 토론 진행\". Picking \"수용\" maps to the \"direct resolution\" branch (`상태: 해결` + a tradeoff-acceptance note in the doc body — `사용자 acknowledged tradeoff: \u003Coriginal tradeoff framing>`). |\n\nSee the **Description requirements** subsection below for per-option description format (recommended-option rationale form + per-label static descriptions).\n\n**Lead recommendation policy**: when the auto-investigation meets the per-category confident criterion — **UC**: grep returns 3–50 hits with ≥80% alignment to one verdict and no canonical-surface counter-example; **UA** (ANY of): cost delta ≥2× on line-count with affected-file count not inverted, OR one option has a hard blocker the other lacks, OR one option touches a doc-marked frozen\u002Fno-touch path the other doesn't; **UD** (ALL of): a parallel decision already committed elsewhere in this saved doc anchors the pick (cited as `§\u003Canchor>`) AND one of the offered options aligns with that committed pattern AND the doc records no \"this case is different\" rationale — never on lead taste; **UR**: blast radius scoped to ≤1 module with no concrete lower-cost alternative cited (→ `수용`), or ((blast radius ≥2 modules) OR (critical path: auth\u002Fpayment\u002Fdata integrity\u002Fpersistence schema\u002Fpublic API contract)) AND (a concrete cited alternative without prior rejection rationale) (→ `재설계`), or the tradeoff explicitly references cross-team coupling \u002F out-of-scope expertise AND ≥2 distinct expert roles would weigh in differently (→ `팀 토론 진행`), or the issue is downstream of a depth-1 parent currently in `상태: 대기` or `상태: 결정대기` (→ `보류`); **NONE-good case**: when the lead is confident no listed option fits because of a doc-cited gap (`§\u003Canchor>` constraint that all options miss, or a blocker absent in `\u003Cevidence path>` that all options require), force `팀 토론 진행 ← 추천` with the gap citation in the rationale — without a specific gap citation this case degrades to inconclusive.\n\n**Recommendation contract**: the lead applies the documented `AskUserQuestion` recommendation convention — append `← 추천` to the recommended option's label, force it to position 1, and place the rationale in that option's `description` field. The description follows the format `\u003Csemantics> — 추천 근거: \u003Cevidence>` where `\u003Csemantics>` is a brief (≤10 Korean syllable) action\u002Fresult summary (긴 UD\u002FUA pick label로 인해 ≤10 음절을 약간 초과해야 의미 보존이 가능한 경우 soft over-flow 허용 — semantic clarity가 우선) and `\u003Cevidence>` carries the rationale. The description MUST be ≤2 sentences, ≤140 chars, and `\u003Cevidence>` MUST carry at least one citation token (code path `:line`, `§\u003Canchor>`, a quantitative measurement such as `affected files: 4` \u002F `~4×` \u002F `12\u002F12 hits`, or a blocker fact `requires X, absent in \u003Cevidence path>`). Opinion phrases (`cleaner`, `simpler`, `idiomatic`, `common practice`, `I think`, `feels like`) are forbidden unless paired with a citation token in the same sentence; this citation\u002Fdenylist rule applies only to descriptions of options carrying `← 추천` — static descriptions on non-recommended options are display-only and exempt. All four options are eligible candidates — including `팀 토론 진행` and `보류` — provided their confidence criterion is met. When the criterion fails (grep results split outside 80\u002F20, cost delta within 1.5×, no parallel anchor for UD, mixed UR impact, NONE-good without a gap citation, any auto-investigation hard limit tripped), the lead refuses to recommend: Why-it-matters surfaces *\"조사 inconclusive — 사용자 판단 필요\"* and the menu renders in default order with no `← 추천` suffix. Why-it-matters never duplicates the rationale (that lives only in the recommended option's `description`); when confident it is framed as *\"결정만 내리면 적용 가능\"*.\n\n**UC sub-loop interaction**: the prior recommendation is suppressed by default on first sub-loop entry — re-computation is permitted only if (a) a new auto-investigation pass with materially different inputs still meets the confident criterion, or (b) the dialogue surfaces a previously-unrecorded fact that flips the alignment ratio; in both cases the description must cite the new evidence. \"Previously-unrecorded\" means the fact is absent from the original `AskUserQuestion` surface's auto-investigation summary text — the lead's in-session memory of earlier turns does NOT qualify.\n\n**Dropped-confirm prompt carve-out**: the UC false-positive prompt (body: *\"이 항목은 §X에서 이미 다뤄지고 있어…\"*) is structurally a confirmation dialog (binary accept \u002F override \u002F punt), not a pick-one-among-equals menu — `← 추천` is **NOT** applied to its `확인` option (the prompt body already asserts the lead's verdict; adding the suffix would double-signal and friction `그래도 유지`). Its `확인` option uses a hybrid description form `\u003Cstatic semantics> — 근거: \u003Cfalse-positive evidence> (\u003Cpath:line>)` (with `근거:` prefix, NOT `추천 근거:` — the segment is a fact statement, not a recommendation rationale); the citation\u002Fdenylist rules of this paragraph do NOT apply to that hybrid form. The hybrid form still respects the recommended-option ≤140 chars \u002F ≤2 sentences hard limits.\n\n**Cap-handling — conditional inclusion (category-agnostic)**: when concrete picks plus structural slots `보류`\u002F`팀 토론 진행` would exceed AskUserQuestion's 4-option cap (i.e., K_pick ≥ 3 in UD\u002FUA), the menu undergoes **conditional inclusion** rather than blanket collapse. **Branch (a) — when the recommended option is `보류` or `팀 토론 진행`**: both structural slots are pinned (recommended at position 1; the non-recommended structural is placed at the position it would occupy in the canonical order `[picks..., 보류, 팀 토론 진행]` after removing the recommended item and shifting remaining items up — typically position 4 since `팀 토론 진행` is canonical-last, and `보류` lands at position 4 when `팀 토론 진행` is recommended), and the `K_pick − 2` lowest-priority concrete picks are dropped per a worst-cascade rule (hard blocker → deprecated-path overlap → frozen-path overlap → largest line-count delta ≥1.5× → doc-order LAST tiebreaker; continue-on-tie within tied subset). The 2 surviving picks fill the visible pick slots in canonical relative order. **Branch (b) — when the recommended option is a concrete pick OR the result is inconclusive**: both structural slots are **hidden** from the options array but remain reachable via the AskUserQuestion `Other` channel — the user types `보류` or `팀 토론 진행` (NFC-normalized + whitespace-normalized including U+3000 → U+0020, exact-match against canonical Korean tokens) and the lead processes the input identically to a menu selection. Hide ≠ collapse: the decision path remains open via `Other`, so the *\"`보류`\u002F`팀 토론 진행` never collapse\"* commitment is preserved; only the visible slot is reassigned under cap pressure when no recommendation endorses them. K_pick ≤ 2 (option count ≤ 4) skips conditional inclusion entirely — both structural slots are always shown. **Disclosure**: when conditional inclusion fires, the Why-it-matters companion text discloses the dropped picks (branch a, format `옵션 캡(4)으로 \u003CK_pick>개 픽 중 \u003CX>건 생략 — 생략 픽: \u003Clabel1>, \u003Clabel2>, ...`) or the Other-channel reachability of `보류`\u002F`팀 토론 진행` (branch b, format `보류·팀 토론 진행은 Other 채널에 '보류' 또는 '팀 토론 진행' 입력 시 동일 처리.`) so the user audits the option-set difference. Branch (b) carries the Other-channel disclosure whenever conditional inclusion fires (`K_pick ≥ 3`), and additionally appends the dropped-picks disclosure when `K_pick > 4`. **Multi-session consistency**: the cascade is stateless — re-computed from scratch on each AskUserQuestion call, no drop-state persistence in the doc.\n\n**Mid-flight reclassification**: if auto-investigation reveals a category change (UC→UD\u002FUR, UA→UD), the lead Edits the doc's `Category` field, surfaces with the new menu, and re-applies the new category's confident criterion. **Investigation-time only**: once `AskUserQuestion` has entered `awaiting-decision`, the prompt is immutable; if reclassification surfaces late, the lead applies one of two fallbacks. **(i) Apply-then-defer** (when the user response is `보류` only): apply the user's 보류 as the resolution, Editing `Category` field first, then `상태: 보류 + 사유` where `사유` is always lead-generated in the canonical defer-branch form `사유: 사용자 결정 보류 (\u003Cdate YYYY-MM-DD>) (재분류됨: \u003Cold-cat> → \u003Cnew-cat>)` (no user-reason-collection branch — there is no free-text input channel on the `AskUserQuestion` fallback path, and on the form path the note is the user-reason channel; the `\u003Cdate>` stamp + `사용자 결정 보류` prefix are mandatory per the cross-issue defer convention). **(ii) Immediate-defer** (default for any other response, including `팀 토론 진행`): `상태: 보류` + `사유: 재분류 필요 — 다음 walkthrough에서 처리`; the user's response is discarded because original-category interpretation can be invalid under the new category (team-spawn flow especially is category-coupled and would synthesize under wrong category if (i) were used). The lead's text response discloses the reclassification to avoid silent doc mutation, with distinct messages per case — case (i): *\"방금 보류 결정을 적용했습니다. 참고로 이 이슈의 Category가 \u003Cold> → \u003Cnew>로 재분류되었습니다.\"*; case (ii) (the consequential one — a discarded user selection must be explained): *\"재분류(\u003Cold> → \u003Cnew>)이 발견되어 이 이슈는 다음 walkthrough에서 새 카테고리로 다시 surface됩니다. 방금 선택하신 응답은 새 카테고리의 메뉴 의미가 다를 수 있어 적용하지 않았습니다.\"*\n\n**Team-spawn coupling**: recommending `팀 토론 진행` does NOT preload the team composition into this `AskUserQuestion` prompt — the role\u002Fscope\u002Fmodel proposal remains the separate downstream step described in the Team Spawn Flow below, preserving the two-layer approval (entry into the team flow vs. composition approval). **Display-layer fence**: the entire recommendation mechanism is a display-layer concern on `awaiting-decision`: no new states, no doc markers, no transition edges, no checkpoint format changes.\n\n#### Description requirements\n\nEvery option in a per-category `AskUserQuestion` menu carries a 1-line `description`. For the recommended option (when present), the description follows the format `\u003Csemantics> — 추천 근거: \u003Cevidence with ≥1 citation token>` and must satisfy the citation-token allowlist + denylist rule defined in the **Lead recommendation policy** paragraph above. For all other options (non-recommended in a recommended menu, and all options in an inconclusive menu), the description is a static 1-line semantics text fixed per label as tabulated below. **This table is the single source of truth for static option semantics** — when the per-category option menu's decision branches (the menu table preceding this subsection) are amended, the static description for the affected label MUST be updated atomically in the same edit.\n\n| Label | Static description |\n| --- | --- |\n| 수용 | 현재 트레이드오프를 인정하고 해결됨으로 표시합니다. |\n| 재설계 | 보류 처리 후 Step 6 refinement에서 재설계합니다. |\n| 보류 | 지금 결정을 미루고 나중에 처리합니다. |\n| 팀 토론 진행 | 전문 팀을 구성해 이 이슈를 심층 논의합니다. |\n| 맞음 | 가정이 정확합니다. 해결됨으로 표시합니다. |\n| 다르게 수정 | 가정 내용을 직접 수정합니다. |\n| 더 논의 | 리드와 추가 대화를 진행한 뒤 결정합니다. |\n| 확인 | 이 항목을 문서에서 즉시 삭제합니다. |\n| 그래도 유지 | 이 항목을 유지하고 정상 UC 메뉴로 진행합니다. |\n| UD concrete picks | `\u003C해당 값>으로 확정합니다.` (dynamic — `\u003C해당 값>`은 이슈가 surface한 개별 pick 라벨) |\n| UA option picks | `\u003Coption name>으로 구현합니다.` (dynamic — `\u003Coption name>`은 이슈가 surface한 개별 alternative 라벨) |\n\n**Dynamic pick recommendation form** (UD\u002FUA concrete pick이 추천 옵션일 때): 위 dynamic static template (`...합니다.`)을 그대로 description에 쓰지 않고, `\u003Csemantics>` slot에 verb-stem 형태 (trailing `합니다.` 제거) 로 변환한 뒤 recommended-option format 적용한다. UD 예: `\u003C해당 값>으로 확정 — 추천 근거: \u003Cevidence>`. UA 예: `\u003Coption name>으로 구현 — 추천 근거: \u003Cevidence>`. trailing 마침표 제거는 em-dash separator의 명확성을 보존하기 위함이며, `\u003Csemantics>` slot의 ≤10 음절 budget 적용 (긴 `\u003C해당 값>` \u002F `\u003Coption name>` 라벨의 경우 ≤10 약간 초과 가능; 의미 명확성 우선).\n\n**Dropped-confirm prompt exception** (third description type): the UC false-positive prompt's `확인` option uses a hybrid format — `\u003Cstatic semantics> — 근거: \u003Cfalse-positive evidence> (\u003Cpath:line>)` — with the `근거:` prefix (not `추천 근거:`) signaling fact statement rather than recommendation. The citation\u002Fdenylist rules of the **Lead recommendation policy** paragraph do NOT apply (the `확인` label has no `← 추천` suffix per the dropped-confirm carve-out); the evidence segment is descriptive rather than rationale. The hybrid form inherits the recommended-option ≤140 chars \u002F ≤2 sentences hard limits; if the evidence path exceeds budget, prefer a shorter `§\u003Canchor>` citation or relative path over the absolute path.\n\n**Team spawn flow** (when the user picks \"팀 토론 진행\"):\n\n1. The lead proposes a role\u002Fscope\u002Fmodel composition for that issue in Korean → user approval. If the user rejects or asks to revise the composition, the lead either (i) re-proposes a revised composition (repeatable), or (ii) if the user withdraws \"팀 토론 진행\", returns to that category's normal terminal option menu (direct resolution \u002F defer \u002F (UC only) drop branch \u002F (UR only) redesign \u002F (UC only) discuss-further, per category). **UC exposes \"보류\" directly in this fallback**: the user already engaged the issue actively via the team-spawn proposal, so UC's initial-menu gate (forcing auto-investigation review) no longer applies — the fallback's \"보류\" is deliberately directly reachable.\n2. Spawn the approved members as fresh nameless background tasks (`Agent`, `subagent_type: \"claude\"`, `run_in_background: true`, no name) and record each `agentId` in the ledger. **Stamp `epoch`** (`max(disk epoch, 0)+1`, re-derived from the on-disk ledger — never an in-context counter; this fresh walkthrough team → `epoch 2` in the normal sequence) **and the round-1 `witnessNonce`** on every one of its rows in the same at-spawn recording window as `agentId`\u002F`scratchDir`, per the protocol Spawn section. Create this fresh team's **own** witness dir with a fresh run of the protocol's `## Spawn` command — `\u003Cplugin root>\u002Forchestrator\u002Fcc-team-witness-init.sh {issue-slug}` (no `bash` in front — see the protocol's note) — and record the **printed path, literally** (not `$WITNESS_DIR`) as each member's `scratchDir`; the issue-discussion rounds are witnessed per `_common\u002Fagent-team-protocol.md`.\n3. English discussion → synthesis → the lead Edits the doc to reflect the decision. **Team result → state mapping**: (a) team agrees on a single resolution → `상태: 해결` + decision reflected in the doc body; (b) team agrees on \"recommend deferral\" → `상태: 보류` + reason `팀 토론 결과 추가 검토 필요`; (c) team finds depth-2 items → the doc-first handling above (recorded as separate entries + accumulated in the parent's announce); (d) team agrees a UC issue is a false positive → route to the dropped-confirm prompt above (entry REMOVED after user confirmation). In all cases the doc Edit completes before the team-cleanup in step 4.\n4. **Before entering the next issue or ending the walkthrough**: Read `${CLAUDE_SKILL_DIR}\u002F..\u002F_common\u002Fteam-cleanup.md` and apply it (returned tasks already self-terminated — no-op; `TaskStop` any `state=running` agentId; ledger hygiene).\n5. Proceed to the next queue item.\n\n#### Abort Semantics\n\n- Abort is detected by lead judgment (no regex matching). Examples:\n    - Full abort: \"그만\", \"중단\", \"이만 됐어\", \"리파인먼트로 넘어가자\", \"skip rest\".\n    - Single-issue skip: \"이건 패스\", \"다음 이슈\", \"이건 나중에\". On a skip, mark only the current issue `상태: 보류` + `사유: 사용자 per-issue skip, \u003Cskip date YYYY-MM-DD>` (distinguishable from the full-abort reason) and proceed to the next queue item. **Active team handling**: if a walkthrough-spawned team is active at skip time, apply `_common\u002Fteam-cleanup.md` (`TaskStop` any `state=running` agentId + ledger hygiene) before entering the next queue item — the same cleanup obligation as the full-abort path (cleanup-anchor doctrine).\n- On full abort, in ONE batched Edit mark all remaining `대기` \u002F `조사중` \u002F `결정대기` items `상태: 보류` + `사유: 사용자 조기 종료, \u003Cabort date YYYY-MM-DD, runtime-generated>`, then enter Step 6. (CFI-2)\n- If a walkthrough-spawned team is active (spawned, cleanup not yet done) at abort time, clean it up via `_common\u002Fteam-cleanup.md` (`TaskStop` any `state=running` agentId + ledger hygiene) *before* the batch `보류` Edit. The issue in progress is included in the batch and marked `상태: 보류`.\n- If the user is viewing a UC dropped-confirmation prompt at abort time, the drop is auto-cancelled and that issue is kept in the doc, included in the batch as `상태: 보류` + `사유: 사용자 조기 종료 (drop 미확정, 재호출 시 재표면)`. No item is ever silently deleted without the user's explicit drop confirmation.\n\n### Step 6: Plan Refinement with User\n\n**State check on entry**: Re-read the ledger from disk (re-read — do not trust in-context copies; a missing\u002Funparseable block is fail-closed via `AskUserQuestion`). If the ledger has any residual `state=running` row (a Step 3 original-team member, any prior walkthrough-spawned member from Step 5, or any prior Step 6 refinement member still running), notify the user in Korean (*\"이전 단계의 팀이 아직 살아있어 정리 후 리파인먼트를 시작하겠습니다.\"*), then execute cleanup now (Read `${CLAUDE_SKILL_DIR}\u002F..\u002F_common\u002Fteam-cleanup.md` and apply it — `TaskStop` each `state=running` agentId, then ledger hygiene) before any Step 6 activity. A residual `state=running` row is the leftover-detection signal (it replaces the removed `teams\u002F` filesystem scan). The `\u003Cslug>` (the ledger key and `docs\u002F\u003Cslug>.md` filename) is recovered from the saved design document filename in `docs\u002F` (the filename encodes the topic slug per Step 4's save convention — local file-system state, not memory). **Preferred slug recovery**: the lead remembers the exact filename it saved in Step 4 (not mere \"most recent .md file\" — that may be unrelated to the design workflow if the project is actively edited elsewhere). If the lead cannot recall the exact filename, fall back to matching against `docs\u002F` modification times within a narrow window after Step 4, and if still ambiguous (multiple candidates), prompt the user via `AskUserQuestion` to confirm the target document. Never assume the most recently modified `docs\u002F*.md` is the design doc without validation. Because the ledger lives inside this workflow's own `docs\u002F\u003Cslug>.md`, every ledger row belongs to the current workflow's topic — there is no cross-matching of unrelated prior-session work. Any `state=running` row is treated as active and requires cleanup. Under normal flow, all prior members have already self-terminated and this step proceeds with the lead only. **Worktree gate (in-session verification cleanup)**: also run the two-command boundary gate (`_common\u002Fverification.md` §6) on entry, in full — assertion 1 and all three of 2a\u002F2b\u002F2c, not the `cc-design-exp-` count alone; force-remove (`git worktree remove --force`) + `git worktree prune` any mechanism-owned worktree that leaked from a prior step before proceeding.\n\n- On entering Step 6, emit ONE short Korean notice that the design document is ready for refinement and invite the user's input, then YIELD the turn and wait for the user's reply. At Step 6 ENTRY do NOT call `AskUserQuestion` to open the discussion or manufacture a refinement question (e.g. '무엇을 다듬을까요?'). Once the user replies, discuss the design document with them in Korean and refine the plan together. (CFI-2)\n- Lead-only by default: doc edits, user Q&A, and codebase re-exploration require no team.\n- If the user raises questions requiring deeper investigation that exceed lead-only capacity, verify the ledger shows no residual `state=running` row (if one remains, notify in Korean: *\"새 리파인먼트 팀을 만들기 전에 기존 팀을 먼저 정리하겠습니다.\"* and execute cleanup), then propose composing a **new** team for that specific investigation — mirror Step 2 (role\u002Fscope\u002Fmodel proposal → user approval → spawn the members as fresh nameless background tasks recorded in the ledger). **A Step 6 investigation team is always a NEW team — never a reused or restarted prior design team.** The closed list of prior-team re-convenings that *are* permitted anywhere in this skill is in `## Constraints` → **Permitted team resumes**; no Step 6 investigation is on it.\n- Only create a new team if the user approves. Otherwise, continue refining in the current session.\n- If a new team is created, spawn its members as fresh nameless background tasks (`Agent`, `subagent_type: \"claude\"`, `run_in_background: true`, no name) recorded in the ledger (**stamp `epoch` = `max(disk epoch, 0)+1`, re-derived from the on-disk ledger — never an in-context counter; this fresh refinement team → `epoch 3` in the normal sequence — and the round-1 `witnessNonce` on every row in the at-spawn recording window, per the protocol Spawn section**) — each fresh refinement team gets its **own** nested witness dir from a fresh run of the protocol's `## Spawn` command, recorded as the rows' `scratchDir`, and its rounds are witnessed per `_common\u002Fagent-team-protocol.md`. Conduct internal discussion in English. After discussion converges and results are synthesized, update the saved document in `docs\u002F`. Then notify the user in Korean: *\"리파인먼트 팀을 정리한 뒤 후속 논의를 이어가겠습니다.\"* **Before creating the next refinement team or returning to user discussion, Read `${CLAUDE_SKILL_DIR}\u002F..\u002F_common\u002Fteam-cleanup.md`** and apply it (returned members self-terminated — no-op; `TaskStop` any `state=running` agentId; ledger hygiene). Present the updated results to the user in Korean.\n- Repeat until the user is satisfied with the plan. That satisfaction signal is the ONLY exit from Step 6, and it enters Step 7 automatically in the same turn (CFI-3a).\n\n---\n\n### Step 7: Class C Coherence Pass & Freeze (document-wide, single-pass, non-recursive)\n\n**What this pass is.** ONE document-wide coherence-and-completeness check of the FINAL text, run by the **Step 3 discussion team**. It is not the Step 4 fidelity pass repeated — the two answer different questions. Fidelity asks *\"did synthesis distort or drop what I said?\"* and is meaningful only immediately after synthesis. This pass asks *\"is the whole document coherent and complete?\"* and is meaningful only on the final text, after Step 5's walkthrough decisions and Step 6's refinements have landed. Both passes exist; neither replaces the other. Because it runs on the final text, \"single-pass and non-recursive\" here means **once over what actually ships**.\n\n**Why the authoring team, and why it cannot be deferred.** Context-dependent defects — a Step 5 or Step 6 decision that contradicts a requirement confirmed in the Step 1 interview, an architecture point discussed but never written down — leave no evidence in the artifact. A fresh reader's sensitivity to them is structurally **zero**, not merely low, because the evidence it would need is not in the document. The authoring team is the only non-zero channel, and its context dies when `design` ends. So this pass cannot be handed to any later command; a downstream audit covers the complementary class, not this one.\n\n**Single-pass and NON-RECURSIVE (hard).** Exactly one pass over the final text. The lead does NOT re-submit the pass's own corrections for another round — reviewing its own output would reproduce, inside `design`, the generator this pipeline removed. (CFI-3b)\n\n**Roster scoping (mandatory, before any dispatch).** The Step 3 team is `epoch 1`, but Step 5 and Step 6 may have spawned fresh teams at `epoch 2`, `3`, … — and Step 6 loops, so the maximum is not statically knowable. Apply the protocol's **re-convened prior team — `epoch` re-stamp** (`_common\u002Fagent-team-protocol.md`, Spawn): re-derive `epoch := max(disk epoch, 0) + 1` from the on-disk ledger and write it onto **every Step-3 row**, one single-row Edit per row, all in one contiguous window, before the first `coherence` dispatch and alongside each row's `coherence` `witnessNonce`. **Never hard-code the value.** After the re-stamp the roster's `max(epoch)` over non-aborted rows resolves to exactly the Step 3 team; without it the roster resolves to the last fresh team and self-heal would consume a foreign-role member's output as this pass's product. The re-stamp is written by the leg, in the leg's session, because the leg is the session that dispatches into those rows and owns any same-key resume of the members it dispatches.\n\n**Procedure**\n\n1. **Re-read the ledger from disk** (never in-context copies; missing or unparseable is fail-closed via `AskUserQuestion`). If any `state=running` row survives from Step 5 or Step 6, Read `${CLAUDE_SKILL_DIR}\u002F..\u002F_common\u002Fteam-cleanup.md` and apply it first.\n2. **Precondition — does the leg's team still exist on disk?** `stat` `${CLAUDE_CONFIG_DIR}\u002Fprojects\u002F*\u002F\u003Csession_id>\u002Fsubagents\u002F`, globbed by the leg's `session_id` from `leg.json` (never re-derive the project key). Present → the primary path (3). Absent → that is the transcript loss, and it is one of exactly **two** triggers of the fallback (3'). The other is the pull-check ladder's step-8 death while `phase` is `resume`, where rung 1r is forbidden precisely because a re-dispatched leg would save over this document. There is no third trigger.\n3. **Primary path — the resumed leg dispatches its own team's roles afresh.** The seat writes `phase: resume` together with `state: pending` into `leg.json`, in one atomic write — the discuss-phase consumption left `state: done`, and without `pending` the pull-check that observes `coherence.md` never runs (CFI-1b). It then writes the coherence message — the final document's **path** plus every `[Step 7 정합 점검 대상]` note the Step 5 router queued (there may be none); the document is never embedded — to a resume file `$STATE\u002Fresume.\u003CISO8601>.txt` and sends it through the resume line of Step 2's dispatch block (item 6), which passes that file as `$(cat …)` command substitution and never inlines the message on the command line (the notes are backtick-heavy Markdown), and yields as in CFI-1a. Inside the leg: re-stamp the Step-3 rows' `epoch` per the paragraph above (a precondition of dispatch, not an optimization), write each row's `coherence` `witnessNonce` **before** the dispatch and flip the row (`agentId`, `outputFile`, `round\u002Fphase`, `state`, `stallMark`) **after** it, dispatching each Step 3 role afresh at the new `epoch` — a new key, so a new dispatch under `## Constraints` → **Permitted team resumes** — with phase token `coherence` (colon-free, per the protocol), the task-assignment header from `_common\u002Fagent-team-protocol.md` embedded verbatim, the member's own past witnesses by path, and the whole final document read by path. This is the same class of input as the fallback (3') — what was written to disk, no retained context — but not the same input: the fallback reads the whole durable corpus and the brief. **Serialization clause**: from the moment the coherence turn is dispatched until its artifact (`$STATE\u002Fcoherence.md`, header `\u003C!-- cc-design-coherence v1; writer=design-discuss-unattended; reader=design; slug=\u003Cslug> -->`) is observed, the seat does not edit the document; the leg writes the ledger block only and never writes prose. Two processes with no lock between them are otherwise concurrent writers of the very document being frozen.\n    - 3'. **Fallback (only on one of step 2's two triggers).** Respawn the Step 3 roles **fresh at a new `epoch`** from the durable witness corpus (`$STATE\u002Fwitness\u002F`: every round and phase witness, each member's rendered dispatch prompt, and `INDEX.md`), the brief, and the final document by path. `INDEX.md`'s `lead`\u002F`sweep` row and `SWEEP.md` are not member roles: neither is respawned nor put on the roster. Class C sensitivity here is partial, not zero: what was written anywhere is recovered — a Step 5\u002F6 decision contradicting a Step 1 requirement is *more* detectable than today, because the brief is the interview's durable record — and what was thought but never witnessed is not.\n4. Emit ONE one-way Korean notice at entry (not a question): *\"팀이 최종 문서의 전체 정합성을 점검하고 있습니다.\"*\n5. **Collect by witness** — each member publishes `${scratchDir}\u002F{role-slug}.coherence.md` (sentinel\u002Fnonce per the protocol; the return text is only an early-wake hint and the collector reconciles the witness, never the return). Case-1 (thin\u002Fempty witness) and Case-2 (never-returns) handling is identical to the Step 4 fidelity pass's, with `coherence` substituted for `fidelity`. The finding blocks keep a free shape, but each witness ends, above its sentinel, with one line of its own `findings: \u003Cn>` (`findings: 0` when it found nothing); a coherence witness without that line is a Case 3 non-conforming witness (`_common\u002Fagent-team-protocol.md`) — re-instruct the member and take its `coherence-rev\u003Ck>` revision. The count is the line's value; it is not checked against the blocks. A missing witness is NEVER read as \"no objection\". On the primary path the leg collects and returns its findings in `coherence.md`; the seat's pull-check observes that file.\n6. **Triage and apply — ONE time, by the seat, after the leg's turn has ended.** The lead applies corrections directly from `coherence.md`. A finding that contradicts a converged decision does **not** reuse the fidelity pass's re-convergence cycle. That cycle opens by messaging the affected author, and here nobody can: the authors' `coherence` dispatches belong to the leg, a same-key resume is addressable only from the session that dispatched the member, and the leg's turn has ended by the time this step runs — so the borrowed procedure's first step has no executor while only its terminus does. The seat raises such a finding to the user itself — `등급 2` — naming the finding, the converged decision it contradicts and what each answer costs, and applies the answer directly. That is the seat's only channel, not an abbreviation of the team cycle; Step 4's fidelity pass keeps its own cycle, which runs inside the leg where the authors are addressable. Do NOT re-dispatch the team over the corrected text. Clear each consumed `[Step 7 정합 점검 대상]` note as its item is disposed of, so no queue marker survives into the frozen bytes.\n7. **Cleanup** — Read `${CLAUDE_SKILL_DIR}\u002F..\u002F_common\u002Fteam-cleanup.md` and apply it.\n8. **Slicing self-check (only when the document has a `## 구현 슬라이싱` section; the lead runs it, no team).** Downstream orchestration parses this section mechanically and cannot ask anyone what was meant, so five composition rules and two split rules are checked here — the last moment the authors are still alive — rather than discovered as a broken build hours later. **(a) Declared ⊇ actual.** For each `### 슬라이스 \u003Cid>` block, the files it declares must include every file the slice's own description says it edits; a slice that describes an edit it did not declare fails. **(b) A `SKILL.md` frontmatter change implies `README.md`.** A slice that creates a `SKILL.md` or edits a `SKILL.md`'s frontmatter must also declare `README.md`, because this repository's README is generated from skill frontmatter and a slice that changes one without the other lands a tree whose generator gate fails. A slice whose description confines its `SKILL.md` edits to the body leaves README unchanged and need not declare it — the driver no longer refuses that declaration, and a slice that regenerates README after all is parked as an edit outside its declared files. When the description does not say which part it edits, declare `README.md`. **(c) Two or more implement slices declare their residual share.** When the section holds two or more blocks whose `**스킬**` is `implement` and the document has a `## 구현 시 검증 항목` section, each such block carries `**잔여 항목**` naming the items it owns, or `없음` when it owns none; without it the driver reads that slice's share as empty and never asks its implement stage for those items' result lines. **(d) A new-grammar block gives a reason per kind.** A block carrying a `**머지 순서**` line carries `**선행 사유**` when its `선행` is not `없음` and `**머지 순서 사유**` when its `머지 순서` is not `없음`; the gate and the driver park a slice that lacks one as a missing required field. **(e) Closure disjointness.** For each slice S, its declared files are prefix-disjoint from every slice in M(S) \\ P(S) as defined under **Blocks and fields**, with no exemption for `README.md`, `plugin.json` or `CHANGELOG.md`; an overlap is repaired by turning the edge that brings the other slice into M(S) \\ P(S) into a `선행`, or by moving the file, never by dropping it from the declaration. **(f) Slice size.** For each block, count its declared files: one element is one file; an element ending in `\u002F` counts as the number of files `git ls-files -- \u003Celement>` prints in the design-time working tree of the repository the block's `**레포**` names, and at least 1 (1 when the design stage cannot read that repository's working tree — no checkout on this machine, or none visible where the design runs); `README.md`, `plugin.json`, `CHANGELOG.md` and test files count like any other file. A block over the baseline of **20** declared files is split into smaller blocks or carries `**크기 사유**`. **(g) One permission profile per slice.** This rule applies only to blocks whose `**스킬**` is `implement`. A work's permission profile is the `--reach` token the act would honestly carry when declared to the gate, and the designer judges it — the gate derives a token only from an argv being run, never from a slice declaration — and when no single token can be decided at design time it is `미상`. The base profile, which every implement slice holds, is the in-worktree reads, writes, commits and tests the gate asks no reach declaration for (derived `-`), `런로컬` (an act that reaches only this run's directory or the stage's prototype namespace) and `협업` (the push, PR and merge the cutpoint allows); `기기전역`, `dev`, `prod`, `배포트리거` and `미상` are each a separate elevated profile. A remote-capable tool (`docker`, `playwright`, `psql` and the like) is judged by the token its gate declaration would honestly carry even when it serves a local test, and a command that reaches a checkout outside the worktree (`git pull` and the like) never carries `런로컬`. A block mixes when its implementation work needs the base profile together with an elevated one, or two or more elevated profiles; a declared `**적용 명령**` counts too — its profile is that command's reach judged the same way, it counts whatever `**적용 주체**` says, and an elevated one mixes with the block's base profile. Mixing is counted by elevated act unit: one elevated act (an apply command, a machine-global install, an external service write), the declared files that exist only for that act (the script it runs, a deploy config or install list only it reads) and those files' test files; the artifacts the act ships or deploys (source, migrations, screens) and any file other work (build, local run, tests) also uses are outside the unit. A block whose declared files all belong to one unit and that has no elevated act outside it does not mix, whatever the kind of act and whatever `**적용 주체**` says. A mixed block either splits the unit off into a block of its own or carries `**권한 혼합 사유**`. The split's `선행` follows the real order: the unit of an apply command names the implementation block it deploys as `선행`, and a block that uses the act's result names the unit block as `선행`. When several blocks declare the same `**적용 명령**`, each is a separate elevated act that runs after its own block's merge, so split each block's unit off on its own and never gather the unit blocks into one; a unit file the original block edited moves with that edit into the unit block split from it, and two unit blocks that declare the same unit file are joined by the `선행` repair of (e). A unit block takes no common file (`README.md`, `plugin.json`, `CHANGELOG.md` and the like): when the unit block's work must edit one, when the elevated work must sit in the same commit as work outside the unit, or when the act has no declared file of its own (an apply command such as `git pull`), do not split, and write `**권한 혼합 사유**` on the original block. Repair the declaration in place (this is still a document edit, so it happens **before** the freeze, not after). If a failure cannot be repaired without a decision the authors did not make — the slice's file set is genuinely unknown — `AskUserQuestion` rather than guess: a wrong declaration is worse than a missing section, because the driver trusts it.\n   - The disposition of the two split rules. A reason names the one coupling a split would break, and a sentence that names none is not a reason; when the person gave the `슬라이스 수` answer, nothing is split and the reason field quotes that answer instead.\n   - Neither split rule asks or stops. A split the designer can decide is made, and otherwise the reason field is written. A split is a new declaration, so run (a) through (g) again on every block it made and bring the section's `**슬라이스 수**` checksum back into line.\n   - Finish a split in this order. The original block's id is kept by one of the new blocks and every other new block takes a new id. A block whose `선행` named the original id is changed to name the block that holds the work it waited for. The new blocks stand where the original block stood, never appended at the section's end: each one after every block its `선행` or `머지 순서` names, and before every block that now names it in either list — the driver runs the blocks once in section order and parks a block whose `선행` has not finished, and a `머지 순서` token naming a block declared later is a defect of the slice that carries it. The original block's `**잔여 항목**` and `**적용 명령**` move to the block that holds the work they cover, and `**적용 주체**` and `**폭발 반경**` move with `**적용 명령**`. The original block's edit description is divided so that each new block describes only the files it declares — an edit description left behind for a moved file fails that block's (a). Files the new blocks declare together (`README.md`, `plugin.json`, `CHANGELOG.md`) follow the repair of (e), a `선행` edge; a unit block split off by (g) takes none of them. Each new block writes the required fields (`**스킬**`, `**레포**`, `**선언 파일**`, `**선행**`, `**절단점**`), and when the original block carried a `**머지 순서**` line every new block writes one too, because without it the block reads as old grammar and loses its reason obligation; the block that received `**적용 명령**` inherits the original `**절단점**`, each other block takes the cutpoint its own work calls for, and the remaining fields (`**리뷰 정책**`, `**라벨 인정**`, `**화면**` and the like) are written on each new block to fit its work. Another block's `**머지 순서**` or `**폭발 반경**` that names the original id is changed by the same standard as `선행` — a blast radius parks by exact string and never checks that the id exists, so a radius left on the block the apply moved away from parks nothing. A new-grammar block that gains a `선행` from the split writes `**선행 사유**` ((d)). When the split declaration cannot be made to pass (a) through (e) without a decision, the split is not made and the original block carries the reason field instead, which is why neither split rule reaches the decision this item's last sentence asks for.\n   - The item's last sentence, \"If a failure cannot be repaired without a decision the authors did not make …\", covers rules (a) through (e) only.\n9. **FREEZE.** Emit in Korean: *\"설계 문서를 동결했습니다. 이후 이 세션에서는 문서를 수정하지 않습니다.\"* When the document has a `## 구현 슬라이싱` section, add one line to that notice from `bash ${CLAUDE_SKILL_DIR}\u002F..\u002F..\u002Forchestrator\u002Fenforcement-surface-screen.sh -- \u003Cevery slice's declared files>`, which prints `\u003Cpath>\u003CTAB>\u003Cclass>` for each path an unattended run's hook refuses: `강제 표면: 슬라이스 \u003Cid> — \u003C경로> (\u003C분류>, \u003C좌석 적용 가능|사람 몫>), …`, slices separated by `; ` — `규칙카탈로그` and `지침파일` read `좌석 적용 가능`, the other two `사람 몫` — or `강제 표면: 없음`, or `강제 표면: 판정불가` when the screen exits 2. It is a notice: such a path stays declared, and the person learns now that a run implementing it will stop on that edit. From this point `design` performs no further document edits. This step is terminal — there is no path back to Step 5 or Step 6. (CFI-3c) At the freeze the seat deletes the state root's **control plane** — `leg.json`, `park.md`, `presentation.md`, `coherence.md`, `leg.*.out`, `leg.*.err` — and keeps `$STATE\u002Fwitness\u002F`: the corpus is the only durable copy of the round products, and deleting the whole root would destroy it at the moment of the freeze. A workflow that ends in an abort keeps everything.\n10. **Hand off — and the handoff has TWO destinations, so read which one you are in first.**\n\n    **If this invocation was asked for by an autopilot kickoff, the destination is that kickoff, not the audit.** Say so: the document is frozen, here is its path and its whole-file `sha256`, go back and resume the kickoff. The audit is already a stage in the run's approved step graph, so naming it here sends the person to run by hand a thing the run is about to dispatch — and if they follow it instead of returning, **the run is never created at all.** That failure leaves nothing behind: no manifest, no grant, no ledger, no report, so a kickoff abandoned at this exact line is indistinguishable from one that was never started. The handoff lands the moment the freeze happens, which is the moment the kickoff is waiting to be resumed, so this is the most conspicuous instruction at precisely the wrong time.\n\n    **Otherwise** — tell the user in Korean that the next step is `\u002Fcc-cmds:design-audit docs\u002F{topic-slug}.md`, the independent Class S audit over the now-frozen document. State its shape in one line so the freeze reads as purposeful rather than bureaucratic: **independent readers · 1 round · non-recursive · one coherence reconciliation, then stop.** It is a fixed budget with a mandatory residual disclosure, not a multi-round loop with a cap — the reader count lives in that skill's own control-flow invariants and is not restated here.\n\n## Constraints\n\n- NO code modifications. Design discussion only.\n- Inter-agent communication must be in English.\n- **Team members are nameless `Agent` sub-agents**: team members ARE `Agent` sub-agents — nameless background tasks (`subagent_type: \"claude\"`, `run_in_background: true`, **no `name`**), one dispatch per `(role, round\u002Fphase)` key and self-terminating on return. What the design discussion requires is NOT a special team primitive but **cross-review and convergence through the witnesses on disk** (debate, challenge, cross-validation across rounds, lead-mediated per `_common\u002Fagent-team-protocol.md`). Each new round or phase is a fresh dispatch of the role that reads its own past witnesses and its peers' witnesses by path; a re-request inside one key resumes the same `agentId`.\n- **Permitted team resumes (same key only).** A resume — `SendMessage` to a member's `agentId` — is permitted only inside the key that member was dispatched for: a send-back `P-rev\u003Ck>`, Case 1, Case 3, the re-assignment for a missing `peer-read:` receipt, and the witness nudge. A new `round\u002Fphase` key is always a fresh dispatch, never a resume. Step 6's ban targets *conscripting a team convened for a different purpose*. It does NOT target *asking a team about the coherence of its own output* — that follows from Class C defects (the context-dependent kind, whose evidence never reached the artifact) having non-zero sensitivity **only** in the authoring team. Exactly two re-convenings of a prior team's roles are permitted in this skill, each a fresh dispatch into that team's rows, and this list is closed: no other re-convening of a prior team is allowed, for any reason, anywhere.\n    1. **Step 3 → Step 4 synthesis fidelity pass** — the Step 3 roles dispatched afresh to check draft↔discussion fidelity. Phase token `fidelity`. Mandated by Step 4's \"Subject & input\" — executed inside the leg (`design-discuss-unattended`), which dispatches into the Step 3 team's rows and owns their same-key resumes.\n    2. **Step 3 → Step 7 Class C coherence pass** — the Step 3 roles dispatched afresh at a new `epoch` **inside the resumed leg**: the seat resumes the leg session (`claude -r \u003Csession_id>`, same flags and redirections) with the coherence message, and the leg dispatches its own team's roles. Phase token `coherence`. Mandated by Step 7. **Fallback** (only on one of Step 7's two triggers): the Step 3 roles are **dispatched fresh at a new `epoch`** by the seat from the durable witness corpus + the brief + the final document **by path** — the same pass with a different input, not a third re-convening.\n\n    Everything else spawns FRESH as a new team: the Step 5 walkthrough team, every Step 6 refinement team, and any re-composition. A walkthrough-spawned team is never extended into a refinement team or the reverse. A Step 5 or Step 6 **fresh** team is never re-convened for the Step 7 coherence pass — the Class C channel is the *authoring* team specifically, and a fresh team's sensitivity to it is structurally zero, so re-convening one would produce a confident answer from the one vantage that cannot see the defect. Every permitted re-convening of a team from an earlier generation carries the protocol's **`epoch` re-stamp** duty (`_common\u002Fagent-team-protocol.md`, Spawn).\n- **Deferred tool loading**: Before using AskUserQuestion, SendMessage, or TaskStop, you MUST first load them via ToolSearch. Run `ToolSearch` with query \"select:AskUserQuestion,mcp__cc-cmds__question_form\", \"select:SendMessage\", and \"select:TaskStop\" to load each tool. These are deferred tools and will NOT work unless loaded first. (`Agent` is a built-in primary tool — do NOT load it via ToolSearch. `SendMessage` to an `agentId` resumes a running member; `TaskStop` aborts one.) AskUserQuestion MUST be loaded before Step 1 (user interview). Before calling AskUserQuestion, Read `${CLAUDE_SKILL_DIR}\u002F..\u002F_common\u002Faskuserquestion.md` and apply its hard constraints to every AskUserQuestion call in this skill.\n\n### Observation & verification carve-out (running + experimenting ≠ modifying)\n\nThe \"NO code modifications\" rule above and in Step 3 is **absolute and unweakened** — but \"modification\" has a precise definition that makes both reproduction (running the unmodified app\u002Ftest suite) and in-session verification (out-of-tree experiments and isolated-worktree mini-implementations) fully compatible with it. This carve-out is a *definition*, not an exception: the two literal \"NO code modifications\" strings stay literally true everywhere. The full operating mechanics live in `${CLAUDE_SKILL_DIR}\u002F..\u002F_common\u002Fverification.md` §6 (Read it); the compression-critical core is restated here.\n\n- **What \"modification\" means**: a change that **persists in the session's main working tree**. (In git vocabulary an experiment worktree is also a \"working tree\", so the scope is the *main* tree specifically.) Running the app\u002Ftest suite as-is, an out-of-tree driver, or an isolated-worktree experiment that is torn down — none persists a change to the main tree, so none is a modification.\n- **FORBIDDEN**: editing any tracked source file **in the main working tree** — even transiently, even \"I'll revert it after.\" There is no in-tree print-logging exception.\n- **Two-command boundary gate** (scope is per-surface): at every team-discussion boundary run the gate exactly as `_common\u002Fverification.md` §6 defines it — assertion 1 (main tree `git status --porcelain` == the pre-workflow baseline, **within the caller's declared measurement surface** — `design` declares none, and §6.0's default for a caller that declares nothing is the whole tree, so here assertion 1 is whole-tree equality) and the three scoped worktree assertions 2a\u002F2b\u002F2c. The worktree half is a separate gate because porcelain does not see records inside `.git\u002Fworktrees\u002F` (the F1 blind spot), and it is **scoped rather than whole-output** because `git worktree list` is repository-global — a sibling worktree's commit is not a mismatch. Step 4's design-document save (`docs\u002F{slug}.md`) and the interview brief `docs\u002Fdesign-brief\u002F{slug}.md` written at leg dispatch are the skill's two sanctioned tracked-file writes and are NOT subject to this gate — the brief is exempted by path filter, never by staging or ignoring it.\n\n**Surface 1 — main working tree** (reproduction + categories a\u002Fb\u002Fc\u002Fd): today's rules, unweakened.\n\n- **ALLOWED**: executing the unmodified app, running the existing test suite, attaching a debugger, raising verbosity via existing flags\u002Flog levels, importing project modules from an out-of-tree driver, and (for category (c)) WebFetch \u002F WebSearch \u002F external CLI. All artifacts, drivers, and logging route to a `\u002Ftmp` sink or existing verbosity\u002FCLI flags — strictly outside the working tree.\n- **Cleanup boundary — \"before findings leave their producer\"**: whoever produces a finding or a verification verdict (the lead, the reproduction agent, or the verification agent) must, *before* it leaves in any form (whichever comes first: a broadcast, a verdict-citing SendMessage, a task return, or a doc Edit), revert all instrumentation, delete every out-of-tree artifact, and verify the two-command gate == baseline. There is no window in which the tree is dirty while a finding\u002Fverdict is visible to another agent. The lead is the backstop: re-verify before the Step 4 save (the pre-save sweep).\n- **Environment vs. working tree (lockfile checklist)**: the gate is scoped to tracked source only. Verification\u002Freproduction may install dependencies and produce build output: (1) gitignored build output (`node_modules`\u002F`dist`\u002F`.next`\u002F`build`) is out of scope — never appears in porcelain; (2) an install that rewrites a **tracked lockfile** (`package-lock.json`\u002F`poetry.lock`) or tracked codegen path must NOT persist — use a non-rewrite form (`npm ci`, `npm install --no-save`, venv) or revert before the boundary; (3) the pass\u002Ffail gate at every boundary is the two-command gate == baseline.\n\n**Surface 2 — isolated worktree (category (e) only)**: for a mini-implementation whose observation unavoidably requires changing tracked content *and* repo-faithful context (the α∧β condition in `_common\u002Fverification.md`). Compression-critical locks (full mechanics in `_common\u002Fverification.md` §6.2):\n\n- **Create** with `WT=$(mktemp -d \"${TMPDIR:-\u002Ftmp}\u002Fcc-design-exp-\u003Cowner-token>-\u003Cslug>.XXXXXX\")` then `git worktree add --detach \"$WT\" HEAD`. `mktemp` + `--detach` are MUST, and the **owner token** is the creating member's phase `witnessNonce` from its ledger row — it is what scopes assertion 2c to this team rather than to every caller of the mechanism on the machine. Append the created path, that token and a timestamp to the team's creation record under the member's `scratchDir`, **in the same Bash call** as the `git worktree add`; assertion 2a reads that record. **EnterWorktree is forbidden** (its only-if-unchanged auto-cleanup guarantees a leak for a changed worktree); the Agent-tool isolation form is forbidden.\n- **In-worktree FORBIDDEN**: no commit \u002F branch \u002F push \u002F tag \u002F `git config` write \u002F hook install \u002F gc·maintenance \u002F **stash** (`refs\u002Fstash` is a shared namespace — an in-worktree stash survives worktree removal in the main repo's `git stash list`, a porcelain-invisible leak).\n- **Lifetime**: from claim pre-registration to that claim's verdict broadcast; no persistence across re-convergence (regenerate from the recipe — deterministic since the main tree is frozen). One experiment = one worktree, never shared across agents.\n- **Final-run rule**: a verdict is backed only when the recorded recipe's patch, applied on a clean reset (`cd \"$WT\" && git checkout -- . && git clean -fd` — the single inseparable line; run from the wrong cwd it destroys the user's main-tree untracked files), is observed to match the recorded `관측 결과`.\n- **Cleanup**: `git worktree remove --force \"$WT\"` + `git worktree prune` + the record check (every path the creation record claims is absent from `git worktree list --porcelain`, and no entry carries this team's owner token), before the verdict ships. Lead backstop: the pre-save sweep and the Step 6 entry state-check add the two-command gate.\n\n- **CFI impact: none** — quality tier (a missed application is quality degradation, not a mis-transition). Nothing is added above the `## Control-Flow Invariants` heading.\n\nTask: $ARGUMENTS\n",{"name":5,"usage":39,"options":40,"description":7,"when_to_use":46,"disable-model-invocation":45},"\u002Fcc-cmds:design \u003Ctask>",[41],{"kind":42,"name":43,"summary":44,"required":45},"positional","\u003Ctask>","설계 토론을 진행할 작업 주제 (자유형 한국어\u002F영문 텍스트).",true,"사용자가 새 기능 설계\u002F아키텍처 결정\u002F다관점 검토가 필요한 설계 논의를 요청할 때","master","98c63c160cafbac635514030d2e3b1a2675bfb3b","plugins\u002Fcc-cmds\u002Fskills\u002Fdesign",1,"https:\u002F\u002Fgithub.com\u002FNharu\u002Fcc-cmds","https:\u002F\u002Fgithub.com\u002FNharu","2026-11-13 01:36:53",{"source":8,"skillName":5,"commands":55,"prompt":65,"zipAvailable":45},[56,59,62],{"tool":57,"command":58},"npx","npx skills add Nharu\u002Fcc-cmds --skill design",{"tool":60,"command":61},"bunx","bunx skills add Nharu\u002Fcc-cmds --skill design",{"tool":63,"command":64},"pnpm","pnpm dlx skills add Nharu\u002Fcc-cmds --skill design","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002FNharu\u002Fcc-cmds\u002Fblob\u002Fmaster\u002Fplugins\u002Fcc-cmds\u002Fskills\u002Fdesign\u002FSKILL.md",[],[68,79,91,98,105,117],{"skillNo":69,"name":70,"nameZh":6,"description":71,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":72,"categories":73,"keywords":74,"publishedAt":34},"01M6DNB8T41Y37D3M9JKHFT7HV","zeroargs","zero-argument command","https:\u002F\u002Fgithub.com\u002FNharu\u002Fcc-cmds\u002Fblob\u002Fmaster\u002Ftests\u002Ffixtures\u002Freadme-gen\u002Fsimple\u002Fzeroargs\u002FSKILL.md",[],[70,75,76,29,77,78],"when","argument","command","ZeRO",{"skillNo":80,"name":81,"nameZh":6,"description":82,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":83,"categories":84,"keywords":88,"publishedAt":34},"01M6DNB5TG3T9QMEF3HPKJPER0","review","에이전트 팀을 활용한 다관점 코드 리뷰","https:\u002F\u002Fgithub.com\u002FNharu\u002Fcc-cmds\u002Fblob\u002Fmaster\u002Ftests\u002Ffixtures\u002Freadme-gen\u002Fpre-yq-skills\u002Freview\u002FSKILL.md",[85],{"categoryNo":86,"categoryName":87,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000023","Skill与智能体开发",[81,89,31,90],"pr","diff",{"skillNo":92,"name":93,"nameZh":6,"description":94,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":95,"categories":96,"keywords":97,"publishedAt":34},"01M6DNAYNZFJR1TATEM9PVHGH2","implement","설계 문서 기반 구현","https:\u002F\u002Fgithub.com\u002FNharu\u002Fcc-cmds\u002Fblob\u002Fmaster\u002Ftests\u002Ffixtures\u002Freadme-gen\u002Fpre-yq-skills\u002Fimplement\u002FSKILL.md",[],[93,31],{"skillNo":99,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":100,"categories":101,"keywords":104,"publishedAt":34},"01M6DNAVQF4KERY94V79NVWAZA","https:\u002F\u002Fgithub.com\u002FNharu\u002Fcc-cmds\u002Fblob\u002Fmaster\u002Ftests\u002Ffixtures\u002Freadme-gen\u002Fpre-yq-skills\u002Fdesign\u002FSKILL.md",[102,103],{"categoryNo":19,"categoryName":20,"taxonomyType":21,"taxonomyTypeDesc":22},{"categoryNo":24,"categoryName":25,"taxonomyType":26,"taxonomyTypeDesc":27},[5,31],{"skillNo":106,"name":107,"nameZh":6,"description":108,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":109,"categories":110,"keywords":113,"publishedAt":34},"01M6DNASB3J3JQMZD57YBDHZ1A","design-upgrade","팀원 모델 업그레이드 분석","https:\u002F\u002Fgithub.com\u002FNharu\u002Fcc-cmds\u002Fblob\u002Fmaster\u002Ftests\u002Ffixtures\u002Freadme-gen\u002Fpre-yq-skills\u002Fdesign-upgrade\u002FSKILL.md",[111,112],{"categoryNo":19,"categoryName":20,"taxonomyType":21,"taxonomyTypeDesc":22},{"categoryNo":24,"categoryName":25,"taxonomyType":26,"taxonomyTypeDesc":27},[114,5,115,31,116],"design upgrade","upgrade","haiku",{"skillNo":118,"name":119,"nameZh":6,"description":120,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":121,"categories":122,"keywords":125,"publishedAt":34},"01M6DNAA53K13C0REE8FDT3QHR","design-review","설계 문서 최종 리뷰","https:\u002F\u002Fgithub.com\u002FNharu\u002Fcc-cmds\u002Fblob\u002Fmaster\u002Ftests\u002Ffixtures\u002Freadme-gen\u002Fpre-yq-skills\u002Fdesign-review\u002FSKILL.md",[123,124],{"categoryNo":19,"categoryName":20,"taxonomyType":21,"taxonomyTypeDesc":22},{"categoryNo":24,"categoryName":25,"taxonomyType":26,"taxonomyTypeDesc":27},[81,5,126,31],"design review"]