@liangjie559567/ultrapower 5.0.23 → 5.1.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 (59) hide show
  1. package/.claude-plugin/plugin.json +1 -1
  2. package/dist/__tests__/compatibility.test.js +6 -6
  3. package/dist/__tests__/doctor-conflicts.test.js +26 -24
  4. package/dist/__tests__/doctor-conflicts.test.js.map +1 -1
  5. package/dist/__tests__/hooks-json-paths.test.d.ts +9 -0
  6. package/dist/__tests__/hooks-json-paths.test.d.ts.map +1 -0
  7. package/dist/__tests__/hooks-json-paths.test.js +91 -0
  8. package/dist/__tests__/hooks-json-paths.test.js.map +1 -0
  9. package/dist/__tests__/live-data.test.js +9 -9
  10. package/dist/__tests__/rate-limit-wait/integration.test.js +68 -68
  11. package/dist/__tests__/rate-limit-wait/tmux-detector.test.js +33 -33
  12. package/dist/agents/prompt-sections/index.js +36 -36
  13. package/dist/cli/index.js +226 -226
  14. package/dist/features/rate-limit-wait/daemon.js +5 -5
  15. package/dist/hooks/autopilot/enforcement.js +19 -19
  16. package/dist/hooks/autopilot/validation.js +58 -58
  17. package/dist/hooks/axiom-boot/index.d.ts.map +1 -1
  18. package/dist/hooks/axiom-boot/index.js +2 -1
  19. package/dist/hooks/axiom-boot/index.js.map +1 -1
  20. package/dist/hooks/axiom-boot/storage.d.ts +1 -0
  21. package/dist/hooks/axiom-boot/storage.d.ts.map +1 -1
  22. package/dist/hooks/axiom-boot/storage.js +37 -1
  23. package/dist/hooks/axiom-boot/storage.js.map +1 -1
  24. package/dist/hooks/bridge.d.ts.map +1 -1
  25. package/dist/hooks/bridge.js +110 -100
  26. package/dist/hooks/bridge.js.map +1 -1
  27. package/dist/hooks/keyword-detector/__tests__/index.test.js +7 -7
  28. package/dist/hooks/learner/learning-queue.d.ts.map +1 -1
  29. package/dist/hooks/learner/learning-queue.js +2 -1
  30. package/dist/hooks/learner/learning-queue.js.map +1 -1
  31. package/dist/hooks/learner/session-reflector.d.ts +22 -0
  32. package/dist/hooks/learner/session-reflector.d.ts.map +1 -0
  33. package/dist/hooks/learner/session-reflector.js +52 -0
  34. package/dist/hooks/learner/session-reflector.js.map +1 -0
  35. package/dist/hooks/learner/usage-tracker.d.ts +45 -0
  36. package/dist/hooks/learner/usage-tracker.d.ts.map +1 -0
  37. package/dist/hooks/learner/usage-tracker.js +143 -0
  38. package/dist/hooks/learner/usage-tracker.js.map +1 -0
  39. package/dist/hooks/omc-orchestrator/index.js +20 -20
  40. package/dist/hooks/session-end/callbacks.js +10 -10
  41. package/dist/hooks/session-end/index.d.ts.map +1 -1
  42. package/dist/hooks/session-end/index.js +17 -0
  43. package/dist/hooks/session-end/index.js.map +1 -1
  44. package/dist/hooks/think-mode/__tests__/index.test.js +6 -6
  45. package/dist/installer/index.d.ts.map +1 -1
  46. package/dist/installer/index.js +6 -11
  47. package/dist/installer/index.js.map +1 -1
  48. package/dist/mcp/codex-core.js +26 -26
  49. package/dist/mcp/gemini-core.js +2 -2
  50. package/dist/skills/__tests__/ax-context-init.test.d.ts +2 -0
  51. package/dist/skills/__tests__/ax-context-init.test.d.ts.map +1 -0
  52. package/dist/skills/__tests__/ax-context-init.test.js +36 -0
  53. package/dist/skills/__tests__/ax-context-init.test.js.map +1 -0
  54. package/dist/team/mcp-team-bridge.js +26 -26
  55. package/docs/CLAUDE.md +1 -1
  56. package/package.json +1 -1
  57. package/scripts/persistent-mode.cjs +605 -605
  58. package/scripts/plugin-setup.mjs +44 -0
  59. package/skills/ax-context/SKILL.md +22 -10
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "ultrapower",
3
3
  "description": "Disciplined multi-agent orchestration: workflow enforcement + parallel execution. Combines superpowers' TDD/debugging discipline with OMC's multi-agent execution capabilities.",
4
- "version": "5.0.23",
4
+ "version": "5.1.0",
5
5
  "author": {
6
6
  "name": "Jesse Vincent & oh-my-claudecode contributors"
7
7
  },
@@ -36,12 +36,12 @@ function createTestPlugin(name, manifest) {
36
36
  // Create a sample skill
37
37
  const sampleSkillDir = join(skillsDir, 'sample-skill');
38
38
  mkdirSync(sampleSkillDir, { recursive: true });
39
- writeFileSync(join(sampleSkillDir, 'SKILL.md'), `---
40
- name: sample-skill
41
- description: A sample skill for testing
42
- ---
43
-
44
- This is a sample skill.
39
+ writeFileSync(join(sampleSkillDir, 'SKILL.md'), `---
40
+ name: sample-skill
41
+ description: A sample skill for testing
42
+ ---
43
+
44
+ This is a sample skill.
45
45
  `);
46
46
  }
47
47
  return pluginDir;
@@ -7,31 +7,33 @@
7
7
  import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest';
8
8
  import { existsSync, mkdirSync, writeFileSync, rmSync } from 'fs';
9
9
  import { join } from 'path';
10
- import { homedir } from 'os';
11
- const TEST_CLAUDE_DIR = join(homedir(), '.claude-test-doctor-conflicts');
12
- const TEST_PROJECT_DIR = join(homedir(), '.claude-test-doctor-project');
13
- const TEST_PROJECT_CLAUDE_DIR = join(TEST_PROJECT_DIR, '.claude');
10
+ import { tmpdir } from 'os';
11
+ import { randomBytes } from 'crypto';
14
12
  // Mock getClaudeConfigDir before importing the module under test
13
+ // Use a factory so each test suite worker gets its own path via the closure
14
+ let testClaudeDir = '';
15
15
  vi.mock('../utils/paths.js', () => ({
16
- getClaudeConfigDir: () => TEST_CLAUDE_DIR,
16
+ getClaudeConfigDir: () => testClaudeDir,
17
17
  }));
18
18
  // Import after mock setup
19
19
  import { checkHookConflicts, runConflictCheck } from '../cli/commands/doctor-conflicts.js';
20
20
  describe('doctor-conflicts: hook ownership classification', () => {
21
21
  let cwdSpy;
22
+ let testProjectDir;
23
+ let testProjectClaudeDir;
22
24
  beforeEach(() => {
23
- for (const dir of [TEST_CLAUDE_DIR, TEST_PROJECT_DIR]) {
24
- if (existsSync(dir)) {
25
- rmSync(dir, { recursive: true, force: true });
26
- }
27
- }
28
- mkdirSync(TEST_CLAUDE_DIR, { recursive: true });
29
- mkdirSync(TEST_PROJECT_CLAUDE_DIR, { recursive: true });
30
- cwdSpy = vi.spyOn(process, 'cwd').mockReturnValue(TEST_PROJECT_DIR);
25
+ // Use unique directories per test to avoid cross-test filesystem races
26
+ const uid = randomBytes(6).toString('hex');
27
+ testClaudeDir = join(tmpdir(), `omc-test-doctor-${uid}`);
28
+ testProjectDir = join(tmpdir(), `omc-test-project-${uid}`);
29
+ testProjectClaudeDir = join(testProjectDir, '.claude');
30
+ mkdirSync(testClaudeDir, { recursive: true });
31
+ mkdirSync(testProjectClaudeDir, { recursive: true });
32
+ cwdSpy = vi.spyOn(process, 'cwd').mockReturnValue(testProjectDir);
31
33
  });
32
34
  afterEach(() => {
33
35
  cwdSpy.mockRestore();
34
- for (const dir of [TEST_CLAUDE_DIR, TEST_PROJECT_DIR]) {
36
+ for (const dir of [testClaudeDir, testProjectDir]) {
35
37
  if (existsSync(dir)) {
36
38
  rmSync(dir, { recursive: true, force: true });
37
39
  }
@@ -73,7 +75,7 @@ describe('doctor-conflicts: hook ownership classification', () => {
73
75
  }],
74
76
  },
75
77
  };
76
- writeFileSync(join(TEST_CLAUDE_DIR, 'settings.json'), JSON.stringify(settings));
78
+ writeFileSync(join(testClaudeDir, 'settings.json'), JSON.stringify(settings));
77
79
  const conflicts = checkHookConflicts();
78
80
  // All hooks should be classified as OMC-owned
79
81
  expect(conflicts.length).toBeGreaterThan(0);
@@ -92,7 +94,7 @@ describe('doctor-conflicts: hook ownership classification', () => {
92
94
  }],
93
95
  },
94
96
  };
95
- writeFileSync(join(TEST_CLAUDE_DIR, 'settings.json'), JSON.stringify(settings));
97
+ writeFileSync(join(testClaudeDir, 'settings.json'), JSON.stringify(settings));
96
98
  const conflicts = checkHookConflicts();
97
99
  expect(conflicts).toHaveLength(1);
98
100
  expect(conflicts[0].isOmc).toBe(true);
@@ -108,7 +110,7 @@ describe('doctor-conflicts: hook ownership classification', () => {
108
110
  }],
109
111
  },
110
112
  };
111
- writeFileSync(join(TEST_CLAUDE_DIR, 'settings.json'), JSON.stringify(settings));
113
+ writeFileSync(join(testClaudeDir, 'settings.json'), JSON.stringify(settings));
112
114
  const conflicts = checkHookConflicts();
113
115
  expect(conflicts).toHaveLength(1);
114
116
  expect(conflicts[0].isOmc).toBe(false);
@@ -130,7 +132,7 @@ describe('doctor-conflicts: hook ownership classification', () => {
130
132
  }],
131
133
  },
132
134
  };
133
- writeFileSync(join(TEST_CLAUDE_DIR, 'settings.json'), JSON.stringify(settings));
135
+ writeFileSync(join(testClaudeDir, 'settings.json'), JSON.stringify(settings));
134
136
  const conflicts = checkHookConflicts();
135
137
  expect(conflicts).toHaveLength(2);
136
138
  const preTool = conflicts.find(c => c.event === 'PreToolUse');
@@ -150,7 +152,7 @@ describe('doctor-conflicts: hook ownership classification', () => {
150
152
  }],
151
153
  },
152
154
  };
153
- writeFileSync(join(TEST_CLAUDE_DIR, 'settings.json'), JSON.stringify(omcOnlySettings));
155
+ writeFileSync(join(testClaudeDir, 'settings.json'), JSON.stringify(omcOnlySettings));
154
156
  const omcReport = runConflictCheck();
155
157
  // hasConflicts should be false when all hooks are OMC-owned
156
158
  expect(omcReport.hookConflicts.every(h => h.isOmc)).toBe(true);
@@ -168,7 +170,7 @@ describe('doctor-conflicts: hook ownership classification', () => {
168
170
  }],
169
171
  },
170
172
  };
171
- writeFileSync(join(TEST_PROJECT_CLAUDE_DIR, 'settings.json'), JSON.stringify(projectSettings));
173
+ writeFileSync(join(testProjectClaudeDir, 'settings.json'), JSON.stringify(projectSettings));
172
174
  const conflicts = checkHookConflicts();
173
175
  expect(conflicts).toHaveLength(1);
174
176
  expect(conflicts[0].event).toBe('PreToolUse');
@@ -195,8 +197,8 @@ describe('doctor-conflicts: hook ownership classification', () => {
195
197
  }],
196
198
  },
197
199
  };
198
- writeFileSync(join(TEST_CLAUDE_DIR, 'settings.json'), JSON.stringify(profileSettings));
199
- writeFileSync(join(TEST_PROJECT_CLAUDE_DIR, 'settings.json'), JSON.stringify(projectSettings));
200
+ writeFileSync(join(testClaudeDir, 'settings.json'), JSON.stringify(profileSettings));
201
+ writeFileSync(join(testProjectClaudeDir, 'settings.json'), JSON.stringify(projectSettings));
200
202
  const conflicts = checkHookConflicts();
201
203
  expect(conflicts).toHaveLength(2);
202
204
  const sessionStart = conflicts.find(c => c.event === 'SessionStart');
@@ -216,8 +218,8 @@ describe('doctor-conflicts: hook ownership classification', () => {
216
218
  },
217
219
  };
218
220
  // Same hook in both profile and project settings
219
- writeFileSync(join(TEST_CLAUDE_DIR, 'settings.json'), JSON.stringify(sharedHook));
220
- writeFileSync(join(TEST_PROJECT_CLAUDE_DIR, 'settings.json'), JSON.stringify(sharedHook));
221
+ writeFileSync(join(testClaudeDir, 'settings.json'), JSON.stringify(sharedHook));
222
+ writeFileSync(join(testProjectClaudeDir, 'settings.json'), JSON.stringify(sharedHook));
221
223
  const conflicts = checkHookConflicts();
222
224
  // Should appear only once, not twice
223
225
  expect(conflicts).toHaveLength(1);
@@ -1 +1 @@
1
- {"version":3,"file":"doctor-conflicts.test.js","sourceRoot":"","sources":["../../src/__tests__/doctor-conflicts.test.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"doctor-conflicts.test.js","sourceRoot":"","sources":["../../src/__tests__/doctor-conflicts.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Tests for hooks/hooks.json path correctness (issue: stop-continuation.mjs MODULE_NOT_FOUND)
3
+ *
4
+ * hooks/hooks.json uses ${CLAUDE_PLUGIN_ROOT}/templates/hooks/*.mjs
5
+ * The plugin cache must contain templates/hooks/ for these paths to resolve.
6
+ * plugin-setup.mjs must copy templates/hooks/ to the plugin cache on install.
7
+ */
8
+ export {};
9
+ //# sourceMappingURL=hooks-json-paths.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hooks-json-paths.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/hooks-json-paths.test.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG"}
@@ -0,0 +1,91 @@
1
+ /**
2
+ * Tests for hooks/hooks.json path correctness (issue: stop-continuation.mjs MODULE_NOT_FOUND)
3
+ *
4
+ * hooks/hooks.json uses ${CLAUDE_PLUGIN_ROOT}/templates/hooks/*.mjs
5
+ * The plugin cache must contain templates/hooks/ for these paths to resolve.
6
+ * plugin-setup.mjs must copy templates/hooks/ to the plugin cache on install.
7
+ */
8
+ import { describe, it, expect } from 'vitest';
9
+ import { readFileSync, existsSync } from 'fs';
10
+ import { join, dirname } from 'path';
11
+ import { fileURLToPath } from 'url';
12
+ const __filename = fileURLToPath(import.meta.url);
13
+ const __dirname = dirname(__filename);
14
+ const PROJECT_ROOT = join(__dirname, '..', '..');
15
+ function loadHooksJson() {
16
+ const hooksJsonPath = join(PROJECT_ROOT, 'hooks', 'hooks.json');
17
+ return JSON.parse(readFileSync(hooksJsonPath, 'utf-8'));
18
+ }
19
+ /**
20
+ * Extract the relative path after ${CLAUDE_PLUGIN_ROOT}/ from a command string.
21
+ * e.g. "node ${CLAUDE_PLUGIN_ROOT}/templates/hooks/foo.mjs" -> "templates/hooks/foo.mjs"
22
+ */
23
+ function extractPluginRelativePath(command) {
24
+ const match = command.match(/\$\{CLAUDE_PLUGIN_ROOT\}\/(.+\.mjs)/);
25
+ return match ? match[1] : null;
26
+ }
27
+ describe('hooks/hooks.json path correctness', () => {
28
+ it('all hook commands reference files that exist in the project source', () => {
29
+ const hooksJson = loadHooksJson();
30
+ const missing = [];
31
+ for (const [event, groups] of Object.entries(hooksJson.hooks)) {
32
+ for (const group of groups) {
33
+ for (const hook of group.hooks) {
34
+ if (hook.type !== 'command')
35
+ continue;
36
+ const relPath = extractPluginRelativePath(hook.command);
37
+ if (!relPath)
38
+ continue;
39
+ const fullPath = join(PROJECT_ROOT, relPath);
40
+ if (!existsSync(fullPath)) {
41
+ missing.push(`${event}: ${hook.command} -> ${fullPath} (NOT FOUND)`);
42
+ }
43
+ }
44
+ }
45
+ }
46
+ expect(missing).toEqual([]);
47
+ });
48
+ it('Stop hook command references templates/hooks/stop-continuation.mjs', () => {
49
+ const hooksJson = loadHooksJson();
50
+ const stopGroups = hooksJson.hooks['Stop'] ?? [];
51
+ expect(stopGroups.length).toBeGreaterThan(0);
52
+ for (const group of stopGroups) {
53
+ for (const hook of group.hooks) {
54
+ if (hook.type !== 'command')
55
+ continue;
56
+ expect(hook.command).toContain('templates/hooks/stop-continuation.mjs');
57
+ }
58
+ }
59
+ });
60
+ it('all hook .mjs files referenced in hooks.json exist under templates/hooks/', () => {
61
+ const hooksJson = loadHooksJson();
62
+ const templatesHooksDir = join(PROJECT_ROOT, 'templates', 'hooks');
63
+ const missing = [];
64
+ for (const [event, groups] of Object.entries(hooksJson.hooks)) {
65
+ for (const group of groups) {
66
+ for (const hook of group.hooks) {
67
+ if (hook.type !== 'command')
68
+ continue;
69
+ const relPath = extractPluginRelativePath(hook.command);
70
+ if (!relPath)
71
+ continue;
72
+ if (!relPath.startsWith('templates/hooks/'))
73
+ continue;
74
+ const filename = relPath.replace('templates/hooks/', '');
75
+ const fullPath = join(templatesHooksDir, filename);
76
+ if (!existsSync(fullPath)) {
77
+ missing.push(`${event}: ${filename} (NOT FOUND in templates/hooks/)`);
78
+ }
79
+ }
80
+ }
81
+ }
82
+ expect(missing).toEqual([]);
83
+ });
84
+ it('plugin-setup.mjs copies templates/hooks/ to plugin cache', () => {
85
+ // Verify that plugin-setup.mjs contains logic to copy templates/hooks/ to cache
86
+ const setupScript = readFileSync(join(PROJECT_ROOT, 'scripts', 'plugin-setup.mjs'), 'utf-8');
87
+ // Must have cpSync call referencing srcTemplatesHooks (not just a comment)
88
+ expect(setupScript).toMatch(/cpSync\s*\(\s*srcTemplatesHooks/);
89
+ });
90
+ });
91
+ //# sourceMappingURL=hooks-json-paths.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hooks-json-paths.test.js","sourceRoot":"","sources":["../../src/__tests__/hooks-json-paths.test.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,IAAI,CAAC;AAC9C,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AACrC,OAAO,EAAE,aAAa,EAAE,MAAM,KAAK,CAAC;AAEpC,MAAM,UAAU,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAClD,MAAM,SAAS,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;AACtC,MAAM,YAAY,GAAG,IAAI,CAAC,SAAS,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;AAiBjD,SAAS,aAAa;IACpB,MAAM,aAAa,GAAG,IAAI,CAAC,YAAY,EAAE,OAAO,EAAE,YAAY,CAAC,CAAC;IAChE,OAAO,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,aAAa,EAAE,OAAO,CAAC,CAAC,CAAC;AAC1D,CAAC;AAED;;;GAGG;AACH,SAAS,yBAAyB,CAAC,OAAe;IAChD,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,qCAAqC,CAAC,CAAC;IACnE,OAAO,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;AACjC,CAAC;AAED,QAAQ,CAAC,mCAAmC,EAAE,GAAG,EAAE;IACjD,EAAE,CAAC,oEAAoE,EAAE,GAAG,EAAE;QAC5E,MAAM,SAAS,GAAG,aAAa,EAAE,CAAC;QAClC,MAAM,OAAO,GAAa,EAAE,CAAC;QAE7B,KAAK,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,CAAC;YAC9D,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;gBAC3B,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,KAAK,EAAE,CAAC;oBAC/B,IAAI,IAAI,CAAC,IAAI,KAAK,SAAS;wBAAE,SAAS;oBACtC,MAAM,OAAO,GAAG,yBAAyB,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;oBACxD,IAAI,CAAC,OAAO;wBAAE,SAAS;oBAEvB,MAAM,QAAQ,GAAG,IAAI,CAAC,YAAY,EAAE,OAAO,CAAC,CAAC;oBAC7C,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;wBAC1B,OAAO,CAAC,IAAI,CAAC,GAAG,KAAK,KAAK,IAAI,CAAC,OAAO,OAAO,QAAQ,cAAc,CAAC,CAAC;oBACvE,CAAC;gBACH,CAAC;YACH,CAAC;QACH,CAAC;QAED,MAAM,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IAC9B,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,oEAAoE,EAAE,GAAG,EAAE;QAC5E,MAAM,SAAS,GAAG,aAAa,EAAE,CAAC;QAClC,MAAM,UAAU,GAAG,SAAS,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;QAEjD,MAAM,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC;QAE7C,KAAK,MAAM,KAAK,IAAI,UAAU,EAAE,CAAC;YAC/B,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,KAAK,EAAE,CAAC;gBAC/B,IAAI,IAAI,CAAC,IAAI,KAAK,SAAS;oBAAE,SAAS;gBACtC,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,SAAS,CAAC,uCAAuC,CAAC,CAAC;YAC1E,CAAC;QACH,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,2EAA2E,EAAE,GAAG,EAAE;QACnF,MAAM,SAAS,GAAG,aAAa,EAAE,CAAC;QAClC,MAAM,iBAAiB,GAAG,IAAI,CAAC,YAAY,EAAE,WAAW,EAAE,OAAO,CAAC,CAAC;QACnE,MAAM,OAAO,GAAa,EAAE,CAAC;QAE7B,KAAK,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,CAAC;YAC9D,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;gBAC3B,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,KAAK,EAAE,CAAC;oBAC/B,IAAI,IAAI,CAAC,IAAI,KAAK,SAAS;wBAAE,SAAS;oBACtC,MAAM,OAAO,GAAG,yBAAyB,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;oBACxD,IAAI,CAAC,OAAO;wBAAE,SAAS;oBACvB,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,kBAAkB,CAAC;wBAAE,SAAS;oBAEtD,MAAM,QAAQ,GAAG,OAAO,CAAC,OAAO,CAAC,kBAAkB,EAAE,EAAE,CAAC,CAAC;oBACzD,MAAM,QAAQ,GAAG,IAAI,CAAC,iBAAiB,EAAE,QAAQ,CAAC,CAAC;oBACnD,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;wBAC1B,OAAO,CAAC,IAAI,CAAC,GAAG,KAAK,KAAK,QAAQ,kCAAkC,CAAC,CAAC;oBACxE,CAAC;gBACH,CAAC;YACH,CAAC;QACH,CAAC;QAED,MAAM,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IAC9B,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,0DAA0D,EAAE,GAAG,EAAE;QAClE,gFAAgF;QAChF,MAAM,WAAW,GAAG,YAAY,CAAC,IAAI,CAAC,YAAY,EAAE,SAAS,EAAE,kBAAkB,CAAC,EAAE,OAAO,CAAC,CAAC;QAC7F,2EAA2E;QAC3E,MAAM,CAAC,WAAW,CAAC,CAAC,OAAO,CAAC,iCAAiC,CAAC,CAAC;IACjE,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -253,15 +253,15 @@ describe('resolveLiveData - output formats', () => {
253
253
  expect(result).toContain('format="table"');
254
254
  });
255
255
  it('!diff adds format="diff" with file/add/del stats', () => {
256
- const diffOutput = `diff --git a/src/main.ts b/src/main.ts
257
- --- a/src/main.ts
258
- +++ b/src/main.ts
259
- @@ -1,3 +1,5 @@
260
- +import { foo } from 'bar';
261
- +import { baz } from 'qux';
262
- const x = 1;
263
- -const y = 2;
264
- const z = 3;
256
+ const diffOutput = `diff --git a/src/main.ts b/src/main.ts
257
+ --- a/src/main.ts
258
+ +++ b/src/main.ts
259
+ @@ -1,3 +1,5 @@
260
+ +import { foo } from 'bar';
261
+ +import { baz } from 'qux';
262
+ const x = 1;
263
+ -const y = 2;
264
+ const z = 3;
265
265
  `;
266
266
  mockedExecSync.mockReturnValue(diffOutput);
267
267
  const result = resolveLiveData('!diff git diff');
@@ -95,20 +95,20 @@ describe('Rate Limit Wait Integration Tests', () => {
95
95
  });
96
96
  describe('Scenario: tmux pane analysis accuracy', () => {
97
97
  it('should correctly identify Claude Code rate limit message', () => {
98
- const realWorldContent = `
99
- ╭─────────────────────────────────────────────────────────────────╮
100
- │ Claude Code │
101
- ╰─────────────────────────────────────────────────────────────────╯
102
-
103
- You've reached your usage limit for the 5-hour period.
104
- Your limit will reset at 3:45 PM.
105
-
106
- What would you like to do?
107
-
108
- [1] Wait and continue automatically when limit resets
109
- [2] Switch to a different conversation
110
- [3] Exit
111
-
98
+ const realWorldContent = `
99
+ ╭─────────────────────────────────────────────────────────────────╮
100
+ │ Claude Code │
101
+ ╰─────────────────────────────────────────────────────────────────╯
102
+
103
+ You've reached your usage limit for the 5-hour period.
104
+ Your limit will reset at 3:45 PM.
105
+
106
+ What would you like to do?
107
+
108
+ [1] Wait and continue automatically when limit resets
109
+ [2] Switch to a different conversation
110
+ [3] Exit
111
+
112
112
  > `;
113
113
  const result = analyzePaneContent(realWorldContent);
114
114
  expect(result.hasClaudeCode).toBe(true);
@@ -118,18 +118,18 @@ What would you like to do?
118
118
  expect(result.confidence).toBeGreaterThanOrEqual(0.8);
119
119
  });
120
120
  it('should correctly identify weekly rate limit message', () => {
121
- const weeklyLimitContent = `
122
- Claude Code v1.0.0
123
-
124
- ⚠️ Weekly usage limit reached
125
-
126
- You've used your weekly allocation of tokens.
127
- Limit resets on Monday at 12:00 AM UTC.
128
-
129
- Options:
130
- [1] Continue when limit resets
131
- [2] Exit
132
-
121
+ const weeklyLimitContent = `
122
+ Claude Code v1.0.0
123
+
124
+ ⚠️ Weekly usage limit reached
125
+
126
+ You've used your weekly allocation of tokens.
127
+ Limit resets on Monday at 12:00 AM UTC.
128
+
129
+ Options:
130
+ [1] Continue when limit resets
131
+ [2] Exit
132
+
133
133
  Enter choice: `;
134
134
  const result = analyzePaneContent(weeklyLimitContent);
135
135
  expect(result.hasClaudeCode).toBe(true);
@@ -138,18 +138,18 @@ Enter choice: `;
138
138
  expect(result.rateLimitType).toBe('weekly');
139
139
  });
140
140
  it('should NOT flag normal Claude Code output as blocked', () => {
141
- const normalContent = `
142
- Claude Code
143
-
144
- > What would you like to build today?
145
-
146
- I can help you with:
147
- - Writing code
148
- - Debugging
149
- - Refactoring
150
- - Documentation
151
-
152
- Just describe what you need!
141
+ const normalContent = `
142
+ Claude Code
143
+
144
+ > What would you like to build today?
145
+
146
+ I can help you with:
147
+ - Writing code
148
+ - Debugging
149
+ - Refactoring
150
+ - Documentation
151
+
152
+ Just describe what you need!
153
153
  `;
154
154
  const result = analyzePaneContent(normalContent);
155
155
  expect(result.hasClaudeCode).toBe(true);
@@ -157,12 +157,12 @@ Just describe what you need!
157
157
  expect(result.isBlocked).toBe(false);
158
158
  });
159
159
  it('should NOT flag unrelated rate limit messages', () => {
160
- const unrelatedContent = `
161
- $ curl https://api.github.com/users/test
162
- {
163
- "message": "API rate limit exceeded for IP",
164
- "documentation_url": "https://docs.github.com"
165
- }
160
+ const unrelatedContent = `
161
+ $ curl https://api.github.com/users/test
162
+ {
163
+ "message": "API rate limit exceeded for IP",
164
+ "documentation_url": "https://docs.github.com"
165
+ }
166
166
  $ `;
167
167
  const result = analyzePaneContent(unrelatedContent);
168
168
  expect(result.hasClaudeCode).toBe(false);
@@ -172,18 +172,18 @@ $ `;
172
172
  it('should handle edge case: old rate limit message scrolled up', () => {
173
173
  // Only last 15 lines should be analyzed
174
174
  // Rate limit message from earlier should be ignored if not in recent content
175
- const scrolledContent = `
176
- User: fix the bug
177
- Assistant: I'll fix that for you.
178
- [Edit] src/main.ts
179
- Done! The bug is fixed.
180
-
181
- User: thanks
182
- Assistant: You're welcome!
183
-
184
- User: what else?
185
- Assistant: I can help with more tasks.
186
-
175
+ const scrolledContent = `
176
+ User: fix the bug
177
+ Assistant: I'll fix that for you.
178
+ [Edit] src/main.ts
179
+ Done! The bug is fixed.
180
+
181
+ User: thanks
182
+ Assistant: You're welcome!
183
+
184
+ User: what else?
185
+ Assistant: I can help with more tasks.
186
+
187
187
  > `;
188
188
  const result = analyzePaneContent(scrolledContent);
189
189
  expect(result.isBlocked).toBe(false);
@@ -311,25 +311,25 @@ Assistant: I can help with more tasks.
311
311
  });
312
312
  describe('Scenario: Confidence scoring', () => {
313
313
  it('should give higher confidence for multiple indicators', () => {
314
- const highConfidenceContent = `
315
- Claude Code
316
- Rate limit reached
317
- 5-hour usage limit
318
- [1] Continue
319
- [2] Exit
314
+ const highConfidenceContent = `
315
+ Claude Code
316
+ Rate limit reached
317
+ 5-hour usage limit
318
+ [1] Continue
319
+ [2] Exit
320
320
  `;
321
- const lowConfidenceContent = `
322
- Claude
323
- rate limit
321
+ const lowConfidenceContent = `
322
+ Claude
323
+ rate limit
324
324
  `;
325
325
  const highResult = analyzePaneContent(highConfidenceContent);
326
326
  const lowResult = analyzePaneContent(lowConfidenceContent);
327
327
  expect(highResult.confidence).toBeGreaterThan(lowResult.confidence);
328
328
  });
329
329
  it('should require minimum confidence to mark as blocked', () => {
330
- const ambiguousContent = `
331
- some claude reference
332
- limit mentioned
330
+ const ambiguousContent = `
331
+ some claude reference
332
+ limit mentioned
333
333
  `;
334
334
  const result = analyzePaneContent(ambiguousContent);
335
335
  // Even if some patterns match, confidence should be too low
@@ -15,11 +15,11 @@ describe('tmux-detector', () => {
15
15
  });
16
16
  describe('analyzePaneContent', () => {
17
17
  it('should detect rate limit messages with Claude Code context', () => {
18
- const content = `
19
- Claude Code v1.2.3
20
- You've reached your rate limit. Please wait for the limit to reset.
21
- [1] Continue when ready
22
- [2] Exit
18
+ const content = `
19
+ Claude Code v1.2.3
20
+ You've reached your rate limit. Please wait for the limit to reset.
21
+ [1] Continue when ready
22
+ [2] Exit
23
23
  `;
24
24
  const result = analyzePaneContent(content);
25
25
  expect(result.hasClaudeCode).toBe(true);
@@ -28,38 +28,38 @@ describe('tmux-detector', () => {
28
28
  expect(result.confidence).toBeGreaterThan(0.5);
29
29
  });
30
30
  it('should detect 5-hour rate limit', () => {
31
- const content = `
32
- Claude Code assistant
33
- 5-hour usage limit reached
34
- [1] Wait for reset
31
+ const content = `
32
+ Claude Code assistant
33
+ 5-hour usage limit reached
34
+ [1] Wait for reset
35
35
  `;
36
36
  const result = analyzePaneContent(content);
37
37
  expect(result.hasRateLimitMessage).toBe(true);
38
38
  expect(result.rateLimitType).toBe('five_hour');
39
39
  });
40
40
  it('should detect weekly rate limit', () => {
41
- const content = `
42
- Claude Code
43
- Weekly usage quota exceeded
44
- Please try again later
41
+ const content = `
42
+ Claude Code
43
+ Weekly usage quota exceeded
44
+ Please try again later
45
45
  `;
46
46
  const result = analyzePaneContent(content);
47
47
  expect(result.hasRateLimitMessage).toBe(true);
48
48
  expect(result.rateLimitType).toBe('weekly');
49
49
  });
50
50
  it('should not flag content without Claude Code indicators', () => {
51
- const content = `
52
- vim test.js
53
- Hello World
51
+ const content = `
52
+ vim test.js
53
+ Hello World
54
54
  `;
55
55
  const result = analyzePaneContent(content);
56
56
  expect(result.hasClaudeCode).toBe(false);
57
57
  expect(result.isBlocked).toBe(false);
58
58
  });
59
59
  it('should not flag rate limit messages in non-Claude contexts', () => {
60
- const content = `
61
- curl api.example.com
62
- Error: rate limit exceeded
60
+ const content = `
61
+ curl api.example.com
62
+ Error: rate limit exceeded
63
63
  `;
64
64
  const result = analyzePaneContent(content);
65
65
  expect(result.hasClaudeCode).toBe(false);
@@ -74,25 +74,25 @@ describe('tmux-detector', () => {
74
74
  expect(result.confidence).toBe(0);
75
75
  });
76
76
  it('should detect waiting patterns', () => {
77
- const content = `
78
- Claude assistant
79
- Rate limit reached
80
- [1] Continue
81
- [2] Cancel
77
+ const content = `
78
+ Claude assistant
79
+ Rate limit reached
80
+ [1] Continue
81
+ [2] Cancel
82
82
  `;
83
83
  const result = analyzePaneContent(content);
84
84
  expect(result.confidence).toBeGreaterThan(0.6);
85
85
  });
86
86
  it('should detect Claude limit screen phrasing: hit your limit + numeric menu', () => {
87
- const content = `
88
- Claude Code
89
- You've hit your limit · resets Feb 17 at 2pm (Asia/Seoul)
90
- What do you want to do?
91
-
92
- ❯ 1. Stop and wait for limit to reset
93
- 2. Request more
94
-
95
- Enter to confirm · Esc to cancel
87
+ const content = `
88
+ Claude Code
89
+ You've hit your limit · resets Feb 17 at 2pm (Asia/Seoul)
90
+ What do you want to do?
91
+
92
+ ❯ 1. Stop and wait for limit to reset
93
+ 2. Request more
94
+
95
+ Enter to confirm · Esc to cancel
96
96
  `;
97
97
  const result = analyzePaneContent(content);
98
98
  expect(result.hasClaudeCode).toBe(true);