@decencia/ch-cli 1.30.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.
- package/agent/2t-decencia-channel-issue-coder.md +1 -1
- package/agent/2t-decencia-channel-pr-merger.md +1 -1
- package/agent/2t-decencia-channel-terraformer.md +1 -1
- package/dist/commands/policies.d.ts +12 -0
- package/dist/commands/policies.d.ts.map +1 -0
- package/dist/commands/policies.js +302 -0
- package/dist/commands/policies.js.map +1 -0
- package/dist/commands/screens.d.ts.map +1 -1
- package/dist/commands/screens.js +103 -23
- package/dist/commands/screens.js.map +1 -1
- package/dist/commands/specs.d.ts +15 -0
- package/dist/commands/specs.d.ts.map +1 -1
- package/dist/commands/specs.js +117 -10
- package/dist/commands/specs.js.map +1 -1
- package/dist/commands/sprints.d.ts +16 -0
- package/dist/commands/sprints.d.ts.map +1 -1
- package/dist/commands/sprints.js +152 -4
- package/dist/commands/sprints.js.map +1 -1
- package/dist/commands/sqa.d.ts +23 -0
- package/dist/commands/sqa.d.ts.map +1 -1
- package/dist/commands/sqa.js +252 -6
- package/dist/commands/sqa.js.map +1 -1
- package/dist/commands/userflows.d.ts +11 -0
- package/dist/commands/userflows.d.ts.map +1 -0
- package/dist/commands/userflows.js +275 -0
- package/dist/commands/userflows.js.map +1 -0
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/skill/2t-decencia-channel-change-manager/SKILL.md +1 -1
- package/skill/2t-decencia-channel-change-propagation-v2/SKILL.md +11 -7
- package/skill/2t-decencia-channel-cli-v2/SKILL.md +48 -20
- package/skill/2t-decencia-channel-db-schema-v2/SKILL.md +4 -4
- package/skill/2t-decencia-channel-github-issue/SKILL.md +1 -1
- package/skill/2t-decencia-channel-orchestrator/SKILL.md +1 -1
- package/skill/2t-decencia-channel-policy-v2/SKILL.md +114 -0
- package/skill/2t-decencia-channel-prd-v2/SKILL.md +37 -12
- package/skill/2t-decencia-channel-project-bootstrap/SKILL.md +22 -25
- package/skill/2t-decencia-channel-screen-v2/SKILL.md +135 -0
- package/skill/2t-decencia-channel-spec-v2/SKILL.md +288 -443
- package/skill/2t-decencia-channel-sprint-builder-v2/SKILL.md +11 -3
- package/skill/2t-decencia-channel-sprint-runner/SKILL.md +1 -1
- package/skill/2t-decencia-channel-sqa-v2/SKILL.md +124 -21
- package/skill/2t-decencia-channel-userflow-v2/SKILL.md +125 -0
- package/skill/2t-decencia-channel-work-status-v2/SKILL.md +3 -3
|
@@ -0,0 +1,275 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.parseUserflowOrder = parseUserflowOrder;
|
|
4
|
+
exports.registerUserflowsCommand = registerUserflowsCommand;
|
|
5
|
+
const client_1 = require("../client");
|
|
6
|
+
const output_1 = require("../output");
|
|
7
|
+
const utils_1 = require("../utils");
|
|
8
|
+
/**
|
|
9
|
+
* ch userflows — 유저플로우(분기 있는 사용자 여정의 Mermaid 문서) 관리 명령.
|
|
10
|
+
*
|
|
11
|
+
* ch-api의 /userflows REST(이슈 #216)를 호출한다. 명령 계약의 SSOT는 스킬
|
|
12
|
+
* `2t-decencia-channel-userflow-v2` §5이며, `ch screens` 선례를 그대로 따른다.
|
|
13
|
+
*
|
|
14
|
+
* 지키는 계약 두 가지:
|
|
15
|
+
* - 출력(PLAT-003): `--json`(기계 모드)이면 stdout은 순수 JSON 문서 하나뿐이고
|
|
16
|
+
* 사람용 메시지는 stderr로 나간다. 빈 목록도 stdout에는 `[]`로 나간다.
|
|
17
|
+
* - 종료코드: HTTP 4xx/5xx는 client의 응답 인터셉터가 exitCode를 세우지만, 서버에
|
|
18
|
+
* 닿기 전 로컬 입력 오류(파일 없음·--order 비숫자·수정 필드 0개)는 아무도
|
|
19
|
+
* 세워주지 않는다. 그래서 공용 failInput()(output.ts)으로 직접 exitCode=1을 세운다.
|
|
20
|
+
*
|
|
21
|
+
* Mermaid 문법은 CLI도 서버도 검증하지 않는다 — 문자열로 실어 보낼 뿐이다
|
|
22
|
+
* (렌더러 버전마다 유효 문법이 갈려서, 파서를 들고 있으면 그 버전이 곧 저장 가능한
|
|
23
|
+
* 문법의 상한이 된다). 렌더 실패는 웹 뷰어가 안내한다.
|
|
24
|
+
*/
|
|
25
|
+
/** create/update의 help 하단에 붙는 --file 안내. */
|
|
26
|
+
const FILE_HELP = `
|
|
27
|
+
--file <경로> — Mermaid 코드 파일 (.mmd):
|
|
28
|
+
ch userflows create --name "로그인·계정 복구" --file ./login-flow.mmd
|
|
29
|
+
cat login-flow.mmd | ch userflows create --name "로그인·계정 복구" --file -
|
|
30
|
+
|
|
31
|
+
BOM·CRLF는 자동 정제되어 LF로 전송된다 (PowerShell Out-File 호환).
|
|
32
|
+
"-"를 주면 stdin에서 읽는다. 플래그 없이 stdin을 넘겨다보지는 않는다 —
|
|
33
|
+
에이전트·CI 셸에서 fd0가 '열린 채 EOF가 오지 않는 파이프'인 경우가 흔해서,
|
|
34
|
+
암묵적 stdin 읽기는 "ch userflows update <id> --order 3" 같은 평범한 호출을
|
|
35
|
+
무한 대기시킨다.
|
|
36
|
+
|
|
37
|
+
수정은 Read-before-Write:
|
|
38
|
+
Mermaid는 통째 교체다(부분 병합 없음). 고칠 때는 먼저
|
|
39
|
+
'ch userflows get <flowId> --json'으로 현재 코드를 받아 편집한 뒤 전체를 넘긴다.
|
|
40
|
+
`;
|
|
41
|
+
/**
|
|
42
|
+
* `--order` 값을 숫자로 파싱한다. 문자열을 그대로 서버에 실어 보내면 400으로
|
|
43
|
+
* 되돌아오므로 요청 전에 CLI가 거른다 (screens의 parseScreenOrder 선례).
|
|
44
|
+
*
|
|
45
|
+
* screens에서 import하지 않고 여기 둔다 — 커맨드 모듈끼리 헬퍼를 주고받으면
|
|
46
|
+
* 리소스 하나의 규칙 변경이 다른 리소스로 새어 나간다.
|
|
47
|
+
*/
|
|
48
|
+
function parseUserflowOrder(value, label = '--order') {
|
|
49
|
+
const trimmed = String(value).trim();
|
|
50
|
+
const n = Number(trimmed);
|
|
51
|
+
if (trimmed === '' || !Number.isFinite(n)) {
|
|
52
|
+
throw new Error(`${label}: 숫자를 지정하세요 (예: 3). 받은 값: "${value}"`);
|
|
53
|
+
}
|
|
54
|
+
return n;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Mermaid 코드를 해석한다. `--file -`이면 stdin, 그 외에는 파일에서 읽는다.
|
|
58
|
+
* 어느 경로든 BOM 제거 + CRLF→LF 정규화(readContentFile/readContentStdin).
|
|
59
|
+
*
|
|
60
|
+
* 인라인 플래그(`--mermaid "<코드>"`)는 두지 않는다. 플로우차트는 여러 줄이라
|
|
61
|
+
* 셸 인용부호를 타고 넘어오다 줄바꿈이 뭉개진다 — 파일이 정본이다.
|
|
62
|
+
*/
|
|
63
|
+
function resolveMermaid(file) {
|
|
64
|
+
if (file === '-') {
|
|
65
|
+
const piped = (0, utils_1.readContentStdin)();
|
|
66
|
+
if (piped === null) {
|
|
67
|
+
throw new Error('--file -: stdin에서 읽을 내용이 없습니다. Mermaid 코드를 파이프로 넘기거나 --file <경로>를 쓰세요.');
|
|
68
|
+
}
|
|
69
|
+
return requireNonEmptyMermaid(piped, '--file -');
|
|
70
|
+
}
|
|
71
|
+
return requireNonEmptyMermaid((0, utils_1.readContentFile)(file, '--file'), '--file');
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* 빈 Mermaid를 요청 전에 거른다. 서버도 400으로 막지만(CreateUserflowDto), 여기서
|
|
75
|
+
* 걸러야 "저장됐겠거니" 하고 넘어가지 않는다. PowerShell `Out-File`이 개행만 흘려
|
|
76
|
+
* 넣은 .mmd가 실제로 이 모양이라 흔하다.
|
|
77
|
+
*/
|
|
78
|
+
function requireNonEmptyMermaid(mermaid, label) {
|
|
79
|
+
if (mermaid.trim() === '') {
|
|
80
|
+
throw new Error(`${label}: Mermaid 코드가 비어 있습니다.`);
|
|
81
|
+
}
|
|
82
|
+
return mermaid;
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* 플래그를 요청 바디로 변환한다. 지정된 플래그만 담으므로 update에서 그대로 PATCH
|
|
86
|
+
* 바디가 되고, 미지정 필드는 서버가 보존한다.
|
|
87
|
+
*
|
|
88
|
+
* 입력 오류(파일 없음·본문 비었음·--order 비숫자)는 throw한다 — 호출부가
|
|
89
|
+
* failInput으로 받아 종료코드를 세운다.
|
|
90
|
+
*/
|
|
91
|
+
function buildUserflowBody(options) {
|
|
92
|
+
const body = {};
|
|
93
|
+
if (options.name !== undefined)
|
|
94
|
+
body.name = options.name;
|
|
95
|
+
// 빈 문자열 판정은 `!== undefined`로 한다. falsy 체크를 쓰면 `--description ""`
|
|
96
|
+
// (설명 지우기)가 무시된다.
|
|
97
|
+
if (options.description !== undefined)
|
|
98
|
+
body.description = options.description;
|
|
99
|
+
if (options.file !== undefined)
|
|
100
|
+
body.mermaid = resolveMermaid(options.file);
|
|
101
|
+
if (options.order !== undefined) {
|
|
102
|
+
body.order = parseUserflowOrder(options.order, '--order');
|
|
103
|
+
}
|
|
104
|
+
return body;
|
|
105
|
+
}
|
|
106
|
+
/** 기계 모드(=stdout이 순수 JSON이어야 하는 모드)인지. */
|
|
107
|
+
function isMachineOutput(globalOpts) {
|
|
108
|
+
return !!(globalOpts.json || globalOpts.csv || globalOpts.quiet);
|
|
109
|
+
}
|
|
110
|
+
// ── 서브커맨드 ────────────────────────────────────────────────────────────
|
|
111
|
+
function registerUserflowsList(userflows, program) {
|
|
112
|
+
userflows
|
|
113
|
+
.command('list')
|
|
114
|
+
.description('유저플로우 목록 조회 (order 오름차순, order 없는 플로우는 뒤)')
|
|
115
|
+
.action(async () => {
|
|
116
|
+
const globalOpts = program.opts();
|
|
117
|
+
try {
|
|
118
|
+
const client = (0, client_1.createClient)({ projectId: globalOpts.project });
|
|
119
|
+
const { data } = await client.get('/userflows');
|
|
120
|
+
const items = Array.isArray(data) ? data : data?.data ?? [];
|
|
121
|
+
// 기계 모드 분기를 빈값 안내(printInfo)보다 앞에 둔다. 빈 결과도 stdout에
|
|
122
|
+
// `[]`로 나가야 하고, 사람용 안내문이 stdout(JSON)을 오염시키면 안 된다
|
|
123
|
+
// (PLAT-003, 이슈 #50 — db-tables에서 겪은 회귀).
|
|
124
|
+
if (isMachineOutput(globalOpts)) {
|
|
125
|
+
(0, output_1.formatOutput)(items, globalOpts);
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
128
|
+
if (!items.length) {
|
|
129
|
+
(0, output_1.printInfo)('등록된 유저플로우가 없습니다.');
|
|
130
|
+
return;
|
|
131
|
+
}
|
|
132
|
+
// 표는 스킬 §5대로 order | id | name 세 컬럼이다. Mermaid 본문은 목록에
|
|
133
|
+
// 싣지 않는다 — 한 장이 수십 줄이라 표가 읽히지 않는다(get으로 본다).
|
|
134
|
+
(0, output_1.printTable)(['order', 'id', 'name'], items.map((f) => [
|
|
135
|
+
f?.order === undefined || f?.order === null ? '' : String(f.order),
|
|
136
|
+
String(f?.id ?? ''),
|
|
137
|
+
String(f?.name ?? ''),
|
|
138
|
+
]));
|
|
139
|
+
}
|
|
140
|
+
catch (error) {
|
|
141
|
+
// 오류 출력·종료코드는 client 인터셉터가 처리했다.
|
|
142
|
+
}
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
function registerUserflowsGet(userflows, program) {
|
|
146
|
+
// 로컬 --json은 두지 않는다. commander가 부모(program)의 전역 옵션을 서브커맨드
|
|
147
|
+
// 뒤에서도 해석하므로 `ch userflows get <id> --json`이 그대로 동작한다.
|
|
148
|
+
userflows
|
|
149
|
+
.command('get <flowId>')
|
|
150
|
+
.description('유저플로우 상세 조회 (Mermaid 코드 포함 — 수정 전 Read-before-Write)')
|
|
151
|
+
.action(async (flowId) => {
|
|
152
|
+
const globalOpts = program.opts();
|
|
153
|
+
try {
|
|
154
|
+
const client = (0, client_1.createClient)({ projectId: globalOpts.project });
|
|
155
|
+
const { data } = await client.get(`/userflows/${flowId}`);
|
|
156
|
+
(0, output_1.formatOutput)(data, globalOpts);
|
|
157
|
+
}
|
|
158
|
+
catch (error) {
|
|
159
|
+
// Error already handled
|
|
160
|
+
}
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
function registerUserflowsCreate(userflows, program) {
|
|
164
|
+
userflows
|
|
165
|
+
.command('create')
|
|
166
|
+
.description('유저플로우 생성 (한 장 = 한 여정)')
|
|
167
|
+
.requiredOption('--name <name>', '여정 이름 (필수)')
|
|
168
|
+
// --file을 requiredOption으로 둔다. mermaid는 서버 필수 필드라 없으면 400인데,
|
|
169
|
+
// 왕복 한 번 없이 여기서 걸러야 종료코드 계약("로컬 입력 오류는 요청 없이 exit≠0")이 선다.
|
|
170
|
+
.requiredOption('--file <path>', 'Mermaid 코드 파일 (.mmd, "-"이면 stdin) (필수)')
|
|
171
|
+
.option('--description <text>', '한 줄 설명 (이 여정이 무엇을 보여주는지)')
|
|
172
|
+
.option('--order <n>', '목록 정렬 순서 (숫자)')
|
|
173
|
+
.addHelpText('after', FILE_HELP)
|
|
174
|
+
.action(async (options) => {
|
|
175
|
+
const globalOpts = program.opts();
|
|
176
|
+
try {
|
|
177
|
+
// 파일을 먼저 읽고 dry-run을 판정한다 — 깨진 파일이 --dry-run에서 통과하면
|
|
178
|
+
// 정작 실행할 때 실패한다 (sqa add-scenario와 같은 순서).
|
|
179
|
+
let body;
|
|
180
|
+
try {
|
|
181
|
+
body = buildUserflowBody(options);
|
|
182
|
+
}
|
|
183
|
+
catch (e) {
|
|
184
|
+
(0, output_1.failInput)(e?.message ?? String(e));
|
|
185
|
+
return;
|
|
186
|
+
}
|
|
187
|
+
if (globalOpts.dryRun) {
|
|
188
|
+
(0, output_1.printInfo)(`[DRY-RUN] 유저플로우 "${options.name}" 생성 요청`);
|
|
189
|
+
return;
|
|
190
|
+
}
|
|
191
|
+
const client = (0, client_1.createClient)({ projectId: globalOpts.project });
|
|
192
|
+
const { data } = await client.post('/userflows', body);
|
|
193
|
+
(0, output_1.formatOutput)(data, globalOpts);
|
|
194
|
+
(0, output_1.printSuccess)('유저플로우가 생성되었습니다.');
|
|
195
|
+
}
|
|
196
|
+
catch (error) {
|
|
197
|
+
// Error already handled
|
|
198
|
+
}
|
|
199
|
+
});
|
|
200
|
+
}
|
|
201
|
+
function registerUserflowsUpdate(userflows, program) {
|
|
202
|
+
userflows
|
|
203
|
+
.command('update <flowId>')
|
|
204
|
+
.description('유저플로우 부분 업데이트 (지정한 플래그만 변경)')
|
|
205
|
+
.option('--name <name>', '여정 이름')
|
|
206
|
+
.option('--file <path>', 'Mermaid 코드 파일 (.mmd, "-"이면 stdin) — 통째 교체')
|
|
207
|
+
.option('--description <text>', '한 줄 설명 ("" 이면 지움)')
|
|
208
|
+
.option('--order <n>', '목록 정렬 순서 (숫자)')
|
|
209
|
+
.addHelpText('after', FILE_HELP)
|
|
210
|
+
.action(async (flowId, options) => {
|
|
211
|
+
const globalOpts = program.opts();
|
|
212
|
+
try {
|
|
213
|
+
// 파일 읽기·입력 검증을 dry-run 판정보다 먼저 — create와 같은 이유.
|
|
214
|
+
let body;
|
|
215
|
+
try {
|
|
216
|
+
body = buildUserflowBody(options);
|
|
217
|
+
}
|
|
218
|
+
catch (e) {
|
|
219
|
+
(0, output_1.failInput)(e?.message ?? String(e));
|
|
220
|
+
return;
|
|
221
|
+
}
|
|
222
|
+
if (Object.keys(body).length === 0) {
|
|
223
|
+
(0, output_1.failInput)('수정할 필드를 지정하세요.');
|
|
224
|
+
return;
|
|
225
|
+
}
|
|
226
|
+
if (globalOpts.dryRun) {
|
|
227
|
+
(0, output_1.printInfo)(`[DRY-RUN] 유저플로우 "${flowId}" 수정 요청`);
|
|
228
|
+
return;
|
|
229
|
+
}
|
|
230
|
+
const client = (0, client_1.createClient)({ projectId: globalOpts.project });
|
|
231
|
+
const { data } = await client.patch(`/userflows/${flowId}`, body);
|
|
232
|
+
(0, output_1.formatOutput)(data, globalOpts);
|
|
233
|
+
(0, output_1.printSuccess)('유저플로우가 수정되었습니다.');
|
|
234
|
+
}
|
|
235
|
+
catch (error) {
|
|
236
|
+
// Error already handled
|
|
237
|
+
}
|
|
238
|
+
});
|
|
239
|
+
}
|
|
240
|
+
function registerUserflowsDelete(userflows, program) {
|
|
241
|
+
userflows
|
|
242
|
+
.command('delete <flowId>')
|
|
243
|
+
.description('유저플로우 삭제')
|
|
244
|
+
.action(async (flowId) => {
|
|
245
|
+
const globalOpts = program.opts();
|
|
246
|
+
try {
|
|
247
|
+
if (globalOpts.dryRun) {
|
|
248
|
+
(0, output_1.printInfo)(`[DRY-RUN] 유저플로우 "${flowId}" 삭제 요청`);
|
|
249
|
+
return;
|
|
250
|
+
}
|
|
251
|
+
const client = (0, client_1.createClient)({ projectId: globalOpts.project });
|
|
252
|
+
const { data } = await client.delete(`/userflows/${flowId}`);
|
|
253
|
+
// 기계 모드에서는 서버 응답을 stdout에 순수 JSON으로 남겨 JSON.parse가 되게 한다.
|
|
254
|
+
// 사람용(표) 모드에서는 성공 한 줄이면 충분하다.
|
|
255
|
+
if (isMachineOutput(globalOpts)) {
|
|
256
|
+
(0, output_1.formatOutput)(data, globalOpts);
|
|
257
|
+
}
|
|
258
|
+
(0, output_1.printSuccess)('유저플로우가 삭제되었습니다.');
|
|
259
|
+
}
|
|
260
|
+
catch (error) {
|
|
261
|
+
// Error already handled
|
|
262
|
+
}
|
|
263
|
+
});
|
|
264
|
+
}
|
|
265
|
+
function registerUserflowsCommand(program) {
|
|
266
|
+
const userflows = program
|
|
267
|
+
.command('userflows')
|
|
268
|
+
.description('유저플로우 관리 — 분기 있는 사용자 여정의 Mermaid 문서 (/userflows)');
|
|
269
|
+
registerUserflowsList(userflows, program);
|
|
270
|
+
registerUserflowsGet(userflows, program);
|
|
271
|
+
registerUserflowsCreate(userflows, program);
|
|
272
|
+
registerUserflowsUpdate(userflows, program);
|
|
273
|
+
registerUserflowsDelete(userflows, program);
|
|
274
|
+
}
|
|
275
|
+
//# sourceMappingURL=userflows.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"userflows.js","sourceRoot":"","sources":["../../src/commands/userflows.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -53,6 +53,8 @@ const prd_1 = require("./commands/prd");
|
|
|
53
53
|
const db_schema_1 = require("./commands/db-schema");
|
|
54
54
|
const db_tables_1 = require("./commands/db-tables");
|
|
55
55
|
const screens_1 = require("./commands/screens");
|
|
56
|
+
const userflows_1 = require("./commands/userflows");
|
|
57
|
+
const policies_1 = require("./commands/policies");
|
|
56
58
|
const backup_1 = require("./commands/backup");
|
|
57
59
|
const handoff_1 = require("./commands/handoff");
|
|
58
60
|
const notifications_1 = require("./commands/notifications");
|
|
@@ -112,6 +114,8 @@ program.hook('preAction', (thisCommand) => {
|
|
|
112
114
|
(0, db_schema_1.registerDbSchemaCommand)(program);
|
|
113
115
|
(0, db_tables_1.registerDbTablesCommand)(program);
|
|
114
116
|
(0, screens_1.registerScreensCommand)(program);
|
|
117
|
+
(0, userflows_1.registerUserflowsCommand)(program);
|
|
118
|
+
(0, policies_1.registerPoliciesCommand)(program);
|
|
115
119
|
(0, backup_1.registerBackupCommand)(program);
|
|
116
120
|
(0, handoff_1.registerHandoffCommand)(program);
|
|
117
121
|
(0, notifications_1.registerNotificationsCommand)(program);
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
name: 2t-decencia-channel-change-manager
|
|
3
3
|
description: 기존 소통채널 프로젝트의 기능 추가/수정을 사용자와 대화로 명확화 → 전파 스킬로 연관 PRD/spec/DB/SQA 일괄 갱신 → 변경으로 생긴 새 할일을 GitHub 이슈로 발행하는 오케스트레이터 스킬. (1)대화로 변경 내용 확정 → (2)[게이트] 영향 범위 확인 후 전파 적용 → (3)[게이트] 할일 목록 확인 후 이슈 발행. "이 기능 바꿀래"·"기획 수정"·"이거 추가해줘(기존 프로젝트)" 류 요청 시.
|
|
4
4
|
allowed-tools: Bash(ch:*) Bash(git:*) Bash(gh:*) Read Write
|
|
5
|
-
version: 1.
|
|
5
|
+
version: 1.31.0
|
|
6
6
|
---
|
|
7
7
|
|
|
8
8
|
<!-- ch-version-gate -->
|
|
@@ -10,7 +10,7 @@ description: |
|
|
|
10
10
|
(3) 명세·DB·SQA가 서로 어긋나 있는 의심이 들 때 (정합성 점검),
|
|
11
11
|
(4) PRD 갱신 후 하위 spec/db/SQA로 변경분을 흘려보내야 할 때,
|
|
12
12
|
(5) Sprint 진행 중 도메인 규칙·스키마가 흔들렸을 때 연쇄 갱신이 필요할 때.
|
|
13
|
-
version: 1.
|
|
13
|
+
version: 1.31.0
|
|
14
14
|
---
|
|
15
15
|
|
|
16
16
|
<!-- ch-version-gate -->
|
|
@@ -134,14 +134,18 @@ ch check
|
|
|
134
134
|
| D | **spec 의 비즈니스 규칙(logic)** 변경 | `spec.logic` | 의존 spec, SQA(정상/비정상 TC), db-tables(검증 규칙·trigger), PRD 도메인 규칙 절 |
|
|
135
135
|
| E | **권한/역할 정책** 변경 | 영향 spec.logic, db-tables.securityRules | 모든 영향 spec의 SQA(접근권한 TC), db-schema 보안 일관성 절, PRD 권한 절 |
|
|
136
136
|
| F | **Story Point(points) 변경** | `spec.points` | Sprint 용량 산정, workStatus |
|
|
137
|
-
| G | **Epic 명/범위 변경** | `spec.epic`, PRD
|
|
137
|
+
| G | **Epic 명/범위 변경** | `spec.epic`, PRD 기능 요구사항 카테고리 절 | 모든 같은 Epic 산하 spec 재태깅, Sprint 묶음 |
|
|
138
138
|
| H | **PRD 본문 변경** | `prd` | 그 PRD에서 파생된 spec, db-schema, SQA 시트 — **전수 리뷰 트리거** |
|
|
139
139
|
|
|
140
|
+
> **스토리 명세 프로젝트**(`storySpecsEnabled=true` — [[2t-decencia-channel-spec-v2]] §0)에서는 이렇게 읽는다:
|
|
141
|
+
> C(UI 변경) = 화면 연결(`ui.screenRefs`)·화면(screens) 변경. interactionMap 등 UI 상세는 없다.
|
|
142
|
+
> D(logic 변경) = 스토리문장(`story`)·사전 조건(`preconditions`)·로직 플로우(`dataFlowScenarios`)·비즈니스 규칙 변경. stateTransitions는 없다.
|
|
143
|
+
|
|
140
144
|
사용자 발화 → 진앙 매핑 예시:
|
|
141
145
|
- "users 테이블에 last_login_at 추가" → **A**
|
|
142
146
|
- "회원 등급에 VIP 추가, 권한도 더 줘야 함" → **E** (+ D)
|
|
143
147
|
- "로그인 화면에 SNS 로그인 버튼 추가" → **C** (+ E if 권한)
|
|
144
|
-
- "이 spec의 규모(Story Point)를 다시 매김" → **F** (규모가 너무 크면 spec 자체를 여러 Story로 분리 — [[2t-decencia-channel-spec-v2]] §
|
|
148
|
+
- "이 spec의 규모(Story Point)를 다시 매김" → **F** (규모가 너무 크면 spec 자체를 여러 Story로 분리 — [[2t-decencia-channel-spec-v2]] §2·§14)
|
|
145
149
|
|
|
146
150
|
---
|
|
147
151
|
|
|
@@ -153,7 +157,7 @@ ch check
|
|
|
153
157
|
|
|
154
158
|
```bash
|
|
155
159
|
# 모든 spec과 dbTableRefs/relatedSpecIds
|
|
156
|
-
ch specs list --json --per-page
|
|
160
|
+
ch specs list --json --per-page 100 > /tmp/specs.json
|
|
157
161
|
|
|
158
162
|
# 모든 db-table
|
|
159
163
|
ch db-tables list --json > /tmp/tables.json
|
|
@@ -313,7 +317,7 @@ ch prd get --json | jq -r '.content' | grep -niE "데이터 모델|컬럼|nullab
|
|
|
313
317
|
- **B (새 테이블)**: 1 → 2(인벤토리/ERD, 테이블 단위) → 3(dbTableRefs) → 4 → 6. **5(PRD) 스킵** (새 *기능*이면 그건 C/H로 별도)
|
|
314
318
|
- **C (UI만 변경)**: 1·2 스킵하고 3 → 4 → 5 → 6
|
|
315
319
|
- **E (권한)**: 1(securityRules) + 3(logic) 거의 동시 → 2 → 4 → 5(권한 *정책* 절 — 기능이므로 PRD 가능) → 6
|
|
316
|
-
- **G (Epic 변경)**: 3(spec.epic 재태깅) → 5(PRD
|
|
320
|
+
- **G (Epic 변경)**: 3(spec.epic 재태깅) → 5(PRD 기능 요구사항 카테고리) → 6
|
|
317
321
|
- **H (PRD 변경)**: 5(PRD) → 영향 재조사 → 1~4 순차 → 6
|
|
318
322
|
|
|
319
323
|
---
|
|
@@ -378,7 +382,7 @@ ch specs update <specId> --work-status /tmp/ws.md --no-version
|
|
|
378
382
|
### 6.1 spec ↔ db-table 양방향 일치
|
|
379
383
|
|
|
380
384
|
```bash
|
|
381
|
-
ch specs list --json --per-page
|
|
385
|
+
ch specs list --json --per-page 100 | jq -r '.data[] | "spec\t" + .id + "\t" + ((.dbTableRefs // []) | join(","))' > /tmp/spec_refs.tsv
|
|
382
386
|
ch db-tables list --json | jq -r '.data[] | "table\t" + .id + "\t" + ((.relatedSpecIds // []) | join(","))' > /tmp/table_refs.tsv
|
|
383
387
|
|
|
384
388
|
# spec.dbTableRefs에는 있는데 table.relatedSpecIds에 누락된 경우 → 불일치
|
|
@@ -489,7 +493,7 @@ jq -r '.data[] | select((.logic // "" | tostring) | test("nullable|timestamp\\b|
|
|
|
489
493
|
3) ch specs update — 영향 spec.epic 일괄 재태깅
|
|
490
494
|
(스크립트: for s in $(jq -r ... ); do ch specs update $s --epic <new>; done)
|
|
491
495
|
4) (SQA는 대개 무영향. Epic 단위 필터링하는 사용처가 있다면 시트 분리 검토)
|
|
492
|
-
5) PRD
|
|
496
|
+
5) PRD 기능 요구사항 카테고리 절
|
|
493
497
|
6) Sprint — Epic 단위 묶음 사용 중이라면 sprint 재구성 검토
|
|
494
498
|
7) workStatus
|
|
495
499
|
```
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
name: 2t-decencia-channel-cli-v2
|
|
3
3
|
description: |
|
|
4
4
|
[2t][v2] 소통채널 CLI(`ch`, npm @decencia/ch-cli) 가이드.
|
|
5
|
-
Epic-Story 체계(규모=Story Point)와 db-tables·screens 리소스, --work-status, --id, --points
|
|
5
|
+
Epic-Story 체계(규모=Story Point)와 db-tables·screens 리소스, 스토리 명세 플래그(--story·--preconditions), --work-status, --id, --points 등을 망라한다.
|
|
6
6
|
Use when:
|
|
7
7
|
(1) spec/db-table/화면(screen)을 CLI로 다룰 때,
|
|
8
8
|
(2) spec 규모를 Story Point(`--points`)로 매길 때,
|
|
@@ -10,7 +10,7 @@ description: |
|
|
|
10
10
|
(4) ch screens 명령(list/get/create/update/delete/migrate)으로 화면을 다루거나 레거시 프로젝트를 화면 모드로 이관할 때,
|
|
11
11
|
(5) spec의 화면 연결을 CLI로 걸거나 풀 때 (`ch specs screen-refs`),
|
|
12
12
|
(6) Spec ID를 JIRA 스타일(`LOGIN-001`)로 직접 지정할 때 (`ch specs create --id`).
|
|
13
|
-
version: 1.
|
|
13
|
+
version: 1.31.0
|
|
14
14
|
---
|
|
15
15
|
|
|
16
16
|
<!-- ch-version-gate -->
|
|
@@ -42,32 +42,52 @@ ch specs update <specId> --logic /tmp/logic.json # 3) 수정 적용
|
|
|
42
42
|
|
|
43
43
|
## 1. spec 명령
|
|
44
44
|
|
|
45
|
+
프로젝트 모드에 따라 쓰는 플래그가 다르다 ([[2t-decencia-channel-spec-v2]] §0).
|
|
46
|
+
|
|
47
|
+
**스토리 명세 모드** (`storySpecsEnabled=true` — 신규 프로젝트 기본):
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
# 생성 (사용자 지정 Spec ID = Epic 도메인 코드 prefix 권장)
|
|
51
|
+
# ID 패턴: ^[A-Za-z][A-Za-z0-9_]*-[A-Za-z0-9]+$ (MaxLength 60), 충돌 시 409
|
|
52
|
+
ch specs create --id AUTH-001 \
|
|
53
|
+
--name "로그인" \
|
|
54
|
+
--device web,app --domain 회원 --permission 비회원 \
|
|
55
|
+
--epic AUTH \
|
|
56
|
+
--points 5 \
|
|
57
|
+
--story "회원은 이메일과 비밀번호로 로그인해서, 재인증 없이 자신의 프로젝트에 바로 접근하고 싶다." \
|
|
58
|
+
--preconditions ./preconditions.md \
|
|
59
|
+
--logic ./logic.json \
|
|
60
|
+
--db-tables tbl_users,tbl_sessions
|
|
61
|
+
|
|
62
|
+
# 수정: 지정한 플래그만 PATCH. --no-version 시 버전 기록 생략.
|
|
63
|
+
ch specs update <specId> --story "..." --no-version
|
|
64
|
+
ch specs update <specId> --preconditions ./preconditions.md --no-version
|
|
65
|
+
ch specs update <specId> --points 8 --no-version
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
- `--story "<줄글>"` — 스토리문장(As a/I want/So that). 스칼라라 그 값만 바뀐다.
|
|
69
|
+
- `--preconditions <텍스트|파일경로>` — 사전 조건 마크다운.
|
|
70
|
+
- `--domain`은 쉼표로 **복수** 지정 (`--domain 회원,관리자`).
|
|
71
|
+
- `--type`(기능유형)·`--content`는 스토리 명세 모드에서 쓰지 않는다 (레거시 전용).
|
|
72
|
+
- `--ui`는 화면 연결이 필요할 때 `{"screenRefs":[...]}`만 싣는다 (생성 시에만 — §1 화면 연결).
|
|
73
|
+
|
|
74
|
+
**레거시 모드** (`storySpecsEnabled` 미설정·false — 기존 프로젝트):
|
|
75
|
+
|
|
45
76
|
```bash
|
|
46
|
-
# 생성 (자동 ID)
|
|
47
77
|
ch specs create \
|
|
48
78
|
--name "로그인" \
|
|
49
79
|
--device web,app --domain user --type 인증 --permission 비회원 \
|
|
50
80
|
--content "이메일/비밀번호 로그인" \
|
|
51
|
-
--epic 인증 \
|
|
52
|
-
--
|
|
53
|
-
--ui ./ui.json \
|
|
54
|
-
--logic ./logic.json \
|
|
81
|
+
--epic 인증 --points 5 \
|
|
82
|
+
--ui ./ui.json --logic ./logic.json \
|
|
55
83
|
--db-tables tbl_users,tbl_sessions \
|
|
56
84
|
--work-status ./work-status.md
|
|
57
85
|
|
|
58
|
-
# 생성 (사용자 지정 Spec ID, JIRA 스타일 — ch-cli 1.3.5+ / ch-api b029f88+)
|
|
59
|
-
# 패턴: ^[A-Za-z][A-Za-z0-9_]*-[A-Za-z0-9]+$ (MaxLength 60)
|
|
60
|
-
# 충돌 시 409, 패턴 위반 시 400
|
|
61
|
-
ch specs create --id LOGIN-001 \
|
|
62
|
-
--name "로그인" --device web --domain user --type 인증 --epic 인증
|
|
63
|
-
|
|
64
|
-
# 수정: 지정한 플래그만 PATCH. --no-version 시 버전 기록 생략.
|
|
65
86
|
ch specs update <specId> --epic 인증 --no-version
|
|
66
|
-
ch specs update <specId> --points 8 --no-version
|
|
67
87
|
ch specs update <specId> --work-status ./status.md
|
|
68
88
|
```
|
|
69
89
|
|
|
70
|
-
> `--id`의 자세한 네이밍 규칙·예외·자동 다음 번호 산정 스크립트는 [[2t-decencia-channel-spec-v2]] §
|
|
90
|
+
> `--id`의 자세한 네이밍 규칙·예외·자동 다음 번호 산정 스크립트는 [[2t-decencia-channel-spec-v2]] §4 참조.
|
|
71
91
|
|
|
72
92
|
### Story Point (`--points`)
|
|
73
93
|
|
|
@@ -79,7 +99,7 @@ ch specs update <specId> --points 8 --no-version
|
|
|
79
99
|
```
|
|
80
100
|
|
|
81
101
|
- `--points <n>` — 0 이상의 숫자(보통 피보나치 1/2/3/5/8/13). 진행률(%)·완료율은 없다 — 완료 여부는 `status`로.
|
|
82
|
-
- Sprint 용량 = Σ spec.points ([[2t-decencia-channel-sprint-builder-v2]]). 규모 산정 가이드는 [[2t-decencia-channel-spec-v2]] §
|
|
102
|
+
- Sprint 용량 = Σ spec.points ([[2t-decencia-channel-sprint-builder-v2]]). 규모 산정 가이드는 [[2t-decencia-channel-spec-v2]] §11.
|
|
83
103
|
|
|
84
104
|
### Task JSON (`--tasks`) — [deprecated]
|
|
85
105
|
|
|
@@ -107,7 +127,13 @@ ch specs update <specId> --points 8 --no-version
|
|
|
107
127
|
|
|
108
128
|
### UI JSON (`--ui`)
|
|
109
129
|
|
|
110
|
-
|
|
130
|
+
**스토리 명세 모드** (`storySpecsEnabled=true`) — `screenRefs`만 쓴다. interactionMap·primaryActions·keyInformation은 스토리 명세에 없다.
|
|
131
|
+
|
|
132
|
+
```json
|
|
133
|
+
{ "screenRefs": ["SCR-LOGIN"] }
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
**레거시 + 화면 모드** (`screensEnabled=true`) — spec.ui 소유 4필드만 쓴다.
|
|
111
137
|
|
|
112
138
|
```json
|
|
113
139
|
{
|
|
@@ -161,7 +187,8 @@ ch specs update <specId> --points 8 --no-version
|
|
|
161
187
|
```
|
|
162
188
|
|
|
163
189
|
- `dataFlowScenarios[]`=시나리오, 각 시나리오의 `steps[]`=순서 있는 단계, 각 단계의 `refs[]`=**db-tables의 tableId(+선택 field)를 가리키는 구조적 참조**(SSOT — 스키마 정의는 db-tables에만). 서버가 실존 검증: 없는 tableId/컬럼이면 400. `direction`은 `READ|WRITE|READWRITE`.
|
|
164
|
-
-
|
|
190
|
+
- `stateTransitions`(화면 상태 전이)는 **레거시 전용**이다. 스토리 명세 모드에서는 쓰지 않는다. 스토리 명세의 흐름은 로직 플로우 하나다(정상/예외 구분 없음 — 실패 경로는 분기로) — [[2t-decencia-channel-spec-v2]] §7.
|
|
191
|
+
- 단계 `description`은 필드명 나열이 아니라 **완결 문장**으로 — [[2t-decencia-channel-spec-v2]] §7.
|
|
165
192
|
- 하위호환: 레거시 `dataFlow`(문자열)/`dataFlowRefs[]`/`businessRuleRefs[]`도 그대로 수용된다(점진 마이그레이션). SQA 항목도 동일 취지로 `--db-tables`(쉼표 구분)를 가진다 — [[2t-decencia-channel-sqa-v2]].
|
|
166
193
|
|
|
167
194
|
### dbTableRefs (`--db-tables`)
|
|
@@ -248,6 +275,7 @@ ch db-tables delete <tableId> # 참조 spec의 dbTableRefs도
|
|
|
248
275
|
## 3. screens 명령 (화면)
|
|
249
276
|
|
|
250
277
|
화면(Screen)은 화면 정의의 SSOT다. `ch_projects.screensEnabled=true`인 프로젝트에서 쓴다.
|
|
278
|
+
**무엇을 적어야 하는지**(필수 기재항목 6종·디스크립션 작성규칙·예외상태 4종)는 [[2t-decencia-channel-screen-v2]]가 정본이다.
|
|
251
279
|
|
|
252
280
|
```bash
|
|
253
281
|
ch screens list # 표 출력: order | id | name | route | epic | states | specs
|
|
@@ -281,7 +309,7 @@ ch screens migrate --rollback # 화면 모드만 끄기 (화
|
|
|
281
309
|
ch screens migrate --rollback --force # 되돌아갈 route가 없어도 강행 (기본은 서버가 409로 거절)
|
|
282
310
|
```
|
|
283
311
|
|
|
284
|
-
- `--id`는
|
|
312
|
+
- `--id`는 슬러그 스타일(`SCR-001`, `STORE-ORDER-DETAIL` 같은 다중 세그먼트 허용). 패턴 `^[A-Za-z][A-Za-z0-9_]*(-[A-Za-z0-9_]+)+$`, 중복 시 409. (spec ID 패턴과 다르다 — 화면만 완화됐다.)
|
|
285
313
|
- 화면 소유 필드다. spec.ui가 아니라 여기에 적는다.
|
|
286
314
|
- `--figma-node-id <id>` — 이 화면의 Figma 노드 ID(`123:456`). Figma URL의 `?node-id=` 값에서 `-`를 `:`로 바꾼 값이다.
|
|
287
315
|
- `--page-file <path>` — 이 화면의 **페이지 진입 파일** 경로 하나(예: `src/app/store/[code]/page.tsx`). 하위 컴포넌트는 적지 않는다.
|
|
@@ -8,7 +8,7 @@ description: |
|
|
|
8
8
|
(2) DB 테이블 단위로 컬럼·인덱스·보안규칙을 등록·수정할 때,
|
|
9
9
|
(3) 새 테이블을 추가하면서 전체 인벤토리도 함께 업데이트할 때,
|
|
10
10
|
(4) spec.dbTableRefs와 양방향 동기화가 필요한 작업 시.
|
|
11
|
-
version: 1.
|
|
11
|
+
version: 1.31.0
|
|
12
12
|
---
|
|
13
13
|
|
|
14
14
|
<!-- ch-version-gate -->
|
|
@@ -277,7 +277,7 @@ description 활용 권장:
|
|
|
277
277
|
|
|
278
278
|
### 5-4. state-machines.json — 엔티티 상태머신
|
|
279
279
|
|
|
280
|
-
엔티티가 **저장되는 상태 컬럼**을 가지면(주문 `status`, 배포 `phase` 등) 그 생애주기를 여기에 정의한다. 화면의 휘발성 UI 전이(idle/loading 등)는 여기
|
|
280
|
+
엔티티가 **저장되는 상태 컬럼**을 가지면(주문 `status`, 배포 `phase` 등) 그 생애주기를 여기에 정의한다. 화면의 휘발성 UI 전이(idle/loading 등)는 여기 적지 않는다 — 화면(screens)의 `states`에, 레거시 프로젝트는 spec.logic.stateTransitions에 적는다([[2t-decencia-channel-spec-v2]] §L-3).
|
|
281
281
|
|
|
282
282
|
`StateMachine[]` — 한 테이블에 상태머신 여러 개 가능(컬럼별).
|
|
283
283
|
|
|
@@ -327,7 +327,7 @@ description 활용 권장:
|
|
|
327
327
|
|
|
328
328
|
#### spec dataFlow와의 상호참조 (`columnRef` ↔ `toState`)
|
|
329
329
|
|
|
330
|
-
spec은 이 상태머신을 **`columnRef`로 잇는다**. spec의 dataFlow ref에서 `field`가 이 머신의 `columnRef`와 같으면, 그 ref는 이 엔티티의 상태 접근이다. 그 ref가 WRITE면 `toState`에 목표 상태(이 머신 `states[].value` 중 하나)를 적는다 — [[2t-decencia-channel-spec-v2]] §
|
|
330
|
+
spec은 이 상태머신을 **`columnRef`로 잇는다**. spec의 dataFlow ref에서 `field`가 이 머신의 `columnRef`와 같으면, 그 ref는 이 엔티티의 상태 접근이다. 그 ref가 WRITE면 `toState`에 목표 상태(이 머신 `states[].value` 중 하나)를 적는다 — [[2t-decencia-channel-spec-v2]] §10-2.
|
|
331
331
|
|
|
332
332
|
- **링크 방향**: db-tables가 상태를 **정의**(states·transitions)하고, spec은 `tableId` + `field`(=columnRef) + `toState`로 **참조**만 한다.
|
|
333
333
|
- `ch specs get`은 이 머신 요약(states·transitions)을 spec ref 옆에 **읽기 시점에 인라인**해 준다. 그래서 상태 목록을 spec에 베낄 필요가 없다.
|
|
@@ -372,7 +372,7 @@ spec은 이 상태머신을 **`columnRef`로 잇는다**. spec의 dataFlow ref
|
|
|
372
372
|
## 8. 흔한 함정
|
|
373
373
|
|
|
374
374
|
- columns/indexes/securityRules/stateMachines JSON은 **전체 교체**. 일부 수정 시 반드시 `get` 후 편집.
|
|
375
|
-
- 상태 컬럼의 생애주기(주문 status 등)를 spec
|
|
375
|
+
- 상태 컬럼의 생애주기(주문 status 등)를 spec 쪽(흐름·레거시 stateTransitions)에 정의하면 SSOT 위반 — 저장되는 엔티티 상태는 db-tables.stateMachines가 SSOT. spec의 흐름은 `toState` 링크로 참조만 한다.
|
|
376
376
|
- 전체 스펙 문서의 `--content`도 통째 교체. 작은 수정도 `get` 후 부분 편집해 통째 전송.
|
|
377
377
|
- `relatedSpecIds`를 JSON에 명시해도 서버가 무시 (자동 관리 영역).
|
|
378
378
|
- 새 테이블을 만들고 전체 스펙 인벤토리 갱신을 잊으면, 문서 읽는 사람이 그 테이블의 존재를 모른다.
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
name: 2t-decencia-channel-github-issue
|
|
3
3
|
description: gh CLI로 현재 repo에 GitHub 이슈를 작성한다. 이슈 1개=유형 1개(feat/fix/bug), 표준 본문 양식(작업내용·관련 명세 백링크·완료조건)으로 발행. "이슈 만들어줘"/"깃헙 이슈로 등록해줘" 요청 시, 또는 소통채널 기획·명세 작업 후 처리할 일들을 GitHub 이슈로 옮길 때 사용. 멱등성/중복방지·확인단계는 다루지 않음(요청대로 바로 생성).
|
|
4
4
|
allowed-tools: Bash(gh:*) Bash(git:*) Read Write
|
|
5
|
-
version: 1.
|
|
5
|
+
version: 1.31.0
|
|
6
6
|
---
|
|
7
7
|
|
|
8
8
|
<!-- ch-version-gate -->
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
name: 2t-decencia-channel-orchestrator
|
|
3
3
|
description: 소통채널 작업의 단일 진입점(디스패처). 사용자 요청을 듣고 7종(bootstrap·terraformer·change-manager·github-issue·issue-coder·pr-merger·sprint-runner) 중 적절한 곳으로 라우팅하고, 필요하면 여러 단계를 순차 오케스트레이션한다. 대화형 스킬은 메인 세션에서 Skill로, 자율 에이전트는 Agent로 위임. "소통채널 작업 해줘"·"이거 어떻게 처리하지?"처럼 무엇부터 할지 모를 때, 또는 신규기획/코드편입/기획변경/이슈/구현/머지/스프린트실행 어디로든 시작할 때.
|
|
4
4
|
allowed-tools: Skill Agent Read Bash(ch:*) Bash(gh:*) Bash(git:*)
|
|
5
|
-
version: 1.
|
|
5
|
+
version: 1.31.0
|
|
6
6
|
---
|
|
7
7
|
|
|
8
8
|
<!-- ch-version-gate -->
|