oh-my-claude-sisyphus 3.7.16 → 3.8.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 (49) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/README.md +8 -6
  4. package/agents/AGENTS.md +8 -8
  5. package/agents/architect.md +32 -0
  6. package/agents/build-fixer.md +35 -0
  7. package/agents/code-reviewer.md +51 -0
  8. package/agents/executor-high.md +49 -0
  9. package/agents/explore-high.md +39 -0
  10. package/agents/explore-medium.md +33 -0
  11. package/dist/__tests__/hooks/learner/bridge.test.js +13 -7
  12. package/dist/__tests__/hooks/learner/bridge.test.js.map +1 -1
  13. package/dist/__tests__/hooks.test.js +306 -67
  14. package/dist/__tests__/hooks.test.js.map +1 -1
  15. package/dist/__tests__/installer.test.js +31 -15
  16. package/dist/__tests__/installer.test.js.map +1 -1
  17. package/dist/hooks/bridge.js +3 -3
  18. package/dist/hooks/bridge.js.map +1 -1
  19. package/dist/hooks/clear-suggestions/constants.d.ts +54 -0
  20. package/dist/hooks/clear-suggestions/constants.d.ts.map +1 -0
  21. package/dist/hooks/clear-suggestions/constants.js +102 -0
  22. package/dist/hooks/clear-suggestions/constants.js.map +1 -0
  23. package/dist/hooks/clear-suggestions/index.d.ts +61 -0
  24. package/dist/hooks/clear-suggestions/index.d.ts.map +1 -0
  25. package/dist/hooks/clear-suggestions/index.js +276 -0
  26. package/dist/hooks/clear-suggestions/index.js.map +1 -0
  27. package/dist/hooks/clear-suggestions/triggers.d.ts +65 -0
  28. package/dist/hooks/clear-suggestions/triggers.d.ts.map +1 -0
  29. package/dist/hooks/clear-suggestions/triggers.js +222 -0
  30. package/dist/hooks/clear-suggestions/triggers.js.map +1 -0
  31. package/dist/hooks/clear-suggestions/types.d.ts +92 -0
  32. package/dist/hooks/clear-suggestions/types.d.ts.map +1 -0
  33. package/dist/hooks/clear-suggestions/types.js +9 -0
  34. package/dist/hooks/clear-suggestions/types.js.map +1 -0
  35. package/dist/hooks/index.d.ts +1 -0
  36. package/dist/hooks/index.d.ts.map +1 -1
  37. package/dist/hooks/index.js +3 -0
  38. package/dist/hooks/index.js.map +1 -1
  39. package/dist/hooks/keyword-detector/__tests__/index.test.js +51 -51
  40. package/dist/hooks/keyword-detector/__tests__/index.test.js.map +1 -1
  41. package/dist/hooks/keyword-detector/index.d.ts +1 -1
  42. package/dist/hooks/keyword-detector/index.d.ts.map +1 -1
  43. package/dist/hooks/keyword-detector/index.js +18 -5
  44. package/dist/hooks/keyword-detector/index.js.map +1 -1
  45. package/docs/CLAUDE.md +83 -0
  46. package/package.json +1 -1
  47. package/scripts/keyword-detector.mjs +203 -83
  48. package/scripts/post-tool-verifier.mjs +39 -1
  49. package/templates/hooks/keyword-detector.sh +197 -31
@@ -108,53 +108,33 @@ describe('Keyword Detector', () => {
108
108
  expect(detected[0].keyword).toBe('ultrathink');
109
109
  });
110
110
  it('should detect think keyword', () => {
111
- const detected = detectKeywordsWithType('Let me think about it');
111
+ const detected = detectKeywordsWithType('Let me think hard about it');
112
112
  expect(detected).toHaveLength(1);
113
113
  expect(detected[0].type).toBe('ultrathink');
114
- expect(detected[0].keyword).toBe('think');
114
+ expect(detected[0].keyword).toBe('think hard');
115
115
  });
116
- it('should detect search keywords', () => {
117
- const searchTerms = ['search', 'find', 'locate', 'lookup', 'explore'];
118
- for (const term of searchTerms) {
119
- const detected = detectKeywordsWithType(`Please ${term} this file`);
120
- expect(detected).toHaveLength(1);
121
- expect(detected[0].type).toBe('search');
122
- expect(detected[0].keyword).toBe(term);
123
- }
124
- });
125
- it('should detect search patterns', () => {
116
+ it('should detect deepsearch keywords for codebase search', () => {
126
117
  const patterns = [
127
- 'where is the config',
128
- 'show me all files',
129
- 'list all functions'
118
+ 'search the codebase',
119
+ 'find in codebase',
120
+ 'search code for pattern'
130
121
  ];
131
122
  for (const pattern of patterns) {
132
123
  const detected = detectKeywordsWithType(pattern);
133
124
  expect(detected.length).toBeGreaterThan(0);
134
- const hasSearchType = detected.some(d => d.type === 'search');
135
- expect(hasSearchType).toBe(true);
136
- }
137
- });
138
- it('should detect analyze keywords', () => {
139
- const analyzeTerms = ['analyze', 'investigate', 'examine', 'debug'];
140
- for (const term of analyzeTerms) {
141
- const detected = detectKeywordsWithType(`Please ${term} this code`);
142
- expect(detected).toHaveLength(1);
143
- expect(detected[0].type).toBe('analyze');
144
- expect(detected[0].keyword).toBe(term);
125
+ expect(detected[0].type).toBe('deepsearch');
145
126
  }
146
127
  });
147
- it('should detect analyze patterns', () => {
128
+ it('should detect analyze keywords with restricted patterns', () => {
148
129
  const patterns = [
149
- 'why is this failing',
150
- 'how does this work',
151
- 'how to implement this'
130
+ 'deep analyze this code',
131
+ 'investigate the bug',
132
+ 'debug the issue'
152
133
  ];
153
134
  for (const pattern of patterns) {
154
135
  const detected = detectKeywordsWithType(pattern);
155
136
  expect(detected.length).toBeGreaterThan(0);
156
- const hasAnalyzeType = detected.some(d => d.type === 'analyze');
157
- expect(hasAnalyzeType).toBe(true);
137
+ expect(detected[0].type).toBe('analyze');
158
138
  }
159
139
  });
160
140
  it('should be case insensitive', () => {
@@ -173,27 +153,215 @@ describe('Keyword Detector', () => {
173
153
  expect(detected[0].keyword).toBe('ultrawork');
174
154
  });
175
155
  it('should include position information', () => {
176
- const detected = detectKeywordsWithType('Start search here');
177
- expect(detected[0].position).toBe(6); // Position of 'search'
156
+ const detected = detectKeywordsWithType('Start search the codebase here');
157
+ expect(detected[0].position).toBeGreaterThanOrEqual(0);
178
158
  });
179
159
  it('should return empty array for no matches', () => {
180
160
  const detected = detectKeywordsWithType('Just plain text');
181
161
  expect(detected).toEqual([]);
182
162
  });
183
163
  it('should detect multiple different keyword types', () => {
184
- const text = 'search and analyze this code';
164
+ const text = 'search the codebase and investigate the bug';
185
165
  const detected = detectKeywordsWithType(text);
186
166
  expect(detected.length).toBeGreaterThanOrEqual(2);
187
167
  const types = detected.map(d => d.type);
188
- expect(types).toContain('search');
168
+ expect(types).toContain('deepsearch');
189
169
  expect(types).toContain('analyze');
190
170
  });
171
+ // New keyword types tests
172
+ it('should detect cancel keyword', () => {
173
+ const detected = detectKeywordsWithType('stop this task');
174
+ expect(detected).toHaveLength(1);
175
+ expect(detected[0].type).toBe('cancel');
176
+ expect(detected[0].keyword).toBe('stop');
177
+ });
178
+ it('should detect cancel keyword variations', () => {
179
+ const cancelTerms = ['stop', 'cancel', 'abort'];
180
+ for (const term of cancelTerms) {
181
+ const detected = detectKeywordsWithType(`Please ${term} the process`);
182
+ expect(detected).toHaveLength(1);
183
+ expect(detected[0].type).toBe('cancel');
184
+ expect(detected[0].keyword).toBe(term);
185
+ }
186
+ });
187
+ it('should detect ultrapilot keyword', () => {
188
+ const detected = detectKeywordsWithType('use ultrapilot for this');
189
+ expect(detected).toHaveLength(1);
190
+ expect(detected[0].type).toBe('ultrapilot');
191
+ expect(detected[0].keyword).toBe('ultrapilot');
192
+ });
193
+ it('should detect ultrapilot patterns', () => {
194
+ const patterns = [
195
+ 'ultrapilot this project',
196
+ 'parallel build the app',
197
+ 'swarm build the system'
198
+ ];
199
+ for (const pattern of patterns) {
200
+ const detected = detectKeywordsWithType(pattern);
201
+ expect(detected.length).toBeGreaterThan(0);
202
+ const hasUltrapilot = detected.some(d => d.type === 'ultrapilot');
203
+ expect(hasUltrapilot).toBe(true);
204
+ }
205
+ });
206
+ it('should detect ecomode keyword', () => {
207
+ const detected = detectKeywordsWithType('use ecomode for this');
208
+ expect(detected).toHaveLength(1);
209
+ expect(detected[0].type).toBe('ecomode');
210
+ expect(detected[0].keyword).toBe('ecomode');
211
+ });
212
+ it('should detect ecomode variations', () => {
213
+ const ecoTerms = ['eco', 'ecomode', 'efficient', 'save-tokens', 'budget'];
214
+ for (const term of ecoTerms) {
215
+ const detected = detectKeywordsWithType(`Use ${term} mode`);
216
+ expect(detected).toHaveLength(1);
217
+ expect(detected[0].type).toBe('ecomode');
218
+ expect(detected[0].keyword).toBe(term);
219
+ }
220
+ });
221
+ it('should detect swarm keyword', () => {
222
+ const detected = detectKeywordsWithType('swarm 5 agents to fix this');
223
+ expect(detected).toHaveLength(1);
224
+ expect(detected[0].type).toBe('swarm');
225
+ expect(detected[0].keyword).toBe('swarm 5 agents');
226
+ });
227
+ it('should detect coordinated agents pattern', () => {
228
+ const detected = detectKeywordsWithType('use coordinated agents');
229
+ expect(detected).toHaveLength(1);
230
+ expect(detected[0].type).toBe('swarm');
231
+ expect(detected[0].keyword).toBe('coordinated agents');
232
+ });
233
+ it('should detect pipeline keyword', () => {
234
+ const detected = detectKeywordsWithType('pipeline this task');
235
+ expect(detected).toHaveLength(1);
236
+ expect(detected[0].type).toBe('pipeline');
237
+ expect(detected[0].keyword).toBe('pipeline');
238
+ });
239
+ it('should detect chain agents pattern', () => {
240
+ const detected = detectKeywordsWithType('chain agents together');
241
+ expect(detected).toHaveLength(1);
242
+ expect(detected[0].type).toBe('pipeline');
243
+ expect(detected[0].keyword).toBe('chain agents');
244
+ });
245
+ it('should detect ralplan keyword', () => {
246
+ const detected = detectKeywordsWithType('ralplan this feature');
247
+ expect(detected).toHaveLength(1);
248
+ expect(detected[0].type).toBe('ralplan');
249
+ expect(detected[0].keyword).toBe('ralplan');
250
+ });
251
+ it('should detect plan patterns', () => {
252
+ const patterns = [
253
+ 'plan this feature',
254
+ 'plan the refactoring'
255
+ ];
256
+ for (const pattern of patterns) {
257
+ const detected = detectKeywordsWithType(pattern);
258
+ expect(detected.length).toBeGreaterThan(0);
259
+ const hasPlan = detected.some(d => d.type === 'plan');
260
+ expect(hasPlan).toBe(true);
261
+ }
262
+ });
263
+ it('should detect tdd keyword', () => {
264
+ const detected = detectKeywordsWithType('use tdd for this');
265
+ expect(detected).toHaveLength(1);
266
+ expect(detected[0].type).toBe('tdd');
267
+ expect(detected[0].keyword).toBe('tdd');
268
+ });
269
+ it('should detect tdd patterns', () => {
270
+ const patterns = [
271
+ 'test first development',
272
+ 'red green refactor'
273
+ ];
274
+ for (const pattern of patterns) {
275
+ const detected = detectKeywordsWithType(pattern);
276
+ expect(detected.length).toBeGreaterThan(0);
277
+ const hasTDD = detected.some(d => d.type === 'tdd');
278
+ expect(hasTDD).toBe(true);
279
+ }
280
+ });
281
+ it('should detect research keyword', () => {
282
+ const detected = detectKeywordsWithType('research this topic');
283
+ expect(detected).toHaveLength(1);
284
+ expect(detected[0].type).toBe('research');
285
+ expect(detected[0].keyword).toBe('research');
286
+ });
287
+ it('should detect research patterns', () => {
288
+ const patterns = [
289
+ 'analyze data from the file',
290
+ 'run statistics on this'
291
+ ];
292
+ for (const pattern of patterns) {
293
+ const detected = detectKeywordsWithType(pattern);
294
+ expect(detected.length).toBeGreaterThan(0);
295
+ const hasResearch = detected.some(d => d.type === 'research');
296
+ expect(hasResearch).toBe(true);
297
+ }
298
+ });
299
+ it('should detect deepsearch keyword', () => {
300
+ const detected = detectKeywordsWithType('deepsearch for the pattern');
301
+ expect(detected).toHaveLength(1);
302
+ expect(detected[0].type).toBe('deepsearch');
303
+ expect(detected[0].keyword).toBe('deepsearch');
304
+ });
305
+ it('should detect deepsearch patterns', () => {
306
+ const patterns = [
307
+ 'search the codebase for errors',
308
+ 'search codebase for pattern',
309
+ 'find in codebase',
310
+ 'find in all files'
311
+ ];
312
+ for (const pattern of patterns) {
313
+ const detected = detectKeywordsWithType(pattern);
314
+ expect(detected.length).toBeGreaterThan(0);
315
+ const hasDeepsearch = detected.some(d => d.type === 'deepsearch');
316
+ expect(hasDeepsearch).toBe(true);
317
+ }
318
+ });
319
+ it('should NOT detect deepsearch for generic find', () => {
320
+ const patterns = [
321
+ 'find the file',
322
+ 'find this function',
323
+ 'search for help'
324
+ ];
325
+ for (const pattern of patterns) {
326
+ const detected = detectKeywordsWithType(pattern);
327
+ const hasDeepsearch = detected.some(d => d.type === 'deepsearch');
328
+ expect(hasDeepsearch).toBe(false);
329
+ }
330
+ });
331
+ it('should detect analyze patterns with restrictions', () => {
332
+ const patterns = [
333
+ 'deep analyze this code',
334
+ 'investigate the bug',
335
+ 'investigate this issue',
336
+ 'debug the problem',
337
+ 'debug this error'
338
+ ];
339
+ for (const pattern of patterns) {
340
+ const detected = detectKeywordsWithType(pattern);
341
+ expect(detected.length).toBeGreaterThan(0);
342
+ const hasAnalyze = detected.some(d => d.type === 'analyze');
343
+ expect(hasAnalyze).toBe(true);
344
+ }
345
+ });
346
+ it('should NOT detect analyze for generic patterns', () => {
347
+ const patterns = [
348
+ 'how to do this',
349
+ 'understand this code',
350
+ 'review this code',
351
+ 'analyze without context'
352
+ ];
353
+ for (const pattern of patterns) {
354
+ const detected = detectKeywordsWithType(pattern);
355
+ const hasAnalyze = detected.some(d => d.type === 'analyze');
356
+ expect(hasAnalyze).toBe(false);
357
+ }
358
+ });
191
359
  });
192
360
  describe('hasKeyword', () => {
193
361
  it('should return true when keyword exists', () => {
194
362
  expect(hasKeyword('use ultrawork mode')).toBe(true);
195
- expect(hasKeyword('search for files')).toBe(true);
196
- expect(hasKeyword('analyze this')).toBe(true);
363
+ expect(hasKeyword('search the codebase')).toBe(true);
364
+ expect(hasKeyword('investigate the bug')).toBe(true);
197
365
  });
198
366
  it('should return false when no keyword exists', () => {
199
367
  expect(hasKeyword('just normal text')).toBe(false);
@@ -204,7 +372,7 @@ describe('Keyword Detector', () => {
204
372
  expect(hasKeyword(text)).toBe(false);
205
373
  });
206
374
  it('should detect keywords outside code blocks', () => {
207
- const text = 'Please search\n```\nsome code\n```\nfor this';
375
+ const text = 'Please search the codebase\n```\nsome code\n```\nfor this';
208
376
  expect(hasKeyword(text)).toBe(true);
209
377
  });
210
378
  it('should handle empty string', () => {
@@ -219,20 +387,20 @@ describe('Keyword Detector', () => {
219
387
  expect(primary).not.toBeNull();
220
388
  expect(primary.type).toBe('ultrawork');
221
389
  });
222
- it('should return ultrathink when no ultrawork', () => {
223
- const text = 'search and think about this';
390
+ it('should return ultrathink when present', () => {
391
+ const text = 'think hard about this problem';
224
392
  const primary = getPrimaryKeyword(text);
225
393
  expect(primary).not.toBeNull();
226
394
  expect(primary.type).toBe('ultrathink');
227
395
  });
228
- it('should return search when only search keyword', () => {
229
- const text = 'find all files';
396
+ it('should return deepsearch for codebase search', () => {
397
+ const text = 'find in codebase';
230
398
  const primary = getPrimaryKeyword(text);
231
399
  expect(primary).not.toBeNull();
232
- expect(primary.type).toBe('search');
400
+ expect(primary.type).toBe('deepsearch');
233
401
  });
234
402
  it('should return analyze when only analyze keyword', () => {
235
- const text = 'investigate this issue';
403
+ const text = 'investigate the issue';
236
404
  const primary = getPrimaryKeyword(text);
237
405
  expect(primary).not.toBeNull();
238
406
  expect(primary.type).toBe('analyze');
@@ -242,18 +410,89 @@ describe('Keyword Detector', () => {
242
410
  expect(primary).toBeNull();
243
411
  });
244
412
  it('should ignore code blocks', () => {
245
- const text = '```\nultrawork code\n```\nsearch this';
413
+ const text = '```\nultrawork code\n```\nsearch the codebase';
246
414
  const primary = getPrimaryKeyword(text);
247
415
  expect(primary).not.toBeNull();
248
- expect(primary.type).toBe('search');
416
+ expect(primary.type).toBe('deepsearch');
249
417
  });
250
418
  it('should return first detected when same priority', () => {
251
- // Both search and analyze have same priority
252
- const text = 'search and analyze';
419
+ // deepsearch has higher priority than analyze in the priority list
420
+ const text = 'search the codebase and investigate the bug';
253
421
  const primary = getPrimaryKeyword(text);
254
422
  expect(primary).not.toBeNull();
255
- // Should return search as it comes first in priority list
256
- expect(primary.type).toBe('search');
423
+ // Should return deepsearch as it comes first in priority list
424
+ expect(primary.type).toBe('deepsearch');
425
+ });
426
+ // New priority tests for new keywords
427
+ it('should give cancel highest priority', () => {
428
+ const primary = getPrimaryKeyword('stop searching for files');
429
+ expect(primary).not.toBeNull();
430
+ expect(primary.type).toBe('cancel');
431
+ });
432
+ it('should give cancel priority over analyze', () => {
433
+ const primary = getPrimaryKeyword('cancel this investigation');
434
+ expect(primary).not.toBeNull();
435
+ expect(primary.type).toBe('cancel');
436
+ });
437
+ it('should prioritize cancel over all other keywords', () => {
438
+ const primary = getPrimaryKeyword('stop ultrawork and search');
439
+ expect(primary).not.toBeNull();
440
+ expect(primary.type).toBe('cancel');
441
+ });
442
+ it('should prioritize ralph after cancel', () => {
443
+ const primary = getPrimaryKeyword('ralph mode for the task');
444
+ expect(primary).not.toBeNull();
445
+ expect(primary.type).toBe('ralph');
446
+ });
447
+ it('should prioritize ultrapilot correctly', () => {
448
+ const primary = getPrimaryKeyword('ultrapilot this task');
449
+ expect(primary).not.toBeNull();
450
+ expect(primary.type).toBe('ultrapilot');
451
+ });
452
+ it('should prioritize ecomode correctly', () => {
453
+ const primary = getPrimaryKeyword('use efficient mode for this');
454
+ expect(primary).not.toBeNull();
455
+ expect(primary.type).toBe('ecomode');
456
+ });
457
+ it('should prioritize swarm correctly', () => {
458
+ const primary = getPrimaryKeyword('swarm 5 agents for this');
459
+ expect(primary).not.toBeNull();
460
+ expect(primary.type).toBe('swarm');
461
+ });
462
+ it('should prioritize pipeline correctly', () => {
463
+ const primary = getPrimaryKeyword('pipeline the task');
464
+ expect(primary).not.toBeNull();
465
+ expect(primary.type).toBe('pipeline');
466
+ });
467
+ it('should prioritize ralplan over plan', () => {
468
+ const primary = getPrimaryKeyword('ralplan this project');
469
+ expect(primary).not.toBeNull();
470
+ expect(primary.type).toBe('ralplan');
471
+ });
472
+ it('should detect plan correctly', () => {
473
+ const primary = getPrimaryKeyword('plan this feature');
474
+ expect(primary).not.toBeNull();
475
+ expect(primary.type).toBe('plan');
476
+ });
477
+ it('should prioritize tdd correctly', () => {
478
+ const primary = getPrimaryKeyword('tdd for this feature');
479
+ expect(primary).not.toBeNull();
480
+ expect(primary.type).toBe('tdd');
481
+ });
482
+ it('should prioritize research correctly', () => {
483
+ const primary = getPrimaryKeyword('research this topic');
484
+ expect(primary).not.toBeNull();
485
+ expect(primary.type).toBe('research');
486
+ });
487
+ it('should prioritize deepsearch over generic search', () => {
488
+ const primary = getPrimaryKeyword('search the codebase');
489
+ expect(primary).not.toBeNull();
490
+ expect(primary.type).toBe('deepsearch');
491
+ });
492
+ it('should prioritize analyze with restricted pattern', () => {
493
+ const primary = getPrimaryKeyword('investigate the bug');
494
+ expect(primary).not.toBeNull();
495
+ expect(primary.type).toBe('analyze');
257
496
  });
258
497
  });
259
498
  });
@@ -577,7 +816,7 @@ describe('Hook Output Structure', () => {
577
816
  describe('Integration: Keyword Detection with Code Blocks', () => {
578
817
  it('should detect keywords outside code and ignore inside', () => {
579
818
  const text = `
580
- Please search for files
819
+ Please search the codebase
581
820
 
582
821
  \`\`\`javascript
583
822
  // This search should be ignored
@@ -586,25 +825,25 @@ function search() {
586
825
  }
587
826
  \`\`\`
588
827
 
589
- Now analyze the results
828
+ Now investigate the bug
590
829
  `;
591
830
  const detected = detectKeywordsWithType(removeCodeBlocks(text));
592
831
  const types = detected.map(d => d.type);
593
- expect(types).toContain('search');
832
+ expect(types).toContain('deepsearch');
594
833
  expect(types).toContain('analyze');
595
834
  // Should only detect the ones outside code blocks
596
- expect(detected.filter(d => d.type === 'search')).toHaveLength(1);
835
+ expect(detected.filter(d => d.type === 'deepsearch')).toHaveLength(1);
597
836
  expect(detected.filter(d => d.type === 'analyze')).toHaveLength(1);
598
837
  });
599
838
  it('should handle inline code with keywords', () => {
600
- const text = 'Use the `search` command to find files';
839
+ const text = 'Use the `deepsearch` command to find in codebase';
601
840
  const cleanText = removeCodeBlocks(text);
602
841
  const detected = detectKeywordsWithType(cleanText);
603
- // The word 'find' should still be detected
604
- expect(detected.some(d => d.type === 'search')).toBe(true);
842
+ // The phrase 'find in codebase' should still be detected
843
+ expect(detected.some(d => d.type === 'deepsearch')).toBe(true);
605
844
  });
606
845
  it('should prioritize ultrawork even with other keywords', () => {
607
- const text = 'search, analyze, and use ultrawork mode';
846
+ const text = 'search the codebase, investigate the bug, and use ultrawork mode';
608
847
  const primary = getPrimaryKeyword(text);
609
848
  expect(primary).not.toBeNull();
610
849
  expect(primary.type).toBe('ultrawork');
@@ -631,33 +870,33 @@ describe('Edge Cases', () => {
631
870
  });
632
871
  describe('Whitespace handling', () => {
633
872
  it('should detect keywords with extra whitespace', () => {
634
- const text = ' search for files ';
873
+ const text = ' search the codebase ';
635
874
  expect(hasKeyword(text)).toBe(true);
636
875
  });
637
876
  it('should handle newlines and tabs', () => {
638
- const text = 'search\n\tfor\r\nfiles';
877
+ const text = 'search\n\tthe\r\ncodebase';
639
878
  const detected = detectKeywordsWithType(text);
640
- expect(detected.some(d => d.type === 'search')).toBe(true);
879
+ expect(detected.some(d => d.type === 'deepsearch')).toBe(true);
641
880
  });
642
881
  });
643
882
  describe('Unicode and special characters', () => {
644
883
  it('should handle unicode characters', () => {
645
- const text = 'search for files with émojis 🔍';
884
+ const text = 'search the codebase with émojis 🔍';
646
885
  expect(hasKeyword(text)).toBe(true);
647
886
  });
648
887
  it('should handle mixed scripts', () => {
649
- const text = 'Please search 搜索 искать';
888
+ const text = 'Please search the codebase 搜索 искать';
650
889
  const detected = detectKeywordsWithType(text);
651
- expect(detected.some(d => d.keyword === 'search')).toBe(true);
890
+ expect(detected.some(d => d.type === 'deepsearch')).toBe(true);
652
891
  });
653
892
  });
654
893
  describe('Very long inputs', () => {
655
894
  it('should handle long text efficiently', () => {
656
- const longText = 'plain text '.repeat(1000) + ' search here';
895
+ const longText = 'plain text '.repeat(1000) + ' search the codebase';
657
896
  expect(hasKeyword(longText)).toBe(true);
658
897
  });
659
898
  it('should handle many code blocks', () => {
660
- const manyBlocks = '```code```\n'.repeat(100) + 'search here';
899
+ const manyBlocks = '```code```\n'.repeat(100) + 'search the codebase';
661
900
  const cleaned = removeCodeBlocks(manyBlocks);
662
901
  expect(hasKeyword(cleaned)).toBe(true);
663
902
  });