@su-record/vibe 3.2.0 → 3.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 (64) hide show
  1. package/README.en.md +3 -2
  2. package/README.md +4 -1
  3. package/dist/cli/design/design-md-parser.test.js +2 -2
  4. package/dist/cli/design/design-md-parser.test.js.map +1 -1
  5. package/dist/cli/setup/Provisioner.d.ts.map +1 -1
  6. package/dist/cli/setup/Provisioner.js +23 -7
  7. package/dist/cli/setup/Provisioner.js.map +1 -1
  8. package/dist/cli/utils/cli-detector.d.ts +3 -3
  9. package/dist/cli/utils/cli-detector.d.ts.map +1 -1
  10. package/dist/cli/utils/cli-detector.js +7 -27
  11. package/dist/cli/utils/cli-detector.js.map +1 -1
  12. package/dist/cli/utils/cli-detector.test.js +3 -2
  13. package/dist/cli/utils/cli-detector.test.js.map +1 -1
  14. package/dist/infra/lib/llm-availability.d.ts.map +1 -1
  15. package/dist/infra/lib/llm-availability.js +2 -10
  16. package/dist/infra/lib/llm-availability.js.map +1 -1
  17. package/dist/infra/lib/llm-availability.test.js +3 -2
  18. package/dist/infra/lib/llm-availability.test.js.map +1 -1
  19. package/dist/infra/lib/utils.d.ts +6 -0
  20. package/dist/infra/lib/utils.d.ts.map +1 -1
  21. package/dist/infra/lib/utils.js +33 -0
  22. package/dist/infra/lib/utils.js.map +1 -1
  23. package/dist/tools/convention/validateCodeQuality.d.ts +1 -0
  24. package/dist/tools/convention/validateCodeQuality.d.ts.map +1 -1
  25. package/dist/tools/convention/validateCodeQuality.js +3 -2
  26. package/dist/tools/convention/validateCodeQuality.js.map +1 -1
  27. package/dist/tools/index.d.ts +2 -2
  28. package/dist/tools/index.d.ts.map +1 -1
  29. package/dist/tools/index.js +2 -0
  30. package/dist/tools/index.js.map +1 -1
  31. package/dist/tools/spec/executionPacket.d.ts +101 -0
  32. package/dist/tools/spec/executionPacket.d.ts.map +1 -0
  33. package/dist/tools/spec/executionPacket.js +394 -0
  34. package/dist/tools/spec/executionPacket.js.map +1 -0
  35. package/dist/tools/spec/executionPacket.test.d.ts +2 -0
  36. package/dist/tools/spec/executionPacket.test.d.ts.map +1 -0
  37. package/dist/tools/spec/executionPacket.test.js +360 -0
  38. package/dist/tools/spec/executionPacket.test.js.map +1 -0
  39. package/dist/tools/spec/index.d.ts +2 -0
  40. package/dist/tools/spec/index.d.ts.map +1 -1
  41. package/dist/tools/spec/index.js +2 -0
  42. package/dist/tools/spec/index.js.map +1 -1
  43. package/dist/tools/spec/specGenerator.d.ts +12 -0
  44. package/dist/tools/spec/specGenerator.d.ts.map +1 -1
  45. package/dist/tools/spec/specGenerator.js +96 -14
  46. package/dist/tools/spec/specGenerator.js.map +1 -1
  47. package/dist/tools/spec/specGenerator.test.d.ts +2 -0
  48. package/dist/tools/spec/specGenerator.test.d.ts.map +1 -0
  49. package/dist/tools/spec/specGenerator.test.js +130 -0
  50. package/dist/tools/spec/specGenerator.test.js.map +1 -0
  51. package/hooks/scripts/__tests__/.vibe/command-log.txt +3 -3
  52. package/hooks/scripts/__tests__/llm-orchestrate-antigravity.test.js +5 -2
  53. package/hooks/scripts/__tests__/run-ledger-verify-required.test.js +7 -2
  54. package/hooks/scripts/__tests__/run-ledger.test.js +161 -10
  55. package/hooks/scripts/__tests__/utils-npm-root.test.js +5 -4
  56. package/hooks/scripts/lib/run-ledger.js +123 -21
  57. package/hooks/scripts/verify-ledger.js +23 -3
  58. package/package.json +1 -1
  59. package/skills/spec/SKILL.md +7 -0
  60. package/skills/vibe.run/SKILL.md +29 -6
  61. package/skills/vibe.trace/SKILL.md +3 -3
  62. package/skills/vibe.verify/SKILL.md +10 -4
  63. package/vibe/rules/loop-contract.md +7 -3
  64. package/vibe/templates/spec-template.md +32 -5
@@ -0,0 +1,360 @@
1
+ import { describe, expect, it } from 'vitest';
2
+ import fs from 'fs';
3
+ import os from 'os';
4
+ import path from 'path';
5
+ import { compileExecutionPacket, validateExecutionPacket, writeExecutionPacket, } from './executionPacket.js';
6
+ const canonicalSpec = `# SPEC: Example
7
+
8
+ ## Context Sources
9
+ - docs/prd.md
10
+
11
+ ## Assumptions
12
+ - PostgreSQL 16 is available
13
+
14
+ ## Constraints
15
+ - Preserve backward compatibility
16
+ - Do not expose secrets
17
+
18
+ ## Requirements
19
+
20
+ | ID | Requirement | Done Criteria |
21
+ |----|-------------|---------------|
22
+ | REQ-example-001 | Build remains valid | D1 |
23
+ | REQ-example-002 | Tests remain valid | D2 |
24
+
25
+ ## Done Criteria (deterministic gates)
26
+
27
+ | # | Criterion | Verified by |
28
+ |---|-----------|-------------|
29
+ | D1 | Build succeeds | npm run build exit 0 |
30
+ | D2 | Tests pass | npm test exit 0 |
31
+
32
+ ### Evidence Required
33
+ - D1 → build command result
34
+ - D2 → test command result
35
+ `;
36
+ function input(overrides = {}) {
37
+ return {
38
+ canonicalSpec,
39
+ canonicalSpecPath: '.vibe/specs/example.md',
40
+ profile: 'codex',
41
+ ...overrides,
42
+ };
43
+ }
44
+ describe('Execution Packet Compiler', () => {
45
+ it('동일 입력은 source/hash와 계약을 보존한 byte-identical packet을 생성', () => {
46
+ const first = compileExecutionPacket(input());
47
+ const second = compileExecutionPacket(input());
48
+ expect(first.ok).toBe(true);
49
+ expect(second).toEqual(first);
50
+ if (!first.ok)
51
+ return;
52
+ expect(JSON.stringify(second)).toBe(JSON.stringify(first));
53
+ expect(first.packet.canonicalSpecHash).toMatch(/^[a-f0-9]{64}$/);
54
+ expect(first.packet.requirements.map(item => item.id))
55
+ .toEqual(['REQ-example-001', 'REQ-example-002']);
56
+ expect(first.packet.doneCriteria.map(item => item.id)).toEqual(['D1', 'D2']);
57
+ expect(first.packet.evidenceRequired.map(item => item.criterionId))
58
+ .toEqual(['D1', 'D2']);
59
+ expect(first.packet.constraints).toEqual([
60
+ 'Preserve backward compatibility',
61
+ 'Do not expose secrets',
62
+ ]);
63
+ expect(first.packet.sourcePointers).toContainEqual({
64
+ id: 'D1',
65
+ path: '.vibe/specs/example.md',
66
+ line: 24,
67
+ });
68
+ expect(first.audit.preservedCriterionIds).toEqual(['D1', 'D2']);
69
+ });
70
+ it('Codex와 Claude Code 프로파일은 동일한 핵심 계약을 보존', () => {
71
+ const codex = compileExecutionPacket(input({ profile: 'codex' }));
72
+ const claude = compileExecutionPacket(input({ profile: 'claude-code' }));
73
+ expect(codex.ok).toBe(true);
74
+ expect(claude.ok).toBe(true);
75
+ if (!codex.ok || !claude.ok)
76
+ return;
77
+ expect(codex.packet.profile).not.toBe(claude.packet.profile);
78
+ expect(codex.packet.contextBudget).not.toBe(claude.packet.contextBudget);
79
+ expect(codex.packet.requirements).toEqual(claude.packet.requirements);
80
+ expect(codex.packet.constraints).toEqual(claude.packet.constraints);
81
+ expect(codex.packet.doneCriteria).toEqual(claude.packet.doneCriteria);
82
+ expect(codex.packet.evidenceRequired).toEqual(claude.packet.evidenceRequired);
83
+ expect(codex.packet.isolationPolicy).toEqual({
84
+ reloadPerScenario: true,
85
+ includeExplorationLogs: false,
86
+ stateSource: 'disk',
87
+ });
88
+ });
89
+ it('누락된 evidence를 오류 코드와 원본 위치로 보고하고 packet을 생성하지 않음', () => {
90
+ const result = compileExecutionPacket(input({
91
+ canonicalSpec: canonicalSpec.replace('- D2 → test command result\n', ''),
92
+ }));
93
+ expect(result.ok).toBe(false);
94
+ if (result.ok)
95
+ return;
96
+ expect(result.errors).toContainEqual({
97
+ code: 'MISSING_EVIDENCE',
98
+ message: 'Missing evidence: D2',
99
+ sourceId: 'D2',
100
+ sourcePointer: { path: '.vibe/specs/example.md', line: 25 },
101
+ });
102
+ expect(result).not.toHaveProperty('packet');
103
+ });
104
+ it('알 수 없는 criterion 선택과 evidence 참조를 거부', () => {
105
+ const unknownSelection = compileExecutionPacket(input({
106
+ selectedRequirementIds: ['REQ-example-999'],
107
+ }));
108
+ const unknownEvidence = compileExecutionPacket(input({
109
+ canonicalSpec: `${canonicalSpec}- D9 → unknown proof\n`,
110
+ }));
111
+ expect(unknownSelection.ok).toBe(false);
112
+ expect(unknownEvidence.ok).toBe(false);
113
+ if (!unknownSelection.ok) {
114
+ expect(unknownSelection.errors.map(error => error.code))
115
+ .toContain('UNKNOWN_REQUIREMENT_ID');
116
+ }
117
+ if (!unknownEvidence.ok) {
118
+ expect(unknownEvidence.errors.map(error => error.code))
119
+ .toContain('UNKNOWN_EVIDENCE_ID');
120
+ }
121
+ });
122
+ it('빈 requirement 선택과 알 수 없는 Done Criterion 매핑을 거부', () => {
123
+ const empty = compileExecutionPacket(input({ selectedRequirementIds: [] }));
124
+ const invalidMapping = compileExecutionPacket(input({
125
+ canonicalSpec: canonicalSpec.replace('| D1 |', '| D9 |'),
126
+ }));
127
+ expect(empty).toMatchObject({
128
+ ok: false,
129
+ errors: [{ code: 'EMPTY_SELECTION' }],
130
+ });
131
+ expect(invalidMapping.ok).toBe(false);
132
+ if (!invalidMapping.ok) {
133
+ expect(invalidMapping.errors.map(error => error.code))
134
+ .toContain('INVALID_REQUIREMENT_MAPPING');
135
+ }
136
+ });
137
+ it('어떤 requirement에도 매핑되지 않은 Done Criterion을 거부', () => {
138
+ const orphaned = canonicalSpec.replace('| REQ-example-002 | Tests remain valid | D2 |\n', '');
139
+ expect(compileExecutionPacket(input({ canonicalSpec: orphaned })))
140
+ .toMatchObject({
141
+ ok: false,
142
+ errors: [{ code: 'INVALID_REQUIREMENT_MAPPING', sourceId: 'D2' }],
143
+ });
144
+ });
145
+ it('Done Criteria 밖의 D 행은 계약 기준으로 인정하지 않음', () => {
146
+ const misplaced = canonicalSpec.replace('## Done Criteria', '## Unrelated Table');
147
+ expect(compileExecutionPacket(input({ canonicalSpec: misplaced }))).toEqual({
148
+ ok: false,
149
+ errors: [{ code: 'MISSING_DONE_CRITERIA', message: 'No contract criteria found' }],
150
+ });
151
+ });
152
+ it('profile 필수 Constraints 섹션 누락을 차단', () => {
153
+ const withoutConstraints = canonicalSpec.replace(/## Constraints[\s\S]*?(?=## Done Criteria)/, '');
154
+ const result = compileExecutionPacket(input({ canonicalSpec: withoutConstraints }));
155
+ expect(result).toEqual({
156
+ ok: false,
157
+ errors: [{
158
+ code: 'MISSING_REQUIRED_SECTION',
159
+ message: 'Constraints section is required',
160
+ }],
161
+ });
162
+ });
163
+ it('지원하지 않는 runtime profile을 구조화된 오류로 거부', () => {
164
+ const result = Reflect.apply(compileExecutionPacket, undefined, [{
165
+ ...input(),
166
+ profile: 'unknown',
167
+ }]);
168
+ expect(result).toEqual({
169
+ ok: false,
170
+ errors: [{ code: 'INVALID_PROFILE', message: 'Unsupported profile: unknown' }],
171
+ });
172
+ });
173
+ it('반환 packet 변경이 다음 컴파일의 profile 결정성을 오염시키지 않음', () => {
174
+ const first = compileExecutionPacket(input());
175
+ expect(first.ok).toBe(true);
176
+ if (!first.ok)
177
+ return;
178
+ first.packet.isolationPolicy.reloadPerScenario = false;
179
+ const second = compileExecutionPacket(input());
180
+ expect(second.ok).toBe(true);
181
+ if (!second.ok)
182
+ return;
183
+ expect(second.packet.isolationPolicy.reloadPerScenario).toBe(true);
184
+ });
185
+ it('context budget 초과는 문자열 절단 없이 구조화된 오류를 반환', () => {
186
+ const oversizedConstraint = `- ${'x'.repeat(25_000)}`;
187
+ const oversizedSpec = canonicalSpec.replace('- Do not expose secrets', `- Do not expose secrets\n${oversizedConstraint}`);
188
+ const result = compileExecutionPacket(input({ canonicalSpec: oversizedSpec }));
189
+ expect(result).toEqual({
190
+ ok: false,
191
+ errors: [{
192
+ code: 'BUDGET_EXCEEDED',
193
+ message: 'Packet exceeds 24000 characters',
194
+ }],
195
+ });
196
+ expect(result).not.toHaveProperty('packet');
197
+ });
198
+ it('packet 파일을 원자 기록하고 원본 SPEC 변경 시 stale로 판정', () => {
199
+ const projectPath = fs.mkdtempSync(path.join(os.tmpdir(), 'vibe-packet-'));
200
+ const specPath = '.vibe/specs/example.md';
201
+ const absoluteSpecPath = path.join(projectPath, specPath);
202
+ fs.mkdirSync(path.dirname(absoluteSpecPath), { recursive: true });
203
+ fs.writeFileSync(absoluteSpecPath, canonicalSpec);
204
+ try {
205
+ const written = writeExecutionPacket({ projectPath, specPath, profile: 'codex' });
206
+ expect(written.ok).toBe(true);
207
+ if (!written.ok)
208
+ return;
209
+ expect(written.packetPath).toBe('.vibe/packets/example/codex.json');
210
+ expect(fs.existsSync(path.join(projectPath, written.packetPath))).toBe(true);
211
+ expect(validateExecutionPacket({
212
+ projectPath,
213
+ specPath,
214
+ packetPath: written.packetPath,
215
+ })).toMatchObject({ valid: true });
216
+ fs.appendFileSync(absoluteSpecPath, '\n<!-- changed -->\n');
217
+ expect(validateExecutionPacket({
218
+ projectPath,
219
+ specPath,
220
+ packetPath: written.packetPath,
221
+ })).toEqual({
222
+ valid: false,
223
+ code: 'STALE_PACKET',
224
+ message: 'Execution packet does not match the current canonical SPEC',
225
+ });
226
+ }
227
+ finally {
228
+ fs.rmSync(projectPath, { recursive: true, force: true });
229
+ }
230
+ });
231
+ it('packet 디렉터리의 symbolic link를 통한 project 외부 쓰기를 거부', () => {
232
+ const projectPath = fs.mkdtempSync(path.join(os.tmpdir(), 'vibe-packet-project-'));
233
+ const outsidePath = fs.mkdtempSync(path.join(os.tmpdir(), 'vibe-packet-outside-'));
234
+ const specPath = '.vibe/specs/example.md';
235
+ const absoluteSpecPath = path.join(projectPath, specPath);
236
+ fs.mkdirSync(path.dirname(absoluteSpecPath), { recursive: true });
237
+ fs.writeFileSync(absoluteSpecPath, canonicalSpec);
238
+ fs.symlinkSync(outsidePath, path.join(projectPath, '.vibe', 'packets'));
239
+ try {
240
+ expect(writeExecutionPacket({ projectPath, specPath, profile: 'codex' }))
241
+ .toEqual({
242
+ ok: false,
243
+ errors: [{
244
+ code: 'INVALID_PATH',
245
+ message: 'Execution packet path contains a symbolic link',
246
+ }],
247
+ });
248
+ expect(fs.readdirSync(outsidePath)).toEqual([]);
249
+ }
250
+ finally {
251
+ fs.rmSync(projectPath, { recursive: true, force: true });
252
+ fs.rmSync(outsidePath, { recursive: true, force: true });
253
+ }
254
+ });
255
+ it('packet identity가 요청 SPEC과 다르거나 허용 경로 밖이면 거부', () => {
256
+ const projectPath = fs.mkdtempSync(path.join(os.tmpdir(), 'vibe-packet-identity-'));
257
+ const specPath = '.vibe/specs/example.md';
258
+ const absoluteSpecPath = path.join(projectPath, specPath);
259
+ fs.mkdirSync(path.dirname(absoluteSpecPath), { recursive: true });
260
+ fs.writeFileSync(absoluteSpecPath, canonicalSpec);
261
+ try {
262
+ const written = writeExecutionPacket({ projectPath, specPath, profile: 'codex' });
263
+ expect(written.ok).toBe(true);
264
+ if (!written.ok)
265
+ return;
266
+ expect(validateExecutionPacket({
267
+ projectPath,
268
+ specPath: '.vibe/specs/different.md',
269
+ packetPath: written.packetPath,
270
+ })).toMatchObject({ valid: false, code: 'INVALID_PACKET' });
271
+ expect(validateExecutionPacket({
272
+ projectPath,
273
+ specPath,
274
+ packetPath: '.vibe/specs/example.md',
275
+ })).toMatchObject({ valid: false, code: 'INVALID_PACKET' });
276
+ }
277
+ finally {
278
+ fs.rmSync(projectPath, { recursive: true, force: true });
279
+ }
280
+ });
281
+ it('저장된 packet 계약 본문 변조를 canonical 재컴파일로 거부', () => {
282
+ const projectPath = fs.mkdtempSync(path.join(os.tmpdir(), 'vibe-packet-tamper-'));
283
+ const specPath = '.vibe/specs/example.md';
284
+ const absoluteSpecPath = path.join(projectPath, specPath);
285
+ fs.mkdirSync(path.dirname(absoluteSpecPath), { recursive: true });
286
+ fs.writeFileSync(absoluteSpecPath, canonicalSpec);
287
+ try {
288
+ const written = writeExecutionPacket({ projectPath, specPath, profile: 'codex' });
289
+ expect(written.ok).toBe(true);
290
+ if (!written.ok)
291
+ return;
292
+ const packetFile = path.join(projectPath, written.packetPath);
293
+ fs.writeFileSync(packetFile, JSON.stringify({ ...written.packet, constraints: [] }));
294
+ expect(validateExecutionPacket({
295
+ projectPath,
296
+ specPath,
297
+ packetPath: written.packetPath,
298
+ })).toMatchObject({ valid: false, code: 'INVALID_PACKET' });
299
+ }
300
+ finally {
301
+ fs.rmSync(projectPath, { recursive: true, force: true });
302
+ }
303
+ });
304
+ it('호출자가 승인하지 않은 requirement subset packet을 거부', () => {
305
+ const projectPath = fs.mkdtempSync(path.join(os.tmpdir(), 'vibe-packet-subset-'));
306
+ const specPath = '.vibe/specs/example.md';
307
+ const absoluteSpecPath = path.join(projectPath, specPath);
308
+ fs.mkdirSync(path.dirname(absoluteSpecPath), { recursive: true });
309
+ fs.writeFileSync(absoluteSpecPath, canonicalSpec);
310
+ try {
311
+ const written = writeExecutionPacket({
312
+ projectPath,
313
+ specPath,
314
+ profile: 'codex',
315
+ selectedRequirementIds: ['REQ-example-001'],
316
+ });
317
+ expect(written.ok).toBe(true);
318
+ if (!written.ok)
319
+ return;
320
+ expect(validateExecutionPacket({
321
+ projectPath,
322
+ specPath,
323
+ packetPath: written.packetPath,
324
+ })).toMatchObject({ valid: false, code: 'INVALID_PACKET' });
325
+ expect(validateExecutionPacket({
326
+ projectPath,
327
+ specPath,
328
+ packetPath: written.packetPath,
329
+ selectedRequirementIds: ['REQ-example-001'],
330
+ })).toEqual({ valid: true });
331
+ }
332
+ finally {
333
+ fs.rmSync(projectPath, { recursive: true, force: true });
334
+ }
335
+ });
336
+ it('symbolic link SPEC을 통한 project 외부 읽기를 거부', () => {
337
+ const projectPath = fs.mkdtempSync(path.join(os.tmpdir(), 'vibe-spec-project-'));
338
+ const outsidePath = fs.mkdtempSync(path.join(os.tmpdir(), 'vibe-spec-outside-'));
339
+ const specPath = '.vibe/specs/example.md';
340
+ const outsideSpec = path.join(outsidePath, 'example.md');
341
+ fs.mkdirSync(path.join(projectPath, '.vibe', 'specs'), { recursive: true });
342
+ fs.writeFileSync(outsideSpec, canonicalSpec);
343
+ fs.symlinkSync(outsideSpec, path.join(projectPath, specPath));
344
+ try {
345
+ expect(writeExecutionPacket({ projectPath, specPath, profile: 'codex' }))
346
+ .toMatchObject({ ok: false, errors: [{ code: 'INVALID_PATH' }] });
347
+ }
348
+ finally {
349
+ fs.rmSync(projectPath, { recursive: true, force: true });
350
+ fs.rmSync(outsidePath, { recursive: true, force: true });
351
+ }
352
+ });
353
+ it('vibe.run 계약은 packet 생성과 stale 거부를 명시', () => {
354
+ const skill = fs.readFileSync(path.join(process.cwd(), 'skills', 'vibe.run', 'SKILL.md'), 'utf-8');
355
+ expect(skill).toContain('writeExecutionPacket');
356
+ expect(skill).toContain('validateExecutionPacket');
357
+ expect(skill).toContain('STALE_PACKET');
358
+ });
359
+ });
360
+ //# sourceMappingURL=executionPacket.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"executionPacket.test.js","sourceRoot":"","sources":["../../../src/tools/spec/executionPacket.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EACL,sBAAsB,EACtB,uBAAuB,EACvB,oBAAoB,GAErB,MAAM,sBAAsB,CAAC;AAE9B,MAAM,aAAa,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA6BrB,CAAC;AAEF,SAAS,KAAK,CACZ,YAAkD,EAAE;IAEpD,OAAO;QACL,aAAa;QACb,iBAAiB,EAAE,wBAAwB;QAC3C,OAAO,EAAE,OAAO;QAChB,GAAG,SAAS;KACb,CAAC;AACJ,CAAC;AAED,QAAQ,CAAC,2BAA2B,EAAE,GAAG,EAAE;IACzC,EAAE,CAAC,uDAAuD,EAAE,GAAG,EAAE;QAC/D,MAAM,KAAK,GAAG,sBAAsB,CAAC,KAAK,EAAE,CAAC,CAAC;QAC9C,MAAM,MAAM,GAAG,sBAAsB,CAAC,KAAK,EAAE,CAAC,CAAC;QAE/C,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC5B,MAAM,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;QAC9B,IAAI,CAAC,KAAK,CAAC,EAAE;YAAE,OAAO;QACtB,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC;QAC3D,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,iBAAiB,CAAC,CAAC,OAAO,CAAC,gBAAgB,CAAC,CAAC;QACjE,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,YAAY,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;aACnD,OAAO,CAAC,CAAC,iBAAiB,EAAE,iBAAiB,CAAC,CAAC,CAAC;QACnD,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,YAAY,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC;QAC7E,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,gBAAgB,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;aAChE,OAAO,CAAC,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC;QACzB,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,OAAO,CAAC;YACvC,iCAAiC;YACjC,uBAAuB;SACxB,CAAC,CAAC;QACH,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC,cAAc,CAAC;YACjD,EAAE,EAAE,IAAI;YACR,IAAI,EAAE,wBAAwB;YAC9B,IAAI,EAAE,EAAE;SACT,CAAC,CAAC;QACH,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,qBAAqB,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC;IAClE,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,wCAAwC,EAAE,GAAG,EAAE;QAChD,MAAM,KAAK,GAAG,sBAAsB,CAAC,KAAK,CAAC,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC;QAClE,MAAM,MAAM,GAAG,sBAAsB,CAAC,KAAK,CAAC,EAAE,OAAO,EAAE,aAAa,EAAE,CAAC,CAAC,CAAC;QAEzE,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC5B,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC7B,IAAI,CAAC,KAAK,CAAC,EAAE,IAAI,CAAC,MAAM,CAAC,EAAE;YAAE,OAAO;QACpC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QAC7D,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC;QACzE,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC;QACtE,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;QACpE,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC;QACtE,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,gBAAgB,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,gBAAgB,CAAC,CAAC;QAC9E,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,eAAe,CAAC,CAAC,OAAO,CAAC;YAC3C,iBAAiB,EAAE,IAAI;YACvB,sBAAsB,EAAE,KAAK;YAC7B,WAAW,EAAE,MAAM;SACpB,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,kDAAkD,EAAE,GAAG,EAAE;QAC1D,MAAM,MAAM,GAAG,sBAAsB,CAAC,KAAK,CAAC;YAC1C,aAAa,EAAE,aAAa,CAAC,OAAO,CAAC,8BAA8B,EAAE,EAAE,CAAC;SACzE,CAAC,CAAC,CAAC;QAEJ,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC9B,IAAI,MAAM,CAAC,EAAE;YAAE,OAAO;QACtB,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,cAAc,CAAC;YACnC,IAAI,EAAE,kBAAkB;YACxB,OAAO,EAAE,sBAAsB;YAC/B,QAAQ,EAAE,IAAI;YACd,aAAa,EAAE,EAAE,IAAI,EAAE,wBAAwB,EAAE,IAAI,EAAE,EAAE,EAAE;SAC5D,CAAC,CAAC;QACH,MAAM,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,cAAc,CAAC,QAAQ,CAAC,CAAC;IAC9C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,sCAAsC,EAAE,GAAG,EAAE;QAC9C,MAAM,gBAAgB,GAAG,sBAAsB,CAAC,KAAK,CAAC;YACpD,sBAAsB,EAAE,CAAC,iBAAiB,CAAC;SAC5C,CAAC,CAAC,CAAC;QACJ,MAAM,eAAe,GAAG,sBAAsB,CAAC,KAAK,CAAC;YACnD,aAAa,EAAE,GAAG,aAAa,wBAAwB;SACxD,CAAC,CAAC,CAAC;QAEJ,MAAM,CAAC,gBAAgB,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACxC,MAAM,CAAC,eAAe,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACvC,IAAI,CAAC,gBAAgB,CAAC,EAAE,EAAE,CAAC;YACzB,MAAM,CAAC,gBAAgB,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;iBACrD,SAAS,CAAC,wBAAwB,CAAC,CAAC;QACzC,CAAC;QACD,IAAI,CAAC,eAAe,CAAC,EAAE,EAAE,CAAC;YACxB,MAAM,CAAC,eAAe,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;iBACpD,SAAS,CAAC,qBAAqB,CAAC,CAAC;QACtC,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,gDAAgD,EAAE,GAAG,EAAE;QACxD,MAAM,KAAK,GAAG,sBAAsB,CAAC,KAAK,CAAC,EAAE,sBAAsB,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC;QAC5E,MAAM,cAAc,GAAG,sBAAsB,CAAC,KAAK,CAAC;YAClD,aAAa,EAAE,aAAa,CAAC,OAAO,CAAC,QAAQ,EAAE,QAAQ,CAAC;SACzD,CAAC,CAAC,CAAC;QAEJ,MAAM,CAAC,KAAK,CAAC,CAAC,aAAa,CAAC;YAC1B,EAAE,EAAE,KAAK;YACT,MAAM,EAAE,CAAC,EAAE,IAAI,EAAE,iBAAiB,EAAE,CAAC;SACtC,CAAC,CAAC;QACH,MAAM,CAAC,cAAc,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACtC,IAAI,CAAC,cAAc,CAAC,EAAE,EAAE,CAAC;YACvB,MAAM,CAAC,cAAc,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;iBACnD,SAAS,CAAC,6BAA6B,CAAC,CAAC;QAC9C,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,6CAA6C,EAAE,GAAG,EAAE;QACrD,MAAM,QAAQ,GAAG,aAAa,CAAC,OAAO,CAAC,iDAAiD,EAAE,EAAE,CAAC,CAAC;QAC9F,MAAM,CAAC,sBAAsB,CAAC,KAAK,CAAC,EAAE,aAAa,EAAE,QAAQ,EAAE,CAAC,CAAC,CAAC;aAC/D,aAAa,CAAC;YACb,EAAE,EAAE,KAAK;YACT,MAAM,EAAE,CAAC,EAAE,IAAI,EAAE,6BAA6B,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;SAClE,CAAC,CAAC;IACP,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,uCAAuC,EAAE,GAAG,EAAE;QAC/C,MAAM,SAAS,GAAG,aAAa,CAAC,OAAO,CAAC,kBAAkB,EAAE,oBAAoB,CAAC,CAAC;QAClF,MAAM,CAAC,sBAAsB,CAAC,KAAK,CAAC,EAAE,aAAa,EAAE,SAAS,EAAE,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC;YAC1E,EAAE,EAAE,KAAK;YACT,MAAM,EAAE,CAAC,EAAE,IAAI,EAAE,uBAAuB,EAAE,OAAO,EAAE,4BAA4B,EAAE,CAAC;SACnF,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,kCAAkC,EAAE,GAAG,EAAE;QAC1C,MAAM,kBAAkB,GAAG,aAAa,CAAC,OAAO,CAC9C,4CAA4C,EAC5C,EAAE,CACH,CAAC;QACF,MAAM,MAAM,GAAG,sBAAsB,CAAC,KAAK,CAAC,EAAE,aAAa,EAAE,kBAAkB,EAAE,CAAC,CAAC,CAAC;QAEpF,MAAM,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC;YACrB,EAAE,EAAE,KAAK;YACT,MAAM,EAAE,CAAC;oBACP,IAAI,EAAE,0BAA0B;oBAChC,OAAO,EAAE,iCAAiC;iBAC3C,CAAC;SACH,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,sCAAsC,EAAE,GAAG,EAAE;QAC9C,MAAM,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC,sBAAsB,EAAE,SAAS,EAAE,CAAC;gBAC/D,GAAG,KAAK,EAAE;gBACV,OAAO,EAAE,SAAS;aACnB,CAAC,CAAC,CAAC;QACJ,MAAM,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC;YACrB,EAAE,EAAE,KAAK;YACT,MAAM,EAAE,CAAC,EAAE,IAAI,EAAE,iBAAiB,EAAE,OAAO,EAAE,8BAA8B,EAAE,CAAC;SAC/E,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,6CAA6C,EAAE,GAAG,EAAE;QACrD,MAAM,KAAK,GAAG,sBAAsB,CAAC,KAAK,EAAE,CAAC,CAAC;QAC9C,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC5B,IAAI,CAAC,KAAK,CAAC,EAAE;YAAE,OAAO;QACtB,KAAK,CAAC,MAAM,CAAC,eAAe,CAAC,iBAAiB,GAAG,KAAK,CAAC;QAEvD,MAAM,MAAM,GAAG,sBAAsB,CAAC,KAAK,EAAE,CAAC,CAAC;QAC/C,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC7B,IAAI,CAAC,MAAM,CAAC,EAAE;YAAE,OAAO;QACvB,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,eAAe,CAAC,iBAAiB,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACrE,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,0CAA0C,EAAE,GAAG,EAAE;QAClD,MAAM,mBAAmB,GAAG,KAAK,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC;QACtD,MAAM,aAAa,GAAG,aAAa,CAAC,OAAO,CACzC,yBAAyB,EACzB,4BAA4B,mBAAmB,EAAE,CAClD,CAAC;QACF,MAAM,MAAM,GAAG,sBAAsB,CAAC,KAAK,CAAC,EAAE,aAAa,EAAE,aAAa,EAAE,CAAC,CAAC,CAAC;QAE/E,MAAM,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC;YACrB,EAAE,EAAE,KAAK;YACT,MAAM,EAAE,CAAC;oBACP,IAAI,EAAE,iBAAiB;oBACvB,OAAO,EAAE,iCAAiC;iBAC3C,CAAC;SACH,CAAC,CAAC;QACH,MAAM,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,cAAc,CAAC,QAAQ,CAAC,CAAC;IAC9C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,2CAA2C,EAAE,GAAG,EAAE;QACnD,MAAM,WAAW,GAAG,EAAE,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE,cAAc,CAAC,CAAC,CAAC;QAC3E,MAAM,QAAQ,GAAG,wBAAwB,CAAC;QAC1C,MAAM,gBAAgB,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAC;QAC1D,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,gBAAgB,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAClE,EAAE,CAAC,aAAa,CAAC,gBAAgB,EAAE,aAAa,CAAC,CAAC;QAElD,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,oBAAoB,CAAC,EAAE,WAAW,EAAE,QAAQ,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC,CAAC;YAClF,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAC9B,IAAI,CAAC,OAAO,CAAC,EAAE;gBAAE,OAAO;YACxB,MAAM,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,kCAAkC,CAAC,CAAC;YACpE,MAAM,CAAC,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAC7E,MAAM,CAAC,uBAAuB,CAAC;gBAC7B,WAAW;gBACX,QAAQ;gBACR,UAAU,EAAE,OAAO,CAAC,UAAU;aAC/B,CAAC,CAAC,CAAC,aAAa,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;YAEnC,EAAE,CAAC,cAAc,CAAC,gBAAgB,EAAE,sBAAsB,CAAC,CAAC;YAC5D,MAAM,CAAC,uBAAuB,CAAC;gBAC7B,WAAW;gBACX,QAAQ;gBACR,UAAU,EAAE,OAAO,CAAC,UAAU;aAC/B,CAAC,CAAC,CAAC,OAAO,CAAC;gBACV,KAAK,EAAE,KAAK;gBACZ,IAAI,EAAE,cAAc;gBACpB,OAAO,EAAE,4DAA4D;aACtE,CAAC,CAAC;QACL,CAAC;gBAAS,CAAC;YACT,EAAE,CAAC,MAAM,CAAC,WAAW,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;QAC3D,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,kDAAkD,EAAE,GAAG,EAAE;QAC1D,MAAM,WAAW,GAAG,EAAE,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE,sBAAsB,CAAC,CAAC,CAAC;QACnF,MAAM,WAAW,GAAG,EAAE,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE,sBAAsB,CAAC,CAAC,CAAC;QACnF,MAAM,QAAQ,GAAG,wBAAwB,CAAC;QAC1C,MAAM,gBAAgB,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAC;QAC1D,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,gBAAgB,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAClE,EAAE,CAAC,aAAa,CAAC,gBAAgB,EAAE,aAAa,CAAC,CAAC;QAClD,EAAE,CAAC,WAAW,CAAC,WAAW,EAAE,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,OAAO,EAAE,SAAS,CAAC,CAAC,CAAC;QAExE,IAAI,CAAC;YACH,MAAM,CAAC,oBAAoB,CAAC,EAAE,WAAW,EAAE,QAAQ,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC,CAAC;iBACtE,OAAO,CAAC;gBACP,EAAE,EAAE,KAAK;gBACT,MAAM,EAAE,CAAC;wBACP,IAAI,EAAE,cAAc;wBACpB,OAAO,EAAE,gDAAgD;qBAC1D,CAAC;aACH,CAAC,CAAC;YACL,MAAM,CAAC,EAAE,CAAC,WAAW,CAAC,WAAW,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;QAClD,CAAC;gBAAS,CAAC;YACT,EAAE,CAAC,MAAM,CAAC,WAAW,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;YACzD,EAAE,CAAC,MAAM,CAAC,WAAW,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;QAC3D,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,6CAA6C,EAAE,GAAG,EAAE;QACrD,MAAM,WAAW,GAAG,EAAE,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE,uBAAuB,CAAC,CAAC,CAAC;QACpF,MAAM,QAAQ,GAAG,wBAAwB,CAAC;QAC1C,MAAM,gBAAgB,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAC;QAC1D,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,gBAAgB,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAClE,EAAE,CAAC,aAAa,CAAC,gBAAgB,EAAE,aAAa,CAAC,CAAC;QAElD,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,oBAAoB,CAAC,EAAE,WAAW,EAAE,QAAQ,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC,CAAC;YAClF,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAC9B,IAAI,CAAC,OAAO,CAAC,EAAE;gBAAE,OAAO;YACxB,MAAM,CAAC,uBAAuB,CAAC;gBAC7B,WAAW;gBACX,QAAQ,EAAE,0BAA0B;gBACpC,UAAU,EAAE,OAAO,CAAC,UAAU;aAC/B,CAAC,CAAC,CAAC,aAAa,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,gBAAgB,EAAE,CAAC,CAAC;YAC5D,MAAM,CAAC,uBAAuB,CAAC;gBAC7B,WAAW;gBACX,QAAQ;gBACR,UAAU,EAAE,wBAAwB;aACrC,CAAC,CAAC,CAAC,aAAa,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,gBAAgB,EAAE,CAAC,CAAC;QAC9D,CAAC;gBAAS,CAAC;YACT,EAAE,CAAC,MAAM,CAAC,WAAW,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;QAC3D,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,yCAAyC,EAAE,GAAG,EAAE;QACjD,MAAM,WAAW,GAAG,EAAE,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE,qBAAqB,CAAC,CAAC,CAAC;QAClF,MAAM,QAAQ,GAAG,wBAAwB,CAAC;QAC1C,MAAM,gBAAgB,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAC;QAC1D,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,gBAAgB,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAClE,EAAE,CAAC,aAAa,CAAC,gBAAgB,EAAE,aAAa,CAAC,CAAC;QAElD,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,oBAAoB,CAAC,EAAE,WAAW,EAAE,QAAQ,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC,CAAC;YAClF,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAC9B,IAAI,CAAC,OAAO,CAAC,EAAE;gBAAE,OAAO;YACxB,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,OAAO,CAAC,UAAU,CAAC,CAAC;YAC9D,EAAE,CAAC,aAAa,CAAC,UAAU,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,GAAG,OAAO,CAAC,MAAM,EAAE,WAAW,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC;YACrF,MAAM,CAAC,uBAAuB,CAAC;gBAC7B,WAAW;gBACX,QAAQ;gBACR,UAAU,EAAE,OAAO,CAAC,UAAU;aAC/B,CAAC,CAAC,CAAC,aAAa,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,gBAAgB,EAAE,CAAC,CAAC;QAC9D,CAAC;gBAAS,CAAC;YACT,EAAE,CAAC,MAAM,CAAC,WAAW,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;QAC3D,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,4CAA4C,EAAE,GAAG,EAAE;QACpD,MAAM,WAAW,GAAG,EAAE,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE,qBAAqB,CAAC,CAAC,CAAC;QAClF,MAAM,QAAQ,GAAG,wBAAwB,CAAC;QAC1C,MAAM,gBAAgB,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAC;QAC1D,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,gBAAgB,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAClE,EAAE,CAAC,aAAa,CAAC,gBAAgB,EAAE,aAAa,CAAC,CAAC;QAElD,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,oBAAoB,CAAC;gBACnC,WAAW;gBACX,QAAQ;gBACR,OAAO,EAAE,OAAO;gBAChB,sBAAsB,EAAE,CAAC,iBAAiB,CAAC;aAC5C,CAAC,CAAC;YACH,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAC9B,IAAI,CAAC,OAAO,CAAC,EAAE;gBAAE,OAAO;YACxB,MAAM,CAAC,uBAAuB,CAAC;gBAC7B,WAAW;gBACX,QAAQ;gBACR,UAAU,EAAE,OAAO,CAAC,UAAU;aAC/B,CAAC,CAAC,CAAC,aAAa,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,gBAAgB,EAAE,CAAC,CAAC;YAC5D,MAAM,CAAC,uBAAuB,CAAC;gBAC7B,WAAW;gBACX,QAAQ;gBACR,UAAU,EAAE,OAAO,CAAC,UAAU;gBAC9B,sBAAsB,EAAE,CAAC,iBAAiB,CAAC;aAC5C,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;QAC/B,CAAC;gBAAS,CAAC;YACT,EAAE,CAAC,MAAM,CAAC,WAAW,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;QAC3D,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,0CAA0C,EAAE,GAAG,EAAE;QAClD,MAAM,WAAW,GAAG,EAAE,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE,oBAAoB,CAAC,CAAC,CAAC;QACjF,MAAM,WAAW,GAAG,EAAE,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE,oBAAoB,CAAC,CAAC,CAAC;QACjF,MAAM,QAAQ,GAAG,wBAAwB,CAAC;QAC1C,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,YAAY,CAAC,CAAC;QACzD,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAC5E,EAAE,CAAC,aAAa,CAAC,WAAW,EAAE,aAAa,CAAC,CAAC;QAC7C,EAAE,CAAC,WAAW,CAAC,WAAW,EAAE,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAC,CAAC;QAE9D,IAAI,CAAC;YACH,MAAM,CAAC,oBAAoB,CAAC,EAAE,WAAW,EAAE,QAAQ,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC,CAAC;iBACtE,aAAa,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,EAAE,IAAI,EAAE,cAAc,EAAE,CAAC,EAAE,CAAC,CAAC;QACtE,CAAC;gBAAS,CAAC;YACT,EAAE,CAAC,MAAM,CAAC,WAAW,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;YACzD,EAAE,CAAC,MAAM,CAAC,WAAW,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;QAC3D,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,sCAAsC,EAAE,GAAG,EAAE;QAC9C,MAAM,KAAK,GAAG,EAAE,CAAC,YAAY,CAC3B,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,QAAQ,EAAE,UAAU,EAAE,UAAU,CAAC,EAC1D,OAAO,CACR,CAAC;QACF,MAAM,CAAC,KAAK,CAAC,CAAC,SAAS,CAAC,sBAAsB,CAAC,CAAC;QAChD,MAAM,CAAC,KAAK,CAAC,CAAC,SAAS,CAAC,yBAAyB,CAAC,CAAC;QACnD,MAAM,CAAC,KAAK,CAAC,CAAC,SAAS,CAAC,cAAc,CAAC,CAAC;IAC1C,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -7,6 +7,8 @@ export { parsePRD, parsePRDFile } from './prdParser.js';
7
7
  export type { Requirement, ParsedPRD, PRDMetadata } from './prdParser.js';
8
8
  export { generateSpec } from './specGenerator.js';
9
9
  export type { SpecGeneratorOptions, GeneratedSpec } from './specGenerator.js';
10
+ export { compileExecutionPacket, getHarnessProfile, validateExecutionPacket, writeExecutionPacket, } from './executionPacket.js';
11
+ export type { CompileExecutionPacketInput, CompileExecutionPacketResult, ExecutionPacket, ExecutionPacketFileInput, HarnessProfile, HarnessProfileName, PacketError, PacketErrorCode, ValidateExecutionPacketInput, ValidateExecutionPacketResult, WriteExecutionPacketResult, } from './executionPacket.js';
10
12
  export { generateTraceabilityMatrix, formatMatrixAsMarkdown, formatMatrixAsHtml } from './traceabilityMatrix.js';
11
13
  export type { TraceItem, TraceabilityMatrix, TraceSummary, TraceMatrixOptions } from './traceabilityMatrix.js';
12
14
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/tools/spec/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EACL,qBAAqB,EACrB,sBAAsB,EACtB,qBAAqB,EACrB,gBAAgB,EAChB,kBAAkB,EAClB,mBAAmB,EACnB,oBAAoB,EACpB,mBAAmB,EACnB,eAAe,EACf,aAAa,EACb,aAAa,EACb,gBAAgB,EACjB,MAAM,oBAAoB,CAAC;AAG5B,OAAO,EACL,QAAQ,EACR,YAAY,EACb,MAAM,gBAAgB,CAAC;AACxB,YAAY,EACV,WAAW,EACX,SAAS,EACT,WAAW,EACZ,MAAM,gBAAgB,CAAC;AAGxB,OAAO,EACL,YAAY,EACb,MAAM,oBAAoB,CAAC;AAC5B,YAAY,EACV,oBAAoB,EACpB,aAAa,EACd,MAAM,oBAAoB,CAAC;AAG5B,OAAO,EACL,0BAA0B,EAC1B,sBAAsB,EACtB,kBAAkB,EACnB,MAAM,yBAAyB,CAAC;AACjC,YAAY,EACV,SAAS,EACT,kBAAkB,EAClB,YAAY,EACZ,kBAAkB,EACnB,MAAM,yBAAyB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/tools/spec/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EACL,qBAAqB,EACrB,sBAAsB,EACtB,qBAAqB,EACrB,gBAAgB,EAChB,kBAAkB,EAClB,mBAAmB,EACnB,oBAAoB,EACpB,mBAAmB,EACnB,eAAe,EACf,aAAa,EACb,aAAa,EACb,gBAAgB,EACjB,MAAM,oBAAoB,CAAC;AAG5B,OAAO,EACL,QAAQ,EACR,YAAY,EACb,MAAM,gBAAgB,CAAC;AACxB,YAAY,EACV,WAAW,EACX,SAAS,EACT,WAAW,EACZ,MAAM,gBAAgB,CAAC;AAGxB,OAAO,EACL,YAAY,EACb,MAAM,oBAAoB,CAAC;AAC5B,YAAY,EACV,oBAAoB,EACpB,aAAa,EACd,MAAM,oBAAoB,CAAC;AAG5B,OAAO,EACL,sBAAsB,EACtB,iBAAiB,EACjB,uBAAuB,EACvB,oBAAoB,GACrB,MAAM,sBAAsB,CAAC;AAC9B,YAAY,EACV,2BAA2B,EAC3B,4BAA4B,EAC5B,eAAe,EACf,wBAAwB,EACxB,cAAc,EACd,kBAAkB,EAClB,WAAW,EACX,eAAe,EACf,4BAA4B,EAC5B,6BAA6B,EAC7B,0BAA0B,GAC3B,MAAM,sBAAsB,CAAC;AAG9B,OAAO,EACL,0BAA0B,EAC1B,sBAAsB,EACtB,kBAAkB,EACnB,MAAM,yBAAyB,CAAC;AACjC,YAAY,EACV,SAAS,EACT,kBAAkB,EAClB,YAAY,EACZ,kBAAkB,EACnB,MAAM,yBAAyB,CAAC"}
@@ -8,6 +8,8 @@ export { generateRequirementId, generateRequirementIds, validateRequirementId, c
8
8
  export { parsePRD, parsePRDFile } from './prdParser.js';
9
9
  // SPEC Generator
10
10
  export { generateSpec } from './specGenerator.js';
11
+ // Execution Packet Compiler
12
+ export { compileExecutionPacket, getHarnessProfile, validateExecutionPacket, writeExecutionPacket, } from './executionPacket.js';
11
13
  // Traceability Matrix
12
14
  export { generateTraceabilityMatrix, formatMatrixAsMarkdown, formatMatrixAsHtml } from './traceabilityMatrix.js';
13
15
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/tools/spec/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,iBAAiB;AACjB,OAAO,EACL,qBAAqB,EACrB,sBAAsB,EACtB,qBAAqB,EACrB,gBAAgB,EAChB,kBAAkB,EAClB,mBAAmB,EACnB,oBAAoB,EACpB,mBAAmB,EACnB,eAAe,EACf,aAAa,EACb,aAAa,EACb,gBAAgB,EACjB,MAAM,oBAAoB,CAAC;AAE5B,aAAa;AACb,OAAO,EACL,QAAQ,EACR,YAAY,EACb,MAAM,gBAAgB,CAAC;AAOxB,iBAAiB;AACjB,OAAO,EACL,YAAY,EACb,MAAM,oBAAoB,CAAC;AAM5B,sBAAsB;AACtB,OAAO,EACL,0BAA0B,EAC1B,sBAAsB,EACtB,kBAAkB,EACnB,MAAM,yBAAyB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/tools/spec/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,iBAAiB;AACjB,OAAO,EACL,qBAAqB,EACrB,sBAAsB,EACtB,qBAAqB,EACrB,gBAAgB,EAChB,kBAAkB,EAClB,mBAAmB,EACnB,oBAAoB,EACpB,mBAAmB,EACnB,eAAe,EACf,aAAa,EACb,aAAa,EACb,gBAAgB,EACjB,MAAM,oBAAoB,CAAC;AAE5B,aAAa;AACb,OAAO,EACL,QAAQ,EACR,YAAY,EACb,MAAM,gBAAgB,CAAC;AAOxB,iBAAiB;AACjB,OAAO,EACL,YAAY,EACb,MAAM,oBAAoB,CAAC;AAM5B,4BAA4B;AAC5B,OAAO,EACL,sBAAsB,EACtB,iBAAiB,EACjB,uBAAuB,EACvB,oBAAoB,GACrB,MAAM,sBAAsB,CAAC;AAe9B,sBAAsB;AACtB,OAAO,EACL,0BAA0B,EAC1B,sBAAsB,EACtB,kBAAkB,EACnB,MAAM,yBAAyB,CAAC"}
@@ -18,6 +18,18 @@ export interface SpecGeneratorOptions {
18
18
  additionalConstraints?: string[];
19
19
  /** 출력 형식 추가 */
20
20
  additionalOutputs?: string[];
21
+ /** 컨텍스트 출처 */
22
+ contextSources?: string[];
23
+ /** 확인 없이 채택한 가정 */
24
+ assumptions?: string[];
25
+ /** 완료를 증명할 산출물 */
26
+ evidenceRequired?: EvidenceRequirement[];
27
+ /** 출시 시 사람이 판단할 비차단 기준 */
28
+ humanTaste?: string[];
29
+ }
30
+ export interface EvidenceRequirement {
31
+ criterionId: string;
32
+ evidence: string;
21
33
  }
22
34
  /** 생성된 SPEC */
23
35
  export interface GeneratedSpec {
@@ -1 +1 @@
1
- {"version":3,"file":"specGenerator.d.ts","sourceRoot":"","sources":["../../../src/tools/spec/specGenerator.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,SAAS,EAAe,MAAM,gBAAgB,CAAC;AAOxD,iBAAiB;AACjB,MAAM,WAAW,oBAAoB;IACnC,YAAY;IACZ,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;IACrB,+BAA+B;IAC/B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,eAAe;IACf,gBAAgB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC5B,eAAe;IACf,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,eAAe;IACf,qBAAqB,CAAC,EAAE,MAAM,EAAE,CAAC;IACjC,eAAe;IACf,iBAAiB,CAAC,EAAE,MAAM,EAAE,CAAC;CAC9B;AAED,eAAe;AACf,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,gBAAgB,EAAE,MAAM,CAAC;IACzB,OAAO,EAAE,OAAO,CAAC;IACjB,UAAU,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;CAClD;AAaD;;GAEG;AACH,wBAAgB,YAAY,CAC1B,GAAG,EAAE,SAAS,EACd,WAAW,EAAE,MAAM,EACnB,OAAO,GAAE,oBAAyB,GACjC,aAAa,CAmBf"}
1
+ {"version":3,"file":"specGenerator.d.ts","sourceRoot":"","sources":["../../../src/tools/spec/specGenerator.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,SAAS,EAAe,MAAM,gBAAgB,CAAC;AAOxD,iBAAiB;AACjB,MAAM,WAAW,oBAAoB;IACnC,YAAY;IACZ,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;IACrB,+BAA+B;IAC/B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,eAAe;IACf,gBAAgB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC5B,eAAe;IACf,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,eAAe;IACf,qBAAqB,CAAC,EAAE,MAAM,EAAE,CAAC;IACjC,eAAe;IACf,iBAAiB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC7B,cAAc;IACd,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;IAC1B,mBAAmB;IACnB,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IACvB,kBAAkB;IAClB,gBAAgB,CAAC,EAAE,mBAAmB,EAAE,CAAC;IACzC,0BAA0B;IAC1B,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;CACvB;AAED,MAAM,WAAW,mBAAmB;IAClC,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,eAAe;AACf,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,gBAAgB,EAAE,MAAM,CAAC;IACzB,OAAO,EAAE,OAAO,CAAC;IACjB,UAAU,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;CAClD;AAaD;;GAEG;AACH,wBAAgB,YAAY,CAC1B,GAAG,EAAE,SAAS,EACd,WAAW,EAAE,MAAM,EACnB,OAAO,GAAE,oBAAyB,GACjC,aAAa,CAmBf"}
@@ -69,7 +69,7 @@ function generateSplitSpec(prd, featureName, phases, options) {
69
69
  * 단일 SPEC 콘텐츠 빌드
70
70
  */
71
71
  function buildSpecContent(prd, featureName, phases, options) {
72
- const { techStack = [], relatedCodePaths = [], designReference, additionalConstraints = [], additionalOutputs = [] } = options;
72
+ const { techStack = [], relatedCodePaths = [], designReference, additionalConstraints = [], additionalOutputs = [], contextSources = [], assumptions = [], humanTaste = [], } = options;
73
73
  const now = new Date().toISOString();
74
74
  let content = `---
75
75
  status: pending
@@ -106,8 +106,16 @@ ${designReference || '- (None specified)'}
106
106
  ### Requirements Source
107
107
  - Parsed from PRD: ${prd.requirements.length} requirements
108
108
  - Format: ${prd.metadata.format}
109
+
110
+ ### Context Sources
111
+ ${contextSources.length > 0 ? contextSources.map(source => `- ${source}`).join('\n') : '- PRD input supplied to this generator'}
112
+
113
+ ### Assumptions
114
+ ${assumptions.length > 0 ? assumptions.map(assumption => `- ${assumption}`).join('\n') : '- None recorded'}
109
115
  </context>
110
116
 
117
+ ${renderContractTables(prd.requirements, featureName)}
118
+
111
119
  ## Task
112
120
  <task>
113
121
  `;
@@ -158,6 +166,12 @@ ${generateFileList(phases, 'modify')}
158
166
  - \`npm test\` (tests pass)
159
167
  - \`tsc --noEmit\` (type check)
160
168
  ${additionalOutputs.map(o => `- ${o}`).join('\n')}
169
+
170
+ ### Evidence Required
171
+ ${renderEvidenceRequired(options.evidenceRequired, prd.requirements)}
172
+
173
+ ### Human Taste (Non-Blocking)
174
+ ${humanTaste.length > 0 ? humanTaste.map(item => `- ${item}`).join('\n') : '- None recorded; release review remains a human decision'}
161
175
  </output_format>
162
176
 
163
177
  ## Acceptance Criteria
@@ -222,12 +236,14 @@ isMaster: true
222
236
  ### Tech Stack
223
237
  ${options.techStack?.map(t => `- ${t}`).join('\n') || '- (See project configuration)'}
224
238
 
239
+ ### Context Sources
240
+ ${options.contextSources?.map(source => `- ${source}`).join('\n') || '- PRD input supplied to this generator'}
241
+
242
+ ### Assumptions
243
+ ${options.assumptions?.map(assumption => `- ${assumption}`).join('\n') || '- None recorded'}
244
+
225
245
  ### Constraints (Apply to All Phases)
226
- - Follow existing code patterns
227
- - TypeScript strict mode
228
- - No \`any\` type
229
- - Functions ≤50 lines max
230
- ${options.additionalConstraints?.map(c => `- ${c}`).join('\n') || ''}
246
+ ${renderSharedConstraints(options.additionalConstraints)}
231
247
 
232
248
  ## Execution Order
233
249
  \`\`\`
@@ -236,6 +252,12 @@ ${phases.map((p, i) => `Phase ${i + 1}: ${p.name}`).join(' → ')}
236
252
 
237
253
  ## Dependencies
238
254
  ${generateDependencyList(phases)}
255
+
256
+ ## Evidence Required
257
+ ${renderEvidenceRequired(options.evidenceRequired, prd.requirements)}
258
+
259
+ ## Human Taste (Non-Blocking)
260
+ ${options.humanTaste?.map(item => `- ${item}`).join('\n') || '- None recorded; release review remains a human decision'}
239
261
  `;
240
262
  return content;
241
263
  }
@@ -268,13 +290,24 @@ Developer implementing Phase ${phaseNumber} of ${featureName}.
268
290
  ### Phase Goal
269
291
  ${getPhaseGoal(phase)}
270
292
 
271
- ### Requirements (${phase.requirements.length})
272
- ${phase.requirements.map(r => `- ${r.id}: ${truncateText(r.description, 50)}`).join('\n')}
293
+ ### Requirement Summary (${phase.requirements.length})
294
+ ${phase.requirements.map(r => `- ${r.id}: ${truncateText(r.description, 50)}`).join('\n') || '- Build and verification phase'}
273
295
 
274
296
  ### Dependencies
275
297
  ${phaseNumber > 1 ? `- Requires Phase ${phaseNumber - 1} completion` : '- No dependencies (first phase)'}
298
+
299
+ ### Context Sources
300
+ ${options.contextSources?.map(source => `- ${source}`).join('\n') || '- Inherited from master SPEC and PRD input'}
301
+
302
+ ### Assumptions
303
+ ${options.assumptions?.map(assumption => `- ${assumption}`).join('\n') || '- None recorded'}
276
304
  </context>
277
305
 
306
+ ## Constraints
307
+ ${renderSharedConstraints(options.additionalConstraints)}
308
+
309
+ ${renderContractTables(phase.requirements, `${featureName}-phase-${phaseNumber}`)}
310
+
278
311
  ## Task
279
312
  <task>
280
313
  `;
@@ -292,12 +325,59 @@ ${phaseNumber > 1 ? `- Requires Phase ${phaseNumber - 1} completion` : '- No dep
292
325
  content += `- [ ] Phase ${phaseNumber} build succeeds
293
326
  - [ ] Phase ${phaseNumber} tests pass
294
327
  </acceptance>
328
+
329
+ ## Evidence Required
330
+ ${renderEvidenceRequired(options.evidenceRequired, phase.requirements)}
331
+
332
+ ## Human Taste (Non-Blocking)
333
+ ${options.humanTaste?.map(item => `- ${item}`).join('\n') || '- None recorded; release review remains a human decision'}
295
334
  `;
296
335
  return content;
297
336
  }
298
337
  // ============================================
299
338
  // Helper Functions
300
339
  // ============================================
340
+ function renderEvidenceRequired(evidence, requirements) {
341
+ const byCriterion = new Map(evidence?.map(item => [item.criterionId, item.evidence]) ?? []);
342
+ const targets = requirements.length > 0
343
+ ? requirements
344
+ : [fallbackRequirement('phase-build', 'Phase build and tests pass')];
345
+ return targets.map((requirement, index) => {
346
+ const proof = byCriterion.get(`D${index + 1}`) ?? byCriterion.get(requirement.id)
347
+ ?? 'Command results and exit codes for this criterion';
348
+ return `- D${index + 1} → ${proof}`;
349
+ }).join('\n');
350
+ }
351
+ function renderContractTables(requirements, featureName) {
352
+ const targets = requirements.length > 0
353
+ ? requirements
354
+ : [fallbackRequirement(`REQ-${normalizeFileName(featureName)}-001`, 'Build and tests pass for this phase')];
355
+ const requirementRows = targets.map((requirement, index) => `| ${requirement.id} | ${truncateText(requirement.description, 80)} | D${index + 1} |`).join('\n');
356
+ const criterionRows = targets.map((requirement, index) => `| D${index + 1} | ${truncateText(requirement.description, 80)} | Automated verification exits 0 |`).join('\n');
357
+ return `## Requirements
358
+
359
+ | ID | Requirement | Done Criteria |
360
+ |----|-------------|---------------|
361
+ ${requirementRows}
362
+
363
+ ## Done Criteria
364
+
365
+ | # | Criterion | Verified by |
366
+ |---|-----------|-------------|
367
+ ${criterionRows}`;
368
+ }
369
+ function fallbackRequirement(id, description) {
370
+ return { id, description, acceptanceCriteria: [], priority: 'high' };
371
+ }
372
+ function renderSharedConstraints(additional) {
373
+ return [
374
+ 'Follow existing code patterns',
375
+ 'TypeScript strict mode',
376
+ 'No `any` type',
377
+ 'Functions ≤50 lines max',
378
+ ...(additional ?? []),
379
+ ].map(item => `- ${item}`).join('\n');
380
+ }
301
381
  /**
302
382
  * 요구사항을 Phase로 그룹화
303
383
  */
@@ -324,11 +404,12 @@ function groupRequirementsIntoPhases(requirements, threshold) {
324
404
  });
325
405
  }
326
406
  // Phase 2+: 핵심 기능 (high priority)
327
- if (high.length > 0) {
407
+ const remainingHigh = high.filter(requirement => !setupReqs.includes(requirement));
408
+ if (remainingHigh.length > 0) {
328
409
  phases.push({
329
410
  name: 'Core Features',
330
- requirements: high,
331
- tasks: high.map(r => generateTaskFromRequirement(r)),
411
+ requirements: remainingHigh,
412
+ tasks: remainingHigh.map(r => generateTaskFromRequirement(r)),
332
413
  });
333
414
  }
334
415
  // Phase 3+: 중요 기능 (medium priority)
@@ -341,11 +422,12 @@ function groupRequirementsIntoPhases(requirements, threshold) {
341
422
  });
342
423
  }
343
424
  // Phase 4+: 부가 기능 (low priority)
344
- if (low.length > 0) {
425
+ const remainingLow = low.filter(requirement => !setupReqs.includes(requirement));
426
+ if (remainingLow.length > 0) {
345
427
  phases.push({
346
428
  name: 'Enhancements',
347
- requirements: low,
348
- tasks: low.map(r => generateTaskFromRequirement(r)),
429
+ requirements: remainingLow,
430
+ tasks: remainingLow.map(r => generateTaskFromRequirement(r)),
349
431
  });
350
432
  }
351
433
  // 마지막 Phase: 테스트 & 검증