@decencia/ch-cli 1.27.0 → 1.28.1

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.
@@ -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.27.0
6
+ version: 1.28.1
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.27.0
6
+ version: 1.28.1
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.27.0
6
+ version: 1.28.1
7
7
  ---
8
8
 
9
9
  ## 역할
@@ -0,0 +1,94 @@
1
+ import { Command } from 'commander';
2
+ /** 스킬 스코프 — 글로벌(팀 공유) 또는 프로젝트(서브컬렉션). */
3
+ export type SkillScope = 'global' | 'project';
4
+ /** 업로드 대상 파일 하나 — 절대경로 + 폴더 루트 기준 상대경로(POSIX). */
5
+ export interface SkillUpload {
6
+ absPath: string;
7
+ relPath: string;
8
+ }
9
+ /** SKILL.md frontmatter 에서 뽑는 인덱스(라우팅 신호). */
10
+ export interface SkillFrontmatter {
11
+ name: string;
12
+ description: string;
13
+ }
14
+ /** ch-api 가 돌려주는 목록 항목(list 응답)의 최소 형태. */
15
+ interface SkillIndexEntry {
16
+ id: string;
17
+ name: string;
18
+ }
19
+ /** 스킬 폴더 규약상 고정된 매니페스트 파일명. frontmatter 의 출처. */
20
+ export declare const SKILL_MANIFEST_FILENAME = "SKILL.md";
21
+ /**
22
+ * 스코프를 결정한다: `--global` 이면 글로벌(팀 공유), 아니면 프로젝트.
23
+ *
24
+ * 프로젝트 스코프에서 "어느 프로젝트냐"는 ch 전역 규약대로 프로젝트 컨텍스트
25
+ * (`--project <projectId>` / `.ch-project` / `~/.ch/config.json`)로 정한다.
26
+ * ch 는 이미 `--project <projectId>`(값 있는 옵션)를 전역으로 쓰므로, 같은 이름의
27
+ * boolean `--project` 스코프 플래그는 둘 수 없다(commander 가 값 옵션으로 해석).
28
+ * 그래서 프로젝트 스코프는 `--global` 의 부재로 나타낸다 — 다른 모든 ch 커맨드가
29
+ * 프로젝트를 다루는 방식과 동일하다.
30
+ */
31
+ export declare function resolveScope(opts: {
32
+ global?: boolean;
33
+ }): SkillScope;
34
+ /** 스코프별 ch-api 기본 경로. */
35
+ export declare function skillBasePath(scope: SkillScope): string;
36
+ /**
37
+ * `list` 가 조회할 스코프들을 정한다(소비 인덱스용).
38
+ * - `--global` 이면 글로벌만.
39
+ * - 플래그가 없으면 글로벌+프로젝트 둘 다 — 에이전트가 팀 공유 스킬과 프로젝트
40
+ * 스킬을 한 목록에서 보고 고르게(각 항목의 scope 로 구분). 웹 스킬 목록
41
+ * 화면(SKILL-001)이 두 스코프를 함께 보여주는 것과 같은 소비 모델이다.
42
+ *
43
+ * get/register/update 는 대상 스코프가 하나여야 하므로 resolveScope(단일)를
44
+ * 쓰지만, list 는 읽기 전용 발견(discovery)이라 기본을 합집합으로 넓힌다.
45
+ */
46
+ export declare function scopesToList(opts: {
47
+ global?: boolean;
48
+ }): SkillScope[];
49
+ /**
50
+ * Content-Type 헤더에서 순수 MIME 타입만 뽑는다(`; charset=...` 파라미터 제거).
51
+ * 값이 없으면 application/octet-stream 으로 폴백.
52
+ */
53
+ export declare function extractMime(contentType: string | undefined): string;
54
+ /**
55
+ * 폴더를 재귀적으로 훑어 업로드 대상 파일 목록을 만든다.
56
+ * 하위 폴더·임의 파일을 모두 보존하고, 상대경로는 폴더 루트 기준 POSIX(`/`)로
57
+ * 정규화한다(서버의 paths 정렬 규칙과 맞춤). 결과는 상대경로 사전순 정렬.
58
+ * (심볼릭 링크는 건너뛴다 — 루프·바깥 참조 방지.)
59
+ */
60
+ export declare function collectSkillFiles(dir: string): SkillUpload[];
61
+ /**
62
+ * 상대경로 목록에서 루트에 가장 가까운 SKILL.md 를 고른다(서버 규칙과 동일).
63
+ * 없으면 undefined.
64
+ */
65
+ export declare function pickRootSkillMd(relPaths: string[]): string | undefined;
66
+ /**
67
+ * frontmatter 값이 인덱스로 쓸 만한지 검증한다(서버 파서와 동일 규약).
68
+ * 비었거나(공백만) 블록 스칼라 지시자(`|`·`>` 등)만 남았으면 무효.
69
+ */
70
+ export declare function isValidFrontmatterValue(value: string): boolean;
71
+ /**
72
+ * SKILL.md 텍스트에서 frontmatter(name·description)를 뽑는다(서버 파서와 동일 규약).
73
+ * description 은 여러 줄 YAML 블록 스칼라(`|`·`>`)일 수 있어(이슈 #197) 손파싱 대신
74
+ * 검증된 YAML 파서(js-yaml)로 파싱한다. frontmatter 블록이 없거나 파싱 실패/필드
75
+ * 부재면 빈 문자열 — 검증/거부는 호출측 책임.
76
+ * 서버(ch-api)가 최종 SSOT지만, 업로드 전에 여기서 먼저 걸러 헛수고를 막는다.
77
+ */
78
+ export declare function parseSkillFrontmatter(markdown: string): SkillFrontmatter;
79
+ /** 목록에서 name 으로 스킬 문서 id 를 찾는다(update 의 name→id 해석). */
80
+ export declare function findSkillIdByName(list: SkillIndexEntry[], name: string): string | undefined;
81
+ /**
82
+ * 스킬 폴더를 검증하고 업로드 대상을 만든다(신규 등록·수정 공용).
83
+ * - 폴더 존재·디렉터리 여부
84
+ * - 파일 존재(빈 폴더 거부)
85
+ * - 루트 SKILL.md 존재 + frontmatter(name·description) 존재
86
+ * 실패 시 사용자 친화 에러를 throw 한다.
87
+ */
88
+ export declare function prepareSkillUpload(dir: string): {
89
+ uploads: SkillUpload[];
90
+ frontmatter: SkillFrontmatter;
91
+ };
92
+ export declare function registerSkillsCommand(program: Command): void;
93
+ export {};
94
+ //# sourceMappingURL=skills.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skills.d.ts","sourceRoot":"","sources":["../../src/commands/skills.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAgBpC,yCAAyC;AACzC,MAAM,MAAM,UAAU,GAAG,QAAQ,GAAG,SAAS,CAAC;AAE9C,kDAAkD;AAClD,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,8CAA8C;AAC9C,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,2CAA2C;AAC3C,UAAU,eAAe;IACvB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;CACd;AAED,iDAAiD;AACjD,eAAO,MAAM,uBAAuB,aAAa,CAAC;AAIlD;;;;;;;;;GASG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE;IAAE,MAAM,CAAC,EAAE,OAAO,CAAA;CAAE,GAAG,UAAU,CAEnE;AAED,yBAAyB;AACzB,wBAAgB,aAAa,CAAC,KAAK,EAAE,UAAU,GAAG,MAAM,CAEvD;AAED;;;;;;;;;GASG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE;IAAE,MAAM,CAAC,EAAE,OAAO,CAAA;CAAE,GAAG,UAAU,EAAE,CAErE;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,WAAW,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CAGnE;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,WAAW,EAAE,CAqB5D;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,MAAM,GAAG,SAAS,CAQtE;AAKD;;;GAGG;AACH,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAG9D;AA6BD;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,MAAM,GAAG,gBAAgB,CAsBxE;AAED,wDAAwD;AACxD,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE,eAAe,EAAE,EACvB,IAAI,EAAE,MAAM,GACX,MAAM,GAAG,SAAS,CAEpB;AAED;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,GAAG;IAC/C,OAAO,EAAE,WAAW,EAAE,CAAC;IACvB,WAAW,EAAE,gBAAgB,CAAC;CAC/B,CAoCA;AAqBD,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAyM5D"}
@@ -0,0 +1,406 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ var __importDefault = (this && this.__importDefault) || function (mod) {
36
+ return (mod && mod.__esModule) ? mod : { "default": mod };
37
+ };
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ exports.SKILL_MANIFEST_FILENAME = void 0;
40
+ exports.resolveScope = resolveScope;
41
+ exports.skillBasePath = skillBasePath;
42
+ exports.scopesToList = scopesToList;
43
+ exports.extractMime = extractMime;
44
+ exports.collectSkillFiles = collectSkillFiles;
45
+ exports.pickRootSkillMd = pickRootSkillMd;
46
+ exports.isValidFrontmatterValue = isValidFrontmatterValue;
47
+ exports.parseSkillFrontmatter = parseSkillFrontmatter;
48
+ exports.findSkillIdByName = findSkillIdByName;
49
+ exports.prepareSkillUpload = prepareSkillUpload;
50
+ exports.registerSkillsCommand = registerSkillsCommand;
51
+ const fs = __importStar(require("fs"));
52
+ const path = __importStar(require("path"));
53
+ const js_yaml_1 = require("js-yaml");
54
+ const form_data_1 = __importDefault(require("form-data"));
55
+ const client_1 = require("../client");
56
+ const output_1 = require("../output");
57
+ /** 스킬 폴더 규약상 고정된 매니페스트 파일명. frontmatter 의 출처. */
58
+ exports.SKILL_MANIFEST_FILENAME = 'SKILL.md';
59
+ // ── 순수 헬퍼 (단위 테스트 대상) ──────────────────────────────────────────
60
+ /**
61
+ * 스코프를 결정한다: `--global` 이면 글로벌(팀 공유), 아니면 프로젝트.
62
+ *
63
+ * 프로젝트 스코프에서 "어느 프로젝트냐"는 ch 전역 규약대로 프로젝트 컨텍스트
64
+ * (`--project <projectId>` / `.ch-project` / `~/.ch/config.json`)로 정한다.
65
+ * ch 는 이미 `--project <projectId>`(값 있는 옵션)를 전역으로 쓰므로, 같은 이름의
66
+ * boolean `--project` 스코프 플래그는 둘 수 없다(commander 가 값 옵션으로 해석).
67
+ * 그래서 프로젝트 스코프는 `--global` 의 부재로 나타낸다 — 다른 모든 ch 커맨드가
68
+ * 프로젝트를 다루는 방식과 동일하다.
69
+ */
70
+ function resolveScope(opts) {
71
+ return opts.global ? 'global' : 'project';
72
+ }
73
+ /** 스코프별 ch-api 기본 경로. */
74
+ function skillBasePath(scope) {
75
+ return scope === 'global' ? '/skills/global' : '/skills/project';
76
+ }
77
+ /**
78
+ * `list` 가 조회할 스코프들을 정한다(소비 인덱스용).
79
+ * - `--global` 이면 글로벌만.
80
+ * - 플래그가 없으면 글로벌+프로젝트 둘 다 — 에이전트가 팀 공유 스킬과 프로젝트
81
+ * 스킬을 한 목록에서 보고 고르게(각 항목의 scope 로 구분). 웹 스킬 목록
82
+ * 화면(SKILL-001)이 두 스코프를 함께 보여주는 것과 같은 소비 모델이다.
83
+ *
84
+ * get/register/update 는 대상 스코프가 하나여야 하므로 resolveScope(단일)를
85
+ * 쓰지만, list 는 읽기 전용 발견(discovery)이라 기본을 합집합으로 넓힌다.
86
+ */
87
+ function scopesToList(opts) {
88
+ return opts.global ? ['global'] : ['global', 'project'];
89
+ }
90
+ /**
91
+ * Content-Type 헤더에서 순수 MIME 타입만 뽑는다(`; charset=...` 파라미터 제거).
92
+ * 값이 없으면 application/octet-stream 으로 폴백.
93
+ */
94
+ function extractMime(contentType) {
95
+ const base = (contentType || '').split(';')[0].trim();
96
+ return base || 'application/octet-stream';
97
+ }
98
+ /**
99
+ * 폴더를 재귀적으로 훑어 업로드 대상 파일 목록을 만든다.
100
+ * 하위 폴더·임의 파일을 모두 보존하고, 상대경로는 폴더 루트 기준 POSIX(`/`)로
101
+ * 정규화한다(서버의 paths 정렬 규칙과 맞춤). 결과는 상대경로 사전순 정렬.
102
+ * (심볼릭 링크는 건너뛴다 — 루프·바깥 참조 방지.)
103
+ */
104
+ function collectSkillFiles(dir) {
105
+ const root = path.resolve(dir);
106
+ const out = [];
107
+ const walk = (current) => {
108
+ const entries = fs.readdirSync(current, { withFileTypes: true });
109
+ for (const entry of entries) {
110
+ const abs = path.join(current, entry.name);
111
+ if (entry.isSymbolicLink())
112
+ continue;
113
+ if (entry.isDirectory()) {
114
+ walk(abs);
115
+ }
116
+ else if (entry.isFile()) {
117
+ const rel = path.relative(root, abs).split(path.sep).join('/');
118
+ out.push({ absPath: abs, relPath: rel });
119
+ }
120
+ }
121
+ };
122
+ walk(root);
123
+ out.sort((a, b) => a.relPath.localeCompare(b.relPath));
124
+ return out;
125
+ }
126
+ /**
127
+ * 상대경로 목록에서 루트에 가장 가까운 SKILL.md 를 고른다(서버 규칙과 동일).
128
+ * 없으면 undefined.
129
+ */
130
+ function pickRootSkillMd(relPaths) {
131
+ return relPaths
132
+ .filter((p) => p === exports.SKILL_MANIFEST_FILENAME ||
133
+ p.endsWith(`/${exports.SKILL_MANIFEST_FILENAME}`))
134
+ .sort((a, b) => a.split('/').length - b.split('/').length)[0];
135
+ }
136
+ /** YAML 로 파싱되기 전, 손으로 쓴 블록 스칼라 지시자만 남은 퇴화 값(방어용). */
137
+ const BLOCK_SCALAR_INDICATORS = new Set(['|', '>', '|-', '>-', '|+', '>+']);
138
+ /**
139
+ * frontmatter 값이 인덱스로 쓸 만한지 검증한다(서버 파서와 동일 규약).
140
+ * 비었거나(공백만) 블록 스칼라 지시자(`|`·`>` 등)만 남았으면 무효.
141
+ */
142
+ function isValidFrontmatterValue(value) {
143
+ const trimmed = value.trim();
144
+ return trimmed.length > 0 && !BLOCK_SCALAR_INDICATORS.has(trimmed);
145
+ }
146
+ /** frontmatter 블록(여는 `---`와 닫는 `---` 사이) 텍스트만 잘라낸다. 없으면 null. */
147
+ function extractFrontmatterBlock(markdown) {
148
+ const text = markdown.charCodeAt(0) === 0xfeff ? markdown.slice(1) : markdown;
149
+ const lines = text.split(/\r?\n/);
150
+ let start = 0;
151
+ while (start < lines.length && lines[start].trim() === '')
152
+ start++;
153
+ if (start >= lines.length || lines[start].trim() !== '---')
154
+ return null;
155
+ for (let i = start + 1; i < lines.length; i++) {
156
+ if (lines[i].trim() === '---') {
157
+ return lines.slice(start + 1, i).join('\n');
158
+ }
159
+ }
160
+ return null;
161
+ }
162
+ /** YAML 스칼라 값을 인덱스 문자열로 정규화한다(문자열/숫자/불리언 허용, 그 외 빈 값). */
163
+ function coerceScalar(value) {
164
+ if (value == null)
165
+ return '';
166
+ if (typeof value === 'string')
167
+ return value.trim();
168
+ if (typeof value === 'number' || typeof value === 'boolean') {
169
+ return String(value);
170
+ }
171
+ return '';
172
+ }
173
+ /**
174
+ * SKILL.md 텍스트에서 frontmatter(name·description)를 뽑는다(서버 파서와 동일 규약).
175
+ * description 은 여러 줄 YAML 블록 스칼라(`|`·`>`)일 수 있어(이슈 #197) 손파싱 대신
176
+ * 검증된 YAML 파서(js-yaml)로 파싱한다. frontmatter 블록이 없거나 파싱 실패/필드
177
+ * 부재면 빈 문자열 — 검증/거부는 호출측 책임.
178
+ * 서버(ch-api)가 최종 SSOT지만, 업로드 전에 여기서 먼저 걸러 헛수고를 막는다.
179
+ */
180
+ function parseSkillFrontmatter(markdown) {
181
+ const empty = { name: '', description: '' };
182
+ if (!markdown)
183
+ return empty;
184
+ const block = extractFrontmatterBlock(markdown);
185
+ if (block === null)
186
+ return empty;
187
+ let doc;
188
+ try {
189
+ doc = (0, js_yaml_1.load)(block);
190
+ }
191
+ catch {
192
+ return empty;
193
+ }
194
+ if (doc === null || typeof doc !== 'object' || Array.isArray(doc)) {
195
+ return empty;
196
+ }
197
+ const record = doc;
198
+ return {
199
+ name: coerceScalar(record.name),
200
+ description: coerceScalar(record.description),
201
+ };
202
+ }
203
+ /** 목록에서 name 으로 스킬 문서 id 를 찾는다(update 의 name→id 해석). */
204
+ function findSkillIdByName(list, name) {
205
+ return list.find((s) => s.name === name)?.id;
206
+ }
207
+ /**
208
+ * 스킬 폴더를 검증하고 업로드 대상을 만든다(신규 등록·수정 공용).
209
+ * - 폴더 존재·디렉터리 여부
210
+ * - 파일 존재(빈 폴더 거부)
211
+ * - 루트 SKILL.md 존재 + frontmatter(name·description) 존재
212
+ * 실패 시 사용자 친화 에러를 throw 한다.
213
+ */
214
+ function prepareSkillUpload(dir) {
215
+ const resolved = path.resolve(dir);
216
+ if (!fs.existsSync(resolved)) {
217
+ throw new Error(`폴더를 찾을 수 없습니다: ${resolved}`);
218
+ }
219
+ if (!fs.statSync(resolved).isDirectory()) {
220
+ throw new Error(`폴더가 아닙니다(파일 경로): ${resolved}`);
221
+ }
222
+ const uploads = collectSkillFiles(resolved);
223
+ if (uploads.length === 0) {
224
+ throw new Error(`빈 폴더입니다(업로드할 파일이 없습니다): ${resolved}`);
225
+ }
226
+ const skillMdRel = pickRootSkillMd(uploads.map((u) => u.relPath));
227
+ if (!skillMdRel) {
228
+ throw new Error(`SKILL.md 가 없습니다. 스킬 폴더 루트에 ${exports.SKILL_MANIFEST_FILENAME} 가 필요합니다: ${resolved}`);
229
+ }
230
+ const skillMd = uploads.find((u) => u.relPath === skillMdRel);
231
+ const frontmatter = parseSkillFrontmatter(fs.readFileSync(skillMd.absPath, 'utf-8'));
232
+ // 파싱 후 방어: 비었거나 블록 스칼라 지시자(`|`·`>`)만 남은 값은 거부(이슈 #197).
233
+ if (!isValidFrontmatterValue(frontmatter.name) ||
234
+ !isValidFrontmatterValue(frontmatter.description)) {
235
+ throw new Error(`${exports.SKILL_MANIFEST_FILENAME} frontmatter 에 name·description 이 모두 필요합니다: ${skillMdRel}`);
236
+ }
237
+ return { uploads, frontmatter };
238
+ }
239
+ /**
240
+ * 폴더구조를 보존한 multipart 폼을 만든다.
241
+ * `files` 를 상대경로 정렬 순서대로 append 하고, 같은 순서의 `paths`(JSON 배열)를
242
+ * 함께 보낸다 — 서버가 paths[i] 를 files[i] 의 상대경로로 매칭한다.
243
+ */
244
+ function buildUploadForm(uploads) {
245
+ const form = new form_data_1.default();
246
+ form.append('paths', JSON.stringify(uploads.map((u) => u.relPath)));
247
+ for (const u of uploads) {
248
+ form.append('files', fs.createReadStream(u.absPath));
249
+ }
250
+ return form;
251
+ }
252
+ // ── 커맨드 등록 ────────────────────────────────────────────────────────────
253
+ function registerSkillsCommand(program) {
254
+ const skills = program
255
+ .command('skills')
256
+ .description('스킬 목록·조회·등록·수정 (E19) — ch-api /skills 프록시');
257
+ // ch skills list
258
+ skills
259
+ .command('list')
260
+ .description('스킬 목록 조회 (name·description·scope 인덱스) — 기본은 글로벌+프로젝트')
261
+ .option('--global', '글로벌(팀 공유) 스킬만. 생략 시 글로벌+프로젝트 스킬을 함께 반환(각 항목의 scope 로 구분)')
262
+ .action(async (options) => {
263
+ const globalOpts = program.opts();
264
+ const scopes = scopesToList(options);
265
+ const client = (0, client_1.createClient)({ projectId: globalOpts.project });
266
+ // 스코프별로 독립 조회해 합친다 — 한쪽(예: 프로젝트 컨텍스트 미해석)이
267
+ // 실패해도 다른 쪽 결과는 보존한다(인터셉터가 exitCode 로 실패를 알린다).
268
+ const merged = [];
269
+ for (const scope of scopes) {
270
+ try {
271
+ const { data } = await client.get(skillBasePath(scope));
272
+ if (Array.isArray(data))
273
+ merged.push(...data);
274
+ }
275
+ catch (error) {
276
+ // Error already handled by client interceptor (exitCode/stderr).
277
+ }
278
+ }
279
+ (0, output_1.formatOutput)(merged, globalOpts);
280
+ });
281
+ // ch skills get <name> [--file <path>] --global|--project
282
+ skills
283
+ .command('get <name>')
284
+ .description('스킬 단건 조회 — SKILL.md 본문 + 파일 매니페스트, --file 로 개별 파일만')
285
+ .option('--global', '글로벌(팀 공유) 스킬. 생략 시 프로젝트 스킬(대상 프로젝트는 --project <id>/.ch-project/config)')
286
+ .option('--file <path>', '지목한 개별 파일만 반환(스킬 폴더 기준 상대경로). 기본은 파일 원본을 stdout 으로, --json 이면 {scope,name,path,mime,content} JSON')
287
+ .action(async (name, options) => {
288
+ const globalOpts = program.opts();
289
+ const scope = resolveScope(options);
290
+ try {
291
+ const client = (0, client_1.createClient)({ projectId: globalOpts.project });
292
+ // 서버 엔드포인트는 문서 id 를 받으므로 name→id 를 목록에서 해석한다.
293
+ const { data: list } = await client.get(skillBasePath(scope));
294
+ const id = findSkillIdByName(Array.isArray(list) ? list : [], name);
295
+ if (!id) {
296
+ (0, output_1.failInput)(`스킬을 찾을 수 없습니다: "${name}" (${scope}). 목록은 ch skills list 로 확인하세요.`);
297
+ return;
298
+ }
299
+ if (options.file) {
300
+ // 개별 파일 — 서버가 원본 바이트를 스트리밍한다.
301
+ const res = await client.get(`${skillBasePath(scope)}/${id}/file`, {
302
+ params: { path: options.file },
303
+ responseType: 'arraybuffer',
304
+ });
305
+ const buffer = Buffer.from(res.data);
306
+ if ((0, output_1.isMachineMode)()) {
307
+ // 기계 모드: stdout 은 순수 JSON 하나만(1.x 출력 계약).
308
+ const contentType = res.headers['content-type'];
309
+ const mime = extractMime(typeof contentType === 'string' ? contentType : undefined);
310
+ (0, output_1.formatOutput)({
311
+ scope,
312
+ name,
313
+ path: options.file,
314
+ mime,
315
+ content: buffer.toString('utf8'),
316
+ }, globalOpts);
317
+ }
318
+ else {
319
+ // 기본: 파일 원본을 그대로 stdout 으로(에이전트가 바로 읽어 소비).
320
+ process.stdout.write(buffer);
321
+ }
322
+ return;
323
+ }
324
+ // 단건 — SKILL.md 본문 + files 매니페스트.
325
+ const { data } = await client.get(`${skillBasePath(scope)}/${id}`);
326
+ (0, output_1.formatOutput)(data, globalOpts);
327
+ }
328
+ catch (error) {
329
+ // Error already handled by client interceptor
330
+ }
331
+ });
332
+ // ch skills register <dir> --global|--project
333
+ skills
334
+ .command('register <dir>')
335
+ .description('로컬 폴더를 새 스킬로 등록 (신규 전용) — 폴더구조 보존 업로드')
336
+ .option('--global', '글로벌(팀 공유) 스킬로 등록 — systemAdmin. 생략 시 프로젝트 스킬(admin·developer, 대상 프로젝트는 --project <id>/.ch-project/config)')
337
+ .action(async (dir, options) => {
338
+ const globalOpts = program.opts();
339
+ const scope = resolveScope(options);
340
+ let prepared;
341
+ try {
342
+ prepared = prepareSkillUpload(dir);
343
+ }
344
+ catch (e) {
345
+ (0, output_1.failInput)(e?.message ?? String(e));
346
+ return;
347
+ }
348
+ const { uploads, frontmatter } = prepared;
349
+ if (globalOpts.dryRun) {
350
+ (0, output_1.printInfo)(`[DRY-RUN] 스킬 "${frontmatter.name}"(${scope}) 등록 요청 — 파일 ${uploads.length}개`);
351
+ return;
352
+ }
353
+ try {
354
+ const form = buildUploadForm(uploads);
355
+ const client = (0, client_1.createClient)({ projectId: globalOpts.project });
356
+ const { data } = await client.post(skillBasePath(scope), form, {
357
+ headers: { ...form.getHeaders() },
358
+ });
359
+ (0, output_1.formatOutput)(data, globalOpts);
360
+ (0, output_1.printSuccess)(`스킬 "${frontmatter.name}"이(가) 등록되었습니다 (${scope}, 파일 ${uploads.length}개).`);
361
+ }
362
+ catch (error) {
363
+ // Error already handled (409=동일 name 중복 등)
364
+ }
365
+ });
366
+ // ch skills update <name> <dir> --global|--project
367
+ skills
368
+ .command('update <name> <dir>')
369
+ .description('기존 스킬의 파일을 새 폴더로 통째 교체')
370
+ .option('--global', '글로벌(팀 공유) 스킬. 생략 시 프로젝트 스킬(대상 프로젝트는 --project <id>/.ch-project/config)')
371
+ .action(async (name, dir, options) => {
372
+ const globalOpts = program.opts();
373
+ const scope = resolveScope(options);
374
+ let prepared;
375
+ try {
376
+ prepared = prepareSkillUpload(dir);
377
+ }
378
+ catch (e) {
379
+ (0, output_1.failInput)(e?.message ?? String(e));
380
+ return;
381
+ }
382
+ const { uploads } = prepared;
383
+ if (globalOpts.dryRun) {
384
+ (0, output_1.printInfo)(`[DRY-RUN] 스킬 "${name}"(${scope}) 파일 교체 요청 — 파일 ${uploads.length}개`);
385
+ return;
386
+ }
387
+ try {
388
+ const client = (0, client_1.createClient)({ projectId: globalOpts.project });
389
+ // 서버 PATCH 는 문서 id 를 받으므로 name→id 를 목록에서 해석한다.
390
+ const { data: list } = await client.get(skillBasePath(scope));
391
+ const id = findSkillIdByName(Array.isArray(list) ? list : [], name);
392
+ if (!id) {
393
+ (0, output_1.failInput)(`수정할 스킬을 찾을 수 없습니다: "${name}" (${scope}). 신규 등록은 register 를 사용하세요.`);
394
+ return;
395
+ }
396
+ const form = buildUploadForm(uploads);
397
+ const { data } = await client.patch(`${skillBasePath(scope)}/${id}`, form, { headers: { ...form.getHeaders() } });
398
+ (0, output_1.formatOutput)(data, globalOpts);
399
+ (0, output_1.printSuccess)(`스킬 "${name}"이(가) 수정되었습니다 (${scope}, 파일 ${uploads.length}개).`);
400
+ }
401
+ catch (error) {
402
+ // Error already handled
403
+ }
404
+ });
405
+ }
406
+ //# sourceMappingURL=skills.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skills.js","sourceRoot":"","sources":["../../src/commands/skills.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,QAAQ;IACvB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,aAAa,EAAE,OAAO,GAAG,MAAM,GAAG,KAAK,CAAC;CACzC;AAED,MAAM,WAAW,cAAc;IAC7B,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,cAAc;IAC7B,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,YAAY,GAAG,OAAO,GAAG,QAAQ,CAAC;CAC3C;AAMD,wBAAgB,UAAU,IAAI,QAAQ,GAAG,IAAI,CAU5C;AAED;;GAEG;AACH,wBAAgB,gBAAgB,IAAI,cAAc,GAAG,IAAI,CAkBxD;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,YAAY,CAAC,EAAE,MAAM,GAAG,cAAc,GAAG,IAAI,CAgB9E;AAED,gFAAgF;AAChF,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,cAAc,CAAC,QAAQ,CAAC,GAAG,MAAM,CAW9E;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,0BAA0B,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAiB/D;AAED,wBAAgB,UAAU,CAAC,MAAM,EAAE,QAAQ,GAAG,IAAI,CAKjD;AAED,wBAAgB,WAAW,IAAI,IAAI,CAIlC;AAED,wBAAgB,aAAa,IAAI,MAAM,CAEtC"}
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,QAAQ;IACvB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,aAAa,EAAE,OAAO,GAAG,MAAM,GAAG,KAAK,CAAC;CACzC;AAED,MAAM,WAAW,cAAc;IAC7B,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,cAAc;IAC7B,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,YAAY,GAAG,OAAO,GAAG,QAAQ,CAAC;CAC3C;AAMD,wBAAgB,UAAU,IAAI,QAAQ,GAAG,IAAI,CAU5C;AAED;;GAEG;AACH,wBAAgB,gBAAgB,IAAI,cAAc,GAAG,IAAI,CAkBxD;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,YAAY,CAAC,EAAE,MAAM,GAAG,cAAc,GAAG,IAAI,CAgB9E;AAED,gFAAgF;AAChF,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,cAAc,CAAC,QAAQ,CAAC,GAAG,MAAM,CAW9E;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,0BAA0B,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAwB/D;AAED,wBAAgB,UAAU,CAAC,MAAM,EAAE,QAAQ,GAAG,IAAI,CAKjD;AAED,wBAAgB,WAAW,IAAI,IAAI,CAIlC;AAED,wBAAgB,aAAa,IAAI,MAAM,CAEtC"}
package/dist/config.js CHANGED
@@ -138,6 +138,12 @@ function pathRequiresProjectContext(url) {
138
138
  if (normalized === 'projects') {
139
139
  return false;
140
140
  }
141
+ // Account-level: global skills (팀 공유, systemAdmin). No X-Project-Id needed.
142
+ // Project skills (`/skills/project*`) ARE project-scoped and must still
143
+ // require context.
144
+ if (normalized === 'skills/global' || normalized.startsWith('skills/global/')) {
145
+ return false;
146
+ }
141
147
  return true;
142
148
  }
143
149
  function saveConfig(config) {
@@ -1 +1 @@
1
- {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -46,6 +46,7 @@ const requests_1 = require("./commands/requests");
46
46
  const qna_1 = require("./commands/qna");
47
47
  const sqa_1 = require("./commands/sqa");
48
48
  const archives_1 = require("./commands/archives");
49
+ const skills_1 = require("./commands/skills");
49
50
  const members_1 = require("./commands/members");
50
51
  const dev_status_1 = require("./commands/dev-status");
51
52
  const prd_1 = require("./commands/prd");
@@ -104,6 +105,7 @@ program.hook('preAction', (thisCommand) => {
104
105
  (0, qna_1.registerQnaCommand)(program);
105
106
  (0, sqa_1.registerSqaCommand)(program);
106
107
  (0, archives_1.registerArchivesCommand)(program);
108
+ (0, skills_1.registerSkillsCommand)(program);
107
109
  (0, members_1.registerMembersCommand)(program);
108
110
  (0, dev_status_1.registerDevStatusCommand)(program);
109
111
  (0, prd_1.registerPrdCommand)(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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@decencia/ch-cli",
3
- "version": "1.27.0",
3
+ "version": "1.28.1",
4
4
  "description": "Decencia Communication Channel CLI",
5
5
  "main": "dist/index.js",
6
6
  "bin": {
@@ -31,9 +31,11 @@
31
31
  "chalk": "^4.1.2",
32
32
  "cli-table3": "^0.6.5",
33
33
  "commander": "^14.0.3",
34
- "form-data": "^4.0.5"
34
+ "form-data": "^4.0.5",
35
+ "js-yaml": "^4.1.0"
35
36
  },
36
37
  "devDependencies": {
38
+ "@types/js-yaml": "^4.0.9",
37
39
  "@types/node": "^25.6.0",
38
40
  "typescript": "^6.0.3"
39
41
  }
@@ -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.27.0
5
+ version: 1.28.1
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.27.0
13
+ version: 1.28.1
14
14
  ---
15
15
 
16
16
  <!-- ch-version-gate -->
@@ -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.27.0
13
+ version: 1.28.1
14
14
  ---
15
15
 
16
16
  <!-- ch-version-gate -->
@@ -8,7 +8,7 @@ description: |
8
8
  (2) DB 테이블 단위로 컬럼·인덱스·보안규칙을 등록·수정할 때,
9
9
  (3) 새 테이블을 추가하면서 전체 인벤토리도 함께 업데이트할 때,
10
10
  (4) spec.dbTableRefs와 양방향 동기화가 필요한 작업 시.
11
- version: 1.27.0
11
+ version: 1.28.1
12
12
  ---
13
13
 
14
14
  <!-- ch-version-gate -->
@@ -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.27.0
5
+ version: 1.28.1
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.27.0
5
+ version: 1.28.1
6
6
  ---
7
7
 
8
8
  <!-- ch-version-gate -->
@@ -7,7 +7,7 @@ description: |
7
7
  (1) PRD를 작성하거나 갱신할 때,
8
8
  (2) PRD 구성에서 Epic/스토리 구조를 후속 spec 작성에 매핑할 때,
9
9
  (3) Read-before-Write 규칙으로 PRD content를 안전하게 수정해야 할 때.
10
- version: 1.27.0
10
+ version: 1.28.1
11
11
  ---
12
12
 
13
13
  <!-- 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) 내용 확정 → (3)DB 스키마 → (4)spec 업로드 → (5)화면 구성·연결 → (6)SQA 시트. 각 단계 사용자 승인 게이트, 작성 디테일은 기존 2t-decencia-channel-*-v2 스킬을 적극 재사용. "새 기획 만들어줘"·"프로젝트 처음부터 세팅" 류 요청 시.
4
4
  allowed-tools: Bash(ch:*) Bash(git:*) Read Write
5
- version: 1.27.0
5
+ version: 1.28.1
6
6
  ---
7
7
 
8
8
  <!-- ch-version-gate -->
@@ -11,7 +11,7 @@ description: |
11
11
  (2) UI 메타데이터·비즈니스 로직·DB 참조를 함께 다룰 때,
12
12
  (3) Story 규모를 Story Point(`--points`)로 매길 때,
13
13
  (4) 신규 spec ID를 `LOGIN-001` 같은 JIRA 스타일로 부여하고 싶을 때 (`ch specs create --id`).
14
- version: 1.27.0
14
+ version: 1.28.1
15
15
  ---
16
16
 
17
17
  <!-- ch-version-gate -->
@@ -7,7 +7,7 @@ description: |
7
7
  (1) sprint를 구성할 때,
8
8
  (2) Σ spec.points 기반 sprint 용량 산정이 필요할 때,
9
9
  (3) Epic·도메인·의존성을 함께 고려해 spec을 sprint에 배분할 때.
10
- version: 1.27.0
10
+ version: 1.28.1
11
11
  ---
12
12
 
13
13
  <!-- 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.27.0
5
+ version: 1.28.1
6
6
  ---
7
7
 
8
8
  <!-- ch-version-gate -->
@@ -12,7 +12,7 @@ description: |
12
12
  (4) 명세 영역별 완성형 TC 번들(퍼블리싱/프론트/백엔드 디센시아 운영 관점 포함)을 가져다 쓸 때,
13
13
  (5) 새 명세 작업 중 반복 패턴을 발견해 영역별 번들을 보강할 때,
14
14
  (6) Sprint 종료 전 spec별 SQA 통과 여부를 점검할 때.
15
- version: 1.27.0
15
+ version: 1.28.1
16
16
  ---
17
17
 
18
18
  <!-- ch-version-gate -->
@@ -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.27.0
11
+ version: 1.28.1
12
12
  ---
13
13
 
14
14
  <!-- ch-version-gate -->