@su-record/vibe 2.13.0 → 2.14.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 (69) hide show
  1. package/CLAUDE.md +18 -15
  2. package/README.en.md +7 -5
  3. package/README.md +8 -6
  4. package/dist/cli/detect/matcher.d.ts +15 -0
  5. package/dist/cli/detect/matcher.d.ts.map +1 -0
  6. package/dist/cli/detect/matcher.js +278 -0
  7. package/dist/cli/detect/matcher.js.map +1 -0
  8. package/dist/cli/detect/signatures.d.ts +76 -0
  9. package/dist/cli/detect/signatures.d.ts.map +1 -0
  10. package/dist/cli/detect/signatures.js +175 -0
  11. package/dist/cli/detect/signatures.js.map +1 -0
  12. package/dist/cli/detect/workspace.d.ts +7 -0
  13. package/dist/cli/detect/workspace.d.ts.map +1 -0
  14. package/dist/cli/detect/workspace.js +112 -0
  15. package/dist/cli/detect/workspace.js.map +1 -0
  16. package/dist/cli/detect.characterization.test.d.ts +7 -0
  17. package/dist/cli/detect.characterization.test.d.ts.map +1 -0
  18. package/dist/cli/detect.characterization.test.js +294 -0
  19. package/dist/cli/detect.characterization.test.js.map +1 -0
  20. package/dist/cli/detect.d.ts.map +1 -1
  21. package/dist/cli/detect.js +64 -488
  22. package/dist/cli/detect.js.map +1 -1
  23. package/dist/cli/postinstall/constants.d.ts.map +1 -1
  24. package/dist/cli/postinstall/constants.js +1 -0
  25. package/dist/cli/postinstall/constants.js.map +1 -1
  26. package/dist/cli/setup/ProjectSetup.d.ts.map +1 -1
  27. package/dist/cli/setup/ProjectSetup.js +5 -4
  28. package/dist/cli/setup/ProjectSetup.js.map +1 -1
  29. package/dist/infra/lib/ui-ux/CsvDataLoader.d.ts +10 -1
  30. package/dist/infra/lib/ui-ux/CsvDataLoader.d.ts.map +1 -1
  31. package/dist/infra/lib/ui-ux/CsvDataLoader.js +11 -5
  32. package/dist/infra/lib/ui-ux/CsvDataLoader.js.map +1 -1
  33. package/dist/infra/lib/ui-ux/CsvDataLoader.test.js +8 -8
  34. package/dist/infra/lib/ui-ux/CsvDataLoader.test.js.map +1 -1
  35. package/dist/infra/lib/ui-ux/SearchService.test.js +1 -1
  36. package/dist/infra/lib/ui-ux/SearchService.test.js.map +1 -1
  37. package/dist/tools/index.d.ts +2 -0
  38. package/dist/tools/index.d.ts.map +1 -1
  39. package/dist/tools/index.js +2 -0
  40. package/dist/tools/index.js.map +1 -1
  41. package/dist/tools/loop/index.d.ts +6 -0
  42. package/dist/tools/loop/index.d.ts.map +1 -0
  43. package/dist/tools/loop/index.js +5 -0
  44. package/dist/tools/loop/index.js.map +1 -0
  45. package/dist/tools/loop/validateLoopDefinition.d.ts +38 -0
  46. package/dist/tools/loop/validateLoopDefinition.d.ts.map +1 -0
  47. package/dist/tools/loop/validateLoopDefinition.js +224 -0
  48. package/dist/tools/loop/validateLoopDefinition.js.map +1 -0
  49. package/dist/tools/loop/validateLoopDefinition.test.d.ts +14 -0
  50. package/dist/tools/loop/validateLoopDefinition.test.d.ts.map +1 -0
  51. package/dist/tools/loop/validateLoopDefinition.test.js +229 -0
  52. package/dist/tools/loop/validateLoopDefinition.test.js.map +1 -0
  53. package/hooks/scripts/__tests__/.vibe/command-log.txt +39 -0
  54. package/hooks/scripts/__tests__/.vibe/memories/memories.db-shm +0 -0
  55. package/hooks/scripts/__tests__/.vibe/memories/memories.db-wal +0 -0
  56. package/hooks/scripts/__tests__/keyword-detector.test.js +26 -18
  57. package/hooks/scripts/__tests__/loop-ledger.test.js +321 -0
  58. package/hooks/scripts/keyword-detector.js +22 -22
  59. package/hooks/scripts/lib/hook-context.js +31 -2
  60. package/hooks/scripts/lib/loop-ledger.js +118 -0
  61. package/hooks/scripts/loop-ledger.js +56 -0
  62. package/package.json +3 -2
  63. package/skills/vibe/SKILL.md +40 -23
  64. package/skills/vibe.loop/SKILL.md +116 -0
  65. package/skills/vibe.run/SKILL.md +22 -18
  66. package/skills/vibe.run/references/ralph-loop.md +18 -17
  67. package/skills/vibe.run/references/ultrawork-mode.md +36 -33
  68. package/vibe/rules/loop-contract.md +54 -0
  69. package/vibe/templates/loop-template.md +69 -0
@@ -0,0 +1,229 @@
1
+ /**
2
+ * validateLoopDefinition 테스트
3
+ *
4
+ * 커버리지:
5
+ * - 유효한 전체 정의 (scheduled + ledger, manual + tests, on-event + none)
6
+ * - 각 enum 위반
7
+ * - schedule iff scheduled 조건
8
+ * - test_command iff tests 조건
9
+ * - max_iterations 범위 (경계값 포함)
10
+ * - pipeline non-vibe 항목
11
+ * - 필수 필드 누락
12
+ */
13
+ import { describe, it, expect } from 'vitest';
14
+ import { validateLoopDefinition } from './validateLoopDefinition.js';
15
+ // ─── Fixture helpers ──────────────────────────────────────────────────
16
+ function makeContent(overrides = {}) {
17
+ const defaults = {
18
+ name: 'nightly-triage',
19
+ trigger: 'scheduled',
20
+ schedule: '0 2 * * *',
21
+ goal: '회귀 항목 자동 처리',
22
+ discover: '오픈 회귀 스캔',
23
+ verify: 'ledger',
24
+ max_iterations: 10,
25
+ isolation: 'none',
26
+ status: 'active',
27
+ };
28
+ const merged = { ...defaults, ...overrides };
29
+ const pipeline = merged['pipeline'] ?? ['vibe.spec', 'vibe.run', 'vibe.verify'];
30
+ delete merged['pipeline'];
31
+ let fm = '---\n';
32
+ for (const [k, v] of Object.entries(merged)) {
33
+ if (v === undefined)
34
+ continue;
35
+ fm += `${k}: ${v}\n`;
36
+ }
37
+ // pipeline 블록 시퀀스
38
+ if (Array.isArray(pipeline) && pipeline.length > 0) {
39
+ fm += 'pipeline:\n';
40
+ for (const item of pipeline) {
41
+ fm += ` - ${item}\n`;
42
+ }
43
+ }
44
+ fm += '---\n\n# 루프 본문\n';
45
+ return fm;
46
+ }
47
+ // ─── 유효한 정의 ──────────────────────────────────────────────────────
48
+ describe('validateLoopDefinition: 유효한 정의', () => {
49
+ it('scheduled + ledger 전체 정의 → valid=true, errors=[]', () => {
50
+ const result = validateLoopDefinition(makeContent());
51
+ expect(result.valid).toBe(true);
52
+ expect(result.errors).toHaveLength(0);
53
+ expect(result.definition).not.toBeNull();
54
+ expect(result.definition?.name).toBe('nightly-triage');
55
+ expect(result.definition?.trigger).toBe('scheduled');
56
+ expect(result.definition?.schedule).toBe('0 2 * * *');
57
+ expect(result.definition?.pipeline).toEqual(['vibe.spec', 'vibe.run', 'vibe.verify']);
58
+ expect(result.definition?.max_iterations).toBe(10);
59
+ });
60
+ it('manual + tests + test_command → valid=true', () => {
61
+ const content = makeContent({
62
+ trigger: 'manual',
63
+ schedule: undefined,
64
+ verify: 'tests',
65
+ test_command: 'npx vitest run',
66
+ });
67
+ const result = validateLoopDefinition(content);
68
+ expect(result.valid).toBe(true);
69
+ expect(result.definition?.trigger).toBe('manual');
70
+ expect(result.definition?.test_command).toBe('npx vitest run');
71
+ });
72
+ it('on-event + none + isolation=worktree → valid=true', () => {
73
+ const content = makeContent({
74
+ trigger: 'on-event',
75
+ schedule: undefined,
76
+ verify: 'none',
77
+ isolation: 'worktree',
78
+ });
79
+ const result = validateLoopDefinition(content);
80
+ expect(result.valid).toBe(true);
81
+ expect(result.definition?.isolation).toBe('worktree');
82
+ });
83
+ it('max_iterations 경계값 1 → valid=true', () => {
84
+ const result = validateLoopDefinition(makeContent({ max_iterations: 1 }));
85
+ expect(result.valid).toBe(true);
86
+ });
87
+ it('max_iterations 경계값 50 → valid=true', () => {
88
+ const result = validateLoopDefinition(makeContent({ max_iterations: 50 }));
89
+ expect(result.valid).toBe(true);
90
+ });
91
+ });
92
+ // ─── enum 위반 ────────────────────────────────────────────────────────
93
+ describe('validateLoopDefinition: enum 위반', () => {
94
+ it('trigger 유효하지 않은 값 → error 포함', () => {
95
+ const result = validateLoopDefinition(makeContent({ trigger: 'daily', schedule: undefined }));
96
+ expect(result.valid).toBe(false);
97
+ expect(result.errors.some((e) => e.includes('trigger'))).toBe(true);
98
+ });
99
+ it('verify 유효하지 않은 값 → error 포함', () => {
100
+ const result = validateLoopDefinition(makeContent({ verify: 'manual-check' }));
101
+ expect(result.valid).toBe(false);
102
+ expect(result.errors.some((e) => e.includes('verify'))).toBe(true);
103
+ });
104
+ it('isolation 유효하지 않은 값 → error 포함', () => {
105
+ const result = validateLoopDefinition(makeContent({ isolation: 'docker' }));
106
+ expect(result.valid).toBe(false);
107
+ expect(result.errors.some((e) => e.includes('isolation'))).toBe(true);
108
+ });
109
+ it('status 유효하지 않은 값 → error 포함', () => {
110
+ const result = validateLoopDefinition(makeContent({ status: 'running' }));
111
+ expect(result.valid).toBe(false);
112
+ expect(result.errors.some((e) => e.includes('status'))).toBe(true);
113
+ });
114
+ });
115
+ // ─── schedule iff scheduled ───────────────────────────────────────────
116
+ describe('validateLoopDefinition: schedule 조건', () => {
117
+ it('trigger=scheduled 인데 schedule 없으면 → error', () => {
118
+ const result = validateLoopDefinition(makeContent({ trigger: 'scheduled', schedule: undefined }));
119
+ expect(result.valid).toBe(false);
120
+ expect(result.errors.some((e) => e.includes('schedule'))).toBe(true);
121
+ });
122
+ it('trigger=scheduled + 잘못된 cron 형식 → error', () => {
123
+ const result = validateLoopDefinition(makeContent({ schedule: 'every day' }));
124
+ expect(result.valid).toBe(false);
125
+ expect(result.errors.some((e) => e.includes('cron'))).toBe(true);
126
+ });
127
+ it('trigger=manual 인데 schedule 있으면 → error', () => {
128
+ const content = makeContent({ trigger: 'manual', schedule: '0 2 * * *' });
129
+ const result = validateLoopDefinition(content);
130
+ expect(result.valid).toBe(false);
131
+ expect(result.errors.some((e) => e.includes('schedule'))).toBe(true);
132
+ });
133
+ it('trigger=on-event 인데 schedule 있으면 → error', () => {
134
+ const content = makeContent({ trigger: 'on-event', schedule: '0 2 * * *' });
135
+ const result = validateLoopDefinition(content);
136
+ expect(result.valid).toBe(false);
137
+ expect(result.errors.some((e) => e.includes('schedule'))).toBe(true);
138
+ });
139
+ });
140
+ // ─── test_command iff tests ───────────────────────────────────────────
141
+ describe('validateLoopDefinition: test_command 조건', () => {
142
+ it('verify=tests 인데 test_command 없으면 → error', () => {
143
+ const content = makeContent({
144
+ trigger: 'manual',
145
+ schedule: undefined,
146
+ verify: 'tests',
147
+ });
148
+ const result = validateLoopDefinition(content);
149
+ expect(result.valid).toBe(false);
150
+ expect(result.errors.some((e) => e.includes('test_command'))).toBe(true);
151
+ });
152
+ it('verify=ledger 인데 test_command 있으면 → error', () => {
153
+ const content = makeContent({ test_command: 'npm test' });
154
+ const result = validateLoopDefinition(content);
155
+ expect(result.valid).toBe(false);
156
+ expect(result.errors.some((e) => e.includes('test_command'))).toBe(true);
157
+ });
158
+ it('verify=none 인데 test_command 있으면 → error', () => {
159
+ const content = makeContent({
160
+ trigger: 'manual',
161
+ schedule: undefined,
162
+ verify: 'none',
163
+ test_command: 'npm test',
164
+ });
165
+ const result = validateLoopDefinition(content);
166
+ expect(result.valid).toBe(false);
167
+ expect(result.errors.some((e) => e.includes('test_command'))).toBe(true);
168
+ });
169
+ });
170
+ // ─── max_iterations 범위 ──────────────────────────────────────────────
171
+ describe('validateLoopDefinition: max_iterations 범위', () => {
172
+ it('max_iterations=0 → error', () => {
173
+ const result = validateLoopDefinition(makeContent({ max_iterations: 0 }));
174
+ expect(result.valid).toBe(false);
175
+ expect(result.errors.some((e) => e.includes('max_iterations'))).toBe(true);
176
+ });
177
+ it('max_iterations=51 → error', () => {
178
+ const result = validateLoopDefinition(makeContent({ max_iterations: 51 }));
179
+ expect(result.valid).toBe(false);
180
+ expect(result.errors.some((e) => e.includes('max_iterations'))).toBe(true);
181
+ });
182
+ it('max_iterations 누락 → error', () => {
183
+ const content = makeContent({ max_iterations: undefined });
184
+ const result = validateLoopDefinition(content);
185
+ expect(result.valid).toBe(false);
186
+ expect(result.errors.some((e) => e.includes('max_iterations'))).toBe(true);
187
+ });
188
+ });
189
+ // ─── pipeline non-vibe 항목 ───────────────────────────────────────────
190
+ describe('validateLoopDefinition: pipeline 항목 검사', () => {
191
+ it('pipeline에 non-vibe 항목 포함 → error', () => {
192
+ const content = makeContent({ pipeline: ['vibe.spec', 'npm-test', 'vibe.verify'] });
193
+ const result = validateLoopDefinition(content);
194
+ expect(result.valid).toBe(false);
195
+ expect(result.errors.some((e) => e.includes('npm-test'))).toBe(true);
196
+ });
197
+ it('pipeline 비어 있음 → error', () => {
198
+ const content = makeContent({ pipeline: [] });
199
+ const result = validateLoopDefinition(content);
200
+ expect(result.valid).toBe(false);
201
+ expect(result.errors.some((e) => e.includes('pipeline'))).toBe(true);
202
+ });
203
+ it('pipeline 모두 vibe. 접두사 → valid=true', () => {
204
+ const content = makeContent({ pipeline: ['vibe.analyze', 'vibe.run', 'vibe.verify'] });
205
+ const result = validateLoopDefinition(content);
206
+ expect(result.valid).toBe(true);
207
+ });
208
+ });
209
+ // ─── 필수 필드 누락 ───────────────────────────────────────────────────
210
+ describe('validateLoopDefinition: 필수 필드 누락', () => {
211
+ it('name 누락 → error', () => {
212
+ const content = makeContent({ name: undefined });
213
+ const result = validateLoopDefinition(content);
214
+ expect(result.valid).toBe(false);
215
+ expect(result.errors.some((e) => e.includes('name'))).toBe(true);
216
+ });
217
+ it('goal 누락 → error', () => {
218
+ const content = makeContent({ goal: undefined });
219
+ const result = validateLoopDefinition(content);
220
+ expect(result.valid).toBe(false);
221
+ expect(result.errors.some((e) => e.includes('goal'))).toBe(true);
222
+ });
223
+ it('frontmatter 없는 문서 → error 다수', () => {
224
+ const result = validateLoopDefinition('# 루프 본문만 있는 파일\n\n내용\n');
225
+ expect(result.valid).toBe(false);
226
+ expect(result.errors.length).toBeGreaterThan(0);
227
+ });
228
+ });
229
+ //# sourceMappingURL=validateLoopDefinition.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validateLoopDefinition.test.js","sourceRoot":"","sources":["../../../src/tools/loop/validateLoopDefinition.test.ts"],"names":[],"mappings":"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"}
@@ -37,3 +37,42 @@
37
37
  [2026-06-11T01:30:46.209Z] rm -rf /
38
38
  [2026-06-11T01:30:46.279Z] ls -la
39
39
  [2026-06-11T01:30:46.366Z] rm -rf src/infra/lib/evolution/
40
+ [2026-06-11T05:39:24.632Z] rm -rf /
41
+ [2026-06-11T05:39:24.707Z] ls -la
42
+ [2026-06-11T05:39:24.788Z] rm -rf src/infra/lib/evolution/
43
+ [2026-06-11T05:42:56.571Z] rm -rf /
44
+ [2026-06-11T05:42:56.647Z] ls -la
45
+ [2026-06-11T05:42:56.719Z] rm -rf src/infra/lib/evolution/
46
+ [2026-06-11T05:43:10.797Z] rm -rf /
47
+ [2026-06-11T05:43:10.863Z] ls -la
48
+ [2026-06-11T05:43:10.937Z] rm -rf src/infra/lib/evolution/
49
+ [2026-06-11T05:43:26.675Z] rm -rf /
50
+ [2026-06-11T05:43:26.735Z] ls -la
51
+ [2026-06-11T05:43:26.812Z] rm -rf src/infra/lib/evolution/
52
+ [2026-06-11T06:34:26.211Z] rm -rf /
53
+ [2026-06-11T06:34:26.309Z] ls -la
54
+ [2026-06-11T06:34:26.395Z] rm -rf src/infra/lib/evolution/
55
+ [2026-06-11T06:34:42.990Z] rm -rf /
56
+ [2026-06-11T06:34:43.071Z] ls -la
57
+ [2026-06-11T06:34:43.148Z] rm -rf src/infra/lib/evolution/
58
+ [2026-06-11T06:36:18.231Z] rm -rf /
59
+ [2026-06-11T06:36:18.309Z] ls -la
60
+ [2026-06-11T06:36:18.387Z] rm -rf src/infra/lib/evolution/
61
+ [2026-06-11T07:31:46.181Z] rm -rf /
62
+ [2026-06-11T07:31:46.265Z] ls -la
63
+ [2026-06-11T07:31:46.343Z] rm -rf src/infra/lib/evolution/
64
+ [2026-06-11T07:47:25.041Z] rm -rf /
65
+ [2026-06-11T07:47:25.127Z] ls -la
66
+ [2026-06-11T07:47:25.229Z] rm -rf src/infra/lib/evolution/
67
+ [2026-06-11T07:52:00.840Z] rm -rf /
68
+ [2026-06-11T07:52:00.919Z] ls -la
69
+ [2026-06-11T07:52:00.992Z] rm -rf src/infra/lib/evolution/
70
+ [2026-06-11T07:52:09.088Z] rm -rf /
71
+ [2026-06-11T07:52:09.162Z] ls -la
72
+ [2026-06-11T07:52:09.229Z] rm -rf src/infra/lib/evolution/
73
+ [2026-06-11T07:52:48.347Z] rm -rf /
74
+ [2026-06-11T07:52:48.431Z] ls -la
75
+ [2026-06-11T07:52:48.509Z] rm -rf src/infra/lib/evolution/
76
+ [2026-06-11T07:53:35.344Z] rm -rf /
77
+ [2026-06-11T07:53:35.434Z] ls -la
78
+ [2026-06-11T07:53:35.516Z] rm -rf src/infra/lib/evolution/
@@ -27,28 +27,30 @@ function runDetector(text) {
27
27
  // ══════════════════════════════════════════════════
28
28
  describe('keyword-detector', () => {
29
29
  describe('ralph keyword', () => {
30
- it('should detect ralph keyword', () => {
30
+ it('should detect ralph keyword and emit deprecation hint', () => {
31
31
  const result = runDetector('implement the login feature ralph');
32
- expect(result.stdout).toContain('[RALPH MODE]');
32
+ expect(result.stdout).toContain('[vibe]');
33
+ expect(result.stdout).toContain('deprecated');
33
34
  expect(result.stdout).toContain('persistence');
34
35
  });
35
36
 
36
37
  it('should detect ralph case-insensitively', () => {
37
38
  const result = runDetector('RALPH fix all the bugs');
38
- expect(result.stdout).toContain('[RALPH MODE]');
39
+ expect(result.stdout).toContain('[vibe]');
40
+ expect(result.stdout).toContain('deprecated');
39
41
  });
40
42
  });
41
43
 
42
44
  describe('ultrawork keyword', () => {
43
- it('should detect ultrawork keyword', () => {
45
+ it('should detect ultrawork keyword and emit automationLevel banner', () => {
44
46
  const result = runDetector('ultrawork build the entire app');
45
- expect(result.stdout).toContain('[ULTRAWORK MODE]');
47
+ expect(result.stdout).toContain('[ULTRAWORK]');
46
48
  expect(result.stdout).toContain('parallel');
47
49
  });
48
50
 
49
51
  it('should detect ulw alias', () => {
50
52
  const result = runDetector('ulw refactor the codebase');
51
- expect(result.stdout).toContain('[ULTRAWORK MODE]');
53
+ expect(result.stdout).toContain('[ULTRAWORK]');
52
54
  });
53
55
 
54
56
  it('should detect Korean alias when word boundary matches', () => {
@@ -74,28 +76,32 @@ describe('keyword-detector', () => {
74
76
  // strict 키워드(일상어): 명령 끝 위치 또는 --flag 에서만 발동.
75
77
  // 일상 영어("please verify", "quick question")의 오탐을 막기 위함.
76
78
  describe('verify keyword (strict)', () => {
77
- it('should detect verify at command tail', () => {
79
+ it('should detect verify at command tail and emit deprecation hint', () => {
78
80
  const result = runDetector('make the implementation correct, verify');
79
- expect(result.stdout).toContain('[VERIFY MODE]');
81
+ expect(result.stdout).toContain('[vibe]');
82
+ expect(result.stdout).toContain('deprecated');
80
83
  expect(result.stdout).toContain('verification');
81
84
  });
82
85
 
83
86
  it('should detect --verify flag', () => {
84
87
  const result = runDetector('fix the bug --verify');
85
- expect(result.stdout).toContain('[VERIFY MODE]');
88
+ expect(result.stdout).toContain('[vibe]');
89
+ expect(result.stdout).toContain('deprecated');
86
90
  });
87
91
  });
88
92
 
89
93
  describe('quick keyword (strict)', () => {
90
- it('should detect quick at command tail', () => {
94
+ it('should detect quick at command tail and emit --max-iter 1 hint', () => {
91
95
  const result = runDetector('fix this typo quick');
92
- expect(result.stdout).toContain('[QUICK MODE]');
96
+ expect(result.stdout).toContain('[vibe]');
97
+ expect(result.stdout).toContain('--max-iter 1');
93
98
  expect(result.stdout).toContain('fast');
94
99
  });
95
100
 
96
101
  it('should detect --quick flag', () => {
97
102
  const result = runDetector('build the payment API --quick');
98
- expect(result.stdout).toContain('[QUICK MODE]');
103
+ expect(result.stdout).toContain('[vibe]');
104
+ expect(result.stdout).toContain('--max-iter 1');
99
105
  });
100
106
  });
101
107
 
@@ -140,17 +146,19 @@ describe('keyword-detector', () => {
140
146
  // Keyword combinations / synergies
141
147
  // ══════════════════════════════════════════════════
142
148
  describe('keyword combinations', () => {
143
- it('should detect ralph+ultrawork synergy', () => {
149
+ it('should detect ralph+ultrawork synergy and emit deprecation hint', () => {
144
150
  const result = runDetector('ralph ultrawork build everything from scratch');
145
- expect(result.stdout).toContain('[RALPH+ULTRAWORK]');
151
+ expect(result.stdout).toContain('[vibe]');
152
+ expect(result.stdout).toContain('deprecated');
146
153
  expect(result.stdout).toContain('persistence');
147
154
  expect(result.stdout).toContain('parallel');
148
155
  });
149
156
 
150
- it('should detect ralph+verify synergy', () => {
157
+ it('should detect ralph+verify synergy and emit deprecation hint', () => {
151
158
  // verify is strict → use --verify flag (ralph stays bare)
152
159
  const result = runDetector('ralph fix each step --verify');
153
- expect(result.stdout).toContain('[RALPH+VERIFY]');
160
+ expect(result.stdout).toContain('[vibe]');
161
+ expect(result.stdout).toContain('deprecated');
154
162
  });
155
163
 
156
164
  it('should output both keywords when no synergy key matches sorted order', () => {
@@ -158,7 +166,7 @@ describe('keyword-detector', () => {
158
166
  // sorts keywords alphabetically → tries 'explore+ultrawork' which has no match.
159
167
  // So individual outputs are emitted instead. explore is strict → --explore.
160
168
  const result = runDetector('ultrawork analyze the entire project --explore');
161
- expect(result.stdout).toContain('[ULTRAWORK MODE]');
169
+ expect(result.stdout).toContain('[ULTRAWORK]');
162
170
  expect(result.stdout).toContain('[EXPLORE MODE]');
163
171
  expect(result.stdout).toContain('[FLAGS]');
164
172
  });
@@ -224,7 +232,7 @@ describe('keyword-detector', () => {
224
232
  });
225
233
 
226
234
  it('should merge flags from multiple keywords', () => {
227
- // quick is strict → place at command tail
235
+ // quick is strict → place at command tail; ralph stays bare
228
236
  const result = runDetector('ralph finish this quick');
229
237
  expect(result.stdout).toContain('[FLAGS]');
230
238
  expect(result.stdout).toContain('persistence');