@decencia/ch-cli 1.3.4 → 1.4.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.
- package/dist/commands/backup.d.ts +6 -0
- package/dist/commands/backup.d.ts.map +1 -0
- package/dist/commands/backup.js +200 -0
- package/dist/commands/backup.js.map +1 -0
- package/dist/commands/check.d.ts +3 -0
- package/dist/commands/check.d.ts.map +1 -0
- package/dist/commands/check.js +189 -0
- package/dist/commands/check.js.map +1 -0
- package/dist/commands/setup-skill.d.ts.map +1 -1
- package/dist/commands/setup-skill.js +47 -10
- package/dist/commands/setup-skill.js.map +1 -1
- package/dist/commands/specs.d.ts.map +1 -1
- package/dist/commands/specs.js +3 -0
- package/dist/commands/specs.js.map +1 -1
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -1
- package/dist/skill-meta.d.ts +2 -0
- package/dist/skill-meta.d.ts.map +1 -0
- package/dist/skill-meta.js +15 -0
- package/dist/skill-meta.js.map +1 -0
- package/package.json +3 -2
- package/skill/2t-decencia-channel-change-manager/SKILL.md +73 -0
- package/skill/2t-decencia-channel-change-propagation-v2/SKILL.md +401 -0
- package/skill/2t-decencia-channel-cli-v2/SKILL.md +194 -0
- package/skill/2t-decencia-channel-db-schema-v2/SKILL.md +313 -0
- package/skill/2t-decencia-channel-github-issue/SKILL.md +116 -0
- package/skill/2t-decencia-channel-orchestrator/SKILL.md +64 -0
- package/skill/2t-decencia-channel-prd-v2/SKILL.md +73 -0
- package/skill/2t-decencia-channel-project-bootstrap/SKILL.md +68 -0
- package/skill/2t-decencia-channel-spec-v2/SKILL.md +463 -0
- package/skill/2t-decencia-channel-sprint-builder-v2/SKILL.md +77 -0
- package/skill/2t-decencia-channel-sqa-v2/SKILL.md +422 -0
- package/skill/2t-decencia-channel-work-status-v2/SKILL.md +189 -0
- package/dist/commands/invitations.d.ts +0 -3
- package/dist/commands/invitations.d.ts.map +0 -1
- package/dist/commands/invitations.js +0 -48
- package/dist/commands/invitations.js.map +0 -1
- package/skill/SKILL.md +0 -500
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: 2t-decencia-channel-cli-v2
|
|
3
|
+
description: |
|
|
4
|
+
[2t][v2] 소통채널 CLI(`ch`, npm @decencia/ch-cli) 가이드.
|
|
5
|
+
Epic-Story-Task 체계와 db-tables 리소스, --work-status, --id 등 신규 플래그를 망라한다.
|
|
6
|
+
Use when:
|
|
7
|
+
(1) spec/db-table을 CLI로 다룰 때,
|
|
8
|
+
(2) Task에 description/points/completedAt을 기록할 때,
|
|
9
|
+
(3) ch db-tables 명령(list/get/create/update/delete)을 사용할 때,
|
|
10
|
+
(4) Spec ID를 JIRA 스타일(`LOGIN-001`)로 직접 지정할 때 (`ch specs create --id`).
|
|
11
|
+
version: 1.4.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
|
+
# 소통채널 CLI
|
|
30
|
+
|
|
31
|
+
## 0. Read-before-Write (BLOCKING)
|
|
32
|
+
|
|
33
|
+
문서를 `update`/`set`/`upsert`할 때는 반드시 먼저 해당 문서를 `get`으로 받아 **현재 내용을 확인**한 뒤 수정한다. CLI 플래그는 PATCH 의미라 명시한 필드만 덮어쓰지만, JSON 파일(`--tasks`, `--ui`, `--logic`)은 전체 배열/객체를 통째로 교체하므로 누락 시 데이터 손실 위험.
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
ch specs get <specId> --json > /tmp/before.json # 1) 현재 상태 백업/확인
|
|
37
|
+
# 2) JSON 편집 (tasks/ui/logic 등)
|
|
38
|
+
ch specs update <specId> --tasks /tmp/tasks.json # 3) 수정 적용
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## 1. spec 명령
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
# 생성 (자동 ID)
|
|
45
|
+
ch specs create \
|
|
46
|
+
--name "로그인" \
|
|
47
|
+
--device web,app --domain user --type 인증 --permission 비회원 \
|
|
48
|
+
--content "이메일/비밀번호 로그인" \
|
|
49
|
+
--epic 인증 \
|
|
50
|
+
--tasks ./tasks.json \
|
|
51
|
+
--ui ./ui.json \
|
|
52
|
+
--logic ./logic.json \
|
|
53
|
+
--db-tables tbl_users,tbl_sessions \
|
|
54
|
+
--work-status ./work-status.md
|
|
55
|
+
|
|
56
|
+
# 생성 (사용자 지정 Spec ID, JIRA 스타일 — ch-cli 1.3.5+ / ch-api b029f88+)
|
|
57
|
+
# 패턴: ^[A-Za-z][A-Za-z0-9_]*-[A-Za-z0-9]+$ (MaxLength 60)
|
|
58
|
+
# 충돌 시 409, 패턴 위반 시 400
|
|
59
|
+
ch specs create --id LOGIN-001 \
|
|
60
|
+
--name "로그인" --device web --domain user --type 인증 --epic 인증
|
|
61
|
+
|
|
62
|
+
# 수정: 지정한 플래그만 PATCH. --no-version 시 버전 기록 생략.
|
|
63
|
+
ch specs update <specId> --epic 인증 --no-version
|
|
64
|
+
ch specs update <specId> --tasks ./tasks.json
|
|
65
|
+
ch specs update <specId> --work-status ./status.md
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
> `--id`의 자세한 네이밍 규칙·예외·자동 다음 번호 산정 스크립트는 [[2t-decencia-channel-spec-v2]] §1.5 참조.
|
|
69
|
+
|
|
70
|
+
### Task JSON (`--tasks`)
|
|
71
|
+
|
|
72
|
+
```json
|
|
73
|
+
[
|
|
74
|
+
{
|
|
75
|
+
"id": "",
|
|
76
|
+
"title": "로그인 폼 구현",
|
|
77
|
+
"done": false,
|
|
78
|
+
"assignee": "박준하",
|
|
79
|
+
"points": 5,
|
|
80
|
+
"description": "## 세부\n- React Hook Form\n- Yup validation"
|
|
81
|
+
},
|
|
82
|
+
{
|
|
83
|
+
"id": "",
|
|
84
|
+
"title": "유효성 검증",
|
|
85
|
+
"done": true,
|
|
86
|
+
"points": 2,
|
|
87
|
+
"completedAt": "2026-05-29T08:00:00.000Z"
|
|
88
|
+
}
|
|
89
|
+
]
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
서버 자동 처리:
|
|
93
|
+
- `id` 비어 있으면 UUID 부여
|
|
94
|
+
- `done: true` & `completedAt` 미지정 → 현재 ISO 부여
|
|
95
|
+
- `done: false` → `completedAt` 제거
|
|
96
|
+
- 전체 progress(%) 자동 재계산
|
|
97
|
+
|
|
98
|
+
### UI JSON (`--ui`)
|
|
99
|
+
|
|
100
|
+
```json
|
|
101
|
+
{
|
|
102
|
+
"figmaNodeId": "123:456",
|
|
103
|
+
"route": "/login",
|
|
104
|
+
"file": "src/app/login/page.tsx",
|
|
105
|
+
"access": "public",
|
|
106
|
+
"interactionMap": "## 인터랙션\n1. 이메일 입력 → 검증\n2. ..."
|
|
107
|
+
}
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
### Logic JSON (`--logic`)
|
|
111
|
+
|
|
112
|
+
```json
|
|
113
|
+
{
|
|
114
|
+
"dataFlow": "이메일/비밀번호 → Firebase Auth → ID Token",
|
|
115
|
+
"stateTransitions": "| 현재 | 입력 | 다음 |\n|---|---|---|\n| idle | submit | loading |",
|
|
116
|
+
"businessRules": "- 5회 실패 시 1시간 잠금"
|
|
117
|
+
}
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
### dbTableRefs (`--db-tables`)
|
|
121
|
+
|
|
122
|
+
쉼표 구분 ID 목록. 서버에서 각 테이블의 `relatedSpecIds`에도 자동 반영(양방향 동기화).
|
|
123
|
+
|
|
124
|
+
```bash
|
|
125
|
+
ch specs update <specId> --db-tables tbl_users,tbl_sessions
|
|
126
|
+
ch specs update <specId> --db-tables "" # 모두 해제
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
### workStatus (`--work-status <mdFile>`)
|
|
130
|
+
|
|
131
|
+
마크다운 파일 경로. spec 하단 "작업 현황" 탭에 표시.
|
|
132
|
+
|
|
133
|
+
```bash
|
|
134
|
+
ch specs update <specId> --work-status ./status.md --no-version
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
## 2. db-tables 명령
|
|
138
|
+
|
|
139
|
+
```bash
|
|
140
|
+
ch db-tables list # 표 출력: name | id | columns | indexes | security | specs
|
|
141
|
+
ch db-tables get <tableId> # 상세 (JSON)
|
|
142
|
+
ch db-tables create \
|
|
143
|
+
--name users --description "회원 기본정보" \
|
|
144
|
+
--columns ./users-columns.json \
|
|
145
|
+
--indexes ./users-indexes.json \
|
|
146
|
+
--security ./users-security.json
|
|
147
|
+
ch db-tables update <tableId> --security ./new-security.json
|
|
148
|
+
ch db-tables delete <tableId> # 참조 spec의 dbTableRefs도 서버에서 자동 정리
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
`relatedSpecIds`는 사용자 입력 금지(서버 자동 관리). spec ↔ db-table 양방향 동기화를 서버가 batch로 처리.
|
|
152
|
+
|
|
153
|
+
### columns.json
|
|
154
|
+
|
|
155
|
+
```json
|
|
156
|
+
[
|
|
157
|
+
{ "name": "id", "type": "string", "nullable": false, "description": "PK" },
|
|
158
|
+
{ "name": "email", "type": "string", "nullable": false, "default": "''" }
|
|
159
|
+
]
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
### indexes.json
|
|
163
|
+
|
|
164
|
+
```json
|
|
165
|
+
[
|
|
166
|
+
{ "name": "idx_email", "fields": ["email"], "unique": true }
|
|
167
|
+
]
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
### security.json
|
|
171
|
+
|
|
172
|
+
```json
|
|
173
|
+
{
|
|
174
|
+
"type": "firestore",
|
|
175
|
+
"summary": "본인만 R/W",
|
|
176
|
+
"content": "match /users/{uid} { allow read, write: if request.auth.uid == uid; }",
|
|
177
|
+
"roles": [
|
|
178
|
+
{ "role": "admin", "read": true, "write": true, "delete": true },
|
|
179
|
+
{ "role": "user", "read": "own", "write": "own", "delete": false }
|
|
180
|
+
]
|
|
181
|
+
}
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
## 3. 운영 팁
|
|
185
|
+
|
|
186
|
+
- Windows 한글 출력이 비어 보일 때: `ch specs get <id> --json | Out-File spec.json` (PowerShell)
|
|
187
|
+
- `ch-cli` 버전 확인: `ch --version` (1.3.2+ 권장)
|
|
188
|
+
- 본문(content/markdown)은 항상 `\n` 줄바꿈 — CLI가 BOM/CRLF 자동 정제
|
|
189
|
+
|
|
190
|
+
## 4. 흔한 함정
|
|
191
|
+
|
|
192
|
+
- `--tasks` JSON 통째 교체이므로 일부만 수정해도 **전체 배열 전달 필수**. 반드시 `ch specs get`으로 받아 편집.
|
|
193
|
+
- `--db-tables ""`는 모두 해제. 단일 ID 유지하려면 그 ID만 명시.
|
|
194
|
+
- `relatedSpecIds`를 JSON에 명시해도 서버가 무시 (자동 관리 영역).
|
|
@@ -0,0 +1,313 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: 2t-decencia-channel-db-schema-v2
|
|
3
|
+
description: |
|
|
4
|
+
[2t][v2] 소통채널 DB 스키마 운영 가이드 — 전체 스펙 문서(/db-schema)와 per-table 리소스(/db-tables)를 함께 다룬다.
|
|
5
|
+
데이터 모델 개요·ERD·정책은 전체 문서에, 컬럼·인덱스·보안규칙은 테이블별 문서에 저장.
|
|
6
|
+
Use when:
|
|
7
|
+
(1) 프로젝트 전체 DB 설계 문서(ERD/네이밍/마이그레이션 노트)를 작성·갱신할 때,
|
|
8
|
+
(2) DB 테이블 단위로 컬럼·인덱스·보안규칙을 등록·수정할 때,
|
|
9
|
+
(3) 새 테이블을 추가하면서 전체 인벤토리도 함께 업데이트할 때,
|
|
10
|
+
(4) spec.dbTableRefs와 양방향 동기화가 필요한 작업 시.
|
|
11
|
+
version: 1.4.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
|
+
# DB 스키마 — 전체 스펙 + per-table 분담
|
|
30
|
+
|
|
31
|
+
소통채널은 두 개의 리소스를 함께 운영한다.
|
|
32
|
+
|
|
33
|
+
| 리소스 | CLI | 저장 단위 | 담당 |
|
|
34
|
+
|---|---|---|---|
|
|
35
|
+
| **전체 스펙 문서** (`/db-schema`) | `ch db-schema get/set/versions` | 프로젝트당 **마크다운 1건** | 데이터 모델 개요·ERD·테이블 인벤토리·네이밍·마이그레이션 노트 |
|
|
36
|
+
| **테이블 문서** (`/db-tables/{tableId}`) | `ch db-tables list/get/create/update/delete` | 테이블당 **JSON 1건** | 컬럼 정의·인덱스·보안 규칙·역할 매트릭스 |
|
|
37
|
+
|
|
38
|
+
> 둘은 보완 관계다. 전체 스펙 문서는 **읽는 사람을 위한 설계 의도**, 테이블 문서는 **기계가 검증·동기화할 수 있는 정형 데이터**.
|
|
39
|
+
|
|
40
|
+
---
|
|
41
|
+
|
|
42
|
+
## 🚨 BLOCKING: Read-before-Write
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
# 전체 스펙 문서
|
|
46
|
+
ch db-schema get --json > /tmp/schema.json # 먼저
|
|
47
|
+
# content 편집
|
|
48
|
+
ch db-schema set --content /tmp/schema.md --dbtype firestore
|
|
49
|
+
|
|
50
|
+
# 테이블 문서
|
|
51
|
+
ch db-tables get <tableId> --json > /tmp/tbl.json
|
|
52
|
+
ch db-tables update <tableId> --columns /tmp/cols.json
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
`--content` 통째 교체, `--columns/--indexes/--security` 각각 통째 교체. 기존 내용 보존하려면 반드시 `get` 후 편집.
|
|
56
|
+
|
|
57
|
+
---
|
|
58
|
+
|
|
59
|
+
## 1. DB 유형 판별 (작성 전 필수)
|
|
60
|
+
|
|
61
|
+
| dbType | 대상 | 판단 단서 |
|
|
62
|
+
|---|---|---|
|
|
63
|
+
| **firestore** | Firebase Firestore | 코드에 `firebase-admin`, `firebase/firestore` |
|
|
64
|
+
| **supabase** | Supabase / Postgres | `@supabase/supabase-js`, `pg` |
|
|
65
|
+
| **mysql** | MySQL / MariaDB | `mysql2`, `prisma` (mysql provider) |
|
|
66
|
+
| **generic** | 미정 또는 혼합 | 위 어느 것도 아닐 때 |
|
|
67
|
+
|
|
68
|
+
`ch db-schema set --dbtype <type>` 로 명시. 미정이면 `generic`. DB 유형에 따라 컬럼 `type` 값·보안 규칙 `type` 값이 달라진다.
|
|
69
|
+
|
|
70
|
+
---
|
|
71
|
+
|
|
72
|
+
# Part A — 전체 스펙 문서 (`ch db-schema`)
|
|
73
|
+
|
|
74
|
+
## 2. 전체 스펙 문서 구조
|
|
75
|
+
|
|
76
|
+
마크다운 한 덩어리. 권장 목차:
|
|
77
|
+
|
|
78
|
+
```markdown
|
|
79
|
+
# {프로젝트명} DB 스키마
|
|
80
|
+
|
|
81
|
+
## 1. 개요
|
|
82
|
+
- DB 유형: firestore
|
|
83
|
+
- 호스팅: Firebase (asia-northeast3)
|
|
84
|
+
- 백업 정책: daily, 14d retention
|
|
85
|
+
- 멀티테넌시: 단일 테넌트
|
|
86
|
+
|
|
87
|
+
## 2. 설계 원칙
|
|
88
|
+
- 비정규화 우선 (read-heavy 워크로드)
|
|
89
|
+
- 모든 문서에 createdAt/updatedAt/deletedAt 필수
|
|
90
|
+
- 소프트 삭제 (deletedAt = serverTimestamp())
|
|
91
|
+
- 시간 필드는 timestamp 타입 통일
|
|
92
|
+
- 통화는 number(원 단위), 분수 없음
|
|
93
|
+
|
|
94
|
+
## 3. 네이밍 규칙
|
|
95
|
+
- 컬렉션/테이블: 영문 소문자 복수형 (`users`, `orders`)
|
|
96
|
+
- 필드: lowerCamelCase
|
|
97
|
+
- 인덱스: `idx_{컬럼명}` / 복합은 `idx_{a}_{b}` / unique는 `_unique` 접미
|
|
98
|
+
- ID: 모두 string (Firestore document ID 자동 생성 또는 UUID v4)
|
|
99
|
+
|
|
100
|
+
## 4. 테이블 인벤토리
|
|
101
|
+
|
|
102
|
+
| 이름 | tableId | 설명 | 핵심 키 | spec |
|
|
103
|
+
|---|---|---|---|---|
|
|
104
|
+
| users | tbl_users | 회원 기본정보 | id (uid) | [spec:로그인], [spec:회원가입] |
|
|
105
|
+
| sessions | tbl_sessions | 로그인 세션 | id, userId | [spec:로그인] |
|
|
106
|
+
| orders | tbl_orders | 주문 내역 | id, userId | [spec:주문] |
|
|
107
|
+
| products | tbl_products | 상품 카탈로그 | id | [spec:상품 목록] |
|
|
108
|
+
|
|
109
|
+
> 각 tableId의 컬럼·인덱스·보안규칙 상세는 `ch db-tables get <id>` 또는 웹의 DB 스키마 탭 참조.
|
|
110
|
+
|
|
111
|
+
## 5. ERD (관계도)
|
|
112
|
+
|
|
113
|
+
```
|
|
114
|
+
users (1) ──< sessions (N)
|
|
115
|
+
users (1) ──< orders (N)
|
|
116
|
+
orders (N) >── products (1) // 비정규화: orders.productName 캐시
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
또는 mermaid:
|
|
120
|
+
|
|
121
|
+
\```mermaid
|
|
122
|
+
erDiagram
|
|
123
|
+
USERS ||--o{ SESSIONS : has
|
|
124
|
+
USERS ||--o{ ORDERS : places
|
|
125
|
+
ORDERS }o--|| PRODUCTS : refers
|
|
126
|
+
\```
|
|
127
|
+
|
|
128
|
+
## 6. 정규화 / 비정규화 정책
|
|
129
|
+
- `orders.productName` ← `products.name` 캐시 (상품명 변경 시 batch 갱신)
|
|
130
|
+
- `orders.userDisplayName` ← `users.displayName` 캐시
|
|
131
|
+
- 캐시 필드는 모두 `// denormalized from X` 주석 (테이블 문서의 description에)
|
|
132
|
+
|
|
133
|
+
## 7. 보안 일관성 원칙
|
|
134
|
+
- 모든 테이블에 admin 역할이 read/write/delete 전권
|
|
135
|
+
- 일반 사용자는 본인 문서만 R/W (Firestore: `request.auth.uid == uid` 패턴)
|
|
136
|
+
- 공개 컬렉션(예: products)은 read 전체 허용, write는 admin만
|
|
137
|
+
|
|
138
|
+
## 8. 마이그레이션 노트
|
|
139
|
+
- 2026-05-29: `users.lastLoginAt` 추가 (기존 문서는 backfill 안 함, null 허용)
|
|
140
|
+
- 2026-04-10: `orders` 컬렉션 생성, products와 연결
|
|
141
|
+
- 2026-03-01: 초기 스키마 v1 (users만)
|
|
142
|
+
|
|
143
|
+
## 9. 운영 메모
|
|
144
|
+
- Firestore 쿼리 1초 이상 시 인덱스 점검
|
|
145
|
+
- 대량 삭제는 batch 500 단위로 분할
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
## 3. 작성·갱신 워크플로우 (전체 스펙)
|
|
149
|
+
|
|
150
|
+
### 3-1. 신규 프로젝트 — 처음 작성
|
|
151
|
+
|
|
152
|
+
```bash
|
|
153
|
+
# 1) 위 §2 템플릿 기반으로 schema.md 작성 (테이블 인벤토리는 비어있는 상태로 시작)
|
|
154
|
+
# 2) 업로드
|
|
155
|
+
ch db-schema set --content schema.md --dbtype firestore
|
|
156
|
+
ch db-schema get --json | jq '.content' | head # 검증
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
### 3-2. 새 테이블 추가 시 — 두 곳 동기화
|
|
160
|
+
|
|
161
|
+
```bash
|
|
162
|
+
# 1) 테이블 문서부터 생성 (Part B 참조)
|
|
163
|
+
ch db-tables create --name orders --description "주문" \
|
|
164
|
+
--columns ./orders-cols.json --indexes ./orders-idx.json --security ./orders-sec.json
|
|
165
|
+
# → {"id": "tbl_orders_abc"}
|
|
166
|
+
|
|
167
|
+
# 2) 전체 스펙 문서의 §4 테이블 인벤토리 + §5 ERD에 orders 추가
|
|
168
|
+
ch db-schema get --json | jq -r '.content' > /tmp/schema.md
|
|
169
|
+
# /tmp/schema.md 편집: 인벤토리에 행 추가, ERD에 관계 추가
|
|
170
|
+
ch db-schema set --content /tmp/schema.md
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
> 테이블 생성/삭제할 때마다 전체 스펙 문서의 인벤토리·ERD·마이그레이션 노트를 함께 갱신한다.
|
|
174
|
+
|
|
175
|
+
### 3-3. 정책 변경 — 전체 스펙에만 기록
|
|
176
|
+
|
|
177
|
+
설계 원칙·네이밍·보안 일관성은 전체 스펙 문서에만 적는다. 개별 테이블의 securityRules.content와 충돌하지 않도록 정책은 한 곳에 통합.
|
|
178
|
+
|
|
179
|
+
---
|
|
180
|
+
|
|
181
|
+
# Part B — 테이블 문서 (`ch db-tables`)
|
|
182
|
+
|
|
183
|
+
## 4. CLI 명령
|
|
184
|
+
|
|
185
|
+
```bash
|
|
186
|
+
ch db-tables list # 표: name | id | columns | indexes | security | specs
|
|
187
|
+
ch db-tables get <tableId> --json
|
|
188
|
+
ch db-tables create --name users --description "회원" \
|
|
189
|
+
--columns ./columns.json --indexes ./indexes.json --security ./security.json
|
|
190
|
+
ch db-tables update <tableId> --security ./new-security.json
|
|
191
|
+
ch db-tables delete <tableId> # 참조 spec의 dbTableRefs도 서버에서 자동 정리
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
`relatedSpecIds`는 사용자 입력 금지(서버 자동 관리).
|
|
195
|
+
|
|
196
|
+
## 5. JSON 템플릿
|
|
197
|
+
|
|
198
|
+
### 5-1. columns.json — DB 종류별 type 명세
|
|
199
|
+
|
|
200
|
+
| DB 종류 | type 예 |
|
|
201
|
+
|---|---|
|
|
202
|
+
| **Firestore** | `string`, `number`, `boolean`, `timestamp`, `map`, `array`, `reference` |
|
|
203
|
+
| **Supabase / Postgres** | `text`, `int8`, `numeric`, `boolean`, `timestamptz`, `jsonb`, `uuid` |
|
|
204
|
+
| **MySQL** | `VARCHAR(255)`, `INT`, `DATETIME`, `JSON`, `TEXT` |
|
|
205
|
+
| **Generic** | 자유 문자열 (`string` 등) |
|
|
206
|
+
|
|
207
|
+
```json
|
|
208
|
+
[
|
|
209
|
+
{"name": "id", "type": "string", "nullable": false, "description": "PK"},
|
|
210
|
+
{"name": "email", "type": "string", "nullable": false, "description": "로그인 이메일"},
|
|
211
|
+
{"name": "displayName", "type": "string", "nullable": true, "description": "표시명"},
|
|
212
|
+
{"name": "userId", "type": "string", "nullable": false, "description": "FK → users.id"},
|
|
213
|
+
{"name": "userDisplayName", "type": "string", "nullable": true, "description": "denormalized from users.displayName"},
|
|
214
|
+
{"name": "createdAt", "type": "timestamp", "nullable": false, "default": "serverTimestamp()"},
|
|
215
|
+
{"name": "deletedAt", "type": "timestamp", "nullable": true, "description": "소프트 삭제"}
|
|
216
|
+
]
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
description 활용 권장:
|
|
220
|
+
- `PK` / `FK → table.col` 명시
|
|
221
|
+
- 비정규화 캐시는 `denormalized from X` 적어 두면 ERD 단방향 추적 가능
|
|
222
|
+
- enum이라면 허용값 나열 (`role: "admin" | "user"`)
|
|
223
|
+
|
|
224
|
+
### 5-2. indexes.json
|
|
225
|
+
|
|
226
|
+
```json
|
|
227
|
+
[
|
|
228
|
+
{"name": "idx_email_unique", "fields": ["email"], "unique": true},
|
|
229
|
+
{"name": "idx_userId_created", "fields": ["userId", "createdAt"]},
|
|
230
|
+
{"name": "idx_deletedAt", "fields": ["deletedAt"]}
|
|
231
|
+
]
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
규칙:
|
|
235
|
+
- 자주 필터 + 정렬 쌍은 복합 인덱스 (`["userId", "createdAt"]`)
|
|
236
|
+
- 소프트 삭제 사용 시 `deletedAt` 단일 인덱스 (살아있는 문서만 빠른 쿼리)
|
|
237
|
+
- Firestore는 복합 인덱스가 자동 안 만들어지는 케이스가 많아 명시 권장
|
|
238
|
+
|
|
239
|
+
### 5-3. security.json — 보안 규칙 + 역할 매트릭스
|
|
240
|
+
|
|
241
|
+
`type` 옵션: `firestore` | `rls` (Supabase RLS) | `sql-grant` | `generic`
|
|
242
|
+
|
|
243
|
+
```json
|
|
244
|
+
{
|
|
245
|
+
"type": "firestore",
|
|
246
|
+
"summary": "본인만 R/W, admin은 전권",
|
|
247
|
+
"content": "match /users/{uid} {\n allow read, write: if request.auth.uid == uid;\n allow read, write: if request.auth.token.admin == true;\n}",
|
|
248
|
+
"roles": [
|
|
249
|
+
{"role": "admin", "read": true, "write": true, "delete": true},
|
|
250
|
+
{"role": "user", "read": "own", "write": "own", "delete": false}
|
|
251
|
+
]
|
|
252
|
+
}
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
`read/write/delete`는 `true | false | 문자열 조건(예: "own", "auth.uid == doc.userId")` 자유 입력.
|
|
256
|
+
|
|
257
|
+
### 5-4. 테이블 단위 작성 체크리스트
|
|
258
|
+
|
|
259
|
+
- [ ] 모든 PK/FK가 columns에 명시되어 있는가
|
|
260
|
+
- [ ] 시간 필드(createdAt/updatedAt/deletedAt) 컨벤션 준수
|
|
261
|
+
- [ ] 비정규화 캐시는 description에 출처 명시
|
|
262
|
+
- [ ] 보안 규칙의 roles 매트릭스가 실제 content와 일치
|
|
263
|
+
- [ ] 자주 쓰는 쿼리에 맞는 인덱스 있음
|
|
264
|
+
- [ ] 전체 스펙 문서 §4 인벤토리에도 등록되었는가
|
|
265
|
+
|
|
266
|
+
---
|
|
267
|
+
|
|
268
|
+
## 6. spec ↔ db-table 양방향 동기화
|
|
269
|
+
|
|
270
|
+
- `spec.dbTableRefs`에 tableId 추가 → 서버가 해당 테이블의 `relatedSpecIds`에 specId 자동 add (batch)
|
|
271
|
+
- spec 삭제 → 모든 테이블에서 정리
|
|
272
|
+
- db-table 삭제 → 참조 spec의 `dbTableRefs`에서 정리
|
|
273
|
+
|
|
274
|
+
웹: 칩 X 또는 picker로 변경. 모두 ch-api PATCH 경유.
|
|
275
|
+
|
|
276
|
+
전체 스펙 문서 §4 인벤토리의 "spec" 컬럼은 수동 갱신 — 양방향 동기화는 정형 데이터(테이블 문서)에만 동작한다.
|
|
277
|
+
|
|
278
|
+
---
|
|
279
|
+
|
|
280
|
+
## 7. 웹 UI 흐름
|
|
281
|
+
|
|
282
|
+
- 프로젝트 메뉴 → **DB 스키마** 탭
|
|
283
|
+
- **"문서" 서브탭** → 전체 스펙 문서(마크다운) 표시 / 편집
|
|
284
|
+
- **"테이블" 서브탭** → db-tables 목록 + 상세 패널
|
|
285
|
+
- spec 상세의 "연관 DB 테이블" 섹션:
|
|
286
|
+
- **칩 클릭** → DbTableModal (컬럼·인덱스·보안규칙·역할·연관 명세 표시 + 전체 보기 링크)
|
|
287
|
+
- **칩 X 버튼** → 즉시 해제
|
|
288
|
+
- **+ 버튼** → DbTablePicker 모달 (체크박스 다중 선택)
|
|
289
|
+
|
|
290
|
+
---
|
|
291
|
+
|
|
292
|
+
## 8. 흔한 함정
|
|
293
|
+
|
|
294
|
+
- columns/indexes/securityRules JSON은 **전체 교체**. 일부 수정 시 반드시 `get` 후 편집.
|
|
295
|
+
- 전체 스펙 문서의 `--content`도 통째 교체. 작은 수정도 `get` 후 부분 편집해 통째 전송.
|
|
296
|
+
- `relatedSpecIds`를 JSON에 명시해도 서버가 무시 (자동 관리 영역).
|
|
297
|
+
- 새 테이블을 만들고 전체 스펙 인벤토리 갱신을 잊으면, 문서 읽는 사람이 그 테이블의 존재를 모른다.
|
|
298
|
+
- 보안 정책을 테이블별 securityRules에만 적고 전체 스펙의 §7에 적지 않으면 일관성 검토가 누락된다.
|
|
299
|
+
- ERD 관계를 그리지 않고 column description의 "FK"만 적으면, 신규 개발자가 전체 구조를 파악하기 어렵다.
|
|
300
|
+
|
|
301
|
+
---
|
|
302
|
+
|
|
303
|
+
## 9. 작업 순서 체크리스트
|
|
304
|
+
|
|
305
|
+
신규 프로젝트의 DB를 처음 설계할 때:
|
|
306
|
+
|
|
307
|
+
1. DB 유형 확정 → `ch db-schema set --dbtype firestore` 등
|
|
308
|
+
2. 전체 스펙 문서 초안 (§1 개요 / §2 설계 원칙 / §3 네이밍 규칙 / §7 보안 일관성) 작성
|
|
309
|
+
3. 핵심 테이블 1~2개를 `ch db-tables create`로 등록 (users 먼저)
|
|
310
|
+
4. 전체 스펙 §4 인벤토리에 추가, §5 ERD에 노드 추가
|
|
311
|
+
5. spec 작성 시 `--db-tables tbl_id`로 연결 → 양방향 동기화 자동
|
|
312
|
+
6. 새 테이블이 늘 때마다 §2(테이블 문서) + §4·§5(전체 스펙) 동시 갱신
|
|
313
|
+
7. 분기/릴리즈마다 §8 마이그레이션 노트 한 줄 추가
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: 2t-decencia-channel-github-issue
|
|
3
|
+
description: gh CLI로 현재 repo에 GitHub 이슈를 작성한다. 이슈 1개=유형 1개(feat/fix/bug), 표준 본문 양식(작업내용·관련 명세 백링크·완료조건)으로 발행. "이슈 만들어줘"/"깃헙 이슈로 등록해줘" 요청 시, 또는 소통채널 기획·명세 작업 후 처리할 일들을 GitHub 이슈로 옮길 때 사용. 멱등성/중복방지·확인단계는 다루지 않음(요청대로 바로 생성).
|
|
4
|
+
allowed-tools: Bash(gh:*) Bash(git:*) Read Write
|
|
5
|
+
version: 1.4.0
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
<!-- ch-version-gate -->
|
|
9
|
+
## ⚠️ 시작 전 필수 — 버전 게이트 (생략 금지)
|
|
10
|
+
|
|
11
|
+
이 스킬로 **어떤 작업이든 수행하기 전에 가장 먼저** 아래를 실행한다:
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
ch check
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
- exit code 0(통과)이 **아니면 즉시 중단**한다. 출력에 안내된 업데이트 명령(`npm install -g @decencia/ch-cli@latest` 또는 `ch setup-skill`)을 사용자에게 전달하고, 갱신이 끝나기 전까지 **이 스킬의 어떤 단계도 진행하지 않는다.**
|
|
18
|
+
- `ch`가 미설치/미인증이어도 먼저 `ch check`를 시도한다. (네트워크 불가 시 ch check는 통과시키되 경고를 남긴다.)
|
|
19
|
+
|
|
20
|
+
구버전 스킬·CLI 사용을 막기 위한 게이트다. 건너뛰지 말 것.
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
# 2t-decencia-channel-github-issue — GitHub 이슈 작성 스킬
|
|
24
|
+
|
|
25
|
+
`gh` CLI로 **현재 repo**에 이슈를 작성한다.
|
|
26
|
+
이 스킬의 본질은 **"이슈에 들어갈 내용 양식 + gh로 쏘는 방법"** 가이드다.
|
|
27
|
+
|
|
28
|
+
핵심 원칙:
|
|
29
|
+
- **이슈 1개 = 유형 1개** (`feat` | `fix` | `bug`) — 라벨로 표시.
|
|
30
|
+
- 일괄 발행 가능(여러 이슈 = 양식대로 반복). 단건도 당연히 포함.
|
|
31
|
+
- **멱등성/중복방지·dry-run·확인단계는 다루지 않는다.** 요청받은 이슈를 그냥 생성한다.
|
|
32
|
+
|
|
33
|
+
## Use when
|
|
34
|
+
- "이슈 만들어줘", "깃헙 이슈로 등록해줘"
|
|
35
|
+
- 소통채널 기획/명세 작업 후 처리할 일을 깃헙 이슈로 발행할 때
|
|
36
|
+
|
|
37
|
+
---
|
|
38
|
+
|
|
39
|
+
## 0. 전제 (시작 시 확인)
|
|
40
|
+
|
|
41
|
+
1. **gh 인증**
|
|
42
|
+
```bash
|
|
43
|
+
gh auth status
|
|
44
|
+
```
|
|
45
|
+
실패하면 진행하지 말고 안내: `gh auth login` 을 먼저 실행하세요.
|
|
46
|
+
|
|
47
|
+
2. **repo**: cwd의 git `origin` 을 `gh` 가 자동 인식한다(별도 지정 불필요).
|
|
48
|
+
다른 repo에 쏘려면 각 `gh issue create` 에 `--repo <owner>/<name>` 추가.
|
|
49
|
+
|
|
50
|
+
3. **라벨 보장** (없으면 생성 — 이미 있으면 무시):
|
|
51
|
+
```bash
|
|
52
|
+
gh label create feat --color 0e8a16 --description "새 기능" 2>/dev/null || true
|
|
53
|
+
gh label create fix --color 1d76db --description "의도된 동작 변경" 2>/dev/null || true
|
|
54
|
+
gh label create bug --color d73a4a --description "결함/회귀" 2>/dev/null || true
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
---
|
|
58
|
+
|
|
59
|
+
## 1. 유형 정의 + 작업내용 작성법
|
|
60
|
+
|
|
61
|
+
| 유형 | 의미 | 작업내용 작성법 |
|
|
62
|
+
|------|------|----------------|
|
|
63
|
+
| **feat** | 새로 구현 | 무엇을 구현해야 하는지 |
|
|
64
|
+
| **fix** | **의도된** 동작 변경 | 현재 X → Y 로 변경해야 한다 |
|
|
65
|
+
| **bug** | **의도치 않은** 결함/회귀 | 어떤 작업을 수행하는 과정에서 어떤 문제가 생기는지 (재현 / 기대 동작) |
|
|
66
|
+
|
|
67
|
+
> fix vs bug: 의도적으로 바꾸는 거면 `fix`, 하다가 터진 거면 `bug`.
|
|
68
|
+
|
|
69
|
+
---
|
|
70
|
+
|
|
71
|
+
## 2. 이슈 양식
|
|
72
|
+
|
|
73
|
+
- **제목**: `<유형>: <한 줄 요약>` (예: `feat: 로그인 자동완성 추가`)
|
|
74
|
+
- **라벨**: 유형 1개
|
|
75
|
+
- **본문 템플릿**(마크다운):
|
|
76
|
+
|
|
77
|
+
```markdown
|
|
78
|
+
## 작업내용
|
|
79
|
+
<위 표의 유형별 가이드대로 구체적으로>
|
|
80
|
+
|
|
81
|
+
## 관련 명세
|
|
82
|
+
- [LOGIN-001](https://channel.decenciasoft.com/projects/<projectId>/specs)
|
|
83
|
+
- [USER-003](https://channel.decenciasoft.com/projects/<projectId>/specs)
|
|
84
|
+
|
|
85
|
+
## 완료조건
|
|
86
|
+
- [ ] <무엇이 되면 done 인지>
|
|
87
|
+
- [ ] ...
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
- **관련 명세(specid)**:
|
|
91
|
+
- `projectId` 는 cwd(또는 상위)의 `.ch-project` 파일에서 읽는다(`{"projectId": "..."}`). 없으면 사용자에게 묻거나 링크 없이 specid만 적는다.
|
|
92
|
+
- specid가 **비어 있으면 "관련 명세" 섹션 전체를 생략**한다(허용).
|
|
93
|
+
- **완료조건(AC)**: 개발자가 "뭐가 되면 done"인지 알도록 체크리스트로.
|
|
94
|
+
|
|
95
|
+
---
|
|
96
|
+
|
|
97
|
+
## 3. 발행 (Procedure)
|
|
98
|
+
|
|
99
|
+
1. 위 0번 전제(인증·라벨) 확인.
|
|
100
|
+
2. 발행할 이슈 목록을 양식대로 구성(제목·유형·작업내용·관련명세·완료조건).
|
|
101
|
+
3. 본문은 **파일로 저장 후 `--body-file`** 로 전달한다(따옴표·줄바꿈·한글 안전, Windows에서는 **LF 줄바꿈** 사용 — CRLF 주의).
|
|
102
|
+
```bash
|
|
103
|
+
# 본문을 임시파일에 작성 (LF)
|
|
104
|
+
gh issue create --title "feat: 로그인 자동완성 추가" \
|
|
105
|
+
--body-file /tmp/issue-body.md \
|
|
106
|
+
--label feat
|
|
107
|
+
```
|
|
108
|
+
4. 여러 이슈면 3을 **반복**한다.
|
|
109
|
+
5. 생성된 이슈 URL을 모아 사용자에게 보고한다.
|
|
110
|
+
|
|
111
|
+
---
|
|
112
|
+
|
|
113
|
+
## 주의
|
|
114
|
+
- `--body "..."` 직접 인라인은 따옴표/줄바꿈/한글 깨짐 위험 → `--body-file` 권장.
|
|
115
|
+
- 라벨 미존재 시 `gh issue create --label` 은 실패하므로 0-3번(라벨 보장)을 반드시 선행.
|
|
116
|
+
- 이 스킬은 **중복 검사/되돌리기를 하지 않는다.** 재실행하면 같은 이슈가 또 생길 수 있으니, 호출 측(에이전트/사용자)이 무엇을 발행할지 판단한다.
|