파이프라인 3단계(Planning) 산출물 · 2026-08-26 근거:
docs/seed-spec-cocode.mdv3.0.2 §4 (AC-01~AC-21 — AC-21 은 v3.1.0 ③ 신설)
이 문서의 지위
Seed Spec §4 는 범위 경계(무엇을 만들고 무엇을 안 만드는가)를 규정하고, 측정 가능한 조건은 Planning 으로 이관했다(Seed Spec 머리말 'v3.0.0 재작성 원칙' 2번). 이 문서가 그 산출물이다.
값이 아직 정해지지 않은 항목은 값이 아니라 규칙을 검증한다 — 예컨대 시간 상한은 "10분"이 아니라 "설정된 상한을 초과하면 실패로 기록된다"를 검증한다. 상한 값 자체는 설정이며 확정 주체와 시점을 주석으로 명시했다.
⚠️ v3.1.0 반영 사항 (2026-08-26, Analysis Gate 이후)
Analysis Gate 가 이 문서와 BDD 에서 실제 로직 결함을 잡아냈고, 오너 결정 3건이 확정됐다. Seed Spec v3.1.0 이 정본이며 아래가 우선한다.
1. AC-02 롤백 충돌 감지 — 규칙이 교체됐다. 이 문서 본문의
현재 해시 vs base_content_hash비교 서술(FR-506, 흐름 4, §3.3 등)은 폐기한다.base_content_hash는 편집 직전 해시라 에이전트 편집 후에는 항상 불일치하므로, 그 규칙대로면 모든 롤백이 충돌로 보고되어 안전장치가 무력화된다.
- EditSnapshot 에
result_content_hash(편집 직후 해시)를 신설- 충돌 판정 = 현재 해시 ≠ 그 파일의 마지막 EditSnapshot 의
result_content_hashbase_content_hash는 복원 목표이지 판정 기준이 아니다2. "테스트 파일" 판정 확정 —
test/·integration_test/·widgetbook/디렉터리 아래 파일(경로 기반, 판정 불필요). C-05 가 Planning 에 위임했던 항목이며 이로써 AC-11 이 기계적으로 판정 가능해진다. 이 문서가 U-7/D-1 로 "확정 주체부터 정해야 한다"고 적은 부분은 해소됐다.3. 워크트리 격리·작업 인계는 MVP 밖 — AC-21(Must-Not) 신설. 이 문서가 Q-04 로 "명시되지 않은 회색지대"라 적은 부분은 해소됐다. 단 AC-12(한 워크스페이스 내 복수 작업 동시 진행 + 파일 단위 잠금)는 MVP 안이며 이 제한과 무관하다.
아직 미정 — North Star Metric 과 과금 방식은 오너가 "지금 정하지 않는다"로 결정했다. MVP 출시 후 실사용 데이터를 보고 정한다.
BDD 인수 조건: 코코드 ADE (cocode ADE)
출처:
docs/seed-spec-cocode.mdv3.0.2 §4 (AC-01~AC-21) — 정본. 보조: §2 불변 제약 C-01~C-05, §3 도메인 엔티티 불변식,docs/planning-inputs-cocode.md,docs/decision-log-cocode.md,docs/spec-evaluation-cocode.md작성 단계: Planning (/cc-product:plan). 근거는 두 위치다 — Seed Spec 머리말 "v3.0.0 재작성 원칙" 2번(seed-spec 14행): "측정 가능한 조건은docs/planning-inputs-cocode.md를 거쳐 Planning의 BDD 인수 조건이 된다." 그리고 §4 서문(99행): "근거 없는 임계값·측정 환경·픽스처는 담지 않고docs/planning-inputs-cocode.md를 거쳐 Planning 단계의 BDD 인수 조건이 된다."
0. 이 문서를 읽는 규칙
0.1 전제 — Seed Spec 은 잠기지 않았다
docs/spec-evaluation-cocode.md "판정과 권고" 첫 항목(139행): "Seed spec은 DRAFT 상태로 남는다. 잠기지 않았으므로 후속 단계는 이 문서를 확정된 계약이 아니라 작업 가설로 취급해야 한다."
같은 보고서 6~7행 기준 Specification Gate 는 미통과다(모호성 0.3125, 통과 기준 ≤ 0.2). 아래 시나리오도 같은 지위를 갖는다 — 확정된 인수 계약이 아니라, 정본이 잠기면 그대로 계약이 될 후보다.
0.2 수치 규칙
요구사항 수치(시스템이 만족해야 하는 값)는 Seed Spec §4 "수치의 출처 (전수)" 표(seed-spec 124~143행)에 근거가 있는 것만 쓴다. 이 문서가 쓰는 요구사항 수치는 다음 7개가 전부다.
| 수치 | 쓰인 곳 | 출처표 근거 |
|---|---|---|
| 재시도 3회 | Feature 4 (AC-07) | 130행 — 프로젝트 오너 확답(D-008) + cc-product references/bmad-config.md 의 feedback.maxRetries: 3 |
| LLM 프로바이더 2개 이상 | Feature 3 (AC-06) | 131행 — "멀티 LLM" 성립의 정의상 최소값 |
| ACP 에이전트 1개 이상 | Feature 3 (AC-06) | 132행 — 경로가 존재함을 보이는 최소값 |
| 자가 검증 방법 1종 이상 | Feature 4 (AC-09) | 133행 — ⑤가 항상 대체 경로로 존재하므로 도달 가능한 최소값 |
| 자가 검증 방법 5종(①~⑤) | Feature 4 헤더 | 135행 — C-04 가 정의하는 폐쇄 집합 |
| 데스크톱 플랫폼 3종 | Feature 2 (AC-03·AC-16) | 134행 — 프로젝트 오너 확답(D-016). C-01 본문이 규범적으로 명시 |
| 10만 줄 | Feature 9 (AC-15) | 136행 — Discovery 문서가 인용한 설계 노트 로드맵 1단계의 검증 시나리오 |
근거가 없는 값은 쓰지 않는다. 대신 규칙으로만 쓰고, 해당 위치에 # 설정값 — <대상>: 미정 / 확정 주체 / 확정 시점 / 근거 문서 형식의 주석을 단다. 미확정 값과 미정 판정 규칙 전체는 §0.5 표에 모았다.
이 규칙의 대상이 아닌 수치 — 요구사항 값이 아니므로 출처표를 요구하지 않는다:
- ⓐ 시나리오 서술용 임의 식별자 —
sequence_no예시값 1·2·3·4. EditSnapshot 속성 정의(seed-spec 89행: "같은 DelegatedTask 내 순번")의 순서 관계만 쓰며 임계값이 아니다. - ⓑ 이 문서 자체의 구조 카운트 — 시나리오 수, Scenario Outline 행 수, Feature 번호.
- ⓒ 다른 문서를 인용할 때 그 문서가 적은 수치 — 예: spec-evaluation 의 "판정 주체가 미정인 3건", 모호성 점수 0.3125.
0.3 태그 배정 규칙 — 판정이 개입한다
정본 정의는 cc-product skills/analyst/SKILL.md 226~232행과 references/phase-gates.md 39~51행이다: @happy-path=정상 동작 시나리오(최소 1), @error-handling=오류 처리 시나리오(최소 1), @edge-case=경계·특수 케이스(권장). 정본은 목적만 정의하며 기계적 배정 규칙을 제공하지 않는다. 세 범주는 배타적이지도 않다 — 잠금 대기는 동시성이면서 차단이고, 승인 대기 전이는 보류이면서 조합 커버리지다.
따라서 이 문서는 아래 사다리를 위에서부터 처음 일치하는 규칙으로 적용하고, 두 규칙에 걸치면 앞선 규칙을 쓴다. 이는 이 문서의 표기 관례이지 Seed Spec 의 의무가 아니다.
| 순위 | 태그 | 적용 조건 |
|---|---|---|
| 1 | @error-handling |
전제나 트리거가 오류·실패·위반·충돌·상한 초과·비정상 종료·미승인 변경 시도이고, 시나리오가 그 처리(차단·거부·중단·"실패" 전이·에스컬레이션·충돌 제시·안전한 보존)를 규정한다 |
| 2 | @edge-case |
1이 아니고, 다음 중 하나 — ⓐ 전제가 경계값이거나 정상 경로가 적용 불가한 예외 조건이다 ⓑ 첫 Then 이 부재 확인(Must-Not)·기본값 확인·잠금 상태 확인·상태 유지 확인이다 ⓒ 전제가 동시 편집 경합이다 ⓓ [C-NN]·[불변식] 보충 시나리오다 |
| 3 | @happy-path |
그 외 — 정상 전제에서 기대 결과가 정상 진행·허용·제공이다 |
분쟁 시 기준. 게이트가 요구하는 것은
@happy-path1건 이상 +@error-handling1건 이상뿐이다(cc-productreferences/phase-gates.md51행,skills/analyst/SKILL.md254행,references/PERSONA_MATRIX.md34행). 개별 시나리오의 태그 다툼은 인수 판정에 영향을 주지 않는다. §2 대응표가 요건 충족을 보인다.
0.4 표기
- Gherkin 키워드는 영문 표준(
Feature/Scenario/Scenario Outline/Given/When/Then/And/But/Examples), 본문은 한국어. 각Feature블록이.feature파일 1개가 된다.- ⚠ 알려진 규약 충돌 — cc-flutter
skills/bdd-testing/SKILL.md82행은 "모든 텍스트를 영어로 작성하고# 한글 번역주석을 붙인다"고 규정한다. 그 규칙은 Flutter 앱 저장소의 Patrol E2E.feature를 대상으로 하고 본 산출물은 Planning 단계 스펙 문서이므로 사용자 지시(한국어)를 따랐다..feature파일로 옮길 때 언어 변환이 필요하다 — Design 단계 미결로 남긴다.
- ⚠ 알려진 규약 충돌 — cc-flutter
- 시나리오명 앞머리
[AC-NN]이 출처 AC id 다.[C-NN]·[불변식]은 Seed Spec §2·§3 에서 온 보충 시나리오이며 §4 AC 가 아님을 뜻한다.[AC-NN/불변식]은 그 AC 의 맥락을 채우되 AC 문장 자체에는 없는 조항(§2·§3)에서 온 시나리오다. - 상태·속성은 Seed Spec §3 표기 그대로 쓴다: status
대기·실행중·자가검증중·사람승인대기·완료·실패·롤백됨,completion_mode(자가검증|사람승인),pending_approval_kind(없음|완료승인|테스트변경승인),agent_backend_kind(cocode_agent|cocode_acp),agent_backend_provider,retry_count,verification_log,edit_locks,allowed_hosts,write_exceptions,snapshot_id,base_content_hash,result_content_hash,sequence_no,applied_bricks.- ⚠️
result_content_hash는 v3.1.0 ① 이 신설했는데 이 목록에 빠져 있었다(#98 이 추가). 두 해시의 역할이 다르다 —base_content_hash는 편집 직전 해시로 롤백의 복원 목표이고,result_content_hash는 편집 직후 해시로 충돌 판정 기준이다(현재 해시 ≠ 그 파일의 마지막result_content_hash→ 사람이 그 사이에 손댔다). 목록에서 빠져 있으면 시나리오가 전자만 보고 «모든 롤백이 충돌» 이라는 v3.1.0 이 고친 바로 그 버그로 되돌아간다. - status 는 전이하고,
pending_approval_kind는 설정된다 — 속성값을 "전이한다"고 쓰지 않는다.
- ⚠️
0.5 미확정 값·미정 판정 규칙 — 측정·확정 계획
값을 지어내는 대신 여기에 모았다. 아래 항목이 확정되기 전까지 "영향받는 시나리오" 는 작성은 되어 있으나 실행·판정이 보류된다.
| # | 대상 | 현재 상태 | 확정 주체 | 확정 시점·트리거 | 근거 문서 | 영향받는 시나리오 |
|---|---|---|---|---|---|---|
| U-1 | 자가 검증 시도 시간 상한의 기본값 | 미정. 존재는 AC-08 이 이미 강제(양의 유한한 값, 미설정·무한대 불허) | Planning | 1단계 스파이크 실측 후 조정 | D-020; planning-inputs §1 표 5행·§6 1행 | Feature 4 — AC-08 2건 |
| U-2 | 프레임 타임 목표치·백분위·측정 환경(빌드 모드·하드웨어 등급·플랫폼)·시나리오(스크롤 속도·조작 종류)·표본 창 | 미정. p95 16.7ms 는 확정값이 아니다 |
Planning | A-03 로드맵 1단계 스파이크 실측 후 | planning-inputs §3.3(108행 경고) | Feature 9 — AC-15 |
| U-3 | 참조 워크스페이스 커밋 SHA (coco-de/unibook) |
미정. 고정 없이는 날짜마다 다른 대상을 측정. 줄 수도 추정치이므로 명세 기재 전 실제 체크아웃 검증 필요 | Planning | 벤치마크 착수 전 | planning-inputs §3.2(98·102행)·§6 5행 | Feature 9 — AC-15 |
| U-4 | A-02 스파이크 표본 수·합격 기준 | 미정 — 미설정 자체가 C-04 전환 조항의 발동 조건이므로 안전 측 기본값이 작동 | Planning | 스파이크 실측 분포 확인 후 | D-020; planning-inputs §1 표 6행·§6 2행 | Feature 4 — AC-17 2건 |
| U-5 | allowed_hosts·write_exceptions 기본 목록의 구체적 내용, 의존성 파생분 추출 알고리즘 |
기본 목록은 조사분 존재(§2.1·§2.3·§2.4), 추출 알고리즘은 미정 | Planning | 매니페스트 범위·전이 의존성 포함 여부·재계산 시점 결정 시 | planning-inputs §2.5·§6 4행 | Feature 8 — AC-14 전체 |
| U-6 | 플랫폼별 입력기 지정·입력 코퍼스·시행 횟수·관찰 방법 | 미정 | Planning | IME 스파이크 설계 시 | planning-inputs §4.3 | Feature 2 — AC-16 |
| ~~U-7~~ | "테스트 파일"의 판정 규칙 | ✅ 해소 — Seed Spec v3.1.0 ② (오너 결정). 워크스페이스의 test/ · integration_test/ · widgetbook/ 디렉터리 아래 파일로 판정한다 — 경로 기반이라 판정이 필요 없다(C-05 본문 · AC-11). 이전에 기록한 「확정 주체 불일치」(C-05 는 Planning, spec-evaluation 은 Design)는 오너가 직접 정하면서 무의미해졌다 |
— | 해소됨 | seed-spec C-05·AC-11 (v3.1.0 ②) | Feature 5 — 판정 가능 |
| ~~U-8~~ | C-04 ①~④의 "적용 불가" 판정 규칙 | ✅ 해소 — D-053 (#64). 대상없음 사유 코드 폐쇄 5종으로 확정됐고(no_target:build_no_configured_target · test_zero_collected · no_debug_session · file_not_analyzed · no_registered_parser) 자유 서술을 받지 않는다. 값 집합의 SSOT 는 docs/verification-no-target-cocode.md §5 표다 |
— | 해소됨 | D-053; architecture §6.1 | Feature 4 — AC-09 ⑤ 판정 가능 |
| ~~U-9~~ | 프로바이더/ACP 에이전트 "응답 불가" 감지 기준, 그리고 "무한 대기하지 않는다"의 시간 경계 | ✅ 해소 — architecture §6.2 DD-22 / D-060 (#50). 감지기는 이벤트 스트림 하나만 보며 신호는 둘이다 — S1 전송 종료(TransportClosed) · S2 유휴 초과(마지막 AgentEvent 이후 경과 > 유휴 상한). 둘 다 판정이 개입하지 않는다(사건 발생 여부·시각 비교). 전이 대상은 실패. ⚠️ 유휴 상한의 값은 별개 항목이며 AC-08 출하 기본값과 함께 여전히 미정이다(U-1) |
— | 해소됨 | architecture §6.2 (DD-22 · D-060); unresponsive-detection-cocode.md |
Feature 3 — AC-20 판정 가능 |
| ~~U-10~~ | 롤백 충돌 판정의 비교 대상 | ✅ 해소 — Seed Spec v3.1.0 ①. EditSnapshot 에 result_content_hash(편집 직후 해시)를 신설하고 충돌 판정을 «현재 해시 ≠ 그 파일의 마지막 result_content_hash» 로 교체했다. base_content_hash 는 복원 목표로 역할이 분리됐다 |
— | 해소됨 | seed-spec §3 EditSnapshot (v3.1.0 ①) | Feature 1 — AC-02 판정 가능(보류 시나리오 0건 — 아래 ⚠️) |
| U-11 | 대기 중 두 번째 작업의 status 값 | 미정 — Seed Spec 이 status 값을 규정하지 않음 | Design | 잠금 큐 설계 시 | seed-spec §3 status 값 집합(79행) | Feature 6 — AC-12 |
| ~~U-12~~ | Must-Not(AC-04·AC-05)의 부재 증명 관찰 방법 | ✅ 해소 — D-072 (#98). .github/scripts/check_mvp_scope_must_not.py 가 cocode ADE 자신의 소스에서 해당 식별자의 부재를 확인하고 test_check_mvp_scope_must_not.py 가 그 발동을 고정한다. ⚠️ AC-21 은 U-12 에 들어 있지 않다(v3.1.0 신설이라 U-12 보다 늦다) — 그 관찰 방법은 #98 이 새로 정했고 같은 가드가 담당한다 |
— | 해소됨 | seed-spec AC-04·AC-05·AC-21; D-072 | Feature 2 — AC-04·AC-05·AC-21 판정 가능 |
1. Feature 모음
Feature 1 — 에이전트 편집의 diff 검토와 롤백
Feature: 에이전트 편집의 diff 검토와 롤백
Dart/Flutter 개발자로서
자리를 비운 사이 에이전트가 만든 편집을 되돌릴 수 있어야
안심하고 작업을 위임할 수 있다
# 출처: Seed Spec AC-01, AC-02, AC-19 / C-02 / EditSnapshot·DelegatedTask 불변식
# ✅ 판정 규칙 확정(U-10 해소 — Seed Spec v3.1.0 ①) — 롤백 충돌은
# **«현재 해시 ≠ 그 파일의 마지막 `result_content_hash`»** 로 판정한다.
# `base_content_hash`(편집 **직전** 해시)는 복원 **목표**이지 판정 기준이 아니다 —
# 그것으로 판정하면 에이전트 편집 직후의 내용은 정의상 base 와 달라 **모든 롤백이
# 충돌로 보고**되고 안전장치가 무력화된다. v3.1.0 이 고친 것이 바로 그 버그다.
@happy-path
Scenario: [AC-01] 작업을 열면 변경된 모든 파일의 diff 가 표시된다
Given 작업 "T" 의 에이전트가 파일 "lib/a.dart" 와 "lib/b.dart" 를 편집했다
And 그 편집에 대응하는 EditSnapshot 이 파일별로 존재한다
When 사용자가 화면에서 작업 "T" 를 연다
Then 변경된 파일 목록에 "lib/a.dart" 와 "lib/b.dart" 가 모두 나타난다
And 두 파일 각각에 대해 EditSnapshot 의 diff 가 표시된다
@edge-case
Scenario: [AC-01] 종결 상태가 아닌 작업도 지금까지의 diff 를 보여준다
# AC-01 의 Given 은 "에이전트가 파일을 편집한 DelegatedTask가 존재할 때" 이며
# status 를 한정하지 않는다. 종결 상태(완료·실패·롤백됨, Seed Spec §0)로 좁히지 않는 읽기.
Given 작업 "T" 의 status 가 "실행중" 이다
And 작업 "T" 의 에이전트가 파일 "lib/a.dart" 를 편집해 EditSnapshot 1건을 남겼다
When 사용자가 화면에서 작업 "T" 를 연다
Then "lib/a.dart" 의 diff 가 표시된다
@edge-case
Scenario: [UX-D-27] 편집이 0건인 작업을 열면 빈 diff 목록이 제시되고 오류가 발생하지 않는다
# flow-permutation:326 B-16 의 문면. 라벨이 [AC-01] 이 **아닌** 이유:
# AC-01(seed:103)의 Given 은 "에이전트가 파일을 편집한 DelegatedTask" 라
# 편집 0건은 그 사정 밖이다(flow-permutation:130). 그 AC 의 증거로 쓰면
# 범위를 넓혀 읽는 것이 되므로, 동작을 신설한 UX-D 번호를 라벨로 쓴다
# (bdd:203 [C-02] · :218 [불변식] 의 비-AC 라벨 관례).
# 규칙 출처: ux-spec UX-D-27 (#89).
Given 작업 "T" 의 에이전트가 어떤 파일도 편집하지 않았다
And 작업 "T" 에 대응하는 EditSnapshot 이 0건이다
When 사용자가 화면에서 작업 "T" 를 연다
Then 변경 파일 목록이 0건으로 표시된다
And 빈 화면 표시가 제시된다
And 오류가 발생하지 않는다
And [작업 시작 직전 상태로 되돌리기] 와 [롤백] 이 모두 비활성으로 표시된다
And 두 컨트롤에 같은 비활성 사유가 함께 표시된다
@happy-path
Scenario: [AC-02] 특정 스냅샷으로 롤백하면 그 이후 편집이 함께 원자적으로 되돌아간다
# 부분 롤백 후의 status 는 단언하지 않는다 — DelegatedTask 불변식 5 는 "롤백됨" 도달의
# 필요조건(사용자의 명시적 요청)만 규정하며, sequence_no 1 을 남긴 채 2·3 만 되돌린 작업이
# 종결 상태(§0)로 전이한다는 규정은 Seed Spec 어디에도 없다.
Given 작업 "T" 가 "lib/a.dart" 에 sequence_no 1 과 3 의 EditSnapshot 을 남겼다
And 작업 "T" 가 "lib/b.dart" 에 sequence_no 2 의 EditSnapshot 을 남겼다
And 두 파일 모두 작업 "T" 의 편집 이후 사람이 직접 편집하지 않았다
When 사용자가 sequence_no 1 의 EditSnapshot 으로 롤백을 요청한다
Then sequence_no 1 이후에 같은 작업이 만든 EditSnapshot(2, 3)이 함께 되돌아간다
And 되돌림은 전부 적용되거나 전부 적용되지 않는다
@edge-case
Scenario: [AC-02] 작업 시작 직전 상태로 롤백하면 그 작업의 첫 편집도 되돌아간다
# 경계: 각 파일의 최소 sequence_no 지점(EditSnapshot 불변식 4).
Given 작업 "T" 가 "lib/a.dart" 에 sequence_no 1 과 4 의 EditSnapshot 을 남겼다
And 작업 "T" 가 "lib/b.dart" 에 sequence_no 2 의 EditSnapshot 을 남겼다
And 두 파일 모두 작업 "T" 의 편집 이후 사람이 직접 편집하지 않았다
When 사용자가 "작업 시작 직전 상태" 로 롤백을 요청한다
Then "lib/a.dart" 는 sequence_no 1 의 base_content_hash 가 가리키는 내용으로 복원된다
And "lib/b.dart" 는 sequence_no 2 의 base_content_hash 가 가리키는 내용으로 복원된다
And 작업 "T" 의 EditSnapshot 이 하나도 남지 않고 전부 되돌아간다
@error-handling
Scenario: [AC-02] 사람이 그 사이 직접 편집한 파일은 자동 적용 대신 충돌로 제시된다
# EditSnapshot 불변식 2. 판정 조건은 불변식 2 의 괄호 정의를 그대로 쓴다 — U-10 참조.
Given 작업 "T" 가 "lib/a.dart" 에 EditSnapshot 을 남겼다
And 사용자가 그 이후 "lib/a.dart" 를 에디터로 직접 편집했다
When 사용자가 그 EditSnapshot 으로 롤백을 요청한다
Then 롤백이 자동으로 적용되지 않는다
And "lib/a.dart" 가 충돌로 제시된다
@error-handling
Scenario: [AC-02] 대상 파일 중 하나라도 충돌하면 어떤 파일도 되돌아가지 않는다
# AC-02 의 충돌 조항과 EditSnapshot 불변식 3(원자성 — "전부 적용되거나 전부 적용되지 않는다")을
# 함께 읽은 결과. 두 조항을 결합한 판정이며 어느 한쪽 문장에 단독으로 적혀 있지는 않다.
Given 작업 "T" 가 "lib/a.dart" 와 "lib/b.dart" 에 EditSnapshot 을 남겼다
And "lib/a.dart" 는 작업 "T" 의 편집 이후 사람이 직접 편집하지 않았다
But 사용자가 그 이후 "lib/b.dart" 를 에디터로 직접 편집했다
When 사용자가 작업 시작 직전 상태로 롤백을 요청한다
Then "lib/a.dart" 도 되돌아가지 않는다
And "lib/b.dart" 가 충돌로 제시된다
@error-handling
Scenario: [AC-19] 실패한 작업의 편집은 조용히 폐기되지도 확정되지도 않는다
Given 작업 "T" 의 status 가 "실패" 로 전이했다
And 작업 "T" 는 실패 전까지 "lib/a.dart" 를 편집해 EditSnapshot 을 남겼다
When 사용자가 작업 "T" 를 연다
Then 그때까지 적용된 편집의 diff 가 표시된다
And 롤백 수단이 함께 제공된다
And 사용자의 조작 없이 편집이 폐기되거나 확정되지 않는다
@error-handling
Scenario: [AC-19] 재시도가 남긴 모든 시도의 편집이 시도 경계와 함께 제시된다
# 출처: AC-19(seed:121) + C-02(seed:61) + D-030(누적 확정).
# flow-permutation B-15 "retry_count 가 3인 시점의 편집과 3을 초과한 시점의 편집이
# 모두 diff 에 나타난다" 를 시도 경계 표시와 함께 고정한다 — 경계를 붙이는 것이
# 편집을 **감추는** 것이 아님을 이 시나리오가 못박는다(D-030 은 누적이지 되감기가 아니다).
Given 작업 "T" 의 completion_mode 가 "자가검증" 이다
And 작업 "T" 가 자가 검증에 실패해 재시도를 반복한 끝에 status 가 "실패" 로 전이했다
And 각 시도가 "lib/a.dart" 를 편집해 EditSnapshot 을 남겼다
When 사용자가 작업 "T" 를 연다
Then 모든 시도가 남긴 편집이 diff 에 나타난다
And 각 EditSnapshot 이 어느 시도의 것인지 attempt_no 로 구분된다
And 재시도가 직전 시도의 편집을 자동으로 되돌린 흔적이 없다
@edge-case
Scenario: [C-02] 에이전트의 파일 편집은 EditSnapshot 없이 존재할 수 없다
# 출처: C-02 + EditSnapshot 불변식 1. §4 AC 가 아니라 §2·§3 에서 온 보충 시나리오.
Given 작업 "T" 의 에이전트가 파일 "lib/a.dart" 를 편집한다
When 편집이 워크스페이스에 반영된다
Then "lib/a.dart" 에 대응하는 EditSnapshot 이 존재한다
And 그 EditSnapshot 은 Seed Spec §3 EditSnapshot 이 열거한 속성 전수를 갖는다
# ⚠️ 속성을 여기서 다시 열거하지 않는다 — 초판은 6종을 적었고 v3.1.0 의
# result_content_hash 신설을 반영하지 못한 채 낡아 있었다. 전수 판정은
# core 의 엔티티 테스트(`edit_snapshot_test.dart`)가 수행한다.
@edge-case
Scenario: [C-02] 사람이 에디터로 직접 한 편집은 EditSnapshot 대상이 아니다
# C-02 Rationale: "사람이 에디터로 직접 하는 편집은 이 제약의 대상이 아니다"
Given 사용자가 에디터에서 "lib/a.dart" 를 직접 편집한다
When 편집이 저장된다
Then 그 편집에 대해 EditSnapshot 이 생성되지 않는다
@edge-case
Scenario: [불변식] "롤백됨" 은 사용자의 명시적 롤백 요청으로만 도달한다
# 출처: DelegatedTask 불변식 5. §4 AC 가 아니라 §3 에서 온 보충 시나리오.
# 이 불변식은 "롤백됨" 도달의 필요조건만 규정한다 — 어떤 롤백 요청이 작업을 "롤백됨" 으로
# 보내는지(전량인지 부분도 포함인지)는 Seed Spec 이 규정하지 않으므로 단언하지 않는다.
Given 작업 "T" 의 status 가 "실패" 이다
When 사용자가 롤백을 요청하지 않는다
Then 작업 "T" 의 status 는 "롤백됨" 으로 전이하지 않는다
Feature 2 — MVP 범위와 데스크톱 개발자 인터페이스
Feature: MVP 범위와 데스크톱 개발자 인터페이스
# 출처: Seed Spec AC-03, AC-04, AC-05, AC-16 / C-01, C-03
@happy-path
Scenario Outline: [AC-03] MVP 대상 3개 플랫폼 각각에서 개발자용 인터페이스가 제공된다
# 플랫폼 3종은 C-01 이 규범적으로 명시(출처표 5행: 프로젝트 오너 확답 D-016).
Given cocode ADE 가 MVP 로 출시된 시점이다
When 사용자가 "<플랫폼>" 에서 애플리케이션을 실행한다
Then 코드 에디터가 제공된다
And 파일 트리가 제공된다
And 터미널이 제공된다
Examples:
| 플랫폼 |
| macOS |
| Windows |
| Linux |
@edge-case
Scenario: [AC-04] 드리머 모드는 MVP 에 존재하지 않는다
# Must-Not. C-01: 비개발자용 자연어 전용 "드리머 모드"는 MVP 이후로 순연(D-001).
# ✅ 관찰 방법 확정(U-12 해소 · D-072, #98) —
# `.github/scripts/check_mvp_scope_must_not.py` 가 cocode ADE 자신의 소스
# (`package/cocode_*/lib|bin`, 그리고 `app/cocode` 가 `core` 를 의존하기
# 시작하면 `app/cocode/lib`)에서 그 모드를 가리키는 식별자의 **부재**를 확인한다.
# ⚠️ 한계 — 다른 이름으로 같은 기능이 들어오면 잡지 못한다. **유일한 방어가
# 아니라 재유입 경보**이고 범위 판정 자체는 사람의 리뷰가 한다
# (`check_window_api_seal.py` 도 같은 성질이다).
Given cocode ADE MVP 출시 범위이다
When 사용자가 애플리케이션이 제공하는 기능을 확인한다
Then 코드 뷰 없이 자연어만으로 조작하는 모드가 제공되지 않는다
@edge-case
Scenario: [AC-05] 새 워크스페이스 생성 시 Dart/Flutter 이외 언어는 1급 프로젝트 타입이 아니다
# ✅ 관찰 방법 확정(U-12 해소 · D-072, #98) — 같은 가드가 프로젝트 타입 열거에
# 비-Dart/Flutter 언어 항목이 **0건**임을 확인한다. 프로젝트 «안» 의 비-Dart
# 파일 편집은 AC-05 본문이 명시적으로 제외하므로 패턴에 넣지 않는다(아래 시나리오).
# Must-Not. "1급 프로젝트 타입" 의 정본 정의는 Seed Spec §0 용어집이며 **두 조건의 곱**이다:
# ⓐ 선택지로 제시되고 ⓑ 스캐폴딩·언어 지원·에이전트 도구가 그 타입을 전제로 동작한다.
# ("단순히 파일을 열 수 있음은 1급이 아니다")
# 따라서 "선택지에 아예 나타나지 않는다" 로 좁히면 AC-05 보다 강한 조건이 되어
# 적합한 구현을 탈락시킬 수 있다 — 두 조건의 동시 성립 여부로 판정한다.
Given 사용자가 새 워크스페이스 생성을 시작한다
When 사용자가 프로젝트 타입 선택지를 확인한다
Then Dart/Flutter 이외의 언어에 대해 §0 정의의 두 조건(선택지 제시 + 그 타입을 전제로 한 스캐폴딩·언어 지원·에이전트 도구 동작)이 동시에 성립하지 않는다
@happy-path
Scenario: [AC-05] Dart/Flutter 프로젝트 내부의 비-Dart 파일 편집은 제한되지 않는다
# AC-05 후단 + C-03: CI 설정·네이티브 빌드 파일·생성된 자산 등 Dart 가 아닌 모든 파일.
# 차단 "사유" 는 외부에서 관찰할 수 없으므로 사유를 단언하지 않고 차단 여부만 판정한다.
Given 워크스페이스 "W" 는 Dart/Flutter 프로젝트다
And 워크스페이스 "W" 안에 비-Dart 파일이 존재한다
When 에이전트가 그 비-Dart 파일을 편집한다
Then 편집이 차단되지 않는다
@edge-case
Scenario: [AC-21] 워크트리 격리와 에이전트 간 작업 인계는 MVP 에 존재하지 않는다
# Must-Not. v3.1.0 ③ 신설(오너 결정) — C-03 본문에도 반영됐다.
# ✅ 관찰 방법 확정(D-072, #98) — U-12 는 AC-04·AC-05 만 다루므로(AC-21 은 U-12 보다
# 늦게 신설됐다) 이 관찰 방법은 #98 이 **새로 정한** 것이다:
# `.github/scripts/check_mvp_scope_must_not.py` 가 ⓐ 작업별 워크트리 생성·격리
# ⓑ 에이전트 간 작업 인계를 가리키는 식별자의 **부재**를 확인한다.
Given cocode ADE MVP 출시 범위이다
When 사용자가 애플리케이션이 제공하는 기능을 확인한다
Then 작업마다 별도 워크트리를 만들어 격리하는 기능이 제공되지 않는다
And 한 에이전트의 작업을 다른 에이전트가 이어받는 인계 기능이 제공되지 않는다
@happy-path
Scenario: [AC-21/AC-12] 한 워크스페이스 안의 복수 작업 동시 진행은 이 제한과 무관하다
# ⛔ AC-21 본문이 명시한다 — "한 워크스페이스 안에서 복수 DelegatedTask 를 동시
# 진행하고 파일 단위로 잠그는 AC-12 는 이 제한과 무관하다".
# 이 시나리오가 없으면 AC-21 을 넓게 읽어 AC-12 를 범위 밖으로 오해할 수 있다.
# 가드의 오탐 고정(`test_check_mvp_scope_must_not.py` [2])이 같은 경계를 코드에서 지킨다.
Given 워크스페이스 "W" 가 존재한다
When 작업 "T1" 과 작업 "T2" 가 워크스페이스 "W" 에서 동시에 진행된다
Then 두 작업 모두 진행이 차단되지 않는다
And 파일 단위 잠금으로 서로의 편집이 분리된다
@happy-path
Scenario Outline: [AC-16] 3개 플랫폼 각각의 에디터와 터미널에서 한글 조합 입력이 정상 동작한다
# 설정값 — 플랫폼별 입력기 지정·입력 코퍼스·시행 횟수·관찰 방법: 미정.
# 확정 주체: Planning / 확정 시점: IME 스파이크 설계 시 / 근거: planning-inputs §4.3. (U-6)
# D-016 이 정한 macOS 우선은 게이팅 스파이크의 순서이지 출시 조건의 축소가 아니다 —
# planning-inputs §4.3 의 경고 문단이 이를 명시한다(AC-16 완화에는 Seed Spec 개정이 필요).
Given cocode ADE 가 "<플랫폼>" 에서 실행 중이다
When 사용자가 "<대상>" 에서 한글을 조합 입력한다
Then 조합 중 글자 깨짐이 발생하지 않는다
And 중복 입력이 발생하지 않는다
And 커서 위치 오류가 발생하지 않는다
Examples:
| 플랫폼 | 대상 |
| macOS | 에디터 |
| macOS | 터미널 |
| Windows | 에디터 |
| Windows | 터미널 |
| Linux | 에디터 |
| Linux | 터미널 |
Feature 3 — 에이전트 백엔드 선택과 응답 불가 처리
Feature: 에이전트 백엔드 선택과 응답 불가 처리
# 출처: Seed Spec AC-06, AC-20
@happy-path
Scenario: [AC-06] agent 는 서로 다른 LLM 프로바이더를 2개 이상 제공한다
# "2개 이상" 의 근거는 Seed Spec 출처표 2행: "멀티 LLM" 이 성립하기 위한 정의상 최소값.
# 구체적 조합(Anthropic + OpenAI 호환 게이트웨이)은 D-017 의 구현 선택이며
# 같은 출처표 행이 "이 경계의 일부가 아니다" 라고 명시한다 — 인수 조건에 넣지 않는다.
Given cocode ADE 가 MVP 로 출시된 시점이다
When 사용자가 agent_backend_kind 로 "cocode_agent" 를 선택한다
Then agent_backend_provider 선택지에 서로 다른 LLM 프로바이더가 2개 이상 제시된다
@happy-path
Scenario: [AC-06] acp 로 외부 ACP 에이전트를 1개 이상 연결할 수 있다
# "1개 이상" 의 근거는 Seed Spec 출처표 3행: 경로가 존재함을 보이는 최소값.
# 검증 대상 에이전트 4종(Claude Agent·Codex·Gemini CLI·Copilot CLI)은
# planning-inputs §5.1 + A-05 의 Design 단계 연결 검증 계획이며 이 인수 조건의 값이 아니다.
Given cocode ADE 가 MVP 로 출시된 시점이다
When 사용자가 agent_backend_kind 로 "cocode_acp" 를 선택한다
Then 외부 ACP 에이전트를 1개 이상 연결할 수 있다
@error-handling
Scenario Outline: [AC-20] 백엔드가 응답 불가가 되면 작업은 종결 상태로 전이하고 사유가 제시된다
# ✅ 판정 규칙 확정(U-9 해소 — architecture §6.2 DD-22 / D-060, #50) —
# 감지기는 이벤트 스트림 하나만 보며 신호는 **둘**이다:
# S1 전송 종료(`TransportClosed` — exit·EOF·스트림 종료·인증 거부)
# S2 유휴 초과(마지막 `AgentEvent` 이후 경과 > 유휴 상한)
# 둘 다 **판정이 개입하지 않는다**(사건 발생 여부 · 시각 비교). 연속 오류 횟수는
# 쓰지 않는다 — "이 오류가 재시도 가능한가" 라는 판정이 분쟁 지점이 되기 때문이다.
# ⏸️ 유휴 상한의 **값** 은 별개 항목이며 AC-08 출하 기본값과 함께 여전히 미정이다(U-1).
# 종결 상태의 정본 정의는 Seed Spec §0: 완료·실패·롤백됨.
Given 작업 "T" 의 agent_backend_kind 가 "<백엔드>" 이다
And 작업 "T" 의 status 가 "실행중" 이다
When "<백엔드>" 가 응답 불가 상태로 감지된다
Then 작업 "T" 의 status 가 종결 상태로 전이한다
And 사용자에게 응답 불가 사유가 제시된다
And 작업 "T" 가 무한 대기 상태로 남지 않는다
Examples:
| 백엔드 |
| cocode_agent |
| cocode_acp |
Feature 4 — 자가 검증과 완료 전이 (안전 임계 경로)
Feature: 자가 검증과 완료 전이
# 출처: Seed Spec AC-07, AC-08, AC-09, AC-10, AC-17 / C-04 / DelegatedTask 불변식
# 출처 추가(#32): architecture §7.1 DD-23c — 검증 원문은 워크스페이스 세션 버퍼에만(②) ·
# verification_log 는 회차별 누적(③, attempt_no). 아래 "검증 원문의 열람과 비영속" 블록.
# C-04 자가 검증 방법 정본 5종:
# ① 빌드 성공 ② 테스트 통과 ③ 핫 리로드 후 런타임 오류 없음 ④ 정적 분석 통과
# ⑤ (①~④가 모두 적용 불가한 편집에 한해) 편집 대상 파일의 무결성 확인 —
# 파일이 읽히고, 해당 형식의 파서가 오류를 내지 않으며,
# 정적 분석이 그 파일에 대해 새로운 오류를 보고하지 않음
Background:
Given 워크스페이스 "W" 가 존재한다
And 워크스페이스 "W" 에 DelegatedTask "T" 가 존재한다
# ---------- C-04 전환 조항 (AC-17) — 이 스펙의 최우선 안전 동작 ----------
@edge-case
Scenario Outline: [AC-17] A-02 가 확정되지 않은 상태에서 새 작업의 기본 완료 모드는 사람승인이다
# 태그: §0.3 규칙 2ⓐ(전제가 정상 경로 적용 불가인 예외 조건) + 2ⓑ(기대 결과가 기본값 확인).
# AC-17 의 Given 은 <상황> 의 ⓑ·ⓒ 를 규정한다. ⓐ 는 C-04 전환 조항 본문
# ("가정 A-02의 검증 결과가 Planning 단계에서 정한 기준에 미달하거나") 에서 온다.
# 설정값 — A-02 표본 수·합격 기준: 미정.
# 확정 주체: Planning / 확정 시점: 스파이크 실측 분포 확인 후(D-020) / 근거: planning-inputs §6. (U-4)
Given "<상황>" 이다
When 워크스페이스 "W" 에 새 DelegatedTask "T2" 가 생성된다
Then 작업 "T2" 의 completion_mode 기본값은 "사람승인" 이다
Examples:
| 상황 |
| A-02 의 검증 결과가 Planning 이 정한 기준에 미달한 상태 |
| Planning 단계가 A-02 의 합격 기준을 정하지 않은 상태 |
| A-02 의 검증이 수행되지 않은 상태 |
@edge-case
Scenario: [AC-17] 전환 조항이 발동한 작업은 자가 검증 통과만으로 완료에 도달하지 않는다
Given Planning 단계가 A-02 의 합격 기준을 정하지 않았다
And 새로 생성된 작업 "T" 의 completion_mode 가 "사람승인" 이다
And 작업 "T" 의 에이전트가 편집을 마쳤다
When 작업 "T" 가 자가 검증을 수행해 C-04 의 방법 ①(빌드 성공)을 통과한다
Then 작업 "T" 의 status 가 "사람승인대기" 가 된다
And pending_approval_kind 가 "완료승인" 으로 설정된다
And 작업 "T" 의 status 가 "완료" 로 전이하지 않는다
# ---------- 재시도 상한 (AC-07) ----------
@error-handling
Scenario: [AC-07] 재시도가 3회를 초과하면 실패로 전이하고 사람에게 에스컬레이션한다
# "3회" 의 근거: 출처표 1행 — 프로젝트 오너 확답(D-008) +
# cc-product `references/bmad-config.md` 의 `feedback.maxRetries: 3`. C-04 본문·AC-07·불변식 4.
Given 작업 "T" 의 status 가 "자가검증중" 이다
And 작업 "T" 의 retry_count 가 3 이다
When 자가 검증이 다시 실패해 retry_count 가 3 을 초과한다
Then 작업 "T" 의 status 가 "실패" 로 전이한다
And 사람에게 에스컬레이션된다
And 그 이상 자동 재시도가 발생하지 않는다
@edge-case
Scenario: [AC-07] retry_count 가 3 인 동안에는 실패로 전이하지 않는다
# 경계값. DelegatedTask 불변식 4 는 "retry_count가 3을 초과하거나" 로 규정하므로
# 3 은 아직 상한을 초과한 값이 아니다.
Given 작업 "T" 의 status 가 "자가검증중" 이다
When 자가 검증 실패가 누적되어 retry_count 가 3 이 된다
Then 작업 "T" 의 status 는 retry_count 를 이유로 "실패" 로 전이하지 않는다
# ---------- 검증 실패 원인 분류 (AC-07) — #73 / 일지 D-055 ----------
# `failure_class` 폐쇄 5종과 값별 retry 계수는 `docs/verification-failure-class-cocode.md`
# §3·§4 가 정본이다. 여기서는 그 규칙이 관찰 가능한 형태로 드러나는 3건만 고정한다.
@error-handling
Scenario: [AC-07] 환경 실패로 분류된 검증 실패는 retry_count 를 증가시키지 않는다
# 판정 입력: 프로세스 기동이 ProcessException 으로 실패 → failure:env_tool_unavailable
# (verification-failure-class §3.2 절차 3번). 에이전트가 다시 편집해도 도구는 여전히 없으므로
# 계수하면 고칠 수 없는 것으로 안전장치(D-008 의 3회)를 태운다.
Given 작업 "T" 의 status 가 "자가검증중" 이다
And 작업 "T" 의 retry_count 가 0 이다
When 자가 검증 ④(정적 분석)의 도구 프로세스가 기동하지 못해 검증이 실패한다
Then 그 레코드의 result 가 "실패" 이고 failure_class 가 "failure:env_tool_unavailable" 이다
And 작업 "T" 의 retry_count 가 0 그대로다
And 작업 "T" 의 attempt_no 가 증가하지 않는다
@error-handling
Scenario: [AC-07] 코드 결함으로 분류된 검증 실패는 retry_count 를 증가시킨다
# §3.2 절차의 마지막 포괄 갈래 — 환경 신호가 하나도 관측되지 않으면 코드 결함이다.
# 이것이 현행 거동이며, 환경 실패만이 양성 신호가 있을 때 계수에서 빠진다.
Given 작업 "T" 의 status 가 "자가검증중" 이다
And 작업 "T" 의 retry_count 가 0 이다
When 자가 검증 ④(정적 분석)가 끝까지 실행되어 편집 대상 파일에 새 오류를 보고한다
Then 그 레코드의 result 가 "실패" 이고 failure_class 가 "failure:code_defect" 이다
And 작업 "T" 의 retry_count 가 1 이 된다
@edge-case
Scenario: [AC-07] 같은 실패 횟수에서 두 분류의 retry_count 귀결이 다르다
# 대조 시나리오. 분류가 계수를 가르는 유일한 입력임을 보인다 —
# 실패 횟수가 같아도 환경 실패 쪽은 상한에 도달하지 않는다.
Given 작업 "T1" 과 작업 "T2" 의 status 가 모두 "자가검증중" 이고 retry_count 가 모두 0 이다
When 작업 "T1" 의 자가 검증이 3회 실패하고 그 3회가 모두 "failure:code_defect" 로 분류된다
And 작업 "T2" 의 자가 검증이 3회 실패하고 그 3회가 모두 "failure:env_network_unreachable" 로 분류된다
Then 작업 "T1" 의 retry_count 가 3 이다
And 작업 "T2" 의 retry_count 가 0 이다
And 작업 "T2" 는 retry_count 를 이유로 "실패" 로 전이하지 않는다
# ---------- 시간 상한 (AC-08) ----------
@error-handling
Scenario: [AC-08] 단일 자가 검증 시도가 설정된 시간 상한을 넘기면 중단되고 실패로 기록된다
# 설정값 — 시간 상한의 **기본값**: 미정.
# 확정 주체: Planning / 확정 시점: 1단계 스파이크 실측 후 조정(D-020) /
# 근거: planning-inputs §1 표 5행·§6 1행. (U-1)
# planning-inputs §6: "AC-08 은 설치 직후 양의 유한한 기본값이 존재할 것을 요구하며
# 미설정을 허용하지 않는다. Planning 이 할 일은 그 기본값을 실측 근거로 조정하는 것".
# "실패" 전이와 에스컬레이션의 근거는 DelegatedTask 불변식 4(단일 시도가 시간 상한 초과 시).
Given 작업 "T" 의 status 가 "자가검증중" 이다
And 자가 검증 시도가 진행 중이다
When 그 시도의 경과 시간이 설정된 시간 상한을 넘긴다
Then 그 시도가 중단된다
And 그 시도가 실패로 기록된다
And 작업 "T" 의 status 가 "실패" 로 전이하고 사람에게 에스컬레이션된다
@edge-case
Scenario: [AC-08] 설치 직후 사용자 설정 없이도 시간 상한이 양의 유한한 시간값을 갖는다
Given cocode ADE 를 설치한 직후이며 사용자가 시간 상한을 설정한 적이 없다
When 자가 검증 시도의 시간 상한을 확인한다
Then 시간 상한이 미설정 상태가 아니다
And 시간 상한이 무한대가 아니다
And 시간 상한이 양의 유한한 시간값이다
# ---------- 실행 중 중지 · 승인 거부 (AC-22 · AC-23) — #71 / 일지 D-059 ----------
# status 폐쇄 집합이 9종으로 개정되며(D-032 / seed v3.3.0) 신설된 두 종결 상태의 시나리오다.
# 전이표 81칸은 `docs/state-machine-cocode.md` §2, 중지 호출 경로는
# `docs/stop-and-limits-cocode.md` §4.2 가 정본이다.
@happy-path
Scenario: [AC-22] 실행 중 작업의 중지 요청은 중지됨(종결)으로 전이한다
# AC-22 의 Given 은 `실행중` 또는 `자가검증중` 둘이다 — 전이표 ⑰·⑱.
# 전이가 먼저이고 AgentSession.cancel(CancelReason.userStopped) 이 그 뒤다(§4.2).
Given 작업 "T" 의 status 가 "실행중" 이다
When 사용자가 작업 "T" 의 중지를 요청한다
Then 작업 "T" 의 status 가 "중지됨" 으로 전이한다
And 작업 "T" 는 종결 상태이므로 자동으로 다른 상태로 전이하지 않는다
@edge-case
Scenario: [AC-22] 중지된 작업의 편집은 조용히 폐기되지도 확정되지도 않는다
# AC-19(실패 작업)와 같은 보장이다. 전이표 ㉑ 이 롤백 수단을 연다.
Given 작업 "T" 가 편집 3건을 적용한 뒤 "중지됨" 으로 전이했다
When 사용자가 작업 "T" 를 연다
Then 그때까지 적용된 편집 3건의 diff 가 제공된다
And 롤백 수단이 제공된다
And 사용자의 조작 없이 편집 상태가 변하지 않는다
@happy-path
Scenario: [AC-23] 사람승인대기에서 승인을 거부하면 거부됨(종결)으로 전이한다
# 전이표 ⑲. pending_approval_kind 두 종류에 공통이며, 테스트변경승인 카드의
# [적용하지 않음] 도 이 입력이다(D-058 §2 / prd FR-407).
Given 작업 "T" 의 status 가 "사람승인대기" 이다
When 사용자가 작업 "T" 의 승인을 거부한다
Then 작업 "T" 의 status 가 "거부됨" 으로 전이한다
And pending_approval_kind 가 "없음" 으로 되돌아간다
And 그때까지 적용된 편집의 diff 와 롤백 수단이 제공된다
# ---------- 자가검증 모드의 완료 (AC-09) ----------
@happy-path
Scenario: [AC-09] 적용 가능한 자가 검증 1종 이상을 통과하고 기록한 뒤에만 완료에 도달한다
# "1종 이상" 의 근거는 Seed Spec 출처표 4행: ⑤가 항상 대체 경로로 존재하므로 도달 가능한 최소값.
Given 작업 "T" 의 completion_mode 가 "자가검증" 이다
And 작업 "T" 의 에이전트가 편집을 마쳤다
When 작업 "T" 가 C-04 의 방법 ①(빌드 성공)을 통과한다
And 그 결과가 verification_log 에 기록된다
Then 작업 "T" 의 status 가 "완료" 로 전이한다
@edge-case
Scenario: [AC-09] ⑤로 완료하는 경우 ①~④ 각각의 적용 불가 사유가 기록된다
# ✅ 판정 규칙 확정(U-8 해소 — D-053, #64) — `대상없음` 사유 코드가 **폐쇄 5종**이고
# 자유 서술을 받지 않는다: `no_target:build_no_configured_target` ·
# `test_zero_collected` · `no_debug_session` · `file_not_analyzed` ·
# `no_registered_parser`. 값 집합의 SSOT 는 `verification-no-target-cocode.md` §5 표다.
# ⚠️ ⑤ 가 열리는 조건은 ①~④ 가 **넷 모두** 대상없음일 때다(DD-21a 규칙 3) — 하나라도
# 대상을 가지면 열리지 않는다. #96 실측: 이 경로가 실제로 열리는 비율은 실행자 범위
# 선택에 따라 **0.0% ~ 22.6%** 다(`a02-reliability-measurement-cocode.md` §4).
Given 작업 "T" 의 completion_mode 가 "자가검증" 이다
And 작업 "T" 의 편집에 C-04 의 방법 ①~④ 가 모두 적용 불가하다
When 작업 "T" 가 C-04 의 방법 ⑤(편집 대상 파일의 무결성 확인)를 통과한다
Then verification_log 에 ⑤의 수행 결과가 기록된다
And verification_log 에 ① 이 적용 불가한 사유가 기록된다
And verification_log 에 ② 가 적용 불가한 사유가 기록된다
And verification_log 에 ③ 이 적용 불가한 사유가 기록된다
And verification_log 에 ④ 가 적용 불가한 사유가 기록된다
And 그 뒤에 작업 "T" 의 status 가 "완료" 로 전이한다
@error-handling
Scenario: [AC-09] 통과한 자가 검증 기록이 없으면 완료에 도달하지 않는다
# 후속 status(재시도 계속인지 즉시 실패인지)는 Seed Spec 이 규정하지 않으므로 단언하지 않는다.
# 재시도·시간 상한에 걸리는 경우의 전이는 AC-07·AC-08 이 규정한다.
Given 작업 "T" 의 completion_mode 가 "자가검증" 이다
And 작업 "T" 의 에이전트가 편집을 마쳤다
And 작업 "T" 의 verification_log 에 통과한 자가 검증 결과가 하나도 없다
When 작업 "T" 가 완료 전이를 시도한다
Then 작업 "T" 의 status 가 "완료" 로 전이하지 않는다
# ---------- 검증 원문의 열람과 비영속 · 회차 기록 (AC-09 · DD-23c, #32) ----------
@error-handling
Scenario: [AC-09] 검증 실패 원문은 같은 세션의 [문제] 탭에서 회차·방법별로 볼 수 있다
# 출처: Seed Spec §4 AC-09 + AC-19 + architecture DD-23c-①·② (#32).
# "세션" = 워크스페이스가 cocode ADE 프로세스에 열려 있는 구간(DD-23c-①). 작업 종결은
# 버퍼를 비우지 않는다(①ⓑ) — 그래서 종결된 "T" 의 원문이 이 시나리오에서 보인다.
# 설정값 — 워크스페이스 세션 버퍼 총량 상한: 미정.
# 확정 주체: Design / 확정 시점: #63 구현 시 참조 워크스페이스 실측 후 /
# 근거: architecture §9 미결 20. 이 시나리오는 상한에 걸리지 않는 크기를 전제하므로 값에 종속되지 않는다.
Given 작업 "T" 의 completion_mode 가 "자가검증" 이다
And 작업 "T" 가 C-04 의 방법 ④(정적 분석 통과)에 실패해 재시도 끝에 status 가 "실패" 로 전이했다
And 그 사이 워크스페이스가 닫히거나 앱이 다시 시작된 적이 없다
When 사용자가 작업 "T" 를 열고 하단 [문제] 탭을 연다
Then 실패한 회차·방법의 검증 원문이 표시된다
And 원문 옆에 "검증 원문은 이 세션에서만 볼 수 있습니다" 취지의 고지가 표시된다
And verification_log 에는 그 원문이 아니라 방법·결과·개수·종료 코드·회차만 기록되어 있다
@edge-case
Scenario: [AC-09] 앱을 다시 연 뒤에는 검증 실패 원문이 조회되지 않고 개수·종료 코드·회차만 남는다
# 출처: architecture DD-23b(원문 비영속) + DD-23c-② (#32) — 사후 조회 경로를 신설하지 않는다.
# 태그: §0.3 규칙 2ⓑ(첫 Then 이 부재 확인). "조회되지 않는다" 는 UI 와 `.cocode/history/`
# 어느 경로로도 원문이 나오지 않음을 뜻한다 — 판정 불가 상태가 아니라 단언 가능한 부재다.
Given 작업 "T" 가 C-04 의 방법 ④(정적 분석 통과)에 실패해 status 가 "실패" 로 전이했다
And 사용자가 cocode ADE 를 종료했다가 다시 열고 같은 워크스페이스를 연다
When 사용자가 작업 "T" 를 열고 하단 [문제] 탭을 연다
Then 작업 "T" 의 검증 실패 원문이 조회되지 않는다
And ".cocode/history/" 아래 어디에도 그 원문이 저장되어 있지 않다
And 실패한 회차의 방법·결과·개수·종료 코드는 verification_log 에서 그대로 조회된다
And "검증 원문은 이전 세션에 있었습니다" 취지의 고지가 같은 자리에 표시된다
@edge-case
Scenario: [AC-09] 재시도 회차마다 검증 결과가 회차 번호와 함께 누적되고 완료 판정은 현재 회차만 본다
# 출처: Seed Spec §4 AC-09 + §3 EditSnapshot attempt_no + D-030(누적) + architecture DD-23c-③ (#32).
# 태그: §0.3 규칙 2ⓐ — 전제가 "앞 회차의 실패 기록이 남아 있는" 경계 조건이다.
# 앞 회차의 실패가 현재 회차를 막지 않고, 앞 회차의 통과가 현재 회차의 자격이 되지 않는다
# (architecture §6.1 DD-21a 판정 대상 집합).
Given 작업 "T" 의 completion_mode 가 "자가검증" 이다
And 작업 "T" 의 회차 0 에서 C-04 의 방법 ④(정적 분석 통과)가 실패해 재시도로 회차 1 이 시작됐다
When 작업 "T" 의 회차 1 에서 C-04 의 방법 ①~④ 가 모두 실행되어 ④ 는 통과하고 실패한 방법이 없다
And 그 결과가 verification_log 에 기록된다
Then verification_log 에 회차 0 의 방법 ④ 실패 기록이 그대로 남아 있다
And verification_log 에 회차 1 의 방법 ④ 통과 기록이 별도 레코드로 추가되어 있다
And 각 레코드가 어느 회차의 것인지 attempt_no 로 구분된다
And 작업 "T" 의 status 가 "완료" 로 전이한다
# ---------- 사람승인 모드의 완료 (AC-10) ----------
@happy-path
Scenario: [AC-10] 사람승인 모드는 명시적 승인 후에 완료에 도달한다
Given 작업 "T" 의 completion_mode 가 "사람승인" 이다
And 작업 "T" 의 에이전트가 편집을 마쳤다
And 작업 "T" 의 status 가 "사람승인대기" 이고 pending_approval_kind 가 "완료승인" 이다
When 사용자가 명시적으로 승인한다
Then 작업 "T" 의 status 가 "완료" 로 전이한다
@edge-case
Scenario: [AC-10] 사람승인 모드에서 자가 검증 결과는 정보이지 완료의 관문이 아니다
# DelegatedTask 불변식 2: "이 모드에서 자가 검증 결과는 사용자에게 제시되는 정보이지
# 완료의 관문이 아니다"
Given 작업 "T" 의 completion_mode 가 "사람승인" 이다
And 작업 "T" 가 C-04 의 방법 ①~④ 를 모두 통과했다
When 사용자가 승인하지 않은 채 시간이 지난다
Then 작업 "T" 의 status 가 "사람승인대기" 에 머문다
And 작업 "T" 의 status 가 "완료" 로 전이하지 않는다
And 자가 검증 결과가 사용자에게 제시된다
Feature 5 — 기존 테스트 파일 보호 (안전 임계 경로)
Feature: 기존 테스트 파일 보호
# 출처: Seed Spec AC-11 / C-05 / DelegatedTask 불변식 3
# ✅ 판정 규칙 확정(U-7 해소 — Seed Spec v3.1.0 ②, 오너 결정) — 테스트 파일은
# 워크스페이스의 `test/` · `integration_test/` · `widgetbook/` 아래 파일이다.
# **경로 기반이라 판정이 필요 없다**(C-05 본문 · AC-11).
# 이전에 남겼던 「확정 주체 불일치」(C-05 는 Planning, spec-evaluation 은 Design)는
# 오너가 값을 직접 정하면서 무의미해졌다 — 누가 정하는가가 아니라 **무엇으로 정해졌는가**
# 가 남았고, 그것이 위 세 디렉터리다. 아래 픽스처 "test/a_test.dart" 는 그 규약을 따른다.
# ⚠ 판정 규칙 설계 원칙: 변경의 "성격" 을 판정하지 않는다 — 기존 테스트 파일에 대한
# **모든 변경**이 승인 대상이므로 edge case 를 분류할 필요가 없다(C-05 Rationale, D-014).
Background:
Given 워크스페이스 "W" 에 기존 테스트 파일로 판정되는 "test/a_test.dart" 가 존재한다
And 워크스페이스 "W" 에 DelegatedTask "T" 가 존재한다
@error-handling
Scenario: [AC-11] 기존 테스트 파일 변경은 사람의 명시적 승인 없이 적용되지 않는다
Given 작업 "T" 의 에이전트가 "test/a_test.dart" 의 내용을 변경하려 한다
When 그 변경을 적용하려 한다
Then 작업 "T" 의 status 가 "사람승인대기" 로 전이한다
And pending_approval_kind 가 "테스트변경승인" 으로 설정된다
And 사용자의 명시적 승인 전까지 "test/a_test.dart" 의 내용이 변경되지 않는다
@happy-path
Scenario: [AC-11] 승인 후에 기존 테스트 파일 변경이 적용된다
Given 작업 "T" 의 status 가 "사람승인대기" 이고 pending_approval_kind 가 "테스트변경승인" 이다
When 사용자가 그 테스트 변경을 명시적으로 승인한다
Then "test/a_test.dart" 에 대한 변경이 적용된다
@happy-path
Scenario: [AC-11] 새 테스트 파일 생성만이 이 제한의 예외다
Given 워크스페이스 "W" 에 "test/b_test.dart" 가 존재하지 않는다
When 작업 "T" 의 에이전트가 새 테스트 파일 "test/b_test.dart" 를 생성한다
Then 생성이 승인 없이 진행된다
And 작업 "T" 의 status 가 "사람승인대기" 로 전이하지 않는다
And pending_approval_kind 가 "테스트변경승인" 으로 설정되지 않는다
@edge-case
Scenario Outline: [AC-11] completion_mode 와 무관하게 동일하게 승인 대상이다
# 태그: §0.3 규칙 1(미승인 변경 시도의 처리)과 2(조합 커버리지)에 모두 걸치나,
# 이 시나리오의 목적이 두 completion_mode 조합의 커버리지이므로 @edge-case 로 둔다.
# 배정에 다툼이 있어도 게이트 요건(각 태그 1건 이상)에는 영향이 없다 — §0.3 참조.
# DelegatedTask 불변식 3: "completion_mode와 무관하게, 기존 테스트 파일 변경이 포함된 작업은
# 그 변경을 적용하기 전에 '사람승인대기'(pending_approval_kind=테스트변경승인)로 전이한다"
Given 작업 "T" 의 completion_mode 가 "<모드>" 이다
When 작업 "T" 의 에이전트가 "test/a_test.dart" 의 내용을 변경하려 한다
Then 작업 "T" 의 status 가 "사람승인대기" 로 전이한다
And pending_approval_kind 가 "테스트변경승인" 으로 설정된다
Examples:
| 모드 |
| 자가검증 |
| 사람승인 |
@edge-case
Scenario: [AC-11] 케이스를 덧붙이기만 하는 변경도 성격을 판정하지 않고 승인 대상이다
# C-05: "기존 테스트 파일에 대한 모든 변경(케이스 추가 포함)".
# AC-11: "변경의 성격을 판정하지 않고".
Given 작업 "T" 의 에이전트가 "test/a_test.dart" 에 테스트 케이스를 추가하기만 하려 한다
And 기존 케이스를 삭제하거나 단언을 약화하지 않는다
When 그 변경을 적용하려 한다
Then 변경의 성격에 대한 판정이 수행되지 않는다
And 작업 "T" 의 status 가 "사람승인대기" 로 전이한다
And pending_approval_kind 가 "테스트변경승인" 으로 설정된다
Feature 6 — 파일 편집 잠금과 비정상 종료 복구 (안전 임계 경로)
Feature: 파일 편집 잠금과 비정상 종료 복구
# 출처: Seed Spec AC-12, AC-18 / Workspace 불변식 2
Background:
Given 워크스페이스 "W" 가 존재한다
And 워크스페이스 "W" 에 DelegatedTask "T1" 과 "T2" 가 존재한다
@edge-case
Scenario: [AC-12] 같은 파일을 편집하려는 두 번째 작업은 대기한다
# 대기 중 "T2" 의 status 값은 Seed Spec 이 규정하지 않으므로 단언하지 않는다 — Design 결정(U-11).
Given 작업 "T1" 이 "lib/a.dart" 를 편집 중이다
And 워크스페이스 "W" 의 edit_locks 에 "lib/a.dart" 가 포함되어 있다
When 작업 "T2" 가 "lib/a.dart" 에 접근한다
Then 작업 "T2" 는 "lib/a.dart" 를 편집하지 않는다
And 작업 "T2" 는 작업 "T1" 이 그 파일의 편집을 마칠 때까지 대기한다
And "lib/a.dart" 에 대한 동시 편집이 발생하지 않는다
@happy-path
Scenario: [AC-12] 첫 번째 작업이 그 파일의 편집을 마치면 잠금이 해제되고 두 번째가 진행한다
Given 작업 "T1" 이 "lib/a.dart" 를 편집 중이고 작업 "T2" 가 대기 중이다
When 작업 "T1" 이 "lib/a.dart" 의 편집을 마친다
Then 워크스페이스 "W" 의 edit_locks 에서 "lib/a.dart" 가 제거된다
And 작업 "T2" 가 "lib/a.dart" 를 편집할 수 있다
@edge-case
Scenario: [AC-12] 승인을 기다리는 동안에는 잠금을 유지하지 않는다
# Workspace 불변식 2: "잠금은 에이전트가 그 파일의 편집을 마치는 시점에 해제되며,
# 작업이 사람의 승인을 기다리는 동안 잠금을 유지하지 않는다"
Given 작업 "T1" 이 "lib/a.dart" 의 편집을 마쳤다
And 작업 "T1" 의 status 가 "사람승인대기" 이다
When 워크스페이스 "W" 의 edit_locks 를 확인한다
Then edit_locks 에 "lib/a.dart" 가 포함되어 있지 않다
And 작업 "T2" 가 "lib/a.dart" 를 편집할 수 있다
@error-handling
Scenario: [AC-18] 에이전트 프로세스가 비정상 종료하면 그 작업의 파일 잠금이 해제된다
Given 작업 "T1" 이 "lib/a.dart" 를 편집 중이다
And 워크스페이스 "W" 의 edit_locks 에 "lib/a.dart" 가 포함되어 있다
When 작업 "T1" 의 에이전트 프로세스가 편집 도중 비정상 종료한다
Then 워크스페이스 "W" 의 edit_locks 에서 "lib/a.dart" 가 제거되어 있다
And 작업 "T2" 가 "lib/a.dart" 를 편집할 수 있다
Feature 7 — 워크스페이스 스캐폴딩 원자성
Feature: 워크스페이스 스캐폴딩 원자성
# 출처: Seed Spec AC-13 / Workspace 불변식 3 / Workspace 속성 applied_bricks
@happy-path
Scenario: [AC-13/불변식] brick 스캐폴딩이 끝까지 성공하면 워크스페이스가 생성된다
# ⚠ 출처 주의 — AC-13 은 **실패 경로만** 규정한다("Given brick 스캐폴딩이 진행 중 실패할 때").
# 성공 경로의 근거는 Workspace 불변식 3("전량 성공 또는 전량 롤백")과
# Workspace 속성 applied_bricks 다. ⚠️ 2026-09-10 개정(D-037 / 이슈 #113): co-brick
# 덧붙이기는 **MVP 범위 밖**(AC-24 Must-Not)이므로 이 목록은 최초 스캐폴딩 brick 만
# 담으며 MVP 에서 원소는 1개다.
Given 사용자가 brick 을 선택해 새 워크스페이스 생성을 요청한다
When 스캐폴딩이 끝까지 성공한다
Then 워크스페이스가 생성된다
And 워크스페이스의 applied_bricks 에 그 brick 이 기록된다
@error-handling
Scenario: [AC-13] 스캐폴딩이 진행 중 실패하면 부분 생성 파일이 전량 제거된다
Given 사용자가 brick 을 선택해 새 워크스페이스 생성을 요청한다
And 스캐폴딩이 일부 파일을 이미 생성했다
When 스캐폴딩이 실패한다
Then 부분 생성된 파일이 전량 제거된다
And 워크스페이스가 생성되지 않은 상태로 남는다
Feature 8 — 에이전트 샌드박스 경계
Feature: 에이전트 샌드박스 경계
# 출처: Seed Spec AC-14 / Workspace 속성 allowed_hosts, write_exceptions
# AC-14 가 정한 인수 대상: ⓐ 두 목록이 비어 있지 않은 유효한 값으로 초기화되어 있을 것
# ⓑ 위반 시도가 차단될 것
# 설정값 — 두 목록의 **구체적 내용**: planning-inputs §2.1(필수 호스트 표, 단일 SSOT)·
# §2.3(차단해도 되는 호스트)·§2.4(밖 쓰기 경로 표). 의존성 파생분의 **추출 알고리즘**은
# D-050 ①(#39)이 확정했다 — lock 우선 · 전이 포함 · 게이트가 매니페스트 변경을 알리는
# 시점에 재계산 · 세션 고정. (U-5 해소)
# ⚠ 개수를 인용하지 않는 이유 — **영구 규칙이다**(D-051, #39 · 오너 결정 #109).
# D-018 「최소 11종」 · §2.1 표 12행 · D-021 「12종」의 불일치는 어느 쪽도 정본으로
# 고르지 않고 **목록 자체를 단일 SSOT** 로 두는 것으로 닫혔다 — #38 의 3-OS 실측이
# 표에 없던 api.github.com 을 찾아 11 도 12 도 측정과 어긋났기 때문이다. 그래서 이
# 문서는 어떤 개수도 쓰지 않고 "비어 있지 않다" 만 검증한다.
# 허용 방향(내부 경로·등록 호스트가 동작한다)은 AC-14 ⓐ 의 여집합이며
# AC-01·C-02(에이전트가 워크스페이스 파일을 편집한다)가 전제하는 바다.
Background:
Given 워크스페이스 "W" 가 존재한다
And 작업 "T" 가 워크스페이스 "W" 에서 실행 중이다
@edge-case
Scenario: [AC-14] 설치 직후 두 목록이 비어 있지 않은 유효한 값으로 초기화되어 있다
Given cocode ADE 를 설치한 직후이며 사용자가 목록을 편집한 적이 없다
When 워크스페이스 "W" 의 allowed_hosts 와 write_exceptions 를 확인한다
Then allowed_hosts 가 비어 있지 않다
And write_exceptions 가 비어 있지 않다
@happy-path
Scenario: [AC-14] allowed_hosts 에 있는 호스트로의 네트워크 요청은 허용된다
Given 호스트 "H" 가 워크스페이스 "W" 의 allowed_hosts 에 포함되어 있다
When 작업 "T" 의 에이전트가 호스트 "H" 로 네트워크 요청을 보낸다
Then 요청이 차단되지 않는다
@error-handling
Scenario: [AC-14] allowed_hosts 에 없는 호스트로의 네트워크 요청은 차단된다
Given 호스트 "X" 가 워크스페이스 "W" 의 allowed_hosts 에 포함되어 있지 않다
When 작업 "T" 의 에이전트가 호스트 "X" 로 네트워크 요청을 보낸다
Then 요청이 차단된다
@happy-path
Scenario: [AC-14] 워크스페이스 내부 경로의 파일은 수정할 수 있다
# 원래 Scenario Outline 이었으나 Examples 값이 따옴표를 포함해 `"<경로>"` 자리에서
# 중첩 따옴표가 되고 Given 이 동어반복이 되어 실행 불가였다 — 두 시나리오로 분해했다.
Given 경로 "P1" 이 워크스페이스 "W" 의 경로다
When 작업 "T" 의 에이전트가 "P1" 의 파일을 수정한다
Then 수정이 차단되지 않는다
@happy-path
Scenario: [AC-14] write_exceptions 에 등록된 경로의 파일은 수정할 수 있다
Given 경로 "P2" 가 워크스페이스 "W" 의 경로가 아니다
And 경로 "P2" 가 워크스페이스 "W" 의 write_exceptions 에 포함되어 있다
When 작업 "T" 의 에이전트가 "P2" 의 파일을 수정한다
Then 수정이 차단되지 않는다
@error-handling
Scenario: [AC-14] 워크스페이스 밖이고 write_exceptions 에도 없는 경로의 파일은 수정되지 않는다
Given 경로 "P3" 가 워크스페이스 "W" 의 경로가 아니다
And 경로 "P3" 가 워크스페이스 "W" 의 write_exceptions 에 포함되어 있지 않다
When 작업 "T" 의 에이전트가 "P3" 의 파일을 수정하려 한다
Then 수정이 차단된다
And "P3" 의 파일 내용이 변경되지 않는다
Feature 9 — 대용량 Dart 파일 편집 응답성
Feature: 대용량 Dart 파일 편집 응답성
# 출처: Seed Spec AC-15 / 가정 A-03
# "10만 줄" 의 근거는 Seed Spec 출처표 7행: Discovery 문서가 인용한 설계 노트 로드맵 1단계의
# 검증 시나리오 — discovery-cocode.md 34행(`### Validated/Unvalidated Assumptions` 1행)과
# 112행(`### Technical Feasibility` 에디터 코어 행) 2곳에 기록되어 있다.
# 설정값 — 프레임 타임 목표치·백분위·측정 환경(빌드 모드·하드웨어 등급·플랫폼)·
# 시나리오(스크롤 속도·조작 종류)·표본 창: 미정.
# 확정 주체: Planning / 확정 시점: A-03 로드맵 1단계 스파이크 실측 후 /
# 근거: planning-inputs §3.3. (U-2)
# 설정값 — 참조 워크스페이스 커밋 SHA: 미정. `coco-de/unibook` 추천이나 **SHA 고정이 필수**다.
# 확정 주체: Planning / 확정 시점: 벤치마크 착수 전 / 근거: planning-inputs §3.2·§6. (U-3)
# 같은 §3.2 는 줄 수가 추정치이므로 "수치를 명세에 적기 전 실제 체크아웃에서 검증할 것" 이라고
# 경고한다 — 아래 "10만 줄" 픽스처도 그 검증 대상이다.
# ⚠ v1.1.0~v2.1.0 에 등장했던 `p95 16.7ms` 는 확정값이 아니다(planning-inputs §3.3 경고).
# ⚠ 위 값들이 확정되기 전까지 이 Feature 는 작성만 되어 있고 판정은 보류된다.
@happy-path
Scenario Outline: [AC-15] 10만 줄 Dart 파일에서 조작이 입력한 순서대로 반영된다
Given 사용자가 10만 줄 규모의 Dart 파일을 에디터에서 연 상태다
When 사용자가 "<조작>" 을 수행한다
Then 조작이 입력한 순서대로 반영된다
And 화면이 응답하지 않는 구간이 발생하지 않는다
Examples:
| 조작 |
| 스크롤 |
| 커서 이동 |
| 다중 선택 |
2. AC → 시나리오 대응표
Seed Spec §4 의 AC-01~AC-21 각각에 최소 1건을 배정했다. 아래 표에서 AC 번호 21개가 모두 나타나는지 확인할 수 있다.
⚠️ AC-21 은 v3.1.0 신설이라 이 표가 오래 덮지 못했다(#98 이전 0건 —
ux-spec§12 가 Planning 반환 항목으로 기록해 둔 그 공백이다). #98 이 Feature 2 에 시나리오 2건을 신설하고 이 표에 행을 더했다.
| AC | Feature | 시나리오 수 | 태그 |
|---|---|---|---|
| AC-01 | 1 | 2 | @happy-path, @edge-case |
| AC-02 | 1 | 4 | @happy-path, @edge-case, @error-handling ×2 — AC-02 시나리오 총수(#98 이 의미를 명시) |
| AC-03 | 2 | 1 (Outline 3행) | @happy-path |
| AC-04 | 2 | 1 | @edge-case |
| AC-05 | 2 | 2 | @edge-case, @happy-path |
| AC-06 | 3 | 2 | @happy-path ×2 |
| AC-07 | 4 | 2 | @error-handling, @edge-case |
| AC-08 | 4 | 2 | @error-handling, @edge-case |
| AC-09 | 4 | 6 | @happy-path, @edge-case ×3, @error-handling ×2 |
| AC-10 | 4 | 2 | @happy-path, @edge-case |
| AC-11 | 5 | 5 (1건 Outline 2행) | @error-handling, @happy-path ×2, @edge-case ×2 |
| AC-12 | 6 | 3 | @edge-case ×2, @happy-path |
| AC-13 | 7 | 2 (1건은 [AC-13/불변식] 보충) |
@happy-path, @error-handling |
| AC-14 | 8 | 6 | @edge-case, @happy-path ×3, @error-handling ×2 |
| AC-15 | 9 | 1 (Outline 3행) | @happy-path |
| AC-16 | 2 | 1 (Outline 6행) | @happy-path |
| AC-17 | 4 | 2 (1건 Outline 3행) | @edge-case ×2 |
| AC-18 | 6 | 1 | @error-handling |
| AC-19 | 1 | 2 | @error-handling ×2 |
| AC-20 | 3 | 1 (Outline 2행) | @error-handling |
| AC-21 | 2 | 2 | @edge-case(부재), @happy-path(AC-12 무관 확인) — #98 신설 |
| — (C-02, 불변식) | 1 | 3 | @edge-case ×3 |
Analysis Gate 요건 — @happy-path 1건 이상 + @error-handling 1건 이상(cc-product references/phase-gates.md 51행, skills/analyst/SKILL.md 254행, references/PERSONA_MATRIX.md 34행): 위 표에서 양쪽 모두 다수 존재함이 확인된다.
이 문서가 안전 임계로 분류한 경로 7건. 분류 기준은 이 문서의 것이며 Seed Spec 이 지정한 목록이 아니다 — C-04·C-05 가 규정한 안전 동작(전환 조항·테스트 보호·재시도/시간 상한), EditSnapshot 의 충돌 감지·원자성, 그리고 동시 편집·비정상 종료 시의 잠금이다.
| 안전 임계 경로 | AC | 위치 |
|---|---|---|
| C-04 전환 조항 기본값 | AC-17 | Feature 4 첫 블록 (Outline 3행 + 후속 1건) |
| 기존 테스트 변경 승인 | AC-11 | Feature 5 전체 (5건) |
| 롤백 충돌 감지 | AC-02 | Feature 1 — 충돌 판정에 걸리는 2건(사람 개입 1 + 원자성 결합 1). AC-02 총 4건 중 부분집합이다 ✅ 판정 기준 확정(U-10 해소 — v3.1.0 ① result_content_hash) |
| 재시도 상한 | AC-07 | Feature 4 — 초과 1건 + 경계값 1건 |
| 시간 상한 | AC-08 | Feature 4 — 초과 1건 + 기본값 존재 1건 (⚠ 기본값 U-1 미정) |
| 동시 편집 잠금 | AC-12 | Feature 6 — 3건 |
| 비정상 종료 잠금 해제 | AC-18 | Feature 6 — 1건 |
3. 커버리지의 한계 (명시)
이 문서가 커버하지 않는 것:
- Seed Spec §2 제약·§3 불변식 전부가 아니다. AC 로 승계되지 않은 조항 중 세 건만 보충 시나리오로 넣었다 — ⓐ C-02 본문 + EditSnapshot 불변식 1(EditSnapshot 필수) ⓑ C-02 Rationale(사람이 에디터로 직접 하는 편집은 이 제약의 대상이 아니다 — 불변식이 아니라 Rationale 이다) ⓒ DelegatedTask 불변식 5("롤백됨" 전이 조건). 나머지 조항이 모두 커버되었다고 주장하지 않는다.
- 가정 A-01~A-07 의 검증 시나리오가 아니다. A-02·A-03·A-04·A-06 은 스파이크 대상이고, A-05 는 스파이크가 아니라 "Design 단계에서 v1 협상 계층 구현 후 4종 연결 검증" 이다(Seed Spec §5). 어느 쪽도 인수 조건이 아니다.
- 승인 거부 시의 동작은 없다. Seed Spec 이 "승인 없이는 적용되지 않는다" 만 규정하고 거부 경로를 규정하지 않으므로 시나리오를 쓰지 않았다.
- 성능·용량 목표치가 없다. A-06(설치 용량·콜드 스타트·메모리)은 목표치 자체가 미확정이므로 인수 조건을 쓸 수 없다(planning-inputs §6).
- §0.5 의 미정 항목에 걸린 시나리오는 지금 실행할 수 없다 — 단 그 목록은 #98 에서 크게 줄었다.
- ✅ 해소됨: U-7(테스트 파일 정의 — v3.1.0 ②) · U-8(①~④ 적용 불가 — D-053) · U-9(응답 불가 감지 — architecture §6.2 DD-22) · U-10(롤백 충돌 비교 대상 — v3.1.0 ①) · U-12(Must-Not 관찰 방법 — D-072). 따라서 Feature 5 전체 · Feature 4 의 AC-09 ⑤ · Feature 3 의 AC-20 · Feature 1 의 AC-02 · Feature 2 의 AC-04·AC-05·AC-21 이 판정 가능해졌다.
- ⏸️ 남은 것: U-1(시간 상한 기본값) · U-2(프레임 타임 목표치 — #91 이 측정 규칙까지 확정, 목표치는 오너 대기) · U-3(참조 워크스페이스 SHA — #91 이
9db9015로 고정, 사실상 해소) · U-4(A-02 표본 수·합격 기준 — #96 이 표본 수·ⓑ 정의 확정, 합격 기준은 오너 대기) · U-5(허용 목록 추출 알고리즘 — D-050 이 해소) · U-6(IME 입력기·코퍼스 — #93 이 확정) · U-11(대기 작업 status 값). - ⚠️ 세 곳의 수가 서로 다른 것을 세고 있었다(#98 이 정리). §2 대응표의 4건은 AC-02 시나리오 총수이고, §3 안전 임계표의 2건은 그중 충돌 판정에 걸리는 부분집합이며, 이전 U-10 행과 이 항목이 적던 «3건» 은 무엇을 세는지 근거가 없었다 — U-10 이 해소되어 보류 시나리오가 0건이 된 지금 그 수는 폐기한다. 작성되어 있다는 것과 판정할 수 있다는 것은 다르다.
- 태그 배정은 판정이 개입하는 문서 관례다(§0.3). 개별 배정에 이견이 있을 수 있으며, 게이트 요건(각 태그 1건 이상)만이 규범이다.
- Seed Spec 자체가 잠기지 않았다(§0.1). 정본이 개정되면 이 문서의 시나리오도 함께 개정되어야 한다.
- co-brick 적용 시나리오가 없다 — 기능이 MVP 범위 밖이기 때문이다(D-037 / 이슈 #113 · Seed Spec AC-24 Must-Not). Feature 7 의 두 시나리오는 워크스페이스 최초 스캐폴딩만 다루며,
applied_bricks는 MVP 에서 원소가 1개다. AC-24 는 Must-Not 이라 부재 자체가 요건이므로(AC-04·AC-21 과 같은 유형, §2 대응표의 그 두 행과 같은 처분) 대응 시나리오를 쓰지 않는다 — 없다는 것을 시나리오로 증명하려 하지 않는다.
Generated by cc-product Planning stage (BMAD v6) · 2026-08-26