@decencia/ch-cli 1.11.3 → 1.12.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/screens.d.ts +8 -0
- package/dist/commands/screens.d.ts.map +1 -0
- package/dist/commands/screens.js +333 -0
- package/dist/commands/screens.js.map +1 -0
- package/dist/index.js +2 -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 +1 -1
- package/skill/2t-decencia-channel-cli-v2/SKILL.md +60 -6
- package/skill/2t-decencia-channel-db-schema-v2/SKILL.md +1 -1
- 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-prd-v2/SKILL.md +1 -1
- package/skill/2t-decencia-channel-project-bootstrap/SKILL.md +1 -1
- package/skill/2t-decencia-channel-spec-v2/SKILL.md +1 -1
- package/skill/2t-decencia-channel-sprint-builder-v2/SKILL.md +1 -1
- package/skill/2t-decencia-channel-sprint-runner/SKILL.md +1 -1
- package/skill/2t-decencia-channel-sqa-v2/SKILL.md +1 -1
- package/skill/2t-decencia-channel-work-status-v2/SKILL.md +1 -1
|
@@ -3,7 +3,7 @@ name: 2t-decencia-channel-issue-coder
|
|
|
3
3
|
description: GitHub issue 1개를 입력으로 받아 끝까지 처리하는 코딩 에이전트. 이슈 읽기 → 소통채널 spec/SQA 확인 → git worktree+브랜치에서 구현 → 자체 소프트리뷰 루프 → unittest + SQA → PR 생성 → 소통채널 workStatus·이슈 기록. 다수 병렬 실행 전제, PR까지만(머지·base 브랜치 직접 push·이슈 close는 사람).
|
|
4
4
|
tools: Read, Write, Edit, Grep, Glob, Bash, Agent
|
|
5
5
|
model: opus
|
|
6
|
-
version: 1.
|
|
6
|
+
version: 1.12.0
|
|
7
7
|
---
|
|
8
8
|
|
|
9
9
|
## 역할
|
|
@@ -3,7 +3,7 @@ name: 2t-decencia-channel-pr-merger
|
|
|
3
3
|
description: issue-coder가 낸 PR을 기본 완전 자율로 base 브랜치(기본 브랜치 또는 sprint 통합 브랜치)에 머지하는 에이전트. 핵심 역량은 다수 병렬 worktree가 만든 충돌을 작업 의도 기반(semantic)으로 해결하는 것. CI green+충돌없음이면 바로 squash 머지, 충돌이면 의도대로 해결 후 테스트로 검증하여 머지. 재SQA·전면 재리뷰는 하지 않음. 다수 PR은 직렬 머지.
|
|
4
4
|
tools: Read, Write, Edit, Grep, Glob, Bash
|
|
5
5
|
model: opus
|
|
6
|
-
version: 1.
|
|
6
|
+
version: 1.12.0
|
|
7
7
|
---
|
|
8
8
|
|
|
9
9
|
## 역할
|
|
@@ -3,7 +3,7 @@ name: 2t-decencia-channel-terraformer
|
|
|
3
3
|
description: 소통채널을 쓰지 않던 기존 코드베이스를 역분석하여 소통채널 프로젝트로 편입(terraforming)하는 자율 에이전트. 코드가 single source of truth — 코드를 읽어 DB 스키마 → 기능명세(spec) → PRD를 bottom-up으로 역생성한다(SQA 제외). 대량 분석은 서브에이전트 병렬, 코드로 못 메우는 의도는 [추정]으로 채우고 "사람확인 질문 리스트"를 산출물로 남긴다. PR/머지·이슈 발행은 하지 않음.
|
|
4
4
|
tools: Read, Write, Edit, Grep, Glob, Bash, Agent
|
|
5
5
|
model: opus
|
|
6
|
-
version: 1.
|
|
6
|
+
version: 1.12.0
|
|
7
7
|
---
|
|
8
8
|
|
|
9
9
|
## 역할
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { Command } from 'commander';
|
|
2
|
+
/**
|
|
3
|
+
* `--order` 값을 숫자로 파싱한다. 문자열을 그대로 서버에 실어 보내면 400으로
|
|
4
|
+
* 되돌아오므로 요청 전에 CLI가 거른다 (`--points`의 parsePoints 선례).
|
|
5
|
+
*/
|
|
6
|
+
export declare function parseScreenOrder(value: string, label?: string): number;
|
|
7
|
+
export declare function registerScreensCommand(program: Command): void;
|
|
8
|
+
//# sourceMappingURL=screens.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"screens.d.ts","sourceRoot":"","sources":["../../src/commands/screens.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAqEpC;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,SAAY,GAAG,MAAM,CAOzE;AA0QD,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAY7D"}
|
|
@@ -0,0 +1,333 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.parseScreenOrder = parseScreenOrder;
|
|
4
|
+
exports.registerScreensCommand = registerScreensCommand;
|
|
5
|
+
const client_1 = require("../client");
|
|
6
|
+
const output_1 = require("../output");
|
|
7
|
+
const utils_1 = require("../utils");
|
|
8
|
+
/**
|
|
9
|
+
* ch screens — 화면(Screen) 리소스 관리 명령 (SCREEN-003)
|
|
10
|
+
*
|
|
11
|
+
* ch-api의 /screens REST(SCREEN-001)를 호출한다. `ch db-tables` 선례를 따른다:
|
|
12
|
+
* 복잡한 구조 입력은 JSON 파일 플래그로, 서버가 자동 관리하는 필드(relatedSpecIds)는
|
|
13
|
+
* 플래그를 두지 않는다.
|
|
14
|
+
*
|
|
15
|
+
* 계약 두 가지를 지킨다.
|
|
16
|
+
* - 출력(PLAT-003): `--json`(기계 모드)이면 stdout은 순수 JSON 문서 하나뿐이고
|
|
17
|
+
* 사람용 메시지는 stderr로 나간다. 빈 목록도 stdout에는 `[]`로 나간다.
|
|
18
|
+
* - 종료코드: HTTP 4xx/5xx는 client의 응답 인터셉터가 exitCode를 세우지만,
|
|
19
|
+
* 서버에 닿기 전 로컬 입력 오류(파일 없음·JSON 깨짐·--order 비숫자·수정 필드 0개)는
|
|
20
|
+
* 아무도 세워주지 않는다. 공용 printError는 stderr로 찍기만 할 뿐 종료코드를
|
|
21
|
+
* 건드리지 않으므로(다른 커맨드가 공유하는 함수라 고치면 회귀), 이 커맨드가
|
|
22
|
+
* failInput()으로 직접 exitCode=1을 세운다.
|
|
23
|
+
*
|
|
24
|
+
* screens는 프로젝트 단위 opt-in(ch_projects.screensEnabled)이지만 CLI는 그 플래그를
|
|
25
|
+
* 조회하지도 게이팅하지도 않는다. 서버의 screens CRUD가 플래그와 무관하게 동작하기
|
|
26
|
+
* 때문이다(migrate가 화면을 먼저 만들고 그 다음 플래그를 켠다 — SCREEN-001).
|
|
27
|
+
*/
|
|
28
|
+
/** `--states` JSON 파일 형식 안내 (create/update의 help 하단에 게시). */
|
|
29
|
+
const STATES_HELP = `
|
|
30
|
+
--states <jsonFile> 형식 (ScreenState[]):
|
|
31
|
+
states.json:
|
|
32
|
+
[
|
|
33
|
+
{ "name": "빈 상태", "description": "화면이 없을 때 안내 문구와 생성 버튼을 보여준다" },
|
|
34
|
+
{ "name": "로딩" },
|
|
35
|
+
{ "name": "에러", "description": "조회 실패 시 재시도 버튼을 보여준다" }
|
|
36
|
+
]
|
|
37
|
+
|
|
38
|
+
화면 상태는 빈/로딩/에러 같은 UI 휘발성 상태다. 저장되는 엔티티 상태
|
|
39
|
+
(db-table.stateMachines)와 섞지 않는다.
|
|
40
|
+
|
|
41
|
+
화면 목적(purpose) 입력 (우선순위: --file > --purpose):
|
|
42
|
+
--purpose "<문자열>" 인라인
|
|
43
|
+
--file <경로> 파일에서 (BOM·CRLF 자동 정제)
|
|
44
|
+
--file - stdin에서 (예: cat purpose.md | ch screens create --name X --file -)
|
|
45
|
+
|
|
46
|
+
stdin은 "--file -"로 명시할 때만 읽는다. 플래그 없이 stdin을 넘겨다보지 않는다 —
|
|
47
|
+
에이전트·CI 셸에서 fd0가 '열린 채 EOF가 오지 않는 파이프'인 경우가 흔해서,
|
|
48
|
+
암묵적 stdin 읽기는 "ch screens update <id> --order 3" 같은 평범한 호출을
|
|
49
|
+
무한 대기시킨다.
|
|
50
|
+
|
|
51
|
+
relatedSpecIds는 서버 자동 관리라 플래그가 없다 (spec ↔ screen 링크는 spec 쪽에서 건다).
|
|
52
|
+
`;
|
|
53
|
+
/**
|
|
54
|
+
* 로컬 입력 오류를 보고하고 종료코드를 세운다.
|
|
55
|
+
*
|
|
56
|
+
* printError는 stderr로 찍기만 하고 종료코드를 세우지 않으므로, 여기서 직접 세워
|
|
57
|
+
* 호출한 스크립트·에이전트가 종료코드만으로 실패를 알 수 있게 한다.
|
|
58
|
+
*/
|
|
59
|
+
function failInput(message) {
|
|
60
|
+
(0, output_1.printError)(message);
|
|
61
|
+
process.exitCode = 1;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* `--order` 값을 숫자로 파싱한다. 문자열을 그대로 서버에 실어 보내면 400으로
|
|
65
|
+
* 되돌아오므로 요청 전에 CLI가 거른다 (`--points`의 parsePoints 선례).
|
|
66
|
+
*/
|
|
67
|
+
function parseScreenOrder(value, label = '--order') {
|
|
68
|
+
const trimmed = String(value).trim();
|
|
69
|
+
const n = Number(trimmed);
|
|
70
|
+
if (trimmed === '' || !Number.isFinite(n)) {
|
|
71
|
+
throw new Error(`${label}: 숫자를 지정하세요 (예: 3). 받은 값: "${value}"`);
|
|
72
|
+
}
|
|
73
|
+
return n;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* 화면 목적(purpose) 본문을 해석한다. 우선순위: --file > --purpose.
|
|
77
|
+
* `--file -`이면 stdin에서 읽는다. 어느 경로든 BOM 제거 + CRLF→LF 정규화.
|
|
78
|
+
*
|
|
79
|
+
* stdin을 암묵적으로(플래그 없이) 읽지 않는 이유가 있다. 에이전트·CI 셸에서는 fd0가
|
|
80
|
+
* '열려 있지만 EOF가 오지 않는 파이프'로 상속되는 일이 흔하고, Windows에서는 그 파이프가
|
|
81
|
+
* 진짜 `echo x |` 파이프와 fstat으로 구분되지 않는다(둘 다 TTY도 FIFO도 FILE도 아니다).
|
|
82
|
+
* 그래서 "--file/--purpose가 없으면 stdin을 읽어 본다"는 규칙은 purpose를 주지 않은
|
|
83
|
+
* 평범한 호출(`ch screens update <id> --order 3`)을 무한 대기시킨다 — 실제로 이 커맨드
|
|
84
|
+
* 개발 중 재현했다. stdin 지원은 유지하되 `--file -`로 명시하게 한다(POSIX 관례).
|
|
85
|
+
*/
|
|
86
|
+
function resolvePurpose(options) {
|
|
87
|
+
if (options.file === '-') {
|
|
88
|
+
const piped = (0, utils_1.readContentStdin)();
|
|
89
|
+
if (piped === null) {
|
|
90
|
+
throw new Error('--file -: stdin에서 읽을 내용이 없습니다. 본문을 파이프로 넘기거나 --file <경로>/--purpose를 쓰세요.');
|
|
91
|
+
}
|
|
92
|
+
return piped;
|
|
93
|
+
}
|
|
94
|
+
if (options.file !== undefined) {
|
|
95
|
+
return (0, utils_1.readContentFile)(options.file, '--file');
|
|
96
|
+
}
|
|
97
|
+
if (options.purpose !== undefined) {
|
|
98
|
+
return (0, utils_1.normalizeContent)(options.purpose);
|
|
99
|
+
}
|
|
100
|
+
return undefined;
|
|
101
|
+
}
|
|
102
|
+
/** 화면 필드 플래그 (create/update 공용). create만 --name이 필수다. */
|
|
103
|
+
function addScreenFieldOptions(cmd) {
|
|
104
|
+
return cmd
|
|
105
|
+
.option('--route <route>', '라우트 경로 (예: /projects/[projectId]/specs?tab=prd)')
|
|
106
|
+
.option('--purpose <text>', '화면 목적 (자유 텍스트)')
|
|
107
|
+
.option('--file <path>', '화면 목적을 파일에서 읽기 ("-"이면 stdin, --purpose보다 우선)')
|
|
108
|
+
.option('--access <access>', '접근 권한 (예: admin, developer)')
|
|
109
|
+
.option('--states <jsonFile>', '화면 상태 목록 JSON 파일 (ScreenState[]) — 통째 교체')
|
|
110
|
+
.option('--entry-points <list>', '진입 경로 (쉼표 구분, ""이면 모두 해제)')
|
|
111
|
+
.option('--exit-points <list>', '이탈 경로 (쉼표 구분, ""이면 모두 해제)')
|
|
112
|
+
.option('--order <n>', '화면 순서 (숫자, 목록 정렬 키)')
|
|
113
|
+
.option('--epic <name>', '에픽 라벨 (spec.epic과 같은 라벨 체계)')
|
|
114
|
+
.option('--note <note>', '비고');
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* 플래그를 요청 바디로 변환한다. 지정된 플래그만 담으므로 update에서 그대로 PATCH
|
|
118
|
+
* 바디가 되고, 미지정 필드는 서버가 보존한다.
|
|
119
|
+
*
|
|
120
|
+
* 입력 오류(파일 없음·JSON 깨짐·--order 비숫자·--states 비배열)는 throw한다 —
|
|
121
|
+
* 호출부가 failInput으로 받아 종료코드를 세운다.
|
|
122
|
+
*/
|
|
123
|
+
function buildScreenBody(options) {
|
|
124
|
+
const body = {};
|
|
125
|
+
if (options.name !== undefined)
|
|
126
|
+
body.name = options.name;
|
|
127
|
+
if (options.route !== undefined)
|
|
128
|
+
body.route = options.route;
|
|
129
|
+
if (options.access !== undefined)
|
|
130
|
+
body.access = options.access;
|
|
131
|
+
if (options.epic !== undefined)
|
|
132
|
+
body.epic = options.epic;
|
|
133
|
+
if (options.note !== undefined)
|
|
134
|
+
body.note = options.note;
|
|
135
|
+
// 목적 본문: --file(경로 또는 "-"=stdin) > --purpose. BOM 제거 + CRLF→LF 정규화.
|
|
136
|
+
const purpose = resolvePurpose(options);
|
|
137
|
+
if (purpose !== undefined)
|
|
138
|
+
body.purpose = purpose;
|
|
139
|
+
if (options.states !== undefined) {
|
|
140
|
+
const states = (0, utils_1.readJsonFile)(options.states, '--states');
|
|
141
|
+
if (!Array.isArray(states)) {
|
|
142
|
+
throw new Error('--states: ScreenState 객체의 JSON 배열이어야 합니다 (예: [{"name": "로딩"}]).');
|
|
143
|
+
}
|
|
144
|
+
body.states = states;
|
|
145
|
+
}
|
|
146
|
+
// 배열 해제 판정은 `!== undefined`로 한다. falsy 체크를 쓰면 `--entry-points ""`
|
|
147
|
+
// (모두 해제)가 무시된다.
|
|
148
|
+
if (options.entryPoints !== undefined) {
|
|
149
|
+
body.entryPoints = (0, utils_1.parseCommaSeparated)(options.entryPoints);
|
|
150
|
+
}
|
|
151
|
+
if (options.exitPoints !== undefined) {
|
|
152
|
+
body.exitPoints = (0, utils_1.parseCommaSeparated)(options.exitPoints);
|
|
153
|
+
}
|
|
154
|
+
if (options.order !== undefined) {
|
|
155
|
+
body.order = parseScreenOrder(options.order, '--order');
|
|
156
|
+
}
|
|
157
|
+
return body;
|
|
158
|
+
}
|
|
159
|
+
/** 기계 모드(=stdout이 순수 JSON이어야 하는 모드)인지. */
|
|
160
|
+
function isMachineOutput(globalOpts) {
|
|
161
|
+
return !!(globalOpts.json || globalOpts.csv || globalOpts.quiet);
|
|
162
|
+
}
|
|
163
|
+
// ── 서브커맨드 ────────────────────────────────────────────────────────────
|
|
164
|
+
// 각 서브커맨드는 (screens, program)만 받는 독립 함수다. 새 서브커맨드
|
|
165
|
+
// (예: SCREEN-006의 `migrate`)는 같은 시그니처의 register 함수를 만들어
|
|
166
|
+
// registerScreensCommand의 등록 목록에 한 줄 더하면 된다.
|
|
167
|
+
function registerScreensList(screens, program) {
|
|
168
|
+
screens
|
|
169
|
+
.command('list')
|
|
170
|
+
.description('화면 목록 조회 (order 오름차순, order 없는 화면은 뒤)')
|
|
171
|
+
.action(async () => {
|
|
172
|
+
const globalOpts = program.opts();
|
|
173
|
+
try {
|
|
174
|
+
const client = (0, client_1.createClient)({ projectId: globalOpts.project });
|
|
175
|
+
const { data } = await client.get('/screens');
|
|
176
|
+
const items = Array.isArray(data) ? data : data?.data ?? [];
|
|
177
|
+
// 기계 모드 분기를 빈값 안내(printInfo)보다 앞에 둔다. 빈 결과도 stdout에
|
|
178
|
+
// `[]`로 나가야 하고, 사람용 안내문이 stdout(JSON)을 오염시키면 안 된다.
|
|
179
|
+
// (PLAT-003, 이슈 #50 — db-tables에서 겪은 회귀)
|
|
180
|
+
if (isMachineOutput(globalOpts)) {
|
|
181
|
+
(0, output_1.formatOutput)(items, globalOpts);
|
|
182
|
+
return;
|
|
183
|
+
}
|
|
184
|
+
if (!items.length) {
|
|
185
|
+
(0, output_1.printInfo)('등록된 화면이 없습니다.');
|
|
186
|
+
return;
|
|
187
|
+
}
|
|
188
|
+
(0, output_1.printTable)(['order', 'id', 'name', 'route', 'epic', 'states', 'specs'], items.map((s) => [
|
|
189
|
+
s?.order === undefined || s?.order === null ? '' : String(s.order),
|
|
190
|
+
String(s?.id ?? ''),
|
|
191
|
+
String(s?.name ?? ''),
|
|
192
|
+
String(s?.route ?? ''),
|
|
193
|
+
String(s?.epic ?? ''),
|
|
194
|
+
String(Array.isArray(s?.states) ? s.states.length : 0),
|
|
195
|
+
String(Array.isArray(s?.relatedSpecIds) ? s.relatedSpecIds.length : 0),
|
|
196
|
+
]));
|
|
197
|
+
}
|
|
198
|
+
catch (error) {
|
|
199
|
+
// 오류 출력·종료코드는 client 인터셉터가 처리했다.
|
|
200
|
+
}
|
|
201
|
+
});
|
|
202
|
+
}
|
|
203
|
+
function registerScreensGet(screens, program) {
|
|
204
|
+
// 로컬 --json은 두지 않는다. commander가 부모(program)의 전역 옵션을 서브커맨드
|
|
205
|
+
// 뒤에서도 해석하므로 `ch screens get <id> --json`이 그대로 동작한다.
|
|
206
|
+
screens
|
|
207
|
+
.command('get <screenId>')
|
|
208
|
+
.description('화면 상세 조회')
|
|
209
|
+
.action(async (screenId) => {
|
|
210
|
+
const globalOpts = program.opts();
|
|
211
|
+
try {
|
|
212
|
+
const client = (0, client_1.createClient)({ projectId: globalOpts.project });
|
|
213
|
+
const { data } = await client.get(`/screens/${screenId}`);
|
|
214
|
+
(0, output_1.formatOutput)(data, globalOpts);
|
|
215
|
+
}
|
|
216
|
+
catch (error) {
|
|
217
|
+
// Error already handled
|
|
218
|
+
}
|
|
219
|
+
});
|
|
220
|
+
}
|
|
221
|
+
function registerScreensCreate(screens, program) {
|
|
222
|
+
const create = screens
|
|
223
|
+
.command('create')
|
|
224
|
+
.description('화면 생성 (relatedSpecIds는 서버 자동 관리)')
|
|
225
|
+
.option('--id <screenId>', '사용자 지정 화면 ID (JIRA 스타일, 예: SCR-001). 생략 시 자동 생성')
|
|
226
|
+
.requiredOption('--name <name>', '화면명 (필수)');
|
|
227
|
+
addScreenFieldOptions(create)
|
|
228
|
+
.addHelpText('after', STATES_HELP)
|
|
229
|
+
.action(async (options) => {
|
|
230
|
+
const globalOpts = program.opts();
|
|
231
|
+
try {
|
|
232
|
+
if (globalOpts.dryRun) {
|
|
233
|
+
(0, output_1.printInfo)(`[DRY-RUN] 화면 "${options.name}" 생성 요청`);
|
|
234
|
+
return;
|
|
235
|
+
}
|
|
236
|
+
let body;
|
|
237
|
+
try {
|
|
238
|
+
body = buildScreenBody(options);
|
|
239
|
+
}
|
|
240
|
+
catch (e) {
|
|
241
|
+
failInput(e?.message ?? String(e));
|
|
242
|
+
return;
|
|
243
|
+
}
|
|
244
|
+
if (options.id)
|
|
245
|
+
body.id = options.id;
|
|
246
|
+
const client = (0, client_1.createClient)({ projectId: globalOpts.project });
|
|
247
|
+
const { data } = await client.post('/screens', body);
|
|
248
|
+
(0, output_1.formatOutput)(data, globalOpts);
|
|
249
|
+
(0, output_1.printSuccess)('화면이 생성되었습니다.');
|
|
250
|
+
}
|
|
251
|
+
catch (error) {
|
|
252
|
+
// Error already handled
|
|
253
|
+
}
|
|
254
|
+
});
|
|
255
|
+
}
|
|
256
|
+
function registerScreensUpdate(screens, program) {
|
|
257
|
+
const update = screens
|
|
258
|
+
.command('update <screenId>')
|
|
259
|
+
.description('화면 부분 업데이트 (지정한 필드만 변경)')
|
|
260
|
+
.option('--name <name>', '화면명');
|
|
261
|
+
addScreenFieldOptions(update)
|
|
262
|
+
.addHelpText('after', `${STATES_HELP}
|
|
263
|
+
지정한 플래그만 PATCH로 전송되어 미지정 필드는 서버가 보존한다. 다만 --states는
|
|
264
|
+
배열 통째 교체다 — 일부만 바꾸려면 먼저 'ch screens get <screenId> --json'으로 받아
|
|
265
|
+
배열 전체를 편집해 파일로 넘긴다 (Read-before-Write).
|
|
266
|
+
`)
|
|
267
|
+
.action(async (screenId, options) => {
|
|
268
|
+
const globalOpts = program.opts();
|
|
269
|
+
try {
|
|
270
|
+
if (globalOpts.dryRun) {
|
|
271
|
+
(0, output_1.printInfo)(`[DRY-RUN] 화면 "${screenId}" 수정 요청`);
|
|
272
|
+
return;
|
|
273
|
+
}
|
|
274
|
+
let body;
|
|
275
|
+
try {
|
|
276
|
+
body = buildScreenBody(options);
|
|
277
|
+
}
|
|
278
|
+
catch (e) {
|
|
279
|
+
failInput(e?.message ?? String(e));
|
|
280
|
+
return;
|
|
281
|
+
}
|
|
282
|
+
if (Object.keys(body).length === 0) {
|
|
283
|
+
failInput('수정할 필드를 지정하세요.');
|
|
284
|
+
return;
|
|
285
|
+
}
|
|
286
|
+
const client = (0, client_1.createClient)({ projectId: globalOpts.project });
|
|
287
|
+
const { data } = await client.patch(`/screens/${screenId}`, body);
|
|
288
|
+
(0, output_1.formatOutput)(data, globalOpts);
|
|
289
|
+
(0, output_1.printSuccess)('화면이 수정되었습니다.');
|
|
290
|
+
}
|
|
291
|
+
catch (error) {
|
|
292
|
+
// Error already handled
|
|
293
|
+
}
|
|
294
|
+
});
|
|
295
|
+
}
|
|
296
|
+
function registerScreensDelete(screens, program) {
|
|
297
|
+
screens
|
|
298
|
+
.command('delete <screenId>')
|
|
299
|
+
.description('화면 삭제 (참조 spec의 ui.screenRefs도 서버에서 자동 정리)')
|
|
300
|
+
.action(async (screenId) => {
|
|
301
|
+
const globalOpts = program.opts();
|
|
302
|
+
try {
|
|
303
|
+
if (globalOpts.dryRun) {
|
|
304
|
+
(0, output_1.printInfo)(`[DRY-RUN] 화면 "${screenId}" 삭제 요청`);
|
|
305
|
+
return;
|
|
306
|
+
}
|
|
307
|
+
const client = (0, client_1.createClient)({ projectId: globalOpts.project });
|
|
308
|
+
const { data } = await client.delete(`/screens/${screenId}`);
|
|
309
|
+
// 기계 모드에서는 서버 응답을 stdout에 순수 JSON으로 남겨 JSON.parse가 되게 한다.
|
|
310
|
+
// 사람용(표) 모드에서는 성공 한 줄이면 충분하다.
|
|
311
|
+
if (isMachineOutput(globalOpts)) {
|
|
312
|
+
(0, output_1.formatOutput)(data, globalOpts);
|
|
313
|
+
}
|
|
314
|
+
(0, output_1.printSuccess)('화면이 삭제되었습니다.');
|
|
315
|
+
}
|
|
316
|
+
catch (error) {
|
|
317
|
+
// Error already handled
|
|
318
|
+
}
|
|
319
|
+
});
|
|
320
|
+
}
|
|
321
|
+
function registerScreensCommand(program) {
|
|
322
|
+
const screens = program
|
|
323
|
+
.command('screens')
|
|
324
|
+
.description('화면(Screen) 관리 — 화면 정의 SSOT (/screens)');
|
|
325
|
+
registerScreensList(screens, program);
|
|
326
|
+
registerScreensGet(screens, program);
|
|
327
|
+
registerScreensCreate(screens, program);
|
|
328
|
+
registerScreensUpdate(screens, program);
|
|
329
|
+
registerScreensDelete(screens, program);
|
|
330
|
+
// 확장 지점: 새 서브커맨드는 위와 같은 register…(screens, program) 함수를 만들어
|
|
331
|
+
// 여기에 한 줄 추가한다 (예: `migrate` — SCREEN-006).
|
|
332
|
+
}
|
|
333
|
+
//# sourceMappingURL=screens.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"screens.js","sourceRoot":"","sources":["../../src/commands/screens.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -50,6 +50,7 @@ const dev_status_1 = require("./commands/dev-status");
|
|
|
50
50
|
const prd_1 = require("./commands/prd");
|
|
51
51
|
const db_schema_1 = require("./commands/db-schema");
|
|
52
52
|
const db_tables_1 = require("./commands/db-tables");
|
|
53
|
+
const screens_1 = require("./commands/screens");
|
|
53
54
|
const backup_1 = require("./commands/backup");
|
|
54
55
|
const notifications_1 = require("./commands/notifications");
|
|
55
56
|
const dashboard_1 = require("./commands/dashboard");
|
|
@@ -105,6 +106,7 @@ program.hook('preAction', (thisCommand) => {
|
|
|
105
106
|
(0, prd_1.registerPrdCommand)(program);
|
|
106
107
|
(0, db_schema_1.registerDbSchemaCommand)(program);
|
|
107
108
|
(0, db_tables_1.registerDbTablesCommand)(program);
|
|
109
|
+
(0, screens_1.registerScreensCommand)(program);
|
|
108
110
|
(0, backup_1.registerBackupCommand)(program);
|
|
109
111
|
(0, notifications_1.registerNotificationsCommand)(program);
|
|
110
112
|
(0, dashboard_1.registerDashboardCommand)(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.12.0
|
|
6
6
|
---
|
|
7
7
|
|
|
8
8
|
<!-- ch-version-gate -->
|
|
@@ -2,13 +2,14 @@
|
|
|
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 리소스, --work-status, --id, --points 등 플래그를 망라한다.
|
|
5
|
+
Epic-Story 체계(규모=Story Point)와 db-tables·screens 리소스, --work-status, --id, --points 등 플래그를 망라한다.
|
|
6
6
|
Use when:
|
|
7
|
-
(1) spec/db-table을 CLI로 다룰 때,
|
|
7
|
+
(1) spec/db-table/화면(screen)을 CLI로 다룰 때,
|
|
8
8
|
(2) spec 규모를 Story Point(`--points`)로 매길 때,
|
|
9
9
|
(3) ch db-tables 명령(list/get/create/update/delete)을 사용할 때,
|
|
10
|
-
(4)
|
|
11
|
-
|
|
10
|
+
(4) ch screens 명령(list/get/create/update/delete)으로 화면을 다룰 때,
|
|
11
|
+
(5) Spec ID를 JIRA 스타일(`LOGIN-001`)로 직접 지정할 때 (`ch specs create --id`).
|
|
12
|
+
version: 1.12.0
|
|
12
13
|
---
|
|
13
14
|
|
|
14
15
|
<!-- ch-version-gate -->
|
|
@@ -209,15 +210,68 @@ ch db-tables delete <tableId> # 참조 spec의 dbTableRefs도
|
|
|
209
210
|
}
|
|
210
211
|
```
|
|
211
212
|
|
|
212
|
-
## 3.
|
|
213
|
+
## 3. screens 명령 (화면)
|
|
214
|
+
|
|
215
|
+
화면(Screen)은 화면 정의의 SSOT다. `ch_projects.screensEnabled=true`인 프로젝트에서 쓴다.
|
|
216
|
+
|
|
217
|
+
```bash
|
|
218
|
+
ch screens list # 표 출력: order | id | name | route | epic | states | specs
|
|
219
|
+
ch screens get <screenId> # 상세
|
|
220
|
+
ch screens get <screenId> --json # 기계 모드 (stdout = 순수 JSON)
|
|
221
|
+
|
|
222
|
+
# 생성 (--name만 필수, --id 생략 시 자동 생성)
|
|
223
|
+
ch screens create \
|
|
224
|
+
--id SCR-001 \
|
|
225
|
+
--name "기능명세 목록" \
|
|
226
|
+
--route "/projects/[projectId]/specs?tab=spec" \
|
|
227
|
+
--purpose "프로젝트의 기능명세를 한눈에 보고 원하는 명세로 들어가게 한다." \
|
|
228
|
+
--access "admin, developer" \
|
|
229
|
+
--states ./states.json \
|
|
230
|
+
--entry-points "프로젝트 대시보드에서 '기획' 탭 클릭" \
|
|
231
|
+
--exit-points "목록 행 클릭 시 명세 상세로 이동" \
|
|
232
|
+
--order 1 --epic "E12 화면 관리"
|
|
233
|
+
|
|
234
|
+
# 수정: 지정한 플래그만 PATCH (미지정 필드는 서버가 보존)
|
|
235
|
+
ch screens update <screenId> --order 3
|
|
236
|
+
ch screens update <screenId> --entry-points "" # 진입 경로 모두 해제
|
|
237
|
+
|
|
238
|
+
ch screens delete <screenId> # 참조 spec의 ui.screenRefs도 서버가 자동 정리
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
- `--id`는 JIRA 스타일(`SCR-001`). 패턴 `^[A-Za-z][A-Za-z0-9_]*-[A-Za-z0-9]+$`, 중복 시 409.
|
|
242
|
+
- 화면 목적(purpose) 입력 — 우선순위 `--file` > `--purpose`. BOM·CRLF는 자동 정제된다.
|
|
243
|
+
- `--purpose "<문자열>"` 인라인, `--file <경로>` 파일에서, `--file -` stdin에서.
|
|
244
|
+
- stdin은 **`--file -`로 명시할 때만** 읽는다: `cat purpose.md | ch screens create --name X --file -`
|
|
245
|
+
- `--order`는 숫자. 숫자가 아니면 요청을 보내지 않고 종료코드 ≠ 0으로 끝난다.
|
|
246
|
+
- `create`는 생성 결과(`{ "id": ... }`)를 출력한다. 전체 문서가 필요하면 이어서 `ch screens get <id>`.
|
|
247
|
+
- `relatedSpecIds`는 사용자 입력 금지(서버 자동 관리). spec ↔ screen 링크는 spec 쪽에서 건다.
|
|
248
|
+
- 로컬 입력 오류(파일 없음·JSON 깨짐·`--order` 비숫자·`update` 필드 0개)는 **요청을 보내지 않고** 종료코드 ≠ 0으로 끝난다.
|
|
249
|
+
|
|
250
|
+
### states.json (`--states`)
|
|
251
|
+
|
|
252
|
+
빈/로딩/에러 같은 **UI 휘발성 상태**다. 저장되는 엔티티 상태(db-table의 `stateMachines`)와 섞지 않는다.
|
|
253
|
+
|
|
254
|
+
```json
|
|
255
|
+
[
|
|
256
|
+
{ "name": "빈 상태", "description": "화면이 없을 때 안내 문구와 생성 버튼을 보여준다" },
|
|
257
|
+
{ "name": "로딩" },
|
|
258
|
+
{ "name": "에러", "description": "조회 실패 시 재시도 버튼을 보여준다" }
|
|
259
|
+
]
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
`ScreenState{name, description?}`의 정의(SSOT)는 db-tables의 `screens` 테이블 문서다.
|
|
263
|
+
|
|
264
|
+
## 4. 운영 팁
|
|
213
265
|
|
|
214
266
|
- Windows 한글 출력이 비어 보일 때: `ch specs get <id> --json | Out-File spec.json` (PowerShell)
|
|
215
267
|
- `ch-cli` 버전 확인: `ch --version` (1.3.2+ 권장)
|
|
216
268
|
- 본문(content/markdown)은 항상 `\n` 줄바꿈 — CLI가 BOM/CRLF 자동 정제
|
|
217
269
|
|
|
218
|
-
##
|
|
270
|
+
## 5. 흔한 함정
|
|
219
271
|
|
|
220
272
|
- `--ui`/`--logic`(및 deprecated `--tasks`) JSON은 통째 교체이므로 일부만 수정해도 **전체 전달 필수**. 반드시 `ch specs get`으로 받아 편집. (`--points`는 스칼라라 안전.)
|
|
221
273
|
- Story를 Task로 쪼개지 않는다 — 규모는 `--points`로 매긴다. `--tasks`는 deprecated(하위호환).
|
|
222
274
|
- `--db-tables ""`는 모두 해제. 단일 ID 유지하려면 그 ID만 명시.
|
|
223
275
|
- `relatedSpecIds`를 JSON에 명시해도 서버가 무시 (자동 관리 영역).
|
|
276
|
+
- `ch screens update --states`도 배열 **통째 교체**다. 상태 하나만 고치려 해도 `ch screens get <id> --json`으로 받아 배열 전체를 넘긴다.
|
|
277
|
+
- 화면 SSOT는 `screensEnabled=true`인 프로젝트에서만 screens다. 이 플래그가 꺼진(=기존) 프로젝트는 화면 정보의 SSOT가 여전히 `spec.ui.route`다 — screens를 만들어도 그 프로젝트의 화면 정보가 자동으로 옮겨가지 않는다.
|
|
@@ -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.12.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.12.0
|
|
6
6
|
---
|
|
7
7
|
|
|
8
8
|
<!-- ch-version-gate -->
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
name: 2t-decencia-channel-project-bootstrap
|
|
3
3
|
description: 신규 기획을 사용자와 대화하며 step-by-step으로 소통채널 프로젝트로 만드는 오케스트레이터 스킬. (1)대화로 PRD 완성 → 승인 → (2)페이지명세(spec)+DB스키마 → 승인 → (3)SQA 시트. 각 단계 사용자 승인 게이트, 작성 디테일은 기존 2t-decencia-channel-*-v2 스킬을 적극 재사용. "새 기획 만들어줘"·"프로젝트 처음부터 세팅" 류 요청 시.
|
|
4
4
|
allowed-tools: Bash(ch:*) Bash(git:*) Read Write
|
|
5
|
-
version: 1.
|
|
5
|
+
version: 1.12.0
|
|
6
6
|
---
|
|
7
7
|
|
|
8
8
|
<!-- ch-version-gate -->
|
|
@@ -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.
|
|
5
|
+
version: 1.12.0
|
|
6
6
|
---
|
|
7
7
|
|
|
8
8
|
<!-- ch-version-gate -->
|