@decencia/ch-cli 1.29.0 → 1.31.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. package/agent/2t-decencia-channel-issue-coder.md +1 -1
  2. package/agent/2t-decencia-channel-pr-merger.md +1 -1
  3. package/agent/2t-decencia-channel-terraformer.md +1 -1
  4. package/dist/commands/policies.d.ts +12 -0
  5. package/dist/commands/policies.d.ts.map +1 -0
  6. package/dist/commands/policies.js +302 -0
  7. package/dist/commands/policies.js.map +1 -0
  8. package/dist/commands/screens.d.ts.map +1 -1
  9. package/dist/commands/screens.js +103 -23
  10. package/dist/commands/screens.js.map +1 -1
  11. package/dist/commands/skills.d.ts +13 -0
  12. package/dist/commands/skills.d.ts.map +1 -1
  13. package/dist/commands/skills.js +43 -7
  14. package/dist/commands/skills.js.map +1 -1
  15. package/dist/commands/specs.d.ts +15 -0
  16. package/dist/commands/specs.d.ts.map +1 -1
  17. package/dist/commands/specs.js +117 -10
  18. package/dist/commands/specs.js.map +1 -1
  19. package/dist/commands/sprints.d.ts +16 -0
  20. package/dist/commands/sprints.d.ts.map +1 -1
  21. package/dist/commands/sprints.js +152 -4
  22. package/dist/commands/sprints.js.map +1 -1
  23. package/dist/commands/sqa.d.ts +23 -0
  24. package/dist/commands/sqa.d.ts.map +1 -1
  25. package/dist/commands/sqa.js +252 -6
  26. package/dist/commands/sqa.js.map +1 -1
  27. package/dist/commands/userflows.d.ts +11 -0
  28. package/dist/commands/userflows.d.ts.map +1 -0
  29. package/dist/commands/userflows.js +275 -0
  30. package/dist/commands/userflows.js.map +1 -0
  31. package/dist/index.js +4 -0
  32. package/dist/index.js.map +1 -1
  33. package/package.json +1 -1
  34. package/skill/2t-decencia-channel-change-manager/SKILL.md +1 -1
  35. package/skill/2t-decencia-channel-change-propagation-v2/SKILL.md +11 -7
  36. package/skill/2t-decencia-channel-cli-v2/SKILL.md +48 -20
  37. package/skill/2t-decencia-channel-db-schema-v2/SKILL.md +4 -4
  38. package/skill/2t-decencia-channel-github-issue/SKILL.md +1 -1
  39. package/skill/2t-decencia-channel-orchestrator/SKILL.md +1 -1
  40. package/skill/2t-decencia-channel-policy-v2/SKILL.md +114 -0
  41. package/skill/2t-decencia-channel-prd-v2/SKILL.md +37 -12
  42. package/skill/2t-decencia-channel-project-bootstrap/SKILL.md +22 -25
  43. package/skill/2t-decencia-channel-screen-v2/SKILL.md +135 -0
  44. package/skill/2t-decencia-channel-spec-v2/SKILL.md +288 -443
  45. package/skill/2t-decencia-channel-sprint-builder-v2/SKILL.md +11 -3
  46. package/skill/2t-decencia-channel-sprint-runner/SKILL.md +1 -1
  47. package/skill/2t-decencia-channel-sqa-v2/SKILL.md +124 -21
  48. package/skill/2t-decencia-channel-userflow-v2/SKILL.md +125 -0
  49. package/skill/2t-decencia-channel-work-status-v2/SKILL.md +3 -3
@@ -7,7 +7,7 @@ description: |
7
7
  (1) sprint를 구성할 때,
8
8
  (2) Σ spec.points 기반 sprint 용량 산정이 필요할 때,
9
9
  (3) Epic·도메인·의존성을 함께 고려해 spec을 sprint에 배분할 때.
10
- version: 1.29.0
10
+ version: 1.31.0
11
11
  ---
12
12
 
13
13
  <!-- ch-version-gate -->
@@ -40,7 +40,7 @@ ch sprints create --name "Sprint 1" --start 2026-06-01 --end 2026-06-14 --specs
40
40
 
41
41
  1. 모든 spec을 `ch specs list --json`로 수집.
42
42
  2. 각 spec의 `epic`, `points`(Story Point) 추출.
43
- 3. Sprint 용량 = **Σ spec.points**. spec 하나가 규모 단위이며 별도 하위 합산은 없다. `points` 미지정 spec은 산정 전에 [[2t-decencia-channel-spec-v2]] §3으로 부여한다(미지정은 0이 아니라 누락으로 본다).
43
+ 3. Sprint 용량 = **Σ spec.points**. spec 하나가 규모 단위이며 별도 하위 합산은 없다. `points` 미지정 spec은 산정 전에 [[2t-decencia-channel-spec-v2]] §11로 부여한다(미지정은 0이 아니라 누락으로 본다).
44
44
  4. Sprint 용량(예: 30 SP / 2주) 설정 후, 다음 순서로 채우기:
45
45
  - **의존성** (PRD/spec.dbTableRefs 분석): DB 테이블 신규 생성 spec → 그걸 참조하는 spec 순.
46
46
  - **Epic 단위 묶음**: 같은 Epic은 한 sprint에 몰아주는 게 컨텍스트 비용 ↓.
@@ -81,10 +81,18 @@ Sprint에는 spec뿐 아니라 **요청사항 카드**도 담는다(`ch sprints
81
81
 
82
82
  카드 하나가 Sprint 실행 중 이슈 1건으로 분해되는 절차는 [[2t-decencia-channel-sprint-runner]] §3-1이다.
83
83
 
84
+ ## 4.5 시나리오 할당 — Sprint의 완료조건
85
+
86
+ Sprint 구성 시 **검증 시나리오도 함께 할당한다** (`ch sprints add-scenarios`, [[2t-decencia-channel-sqa-v2]] §4.6).
87
+
88
+ - Story(spec) 완료조건은 TC 통과, **Sprint 완료조건은 할당된 시나리오 전부 통과**다.
89
+ - 이번 Sprint의 spec들이 걸치는 유저플로우에서 시나리오를 고른다 — 돈 경로·최빈 경로·역방향·역할별 1개.
90
+ - 시나리오 없이 Sprint를 닫으면 TC 사이 빈틈(크로스 Story 정합)이 검증되지 않은 채 끝난다.
91
+
84
92
  ## 5. 흔한 함정
85
93
 
86
94
  - `points` 미지정 spec이 많으면 산정 부정확 → spec마다 `--points` 부여(피보나치 1/2/3/5/8/13).
87
95
  - Sprint에 담은 spec의 `points`를 바꾸면 sprint SP 합이 변동 — sprint 재산정 필요.
88
- - Story를 Task로 쪼개 합산하지 않는다 — 규모는 spec 단위 `points` 하나다([[2t-decencia-channel-spec-v2]] §3).
96
+ - Story를 Task로 쪼개 합산하지 않는다 — 규모는 spec 단위 `points` 하나다([[2t-decencia-channel-spec-v2]] §11).
89
97
  - 요청사항 카드는 용량(Σ spec.points)에 넣지 않는다 — 카드는 points가 없다. 진행률만 개수로 함께 센다.
90
98
  - Sprint와 spec.workStatus는 별개. Sprint 진행 상황은 sprint 자체 status로, spec별 메모는 workStatus로.
@@ -2,7 +2,7 @@
2
2
  name: 2t-decencia-channel-sprint-runner
3
3
  description: 특정 Sprint를 끝까지 실행(run)하는 오케스트레이터 스킬. Sprint의 spec을 시드로 이슈 목록을 분해·발행(github-issue)하고, GitHub milestone에 묶인 이슈를 상태별로 분류해 issue-coder(병렬)·pr-merger(직렬)로 전진시킨 뒤, 사람확인이 필요한 곳에서 멈춘다. 사람이 확인·체크 후 재호출하면 멱등하게 이어간다(반복 루프). "스프린트 돌려줘"·"sprint N 실행"·"이 스프린트 개발 진행해줘" 류 요청 시.
4
4
  allowed-tools: Skill Agent Read Bash(ch:*) Bash(gh:*) Bash(git:*)
5
- version: 1.29.0
5
+ version: 1.31.0
6
6
  ---
7
7
 
8
8
  <!-- ch-version-gate -->
@@ -1,18 +1,18 @@
1
1
  ---
2
2
  name: 2t-decencia-channel-sqa-v2
3
3
  description: |
4
- [2t][v2] 소통채널 SQA 운영 가이드.
5
- 시트 구성 2축(A. 명세별 기능 TC — §4.3 영역별 TC 번들 라이브러리에서 도출 / B. 비기능 4축 표준 40개),
6
- §4.3은 명세 영역(접근권한/목록/폼/삭제/상태전이/UI일반/백엔드/규칙/내보내기/차트)마다
7
- Functional·Publishing·Frontend·Backend 카테고리를 묶음으로 제공하는 누적 라이브러리.
4
+ [2t][v2] 소통채널 SQA(검증기준서) 운영 가이드 — 검증 = TC 검증 + 시나리오 검증.
5
+ TC는 Story 완료조건(Story당 4겹: 해피패스/경계·예외/권한/상태반영 — §2, §4.3 영역별 번들에서 도출),
6
+ 시나리오는 Sprint 완료조건(유저플로우 기반 5~10개, TC 사이 빈틈 검증 — §4.6).
7
+ 실행은 시나리오로 하되 판정·기록은 TC 단위.
8
8
  Use when:
9
9
  (1) SQA 시트를 새로 작성하거나 항목을 보강할 때,
10
- (2) spec.ui/logic에서 도출한 검증 항목을 SQA 시트에 등록할 때,
11
- (3) 보안/성능/접근성/호환성 비기능 TC를 시트에 채워야 때,
12
- (4) 명세 영역별 완성형 TC 번들(퍼블리싱/프론트/백엔드 디센시아 운영 관점 포함)을 가져다 쓸 때,
13
- (5) 명세 작업 반복 패턴을 발견해 영역별 번들을 보강할 때,
14
- (6) Sprint 종료 전 spec별 SQA 통과 여부를 점검할 때.
15
- version: 1.29.0
10
+ (2) spec에서 도출한 검증 항목(TC)을 SQA 시트에 등록할 때,
11
+ (3) 시나리오 검증을 작성하거나 Sprint에 할당할 때,
12
+ (4) 보안/성능/접근성/호환성 비기능 TC 시트에 채워야 때,
13
+ (5) 명세 영역별 완성형 TC 번들(퍼블리싱/프론트/백엔드 디센시아 운영 관점 포함)을 가져다 쓸 때,
14
+ (6) Sprint 종료 전 spec별 TC 통과·시나리오 통과 여부를 점검할 때.
15
+ version: 1.31.0
16
16
  ---
17
17
 
18
18
  <!-- ch-version-gate -->
@@ -30,27 +30,50 @@ ch check
30
30
  구버전 스킬·CLI 사용을 막기 위한 게이트다. 건너뛰지 말 것.
31
31
 
32
32
 
33
- # SQA — spec 완료 판정 (SQA 통과 = 완료)
33
+ # SQA(검증기준서)TC 검증 + 시나리오 검증
34
34
 
35
35
  ## 0. Read-before-Write
36
36
 
37
37
  시트 항목(item) 단위 CRUD는 이제 CLI로 모두 지원된다(§3.5). 항상 `ch sqa get <sheetId> --json`으로 현재 항목 목록·id를 먼저 받고 수정한다. 항목 수정/삭제/순서변경은 `id`를 키로 지정하므로 최신 id 확보가 선행되어야 한다.
38
38
 
39
- ## 1. 핵심 규칙
39
+ ## 1. 핵심 규칙 — 검증은 두 층이다
40
40
 
41
- > **spec의 완료 조건 = 그 spec에 연결된 SQA 항목이 모두 통과**
41
+ > **Story(spec)의 완료 조건 = 그 spec에 연결된 TC가 모두 통과**
42
+ > **Sprint의 완료 조건 = 그 Sprint에 할당된 시나리오가 모두 통과**
42
43
 
43
- 별도 acceptanceCriteria 필드 없음. **공식 완료는 SQA**가 판정한다 — spec에 연결된 SQA 항목이 모두 통과해야 spec.status를 완료로 올린다. spec 규모는 Story Point(`spec.points`)로 표현하고, 진행률(%)·Task 체크박스 개념은 없다.
44
+ | | TC 검증 | 시나리오 검증 |
45
+ |---|---|---|
46
+ | 단위 | Story마다 대응되는 검증 리스트 | 한 Story에 종속되지 않음 — 유저플로우 기반 |
47
+ | 잡는 것 | 기능·경계·예외·권한·상태반영 | 개별 TC만으로 못 잡는 **TC 사이의 빈틈** |
48
+ | 완료조건 | Story(spec) 완료 | Sprint 완료 |
49
+ | 작성 | §2~§4.5 | §4.6 |
50
+
51
+ **실행은 시나리오로 하되, 판정·기록은 TC 단위로 남긴다** — 시나리오 스텝마다 매핑된 TC에 Pass/Fail을 기록한다.
52
+
53
+ 별도 acceptanceCriteria 필드 없음. **공식 완료는 SQA**가 판정한다. spec 규모는 Story Point(`spec.points`)로 표현하고, 진행률(%)·Task 체크박스 개념은 없다.
44
54
 
45
55
  ## 2. spec → SQA 항목 도출
46
56
 
47
- SQA 항목은 spec ui·logic(특히 logic.businessRules)에서 도출한다. Story는 Task로 쪼개지 않으므로(`tasks`는 deprecated) 검증 단위는 개별 task가 아니라 **spec이 정의한 동작·규칙**이다.
57
+ SQA 항목은 spec 정의한 동작·규칙에서 도출한다. Story는 Task로 쪼개지 않으므로(`tasks`는 deprecated) 검증 단위는 개별 task가 아니라 **spec이 정의한 동작·규칙**이다.
48
58
 
49
- - 도출 입력: spec.ui(화면·상호작용), spec.logic(dataFlow·businessRules)
59
+ - 도출 입력 (스토리 명세 모드 — [[2t-decencia-channel-spec-v2]] §0): 스토리문장(`story`)·사전 조건(`preconditions`)·로직 플로우(`logic.dataFlowScenarios`)·비즈니스 규칙(`logic.businessRules`)·연결 화면(screens)
60
+ - 도출 입력 (레거시): spec.ui(화면·상호작용), spec.logic(dataFlow·businessRules)
61
+ - 플로우의 **실패·차단 분기는 비정상 TC로 1:1 이상** 옮긴다 — 분기가 있는데 비정상 TC가 없으면 누락이다.
50
62
  - SQA 항목: QA가 검증할 시나리오 (예: "잘못된 비밀번호 5회 시 잠금")
51
63
 
52
64
  **1:N 관계**: spec 1개가 여러 SQA 항목을 유발한다. SQA 항목 작성 시 `relatedSpec`으로 spec에 연결해 추적한다.
53
65
 
66
+ ### Story당 TC 구성 4겹 — 전부 있어야 한다
67
+
68
+ | # | 겹 | 내용 |
69
+ |---|---|---|
70
+ | 1 | **해피패스** | 기본 기능검증 — 정상 경로가 끝까지 동작 |
71
+ | 2 | **경계·예외** | 경계값(길이·0건·최대치)과 실패·차단 경로. 플로우의 실패 분기는 1:1 이상 |
72
+ | 3 | **권한** | 역할별 허용/차단 (§4.3.1 번들) |
73
+ | 4 | **상태반영 여부** | 액션 후 DB·화면 상태가 실제로 바뀌었는가 — 흐름 refs의 WRITE·`toState`를 확인 TC로 |
74
+
75
+ 넷 중 하나라도 비면 그 Story의 TC는 미완성이다. §8 체크리스트로 최종 확인한다.
76
+
54
77
  ## 3. 신규 SQA 작성 워크플로우
55
78
 
56
79
  0. **시트 생성** (없으면 먼저):
@@ -58,11 +81,11 @@ SQA 항목은 spec의 ui·logic(특히 logic.businessRules)에서 도출한다.
58
81
  # --date 생략 시 오늘로 자동 채움 (서버 DTO가 performDate 필수)
59
82
  ch sqa create --name "Sprint 1 SQA" --date 2026-06-01
60
83
  ```
61
- 1. **spec ui·logic을 가져온다**:
84
+ 1. **spec 본문을 가져온다**:
62
85
  ```bash
63
- ch specs get <specId> --json | jq '{ui, logic}'
86
+ ch specs get <specId> --json | jq '{story, preconditions, ui, logic}'
64
87
  ```
65
- 2. spec.ui(화면·상호작용)와 logic.businessRules를 참고하여 검증 항목 도출.
88
+ 2. 검증 항목 도출 — 스토리 명세 모드는 스토리문장·사전 조건·로직 플로우(분기 포함)·businessRules에서, 레거시는 spec.ui(화면·상호작용)와 logic.businessRules에서.
66
89
  3. SQA 시트에 항목 추가 (§3.5 CLI 명령 사용).
67
90
  4. 항목 작성 시 `relatedSpec`에 specId 명시(생략 시 미연결).
68
91
 
@@ -185,7 +208,8 @@ ch sqa reorder-items <sheetId> --file order.json # ["id1","id2",...] 또는 {
185
208
 
186
209
  ### 사용 절차
187
210
 
188
- 1. spec.ui/logic을 읽어 그 spec이 속한 **명세 영역**을 1~N개 식별 (예: "지점 관리 화면" = 접근권한 + 목록 + 등록/수정 폼 + 삭제).
211
+ 1. spec 본문을 읽어 그 spec이 속한 **명세 영역**을 1~N개 식별 (예: "지점 관리 화면" = 접근권한 + 목록 + 등록/수정 폼 + 삭제).
212
+ - 스토리 명세 모드는 스토리문장·로직 플로우·연결 화면(screens)에서 영역을 읽는다. 아래 트리거의 "spec.ui" 언급은 연결된 화면·플로우로, "stateTransitions" 언급은 플로우의 실패 분기·db-table.stateMachines로 바꿔 읽는다.
189
213
  2. 각 영역 번들의 항목을 가져와 그 명세의 도메인 단어로 구체화. 추상 문구 그대로 박지 말 것.
190
214
  - 추상: "Update시 모달창이나 수정 페이지로 데이터가 제대로 전달 되는가?"
191
215
  - 명세별: "지점 수정 모달 진입 시 기존 지점명·지역·전화 필드가 prefill됨"
@@ -374,6 +398,76 @@ ch specs list --json --per-page 100 | node -e "
374
398
 
375
399
  누락된 spec이 있으면 해당 spec의 content를 다시 읽고 TC를 추가한 후 재검증.
376
400
 
401
+ ## 4.6 시나리오 검증 — Sprint 완료조건
402
+
403
+ 시나리오는 **유저플로우를 기반으로** 여러 Story를 관통하는 테스트다 ([[2t-decencia-channel-userflow-v2]]). 화면 이동만 쭉 따라가며 TC를 재확인하는 것이 아니라, **플로우에 따라 변하는 상태들**(잔액·재고·상태 컬럼·알림 발송 여부)을 체크한다.
404
+
405
+ ### 4.6.1 선정 — 유저플로우 기반 5~10개
406
+
407
+ 프로젝트 규모에 따라 5~10개를 고른다. 반드시 포함할 것:
408
+
409
+ - **돈이 흐르는 경로** (결제·정산·환불)
410
+ - **가장 빈번할 경로** (핵심 사용 여정)
411
+ - **역방향** 포함 (취소·반품·되돌리기)
412
+ - **역할별 최소 1개** (관리자·일반·비회원 등 역할마다)
413
+
414
+ ### 4.6.2 양식
415
+
416
+ | 항목 | 내용 |
417
+ |---|---|
418
+ | Scenario ID | `SCN-001` 형식 |
419
+ | 전제 | 계정(역할)·데이터의 **시작 상태** — 어떤 상태에서 출발하는가 |
420
+ | 스텝 | **행동 + 확인 포인트 + TC 매핑** — 각 스텝이 무엇을 하고, 무엇을 확인하고, 어느 TC로 기록되는가 |
421
+ | 종료 | **최종 데이터 정합 확인** — 여정이 끝난 뒤 DB·화면 상태가 맞는가 |
422
+
423
+ - 스텝의 확인 포인트는 단순 TC 재확인이 아니다. **이 스텝까지 오면서 변한 상태**를 본다.
424
+ - 종료의 정합 확인도 TC 항목으로 등록해 마지막 스텝에 매핑한다 — "판정·기록은 TC 단위" 원칙.
425
+ - 시나리오가 참조하는 유저플로우가 있으면 링크한다.
426
+
427
+ ### 4.6.3 Sprint 연결 — Sprint의 완료조건
428
+
429
+ - **Sprint 생성 시 시나리오를 할당한다** ([[2t-decencia-channel-sprint-builder-v2]]). spec·요청사항 카드 배정과 나란히.
430
+ - Sprint 완료 판정 = 할당된 시나리오 전부 통과. Story 완료(TC)가 다 모여도 시나리오가 남았으면 Sprint는 안 끝난 것이다.
431
+
432
+ ### 4.6.4 시나리오 체크리스트
433
+
434
+ - [ ] 해피패스뿐만 아니라 **다양한 분기**에 대한 테스트가 이루어졌는가?
435
+ - [ ] 화면 이동만 쭉 따라가는 것이 아니라 **Epic의 경계에서 상태확인**이 이루어지는가? (예: 주문→포인트 적립, 결제→알림 발송)
436
+
437
+ ### 4.6.5 CLI
438
+
439
+ ```bash
440
+ ch sqa add-scenario <sheetId> --file scenario.json # 시나리오 추가
441
+ ch sqa update-scenario <sheetId> <scenarioId> --file scenario.json
442
+ ch sqa delete-scenario <sheetId> <scenarioId>
443
+ ch sprints add-scenarios <sprintId> <sheetId>:<scenarioId>[,...] # Sprint에 할당
444
+ ch sprints remove-scenarios <sprintId> <sheetId>:<scenarioId>[,...] # 할당 해제
445
+ ```
446
+
447
+ `update-scenario`는 Read-before-Write다 — `ch sqa get <sheetId> --json`으로 현재 scenarios[]를 받아 편집한 뒤 넘긴다(steps는 통째 교체). 시나리오 ID는 불변이라 파일의 `id`는 전송되지 않는다. 개명은 지우고 다시 만든다.
448
+
449
+
450
+ `scenario.json`:
451
+
452
+ ```json
453
+ {
454
+ "id": "SCN-001",
455
+ "name": "주문 → 결제 → 취소 환불",
456
+ "userflowRef": "<userflowId>",
457
+ "precondition": "일반 회원 계정, 잔여 포인트 5,000, 재고 3개인 상품 1종",
458
+ "steps": [
459
+ { "action": "상품을 장바구니에 담고 포인트 2,000을 적용해 결제한다",
460
+ "checkpoint": "결제 완료 + 포인트 잔액 3,000 + 재고 2로 감소",
461
+ "tcRefs": ["item-..."] },
462
+ { "action": "주문을 취소한다",
463
+ "checkpoint": "PG 취소 + 포인트 2,000 복원 + 재고 3 복원 + 취소 알림톡 발송",
464
+ "tcRefs": ["item-..."] }
465
+ ],
466
+ "closing": "ORDERS 상태 canceled, 포인트 원장 합계 5,000, 재고 3 — 시작 상태와 정합",
467
+ "closingTcRef": "item-..."
468
+ }
469
+ ```
470
+
377
471
  ## 5. spec 완료 점검 절차
378
472
 
379
473
  ```bash
@@ -381,11 +475,13 @@ ch specs list --json --per-page 100 | node -e "
381
475
  ch sqa summary <runId>
382
476
  # 2) 모두 "통과(Pass)" 상태인지 확인
383
477
  # 3) 통과 → spec.status 를 "완료"로 갱신
384
- ch specs update <specId> --status 완료 --no-version
478
+ ch specs update <specId> --status completed --no-version
385
479
  ```
386
480
 
387
481
  수동으로 status를 바꾸기 전에 SQA 통과 여부를 반드시 확인.
388
482
 
483
+ **Sprint 완료 점검**: spec별 TC 통과에 더해, Sprint에 할당된 **시나리오가 전부 통과**했는지 확인한 뒤에 Sprint를 완료로 바꾼다 (§4.6.3).
484
+
389
485
  ## 6. workStatus와의 분담
390
486
 
391
487
  - **spec.workStatus**: 개발자의 진행 메모, 블로커, 의사결정 로그.
@@ -407,7 +503,10 @@ ch specs update <specId> --status 완료 --no-version
407
503
  ## 8. 시트 작성 완료 자가 점검 체크리스트
408
504
 
409
505
  - [ ] A축: 모든 spec에 최소 3개 이상 TC가 있는가? (§4.5 커버리지 통과)
506
+ - [ ] A축: 모든 Story에 TC 4겹(해피패스/경계·예외/권한/상태반영)이 있는가? (§2)
410
507
  - [ ] A축 항목 작성 시 §4.3 영역별 번들(Functional/Publishing/Frontend/Backend)을 명세 성격에 맞게 적용했는가?
508
+ - [ ] 시나리오: 유저플로우 기반 5~10개 — 돈 경로·최빈 경로·역방향·역할별 1개 포함? (§4.6.1)
509
+ - [ ] 시나리오: 스텝마다 확인 포인트·TC 매핑이 있고, 종료 정합 TC가 있는가? Sprint에 할당했는가?
411
510
  - [ ] B축: 보안 12 / 성능 10 / 접근성 10 / 호환성 8 — 40개 모두 포함?
412
511
  - [ ] High 우선순위 TC가 60% 이상인가?
413
512
  - [ ] 정상 경로 + 비정상 경로(에러) 모두 커버?
@@ -420,6 +519,10 @@ ch specs update <specId> --status 완료 --no-version
420
519
  ## 9. 흔한 함정
421
520
 
422
521
  - 구현이 끝났다고 판단해도 연결된 SQA가 통과하기 전에는 spec.status를 완료로 바꾸지 않음.
522
+ - **Story TC가 다 통과했다고 Sprint를 닫지 말 것** — Sprint 완료조건은 할당된 시나리오 통과다(§4.6.3).
523
+ - **시나리오를 TC 재확인 목록으로 쓰지 말 것** — 확인 포인트는 플로우에 따라 변한 상태(잔액·재고·상태 컬럼·알림)다.
524
+ - **시나리오도 Run 생성 시점 스냅샷 기준이다** — Run 시작 후 추가·수정한 시나리오는 그 Run에 없으므로 새 `start-run` 전까지 무조건 미통과로 집계된다(항목 CRUD의 스냅샷 규칙과 동일).
525
+ - **시나리오가 참조 중인 TC 항목은 삭제할 수 없다(400)** — 시나리오의 매핑(tcRefs·종료 정합 TC)을 먼저 제거한 뒤 항목을 지운다.
423
526
  - **명세별 E2E만 넣고 끝내지 말 것** — §4.3 번들에서 Publishing/Frontend/Backend 카테고리 누락, §4.2 비기능 4축 미등록이 가장 흔한 실수.
424
527
  - §4.3 번들을 **별도 시트 묶음으로 등록**하지 말 것 — 각 명세의 A축 항목으로 풀어 써야 한다. 추상 문구 그대로 박아넣지 말 것.
425
528
  - 항목 단위 CRUD(§3.5)는 **시트 템플릿**만 변경 — 진행 중 Run에는 반영 안 됨. Run 항목 결과는 `check`/`check-bulk`로.
@@ -0,0 +1,125 @@
1
+ ---
2
+ name: 2t-decencia-channel-userflow-v2
3
+ description: |
4
+ [2t][v2] 소통채널 유저플로우 작성 가이드.
5
+ Mermaid flowchart로 그린다 — 해피패스는 중앙 일직선, 분기는 그 주변으로.
6
+ 대상 선정(분기 있는 여정만, 프로젝트당 3~7장)·6단계 작성 절차·단계별 예외 질문 체크리스트.
7
+ Use when:
8
+ (1) 유저플로우(사용자 여정 분기도)를 새로 그리거나 수정할 때,
9
+ (2) PRD·Epic-Story 목록에서 플로우로 그릴 대상을 고를 때,
10
+ (3) 웹 "유저플로우" 탭에 올릴 Mermaid 코드를 작성할 때.
11
+ version: 1.31.0
12
+ ---
13
+
14
+ <!-- ch-version-gate -->
15
+ ## ⚠️ 시작 전 필수 — 버전 게이트 (생략 금지)
16
+
17
+ 이 스킬로 **어떤 작업이든 수행하기 전에 가장 먼저** 아래를 실행한다:
18
+
19
+ ```bash
20
+ ch check
21
+ ```
22
+
23
+ - exit code 0(통과)이 **아니면 즉시 중단**한다. 출력에 안내된 업데이트 명령(`npm install -g @decencia/ch-cli@latest` 또는 `ch setup-skill`)을 사용자에게 전달하고, 갱신이 끝나기 전까지 **이 스킬의 어떤 단계도 진행하지 않는다.**
24
+ - `ch`가 미설치/미인증이어도 먼저 `ch check`를 시도한다. (네트워크 불가 시 ch check는 통과시키되 경고를 남긴다.)
25
+
26
+ 구버전 스킬·CLI 사용을 막기 위한 게이트다. 건너뛰지 말 것.
27
+
28
+
29
+ # 유저플로우 — 작성 표준
30
+
31
+ 유저플로우는 **분기가 있는 사용자 여정**을 Mermaid로 그린 문서다. 웹 "유저플로우" 탭에 올린다.
32
+ 역할 분담: PRD는 무엇을(기능), spec은 어떻게(흐름 상세 — [[2t-decencia-channel-spec-v2]] §7), 유저플로우는 **여정의 갈림길**을 보여준다.
33
+
34
+ ## 0. 원칙
35
+
36
+ - 그릴 대상은 **PRD·Epic-Story 목록에서** 뽑는다. 코드나 화면에서 역산하지 않는다.
37
+ - **분기가 없으면 그리지 않는다.** 일직선 흐름은 spec의 로직 플로우로 충분하다.
38
+ - **한 장에 모든 플로우를 다 그리지 않는다.** 한 장 = 한 여정.
39
+ - 장수는 프로젝트 규모에 따라 **3~7장**이 적당하다. 너무 잘게 쪼개거나 합쳐서 작성하지 않는다.
40
+
41
+ ## 1. Mermaid 작성 규칙 — 해피패스 중앙 일직선
42
+
43
+ - `flowchart TD`(위→아래)를 쓴다.
44
+ - **해피패스(진입→성공 최단 경로)를 코드 맨 앞에 순서대로 선언한다.** 렌더러가 이 축을 중앙 일직선으로 잡는다.
45
+ - 분기·예외는 해피패스 선언 **뒤에** 붙인다. 축 주변(좌우)으로 뻗는다.
46
+ - 노드 표기: 진입/종료 `([...])` · 판단 `{...}` · 처리 `[...]`.
47
+ - 분기 조건은 edge 라벨로 적는다: `-->|재고 없음|`.
48
+ - 예외 경로도 **반드시 종료점까지 잇는다.** 허공에 끊긴 가지 금지.
49
+ - 노드 텍스트는 사용자 행동·시스템 반응을 짧은 구로. 데이터·테이블 얘기는 쓰지 않는다.
50
+
51
+ 예시 (로그인 여정):
52
+
53
+ ```mermaid
54
+ flowchart TD
55
+ S([앱 진입]) --> A[로그인 화면]
56
+ A --> B{자격 증명 확인}
57
+ B -->|성공| C[대시보드]
58
+ C --> OK([여정 완료])
59
+ B -->|실패 · 5회 미만| A2[오류 표시 후 재입력]
60
+ A2 --> A
61
+ B -->|5회 연속 실패| L[계정 잠금 안내]
62
+ L --> X1([종료: 잠금])
63
+ A -->|비밀번호 찾기| R[재설정 메일 발송]
64
+ R -->|메일 링크| A
65
+ R -->|메일 미도착·이탈| X2([종료: 이탈])
66
+ ```
67
+
68
+ 해피패스 `S → A → B → C → OK`를 먼저 선언했다. 나머지 가지는 그 축에 매달린다.
69
+
70
+ ## 2. 작성 절차 (6단계)
71
+
72
+ | 단계 | 할 일 |
73
+ |---|---|
74
+ | ① 대상 선정 | PRD·Epic-Story 목록에서 **분기 있는** 여정 선별 |
75
+ | ② 끝점 정의 | 진입점 전부 + 종료점 전부를 먼저 박는다 |
76
+ | ③ 해피패스 | 진입→성공까지 최단 경로를 일직선으로 |
77
+ | ④ 분기 추가 | 각 단계마다 "여기서 갈라질 수 있나?" 질문 (§3) |
78
+ | ⑤ 예외 경로 | 각 분기의 실패 쪽 끝을 종료점까지 연결 |
79
+ | ⑥ 검증 | 완성 판정 기준 (§4) 체크 |
80
+
81
+ ## 3. 각 단계에서 기본적으로 던질 질문
82
+
83
+ - 로그인 안 했으면?
84
+ - 권한이 없으면?
85
+ - 데이터가 없으면? (빈 상태)
86
+ - 입력이 잘못되면?
87
+ - 외부 연동이 실패하면?
88
+ - 중간에 이탈했다 돌아오면?
89
+ - 뒤로가기를 누르면?
90
+ - 시간이 지나면? (세션 만료·기한 경과)
91
+ - 두 번 누르면? (중복 제출)
92
+
93
+ 전부 그리라는 뜻이 아니다. 질문을 던져 보고 **여정이 실제로 갈라지는 것만** 그린다.
94
+
95
+ ## 4. 완성 판정 기준 (⑥ 검증)
96
+
97
+ - [ ] ②에서 박은 진입점·종료점이 빠짐없이 그림에 있다
98
+ - [ ] 해피패스가 중앙 일직선으로 읽힌다 (코드 맨 앞 선언)
99
+ - [ ] 모든 분기의 각 가지가 종료점에 닿는다 (끊긴 가지 없음)
100
+ - [ ] §3 질문을 각 단계에 던져봤다
101
+ - [ ] 분기 없는 플로우가 섞여 있지 않다
102
+ - [ ] 전체 장수가 프로젝트 규모 대비 3~7장이다
103
+
104
+ ## 5. 업로드 — 웹 탭 · CLI
105
+
106
+ ```bash
107
+ ch userflows list # 표: order | id | name
108
+ ch userflows get <flowId> # 상세 (--json 이면 순수 JSON)
109
+ ch userflows create --name "로그인·계정 복구" --file ./login-flow.mmd
110
+ ch userflows update <flowId> --file ./login-flow.mmd
111
+ ch userflows delete <flowId>
112
+ ```
113
+
114
+ - `--file`은 Mermaid 코드 파일(.mmd). CRLF는 자동 정제된다.
115
+ - 웹 "유저플로우" 탭이 같은 문서를 zoom in/out·pan 렌더러로 보여준다.
116
+ - Read-before-Write: 수정 전 `get`으로 현재 코드를 받아 편집한다.
117
+
118
+ ## 6. 흔한 함정
119
+
120
+ - **화면 단위로 쪼개기** — 유저플로우는 화면이 아니라 여정 단위다.
121
+ - **분기 없는 CRUD 나열 그리기** — spec의 로직 플로우로 충분하다. 그리지 않는다.
122
+ - **한 장에 전 서비스 그리기** — 아무도 못 읽는다. 여정별로 나눈다.
123
+ - **해피패스를 코드 뒤쪽에 선언** — 중앙 축이 흐트러진다. 맨 앞에 선언한다.
124
+ - **실패 가지를 안내 문구에서 끊기** — 종료점까지 잇는다.
125
+ - **spec 흐름과 중복 상세** — 테이블·컬럼·데이터 이동은 spec `dataFlowScenarios`의 몫이다. 유저플로우는 사용자 갈림길만 그린다.
@@ -8,7 +8,7 @@ description: |
8
8
  (2) "작업 현황 적어줘", "workStatus 갱신해줘" 요청 시,
9
9
  (3) Sprint 종료 회고나 인수인계용으로 spec별 진행 상태를 정리할 때,
10
10
  (4) `ch specs update --work-status` 또는 웹 "작업 현황" 탭에서 갱신할 때.
11
- version: 1.29.0
11
+ version: 1.31.0
12
12
  ---
13
13
 
14
14
  <!-- ch-version-gate -->
@@ -111,9 +111,9 @@ spec 작성 시점에는 비어 있는 게 정상. workStatus는 "방금 만든
111
111
  | 잘못된 위치 | 진짜 위치 |
112
112
  |---|---|
113
113
  | AC/완료 보고 ("로그인 통과 확인") | SQA 항목 |
114
- | 작업 범위 정의 ("Firebase Auth 연결할 것") | spec 본문(content/logic) |
114
+ | 작업 범위 정의 ("Firebase Auth 연결할 것") | spec 본문(스토리문장·흐름 / 레거시는 content·logic) |
115
115
  | 영구 도메인 규칙 ("5회 실패 시 잠금") | logic.businessRules |
116
- | 화면 인터랙션 ("입력 → 검증") | ui.interactionMap |
116
+ | 화면 인터랙션 ("입력 → 검증") | 로직 플로우 (레거시는 ui.interactionMap) |
117
117
  | 컬럼 스펙 | db-tables 문서 |
118
118
 
119
119
  → workStatus는 **시간축 기록**. 시점이 의미를 가지는 것만 적는다. 항구적 규칙은 다른 필드로.