Docs · Cocode ADE · 분석 · 설계 문서

Cocode ADE · 09

UX Spec — 화면 흐름과 UX 설계

셸 · 위임 · 승인 · diff · 롤백 화면과 UX 결정

목차

파이프라인 4단계(Design) 산출물 · 2026-08-26 · 화면 흐름·UX 설계 정본 순서: Seed Spec v3.1.0 > 조직 규약(cc-flutter·cc-coui 스킬) > PRD/BDD > Discovery

작성 방식: 초안을 작성한 에이전트와 별도의 검증 에이전트가 원본 파일을 직접 열어 대조하고 교정했다. 이 파일은 교정본이다.


⚠️ 이 문서 작성 이후 확정된 사항 (2026-08-26, 반영 필요)

아래 셋은 이 문서를 생성한 워크플로가 시작된 뒤 확정됐다. 본문에 반영돼 있지 않으므로 이 블록이 우선한다.

1. Flutter master 채널 + 네이티브 윈도잉 API (D-022) — 창 분리를 window_manager 가 아니라 Flutter 네이티브 윈도잉(RegularWindow·DialogWindow·PopupWindow·SatelliteWindow·WindowingOwner·WindowRegistry)으로 구현한다. 결정적 근거는 windowHandle 이 ffi.Pointer<ffi.Void> 로 네이티브 핸들(Linux GtkWindow·macOS NSWindow·Win32 HWND)을 노출해 네이티브 도킹이 가능하다는 점이다(_window_linux.dart:208, _window_macos.dart:200).

  • 채널 제약: windowingFeature 가 master: 만 선언하므로 stable 에서는 available:false 이고 설정으로도 켤 수 없다(flutter_features.dart:99 가 config 를 읽기 전에 반환). 제품 빌드 전체가 master 채널 위에 서게 된다.
  • 인수한 위험: @internal API · 패치 버전에서도 breaking change 예고 · CI·개발 환경·cob doctor 가 모두 master 전제. 완화로 창 관리 호출을 얇은 자체 인터페이스 뒤에 두어 수정 지점을 한 곳으로 모은다.

2. 프로젝트 초기 세팅은 cob 로 수행 (D-023) — 모노레포 생성과 기능 추가를 cob(co-bricks CLI)로 한다. cob doctor 전 항목 통과 확인. 관련 명령: cob create·cob generate(project.yaml → 모노레포+기능)·cob compose/add·cob apply·cob plan(PRD FR/AC 커버리지 게이팅, 고아 FR hard-fail). 미결: cocode ADE 는 앱이 아니라 데스크톱 IDE 이고 Serverpod 백엔드가 없어, 기존 brick 이 이 형태를 지원하는지 Scaffold 단계에서 cob list-features 로 확인해야 한다.

3. CoUI 실측 인벤토리 (docs/coui-inventory-cocode.md) — 이 문서가 인용하는 CoUI 컴포넌트는 그 인벤토리와 대조해야 한다. 특히 주의: coui-dock 은 IDE 도킹이 아니라 모바일 하단 내비게이션 바이고, coui-diff 는 코드 diff 가 아니라 이미지 비교 슬라이더다(코드 diff 는 coui-code-diff). Figma 검색 결과 Terminal·Toolbar·StatusBar·Sidebar·Panel(단독)·Input·Split·CommandPalette 는 실재하지 않는다.


UX 명세: 코코드 ADE (cocode ADE)

파이프라인 4단계(Design) 산출물 · 작성 2026-08-26 · 대상 Seed Spec v3.1.0 개정 2026-08-26 (감사 반영) — 정정 내역은 §0.5


0. 이 문서의 지위와 규칙

0.1 근거와 권위

층위 문서 이 문서의 취급
권위 docs/seed-spec-cocode.md v3.1.0 뒤집지 않는다. 어긋나면 그 사실을 명시한다
파생 docs/prd-cocode.md(대상 v3.0.2 + v3.1.0 반영 고지), docs/bdd-cocode.md(시나리오 51건 — ^ Scenario 직접 계수 = Scenario: 45 + Scenario Outline: 6 · 2026-09-10 재계수: #20 이 1건, #32 가 3건을 더했다) v3.1.0 과 어긋나는 부분은 §0.3 에 열거
동일 단계 입력 docs/coui-inventory-cocode.md(2026-08-26) — CoUI 실재/비실재 목록의 정본 §6 은 이 문서와 대조한다. 다만 이 문서가 스킬 원문을 인용한 대목 중 확인되지 않는 것이 있어(§0.4 주) 스킬 파일 재확인을 거친 것만 채택한다
입력 docs/planning-inputs-cocode.md, docs/discovery-cocode.md, docs/decision-log-cocode.md(D-001~D-023), docs/contrarian-review-cocode.md, docs/spec-evaluation-cocode.md 계약이 아니다
규약 ~/.claude/skills/cc-flutter/skills/{flutter-patterns,package-layers,coui-flutter-rules,flutter-a11y}/SKILL.md, ~/.claude/skills/cc-coui/skills/<name>/SKILL.md 조직 표준

정정. 초판은 의사결정 일지 범위를 D-001~D-021 로 적었다. 실제는 D-023 까지이며, 누락된 두 건은 UX 전제에 직접 닿는다 — D-022(Flutter master 채널 채택 — 네이티브 윈도잉 API windowHandle 사용, 인수 위험 명시), D-023(초기 세팅을 cob 로 수행). D-022 는 §2.3 의 창·도킹 범위 판단에, D-023 은 §6.3 의 패키지 골격 생성 수단에 영향한다.

0.2 표기 규칙

  • [경계] — Seed Spec §2·§3·§4 에서 직접 파생. elaborate 만 하고 좁히거나 넓히지 않는다.
  • [도출] — 위에서 판정 없이 연역. 연역 근거를 함께 적는다.
  • [규약] — 조직 스킬 파일에서 파생.
  • [UX-D-NN] — 근거 문서에 규정이 없어 이 문서가 새로 정하는 UX 결정. 전량 §11 에 모은다.
  • 수치: 출처(D-NNN / 문서+절 / 외부 표준)가 있을 때만 쓴다. 없으면 값 대신 누가 언제 정하는가를 쓴다.
  • 와이어프레임 안의 값은 전부 예시다. 파일명·시각·경과 시간·줄 수·건수·+38-12 형태의 증감·12.4s 같은 소요 시간은 배치를 보이기 위한 더미 데이터이며 규범값이 아니다. 이 문서에서 인용 가능한 수치는 본문 표에 출처와 함께 적힌 것뿐이다.

0.3 상류 문서와 어긋나는 지점 — 먼저 밝힌다

  1. 프롬프트가 지목한 Discovery §번들 해부 는 존재하지 않는 절이다. 테마 스키마의 실제 출처는 docs/discovery-cocode.md ### Key Insights 3번이고, 원문은 "테마 스키마(LSP 시맨틱 토큰 24종 + UI 9색)는 그대로 채택 가치가 있는 설계다 — 아이디어이지 저작물이 아니므로 법적 문제 없이 재사용 가능" 이다. "가장 값진 발견"이라는 표현은 그 문서에 없다(docs/ 전수 grep — 값진 0건). docs/spec-evaluation-cocode.md 130행이 이 인용(Discovery §번들 해부)을 이미 인용 오류로 기록해 두었다 — 같은 오류가 이 태스크 지시에 재유입됐다.

  2. 롤백 충돌 판정 — 이미 봉인된 잔존 서술이다(초판 서술을 정정한다).

    • PRD FR-506, 흐름 4 4단계, §3.3 불변식 2 는 여전히 본문에 base_content_hash 비교를 적는다.
    • 그러나 PRD 25행과 BDD 25행이 동일 문장으로 이미 그 서술을 폐기 처리했다: "이 문서 본문의 현재 해시 vs base_content_hash 비교 서술(FR-506, 흐름 4, §3.3 등)은 폐기한다." 살아 있는 모순이 아니라 봉인된 잔존물이다.
    • BDD U-10 은 base_content_hash 를 판정 기준으로 쓰지 않는다. 정반대다 — U-10 원문: "미정 — Seed Spec 미규정. … base_content_hash 는 편집 직전 내용의 해시(89행)이므로 에이전트 편집 직후의 파일 내용은 정의상 base 와 다르다. 무엇과 비교해 사람의 개입을 가려내는지가 정해져야 판정이 가능하다." U-10 은 v3.1.0 이 고친 그 버그를 먼저 지목한 항목이며 v3.1.0 으로 해소됐다.
    • 이 문서는 v3.1.0 을 따른다(§4.3).
  3. PRD §1.3 "범위 해석에서 자주 틀리는 세 지점" 3번의 회색지대(Q-04)는 v3.1.0 AC-21 이 해소했다 — 워크트리 격리·작업 인계는 MVP 밖, AC-12(한 워크스페이스 내 복수 작업 + 파일 잠금)는 MVP 안.

  4. BDD 는 AC-01~AC-20 만 덮는다(docs/bdd-cocode.md 746행: "Seed Spec §4 의 AC-01~AC-20 각각에 최소 1건을 배정했다"). v3.1.0 신설 AC-21 에 대응하는 시나리오가 없다 → Planning 으로 되돌릴 항목.

  5. Discovery ## Ideation > Solution Direction 의 아키텍처 그림은 agent 를 "스스로도 ACP 서버로 노출해 UI 코드 경로를 하나로 통일"로 그린다. 오너 결정 1이 이를 뒤집었다 — UI 코드 경로 통일은 ACP 가 아니라 Dart 계약 인터페이스로 달성된다. 이 문서의 화면 계약은 agent_backend_kind(agent | acp) 라는 §3 속성만 알면 되고, 프로토콜을 알 필요가 없다.

  6. Discovery ### Technical Feasibility 의 UI 행은 material_ui/cupertino_ui 1.0 을 권장한다. 오너 결정 4(CoUI 기반)가 이를 대체한다.

  7. flutter-patterns 스킬 본문은 BLoC 로 서술하나(§Actions 2 — "Generate state management code following the BLoC pattern"), 조직 실사용 표준은 BlocSignal 계열이다 — cc-quality/skills/code-review-checklist/REFERENCE.md §Performance 표가 BlocSignalBuilder·buildWhen·BlocSignalSelector 를 점검 항목으로 두고, 같은 파일 §bloc_signals 전용 점검이 context.watch<T>().stateValue 금지를 명시하며, cc-dcm/skills/dcm-bloc/SKILL.md 가 "BlocSignal / CubitSignal 은 다른 패키지의 다른 기반 클래스" 라고 적는다. 오너 결정 2와 일치.

  8. coui-flutter-rules 와 coui-theme 가 충돌한다. 전자는 | context.typography | ❌ 사용 금지 |(63행), 후자는 Overview 예시에 context.typography.bodyMedium(51~52행)을 쓴다. 프롬프트가 지정한 규약은 coui-flutter-rules 이므로 그쪽을 따른다 — 타이포는 context.textStyles + M3 시맨틱.

  9. CoUI 인벤토리와의 관계(신설). docs/coui-inventory-cocode.md 는 같은 Design 단계에서 "UX 명세가 같은 실수를 하지 않도록 실재 목록과 비실재 목록을 함께 남긴다" 는 목적으로 작성됐다. §6 은 그 §1(비실재)·§3(커버)·§4(IDE 전용 15건)·§5(미검증)을 대조 대상으로 삼는다.

0.4 전제 — 뒤집지 않는 오너 결정 4건 (2026-08-26)

# 결정 이 UX 명세에 미치는 영향
1 agent 를 ACP 서버로 노출하지 않음. 내부는 Dart 계약 인터페이스, acp 가 외부 ACP 를 어댑터 화면은 백엔드 종류를 agent_backend_kind 배지로만 구분. 프로토콜 UI 없음
2 상태 관리 = BlocSignal §9
3 EditSnapshot = 파일 기반 저장(Lumide local_history 방식, 파일별 버전 디렉터리). 보존 정책을 설계가 정함 §4.5 — 축 불일치를 발견했다
4 UI = CoUI 기반 + IDE 전용 확장 §6

⚠ 이 4건은 아직 의사결정 일지에 등재되지 않았다. 일지는 D-023 에서 끝나고, docs/coui-inventory-cocode.md 는 결정 4를 D-024 로 인용하지만 그 항목은 일지에 존재하지 않는다. 등재 전까지 이 4건은 추적 가능한 결정이 아니라 구두 전제다 → §12 미결.

⚠ 인벤토리 인용의 한계. coui-inventory-cocode.md §4 는 일부 대목에서 스킬 원문을 인용하나, 재확인 결과 coui-status/SKILL.md 의 "애니메이션 없음" 문장과 coui-scroll-area/SKILL.md 의 "ListView.builder 를 쓰라" 문장은 현재 스킬 파일에 없다. 이 문서는 스킬 파일에서 직접 재확인한 계약 사실만 채택하고, 인벤토리의 결론은 그 근거를 다시 적어 인용한다.

0.5 초판(2026-08-26 최초본) 대비 정정 내역

# 초판 정정
1 의사결정 일지 D-001~D-021 D-001~D-023. D-022·D-023 추가 반영
2 "BDD U-10 은 base_content_hash 를 판정 기준으로 쓴다" U-10 은 그것을 거부하고 같은 버그를 지목한 항목. PRD·BDD 의 v3.1.0 폐기 고지 병기(§0.3-2)
3 P1 근거 "D-007 Rationale 2번" D-007 Options 2번
4 "알림 grep — 히트는 전부 다른 맥락" 히트 0건(11개 문서 전수)
5 UX-D-02/03 이 Resizable 로 접기·복원 가능하다고 전제 계약상 불가 — §2.3 재작성, CocodePaneHost 신설
6 UX-D-07 2차 키가 버킷 ①에서 정의되지 않음 정렬·표시 규칙 분리(§3.3)
7 UX-D-13 게이트가 빈 diff 로 충족 가능 게이트를 "승인 대상 변경을 열었는가"로 교체(§5.2)
8 승인 카드 미리보기의 데이터 출처 미표기 [UX-D-19] PendingChange 신설 개념으로 명시
9 실행중 행 "편집 중 파일명" §3 에 작업↔잠금 귀속 없음 → 미결로 승격(§3.2)
10 실패 사유 "폐쇄 3종" 3종 + 미규정 1경로. 자리표시자 규칙 추가(§3.2)
11 상태바에 컴포넌트 미배정 CocodeStatusBar(Scaffold footers: 기반) 배정(§6.2, S-01)
12 §10 표와 주석의 배정 여부 모순 주석 재작성
13 비정상 종료 status 를 D-13 에 귀속 PRD 흐름 5 미결 A(status) / D-13(감지 기준) 분리
14 AC-01 을 [전체 diff 열기] 버튼 뒤에 둠 작업을 여는 것 = diff 를 여는 것(§2.2)
15 Timeline 선택 계약 "미확인" 확인 완료 — 계약에 선택/콜백 없음(§6.2), 미결에서 제거

1. 설계 원칙 5개

# 원칙 근거
P1 화면은 "지금 보고 있는 사람"이 아니라 "돌아온 사람"을 위해 설계한다. [경계] C-04(비동기 위임 — "에이전트는 사람의 실시간 관찰 없이 자가 검증을 수행"), D-007 Options 2번(*"사람이 자리를 비우면 작업이 멈춤"*을 배제하고 옵션 1을 택함)
P2 화면은 상태를 추론하지 않는다. status 7종·pending_approval_kind 3종은 폐쇄 집합이므로 표시도 1:1 사상이다. §3 에 없는 값은 화면에도 없다 [경계] §3 DelegatedTask "status 값 집합"(7종), FR-203
P3 되돌림은 어느 상태에서도 한 번에 닿는다. 종결 상태가 아니어도, 실패해도 [경계] AC-19, BDD Feature 1 "[AC-01] 종결 상태가 아닌 작업도 지금까지의 diff 를 보여준다"
P4 두 승인은 절대 같은 카드로 그리지 않는다. 하나는 적용 전, 하나는 적용 후다 [경계] AC-10 vs AC-11 + §3 불변식 2·3
P5 CoUI 계약으로 표현 가능한 것은 CoUI, 계약이 없는 것만 IDE 전용. "비슷하다"로 대체하지 않는다 [규약] 오너 결정 4

2. 화면 구조 (a)

2.1 도킹 골격 — 3열 + 하단 + 상태바

아래 목업의 파일명·건수·시각은 전부 예시다(§0.2).

┌──────────────────────────────────────────────────────────────────────────────┐
                    │ File   Edit   View   Delegate   Run   Help                        [Menubar]  │
                    ├───────────────┬──────────────────────────────────────┬───────────────────────┤
                    │ [탐색] [위임] │ lib/a.dart ×  lib/b.dart ×  T-042 ×  │ Task Inspector        │
                    │               ├──────────────────────────────────────┤                       │
                    │ ▾ lib         │  1  import 'package:flutter/...';    │ T-042 로그인 리팩터   │
                    │   ▾ features  │  2                                   │ ● 사람승인대기        │
                    │     a.dart 🔒 │  3  class LoginPage extends ... {    │   └ 완료승인          │
                    │     b.dart    │  4    @override                      │ ─────────────────────  │
                    │ ▾ test        │                                      │ 백엔드 agent     │
                    │     a_test.d  │        [ CocodeEditorView ]            │ 변경 3파일 · 스냅샷 7 │
                    │ ▸ integration │                                      │ 재시도 0/3            │
                    │ ▸ widgetbook  │                                      │ 검증 ①빌드 ✓ ②테스트✓ │
                    │               ├──────────────────────────────────────┤ ┌ 변경 diff ────────┐ │
                    │               │ [터미널] [검증 로그] [문제]          │ │ (열자마자 표시)   │ │
                    │               │ $ flutter test                       │ └───────────────────┘ │
                    │               │                                      │ [승인]      [롤백]    │
                    ├───────────────┴──────────────────────────────────────┴───────────────────────┤
                    │ unibook │ 실행중 2 · 승인대기 3 · 실패 1 │ 잠금 1 │ 되돌림 보존: 전체 작업   │
                    └──────────────────────────────────────────────────────────────────────────────┘
                       ← 좌: 탐색/위임      ← 중: 에디터·diff 스택 →      우: 검토·승인·롤백 →
                    

구성 근거

영역 무엇 근거 구현 수단
중앙 상단 코드 에디터 (탭 스택) [경계] AC-03 CocodeEditorView + CoUI Tabs/TabPane
좌측 탐색 파일 트리 [경계] AC-03 CocodeFileTree
하단 터미널 [경계] AC-03 CocodeTerminalView
하단 [문제] 검증 원문 뷰 = S-08b — 워크스페이스 세션 버퍼의 원문을 작업·회차·방법 축으로 보인다. 이 세션에서만 [도출] AC-09·AC-19 + architecture DD-23c-②: 원문은 영속되지 않으므로 세션 안에 표시 자리가 있어야 P1 이 성립한다 S-08 과 같은 조합 + 고정폭 서체(§7.3) — [UX-D-22] (#32)
좌측 위임 DelegatedTask 목록 = 복귀 보드(§3.3) [도출] C-04 + P1 CocodeVirtualList + Status/Badge
우측 Task Inspector — diff·검증 로그·승인·롤백 [도출] AC-01·AC-02·AC-19 가 요구하는 세 동작의 상주 거처 혼합
상태바 실행중/승인대기/실패 수, edit_locks 크기, 보존 범위 [UX-D-01] CocodeStatusBar — CoUI 에 상태바 컴포넌트가 없다(§6.2)

[UX-D-01] 위임·검토·롤백을 우측 상주 패널에 둔다 — 모달로 띄우지 않는다. 근거: C-04 가 요구하는 것은 "자리를 비울 수 있음"이고, 그러면 돌아왔을 때 에디터를 덮지 않고 검토가 진행돼야 한다. 모달은 편집과 검토를 배타적으로 만들어 P3 를 깬다.

2.2 세 개의 1급 동작이 사는 곳 — 진입점은 각각 2개 이상

동작 주 진입점 보조 진입점 근거
위임 생성 좌측 위임 탭 상단 [+ 위임] 커맨드 팔레트(§8.1) · 파일 트리 우클릭(선택 파일 문맥) [경계] FR-201
검토(diff) 작업을 여는 행위가 곧 diff 를 여는 행위다 — 위임 목록 행을 열면 Inspector 안 diff 영역에 변경된 모든 파일의 diff 가 즉시 표시되고, 중앙 탭으로 확대할 수 있다 커맨드 팔레트 · 파일 트리의 변경 배지 [경계] AC-01
되돌리기 diff 화면의 스냅샷 타임라인 Inspector [롤백] · 실패 배너 안 [롤백] [경계] AC-02, AC-19
워크스페이스 생성 (#88) 첫 실행 화면(S-17)의 [새 워크스페이스 만들기] — 워크스페이스가 0건이면 이 화면이 곧 앱의 첫 장면이라 진입점을 찾을 필요가 없다 메뉴바 File › 새 워크스페이스… · 커맨드 팔레트(§8.1) [경계] AC-05·AC-13 이 담당 화면 S-14 를 요구하는데 도달 경로가 명세에 0건이었다 (#88)

정정. 초판은 diff 를 [전체 diff 열기] 버튼 뒤에 두었다. AC-01 의 Then 은 "When 사용자가 해당 작업을 화면에서 열면, Then 변경된 모든 파일의 diff가 표시된다" 이므로, 여는 것과 표시되는 것 사이에 추가 조작이 끼면 AC-01 이 성립하지 않는다. 중앙 탭 확대는 이미 표시된 것을 넓히는 보조 동작이지 표시의 전제가 아니다.

2.3 도킹 규칙 — CoUI Resizable 계약의 실제 한계 위에서

  • 분할은 중첩 Resizable 로 구성한다 — 바깥 CoreResizableDirection.horizontal 3-pane, 중앙 안쪽 vertical 2-pane. 근거: cc-coui/skills/coui-resizable/SKILL.md ### Three-pane layout(114행) · ### Vertical split with constraints(90행) · ### Nested layout (IDE pattern)(159행).

확인한 계약 한계 3가지 (Widget API 표 184~192행 + 302~304행):

# 계약 사실 원문 근거 귀결
L1 파라미터는 panes·direction·onResize·showDragHandle·resizableStyle 뿐 — controlled sizes 입력이 없다 Widget API 표 코드로 비율을 다시 적용할 수 없다. initialSize 는 마운트 시 seed 뿐
L2 크기는 0.0~1.0 flex 비율 전용 initialSize: 0.3 = 30% (51행) "사이드바 240px 고정" 을 표현할 수 없다
L3 드래그가 인접 패널의 minSize/maxSize 를 넘기면 delta 전체가 거부되고 clamp 되지 않으며 onResize 도 호출되지 않는다 304·333행 사용자 조작이 조용히 삼켜진다
  • [UX-D-02] 패널 비율은 onResize 로 워크스페이스별 저장하고, 복원은 다음 마운트의 initialSize 주입으로만 한다. L1 때문에 실행 중 재적용 경로는 없다. 워크스페이스 전환 시 레이아웃 복원이 필요하면 해당 서브트리를 새 key 로 재마운트한다.
  • [UX-D-03] MVP 도킹 범위 = 고정 슬롯 + 크기 조절 + 패널 표시/숨김.
    • "접기"는 0 으로 줄이는 것이 아니라 마운트 트리에서 제거하는 것이다 — L1·L3 때문에 Resizable 로는 0 까지 접을 수단이 없다. 패널을 숨기면 panes 목록에서 빠지고, 다시 표시하면 저장된 비율로 재마운트된다.
    • 0 으로 접었다 펴는 애니메이션, 픽셀 고정 폭, 실행 중 레이아웃 복원이 필요해지면 CocodePaneHost(§6.2) 또는 CoUI 확장(§12)이 필요하다.
    • 자유 부유창·탭 드래그 재배치·패널 위치 교환은 MVP 밖. 근거: AC-03 은 세 요소의 제공만 요구하고 배치 자유도를 요구하지 않는다. 이는 Seed Spec 이 금지한 것이 아니라 이 문서의 범위 결정이다.
  • 창 분리·네이티브 도킹은 이 문서가 다루지 않는다. D-022 가 Flutter master 채널 + windowHandle 네이티브 API 사용을 결정했고 그 능력의 UX 범위는 아키텍처 문서 몫이다. MVP 셸은 단일 창을 전제한다.
  • 창 크기 하한과 레이아웃 붕괴 임계값: 이 문서가 정하지 않는다. 누가 언제 — 로드맵 1단계 최소 셸 스파이크(A-06) 조립 후 Design 이 실측으로 정한다.

2.4 상태바가 보여주는 것

칸 값 출처
워크스페이스 이름 §3 Workspace
작업 카운트 실행중 · 승인대기 · 실패 §3 DelegatedTask.status
잠금 잠긴 파일 수 §3 Workspace.edit_locks 의 크기 (DD-13 으로 경로 → 리스 사상 — §10-20). ⚠️ EditLockRegistry.startupSweepCompleted 가 true 가 된 뒤에만 렌더한다(D-048, #78): 해제 트리거 3 스윕 전에는 0 도 그리지 않는다 — 0 은 「잠긴 파일이 없다」는 사실 주장인데 그 값이 아직 확정되지 않았고, 반대로 그 시점의 실제 크기를 그리면 유령 잠금 수가 화면에 뜬다
보존 되돌림 가능 범위(§4.5) §3 속성이 아니다 — §4.5 R1~R3 이 정의하는 보존 정책의 파생값이며, 정책 자체가 미확정이다

초판 표제 "전부 §3 속성에서 옴"은 사실이 아니었다. 보존 칸은 §3 에 대응 속성이 없다.

Git 브랜치·변경 표시는 넣지 않는다 — Discovery ## Ideation 의 셸 구성 요소 나열(cocode_ade (Flutter 데스크톱 셸: 에디터·터미널·파일트리·도킹·Git))에 Git 이 있으나 §4 에 대응 인수 경계가 없다. MVP 포함 여부는 Planning 이 정한다.


2.5 첫 실행과 빈 상태 — 아무것도 없을 때 무엇이 보이는가 (#88)

초판 §10 인벤토리 17행 어디에도 첫 실행·빈 상태 화면이 없었고, §2.2 진입점 표는 3행뿐이라 S-14 에 도달할 경로가 명세에 0건이었다. 그 공백을 닫는다.

[UX-D-30] 첫 실행 진입 화면(S-17)을 신설하고, 워크스페이스 생성의 진입점을 「첫 실행 화면 + 메뉴바 + 커맨드 팔레트」 셋으로 둔다.

AC-03(seed:105)은 "애플리케이션 실행 시 에디터·파일트리·터미널 제공" 을 요구하는데, 워크스페이스가 없는 상태의 표시가 미규정이라 현 문언으로는 판정이 갈린다(빈 에디터를 띄우는 것도, 아무것도 안 띄우는 것도 문면을 만족한다). S-17 은 그 판정을 하나로 고정한다 — 세 표면의 자리는 유지하되 각 자리에 빈 상태를 그리고, 화면 가운데에 워크스페이스 생성으로 가는 단일 주 동작을 둔다.

메뉴바 항목의 라벨은 새 워크스페이스…(File 메뉴)다. ux-spec:514·§6.5 가 Menubar 를 1단 flat(action|divider 2종)으로 제약하므로 서브메뉴를 쓰지 않는다. 지금까지 문서에 메뉴 항목 목록이 0건이었고, 이 줄이 그 목록의 첫 항목이다.

⚠️ 「기존 워크스페이스(로컬 폴더) 열기」는 이 판본의 범위가 아니다 — 미정 · 결정 필요. seed-spec §4 인수 경계 21건 어디에도 기존 워크스페이스를 여는 조항이 없다(AC-05·AC-13 은 생성만 다룬다). 이 결정이 첫 실행 화면의 주 동작 버튼이 1개인지 2개인지를 바꾸므로, 결정 이전 판본은 생성 경로만 규정하고 그 사실을 여기 명시한다(§12 등재).

[UX-D-31] 빈 상태는 세 칸(보이는 것 · 다음 동작 라벨 · 그 동작이 여는 화면)을 모두 채운 계약으로만 규정하고, 문구는 승인 주체가 정해질 때까지 «자리표시자»로 표시한다.

칸을 비우면 구현자가 채우게 되고, 그 순간 문구·동작·도착지가 화면마다 갈린다. 반대로 지금 문구를 확정하면 판정 주체 없는 산출물이 된다 — 근거 문서에 UX 문안 기준이 0건이다. 그래서 자리와 동작은 확정하고 글자는 잠정으로 둔다.

자리표시자 표기는 «…» 로 감싸 적는다. 이 표기 규칙은 이 절이 단독으로 정의하고, 빈 상태를 그리는 다른 Story(#89 의 S-09 빈 diff 등)는 소비만 한다.

빈 상태 ① 화면에 보이는 것 ② 다음 동작 버튼의 정확한 라벨 ③ 그 버튼이 여는 화면
ⓐ 워크스페이스 0건 — 메인 셸 (S-01) 첫 실행 진입 화면 S-17: 3열 골격과 상태바는 그대로 두고 파일 트리·에디터·터미널 자리에 각각 EmptyState.compact, 중앙에 주 동작 1개. 상태바 워크스페이스 칸은 «워크스페이스 없음» [새 워크스페이스 만들기] S-14 워크스페이스 생성
ⓑ DelegatedTask 0건 — 복귀 보드 (S-06) 버킷 머리를 하나도 그리지 않고(빈 버킷 머리는 「있었는데 사라졌다」로 읽힌다) 목록 자리에 EmptyState.compact 하나. 배지 카운트 줄은 그대로 그린다 — 승인대기 0 · 실패 0 은 「지금 없다」는 사실이다(§2.4 의 작업 카운트 규칙과 같은 이유) [+ 위임] (§2.2 주 진입점과 같은 라벨) S-05 위임 생성 다이얼로그
ⓒ 스냅샷 0건 — 타임라인 (S-10) 「작업 시작 직전 상태」 노드만 그리고 그 아래 스냅샷 행이 0건, EmptyState.compact 와 되돌리기 비활성 + 사유(#89 UX-D-28 문구를 소비한다) [닫기] 없음 — 호출한 화면(S-07 Inspector 또는 S-09)으로 돌아간다
  • 표현 수단은 CoUI EmptyState(CoreEmptyStateVariant — normal, compact · §6.1 에 이미 채택)뿐이며 신설 컴포넌트도 CoUI 확장(Rung 4)도 필요하지 않다. 세 칸이 요구하는 것은 제목·설명·동작 하나이고 그 셋이 전부 EmptyState 계약 안에 있다 — 그래서 §6.2 신설 목록에 더할 항목이 0건이고 §12 의 「CoUI 확장 승인 가능 여부」 목록도 늘지 않는다.
  • ⓒ 는 flow-permutation §6.3 N-1(편집 0건 작업의 빈 diff 목록)과 같은 근원이지만(편집이 0건이면 EditSnapshot 도 0건) 관찰 대상이 다르다 — N-1 은 AC-01 계열의 diff 목록이고 ⓒ 는 AC-02 계열의 스냅샷 타임라인이다. 그래서 이 문서는 N-1 을 고치지 않고(그것은 #89 소유) flow-permutation §6.3 에 신규 항목 N-6 을 더해 그 행에서 N-1 을 참조만 한다.
  • ⛔ 범위 제외 확인: 위 계약 어디에도 코드 뷰 없이 자연어만으로 조작하는 경로가 없다. 세 빈 상태의 다음 동작은 전부 화면을 여는 것이고(S-14 · S-05 · 복귀), 자연어 입력으로 작업을 수행하는 진입점을 만들지 않는다 — C-01(seed:60)이 드리머 모드를 MVP 이후로 순연했고 AC-04(seed:106, Must-Not)가 그 부재를 요건으로 잠갔다. S-05 의 prompt 는 «에이전트에게 맡길 일»을 적는 칸이지 앱을 조작하는 명령줄이 아니다.

3. 위임 흐름 UX (b)

3.1 위임 생성 다이얼로그

┌─ 작업 위임 ────────────────────────────────────────────────┐
                    │ 무엇을 맡깁니까?                                            │
                    │ ┌────────────────────────────────────────────────────────┐ │
                    │ │ LoginPage 의 폼 검증을 UseCase 로 분리해줘              │ │
                    │ └────────────────────────────────────────────────────────┘ │
                    │                                                            │
                    │ 완료 방식        ○ 자가 검증 후 자동 완료   ● 사람 승인 후 │
                    │   ⓘ 자가 검증 신뢰도(A-02) 기준이 아직 확정되지 않아       │
                    │      기본값이 '사람 승인'입니다.  (AC-17)                  │
                    │      [잠금 아이콘] ← 변경 가능 여부는 D-18 확정에 종속     │
                    │                                                            │
                    │ 에이전트        ● agent   ○ acp                  │
                    │ 프로바이더      [ ⟨목록⟩            ▾ ]                   │
                    │                                   [취소]   [위임하고 나가기]│
                    └────────────────────────────────────────────────────────────┘
                    
  • 입력 필드 4종 = prompt · completion_mode · agent_backend_kind · agent_backend_provider. created_by 는 기록되는 값이지 입력이 아니다. [경계] FR-201
  • 프로바이더 필드의 의미는 agent_backend_kind 에 종속한다 — cocode_agent 면 LLM 프로바이더(AC-06: 2개 이상), cocode_acp 면 연결된 ACP 에이전트(AC-06: 1개 이상). 한 필드가 두 값 집합을 갖는다.
  • 구체적 프로바이더 이름을 이 문서가 고정하지 않는다. Seed Spec §4 출처표: "구체적 프로바이더 조합(Anthropic + OpenAI 호환 게이트웨이)은 D-017이 정한 구현 선택이며 이 경계의 일부가 아니다." 목록은 런타임 설정에서 온다.
  • 기본값 사람승인 + 그 사유 한 줄. [경계] AC-17 / FR-308
  • override 토글은 렌더하되 활성화 여부는 D-18(PRD §4)에 종속한다. AC-17·C-04 는 기본값만 규정하므로, 활성화를 이 문서가 정하면 스펙을 넓히는 것이 된다. [UX-D-04]
  • CTA 문구가 "위임하고 나가기"인 이유: P1. 이 다이얼로그의 성공은 "머무름"이 아니라 "떠남"이다. [UX-D-05]

3.2 status 7종 → 화면 표현 (판정이 개입하지 않는 1:1 표)

status Status 점 색 목록 행 Inspector 주 동작 근거
대기 neutral 회색 · 백엔드 배지 (없음) §3
실행중 info Progress 부정형 + 잠금 칸 3값(잠금 N · 잠금 대기 · 빈칸 — 파일명 아님, 아래 주) diff 보기(P3) AC-01, BDD F1, #77
자가검증중 primary 검증 5종 체크리스트 진행 diff 보기 · 검증 로그 C-04, FR-301
사람승인대기 warning pending_approval_kind 로 카드 종류 분기 §5 AC-10/AC-11
완료 success 변경 파일 수 diff 보기 · 롤백 AC-02
실패 error 사유(아래 규칙) + 편집 잔존 표시 diff · 롤백 · 유지 AC-19, AC-07/08/20
롤백됨 secondary 되돌린 스냅샷 범위 diff 보기(이력) 불변식 5
  • CoreStatusColor 전체 집합은 neutral, primary, secondary, tertiary, info, success, warning, error 8종(cc-coui/skills/coui-status/SKILL.md 86~97행 — "full set")이고 status 는 7종이므로 색이 모자라지 않아 1:1 사상이 가능하다.
  • 색만으로 상태를 전달하지 않는다 — 점 + 한국어 상태어를 항상 함께 놓는다. 근거: WCAG 2.x SC 1.4.1 Use of Color.
  • Status 계약에 진행 모션이 없다 — 파라미터는 color·size·semanticLabel·statusStyle 뿐이다(coui-status Parameters 표). 실행중·자가검증중의 "지금 돌아가는 중" 신호는 별도 Progress(부정형) 또는 CocodeStateIndicator(§6.2)가 담당한다.

[UX-D-20] 실행중 행에 편집 대상 파일명을 표시하지 않는다 — 표시할 근거 속성이 없다. Seed Spec §3 에서 잠금 상태를 보유하는 것은 Workspace.edit_locks(경로 집합)이고, 그 경로가 어느 DelegatedTask 의 것인지 가리키는 속성이 §3 어디에도 없다. 초판이 그린 T-048 실행중 lib/c.dart 는 §3 에 없는 귀속을 전제한다 — P2 위반이다. 따라서 MVP 행은 잠금 보유 여부(있음/없음)만 표시하고, 파일명 표시는 작업↔잠금 귀속 속성이 추가된 뒤로 미룬다 → §12 미결.

📌 2026-09-12 (#77) — 이 보류의 사유는 소멸했다. 판정은 아직 남아 있다. architecture §4.5 DD-13 이 edit_locks 를 경로 집합에서 경로 → 리스(ownerTaskId·ownerSessionId·renewedAt)로 바꾸면서, 「어느 DelegatedTask 의 것인가」를 가리키는 속성이 생겼다(EditLease.ownerTaskId). 남은 것은 데이터 공백이 아니라 「파일명을 그릴 것인가」라는 UX 판정 하나이며, 그 판정 주체는 §12 표 그대로다. #77 은 그 판정의 소유자가 아니므로 뒤집지 않고 사실만 기록한다.

[UX-D-23] 실행중 행의 잠금 칸은 세 값을 갖는다 (#77). 잠금 N(보유 — edit_locks 중 ownerTaskId 가 이 작업인 항목 수) · 잠금 대기(리스 획득을 기다리는 중) · 빈칸(둘 다 아님). 판정 입력이 둘 다 조회이고 판정이 아니므로 §3.2 표제(「판정이 개입하지 않는 1:1 표」)를 깨지 않는다.

  • 두 값이 동시에 참일 수 없다 — 한 작업은 한 번에 한 게이트 연산만 진행하고(게이트 runSerially), 그 연산은 필요한 리스를 다 얻은 뒤에 진행한다. 배타는 규칙이 아니라 구조의 따름정리라 화면이 둘 중 하나를 고를 일이 없다.
  • 색·상태어는 그대로다 — 대기 중인 작업도 status 는 실행중 이므로 info 점과 한국어 상태어가 바뀌지 않는다(WCAG SC 1.4.1 이중화 유지). 잠금 대기가 별도 status 값을 얻지 않는 근거는 docs/state-machine-cocode.md §4(#16 — 폐쇄 집합에 새 값 없음)다.
  • 예상 대기 시간과 대기 순번은 그리지 않는다 — 전자는 계산할 입력이 없고(소요 분포 측정 장치 없음 · DelegatedTask 에 시각 속성 없음 — UX-D-07 과 같은 뿌리), 후자는 계산은 가능하나 읽는 사람의 행동을 바꾸지 않는다(잠금 대기는 사람의 개입 없이 자동 해소되므로 UX-D-07 의 차단성 1차 키에서 별도 버킷을 얻지 못한다). 규칙·근거 전문은 docs/edit-lock-queue-cocode.md §5.

실패 사유 표시 규칙 (정정)

  • Seed Spec/PRD 가 규정한 실패 진입 경로는 3종이다 — 재시도 상한 초과(AC-07 / PRD 흐름5 E-1) · 시간 상한 초과(§3 불변식 4 / E-2) · 프로바이더·ACP 응답 불가(AC-20 / E-3). (E-3 이 "실패"인 것은 AC-20 문면이 아니라 PRD 의 연역이다 — AC-20 은 "종결 상태로 전이"만 규정한다. [도출])
  • 📌 2026-09-13 (#73 / D-055) — 네 번째 진입 경로가 생겼다: E-4 «환경 실패 상한 초과». 검증 실패는 이제 failure_class 폐쇄 5종으로 분류되고(docs/verification-failure-class-cocode.md §3), 환경 실패 4종은 retry_count 를 증가시키지 않는 대신 별도 상한을 소진하면 실패로 전이한다(같은 문서 §4·§5). 화면 규칙은 바뀌지 않는다 — E-4 의 사유도 폐쇄 라벨에서 고른다: failure:env_tool_unavailable(검증 도구를 찾지 못했습니다) · failure:env_tool_aborted(검증 도구가 결과를 내지 못하고 종료했습니다) · failure:env_network_unreachable(네트워크에 연결하지 못했습니다) · failure:policy_host_blocked(허용 목록에 없는 호스트로의 요청이 차단되었습니다 — AC-14 ⓑ). 마지막 하나는 사람이 allowed_hosts 를 고쳐야 풀리므로 재시도하지 않고 즉시 이 경로로 온다. 문장을 지어내지 않는다는 규칙은 그대로다. ⚠️ 코드 집합의 SSOT 는 verification-failure-class-cocode.md §3.1 하나이고, 이 자리가 소유하는 것은 한국어 라벨뿐이다 — 코드를 여기서 더하거나 빼지 않는다(UX-D-23 의 스캐폴딩 사유 코드와 같은 소유 분할). [UX-D-25]
  • 그러나 이 집합은 폐쇄가 아니다. 에이전트 비정상 종료 경로가 있고, 그 작업 자신의 status 는 규정되지 않았다(AC-18 은 잠금만 규정 — PRD 흐름 5 미결 A). 그 작업이 실패로 표시되면 E-1~E-4 중 어느 것도 아니다.
  • 📌 #73 이후 「사유 미규정」 자리표시자가 남는 경우는 이 하나뿐이다(같은 문서 §6 이 명시 열거). 미정 — 결정 필요(판정 주체: Design — architecture-cocode.md §9 미결 8 · 이 문서 §12 · PRD 흐름 5 미결 A). ⚠️ 중지됨·거부됨(D-032 · AC-22·AC-23)은 실패 가 아니다 — 별개 종결 상태이고 이 규칙의 대상이 아니다(화면은 #71·#85 소관).
  • 따라서 화면 규칙은 이렇게 된다: 사유는 규정된 3종 중 하나를 고르거나, 어느 것도 아니면 "사유 미규정" 자리표시자를 그린다. 문장을 지어내지 않는다. 자리표시자가 뜬다는 것은 스펙 공백이 사용자에게 도달했다는 뜻이며, 그 공백은 §12 에 추적된다.
  • retry_count 는 n/3 으로 표시한다. 3 은 §4 출처표 등재 수치(D-008 + cc-product references/bmad-config.md feedback.maxRetries: 3).
  • ~~"작업 중단/취소" 버튼을 두지 않는다.~~ ⛔ 폐기됨 (2026-09-10, D-032 / 이슈 #105). 이 결정이 닫는 docs/flow-permutation-cocode.md 항목은 C-5(「부재 중 무한 체류를 막는 상한이 편집 단계·작업 총량·잠금 대기 어디에도 없다」)이며, C-5 의 네 지점 전부에 대한 처분은 #71 / D-059(docs/stop-and-limits-cocode.md)와 #77(잠금 축)이 끝냈다. Seed Spec v3.3.0 이 status 폐쇄 집합을 9종으로 개정해 중지됨·거부됨 을 신설했고, AC-22(실행 중 중지) · AC-23(승인 거부)가 중단 수단을 Must 로 요구한다. 아래 논거는 성립하지 않는다 — AC-08 의 Given 이 "자가 검증 시도가 진행 중일 때"로 한정돼 편집 단계·잠금 대기를 덮지 못하기 때문이며, 이것이 breakdown-cocode.md C-1 과 flow-permutation C-5 가 지적한 바다. 중지·거부 UI 는 #71·#85 가 설계한다. (이하 원문 보존) status 값 집합 7종에 취소가 없어(seed-spec 전문 grep — 취소는 AC-08 의 "시도가 중단되고"와 PRD 미결 서술에만 등장) 중단을 표현할 상태가 없다. 안전성은 다른 경로가 담보한다 — AC-07(재시도 3회 상한)과 AC-08(양의 유한한 시간 상한)이 작업의 자동 종료를 보장하므로 중단 수단 부재가 무한 점유로 이어지지 않는다. 필요하다면 Seed Spec 개정 사항이다. [UX-D-06]

3.3 돌아왔을 때 먼저 보는 것 — 복귀 보드

┌ 위임 ─────────────────────────────────┐
                    │ ⚠ 승인 대기 3   ✕ 실패 1   ▶ 실행중 2 │  ← 앱 포커스 회복 시 이 탭으로 전환
                    ├───────────────────────────────────────┤
                    │ ▌승인 대기 · 테스트 변경 (1)          │  ① 적용 전에 멈춰 있음
                    │  ● T-051  test/payment_test.dart 외 1 │     (경과 시간 없음 — 아래 주)
                    ├───────────────────────────────────────┤
                    │ ▌승인 대기 · 완료 (2)                 │  ② 편집은 이미 적용됨
                    │  ● T-042  3파일 · 마지막 편집 12분 전 │
                    │  ● T-039  1파일 · 마지막 편집 41분 전 │
                    ├───────────────────────────────────────┤
                    │ ▌실패 (1)                             │  ③ 편집이 남아 처분 대기
                    │  ● T-044  재시도 상한 초과 (3/3)      │
                    │           편집 2파일 남아 있음        │
                    ├───────────────────────────────────────┤
                    │ ▌진행 중 (2)                          │  ④
                    │  ● T-047  자가검증중 ②테스트          │
                    │  ● T-048  실행중  잠금 1              │
                    ├───────────────────────────────────────┤
                    │ ▌종결 (5)                        [접힘]│  ⑤⑥
                    └───────────────────────────────────────┘
                    

[UX-D-07] 복귀 보드 정렬은 폐쇄 키로만 이뤄지며, 정렬 키와 표시 값을 분리한다.

  • 1차 키 = (status, pending_approval_kind) 버킷 — 위 ①~⑥ 순서. 두 값 모두 폐쇄 집합이므로 판정이 개입하지 않는다.
  • 버킷 순서의 근거 [도출]: 사람승인대기·테스트변경승인은 변경을 적용하기 전에 전이하고(FR-404/AC-11, 불변식 3), status 는 단일 값이므로 그 작업은 실행중이 아니다 → 진행이 멈춰 있다. 완료승인은 편집이 이미 적용된 상태에서 확정을 기다린다(AC-10 + PRD 흐름 3-A 5단계). 실패는 편집이 남아 처분을 기다린다(AC-19). 차단성이 큰 순서다.
  • 2차 키 = 버킷 안에서만 최신 EditSnapshot.timestamp 내림차순. 스냅샷이 없는 작업은 버킷 밖으로 밀지 않고 그 버킷의 끝에 task_id 안정 정렬로 둔다.
    • 초판은 "스냅샷이 없으면 맨 뒤"라고 적었다. 그러면 이 문서가 가장 차단성이 크다며 맨 위에 둔 버킷 ①의 항목이 자기 규칙에 의해 맨 뒤로 밀린다 — 버킷 ①은 정의상 적용 전이라 그 변경의 EditSnapshot 이 없기 때문이다. 1차 키가 항상 2차 키를 이긴다.
  • 경과 시간("12분 전")은 EditSnapshot 이 있는 작업에만 표시한다. 없으면 그 자리를 비운다. 지어내지 않는다.
  • 이 모든 제약의 뿌리: DelegatedTask 에 시각 속성이 없다 — PRD §3.4 가 "§3 의 DelegatedTask Attributes 에 시각 속성이 없다(EditSnapshot 에만 timestamp)" 라고 기록하며 "필요 시 Design 이 추가" 로 남겼다. 복귀 보드가 P1 을 제대로 지원하려면 작업 생성·전이 시각이 필요하다 — 이 문서는 그 속성 추가를 Design 데이터 모델에 요청한다 → §12 미결.

[UX-D-08] 알림(OS/푸시)은 MVP 범위 밖이다. 근거: 근거 문서에 알림 요구가 0건이다(docs/*.md 11개 파일 전수 grep — 알림 0건, notification 0건). C-04 는 "사람의 실시간 관찰 없이" 를 요구할 뿐 통지를 요구하지 않는다. MVP 는 복귀 시 인지(pull) 를 보장한다 — 앱 포커스 회복 시 자동 탭 전환 + 배지 카운트 + 상태바. 푸시가 필요한지는 MVP 출시 후 Planning 이 사용자 관찰로 정한다.

3.4 진행 중 관찰 — 검증 로그 패널

┌ 검증 로그 · T-047 ────────────────────────────────────────┐
                    │ ① 빌드 성공          ✓  (소요 시간)                       │
                    │ ② 테스트 통과        ⟳  진행 중                           │
                    │ ③ 핫 리로드 무오류   —  적용 불가 [사유코드]  ← D-2 종속  │
                    │ ④ 정적 분석 통과     ✓                                    │
                    │ ⑤ 파일 무결성        —  ①~④ 중 적용 가능한 것이 있어 미사용│
                    │ ───────────────────────────────────────────────────────── │
                    │ 원문 → [문제] 탭 · 이 세션에서만 볼 수 있습니다           │
                    │   — 워크스페이스를 닫거나 앱을 다시 열면 개수·종료        │
                    │     코드만 남습니다                                       │
                    └───────────────────────────────────────────────────────────┘
                    
  • 5종 목록과 순서는 C-04 원문 그대로(폐쇄 집합 — §4 출처표: "이 문서가 정의하는 폐쇄 집합").
  • ⑤ 행 문구 정정: C-04 는 ⑤를 "①~④가 모두 적용 불가한 편집에 한해" 로 규정한다. 따라서 미사용 사유는 "통과가 있어서"가 아니라 "적용 가능한 것이 있어서"다.
  • ⑤로 완료한 경우 ①~④ 각각의 적용 불가 사유를 표시한다(AC-09 / FR-303). 사유는 자유 서술이 아니라 폐쇄 코드이며, 그 코드 집합은 D-2 미결이다 → UI 는 코드 + 사람 읽는 라벨 슬롯만 정의하고 값은 D-2 확정에 종속시킨다.
  • ③의 관찰 창, ⑤의 정본 파서, ④·⑤의 "새로운 오류" 기준선은 D-12 미결 — 화면은 결과만 표시하고 판정하지 않는다.
  • 원문 표시 슬롯은 이 패널에 두지 않는다 — 하단 [문제] 탭(S-08b)으로 연결하고, 패널 하단에 고지 1줄을 둔다. 고지 문구는 architecture DD-23c-② 의 버퍼 상태 3종(A 있음 / B 이전 세션 / C 세션 상한으로 정리됨)에 1:1 로 붙는 고정 문자열이며 화면은 판정하지 않는다(P2). 위 목업의 문구는 A 다. 원문을 영속하는 경로는 없다 — 다음 세션에서 필요하면 터미널(S-04)에서 같은 검증을 다시 실행해 재현한다(검증은 결정적이라는 전제, state-machine §3). [UX-D-22] (#32)
  • 회차: 패널은 verification_log 의 현재 회차(attempt_no == retry_count)를 기본으로 그리고, 앞 회차의 결과와 원문은 [문제] 탭의 회차 축에서 본다(architecture DD-23c-③ — 완료 판정도 현재 회차만 본다). 회차별 누적은 기록의 형태이지 화면이 계산하는 값이 아니다.

4. diff 검토와 롤백 (c)

4.1 다중 파일 diff — 한 작업이 편집한 전부를 한 화면에

┌ T-042 diff ──────────────────────────────────────────────────────────────────┐
                    │ 보기: ● 작업 전체   ○ 스냅샷 단위        [작업 시작 직전 상태로 되돌리기]    │
                    ├──────────────────────┬───────────────────────────────────────────────────────┤
                    │ 변경 파일 3          │  lib/features/login/login_page.dart                   │
                    │ ─────────────────    │  ┌──────────────────────────────────────────────────┐ │
                    │ ▸ login_page.dart    │  │  (unified diff · 구문 강조 · 가로 스크롤)        │ │
                    │ ▸ login_bloc.dart    │  │                                                  │ │
                    │ ▸ ci.yaml            │  └──────────────────────────────────────────────────┘ │
                    │                      │           [ CocodeDiffView — IDE 전용 ]                 │
                    └──────────────────────┴───────────────────────────────────────────────────────┘
                    
  • AC-01 의 "모든 파일" 은 좌측 목록이 담보한다. 목록은 그 작업의 EditSnapshot 을 file_path 로 묶은 것이다.
  • 두 보기 축이 필요한 이유 [도출]: AC-01 은 작업 단위 diff 를 요구하고, AC-02 는 특정 스냅샷 으로의 롤백을 요구한다 → 스냅샷 경계를 고를 수 있어야 한다. 두 축을 한 화면에서 토글한다.
  • 비-Dart 파일(ci.yaml)도 같은 목록에 나온다 — C-03 / AC-05 후단 / FR-104.
  • 종결 상태가 아니어도 열린다(BDD Feature 1 두 번째 시나리오). 실행 중 작업의 diff 는 "지금까지"임을 배너로 명시한다.
  • ⚠ 이 화면은 적용된 편집만 담는다. 테스트변경승인 대기 중인 미적용 변경은 여기 없다 — 그 변경은 §5.2 의 승인 카드가 담당하며 데이터 출처가 다르다(UX-D-19).

생성·삭제·이름변경의 표시 [도출 — architecture §4.7 DD-25 의 경로별 투영 전이에서] · 라벨·배지 어휘는 [UX-D-21]

  • 좌측 목록은 여전히 file_path 로 묶는다. 다만 이름변경 사슬은 한 행으로 접는다 — 행의 키는 그 작업이 남긴 최종 경로이고, 같은 작업 안에서 previous_path 를 거슬러 올라간 최초 경로를 함께 표기한다(a.dart → b.dart). 이름변경의 이전 경로 투영(H→∅)은 별도 "삭제" 행이 되지 않고 행 라벨 계산에서도 제외한다 — 그 전이는 old → new 행이 표현한다.
  • 행 라벨은 그 행에 대한 첫 투영 전이의 base 상태와 마지막 투영 전이의 result 상태 두 값만으로 정해진다(∅ = 부재). 화면은 그 밖의 것을 계산하지 않는다.
(첫 base, 마지막 result) 배지 행 라벨 우측 diff 창
(H1, H2) M path unified diff — 현행
(∅, H) + path 전량 추가 hunk(빈 내용 대비). 배너: "이 파일은 이 작업이 만들었습니다 — 되돌리면 삭제됩니다"
(H, ∅) − path 전량 삭제 hunk. 배너: "이 파일은 이 작업이 지웠습니다 — 되돌리면 복원됩니다"
(∅, ∅) ± path hunk 없음. 배너: "이 작업 안에서 만들고 지웠습니다 — 순변경 없음". 스냅샷 단위 보기로 안내
이름변경 사슬 포함 위 표의 배지 그대로(내용 변경이 없으면 R) old → new 내용 변경이 없으면 hunk 없이 "경로만 변경 — 내용 동일". 같은 작업이 이후 수정했으면 그 diff
  • 스냅샷 단위 보기에서는 접지 않는다 — 각 스냅샷이 자기 종류(M/+/−/R)로 한 행이며, 이름변경 행은 old → new 다.
  • 배지 4종(M + − R)과 ± 는 git status 문자 관례를 차용한 것이고 색은 §6.4 토큰을 따른다 — 값을 새로 짓지 않는다.
  • 승인 대기 중 미적용 삭제·이름변경(R6 의 테스트변경승인 대상)은 여전히 이 화면에 없다(UX-D-19) — 승인 카드가 같은 어휘로 그린다.

4.2 롤백 대상 선택 — 스냅샷 타임라인

┌ 되돌리기 · T-042 ────────────────────────────────────────────────────────────┐
                    │                                                                              │
                    │  ○ ▲ 작업 시작 직전 상태            ← 이 작업의 EditSnapshot 전부를 되돌림   │
                    │  │                                     (불변식 4: 파일별 최소 sequence_no의  │
                    │  │                                      base_content_hash 로 복원)           │
                    │  ● seq 1  login_page.dart           ← 선택                                   │
                    │  ┆ seq 2  login_bloc.dart           ┐                                        │
                    │  ┆ seq 3  login_page.dart           ├ 함께 되돌아감 (불변식 3)               │
                    │  ┆ seq 4  ci.yaml                   ┘                                        │
                    │                                                                              │
                    │  되돌릴 집합: 스냅샷 4건 · 경로 3개                                          │
                    │  ⓘ 전부 적용되거나 전부 적용되지 않습니다. 부분 적용은 없습니다. (AC-02)     │
                    │                                              [취소]    [되돌리기]            │
                    └──────────────────────────────────────────────────────────────────────────────┘
                    
  • 선택 즉시 되돌릴 집합을 미리 보여준다 — "그 이후 같은 작업이 만든 전부"(불변식 3)라는 규칙을 사용자가 계산하게 두지 않는다.
  • 원자성 문구는 AC-02 원문 술어를 그대로 쓴다.
  • 되돌린 뒤 status: 부분 롤백 후의 status 는 단언하지 않는다 — BDD Feature 1(154행)이 명시적으로 "sequence_no 1 을 남긴 채 2·3 만 되돌린 작업이 종결 상태(§0)로 전이한다는 규정은 Seed Spec 어디에도 없다" 고 기록했다. 화면은 status 를 표시할 뿐 전이를 약속하지 않는다.

생성·삭제·이름변경의 타임라인 행과 "되돌릴 집합" 미리보기 [도출 — DD-25 R4] · [UX-D-21]

  • 타임라인 행은 스냅샷 1건 = 1행이며 종류 배지를 앞에 둔다: seq 5 + test/foo_test.dart · seq 6 − lib/old.dart · seq 7 R lib/a.dart → lib/b.dart. 이름변경은 한 행이다(DD-25 R3 — 두 행으로 그리면 그 사이에 선택 경계가 생긴다).
  • "되돌릴 집합" 요약은 스냅샷 N건 · 경로 M개 로 쓴다 — 이름변경은 경로 2개로 센다(위 와이어프레임의 "경로 3개"가 그 표기다).
  • 미리보기는 경로마다 롤백이 하는 일을 한 단어로 붙인다. 값은 DD-25 R4 의 복원 목표(그 경로의 최소 sequence_no 투영 전이의 base 상태)와 현재 상태에서 판정 없이 나온다:
복원 목표(base 상태) 표시 예
H (내용) 복원 − lib/old.dart → 복원
∅ (부재) 삭제 + test/foo_test.dart → 삭제
이름변경 되돌림(이전 경로 H · 새 경로 ∅) 경로 복귀 lib/b.dart → lib/a.dart 로 복귀 (두 경로를 한 줄로)
목표 = 현재 상태(예: 만들고 지운 파일) 변경 없음 ± lib/tmp.dart → 변경 없음

4.3 충돌 제시 — v3.1.0 판정 기준

판정 [경계] §3 EditSnapshot 불변식 2 — v3.1.0 이 세운 기준에 v3.3.0(D-036)이 작업 범위 한정을 추가했다:

ⓑ 대상 파일의 현재 내용 해시 ≠ 롤백 대상 작업이 그 파일에 남긴 마지막 EditSnapshot 의 result_content_hash → 충돌. ⓐ 그 파일의 전역 마지막 EditSnapshot 이 롤백 대상 작업의 것이 아니면(다른 작업이 그 뒤 같은 파일을 편집했으면) → 충돌. base_content_hash 는 복원 목표이지 충돌 판정 기준이 아니다. 생성·삭제·이름변경에서는 "그 파일"을 경로별 투영 전이로 읽고 "현재 내용 해시"에 부재(∅)를 포함한다(architecture §4.7 DD-25 R4).

┌ 되돌릴 수 없습니다 — 충돌 2건 ───────────────────────────────────────────────┐
                    │ 에이전트가 남긴 상태 이후에 이 파일들이 바뀌었습니다.                        │
                    │ (직접 편집하셨거나 외부 도구가 고쳤을 수 있습니다)                           │
                    │                                                                              │
                    │  ✕ login_page.dart    에이전트가 남긴 상태 ≠ 현재 내용                       │
                    │  ✕ ci.yaml            에이전트가 남긴 상태 ≠ 현재 내용                       │
                    │  ✓ login_bloc.dart    일치                                                   │
                    │                                                                              │
                    │  ⓘ 한 파일이라도 충돌하면 어떤 파일도 되돌아가지 않습니다. (AC-02 원자성)    │
                    │                                                                              │
                    │  [취소]   [충돌 파일 열기]   [현재 내용을 버리고 전체 적용]                  │
                    └──────────────────────────────────────────────────────────────────────────────┘
                    

[UX-D-09] 충돌 이후 선택지는 정확히 셋이며, 전부 집합 단위로만 동작한다. PRD 흐름 4 미결("충돌 제시 이후 사용자에게 어떤 선택지를 주는지(강제 적용 / 파일별 처리 / 취소)는 근거 문서에 규정이 없다 → Design. 단 어떤 선택지를 두더라도 AC-02의 원자성과 EditSnapshot 불변식 2의 '자동 적용하지 않는다'를 깨서는 안 된다")에 대한 이 문서의 결정이다.

선택지 동작 제약 근거
취소 아무것도 하지 않음 불변식 2 "자동 적용하지 않는다"
충돌 파일 열기 에디터로 이동. 해소 후 재시도 —
현재 내용을 버리고 전체 적용 집합 전체에 적용 AC-02 원자성

금지 [경계]: ⓐ 파일 단위 부분 적용 — AC-02 원자성 위반(PRD 가 후보로 적은 "파일별 처리"가 여기 해당한다). ⓑ 자동 3-way 병합 — 불변식 2 의 "자동 적용하지 않는다" 위반.

⚠ 강제 적용은 사람의 편집을 파괴한다. 사람이 에디터로 한 편집은 EditSnapshot 대상이 아니므로(C-02 Rationale, BDD Feature 1 "[C-02] 사람이 에디터로 직접 한 편집은 EditSnapshot 대상이 아니다") 되살릴 근거가 없다. 그래서 [UX-D-10]: 강제 적용 직전에 현재 내용을 대피 사본으로 보존하고 그 위치를 결과에 표시한다. 이 "대피 사본"은 근거 문서에 없는 이 문서의 신설 개념이며, EditSnapshot 이 아니다. 저장 위치·수명은 §4.5 의 보존 정책과 함께 Design 저장소 설계(CH-022 재검토 시점)가 확정해야 한다.

부수 사실(정보). 강제 적용 후 그 파일의 내용은 base_content_hash 목표 상태가 되므로 마지막 result_content_hash 와 다시 불일치한다. 그 작업은 이미 롤백됨이라 재롤백 대상이 아니지만, 같은 파일을 편집한 다른 작업의 롤백은 이 시점부터 충돌로 뜬다. 화면은 이를 정상 동작으로 취급한다 — 불변식 2 가 의도한 그대로다.

생성·삭제·이름변경의 충돌 문구 [도출 — DD-25 R4] · [UX-D-21]

충돌 목록의 한 줄은 ✕ path <사유> 이며 사유는 아래 표에서 (마지막 투영 전이, 현재 상태) 로 고른다. 화면은 이 표 밖의 문구를 만들지 않는다.

마지막 투영 전이 현재 상태 사유 문구
수정 (…→H) 파일 있음, ≠ H 에이전트가 남긴 상태 ≠ 현재 내용 (현행)
수정 (…→H) ∅ 에이전트가 남긴 파일이 삭제됨
생성 (∅→H) 파일 있음, ≠ H 에이전트가 만든 파일이 이후 바뀜
생성 (∅→H) ∅ 에이전트가 만든 파일이 삭제됨
삭제 (H→∅) 파일 있음 에이전트가 지운 경로에 파일이 다시 있음
이름변경 — 이전 경로 (H→∅) 파일 있음 이름변경 전 경로에 다른 파일이 있음
이름변경 — 새 경로 (∅→H) ≠ H / ∅ 이름변경된 파일이 이후 바뀜 / 삭제됨
어느 종류든 디렉터리·심볼릭 링크 등 정규 파일 아님 경로에 파일이 아닌 것이 있음
어느 종류든 (ⓐ) 전역 마지막 스냅샷이 다른 작업 것 다른 작업 {task_id} 이 이후 이 파일을 편집함 (D-036)
  • 마지막 행은 v3.3.0 이 새로 충돌로 판정하게 한 경우다(FP-304). 초판 §4.3 에는 이 문구가 없었다 — breakdown B-3 의 "UI 경로가 없다"는 이것으로 닫힌다.
  • 강제 적용(UX-D-10)의 대피 사본은 현재 상태가 파일인 경로에만 만든다 — ∅ 는 대피할 것이 없다. 이름변경 충돌에서는 두 경로 각각에 이 규칙을 적용한다.
  • 사람이 이미 목표 상태로 되돌려 둔 경우(에이전트가 만든 파일을 먼저 지운 뒤 롤백)도 위 표대로 충돌이다 — 화면이 "결과적으로 같다"를 계산하지 않는다(DD-25 R4).

4.4 실패한 작업의 검토 (AC-19)

같은 diff 화면을 재사용하고 배너만 얹는다.

┌──────────────────────────────────────────────────────────────────────────────┐
                    │ ✕ 실패 · 재시도 상한 초과 (3/3)                                              │
                    │   이 편집은 자동으로 폐기되지도, 확정되지도 않습니다.                        │
                    │   처분을 고르실 때까지 그대로 남아 있습니다.        [편집 유지]  [롤백]      │
                    │   검증 원문은 이 세션에서만 볼 수 있습니다 — 워크스페이스를 닫거나 앱을      │
                    │   다시 열면 개수·종료 코드만 남습니다.                     [문제 탭에서 보기]│
                    └──────────────────────────────────────────────────────────────────────────────┘
                    

[UX-D-11] AC-19 의 "조용히"를 UI 관찰 조건 3개로 환원할 것을 제안한다 (PRD D-15 미결에 대한 입력): ⓐ 실패 전이 시 이 배너가 뜬다 ⓑ 편집 처분 수단(유지·롤백)이 같은 화면에 있다 ⓒ 사용자의 조작 없이 편집 상태가 변하지 않는다. — 셋 다 관찰 가능하고 판정이 필요 없다. D-15 의 최종 확정은 Design 몫이며 이 제안이 그것을 대체하지 않는다.

검증 원문 고지 줄 (#32, UX-D-22). 배너의 마지막 줄은 architecture DD-23c-② 의 버퍼 상태 3종 문구 중 하나다 — 위 목업은 A(원문 있음). 앱을 다시 연 뒤 같은 작업을 열면 같은 자리에 B("검증 원문은 이전 세션에 있었습니다 — 지금은 개수·종료 코드만 남아 있습니다. 같은 검증을 터미널에서 다시 실행하면 재현됩니다")가 오고, 세션 버퍼 상한으로 정리된 경우 C 가 온다. 실패 사유 3종(§3.2)·retry_count·회차별 verification_log 요약은 영속되므로 그대로 남는다. 이 줄은 UX-D-11 의 ⓐ~ⓒ 를 바꾸지 않는다 — 원문의 유무는 편집의 처분과 무관하다.

4.5 스냅샷 보존과 "되돌림 가능 범위"의 표시 — 오너 결정 3 / CH-022

이 문서가 발견한 축 불일치를 먼저 적는다.

  • 오너 결정 3과 Contrarian CH-022 의 참고 기준은 파일 단위다 — CH-022 처분 원문(contrarian-review 144행): "Accepted (risk acknowledged) — 보존 정책은 Design 단계 저장소 설계에서 정할 구현 세부이며 … Lumide 선례(50버전/5MB per file)가 참고 기준", D-003 Rationale: "Lumide의 local_history(파일 버전 스냅샷, 최대 50버전/5MB)".
  • 그런데 롤백의 원자 단위는 작업이다 — AC-02, 불변식 3·4. 특히 불변식 4("작업 시작 직전 상태" = 파일별 최소 sequence_no 스냅샷의 base_content_hash)는 한 작업의 첫 스냅샷이 하나라도 정리되면 성립하지 않는다.
  • 따라서 파일당 50버전/5MB 를 그대로 옮겨 쓸 수 없다. 축이 다르다. 그 값을 이 문서가 채택하면 AC-02 가 보장한 능력이 조용히 사라진다.

[UX-D-12] 보존 정책의 UX 계약 3조 (값이 아니라 규칙을 정한다)

규칙 내용 근거
R1 종결 상태가 아닌 작업(대기·실행중·자가검증중·사람승인대기)의 스냅샷은 정리 대상이 아니다 [도출] 그 작업들은 아직 롤백 대상이며 AC-19·AC-02 가 살아 있다
R2 정리 단위는 파일이 아니라 작업이다 — 한 작업의 스냅샷 집합은 전부 남거나 전부 사라진다 [도출] 불변식 4. 부분 정리는 "작업 시작 직전 상태" 복원을 깨뜨린다. 판정이 필요 없는 규칙이다
R3 정리로 되돌림 가능 범위가 줄면 그 사실이 화면에 나타난다 — 목록 행의 [롤백] 이 비활성화되고 사유가 붙는다. 조용히 사라지지 않는다 [도출] AC-19 가 "조용히 폐기되지 않는다"를 세운 것과 같은 축
  • 상한의 축(작업 수 / 총 용량 / 보존 기간)과 값은 이 문서가 정하지 않는다. 누가 언제 — Design 저장소 설계(CH-022 가 지정한 재검토 시점 "Design 단계 저장소 설계", PRD §3.4·§4.2 가 이관한 상태).
  • 다만 형식 요건은 권고한다: 설치 직후 사용자 설정 없이도 상한이 유한한 값을 갖는다. 이는 AC-08 이 시간 상한에 세운 형식을 유비한 것이며, AC-08 자체는 스냅샷 보존에 대해 아무 말도 하지 않는다.
  • 상태바 되돌림 보존 칸이 R3 의 표면이다.

5. 승인 UX (d)

5.1 두 승인의 구조적 차이 — 카드가 달라야 하는 이유

축 완료승인 테스트변경승인
트리거 completion_mode=사람승인, 편집을 마친 뒤 completion_mode 무관, 기존 테스트 파일 변경을 적용하기 전
근거 AC-10, 불변식 2 AC-11, 불변식 3, C-05
편집 적용 여부 이미 적용됨 → 되돌리려면 롤백 아직 미적용 → 승인해야 적용
화면이 읽는 데이터 EditSnapshot(§3 실재) 미적용 제안 변경 — §3 에 대응 엔티티가 없다 → UX-D-19
승인의 의미 완료로 전이 그 변경이 적용됨 (PRD 흐름 3-B 5)
미승인의 의미 status 집합에 거부가 없다(Seed Spec 전문 0회 — PRD 흐름 3-A 미결이 직접 확인) → 롤백이 유일한 종결 경로 변경이 적용되지 않는다 (흐름 3-B 6). 복귀 status 는 미규정
대상 판정 — 경로 술어: test/ · integration_test/ · widgetbook/ (v3.1.0 ②, C-05·AC-11) — 파일 내용을 읽지 않고 성격도 분류하지 않는다 (FR-403)

[UX-D-19] 승인 대기 중인 미적용 변경을 담는 개념(가칭 PendingChange)은 근거 문서에 없는 이 문서의 신설이다. C-02 와 EditSnapshot 불변식 1 은 에이전트가 실제로 한 편집에만 스냅샷을 요구한다. 테스트변경승인은 FR-404/AC-11/불변식 3 에 따라 적용 전에 전이하므로, 그 시점의 변경 내용을 담는 엔티티가 §3 에 존재하지 않는다. 그런데 AC-11 이 요구하는 "사람의 명시적 승인"은 사람이 무엇을 승인하는지 볼 수 있어야 성립한다. 따라서 이 문서는 ⓐ PendingChange(대상 파일 경로 집합 + 제안 diff + 생성 시각)의 필요를 명시하고 ⓑ 이것이 EditSnapshot 이 아니며 롤백 대상도 아님을 못 박고 ⓒ 저장 위치·수명·승인 후 EditSnapshot 으로의 승격 규칙을 Design 데이터 모델 + 저장소 설계로 이관한다. §4.3 의 '대피 사본'과 같은 성격의 신설이다.

5.2 승인 큐 — 부재 중 쌓이는 곳

┌ 승인 대기 (3) ───────────────────────────────────────────────────────────────┐
                    │                                                                              │
                    │ ▌테스트 변경 승인 · 1건     ← 적용 전에 멈춰 있음. 파일 잠금 없음            │
                    │ ┌──────────────────────────────────────────────────────────────────────────┐ │
                    │ │ T-051  결제 실패 케이스 보강                                             │ │
                    │ │ 대상 2파일 ·  test/payment_test.dart                                     │ │
                    │ │ ┌ 승인 대상 변경 (CoUI CodeDiff · 읽기 전용 미리보기) ─────────────────┐ │ │
                    │ │ │  (PendingChange 의 제안 diff — UX-D-19)                              │ │ │
                    │ │ └──────────────────────────────────────────────────────────────────────┘ │ │
                    │ │ ⚠ 승인 대기 중 이 파일들은 잠겨 있지 않습니다. 직접 고치시면 나중에      │ │
                    │ │   되돌릴 때 충돌로 표시됩니다.                                           │ │
                    │ │           [변경 전체 보기]   [적용하지 않음]   [승인해 적용] (비활성)    │ │
                    │ └──────────────────────────────────────────────────────────────────────────┘ │
                    │                                                                              │
                    │ ▌완료 승인 · 2건            ← 편집은 이미 적용됨                             │
                    │ ┌──────────────────────────────────────────────────────────────────────────┐ │
                    │ │ T-042  로그인 리팩터        검증 ①✓ ②✓ ④✓   (정보이지 관문이 아님)      │ │
                    │ │        검증 원문은 이 세션에서만 볼 수 있습니다 → [문제] 탭              │ │
                    │ │           [전체 diff 보기]   [롤백]           [승인] (비활성)            │ │
                    │ └──────────────────────────────────────────────────────────────────────────┘ │
                    └──────────────────────────────────────────────────────────────────────────────┘
                    

[UX-D-13] 일괄 승인을 제공하지 않는다. 승인은 작업 1건 단위이며, 승인 버튼은 사용자가 그 작업의 승인 대상 변경 전체를 연 뒤에만 활성화된다.

  • "승인 대상 변경"의 정의는 승인 종류마다 다르다 — 완료승인 = 그 작업의 전체 diff(AC-01), 테스트변경승인 = 그 PendingChange 의 제안 diff 전체.

  • 초판은 두 경우 모두 "전체 diff"를 게이트로 삼았다. 그러면 테스트변경승인 작업이 아직 아무 파일도 적용하지 않았을 때 전체 diff 가 비어 있고, 사용자는 빈 화면을 열어 게이트를 통과한 뒤 승인한다. AC-01 의 Then 이 공허하게 참이 되는 구멍이다.

  • 따라서 게이트 조건에 비어 있지 않음을 함께 요구한다: 승인 대상 변경이 0건이면 승인 버튼이 활성화되지 않고, 그 상태는 오류로 표시된다(승인할 것이 없는데 승인 대기에 있다는 뜻이므로).

  • 근거: C-05·AC-10·AC-11 이 요구하는 것은 "사람의 명시적 승인" 이다. "명시적"의 경계를 판정으로 다투는 대신, 승인 대상을 실제로 열었는가라는 관찰 가능한 조건 하나로 환원한다 — 판정이 필요 없는 규칙(원칙 P2).

  • 완료승인 카드에서 자가 검증 결과는 정보로 표시하고 관문으로 쓰지 않는다 — FR-307 / 불변식 2. 원문은 카드에 싣지 않고 [문제] 탭(S-08b)으로 연결하며, 그 옆에 architecture DD-23c-② 의 세션 고지(A/B/C 고정 문자열)를 붙인다 (#32, UX-D-22) — 완료승인은 편집이 이미 적용된 뒤의 확정이므로, 사람이 "다음 세션에는 무엇이 남지 않는지"를 승인 전에 알아야 한다(P1).

  • 승인 대기 중 파일 잠금은 유지되지 않는다 — Workspace 불변식 2("작업이 사람의 승인을 기다리는 동안 잠금을 유지하지 않는다"). 카드가 이 사실과 그 귀결(사용자가 직접 고치면 v3.1.0 충돌 판정에 걸림)을 명시한다. [UX-D-14] — 이 인과를 알려주지 않으면 사용자는 자기 편집이 왜 롤백을 막는지 모른다.

  • 📌 2026-09-13 (#70 / D-057 · #72 / D-058) — 복귀 status 가 확정됐다. 테스트변경승인 «승인» 후에는 변경을 적용하고 항상 실행중 으로 복귀한다(테스트 대상이 바뀌었으므로 자가 검증을 처음부터 다시 탄다 · retry_count 불변). 완료승인 «승인» → 완료. [적용하지 않음] 은 부작위가 아니라 AC-23 의 «거부» 입력이며 거부됨(종결)으로 간다 — 그 변경은 적용되지 않고 이미 적용된 편집은 남는다(D-058 §2 · prd FR-407). 화면은 여전히 전이를 예고하지 않고 status 를 표시할 뿐이다. ⚠️ 완료승인 카드에도 거부 입력이 필요하다 — AC-23 은 pending_approval_kind 를 가리지 않는데 현재 완료승인 카드의 버튼열([전체 diff 보기] [롤백] [승인])에는 거부가 없다. 버튼 배치는 #85 소관이며 D-058 은 입력의 존재만 확정했다. 부분 승인은 존재하지 않는다(prd FR-409) — 승인은 대상 변경 전체에 대한 단일 판정이고 적용은 전량이거나 전무다. [UX-D-26]

5.3 부재 중 축적과 통지

  • 축적은 §3.3 복귀 보드가 담당한다 — 버킷 ① · ②.
  • 통지는 [UX-D-08] 에 따라 인앱 pull 만. 상태바 승인대기 n + 좌측 탭 배지 + 앱 포커스 회복 시 자동 전환.
  • 대기 시간 표시는 최신 EditSnapshot.timestamp 가 있을 때만 한다 — 없으면 비운다(§3.3 과 동일 이유: DelegatedTask 에 시각 속성이 없다, PRD §3.4). 테스트변경승인 카드는 대개 이 경우에 해당한다.

6. CoUI 매핑 (e)

아래 컴포넌트·타입 이름은 전부 ~/.claude/skills/cc-coui/skills/<name>/SKILL.md 실물에서 확인했다. §10 화면 인벤토리가 인용하는 컴포넌트도 전부 이 표에 등재한다 — 초판은 Card·Form·Select 를 §10 에서만 인용해 자기 규칙을 어겼다. 대조 대상: docs/coui-inventory-cocode.md §1(비실재) · §3(커버 22건) · §4(IDE 전용 15건) · §5(미검증).

6.1 그대로 쓰는 CoUI 컴포넌트 — 확인한 계약과 그 한계

용도 컴포넌트 확인한 계약 계약 한계(설계가 알아야 할 것)
도킹 분할 Resizable CoreResizablePaneData(initialSize/minSize/maxSize), CoreResizableDirection.{horizontal,vertical}, onResize → void Function(List<double>), showDragHandle controlled sizes 없음 · flex 비율 전용 · min/max 초과 delta 전체 거부(onResize 미발화) → §2.3 L1~L3
셸 골격 Scaffold (+ AppBar) headers/footers/child/sidebar 슬롯, CoreScaffoldVariant, CoreScaffoldFabLocation 상태바 전용 컴포넌트가 아니라 슬롯이다 — 내용물은 직접 조립
메뉴바 Menubar CoreMenubarMenu/CoreMenubarEntry.action(label:, shortcut:)·.divider() **entries 는 action
커맨드 팔레트 Command CoreCommandGroup/CoreCommandItem, query 는 controlled(onQueryChanged 를 되돌려 배선해야 함) 필터가 label substring 으로 하드코딩(fuzzy 훅 없음) · 결과 리스트는 SingleChildScrollView + listMaxHeight 기본 256px 로 비가상화
우클릭 메뉴 ContextMenu CoreDropdownMenuEntry.action(label:, onSelect:)/.divider() 서브메뉴 없음(Menubar 와 동일)
상태 점 Status CoreStatusColor 8종(full set), CoreStatusSize xs–xl, semanticLabel 슬롯 있음 파라미터에 진행 모션이 없다 — 지속 신호는 Progress/CocodeStateIndicator
카운트·라벨 Badge CoreBadgeVariant 4종(primary/secondary/outline/destructive), CoreComponentSize 5종 —
실패/충돌 고지 Alert CoreAlertVariant — defaultVariant, info, success, warning, destructive —
상단 고지 스트립 Banner CoreBannerVariant — default_, info, success, warning, destructive —
순간 알림 Toast + showToast ToastLayer, ToastLocation, CoreToastVariant 2종(default_/destructive) success/info/warning 시맨틱이 없다. 이 문서의 화면 계약은 Toast 를 쓰지 않는다(UX-D-08: 인앱 pull 만) — 쓰게 되면 색을 직접 만들어야 하므로 CoUI 확장 대상(§12)
확인 다이얼로그 Dialog open/onClose/title/content/leading/trailing/actions —
탭 Tabs / TabPane CoreTabVariant — pill, underline size 파라미터 없음(스타일 슬롯으로)
진행 표시 Progress value 생략 시 부정형(indeterminate) 슬라이드 —
빈 화면 EmptyState CoreEmptyStateVariant — normal, compact —
단축키 키캡 Kbd / KeyboardShortcut keys: List<String> 표시 전용 — 키 등록·처리는 Flutter Shortcuts/Actions 몫. 플랫폼별 라벨(⌘↔Ctrl) 자동 정규화 없음
소규모 스크롤 ScrollArea CoreScrollAreaStyle(height, maxHeight, thumb*), direction child: 를 통째로 받는 구조 — 가상화 계약이 아니다
설정·목록 표 Table / ResizableTable CoreTableRowData/CoreTableCellData/CoreTableSize(CoreFlex/Fixed/IntrinsicTableSize) 행 가상화·정렬·선택 모델 API 없음
카드 Card Widget: Card 승인 카드 컨테이너로만 사용
폼 Form (+ FormField, FormLabel) 확인 완료 워크스페이스 생성 마법사(S-14)
선택 Select Widget: Select 백엔드/프로바이더 선택(S-15)
구분선 Divider 확인 완료 상태바 칸 구분
테마 CoreThemeData · CoreColorScheme · CoreTypography · CoreThemeMode{dark,light,system} §7 CoreColorScheme.fromMap(...)(OKLch/hex) 존재
부분 채택 Tree §6.2 참조 —
부분 채택 CodeDiff §6.2 참조 —

6.2 IDE 전용으로 신설하는 것 — 계약 사실에 근거한 판단

신설 왜 CoUI 로 안 되는가 (확인한 계약)
CocodeEditorView CoUI 에 편집 가능한 코드 표면이 없다. 코어는 re_editor 0.10.0(Discovery ### Technical Feasibility 행, 리스크 높음). AC-15 성능은 A-03 스파이크에 종속
CocodeDiffView CodeDiff 계약이 막는다 — 스킬 63행: "per the contract (CoreCodeDiffContract) this component is read-only with no scroll or selection interactions", 65행: "the diff uses the design system's sans bodySmall/labelSmall roles — not a monospace font", 줄 타입 3종(added/removed/unchanged), variant/size 없음. 다중 파일 · 스크롤 · 선택 · 구문 강조 · 10만 줄(AC-15) 을 이 계약으로 표현할 수 없다. 특히 행 클릭 콜백이 0 이라 AC-02 의 "특정 스냅샷 선택"을 diff 위에서 할 수 없다
CocodeFileTree Tree 계약이 막는다 — onNodeSelect 는 "fires only when a leaf node is tapped"(폴더 선택 불가), 데이터는 전개된 List<CoreTreeNode>(지연 로딩 계약 없음), 확장 상태가 uncontrolled("initial state only — the widget owns state after mount")라 에이전트가 파일을 추가·이동하면 확장 상태가 유지되지 않는다, 다중 선택·이름 변경·드래그 계약 없음. 참조 워크스페이스 coco-de/unibook 은 Dart 파일 9,931개(planning-inputs §3.1 — GitHub git-tree API 기반 정확값)
CocodeTerminalView CoUI 에 터미널이 없다(인벤토리 §1 도 동일 결론). xterm2/flutter_pty2 재사용은 Lumide 이슈 #64(A-04) 결함 상속 위험을 동반 — 재현 확인이 먼저(planning-inputs §4.2)
CocodeStatusBar CoUI 에 상태바 컴포넌트가 없다(인벤토리 §1: "'StatusBar' 컴포넌트 없음 … VS Code 식 하단 status bar 는 실재하지 않음"). Scaffold(footers:) + AppBar + Status + Divider + Text 조립을 감싸는 IDE 전용 위젯으로 만든다
CocodePaneHost Resizable 이 controlled sizes 를 노출하지 않아 프로그램적 접기·픽셀 고정 폭·실행 중 레이아웃 복원을 표현할 수 없다(§2.3 L1~L3). MVP 는 표시/숨김으로 우회하고, 그 이상이 필요해지면 이 위젯 또는 CoUI 확장(§12)
CocodeSnapshotTimeline 확인 완료 — Timeline 계약에 선택도 콜백도 없다. Widget API 파라미터는 items·timelineStyle 둘뿐이고 CoreTimelineItem 필드는 title/description/timestamp(전부 String)뿐이며, Pitfalls 가 "임의의 위젯/컴포넌트를 콘텐츠로 넣는 슬롯은 없습니다" 라고 명시한다. 선택 상태·되돌릴 범위 하이라이트가 필수인 §4.2 를 표현할 수 없으므로 신설로 확정한다(초판의 "확인 후 판단" 미결을 해소)
CocodeStateIndicator Status 파라미터에 진행 모션이 없다(color·size·semanticLabel·statusStyle). 실행중·자가검증중은 색 시맨틱과 지속 모션을 한 몸으로 가져야 P1(돌아와 한눈에 읽기)이 성립한다
CocodeVirtualList ScrollArea 의 정본 예시는 child: 로 Column 전체를 받는 형태다(스킬 Canonical snippet). 수천 행 가상화 계약이 아니며, Table 도 행 가상화 API 가 없다. 위임 목록·검증 로그·diff 행에 필요
CocodeSyntaxScheme CoreColorScheme 에 구문 강조 역할이 없다(§7.1)

CodeDiff 와 Tree 를 쓰는 자리 — 계약 안에서만: CodeDiff = 승인 카드 안 짧은 읽기 전용 미리보기(§5.2). Tree = 롤백 대상 파일 목록처럼 작고, 리프 선택만 필요하고, 표시 중 노드 집합이 변하지 않는 계층 표시.

6.3 확장·의존 규칙 [규약]

  • ui(IDE 전용 위젯 패키지)는 L1 공용 UI 계층이다 — package-layers §계층 65행: "L1 | 공용 UI·인프라 … 도메인 계층을 의존하지 않는다". coui_flutter/coui_core 를 의존하고, 도메인·feature 를 의존하지 않는다.
  • feature 는 다른 feature 의 Route/Page/Bloc 을 import 하지 않는다(같은 문서 §추가 규칙 77행). 패널 간 이동(예: 승인 카드 → diff → 에디터)은 계약 인터페이스 + 런타임 등록으로 뒤집고, 레지스트리 완결성 테스트를 짝으로 붙인다. 등록 누락은 debug 에서만 assert 되고 release 는 빈 화면(SizedBox.shrink) 이다(100행).
  • 재수출되는 패키지를 pubspec 에 또 적지 않는다 — 실측에서 유령 의존 39개의 원인이었다(85~86행).
  • 패키지 골격 생성은 cob 로 한다(D-023). 단 D-023 자신이 "cocode ADE 는 앱이 아니라 데스크톱 IDE 이고 Serverpod 백엔드가 없다. 기존 brick 이 이 형태를 지원하는지는 Scaffold 단계에서 cob list-features 로 확인" 을 미결로 남겼다.

6.4 토큰·밀도 규칙 [규약]

  • 타이포는 context.textStyles + M3 시맨틱(titleSmall, bodyMedium, labelMedium …). context.textStyles.{lgSemibold/sm/xs} 는 Deprecated, context.typography 는 사용 금지 — coui-flutter-rules §API 선택 63행. (§0.3-8 의 규약 충돌 참조)
  • 버튼 크기는 CoreComponentSize 만 — ButtonSize/ButtonDensity 는 존재하지 않는다(같은 문서 151~152행: "these names do not exist and never compiled against v0.127"). 고밀도 툴바는 size: .xs/.sm + buttonStyle 의 padding 조정 경로를 쓴다.
  • 간격은 Gap.space4() 계열(v0.127 bare Gap).
  • 데스크톱 밀도 토큰은 IDE 층에서 정의한다. CoUI 의 치수 시맨틱에는 pointer 축이 없다 — §8.3 의 44dp 하한은 flutter-a11y 의 MinTouchTarget.pointer 를 쓰고, 행 높이·거터 폭 같은 IDE 고유 치수는 ui 가 CoUI 원시값 위에 정의한다.
  • 밀도와 접근성의 충돌 해소: 시각 크기는 줄이되 실효 히트영역은 §8.3 하한을 지킨다.

6.5 계약 한계를 설계로 흡수한 곳

한계 MVP 설계의 대응 넘어서려면
Menubar 서브메뉴 없음 메뉴를 1단으로 설계한다. 깊은 동작은 커맨드 팔레트가 담당(K1) CoUI 확장(§12)
Command fuzzy 없음·비가상화 팔레트 항목 수를 1급 동작으로 한정. substring 검색으로 충분한 규모를 유지 CoUI 확장(§12)
Resizable 접기 불가 표시/숨김으로 대체(UX-D-03) CocodePaneHost 또는 CoUI 확장
Toast 시맨틱 2종 Toast 를 쓰지 않는다(UX-D-08) CoUI 확장
Status 모션 없음 Progress 부정형 병치, 필요 시 CocodeStateIndicator —

7. 테마 (f)

7.1 결정 — 두 층으로 쪼개서 채택한다

대상 결정 근거
UI 9색 그대로 채택하지 않는다. CoUI CoreColorScheme(M3 시맨틱)로 사상한다 두 개의 색 원천이 생기면 CoUI 컴포넌트와 IDE 위젯의 색이 갈라진다. CoreColorScheme 은 surface/onSurface/outline/inverse/status 를 이미 역할별로 갖는다
LSP 시맨틱 토큰 24종 채택한다. CocodeSyntaxScheme 를 신설해 CoreThemeData 와 나란히 공급 ⓐ CoreColorScheme 의 getter 표(coui-theme 148~160행)를 직접 확인한 결과 역할군은 Brand / Secondary / Tertiary / Error / Status(success·warning·info) / Surfaces / Surface tones / Borders(outline) / Inverse / Special(shadow·scrim) / Liquid Glass 뿐이고 구문 강조 역할이 없다 ⓑ Discovery ### Key Insights 3번 ⓒ Discovery ### Technical Feasibility: 하이라이팅 = LSP 시맨틱 토큰 정규화, 리스크 낮음, "Lumide가 검증한 설계"

[UX-D-15] 24종 토큰의 이름 목록을 이 문서가 지어내지 않는다. "24종"과 "9색"은 Discovery ### Key Insights 3번이 유일한 출처이고 개별 토큰 이름은 근거 문서 어디에도 없다. 목록 확정은 LSP 표준(textDocument/semanticTokens legend)과 대조해 에디터 코어 스파이크(A-03) 담당이 구현 시점에 확정한다.

7.2 테마 계층

CoreThemeData  (coui_core — CoUI 정본)
                     ├─ CoreColorScheme      → UI 표면·텍스트·테두리·상태색  ← CoUI 컴포넌트 + ui 공용
                     ├─ CoreTypography       → context.textStyles (M3 시맨틱)
                     ├─ CoreThemeMode        → dark | light | system   (기본: system)
                     └─ (CoUI 계약 밖)
                         └─ CocodeSyntaxScheme → LSP 시맨틱 토큰 세트     ← CocodeEditorView / CocodeDiffView 전용
                             ├─ light 세트
                             └─ dark  세트
                    
  • 기본 CoreThemeMode.system. 구문 팔레트도 밝기별 2세트가 필요하다 — 한 세트만 두면 다크 모드에서 대비가 깨진다.
  • 대비 검사 대상에 구문 토큰을 포함한다 — WCAG AA 4.5:1(본문) / 3:1(큰 텍스트), flutter-a11y §Actions 7번(44행).
  • 사용자 테마 교체 UI 는 MVP 범위 밖. 근거 문서에 요구가 없다. CoreColorScheme.fromMap(...)(OKLch/hex 파싱)이 존재하므로 나중에 열 수 있다는 사실만 기록한다.

7.3 이 절이 열지 못한 두 가지 — ✅ 둘 다 닫혔다 (#55)

🔄 2026-09-13 · #55 결정(spike) 로 닫힘 — 산출물은 docs/mono-font-decision-cocode.md.

  • 고정폭 서체 → D2Coding 1.3.2(NAVER, OFL 1.1) 확정. 후보 3종을 서체 바이너리 실측으로 비교했고, 한글/라틴 advance 비율이 정확히 2.0000 인 것은 D2Coding 뿐이었다(Noto Sans Mono CJK KR 1.84 · coui 현행 체인 1.4405). 토큰은 CocodeMonoFont(package/ui)이고, 자산의 격자 계약은 .github/scripts/check_mono_font_grid.py 가 바이너리를 직접 읽어 강제한다.
  • re_editor 토큰 소비 → 직접 주입 불가 · 어댑터로 성립. CodeEditorStyle 이 테마 객체가 아니라 평탄한 원시값만 받지만 필요한 축이 전부 덮이므로, CoUI 토큰 → CodeEditorStyle 한 방향 어댑터로 이중 관리 없이 성립한다. Material 테마 누수는 전수 5곳이고 그중 4곳이 CodeEditorStyle 로 덮인다 — 어댑터의 계약은 「색 필드 4종을 반드시 채운다」이다(#58 이 이어받는다).

아래 표는 착수 시점의 기록으로 보존한다.

항목 상태 왜 지금 문제인가
고정폭 서체 확정 미정 에디터·터미널·diff 세 화면이 전부 여기 걸린다. AC-16(한글 IME)과 겹쳐 한글 글리프를 가진 고정폭 서체라는 추가 제약이 붙는다 — 라틴 전용 mono 를 쓰면 한글이 폴백되어 열 정렬이 깨진다. CoUI 쪽 CoreFontFamily.mono 의 실제 서체 지정 여부는 미확인(인벤토리 §5)
re_editor 가 CoUI 토큰을 소비할 수 있는가 미검증 에디터가 화면의 최대 면적을 차지한다. 서드파티 에디터 패키지에 CoreColorScheme/CoreTypography 를 주입하는 테마 브리지가 성립하지 않으면 색·폰트를 이중 관리하게 되고, "토큰은 CoUI"라는 오너 결정 4가 실질적으로 무력해진다(인벤토리 §5)

8. 접근성 · 키보드 · IME (g)

8.1 키보드 내비게이션

[UX-D-16] 이 문서는 구체적 키 조합 표를 정하지 않는다. 3플랫폼의 관례가 다르고(Cmd/Ctrl), 근거 문서에 규정이 없다. 대신 판정이 필요 없는 규칙 4개를 정한다.

# 규칙 근거
K1 모든 1급 동작은 커맨드 팔레트에 등재된다. 팔레트에 없는 동작은 존재하지 않는 것으로 본다 Command 계약 존재 + P1 — 마우스 경로만 있는 동작은 복귀 후 탐색 비용이 된다. 단 팔레트 검색은 label substring 이므로(§6.1) 항목 라벨을 사용자가 떠올릴 단어로 시작하게 쓴다
K2 포커스 순환은 폐쇄 순서다 — 좌 패널 → 중앙 에디터/diff → 우 Inspector → 하단 터미널 → (순환). 각 영역의 진입·탈출은 같은 한 쌍의 키 판정 없음
K3 포커스 트랩은 Dialog 와 Command 에만 존재한다. 상주 패널은 트랩하지 않는다 상주 패널이 트랩하면 K2 가 깨진다
K4 파괴적 동작(승인·롤백·강제 적용)은 Enter 기본 활성화를 갖지 않는다. 명시적 포커스 이동 후 활성화 C-05·AC-10 의 "명시적 승인" 취지. [UX-D-17]
  • 키캡 표시는 Kbd / KeyboardShortcut, 메뉴 항목의 단축키는 CoreMenubarEntry.action(shortcut:) 슬롯을 쓴다. 두 컴포넌트 다 표시 전용이며 키를 등록·처리하지 않는다 — 실제 처리와 3플랫폼 라벨 정규화(⌘↔Ctrl)는 IDE 층 인프라다.
  • 누가 언제 키 조합을 정하는가: 플랫폼별 관례 대조가 필요하므로 Breakdown 단계에서 이슈로 분리한다(CH-035 가 IME 담당자·기한을 "Breakdown 단계" 사항으로 처분한 것과 같은 유형 — contrarian-review 175행).

8.2 한글 IME (AC-16 · A-04) — 3플랫폼 Must

  • 대상 조합은 6개다: {macOS, Windows, Linux} × {에디터, 터미널} — BDD Feature 2 Scenario Outline Examples 6행 직접 계수.
  • 인수 술어는 AC-16 원문 그대로: 조합 중 글자 깨짐 없음 · 중복 입력 없음 · 커서 위치 오류 없음.
  • D-016 이 정한 macOS 우선은 게이팅 스파이크의 순서 이지 출시 조건의 축소가 아니다 — planning-inputs §4.3 경고문("AC-16을 완화하려면 Seed Spec 개정이 필요하다") + PRD D-9.

[UX-D-18] UI 가 지켜야 할 IME 계약 3조 (근거 문서에 규정이 없어 이 문서가 정한다):

# 규칙 왜
I1 조합 중(preedit) 구간을 확정 텍스트와 시각적으로 구분한다 AC-16 의 "글자 깨짐"을 사용자가 조합 중 상태와 혼동하지 않게. §7.3 의 고정폭 서체 확정에 종속 — 한글 글리프가 폴백되면 preedit 구간의 열 정렬이 깨진다
I2 조합 중에는 자동완성·자동저장·자가 검증 트리거가 커밋을 가로채지 않는다 중복 입력의 전형적 발생 경로
I3 조합 중 포커스를 다른 패널로 자동 이동시키지 않는다 — 에이전트 작업 완료 이벤트가 도착해도 포커스를 빼앗지 않는다 P1 과 충돌하는 지점이다. 통지는 배지로만(UX-D-08) — 이 결정이 I3 를 자연히 만족시킨다
  • 입력기·코퍼스·시행 횟수·관찰 방법은 Planning 확정(D-9, planning-inputs §4.3).

8.3 히트영역 · 대비 [규약]

항목 값 조건 출처
pointer(마우스) 최소 실효 히트영역 ≥ 44 × 44 dp 배율 미적용 flutter-a11y 62행 (MinTouchTarget.pointer)
터치 ≥ 48 × 48 dp theme.scaling 을 곱한다 같은 표 61행 (MinTouchTarget.touch)
인접 컨트롤 데드존 ≥ 8 dp — 같은 표 63행
대비 4.5:1(본문) / 3:1(큰 텍스트) WCAG AA flutter-a11y §Actions 7번(44행)
  • 데스크톱 IDE 는 pointer 축(44dp) 을 적용한다. 값은 공용 상수 토큰에서 가져오고 리터럴 48/파일 로컬 상수를 새로 만들지 않는다(같은 문서 65행).
  • 원시 GestureDetector + Padding 조합 금지, 디자인 시스템 컴포넌트 레벨에서 min-size 를 보정하지 않는다(135행).
  • 상태 정보는 색 + 텍스트로 이중화한다(WCAG 2.x SC 1.4.1 Use of Color). §3.2 표의 모든 행에 적용.
  • Semantics 라벨 필수 대상: 상태 점(Status.semanticLabel 슬롯 사용), 잠금 아이콘, 스냅샷 타임라인 노드, 충돌 배지.

9. 상태 관리 배선 (BlocSignal) — UX 계약과 닿는 부분만

  • 화면 상태는 BlocSignal 계열로 관리한다(오너 결정 2). 조직 점검 항목: BlocSignalBuilder 에 buildWhen 적용, 좁힌 구독은 BlocSignalSelector, context.watch<T>().stateValue 로 상태를 구독하지 않기 — cc-quality/skills/code-review-checklist/REFERENCE.md §Performance 표 + §bloc_signals 전용 점검.
  • 타입 인자가 지워지지 않게 한다 — cc-dcm/commands/quality.md §Fix Safety Contract 원문: "a BlocSignalProvider<T> inside a typed list loses T, still compiles, passes flutter analyze, and throws ProviderNotFoundException only in a release build". 프로바이더를 리스트로 묶어 배선하는 모든 지점이 대상이다.
  • 이 UX 명세가 요구하는 경계: 위임 목록·승인 큐·검증 로그·스냅샷 타임라인은 상태 스트림에 올린다(부재 중 축적과 복귀 시 일괄 반영이 필요하므로). 에디터 버퍼와 터미널 출력은 올리지 않는다 — 고빈도 갱신을 화면 상태에 실으면 AC-15(10만 줄 응답성)의 여유를 잠식할 수 있다. 상세 구조는 아키텍처 문서 몫이다.

10. 화면 인벤토리 · AC 추적

화면 번호는 순차 발급하며, 현재 마지막 번호는 S-17 이다 (#88). 새 화면을 더하는 Story 는 이 줄을 읽어 다음 번호를 가져가고 이 줄을 함께 갱신한다 — 번호를 각자 계산하면 같은 번호가 두 화면에 붙는다. 부번호(S-01b·S-08b)는 기존 화면에 딸린 표면에만 쓰고 새 번호를 소비하지 않는다.

⚠️ 이 표의 행 수를 인수조건으로 절대값으로 세지 않는다(초판의 「현행 17행」). 여러 Story 가 각자 자기 행을 더하므로 절대값은 곧바로 낡는다 — 판정은 「내 행이 정확히 1행 존재한다」는 상대 판정으로 한다.

# 화면/패널 다루는 AC 구현
S-01 메인 셸(3열 + 하단) AC-03 CoUI Resizable + Menubar + Scaffold
S-01b 상태바 AC-12·AC-18 의 잠금 수 노출, §4.5 R3. ⚠️ 잠금 칸은 스윕 완료 뒤에만 렌더한다(D-048, #78 — §2.4). ⚠️ 대기 칸을 만들지 않는다 (#77) — 대기자는 §2.4 표의 어느 칸에도 대응 출처 속성이 없고(영속되지 않는 런타임 자료구조), 대기는 게이트 연산 1회로 유한해 사람이 읽기 전에 사라진다 CocodeStatusBar (Scaffold(footers:) 기반)
S-02 파일 트리 AC-03 CocodeFileTree
S-03 코드 에디터 AC-03, AC-15, AC-16 CocodeEditorView
S-04 터미널 AC-03, AC-16 CocodeTerminalView
S-05 위임 생성 다이얼로그 FR-201, AC-17 CoUI Dialog + Form/Select
S-06 복귀 보드(위임 목록) C-04, AC-19. 실행중 행의 잠금 칸은 3값(UX-D-23, #77) CocodeVirtualList + Status/Badge/CocodeStateIndicator
S-07 Task Inspector AC-01, AC-02, AC-09, AC-19 혼합
S-08 검증 로그 AC-09, C-04 CoUI 조합 + CocodeVirtualList
S-08b 하단 [문제] 탭 — 검증 원문 뷰(워크스페이스 세션 버퍼 · 작업·회차·방법 축) AC-09·AC-19 의 원문 열람 — 세션 한정(architecture DD-23c-②, 고지 A/B/C) S-08 과 같은 조합(CocodeVirtualList) + 고정폭 서체(§7.3). 부번호는 S-01b 와 같은 방식 — #88 이 세울 순차 발급 규칙과 충돌하지 않도록 새 번호를 쓰지 않았다 (#32)
S-09 다중 파일 diff AC-01 · 생성·삭제·이름변경 행 규칙 §4.1(#28, UX-D-21) CocodeDiffView
S-10 스냅샷 타임라인 · 롤백 선택 AC-02 · 종류 배지·되돌릴 집합 미리보기 §4.2(#28, UX-D-21) CocodeSnapshotTimeline
S-11 충돌 제시 AC-02(v3.3.0 D-036) · 충돌 사유 문구표 §4.3(#28, UX-D-21) CoUI Alert + 목록
S-12 승인 큐(2종 카드) AC-10, AC-11 CoUI Card + CodeDiff
S-13 실패 배너 · 편집 처분 AC-19, AC-07/AC-08/AC-20 CoUI Banner/Alert
S-14 워크스페이스 생성 AC-05(1급 타입 선택), AC-13(실패 시 미생성) · 실패 제시 형태 UX-D-23(#41, D-049) CoUI Dialog + Form
S-15 백엔드/프로바이더 설정 AC-06 CoUI Select/Table
S-16 샌드박스 설정(허용 호스트·쓰기 예외) AC-14 · 차단 호스트 추가 후보 슬롯 UX-D-24(#36) CoUI Table · 편집 모델은 SandboxSettings(core, #36) — 위젯은 셸 Epic #53 의 몫
S-17 첫 실행 진입 화면(워크스페이스 0건) AC-03 — "애플리케이션 실행 시 에디터·파일트리·터미널 제공"(seed:105)의 워크스페이스 없는 상태 판정을 고정한다(§2.5 UX-D-30). AC-05·AC-13 의 담당 화면 S-14 로 가는 주 진입점이기도 하다 CoUI EmptyState(CoreEmptyStateVariant.compact) × 3 표면 + 주 동작 1개 — 신설 컴포넌트 없음

AC 배정 현황 (초판의 자기모순을 정정)

  • 화면이 배정된 AC (18건): AC-01·02·03·05·06·07·08·09·10·11·12·13·14·15·16·17·19·20.
    • AC-05 → S-14(프로젝트 타입 선택지). AC-13 → S-14(실패 시 워크스페이스 미생성). AC-07·AC-08 → S-13(전이 결과 표시 + 사유). AC-12·AC-18 → S-01b(잠금 수).
    • 초판은 이들을 "배정하지 않은 AC" 목록에 넣었는데 같은 표의 담당 칸에는 배정돼 있었다. 표가 맞고 주석이 틀렸다.
  • 화면을 배정하지 않은 AC (2건): AC-04(드리머 모드 부재) · AC-21(워크트리 격리·작업 인계 부재). 둘 다 Must-Not 이며 부재 자체가 요건이므로 그릴 화면이 없다.
  • AC-18 은 부분 노출이다 — 잠금 해제 결과는 S-01b 의 잠금 수에 반영되지만, 비정상 종료한 작업 자신의 status 가 미규정이라 S-06 에 그 작업을 어떤 배지로 그릴지가 정해지지 않았다(§3.2 자리표시자 규칙 + §12).
  • "전수 배정"이라고 주장하지 않는다.

11. 이 문서가 새로 정한 UX 결정 (UX-D-01 ~ 26)

ID 결정 근거의 성격
UX-D-01 위임·검토·롤백을 우측 상주 패널에 둔다(모달 금지) C-04 + AC-01/02/19 에서 도출
UX-D-02 패널 비율을 onResize 로 저장, 복원은 재마운트 시 initialSize 로만 Resizable 계약 한계 L1
UX-D-03 MVP 도킹 = 고정 슬롯 + 크기 조절 + 표시/숨김. "0 으로 접기"·픽셀 고정·부유창 없음 계약 한계 + 범위 결정 — 스펙 금지 아님
UX-D-04 completion_mode 토글은 렌더하되 활성화는 D-18 확정에 종속 스펙을 넓히지 않기 위함
UX-D-05 위임 다이얼로그 CTA = "위임하고 나가기" P1
~~UX-D-06~~ ⛔ 폐기 (D-032, 2026-09-10) — 중지·거부 수단을 둔다. Seed Spec v3.3.0 status 9종 + AC-22·AC-23 폐기 사유: AC-08 의 Given 이 편집 단계·잠금 대기를 덮지 못해 원 논거가 성립하지 않음
UX-D-07 복귀 보드 1차 키 = (status, pending_approval_kind) 버킷, 2차 키 = 버킷 안에서만 최신 EditSnapshot.timestamp. 값이 없으면 버킷 끝 + 경과 시간 미표시 폐쇄 키 — 판정 없음
UX-D-08 MVP 통지 = 인앱 pull only. OS/푸시 알림은 범위 밖 근거 문서에 알림 요구 0건(전수 grep)
UX-D-09 충돌 후 선택지 = 취소 / 충돌 파일 열기 / 전체 강제 적용. 파일 단위 부분 적용·자동 병합 금지 PRD 흐름 4 미결에 대한 Design 결정
UX-D-10 강제 적용 전 현재 내용을 대피 사본으로 보존 신설 개념 — 저장소 설계와 함께 확정 필요
UX-D-11 AC-19 "조용히"를 UI 관찰 조건 3개(ⓐⓑⓒ)로 환원 제안 D-15 에 대한 입력이지 확정 아님
UX-D-12 보존 정책 UX 계약 R1·R2·R3 (값이 아니라 규칙) 축 불일치 발견에 근거
UX-D-13 일괄 승인 없음. 승인 버튼은 승인 대상 변경 전체를 연 뒤, 그리고 그것이 비어 있지 않을 때만 활성화 "명시적 승인"을 관찰 조건으로 환원
UX-D-14 승인 대기 카드가 "잠금 없음 → 직접 편집 시 롤백 충돌" 인과를 고지 Workspace 불변식 2 + v3.1.0 충돌 판정
UX-D-15 구문 토큰 24종의 이름을 지어내지 않는다 근거 문서에 목록 없음
UX-D-16 구체 키 조합 표를 정하지 않고 규칙 K1~K4 만 정한다 근거 문서에 규정 없음
UX-D-17 파괴적 동작에 Enter 기본 활성화 없음 "명시적 승인" 취지
UX-D-18 IME 계약 I1·I2·I3 근거 문서에 규정 없음
UX-D-19 승인 대기 중 미적용 변경을 담는 PendingChange 개념을 신설로 명시하고 데이터 모델·저장소 설계로 이관 신설 개념 — AC-11 의 "명시적 승인"이 성립하려면 필요한데 §3 에 없다
UX-D-20 실행중 행에 편집 대상 파일명을 표시하지 않는다(잠금 보유 여부만) §3 에 작업↔잠금 귀속 속성 없음 — P2 준수
UX-D-21 생성·삭제·이름변경의 표시 어휘 — 배지 M/+/−/R/±, 이름변경 사슬을 한 행으로 접기, 되돌릴 집합의 복원/삭제/경로 복귀/변경 없음, 충돌 사유 문구 9종(D-036 행 포함), 대피 사본은 파일인 경로에만(§4.1~§4.3). 판정은 전부 architecture §4.7 DD-25 의 투영 전이에서 나오고 화면은 값을 계산하지 않는다 DD-25 에서 [도출]. 문구·배지 자체는 이 문서의 결정(#28)
UX-D-22 하단 [문제] 탭 = 검증 원문 뷰 S-08b(세션 한정 — 원문 영속 경로 없음). 원문이 보이는 세 자리(§3.4 검증 로그 패널 · §4.4 실패 배너 · §5.2 완료승인 카드)에 세션 고지를 두되, 문구는 architecture DD-23c-② 의 버퍼 상태 3종(A 있음 / B 이전 세션 / C 상한 정리)에 1:1 고정 문자열 — 화면은 판정하지 않는다. 패널은 현재 회차를 기본으로 그린다 DD-23c(#32)에서 [도출]. 탭의 지위·문구·부번호는 이 문서의 결정
UX-D-23 스캐폴딩 실패 제시(S-14) — ⓐ 제시 자리는 S-14 제자리다(워크스페이스가 생성되지 않아 작업 상세·복귀 보드에 담을 행이 없다). ⓑ 모든 사유에 고정 문구 1줄「아무것도 만들어지지 않았습니다」를 함께 둔다 — AC-13 이 사용자에게 보장하는 것이 그것이다. ⓒ 사유는 자유 서술이 아니라 폐쇄 코드 + 고정 라벨 5종이며, 코드에 없는 원인은 문장을 지어내지 않고 「사유 미규정」 자리표시자를 그린다(§3.2 규칙 재사용): hookFailed(brick 훅이 비정상 종료했습니다) · hookEscapedStaging(brick 훅이 작업 폴더 밖에 쓰려고 해 차단했습니다 — architecture §4.6-2) · writeFailed(파일을 쓰지 못했습니다) · variableRejected(입력한 변수가 brick 의 검증을 통과하지 못했습니다) · canceled(사용자가 취소했습니다). ⓓ 착수 전 거부는 이 실패 화면을 띄우지 않는다 — 폼의 필드 오류로 되돌린다. 사용자가 할 일이 「재시도」가 아니라 「값 수정」이기 때문이며, 이것이 D-049 의 하한(첫 스테이징 쓰기)이 UI 에 드러나는 유일한 자리다. ⓔ 화면은 구간을 판정하지 않는다 — BrickEngine 이 사유 코드와 구간을 함께 준다(P2) D-049(#41)에서 [도출]. 코드 집합·라벨·자리 배치는 이 문서의 결정. PRD 흐름 1 미결 A 를 닫는다
UX-D-24 S-16 은 차단 사건 이력을 담지 않고 「추가 후보」만 담는다. DD-17a 가 차단 목록의 자리를 작업 상세로 정했고, 같은 데이터를 S-16 에도 이력으로 그리면 정본이 둘이 된다(어느 쪽이 최신인지, 지운 것이 어디까지 반영되는지가 곧바로 물음이 된다). 그렇다고 아무 연결도 없으면 사용자는 「막힌 호스트를 보던 화면」과 「그것을 넣는 화면」 사이를 이름을 외워 오가야 한다. 그래서 S-16 은 지금 편집 중인 필드에 넣을 만한 값의 후보만 보인다 — 아직 allowed_hosts 에 없는 차단 호스트를 정규화·중복 제거해 한 줄씩, 각 줄에 「추가」 하나. 추가하는 순간 후보에서 사라진다(그것이 이력과 후보의 관찰 가능한 차이다). 시각·횟수·작업 귀속은 담지 않는다 — 그것이 이력이고 작업 상세의 몫이다. 데이터는 SandboxSettings.addCandidatesFrom(blockedHosts)(core) DD-17a 의 자리 지정과 충돌하지 않는 형태를 이 문서가 정한다(#36 인수조건 5). 「미정 — 결정 필요」를 닫는다
UX-D-25 실패 사유 «코드 집합»은 이 문서가 소유하지 않는다 — 한국어 «라벨»만 소유한다 (#73). failure_class 폐쇄 5종의 SSOT 는 docs/verification-failure-class-cocode.md §3.1 이고, §3.2 의 실패 사유 표시 규칙은 그 코드에 붙는 표시 문자열만 정한다. 코드를 화면 쪽에서 더하거나 빼지 않는다 — 그러면 스키마가 거부하는 값이 화면에만 존재하거나, 화면이 모르는 값이 기록에만 존재한다. UX-D-23(스캐폴딩 사유 코드 5종)과 같은 소유 분할이며, 「문장을 지어내지 않고 폐쇄 라벨에서 고른다」는 §3.2 규칙은 그대로다 D-055(#73)에서 [도출]. 라벨 문자열 자체는 이 문서의 결정
UX-D-26 [적용하지 않음] 은 «거부» 이고, 부분 승인은 없다 (#72). 테스트변경승인 카드의 그 버튼은 AC-23 의 거부 입력이며 작업을 거부됨(종결)으로 보낸다 — 「이 변경만 버리고 작업은 계속」이라는 의미론은 어느 스펙에도 없고, 에이전트가 만든 편집 집합과 실제 적용된 집합이 갈라진 채 작업이 이어지는 상태를 새로 만든다. 승인은 대상 변경 전체에 대한 단일 판정이라 부분 승인 경로가 없고(UX-D-13 의 「작업 1건 단위」 연장), 적용은 전량이거나 전무다. ⚠️ 같은 이유로 완료승인 카드에도 거부 입력이 필요하다(AC-23 은 kind 를 가리지 않는다) — 버튼 배치는 #85 D-058(#72)에서 [도출] · prd FR-407·FR-409
UX-D-27 편집 0건 작업의 diff 화면은 열리고, 빈 목록 + EmptyState 를 그린다 (#89). flow-permutation §6.3 N-1 이 남긴 공백을 닫는다 — AC-01(seed:103)의 Given 은 "에이전트가 파일을 편집한 DelegatedTask" 라 편집 0건은 그 사정 밖이고, 규정이 없어 구현마다 갈릴 수 있었다(예외를 던지거나, 화면을 열지 않거나, 「변경 없음」이라 쓰거나). 규칙은 하나다: 열되 0건임을 보인다. 열지 않으면 사용자는 그 작업이 무엇을 했는지 볼 방법이 없고, 예외를 던지면 정상 상태가 오류가 된다. 표현 수단은 §6.1 에 이미 매핑된 CoUI EmptyState(CoreEmptyStateVariant — normal, compact)이며 신규 컴포넌트가 없다. ⚠️ 이 경우의 BDD 시나리오 라벨은 [AC-01] 이 아니라 [UX-D-27] 이다 — AC-01 의 Given 을 충족하지 않는 경계이므로 그 AC 의 증거로 쓰면 범위를 넓혀 읽는 것이 된다(bdd:203 [C-02] · :218 [불변식] 의 비-AC 라벨 관례를 따른다) flow-permutation:286 N-1 · :326 B-16 을 닫는다. 화면 계약은 이 문서의 결정
UX-D-28 편집 0건이면 롤백 진입점 2종이 «같은 문구로» 잠긴다 (#89). 대상은 diff 화면의 [작업 시작 직전 상태로 되돌리기](:330)와 Inspector 의 [롤백](:174) 둘이며, 조건이 같으므로 문구도 한 곳에서 온다 — 각자 들면 언젠가 갈리고, 그러면 사용자가 같은 이유로 막힌 두 버튼에서 다른 설명을 읽는다. 비활성만 하고 끝내지 않는다: 사유 없이 잠긴 버튼은 「고장」과 구분되지 않는다. 편집 0건은 정상 상태이므로(에이전트가 아직 아무것도 고치지 않았거나 할 것이 없다고 판단했다) 그 사실을 말해 주지 않으면 사용자는 앱을 의심한다. ⚠️ 되돌릴 대상이 0건인 두 원인을 구분한다: 편집 자체가 0건인 경우와, 편집은 있으나 선택한 지점 이후가 비어 있는 경우(최대 sequence_no 선택 — UX-D-29 계열)는 문구가 다르다. 같은 문구를 쓰면 후자에서 사용자가 편집이 통째로 사라졌다고 읽는다. ⚠️ 문면 자체는 잠정이다 — 최종 문안의 승인 주체는 §12 에 등재한 「UX 라이팅 담당」이고 아직 지정되지 않았다. 자리와 조건은 확정이고 글자만 바뀐다 #89 인수조건 2. 자리·조건은 이 문서의 결정, 문안 승인 주체는 §12 미결
UX-D-29 빈 prompt 로는 DelegatedTask 가 생성되지 않는다. 최대 길이 상한은 «정하지 않는다» (#89). flow-permutation §6.3 N-2 를 닫는다. ⓐ 빈 판정은 trim() 후 비었는가다 — 길이 검사만으로는 공백만으로 이루어진 입력이 통과한다(사람 눈에는 빈 칸인데 길이가 0 이 아니다). 근거: seed:78 은 prompt 를 이름만 올려 두었고 prd:311·:235 어디에도 검증 규정이 없어 이 문서가 신설한다. ⓑ 거부는 CTA 비활성으로 하고 사유는 필드 옆에 둔다 — 화면 어딘가의 배너면 무엇을 고쳐야 하는지가 보이지 않는다. ⓒ 사유 표시 시점은 「제출을 시도한 뒤」다 — 다이얼로그를 막 열었을 때 빈 칸 옆에 오류가 먼저 떠 있으면 사용자가 아무것도 하지 않았는데 틀렸다고 말하는 꼴이다. CTA 잠금은 처음부터, 사유 표시는 그 뒤부터. ⓓ 최대 길이 상한은 값을 만들지 않는다 — flow-permutation:124 가 「초장문」을 경계로 들지만 같은 행의 **「스펙 규정」 칸이 「없음」**이다. 확정 전까지 상한을 적용하지 않으며, 그 미결을 §12 에 등재하는 것 자체가 이 항목의 완료 조건이다 flow-permutation:287 N-2 를 닫는다. 검증 규칙은 이 문서의 신설, 상한 값은 §12 미결

12. 이 문서가 남기는 미결 — 누가 언제 정하는가

항목 누가 언제
오너 결정 4건(§0.4)의 의사결정 일지 등재 — 현재 일지는 D-023 에서 끝나고 인벤토리가 인용한 D-024 는 존재하지 않는다 프로젝트 오너 / 일지 관리자 즉시
스냅샷 보존 상한의 축과 값 (§4.5) Design 저장소 설계 CH-022 재검토 시점
대피 사본의 저장 위치·수명 (UX-D-10) Design 저장소 설계 위와 동시
PendingChange 의 저장 위치·수명·승인 후 EditSnapshot 승격 규칙 (UX-D-19) — 삭제·이름변경의 대기 변경도 (base, result, previous_path) 어휘로 담는다(architecture §4.7 DD-25 R7) Design 데이터 모델 + 저장소 설계 위와 동시
작업 ↔ 잠금 파일 귀속 속성 (UX-D-20) — ⚠️ 속성은 생겼다 (DD-13, #77 확인): EditLease.ownerTaskId 가 그 귀속이다. 남은 것은 「실행중 행에 파일명을 그릴 것인가」라는 UX 판정 하나다 ~~Design 데이터 모델~~ UX 실행중 행 상세 설계 시
재시도 시도 경계(attempt_no)의 화면 노출 방식 — 데이터는 확정됐다(seed-spec §3 EditSnapshot attempt_no, D-030 누적). 남은 것은 UI 축이다: diff 좌측 목록이 file_path 단일 축(§4.2, 341행)이라 「같은 파일이 시도 3개에서 편집됨」을 그 목록만으로 표현할 수 없다. 실패한 작업을 열면 최대 4세트가 한 diff 에 겹쳐 보인다(AC-19 · B-15 가 그렇게 보이기를 요구한다 — 숨기는 것이 답이 아니다). 선택지: ⓐ 파일 행 안에 시도 배지 ⓑ 시도별 그룹 헤더로 2단 목록 ⓒ 시도 필터 토글 UX 담당 diff 화면 상세 설계 시
「기존 워크스페이스(로컬 폴더) 열기」가 MVP 범위인가 (UX-D-30) — seed-spec §4 인수 경계 21건에 여는 조항이 없다(AC-05·AC-13 은 생성만). 이 결정이 첫 실행 화면(S-17)의 주 동작 버튼 수를 1개↔2개로 바꾼다. 결정 이전 판본은 생성 경로만 규정한다 프로젝트 오너 또는 Planning MVP 범위 확정 전
prompt 최대 길이 상한 값 (UX-D-29 ⓓ) — flow-permutation:124 의 「스펙 규정: 없음」. 확정 전까지 상한을 적용하지 않으며, 지어낸 숫자를 코드에 넣지 않는다 프로젝트 오너 또는 Planning MVP 범위 확정 전
빈 상태·비활성 사유 마이크로카피의 문안 승인 주체와 톤 기준 지정 (UX-D-28 · UX-D-31) — 근거 문서에 UX 문안 기준이 0건이라 지금 문구를 확정하면 판정 주체 없는 산출물이 된다. 자리·동작·도착지는 확정이고 글자만 바뀐다. 확정 전까지 문구는 «…» 자리표시자 표기로 적는다(표기 규칙의 소유는 §2.5 UX-D-31 단독) 미정 — 이 문서가 지정을 요청한다 문안 검토 착수 시
prompt 최대 길이 상한 값 (UX-D-29 ⓓ) — flow-permutation:124 의 「스펙 규정: 없음」. 확정 전까지 상한을 적용하지 않으며, 지어낸 숫자를 코드에 넣지 않는다 프로젝트 오너 또는 Planning MVP 범위 확정 전
빈 상태·비활성 사유 마이크로카피의 문안 승인 주체 지정 (UX-D-28) — 근거 문서에 UX 문안 기준이 0건이라 지금 문구를 확정하면 판정 주체 없는 산출물이 된다. 자리와 조건은 확정이고 글자만 바뀐다 미정 — 이 문서가 지정을 요청한다 문안 검토 착수 시
DelegatedTask 시각 속성 추가 여부 (§3.3, PRD §3.4 "필요 시 Design 이 추가") Design 데이터 모델 저장소 설계 시
고정폭 서체 확정(한글 글리프 포함) (§7.3) Design 에디터 코어 착수 전 — 에디터·터미널·diff 3화면과 AC-16 이 여기 걸린다
re_editor ↔ CoUI 토큰 브리지 성립 여부 (§7.3) 에디터 코어 스파이크(A-03) 담당 스파이크 시
CoUI 확장(Rung 4) 승인 가능 여부 4건 — Resizable controlled sizes / Menubar 서브메뉴 / Command 커스텀 필터 / Toast success·warning. CoUI 는 다중 프로젝트 공유 자산이라 조직 결정 조직(CoUI 소유자) MVP 범위 확정 전
창 크기 하한 · 레이아웃 붕괴 임계 (§2.3) Design 최소 셸 스파이크(A-06) 직후
구문 토큰 24종 이름 목록 (§7.1) 에디터 코어 스파이크(A-03) 담당 구현 착수 시
키 조합 정본 표 + 3플랫폼 라벨 정규화 (§8.1) Breakdown 이슈 플랫폼 관례 대조 후
검증 ⑤ 사유 폐쇄 코드 집합 (§3.4) Design(D-2) —
completion_mode override 가능 여부 (§3.1) Design(D-18) —
비정상 종료한 작업 자신의 status (§3.2) Design(PRD 흐름 5 미결 A) —
"비정상 종료"의 감지 기준 (§3.2) Design(D-13) —
승인/미승인 이후 복귀 status (§5.2) Design(PRD 흐름 3-B 미결 A) —
프레임 타임 목표치·측정 환경 (S-03) Planning(D-8, planning-inputs §3.3) —
IME 입력기·코퍼스·시행 방법 (§8.2) Planning(D-9, planning-inputs §4.3) —
Git 통합의 MVP 포함 여부 (§2.4) Planning 대응 AC 없음
AC-21 의 BDD 시나리오 부재 (§0.3-4) Planning BDD 갱신 시
cob brick 이 데스크톱 IDE 형태를 지원하는가 (§6.3, D-023 미결) Scaffold 단계 cob list-features 확인 시
게이트를 거치지 않은 삭제·이름변경(터미널 rm/mv — ACP v1 fs 능력에 삭제·이름변경이 없다)을 감시자가 검출했을 때의 화면 표현 — 스냅샷이 없어 §4.1~§4.3 어디에도 그릴 근거가 없다 Design(architecture §9 미결 19) #22·#37 구현 시
워크스페이스 세션 버퍼 총량 상한의 값(§3.4 · S-08b — 값이 없으면 DD-23c-①ⓒ 의 정리가 발동하지 않아 C 문구가 뜰 일이 없다) Design(architecture §9 미결 20) #63 구현 시 참조 워크스페이스 실측 후
DD-23b 의 원문 비영속 판단을 유지·번복할 권한(§3.4·§4.4·§5.2 고지 문구의 전제) 프로젝트 오너(architecture §9 미결 21 · 일지 D-041 결정 대기) — (판정 전까지 비영속 유지)

해소된 미결(초판에서 제거): Timeline 의 선택/콜백 계약 확인 → 확인 완료. 계약에 선택도 콜백도 없다(파라미터 items·timelineStyle, CoreTimelineItem = title/description/timestamp String 3필드, Pitfalls 가 위젯 슬롯 부재 명시). CocodeSnapshotTimeline 신설로 확정한다.


Generated by cc-product Design stage (BMAD v6) · 2026-08-26