vibe-commander 0.2.0 → 0.2.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.
Files changed (37) hide show
  1. package/AGENTS.md +1 -0
  2. package/README.ko.md +643 -0
  3. package/README.md +643 -0
  4. package/dist/adapters/cli/commands/git-helpers.js +5 -3
  5. package/dist/adapters/cli/commands/init-helpers.js +1 -1
  6. package/dist/adapters/cli/commands/io-helpers.js +6 -2
  7. package/dist/adapters/cli/commands/schema.js +7 -3
  8. package/dist/adapters/cli/commands/set-unit.js +8 -2
  9. package/dist/adapters/cli/commands/skill-install.js +10 -4
  10. package/dist/adapters/cli/formatters-schema.d.ts +17 -0
  11. package/dist/adapters/cli/formatters-schema.js +155 -0
  12. package/dist/adapters/cli/formatters-unit.d.ts +0 -8
  13. package/dist/adapters/cli/formatters-unit.js +0 -146
  14. package/dist/adapters/cli/index.js +2 -1
  15. package/dist/adapters/cli/router.d.ts +0 -12
  16. package/dist/adapters/cli/router.js +4 -103
  17. package/dist/adapters/cli/stdin-parser.d.ts +23 -0
  18. package/dist/adapters/cli/stdin-parser.js +109 -0
  19. package/dist/config/schema.d.ts +0 -9
  20. package/dist/config/schema.js +138 -56
  21. package/dist/core/renderers/index.d.ts +1 -1
  22. package/dist/core/renderers/index.js +1 -1
  23. package/dist/core/renderers/marker-utils.js +5 -3
  24. package/dist/core/renderers/schema-renderer.d.ts +16 -0
  25. package/dist/core/renderers/schema-renderer.js +21 -0
  26. package/dist/core/resolvers/index.d.ts +0 -2
  27. package/examples/nextjs-web.config.json +73 -0
  28. package/examples/python-backend.config.json +91 -0
  29. package/examples/tauri-app.config.json +95 -0
  30. package/examples/vscode-tasks.json +101 -0
  31. package/package.json +14 -2
  32. package/schemas/config-schema.json +409 -0
  33. package/skills/claude/SKILL.md +22 -0
  34. package/skills/common/cli-reference.md +22 -0
  35. package/skills/cursor/SKILL.md +22 -0
  36. package/dist/adapters/cli/formatters.d.ts +0 -2
  37. package/dist/adapters/cli/formatters.js +0 -3
@@ -0,0 +1,109 @@
1
+ /**
2
+ * stdin JSON → ParsedArgs 변환 — Layer 3 (Adapter)
3
+ *
4
+ * stdin을 통해 전달된 JSON 데이터를 ParsedArgs로 변환한다.
5
+ * 서브커맨드는 argv에서 결정되고, 인자/옵션은 stdin JSON에서 추출.
6
+ *
7
+ * @module
8
+ */
9
+ import { ok, fail } from '../../types/index.js';
10
+ /**
11
+ * stdin JSON 데이터로부터 ParsedArgs를 생성한다
12
+ *
13
+ * 서브커맨드는 argv에서 결정되고, 인자/옵션은 stdin JSON에서 추출.
14
+ * --stdin은 --no-prompt를 암시한다 (stdin이 JSON 데이터에 사용되므로 인터랙티브 불가).
15
+ *
16
+ * @param subcommand - argv에서 추출한 서브커맨드 이름
17
+ * @param data - stdin에서 파싱한 JSON 객체
18
+ * @param json - --json 플래그 여부
19
+ * @returns ParsedArgs 또는 에러
20
+ */
21
+ export function parseStdinArgs(subcommand, data, json, rawArgs) {
22
+ switch (subcommand) {
23
+ case 'set-unit': {
24
+ const unitId = typeof data.unitId === 'string' ? data.unitId : undefined;
25
+ if (!unitId) {
26
+ return fail('STDIN_MISSING_FIELD', 'stdin JSON에 "unitId" (string) 필드가 필요합니다', '예시: {"unitId": "U-001[Mvp]"}');
27
+ }
28
+ const requestKeys = Array.isArray(data.requestKeys)
29
+ ? data.requestKeys.filter((k) => typeof k === 'string')
30
+ : [];
31
+ const dryRun = rawArgs?.includes('--dry-run') ?? false;
32
+ return ok({ command: 'set-unit', unitId, requestKeys, noPrompt: true, dryRun, json });
33
+ }
34
+ case 'update-commit': {
35
+ const modeValue = typeof data.mode === 'string' ? data.mode : undefined;
36
+ const mode = modeValue === 'append' ? 'append' : 'replace';
37
+ const section = typeof data.section === 'string' ? data.section : undefined;
38
+ const base = {
39
+ command: 'update-commit',
40
+ mode,
41
+ ...(section !== undefined && { section }),
42
+ json,
43
+ };
44
+ if (typeof data.sha === 'string') {
45
+ return ok({ ...base, commitMode: 'manual', sha: data.sha });
46
+ }
47
+ if (typeof data.count === 'number' && Number.isInteger(data.count) && data.count > 0) {
48
+ return ok({ ...base, commitMode: 'auto-recent', count: data.count });
49
+ }
50
+ return ok({ ...base, commitMode: 'auto-head' });
51
+ }
52
+ case 'list-units': {
53
+ const phase = typeof data.phase === 'string' ? data.phase : undefined;
54
+ return ok({
55
+ command: 'list-units',
56
+ ...(phase !== undefined && { phase }),
57
+ json,
58
+ });
59
+ }
60
+ case 'context': {
61
+ const unitId = typeof data.unitId === 'string' ? data.unitId : undefined;
62
+ if (!unitId) {
63
+ return fail('STDIN_MISSING_FIELD', 'stdin JSON에 "unitId" (string) 필드가 필요합니다', '예시: {"unitId": "U-001[Mvp]"}');
64
+ }
65
+ return ok({ command: 'context', unitId, json });
66
+ }
67
+ case 'validate':
68
+ return ok({ command: 'validate', json });
69
+ case 'init':
70
+ return ok({
71
+ command: 'init',
72
+ json,
73
+ stdinData: data,
74
+ fromExisting: rawArgs?.includes('--from-existing') ?? false,
75
+ force: rawArgs?.includes('--force') ?? false,
76
+ });
77
+ case 'skill': {
78
+ if (!rawArgs?.includes('install')) {
79
+ return fail('UNKNOWN_COMMAND', 'skill 서브커맨드가 필요합니다', '사용법: vc skill install --stdin --json');
80
+ }
81
+ const stdinTargets = Array.isArray(data.targets)
82
+ ? data.targets.filter((t) => t === 'cursor' || t === 'claude' || t === 'gemini')
83
+ : [];
84
+ const targets = stdinTargets.length > 0 ? stdinTargets : ['cursor', 'claude', 'gemini'];
85
+ return ok({
86
+ command: 'skill-install',
87
+ targets,
88
+ force: rawArgs.includes('--force'),
89
+ json,
90
+ });
91
+ }
92
+ case 'schema': {
93
+ const sub = typeof data.subcommand === 'string' ? data.subcommand : undefined;
94
+ if (sub && sub !== 'config' && sub !== 'commands' && sub !== 'types') {
95
+ return fail('UNKNOWN_SUBCOMMAND', `알 수 없는 schema 서브커맨드: ${sub}`, '사용 가능한 서브커맨드: config, commands, types');
96
+ }
97
+ const output = typeof data.output === 'string' ? data.output : undefined;
98
+ return ok({
99
+ command: 'schema',
100
+ ...(sub !== undefined && { subcommand: sub }),
101
+ json,
102
+ ...(output !== undefined && { output }),
103
+ });
104
+ }
105
+ default:
106
+ return fail('UNKNOWN_COMMAND', `알 수 없는 명령어: ${subcommand}`, '사용 가능한 명령어: init, set-unit, update-commit, list-units, context, validate, skill, schema');
107
+ }
108
+ }
109
+ //# sourceMappingURL=stdin-parser.js.map
@@ -202,13 +202,4 @@ export type InferredCommandSectionsConfig = z.infer<typeof commandSectionsSchema
202
202
  export type InferredProjectConfig = z.infer<typeof projectConfigSchema>;
203
203
  /** 설정 파일명 */
204
204
  export declare const CONFIG_FILENAME = "vibe-commander.config.json";
205
- /**
206
- * 프로젝트 설정 스키마를 JSON Schema (Draft 2020-12) 형식으로 반환한다
207
- *
208
- * Zod 4의 z.toJSONSchema() 내장 기능을 활용하여 변환.
209
- * 에이전트가 설정 파일 구조를 런타임에 조회할 수 있도록 한다.
210
- *
211
- * @returns JSON Schema 호환 객체
212
- */
213
- export declare function getConfigJsonSchema(): Record<string, unknown>;
214
205
  //# sourceMappingURL=schema.d.ts.map
@@ -12,27 +12,43 @@ import { z } from 'zod';
12
12
  /** 기본 경로 설정 스키마 */
13
13
  export const pathsSchema = z.object({
14
14
  /** 커맨드 파일 경로 (프로젝트 루트 기준) */
15
- commands: z.string().default('commands.md'),
15
+ commands: z
16
+ .string()
17
+ .default('commands.md')
18
+ .describe('Command file path where unit context sections are managed'),
16
19
  /** 로드맵 파일 경로. null이면 list-units 비활성화 */
17
- roadmap: z.string().nullable().default('roadmap.md'),
20
+ roadmap: z
21
+ .string()
22
+ .nullable()
23
+ .default('roadmap.md')
24
+ .describe('Roadmap/backlog file path. Set to null to disable list-units command'),
18
25
  /** 역할별 문서 루트 디렉토리 (키: 역할명, 값: 상대 경로) */
19
- docRoots: z.record(z.string(), z.string()).default({
26
+ docRoots: z
27
+ .record(z.string(), z.string())
28
+ .default({
20
29
  plan: 'unit-plans',
21
30
  result: 'unit-results',
22
31
  runbook: 'unit-runbooks',
23
- }),
32
+ })
33
+ .describe('Document root directories by role (key: role name, value: relative path)'),
24
34
  /** 리팩토링 서브유닛 디렉토리. null이면 서브유닛 미사용 */
25
- refactorSubDir: z.string().nullable().default(null),
35
+ refactorSubDir: z
36
+ .string()
37
+ .nullable()
38
+ .default(null)
39
+ .describe('Refactoring sub-unit directory. Set to null if sub-units are not used'),
26
40
  });
27
41
  // ── 유닛 유형 ──
28
42
  /** 유닛 유형 정의 스키마 */
29
43
  export const unitTypeSchema = z.object({
30
44
  /** 유형 키 (예: "implement", "refactor") */
31
- key: z.string(),
45
+ key: z.string().describe("Unique type key (e.g. 'implement', 'refactor', 'feature')"),
32
46
  /** 표시 이름 (예: "유닛 구현"). 미제공 시 key 값 활용 */
33
- displayName: z.string().optional(),
47
+ displayName: z.string().optional().describe('Human-readable display name for this type'),
34
48
  /** 유닛 ID 매칭 정규식 패턴 (예: "^(U-\\d+|CP-).*") */
35
- idPattern: z.string().refine((val) => {
49
+ idPattern: z
50
+ .string()
51
+ .refine((val) => {
36
52
  try {
37
53
  new RegExp(val);
38
54
  return true;
@@ -40,46 +56,83 @@ export const unitTypeSchema = z.object({
40
56
  catch {
41
57
  return false;
42
58
  }
43
- }, { message: '유효한 정규식 문자열이어야 합니다' }),
59
+ }, { message: '유효한 정규식 문자열이어야 합니다' })
60
+ .describe("Regex pattern to match unit IDs (e.g. '^U-\\\\d+.*', '^FEAT-\\\\d+$')"),
44
61
  /** 계획서 디렉토리 (paths.docRoots 키 참조) */
45
- planDir: z.string(),
62
+ planDir: z.string().describe('Document root key (from paths.docRoots) where plans are stored'),
46
63
  /** 커맨드 파일 내 대상 섹션 헤더 (예: "# 유닛 구현") */
47
- commandSection: z.string(),
64
+ commandSection: z
65
+ .string()
66
+ .describe("Target section header in the command file (e.g. '# Unit Implementation')"),
48
67
  /** 의존성 수집 여부 */
49
- collectDeps: z.boolean(),
68
+ collectDeps: z
69
+ .boolean()
70
+ .describe('Whether to collect dependency documents and commits for this type'),
50
71
  /** 섹션 헤더 템플릿. {{unitId}}, {{title}} 등 변수 치환 지원 */
51
- headerTemplate: z.string(),
72
+ headerTemplate: z
73
+ .string()
74
+ .describe('Section header template with variable interpolation: {{unitId}}, {{title}}, {{titleOnly}}, {{planPath}}, {{shortId}}'),
52
75
  });
53
76
  // ── 문서 탐색 ──
54
77
  /** 개별 문서 역할의 탐색 규칙 스키마 */
55
78
  export const docDiscoveryRuleSchema = z.object({
56
79
  /** 파일 탐색 패턴 (예: "{{unitId}}.md") */
57
- pattern: z.string(),
80
+ pattern: z
81
+ .string()
82
+ .describe('File search pattern. Supports {{unitId}} and {{shortId}} variables'),
58
83
  /** glob 패턴 사용 여부 (기본: false) */
59
- glob: z.boolean().optional().default(false),
84
+ glob: z
85
+ .boolean()
86
+ .optional()
87
+ .default(false)
88
+ .describe('Whether to use glob matching (true) or exact match (false)'),
60
89
  });
61
90
  /** 문서 탐색 설정 스키마 (역할별 규칙 맵) */
62
- export const docDiscoverySchema = z.record(z.string(), docDiscoveryRuleSchema);
91
+ export const docDiscoverySchema = z
92
+ .record(z.string(), docDiscoveryRuleSchema)
93
+ .describe('Document discovery rules by role. Defines file name patterns for finding unit documents');
63
94
  // ── 계획서 파싱 ──
64
95
  /** 메타데이터 테이블 파싱 설정 스키마 */
65
96
  export const metadataTableSchema = z.object({
66
97
  /** ID 필드명 */
67
- idField: z.string().default('Unit ID'),
98
+ idField: z
99
+ .string()
100
+ .default('Unit ID')
101
+ .describe('Field name for the unit ID in the metadata table'),
68
102
  /** Phase 필드명 */
69
- phaseField: z.string().default('Phase'),
103
+ phaseField: z
104
+ .string()
105
+ .default('Phase')
106
+ .describe('Field name for the phase in the metadata table'),
70
107
  /** 의존성 필드명 */
71
- dependsField: z.string().default('의존성'),
108
+ dependsField: z
109
+ .string()
110
+ .default('의존성')
111
+ .describe('Field name for dependencies in the metadata table'),
72
112
  });
73
113
  /** 계획서 파싱 설정 스키마 */
74
114
  export const planParsingSchema = z.object({
75
115
  /** 제목 추출 소스 ("h1" | "frontmatter:title") */
76
- titleSource: z.enum(['h1', 'frontmatter:title']).default('h1'),
116
+ titleSource: z
117
+ .enum(['h1', 'frontmatter:title'])
118
+ .default('h1')
119
+ .describe("How to extract the unit title: 'h1' from first heading, 'frontmatter:title' from YAML frontmatter"),
77
120
  /** 의존성 추출 소스 ("section" | "frontmatter" | "metadata-table") */
78
- dependsSource: z.enum(['section', 'frontmatter', 'metadata-table']).default('section'),
121
+ dependsSource: z
122
+ .enum(['section', 'frontmatter', 'metadata-table'])
123
+ .default('section')
124
+ .describe("How to extract dependencies: 'section' from markdown section, 'frontmatter' from YAML, 'metadata-table' from 2-column table"),
79
125
  /** 의존성 섹션 헤더명. null이면 섹션 기반 추출 비활성화 */
80
- dependsSectionName: z.string().nullable().default('이전 작업에서 가져올 것'),
126
+ dependsSectionName: z
127
+ .string()
128
+ .nullable()
129
+ .default('이전 작업에서 가져올 것')
130
+ .describe('Dependency section header name. Set to null to disable section-based extraction'),
81
131
  /** 페어링 질문 섹션 헤더명 */
82
- pairingQuestionSection: z.string().default('페어링 질문'),
132
+ pairingQuestionSection: z
133
+ .string()
134
+ .default('페어링 질문')
135
+ .describe('Section header name for pairing questions (checkbox items)'),
83
136
  /** 메타데이터 테이블 파싱 설정 */
84
137
  metadataTable: metadataTableSchema.prefault({}),
85
138
  });
@@ -87,24 +140,28 @@ export const planParsingSchema = z.object({
87
140
  /** 상태 표시 매핑 스키마 */
88
141
  export const statusMapSchema = z.object({
89
142
  /** 대기 상태 표시 */
90
- ready: z.string().default('⏸️'),
143
+ ready: z.string().default('⏸️').describe('Ready/waiting status indicator'),
91
144
  /** 진행중 상태 표시 */
92
- inProgress: z.string().default('🚧'),
145
+ inProgress: z.string().default('🚧').describe('In-progress status indicator'),
93
146
  /** 완료 상태 표시 */
94
- completed: z.string().default('✅'),
147
+ completed: z.string().default('✅').describe('Completed status indicator'),
95
148
  /** 차단 상태 표시 */
96
- blocked: z.string().default('❌'),
149
+ blocked: z.string().default('❌').describe('Blocked status indicator'),
97
150
  });
98
151
  /** 백로그(로드맵) 파싱 설정 스키마 */
99
152
  export const backlogParsingSchema = z.object({
100
153
  /** 백로그 섹션 시작 헤더 */
101
- sectionHeader: z.string().default('## 작업 백로그'),
154
+ sectionHeader: z
155
+ .string()
156
+ .default('## 작업 백로그')
157
+ .describe('Backlog section start header in the roadmap file'),
102
158
  /** 백로그 항목 매칭 정규식 (named group 지원) */
103
159
  entryPattern: z
104
160
  .string()
105
- .default('ID=\\[(?<id>.+?)\\]\\((?<path>[^)]+)\\)\\s*\\|\\s*(?<title>[^|]+)\\|\\s*Depends=(?<deps>[^|]*)\\|\\s*(?<status>.+)'),
161
+ .default('ID=\\[(?<id>.+?)\\]\\((?<path>[^)]+)\\)\\s*\\|\\s*(?<title>[^|]+)\\|\\s*Depends=(?<deps>[^|]*)\\|\\s*(?<status>.+)')
162
+ .describe('Regex pattern with named groups (id, path, title, deps, status) to match backlog entries'),
106
163
  /** 완료된 유닛 섹션 헤더 */
107
- completedSection: z.string().default('### 완료'),
164
+ completedSection: z.string().default('### 완료').describe('Section header for completed units'),
108
165
  /** 상태 문자열 ↔ 내부 상태 키 매핑 */
109
166
  statusMap: statusMapSchema.prefault({}),
110
167
  });
@@ -112,40 +169,64 @@ export const backlogParsingSchema = z.object({
112
169
  /** 커밋 탐색 설정 스키마 */
113
170
  export const commitSearchSchema = z.object({
114
171
  /** 탐색 전략 ("git-log-grep" | "conventional-commit" | "disabled") */
115
- strategy: z.string().default('git-log-grep'),
172
+ strategy: z
173
+ .string()
174
+ .default('git-log-grep')
175
+ .describe("Search strategy: 'git-log-grep', 'conventional-commit', or 'disabled'"),
116
176
  /** grep에 사용할 ID 변환 방식 (예: "shortId") */
117
- extractId: z.string().default('shortId'),
177
+ extractId: z
178
+ .string()
179
+ .default('shortId')
180
+ .describe("ID transformation for grep: 'shortId' removes phase tag (e.g. U-001[Mvp] → U-001)"),
118
181
  /** 최대 결과 수 */
119
- maxResults: z.number().default(5),
182
+ maxResults: z.number().default(5).describe('Maximum number of commits to return per dependency'),
120
183
  /**
121
184
  * 제외할 경로 glob 패턴 목록.
122
185
  * 변경 파일이 모두 이 패턴에 매칭되는 커밋은 필터링됨 (문서 전용 커밋 제거).
123
186
  * 기본값 [] → 필터 미적용
124
187
  */
125
- excludePaths: z.array(z.string()).default([]),
188
+ excludePaths: z
189
+ .array(z.string())
190
+ .default([])
191
+ .describe("Glob patterns for paths to exclude (e.g. 'docs/**' to filter doc-only commits)"),
126
192
  /**
127
193
  * 필수 포함 경로 glob 패턴 목록.
128
194
  * 변경 파일 중 하나라도 이 패턴에 매칭되어야 통과 (소스 코드 커밋만 허용).
129
195
  * 기본값 [] → 필터 미적용
130
196
  */
131
- requirePaths: z.array(z.string()).default([]),
197
+ requirePaths: z
198
+ .array(z.string())
199
+ .default([])
200
+ .describe("Glob patterns that at least one changed file must match (e.g. 'src/**' for source-only commits)"),
132
201
  });
133
202
  // ── 커맨드 파일 섹션 ──
134
203
  /** 커맨드 파일 섹션 설정 스키마 */
135
204
  export const commandSectionsSchema = z.object({
136
205
  /** 섹션 구분자 문자열 */
137
- separator: z.string().default('---------------------------------------------------'),
206
+ separator: z
207
+ .string()
208
+ .default('---------------------------------------------------')
209
+ .describe('Section separator string in the command file'),
138
210
  /** 다른 섹션 보존 여부 */
139
- preserveOtherSections: z.boolean().default(true),
211
+ preserveOtherSections: z
212
+ .boolean()
213
+ .default(true)
214
+ .describe('Whether to preserve sections not managed by the current unit type'),
140
215
  /** Commit SHA를 기록할 필드 키워드 (기본: "Commit") */
141
- commitFieldName: z.string().default('Commit'),
216
+ commitFieldName: z
217
+ .string()
218
+ .default('Commit')
219
+ .describe('Field keyword for recording commit SHA in the command file'),
142
220
  /**
143
221
  * HTML 주석 마커 사용 여부.
144
222
  * true이면 섹션 경계에 `<!-- vc:begin:{key} -->` / `<!-- vc:end:{key} -->` 마커를 삽입하고,
145
223
  * 섹션 탐색 시 마커를 우선 사용한다 (Fallback으로 기존 헤더 기반 탐색).
146
224
  * 기본값 false로 기존 프로젝트 하위 호환 보장.
147
225
  */
148
- useMarkers: z.boolean().default(false),
226
+ useMarkers: z
227
+ .boolean()
228
+ .default(false)
229
+ .describe('Use HTML comment markers (<!-- vc:begin/end -->) for safer section boundary detection'),
149
230
  });
150
231
  // ── 최상위 설정 ──
151
232
  /** 기본 문서 탐색 설정 */
@@ -157,13 +238,16 @@ export const DEFAULT_DOC_DISCOVERY = {
157
238
  /** 프로젝트 설정 스키마 (vibe-commander.config.json) */
158
239
  export const projectConfigSchema = z.object({
159
240
  /** JSON Schema URL (IDE 자동완성용) */
160
- $schema: z.string().optional(),
241
+ $schema: z.string().optional().describe('JSON Schema URL for IDE autocomplete and validation'),
161
242
  /** 설정 파일 버전 (현재 1 고정) */
162
- version: z.literal(1),
243
+ version: z.literal(1).describe('Configuration file version (currently 1)'),
163
244
  /** 기본 경로 설정 */
164
245
  paths: pathsSchema.prefault({}),
165
246
  /** 유닛 유형 정의 배열 (순서 = ID 매칭 우선순위, 최소 1개 필수) */
166
- unitTypes: z.array(unitTypeSchema).min(1),
247
+ unitTypes: z
248
+ .array(unitTypeSchema)
249
+ .min(1)
250
+ .describe('Unit type definitions. Array order determines ID matching priority (first match wins)'),
167
251
  /** 문서 탐색 규칙 (역할별) */
168
252
  docDiscovery: docDiscoverySchema.default(DEFAULT_DOC_DISCOVERY),
169
253
  /** 계획서 파싱 규칙 */
@@ -175,23 +259,21 @@ export const projectConfigSchema = z.object({
175
259
  /** 커맨드 파일 섹션 설정 */
176
260
  commandSections: commandSectionsSchema.prefault({}),
177
261
  /** 기본 특별 요청사항 목록 */
178
- defaultSpecialRequests: z.array(z.string()).default([]),
262
+ defaultSpecialRequests: z
263
+ .array(z.string())
264
+ .default([])
265
+ .describe('Default special request strings appended to every unit context'),
179
266
  /** 유닛 유형별 추가 특별 요청사항 (키: unitType.key) */
180
- specialRequestsByType: z.record(z.string(), z.array(z.string())).default({}),
267
+ specialRequestsByType: z
268
+ .record(z.string(), z.array(z.string()))
269
+ .default({})
270
+ .describe('Additional special requests per unit type (key: unitType.key, value: string array)'),
181
271
  /** 키 기반 선택적 특별 요청사항 (--request 옵션용, 키: 사용자 정의 식별자, 값: 텍스트) */
182
- customRequests: z.record(z.string(), z.string()).default({}),
272
+ customRequests: z
273
+ .record(z.string(), z.string())
274
+ .default({})
275
+ .describe('Named special requests selectable via --request option (key: identifier, value: text)'),
183
276
  });
184
277
  /** 설정 파일명 */
185
278
  export const CONFIG_FILENAME = 'vibe-commander.config.json';
186
- /**
187
- * 프로젝트 설정 스키마를 JSON Schema (Draft 2020-12) 형식으로 반환한다
188
- *
189
- * Zod 4의 z.toJSONSchema() 내장 기능을 활용하여 변환.
190
- * 에이전트가 설정 파일 구조를 런타임에 조회할 수 있도록 한다.
191
- *
192
- * @returns JSON Schema 호환 객체
193
- */
194
- export function getConfigJsonSchema() {
195
- return z.toJSONSchema(projectConfigSchema);
196
- }
197
279
  //# sourceMappingURL=schema.js.map
@@ -12,6 +12,6 @@ export { updateSection, updateField } from './section-updater.js';
12
12
  export type { UpdateResult, MarkerOptions } from './section-updater.js';
13
13
  export { createBeginMarker, createEndMarker, findMarkerRange, isValidSectionKey, wrapWithMarkers, stripMarkers, } from './marker-utils.js';
14
14
  export type { MarkerRange } from './marker-utils.js';
15
- export { COMMAND_REGISTRY, SCHEMA_SUBCOMMANDS, renderCommandsSchema, renderTypesSchema, } from './schema-renderer.js';
15
+ export { COMMAND_REGISTRY, SCHEMA_SUBCOMMANDS, renderConfigSchema, renderCommandsSchema, renderTypesSchema, } from './schema-renderer.js';
16
16
  export type { ArgSchema, FlagSchema, CommandSchema, TypeSchemaEntry, SchemaSubcommandInfo, SchemaResult, } from './schema-renderer.js';
17
17
  //# sourceMappingURL=index.d.ts.map
@@ -16,5 +16,5 @@ export { updateSection, updateField } from './section-updater.js';
16
16
  // 마커 유틸리티
17
17
  export { createBeginMarker, createEndMarker, findMarkerRange, isValidSectionKey, wrapWithMarkers, stripMarkers, } from './marker-utils.js';
18
18
  // 스키마 렌더러
19
- export { COMMAND_REGISTRY, SCHEMA_SUBCOMMANDS, renderCommandsSchema, renderTypesSchema, } from './schema-renderer.js';
19
+ export { COMMAND_REGISTRY, SCHEMA_SUBCOMMANDS, renderConfigSchema, renderCommandsSchema, renderTypesSchema, } from './schema-renderer.js';
20
20
  //# sourceMappingURL=index.js.map
@@ -10,10 +10,12 @@
10
10
  * @module
11
11
  */
12
12
  import { stripCR } from '../parsers/md-utils.js';
13
+ /** HTML 주석 마커의 네임스페이스 접두어 */
14
+ const MARKER_PREFIX = 'vc';
13
15
  /** sectionKey 허용 패턴: 영문 소문자 시작, 소문자+숫자+하이픈 */
14
16
  const SECTION_KEY_RE = /^[a-z][a-z0-9-]*$/;
15
17
  /** 마커 라인 매칭 정규식 */
16
- const MARKER_LINE_RE = /^<!--\s*vc:(begin|end):([a-z][a-z0-9-]*)\s*-->$/;
18
+ const MARKER_LINE_RE = new RegExp(`^<!--\\s*${MARKER_PREFIX}:(begin|end):([a-z][a-z0-9-]*)\\s*-->$`);
17
19
  /**
18
20
  * sectionKey가 유효한지 검증한다
19
21
  *
@@ -28,7 +30,7 @@ export function isValidSectionKey(key) {
28
30
  * @example createBeginMarker('implement') → '<!-- vc:begin:implement -->'
29
31
  */
30
32
  export function createBeginMarker(sectionKey) {
31
- return `<!-- vc:begin:${sectionKey} -->`;
33
+ return `<!-- ${MARKER_PREFIX}:begin:${sectionKey} -->`;
32
34
  }
33
35
  /**
34
36
  * end 마커 문자열을 생성한다
@@ -36,7 +38,7 @@ export function createBeginMarker(sectionKey) {
36
38
  * @example createEndMarker('implement') → '<!-- vc:end:implement -->'
37
39
  */
38
40
  export function createEndMarker(sectionKey) {
39
- return `<!-- vc:end:${sectionKey} -->`;
41
+ return `<!-- ${MARKER_PREFIX}:end:${sectionKey} -->`;
40
42
  }
41
43
  /**
42
44
  * 라인 배열에서 지정된 sectionKey의 마커 범위를 찾는다
@@ -7,6 +7,7 @@
7
7
  *
8
8
  * @module
9
9
  */
10
+ import { z } from 'zod';
10
11
  import type { UnitTypeConfig } from '../../types/index.js';
11
12
  /** CLI 커맨드 인자 스키마 */
12
13
  export interface ArgSchema {
@@ -69,6 +70,21 @@ export type SchemaResult = {
69
70
  export declare const COMMAND_REGISTRY: CommandSchema[];
70
71
  /** schema 서브커맨드 도움말 정보 */
71
72
  export declare const SCHEMA_SUBCOMMANDS: SchemaSubcommandInfo[];
73
+ /**
74
+ * 프로젝트 설정 스키마를 JSON Schema (Draft 2020-12) 형식으로 렌더링한다
75
+ *
76
+ * Zod 4의 z.toJSONSchema() 내장 기능을 활용하여 변환.
77
+ * 에이전트가 설정 파일 구조를 런타임에 조회할 수 있도록 한다.
78
+ *
79
+ * @param schema - 변환할 Zod 스키마
80
+ * @param metadata - 스키마 메타데이터 ($id, title, description)
81
+ * @returns JSON Schema 호환 객체
82
+ */
83
+ export declare function renderConfigSchema(schema: z.ZodType, metadata?: {
84
+ id?: string;
85
+ title?: string;
86
+ description?: string;
87
+ }): Record<string, unknown>;
72
88
  /**
73
89
  * 커맨드 메타데이터를 구조화된 형태로 렌더링한다
74
90
  *
@@ -7,6 +7,7 @@
7
7
  *
8
8
  * @module
9
9
  */
10
+ import { z } from 'zod';
10
11
  // ── 커맨드 레지스트리 (정적 메타데이터) ──
11
12
  const GLOBAL_FLAGS = [
12
13
  { name: '--help', alias: '-h', type: 'boolean', description: '도움말 출력' },
@@ -127,6 +128,26 @@ export const SCHEMA_SUBCOMMANDS = [
127
128
  { name: 'types', description: '현재 프로젝트의 유닛 유형 목록 + ID 패턴 출력' },
128
129
  ];
129
130
  // ── 공개 API ──
131
+ /**
132
+ * 프로젝트 설정 스키마를 JSON Schema (Draft 2020-12) 형식으로 렌더링한다
133
+ *
134
+ * Zod 4의 z.toJSONSchema() 내장 기능을 활용하여 변환.
135
+ * 에이전트가 설정 파일 구조를 런타임에 조회할 수 있도록 한다.
136
+ *
137
+ * @param schema - 변환할 Zod 스키마
138
+ * @param metadata - 스키마 메타데이터 ($id, title, description)
139
+ * @returns JSON Schema 호환 객체
140
+ */
141
+ export function renderConfigSchema(schema, metadata) {
142
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-explicit-any
143
+ const jsonSchema = z.toJSONSchema(schema);
144
+ return {
145
+ ...jsonSchema,
146
+ ...(metadata?.id && { $id: metadata.id }),
147
+ ...(metadata?.title && { title: metadata.title }),
148
+ ...(metadata?.description && { description: metadata.description }),
149
+ };
150
+ }
130
151
  /**
131
152
  * 커맨드 메타데이터를 구조화된 형태로 렌더링한다
132
153
  *
@@ -8,8 +8,6 @@
8
8
  export { resolveDepDocs } from './dep-doc-resolver.js';
9
9
  export type { DepDocPattern } from './dep-doc-resolver.js';
10
10
  export { findDepCommits } from './dep-commit-resolver.js';
11
- export type { CommitEntry } from './dep-commit-resolver.js';
12
11
  export { filterCommitsByChangedFiles, matchesGlobPattern } from './commit-filter.js';
13
- export type { CommitWithFiles, CommitFilterOptions } from './commit-filter.js';
14
12
  export { mergeConfigs, isPlainObject } from './config-merger.js';
15
13
  //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1,73 @@
1
+ {
2
+ "$schema": "https://raw.githubusercontent.com/viilab/vibe-commander/main/schemas/config-schema.json",
3
+ "version": 1,
4
+
5
+ "paths": {
6
+ "commands": ".cursor/context.md",
7
+ "roadmap": "docs/backlog.md",
8
+ "docRoots": {
9
+ "spec": "docs/specs",
10
+ "result": "docs/results"
11
+ },
12
+ "refactorSubDir": null
13
+ },
14
+
15
+ "unitTypes": [
16
+ {
17
+ "key": "feature",
18
+ "displayName": "Feature",
19
+ "idPattern": "^FEAT-\\d+$",
20
+ "planDir": "spec",
21
+ "commandSection": "# Current Feature",
22
+ "collectDeps": true,
23
+ "headerTemplate": "### Feature: {{title}}\n- Spec: @{{planPath}}\n- Latest Commit: -"
24
+ },
25
+ {
26
+ "key": "bugfix",
27
+ "displayName": "Bugfix",
28
+ "idPattern": "^BUG-\\d+$",
29
+ "planDir": "spec",
30
+ "commandSection": "# Current Bugfix",
31
+ "collectDeps": true,
32
+ "headerTemplate": "### Bugfix: {{title}}\n- Spec: @{{planPath}}\n- Latest Commit: -"
33
+ }
34
+ ],
35
+
36
+ "planParsing": {
37
+ "titleSource": "frontmatter:title",
38
+ "dependsSource": "frontmatter",
39
+ "dependsSectionName": null,
40
+ "pairingQuestionSection": "Open Questions"
41
+ },
42
+
43
+ "backlogParsing": {
44
+ "sectionHeader": "## Backlog",
45
+ "entryPattern": "- \\[(?<status>.)\\] (?<id>\\S+) — (?<title>.+?)(?:\\s*\\(deps: (?<deps>[^)]+)\\))?$",
46
+ "completedSection": "### Done",
47
+ "statusMap": {
48
+ "ready": " ",
49
+ "inProgress": "~",
50
+ "completed": "x",
51
+ "blocked": "!"
52
+ }
53
+ },
54
+
55
+ "commitSearch": {
56
+ "strategy": "git-log-grep",
57
+ "extractId": "shortId",
58
+ "maxResults": 3,
59
+ "excludePaths": ["docs/**", "*.md"],
60
+ "requirePaths": ["src/**", "app/**"]
61
+ },
62
+
63
+ "commandSections": {
64
+ "separator": "---",
65
+ "preserveOtherSections": true,
66
+ "useMarkers": false
67
+ },
68
+
69
+ "defaultSpecialRequests": [
70
+ "**Use Next.js App Router patterns**",
71
+ "**Run `pnpm test` before marking complete**"
72
+ ]
73
+ }