@su-record/vibe 2.9.38 → 2.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (134) hide show
  1. package/CLAUDE.md +19 -6
  2. package/README.md +31 -24
  3. package/agents/{teams/figma → figma}/figma-analyst.md +2 -2
  4. package/agents/research/{best-practices-agent.md → best-practices.md} +1 -1
  5. package/agents/research/{codebase-patterns-agent.md → codebase-patterns.md} +1 -1
  6. package/agents/research/{framework-docs-agent.md → framework-docs.md} +1 -1
  7. package/agents/research/{security-advisory-agent.md → security-advisory.md} +1 -1
  8. package/agents/teams/research-team.md +4 -4
  9. package/agents/teams/review-debate-team.md +2 -2
  10. package/agents/teams/security-team.md +4 -4
  11. package/dist/cli/commands/init.js +2 -2
  12. package/dist/cli/commands/init.js.map +1 -1
  13. package/dist/cli/postinstall/claude-agents.d.ts +3 -1
  14. package/dist/cli/postinstall/claude-agents.d.ts.map +1 -1
  15. package/dist/cli/postinstall/claude-agents.js +47 -9
  16. package/dist/cli/postinstall/claude-agents.js.map +1 -1
  17. package/dist/cli/postinstall/constants.d.ts +5 -0
  18. package/dist/cli/postinstall/constants.d.ts.map +1 -1
  19. package/dist/cli/postinstall/constants.js +165 -23
  20. package/dist/cli/postinstall/constants.js.map +1 -1
  21. package/dist/cli/postinstall/cursor-skills.js +2 -2
  22. package/dist/cli/postinstall/main.d.ts.map +1 -1
  23. package/dist/cli/postinstall/main.js +19 -10
  24. package/dist/cli/postinstall/main.js.map +1 -1
  25. package/dist/infra/lib/OrchestrateWorkflow.js +1 -1
  26. package/dist/infra/lib/OrchestrateWorkflow.js.map +1 -1
  27. package/dist/infra/lib/telemetry/SkillTelemetry.test.js +4 -4
  28. package/dist/infra/lib/telemetry/SkillTelemetry.test.js.map +1 -1
  29. package/dist/infra/orchestrator/parallelResearch.js +4 -4
  30. package/dist/infra/orchestrator/parallelResearch.js.map +1 -1
  31. package/hooks/scripts/__tests__/curation-index.test.js +157 -0
  32. package/hooks/scripts/__tests__/recipe-extractor.test.js +244 -0
  33. package/hooks/scripts/__tests__/step-counter.test.js +358 -0
  34. package/hooks/scripts/clone-extract.js +712 -0
  35. package/hooks/scripts/clone-refine.js +510 -0
  36. package/hooks/scripts/clone-to-scss.js +275 -0
  37. package/hooks/scripts/clone-validate.js +280 -0
  38. package/hooks/scripts/lib/curation-index.js +101 -0
  39. package/hooks/scripts/recipe-extractor.js +249 -0
  40. package/hooks/scripts/session-start.js +19 -0
  41. package/hooks/scripts/step-counter.js +230 -21
  42. package/package.json +2 -1
  43. package/skills/agents-md/SKILL.md +2 -0
  44. package/skills/arch-guard/SKILL.md +2 -0
  45. package/skills/brand-assets/SKILL.md +1 -0
  46. package/skills/capability-loop/SKILL.md +2 -0
  47. package/skills/characterization-test/SKILL.md +2 -0
  48. package/skills/chub-usage/SKILL.md +1 -0
  49. package/skills/claude-md-guide/SKILL.md +2 -0
  50. package/skills/clone/SKILL.md +361 -0
  51. package/skills/commerce-patterns/SKILL.md +1 -0
  52. package/skills/commit-push-pr/SKILL.md +1 -0
  53. package/skills/context7-usage/SKILL.md +1 -0
  54. package/skills/{vibe-contract → contract}/SKILL.md +7 -8
  55. package/skills/create-prd/SKILL.md +1 -0
  56. package/skills/design-audit/SKILL.md +1 -0
  57. package/skills/design-critique/SKILL.md +1 -0
  58. package/skills/design-distill/SKILL.md +1 -0
  59. package/skills/design-normalize/SKILL.md +1 -0
  60. package/skills/design-polish/SKILL.md +1 -0
  61. package/skills/design-teach/SKILL.md +2 -0
  62. package/skills/devlog/SKILL.md +1 -0
  63. package/skills/{vibe-docs → docs}/SKILL.md +5 -5
  64. package/skills/e2e-commerce/SKILL.md +1 -0
  65. package/skills/event-comms/SKILL.md +1 -0
  66. package/skills/event-ops/SKILL.md +1 -0
  67. package/skills/event-planning/SKILL.md +1 -0
  68. package/skills/exec-plan/SKILL.md +2 -0
  69. package/skills/{vibe-figma → figma}/SKILL.md +4 -3
  70. package/skills/{vibe-figma-convert → figma-convert}/SKILL.md +4 -3
  71. package/skills/{vibe-figma-extract → figma-extract}/SKILL.md +4 -3
  72. package/skills/git-worktree/SKILL.md +1 -0
  73. package/skills/handoff/SKILL.md +2 -0
  74. package/skills/{vibe-interview → interview}/SKILL.md +16 -16
  75. package/skills/parallel-research/SKILL.md +2 -0
  76. package/skills/{vibe-plan → plan}/SKILL.md +9 -9
  77. package/skills/prioritization-frameworks/SKILL.md +1 -0
  78. package/skills/priority-todos/SKILL.md +2 -0
  79. package/skills/{vibe-regress → regress}/SKILL.md +5 -6
  80. package/skills/rob-pike/SKILL.md +2 -0
  81. package/skills/seo-checklist/SKILL.md +1 -0
  82. package/skills/{vibe-spec → spec}/SKILL.md +14 -14
  83. package/skills/{vibe-spec-review → spec-review}/SKILL.md +8 -9
  84. package/skills/systematic-debugging/SKILL.md +2 -0
  85. package/skills/techdebt/SKILL.md +2 -0
  86. package/skills/{vibe-test → test}/SKILL.md +12 -12
  87. package/skills/tool-fallback/SKILL.md +1 -0
  88. package/skills/typescript-advanced-types/SKILL.md +1 -0
  89. package/skills/ui-ux-pro-max/SKILL.md +1 -0
  90. package/skills/user-personas/SKILL.md +1 -0
  91. package/skills/vercel-react-best-practices/SKILL.md +1 -0
  92. package/skills/vibe/SKILL.md +266 -0
  93. package/{commands/vibe.analyze.md → skills/vibe.analyze/SKILL.md} +2 -0
  94. package/skills/vibe.clone/SKILL.md +117 -0
  95. package/{commands/vibe.contract.md → skills/vibe.contract/SKILL.md} +3 -1
  96. package/{commands/vibe.docs.md → skills/vibe.docs/SKILL.md} +3 -1
  97. package/{commands/vibe.event.md → skills/vibe.event/SKILL.md} +2 -0
  98. package/{commands/vibe.figma.md → skills/vibe.figma/SKILL.md} +25 -23
  99. package/{commands/vibe.harness.md → skills/vibe.harness/SKILL.md} +2 -0
  100. package/{commands/vibe.reason.md → skills/vibe.reason/SKILL.md} +2 -0
  101. package/{commands/vibe.regress.md → skills/vibe.regress/SKILL.md} +5 -3
  102. package/{commands/vibe.review.md → skills/vibe.review/SKILL.md} +2 -0
  103. package/{commands/vibe.run.md → skills/vibe.run/SKILL.md} +3 -1
  104. package/{commands/vibe.scaffold.md → skills/vibe.scaffold/SKILL.md} +2 -0
  105. package/{commands/vibe.spec.md → skills/vibe.spec/SKILL.md} +36 -34
  106. package/{commands/vibe.test.md → skills/vibe.test/SKILL.md} +4 -2
  107. package/{commands/vibe.trace.md → skills/vibe.trace/SKILL.md} +7 -0
  108. package/{commands/vibe.utils.md → skills/vibe.utils/SKILL.md} +2 -0
  109. package/{commands/vibe.verify.md → skills/vibe.verify/SKILL.md} +10 -2
  110. package/skills/video-production/SKILL.md +1 -0
  111. /package/agents/{teams/figma → figma}/figma-architect.md +0 -0
  112. /package/agents/{teams/figma → figma}/figma-auditor.md +0 -0
  113. /package/agents/{teams/figma → figma}/figma-builder.md +0 -0
  114. /package/skills/{vibe-docs → docs}/templates/architecture.md +0 -0
  115. /package/skills/{vibe-docs → docs}/templates/behavioral-principles.md +0 -0
  116. /package/skills/{vibe-docs → docs}/templates/readme.md +0 -0
  117. /package/skills/{vibe-docs → docs}/templates/release-notes.md +0 -0
  118. /package/skills/{vibe-figma → figma}/rubrics/extraction-checklist.md +0 -0
  119. /package/skills/{vibe-figma → figma}/templates/component-index.md +0 -0
  120. /package/skills/{vibe-figma → figma}/templates/component-spec.md +0 -0
  121. /package/skills/{vibe-figma → figma}/templates/figma-handoff.md +0 -0
  122. /package/skills/{vibe-figma → figma}/templates/remapped-tree.md +0 -0
  123. /package/skills/{vibe-figma-convert → figma-convert}/rubrics/conversion-rules.md +0 -0
  124. /package/skills/{vibe-figma-convert → figma-convert}/templates/component.md +0 -0
  125. /package/skills/{vibe-figma-extract → figma-extract}/rubrics/image-rules.md +0 -0
  126. /package/skills/{vibe-interview → interview}/checklists/api.md +0 -0
  127. /package/skills/{vibe-interview → interview}/checklists/feature.md +0 -0
  128. /package/skills/{vibe-interview → interview}/checklists/library.md +0 -0
  129. /package/skills/{vibe-interview → interview}/checklists/mobile.md +0 -0
  130. /package/skills/{vibe-interview → interview}/checklists/webapp.md +0 -0
  131. /package/skills/{vibe-interview → interview}/checklists/website.md +0 -0
  132. /package/skills/{vibe-regress → regress}/templates/bug.md +0 -0
  133. /package/skills/{vibe-regress → regress}/templates/test-jest.md +0 -0
  134. /package/skills/{vibe-regress → regress}/templates/test-vitest.md +0 -0
@@ -1 +1 @@
1
- {"version":3,"file":"parallelResearch.js","sourceRoot":"","sources":["../../../src/infra/orchestrator/parallelResearch.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"parallelResearch.js","sourceRoot":"","sources":["../../../src/infra/orchestrator/parallelResearch.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,157 @@
1
+ /**
2
+ * curation-index.js — Phase 3 인덱스 로더 테스트
3
+ *
4
+ * session-start.js 가 다음 세션에 prepend 할 1줄 요약을 만드는 모듈.
5
+ * 본격 YAML parser 의존 없이 우리가 작성한 frontmatter 형식만 처리한다.
6
+ */
7
+ import { describe, it, expect, beforeEach } from 'vitest';
8
+ import fs from 'fs';
9
+ import os from 'os';
10
+ import path from 'path';
11
+ import { loadCurationIndex, _internal } from '../lib/curation-index.js';
12
+
13
+ const { parseFrontmatter } = _internal;
14
+
15
+ function makeTmpProject() {
16
+ return fs.mkdtempSync(path.join(os.tmpdir(), 'vibe-curation-index-'));
17
+ }
18
+
19
+ function writeRecipe(projectDir, filename, frontmatter, body = 'body text') {
20
+ const dir = path.join(projectDir, '.vibe', 'recipes');
21
+ fs.mkdirSync(dir, { recursive: true });
22
+ const fm = Object.entries(frontmatter)
23
+ .map(([k, v]) => typeof v === 'string' ? `${k}: "${v}"` : `${k}: ${v}`)
24
+ .join('\n');
25
+ fs.writeFileSync(path.join(dir, filename), `---\n${fm}\n---\n\n${body}\n`);
26
+ }
27
+
28
+ function writeAntiPattern(projectDir, filename, frontmatter, body = 'body') {
29
+ const dir = path.join(projectDir, '.vibe', 'anti-patterns');
30
+ fs.mkdirSync(dir, { recursive: true });
31
+ const fm = Object.entries(frontmatter)
32
+ .map(([k, v]) => typeof v === 'string' ? `${k}: "${v}"` : `${k}: ${v}`)
33
+ .join('\n');
34
+ fs.writeFileSync(path.join(dir, filename), `---\n${fm}\n---\n\n${body}\n`);
35
+ }
36
+
37
+ describe('parseFrontmatter', () => {
38
+ it('단순 key-value 파싱', () => {
39
+ const input = `---\nslug: foo\ntype: recipe\n---\nbody`;
40
+ expect(parseFrontmatter(input)).toEqual({ slug: 'foo', type: 'recipe' });
41
+ });
42
+
43
+ it('따옴표로 감싼 값', () => {
44
+ const input = `---\nrecipe: "use claude --model"\n---\n`;
45
+ expect(parseFrontmatter(input).recipe).toBe('use claude --model');
46
+ });
47
+
48
+ it('이스케이프된 따옴표', () => {
49
+ const input = `---\nmsg: "say \\"hi\\""\n---\n`;
50
+ expect(parseFrontmatter(input).msg).toBe('say "hi"');
51
+ });
52
+
53
+ it('frontmatter 가 없으면 null', () => {
54
+ expect(parseFrontmatter('no frontmatter here')).toBeNull();
55
+ });
56
+
57
+ it('알 수 없는 라인 무시', () => {
58
+ const input = `---\nslug: foo\n# comment line\nrandom garbage\ntype: recipe\n---\n`;
59
+ expect(parseFrontmatter(input)).toEqual({ slug: 'foo', type: 'recipe' });
60
+ });
61
+ });
62
+
63
+ describe('loadCurationIndex', () => {
64
+ let projectDir;
65
+
66
+ beforeEach(() => {
67
+ projectDir = makeTmpProject();
68
+ });
69
+
70
+ it('빈 .vibe/ 면 빈 인덱스', () => {
71
+ const idx = loadCurationIndex(projectDir);
72
+ expect(idx.recipes).toEqual([]);
73
+ expect(idx.antiPatterns).toEqual([]);
74
+ });
75
+
76
+ it('recipe 1개 로드', () => {
77
+ writeRecipe(projectDir, 'a.md', {
78
+ slug: 'login__20260507-100000',
79
+ type: 'recipe',
80
+ 'symptom-context': 'login flow',
81
+ recipe: 'pin model and retry transient',
82
+ created: '2026-05-07',
83
+ });
84
+ const idx = loadCurationIndex(projectDir);
85
+ expect(idx.recipes).toHaveLength(1);
86
+ expect(idx.recipes[0]).toEqual({
87
+ slug: 'login__20260507-100000',
88
+ summary: 'pin model and retry transient',
89
+ });
90
+ });
91
+
92
+ it('recipe 정렬: created 내림차순', () => {
93
+ writeRecipe(projectDir, 'old.md', { slug: 'old', recipe: 'old', created: '2026-01-01' });
94
+ writeRecipe(projectDir, 'mid.md', { slug: 'mid', recipe: 'mid', created: '2026-03-01' });
95
+ writeRecipe(projectDir, 'new.md', { slug: 'new', recipe: 'new', created: '2026-05-01' });
96
+ const idx = loadCurationIndex(projectDir);
97
+ expect(idx.recipes.map((r) => r.slug)).toEqual(['new', 'mid', 'old']);
98
+ });
99
+
100
+ it('limit 적용', () => {
101
+ for (let i = 0; i < 10; i++) {
102
+ writeRecipe(projectDir, `r${i}.md`, {
103
+ slug: `r${i}`,
104
+ recipe: `recipe ${i}`,
105
+ created: `2026-05-${String(i + 1).padStart(2, '0')}`,
106
+ });
107
+ }
108
+ const idx = loadCurationIndex(projectDir, { recipeLimit: 3 });
109
+ expect(idx.recipes).toHaveLength(3);
110
+ expect(idx.recipes[0].slug).toBe('r9');
111
+ });
112
+
113
+ it('anti-pattern 로드 — tag + suggested-stop', () => {
114
+ writeAntiPattern(projectDir, 'a.md', {
115
+ slug: 'nullability__src__20260507',
116
+ type: 'anti-pattern',
117
+ 'root-cause-tag': 'nullability',
118
+ 'trigger-signature': '(file=src/x.ts, category=nullability)',
119
+ 'suggested-stop': '같은 위치 null 처리 반복 — 타입 가드 필요',
120
+ created: '2026-05-07',
121
+ });
122
+ const idx = loadCurationIndex(projectDir);
123
+ expect(idx.antiPatterns).toHaveLength(1);
124
+ expect(idx.antiPatterns[0].tag).toBe('nullability');
125
+ expect(idx.antiPatterns[0].summary).toBe('같은 위치 null 처리 반복 — 타입 가드 필요');
126
+ });
127
+
128
+ it('frontmatter 손상 파일은 스킵', () => {
129
+ writeRecipe(projectDir, 'good.md', { slug: 'good', recipe: 'works', created: '2026-05-07' });
130
+ fs.writeFileSync(path.join(projectDir, '.vibe', 'recipes', 'broken.md'), 'no frontmatter');
131
+ fs.writeFileSync(path.join(projectDir, '.vibe', 'recipes', 'no-slug.md'), '---\ntype: recipe\n---\n');
132
+ const idx = loadCurationIndex(projectDir);
133
+ expect(idx.recipes).toHaveLength(1);
134
+ expect(idx.recipes[0].slug).toBe('good');
135
+ });
136
+
137
+ it('README.md, _cluster*.md 등 메타 파일 제외', () => {
138
+ writeRecipe(projectDir, 'r.md', { slug: 'r', recipe: 'good', created: '2026-05-07' });
139
+ fs.writeFileSync(path.join(projectDir, '.vibe', 'recipes', 'README.md'), '---\nslug: should-skip\n---\n');
140
+ fs.writeFileSync(path.join(projectDir, '.vibe', 'recipes', '_cluster-x.md'), '---\nslug: should-skip\n---\n');
141
+ const idx = loadCurationIndex(projectDir);
142
+ expect(idx.recipes.map((r) => r.slug)).toEqual(['r']);
143
+ });
144
+
145
+ it('recipe + anti-pattern 동시 로드 (독립)', () => {
146
+ writeRecipe(projectDir, 'r.md', { slug: 'r', recipe: 'do this', created: '2026-05-07' });
147
+ writeAntiPattern(projectDir, 'a.md', {
148
+ slug: 'a',
149
+ 'root-cause-tag': 'auth',
150
+ 'suggested-stop': 'check tokens',
151
+ created: '2026-05-07',
152
+ });
153
+ const idx = loadCurationIndex(projectDir);
154
+ expect(idx.recipes).toHaveLength(1);
155
+ expect(idx.antiPatterns).toHaveLength(1);
156
+ });
157
+ });
@@ -0,0 +1,244 @@
1
+ /**
2
+ * recipe-extractor.js — Phase 3 테스트
3
+ *
4
+ * 검증 범위:
5
+ * - 휴리스틱 게이트: total_tools≥8 AND fails≥3 AND last=success
6
+ * - VIBE_RECIPE_LLM=mock 으로 LLM 우회 (외부 의존 0)
7
+ * - frontmatter schema 충족
8
+ * - silent fail 정책 (jsonl 없음 / 게이트 실패 / 디렉토리 부재)
9
+ *
10
+ * 외부 의존:
11
+ * - 실제 claude CLI 는 호출하지 않음 (mock 모드 사용)
12
+ */
13
+ import { describe, it, expect, beforeEach } from 'vitest';
14
+ import { spawnSync } from 'child_process';
15
+ import fs from 'fs';
16
+ import os from 'os';
17
+ import path from 'path';
18
+ import { fileURLToPath } from 'url';
19
+
20
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
21
+ const SCRIPT = path.resolve(__dirname, '..', 'recipe-extractor.js');
22
+
23
+ function makeTmpProject() {
24
+ return fs.mkdtempSync(path.join(os.tmpdir(), 'vibe-recipe-extractor-'));
25
+ }
26
+
27
+ function writeJsonl(projectDir, records) {
28
+ const dir = path.join(projectDir, '.vibe', 'metrics');
29
+ fs.mkdirSync(dir, { recursive: true });
30
+ const lines = records.map((r) => JSON.stringify(r)).join('\n') + '\n';
31
+ fs.writeFileSync(path.join(dir, 'current-run.jsonl'), lines);
32
+ }
33
+
34
+ function writeRunMeta(projectDir, meta) {
35
+ const dir = path.join(projectDir, '.vibe', 'metrics');
36
+ fs.mkdirSync(dir, { recursive: true });
37
+ fs.writeFileSync(path.join(dir, 'current-run.json'), JSON.stringify(meta));
38
+ }
39
+
40
+ function runExtractor(projectDir, { mock = true } = {}) {
41
+ const result = spawnSync('node', [SCRIPT], {
42
+ encoding: 'utf-8',
43
+ timeout: 5000,
44
+ env: {
45
+ ...process.env,
46
+ CLAUDE_PROJECT_DIR: projectDir,
47
+ ...(mock ? { VIBE_RECIPE_LLM: 'mock' } : {}),
48
+ VIBE_HOOK_DEPTH: '0',
49
+ },
50
+ });
51
+ return result;
52
+ }
53
+
54
+ function listRecipes(projectDir) {
55
+ const dir = path.join(projectDir, '.vibe', 'recipes');
56
+ if (!fs.existsSync(dir)) return [];
57
+ return fs.readdirSync(dir).filter((f) => f.endsWith('.md'));
58
+ }
59
+
60
+ function makeRecord({ tool = 'Bash', ok = true, file = null, category = null }) {
61
+ return {
62
+ ts: new Date().toISOString(),
63
+ tool,
64
+ ok,
65
+ target_file: file,
66
+ error_category: ok ? null : category,
67
+ };
68
+ }
69
+
70
+ describe('recipe-extractor (Phase 3)', () => {
71
+ let projectDir;
72
+
73
+ beforeEach(() => {
74
+ projectDir = makeTmpProject();
75
+ });
76
+
77
+ // ───────── 게이트 통과 조건 ─────────
78
+ describe('휴리스틱 게이트', () => {
79
+ it('총 ≥8 + 실패 ≥3 + 마지막 성공 → recipe 생성', () => {
80
+ const records = [
81
+ makeRecord({ ok: false, category: 'integration' }),
82
+ makeRecord({ ok: false, category: 'integration' }),
83
+ makeRecord({ ok: false, category: 'auth' }),
84
+ makeRecord({ ok: true }),
85
+ makeRecord({ ok: true }),
86
+ makeRecord({ ok: true, tool: 'Edit', file: 'src/foo.ts' }),
87
+ makeRecord({ ok: true, tool: 'Read', file: 'src/foo.ts' }),
88
+ makeRecord({ ok: true, tool: 'Bash' }), // 마지막=성공
89
+ ];
90
+ writeJsonl(projectDir, records);
91
+ writeRunMeta(projectDir, { feature: 'auth-fix', startedAt: '2026-05-07T00:00:00.000Z', steps: 8 });
92
+
93
+ const r = runExtractor(projectDir);
94
+ expect(r.status).toBe(0);
95
+ expect(listRecipes(projectDir)).toHaveLength(1);
96
+ });
97
+
98
+ it('툴콜 부족 (<8) → 생성 안 함', () => {
99
+ const records = [
100
+ makeRecord({ ok: false, category: 'integration' }),
101
+ makeRecord({ ok: false, category: 'integration' }),
102
+ makeRecord({ ok: false, category: 'integration' }),
103
+ makeRecord({ ok: true }),
104
+ ];
105
+ writeJsonl(projectDir, records);
106
+ writeRunMeta(projectDir, { feature: 'x' });
107
+ runExtractor(projectDir);
108
+ expect(listRecipes(projectDir)).toHaveLength(0);
109
+ });
110
+
111
+ it('실패 부족 (<3) → 생성 안 함', () => {
112
+ const records = Array.from({ length: 10 }, () => makeRecord({ ok: true }));
113
+ records[0] = makeRecord({ ok: false, category: 'other' });
114
+ records[1] = makeRecord({ ok: false, category: 'other' });
115
+ writeJsonl(projectDir, records);
116
+ writeRunMeta(projectDir, { feature: 'x' });
117
+ runExtractor(projectDir);
118
+ expect(listRecipes(projectDir)).toHaveLength(0);
119
+ });
120
+
121
+ it('마지막 호출이 실패 → 생성 안 함 (task 미완료)', () => {
122
+ const records = [
123
+ ...Array.from({ length: 5 }, () => makeRecord({ ok: true })),
124
+ makeRecord({ ok: false, category: 'integration' }),
125
+ makeRecord({ ok: false, category: 'integration' }),
126
+ makeRecord({ ok: false, category: 'integration' }),
127
+ ];
128
+ writeJsonl(projectDir, records);
129
+ writeRunMeta(projectDir, { feature: 'x' });
130
+ runExtractor(projectDir);
131
+ expect(listRecipes(projectDir)).toHaveLength(0);
132
+ });
133
+ });
134
+
135
+ // ───────── frontmatter 검증 ─────────
136
+ describe('frontmatter schema', () => {
137
+ function makeQualifyingRun() {
138
+ const records = [
139
+ makeRecord({ tool: 'Bash', ok: false, category: 'integration' }),
140
+ makeRecord({ tool: 'Bash', ok: false, category: 'integration' }),
141
+ makeRecord({ tool: 'Edit', file: 'src/foo.ts', ok: false, category: 'type-narrow' }),
142
+ makeRecord({ tool: 'Edit', file: 'src/foo.ts', ok: true }),
143
+ makeRecord({ tool: 'Read', file: 'src/foo.ts', ok: true }),
144
+ makeRecord({ tool: 'Bash', ok: true }),
145
+ makeRecord({ tool: 'Bash', ok: true }),
146
+ makeRecord({ tool: 'Bash', ok: true }),
147
+ ];
148
+ writeJsonl(projectDir, records);
149
+ writeRunMeta(projectDir, { feature: 'login flow', startedAt: '2026-05-07T10:00:00.000Z', steps: 8 });
150
+ }
151
+
152
+ it('생성된 recipe 의 frontmatter 가 schema 충족', () => {
153
+ makeQualifyingRun();
154
+ runExtractor(projectDir);
155
+ const [filename] = listRecipes(projectDir);
156
+ const content = fs.readFileSync(path.join(projectDir, '.vibe', 'recipes', filename), 'utf-8');
157
+
158
+ expect(content).toMatch(/^---\n/);
159
+ expect(content).toMatch(/^slug: login-flow__\d{8}-\d{6}$/m);
160
+ expect(content).toMatch(/^type: recipe$/m);
161
+ expect(content).toMatch(/^symptom-context: "login flow"$/m);
162
+ expect(content).toMatch(/^recipe: ".+"$/m);
163
+ expect(content).toMatch(/^tools-touched: \[/m);
164
+ expect(content).toMatch(/^retry-count-saved: 3$/m);
165
+ expect(content).toMatch(/^created: \d{4}-\d{2}-\d{2}$/m);
166
+ expect(content).toMatch(/^source-run: "2026-05-07T10:00:00\.000Z"$/m);
167
+ expect(content).toMatch(/^confidence: low$/m);
168
+ });
169
+
170
+ it('파일명이 timestamp slug 포함', () => {
171
+ makeQualifyingRun();
172
+ runExtractor(projectDir);
173
+ const [filename] = listRecipes(projectDir);
174
+ expect(filename).toMatch(/^login-flow__\d{8}-\d{6}\.md$/);
175
+ });
176
+
177
+ it('feature 누락 시 anon slug', () => {
178
+ const records = Array.from({ length: 8 }, (_, i) => makeRecord({
179
+ ok: i < 3 ? false : true,
180
+ category: i < 3 ? 'integration' : null,
181
+ }));
182
+ writeJsonl(projectDir, records);
183
+ writeRunMeta(projectDir, { feature: null });
184
+ runExtractor(projectDir);
185
+ const [filename] = listRecipes(projectDir);
186
+ expect(filename).toMatch(/^anon__/);
187
+ });
188
+ });
189
+
190
+ // ───────── 안전성 ─────────
191
+ describe('silent fail 정책', () => {
192
+ it('jsonl 없음 → exit 0, 파일 생성 안 함', () => {
193
+ const r = runExtractor(projectDir);
194
+ expect(r.status).toBe(0);
195
+ expect(listRecipes(projectDir)).toHaveLength(0);
196
+ });
197
+
198
+ it('빈 jsonl → exit 0, 생성 안 함', () => {
199
+ writeJsonl(projectDir, []);
200
+ const r = runExtractor(projectDir);
201
+ expect(r.status).toBe(0);
202
+ expect(listRecipes(projectDir)).toHaveLength(0);
203
+ });
204
+
205
+ it('VIBE_HOOK_DEPTH≥1 → 재귀 가드, 생성 안 함', () => {
206
+ const records = [
207
+ ...Array.from({ length: 5 }, () => makeRecord({ ok: false, category: 'integration' })),
208
+ makeRecord({ ok: true }), makeRecord({ ok: true }), makeRecord({ ok: true }),
209
+ ];
210
+ writeJsonl(projectDir, records);
211
+ writeRunMeta(projectDir, { feature: 'x' });
212
+
213
+ const r = spawnSync('node', [SCRIPT], {
214
+ encoding: 'utf-8',
215
+ timeout: 5000,
216
+ env: {
217
+ ...process.env,
218
+ CLAUDE_PROJECT_DIR: projectDir,
219
+ VIBE_RECIPE_LLM: 'mock',
220
+ VIBE_HOOK_DEPTH: '1',
221
+ },
222
+ });
223
+ expect(r.status).toBe(0);
224
+ expect(listRecipes(projectDir)).toHaveLength(0);
225
+ });
226
+
227
+ it('손상된 jsonl 라인은 무시', () => {
228
+ const dir = path.join(projectDir, '.vibe', 'metrics');
229
+ fs.mkdirSync(dir, { recursive: true });
230
+ // 일부 라인 손상 + 8개 정상
231
+ const good = Array.from({ length: 8 }, (_, i) => JSON.stringify(makeRecord({
232
+ ok: i < 3 ? false : true,
233
+ category: i < 3 ? 'integration' : null,
234
+ })));
235
+ const lines = ['{ broken', ...good].join('\n') + '\n';
236
+ fs.writeFileSync(path.join(dir, 'current-run.jsonl'), lines);
237
+ writeRunMeta(projectDir, { feature: 'x' });
238
+
239
+ const r = runExtractor(projectDir);
240
+ expect(r.status).toBe(0);
241
+ expect(listRecipes(projectDir)).toHaveLength(1);
242
+ });
243
+ });
244
+ });