oh-my-claude-sisyphus 3.8.16 → 3.9.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 (160) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/.mcp.json +1 -1
  4. package/agents/analyst.md +41 -0
  5. package/agents/architect.md +45 -0
  6. package/agents/critic.md +42 -0
  7. package/agents/deep-executor.md +193 -0
  8. package/agents/planner.md +82 -0
  9. package/bridge/mcp-server.cjs +181 -181
  10. package/dist/__tests__/agent-registry.test.js +1 -1
  11. package/dist/__tests__/installer.test.js +8 -8
  12. package/dist/__tests__/installer.test.js.map +1 -1
  13. package/dist/__tests__/omc-tools-server.test.js +2 -2
  14. package/dist/__tests__/omc-tools-server.test.js.map +1 -1
  15. package/dist/__tests__/skills.test.js +5 -4
  16. package/dist/__tests__/skills.test.js.map +1 -1
  17. package/dist/agents/deep-executor.d.ts +15 -0
  18. package/dist/agents/deep-executor.d.ts.map +1 -0
  19. package/dist/agents/deep-executor.js +47 -0
  20. package/dist/agents/deep-executor.js.map +1 -0
  21. package/dist/agents/definitions.d.ts +15 -0
  22. package/dist/agents/definitions.d.ts.map +1 -1
  23. package/dist/agents/definitions.js +25 -0
  24. package/dist/agents/definitions.js.map +1 -1
  25. package/dist/agents/index.d.ts +1 -0
  26. package/dist/agents/index.d.ts.map +1 -1
  27. package/dist/agents/index.js +1 -0
  28. package/dist/agents/index.js.map +1 -1
  29. package/dist/cli/commands/doctor-conflicts.d.ts +55 -0
  30. package/dist/cli/commands/doctor-conflicts.d.ts.map +1 -0
  31. package/dist/cli/commands/doctor-conflicts.js +261 -0
  32. package/dist/cli/commands/doctor-conflicts.js.map +1 -0
  33. package/dist/cli/index.js +16 -1
  34. package/dist/cli/index.js.map +1 -1
  35. package/dist/features/auto-update.d.ts +12 -0
  36. package/dist/features/auto-update.d.ts.map +1 -1
  37. package/dist/features/auto-update.js +4 -1
  38. package/dist/features/auto-update.js.map +1 -1
  39. package/dist/features/context-injector/types.d.ts +1 -1
  40. package/dist/features/context-injector/types.d.ts.map +1 -1
  41. package/dist/hooks/__tests__/bridge.test.d.ts +2 -0
  42. package/dist/hooks/__tests__/bridge.test.d.ts.map +1 -0
  43. package/dist/hooks/__tests__/bridge.test.js +199 -0
  44. package/dist/hooks/__tests__/bridge.test.js.map +1 -0
  45. package/dist/hooks/beads-context/__tests__/index.test.d.ts +2 -0
  46. package/dist/hooks/beads-context/__tests__/index.test.d.ts.map +1 -0
  47. package/dist/hooks/beads-context/__tests__/index.test.js +150 -0
  48. package/dist/hooks/beads-context/__tests__/index.test.js.map +1 -0
  49. package/dist/hooks/beads-context/constants.d.ts +3 -0
  50. package/dist/hooks/beads-context/constants.d.ts.map +1 -0
  51. package/dist/hooks/beads-context/constants.js +35 -0
  52. package/dist/hooks/beads-context/constants.js.map +1 -0
  53. package/dist/hooks/beads-context/index.d.ts +21 -0
  54. package/dist/hooks/beads-context/index.d.ts.map +1 -0
  55. package/dist/hooks/beads-context/index.js +62 -0
  56. package/dist/hooks/beads-context/index.js.map +1 -0
  57. package/dist/hooks/beads-context/types.d.ts +7 -0
  58. package/dist/hooks/beads-context/types.d.ts.map +1 -0
  59. package/dist/hooks/beads-context/types.js +2 -0
  60. package/dist/hooks/beads-context/types.js.map +1 -0
  61. package/dist/hooks/bridge.d.ts +4 -0
  62. package/dist/hooks/bridge.d.ts.map +1 -1
  63. package/dist/hooks/bridge.js +76 -23
  64. package/dist/hooks/bridge.js.map +1 -1
  65. package/dist/hooks/clear-suggestions/constants.d.ts +54 -0
  66. package/dist/hooks/clear-suggestions/constants.d.ts.map +1 -0
  67. package/dist/hooks/clear-suggestions/constants.js +102 -0
  68. package/dist/hooks/clear-suggestions/constants.js.map +1 -0
  69. package/dist/hooks/clear-suggestions/index.d.ts +61 -0
  70. package/dist/hooks/clear-suggestions/index.d.ts.map +1 -0
  71. package/dist/hooks/clear-suggestions/index.js +282 -0
  72. package/dist/hooks/clear-suggestions/index.js.map +1 -0
  73. package/dist/hooks/clear-suggestions/triggers.d.ts +65 -0
  74. package/dist/hooks/clear-suggestions/triggers.d.ts.map +1 -0
  75. package/dist/hooks/clear-suggestions/triggers.js +222 -0
  76. package/dist/hooks/clear-suggestions/triggers.js.map +1 -0
  77. package/dist/hooks/clear-suggestions/types.d.ts +92 -0
  78. package/dist/hooks/clear-suggestions/types.d.ts.map +1 -0
  79. package/dist/hooks/clear-suggestions/types.js +9 -0
  80. package/dist/hooks/clear-suggestions/types.js.map +1 -0
  81. package/dist/hooks/index.d.ts +1 -0
  82. package/dist/hooks/index.d.ts.map +1 -1
  83. package/dist/hooks/index.js +3 -0
  84. package/dist/hooks/index.js.map +1 -1
  85. package/dist/hooks/permission-handler/index.d.ts.map +1 -1
  86. package/dist/hooks/permission-handler/index.js +3 -1
  87. package/dist/hooks/permission-handler/index.js.map +1 -1
  88. package/dist/hooks/setup/index.d.ts.map +1 -1
  89. package/dist/hooks/setup/index.js +12 -5
  90. package/dist/hooks/setup/index.js.map +1 -1
  91. package/dist/hooks/subagent-tracker/index.d.ts.map +1 -1
  92. package/dist/hooks/subagent-tracker/index.js +25 -9
  93. package/dist/hooks/subagent-tracker/index.js.map +1 -1
  94. package/dist/index.js +1 -1
  95. package/dist/index.js.map +1 -1
  96. package/dist/installer/__tests__/claude-md-merge.test.d.ts +6 -0
  97. package/dist/installer/__tests__/claude-md-merge.test.d.ts.map +1 -0
  98. package/dist/installer/__tests__/claude-md-merge.test.js +220 -0
  99. package/dist/installer/__tests__/claude-md-merge.test.js.map +1 -0
  100. package/dist/installer/__tests__/safe-installer.test.d.ts +6 -0
  101. package/dist/installer/__tests__/safe-installer.test.d.ts.map +1 -0
  102. package/dist/installer/__tests__/safe-installer.test.js +172 -0
  103. package/dist/installer/__tests__/safe-installer.test.js.map +1 -0
  104. package/dist/installer/hooks.d.ts.map +1 -1
  105. package/dist/installer/hooks.js +3 -1
  106. package/dist/installer/hooks.js.map +1 -1
  107. package/dist/installer/index.d.ts +27 -1
  108. package/dist/installer/index.d.ts.map +1 -1
  109. package/dist/installer/index.js +209 -85
  110. package/dist/installer/index.js.map +1 -1
  111. package/dist/mcp/omc-tools-server.d.ts +1 -1
  112. package/dist/mcp/omc-tools-server.d.ts.map +1 -1
  113. package/dist/mcp/omc-tools-server.js +3 -3
  114. package/dist/mcp/omc-tools-server.js.map +1 -1
  115. package/dist/mcp/standalone-server.js +1 -1
  116. package/dist/mcp/standalone-server.js.map +1 -1
  117. package/dist/verification/tier-selector.d.ts +40 -0
  118. package/dist/verification/tier-selector.d.ts.map +1 -0
  119. package/dist/verification/tier-selector.js +95 -0
  120. package/dist/verification/tier-selector.js.map +1 -0
  121. package/dist/verification/tier-selector.test.d.ts +2 -0
  122. package/dist/verification/tier-selector.test.d.ts.map +1 -0
  123. package/dist/verification/tier-selector.test.js +282 -0
  124. package/dist/verification/tier-selector.test.js.map +1 -0
  125. package/docs/AGENTS.md +1 -1
  126. package/docs/CLAUDE.md +90 -378
  127. package/docs/partials/agent-tiers.md +165 -0
  128. package/docs/partials/features.md +131 -0
  129. package/docs/partials/mode-hierarchy.md +120 -0
  130. package/docs/partials/mode-selection-guide.md +82 -0
  131. package/docs/partials/verification-tiers.md +107 -0
  132. package/docs/shared/agent-tiers.md +165 -0
  133. package/docs/shared/features.md +131 -0
  134. package/docs/shared/mode-hierarchy.md +120 -0
  135. package/docs/shared/mode-selection-guide.md +82 -0
  136. package/docs/shared/verification-tiers.md +107 -0
  137. package/package.json +4 -3
  138. package/scripts/compose-docs.mjs +44 -0
  139. package/scripts/keyword-detector.mjs +13 -3
  140. package/skills/deep-executor/SKILL.md +50 -0
  141. package/skills/ecomode/SKILL.md +58 -103
  142. package/skills/omc-setup/SKILL.md +197 -20
  143. package/skills/plan/SKILL.md +62 -0
  144. package/skills/project-session-manager/SKILL.md +87 -4
  145. package/skills/project-session-manager/lib/config.sh +54 -5
  146. package/skills/project-session-manager/lib/parse.sh +65 -11
  147. package/skills/project-session-manager/lib/providers/github.sh +52 -0
  148. package/skills/project-session-manager/lib/providers/interface.sh +76 -0
  149. package/skills/project-session-manager/lib/providers/jira.sh +79 -0
  150. package/skills/project-session-manager/lib/session.sh +49 -12
  151. package/skills/project-session-manager/lib/worktree.sh +37 -4
  152. package/skills/project-session-manager/psm.sh +116 -51
  153. package/skills/ralph/SKILL.md +41 -27
  154. package/skills/ultrawork/SKILL.md +56 -66
  155. package/templates/hooks/keyword-detector.mjs +21 -13
  156. package/templates/hooks/lib/stdin.mjs +62 -0
  157. package/templates/hooks/persistent-mode.mjs +7 -8
  158. package/templates/hooks/post-tool-use.mjs +8 -10
  159. package/templates/hooks/pre-tool-use.mjs +9 -6
  160. package/templates/hooks/session-start.mjs +7 -8
@@ -0,0 +1,220 @@
1
+ /**
2
+ * Tests for CLAUDE.md Merge (Task T5)
3
+ * Tests merge-based CLAUDE.md updates with markers and backups
4
+ */
5
+ import { describe, it, expect } from 'vitest';
6
+ import { mergeClaudeMd } from '../index.js';
7
+ const START_MARKER = '<!-- OMC:START -->';
8
+ const END_MARKER = '<!-- OMC:END -->';
9
+ const USER_CUSTOMIZATIONS = '<!-- User customizations -->';
10
+ const USER_CUSTOMIZATIONS_RECOVERED = '<!-- User customizations (recovered from corrupted markers) -->';
11
+ describe('mergeClaudeMd', () => {
12
+ const omcContent = '# OMC Configuration\n\nThis is the OMC content.';
13
+ describe('Fresh install (no existing content)', () => {
14
+ it('wraps omcContent in markers', () => {
15
+ const result = mergeClaudeMd(null, omcContent);
16
+ expect(result).toContain(START_MARKER);
17
+ expect(result).toContain(END_MARKER);
18
+ expect(result).toContain(omcContent);
19
+ expect(result.indexOf(START_MARKER)).toBeLessThan(result.indexOf(omcContent));
20
+ expect(result.indexOf(omcContent)).toBeLessThan(result.indexOf(END_MARKER));
21
+ });
22
+ it('has correct structure for fresh install', () => {
23
+ const result = mergeClaudeMd(null, omcContent);
24
+ const expected = `${START_MARKER}\n${omcContent}\n${END_MARKER}\n`;
25
+ expect(result).toBe(expected);
26
+ });
27
+ });
28
+ describe('Update existing content with markers', () => {
29
+ it('replaces only content between markers', () => {
30
+ const existingContent = `Some header content\n\n${START_MARKER}\n# Old OMC Content\nOld stuff here.\n${END_MARKER}\n\nUser's custom content\nMore custom stuff`;
31
+ const result = mergeClaudeMd(existingContent, omcContent);
32
+ expect(result).toContain('Some header content');
33
+ expect(result).toContain(omcContent);
34
+ expect(result).toContain('User\'s custom content');
35
+ expect(result).not.toContain('Old OMC Content');
36
+ expect(result).not.toContain('Old stuff here');
37
+ });
38
+ it('preserves content before and after markers', () => {
39
+ const beforeContent = 'This is before the marker\n\n';
40
+ const afterContent = '\n\nThis is after the marker';
41
+ const existingContent = `${beforeContent}${START_MARKER}\nOld content\n${END_MARKER}${afterContent}`;
42
+ const result = mergeClaudeMd(existingContent, omcContent);
43
+ expect(result.startsWith(beforeContent)).toBe(true);
44
+ expect(result.endsWith(afterContent)).toBe(true);
45
+ expect(result).toContain(omcContent);
46
+ });
47
+ it('maintains exact structure with proper newlines', () => {
48
+ const existingContent = `Header\n${START_MARKER}\nOld\n${END_MARKER}\nFooter`;
49
+ const result = mergeClaudeMd(existingContent, omcContent);
50
+ const expected = `Header\n${START_MARKER}\n${omcContent}\n${END_MARKER}\nFooter`;
51
+ expect(result).toBe(expected);
52
+ });
53
+ });
54
+ describe('No markers in existing content', () => {
55
+ it('wraps omcContent in markers and preserves existing content after user customizations header', () => {
56
+ const existingContent = '# My Custom Config\n\nCustom settings here.';
57
+ const result = mergeClaudeMd(existingContent, omcContent);
58
+ expect(result).toContain(START_MARKER);
59
+ expect(result).toContain(END_MARKER);
60
+ expect(result).toContain(omcContent);
61
+ expect(result).toContain(USER_CUSTOMIZATIONS);
62
+ expect(result).toContain('# My Custom Config');
63
+ expect(result).toContain('Custom settings here.');
64
+ // Check order: OMC section first, then user customizations header, then existing content
65
+ const omcIndex = result.indexOf(START_MARKER);
66
+ const customizationsIndex = result.indexOf(USER_CUSTOMIZATIONS);
67
+ const existingIndex = result.indexOf('# My Custom Config');
68
+ expect(omcIndex).toBeLessThan(customizationsIndex);
69
+ expect(customizationsIndex).toBeLessThan(existingIndex);
70
+ });
71
+ it('has correct structure when adding markers to existing content', () => {
72
+ const existingContent = 'Existing content';
73
+ const result = mergeClaudeMd(existingContent, omcContent);
74
+ const expected = `${START_MARKER}\n${omcContent}\n${END_MARKER}\n\n${USER_CUSTOMIZATIONS}\n${existingContent}`;
75
+ expect(result).toBe(expected);
76
+ });
77
+ });
78
+ describe('Corrupted markers', () => {
79
+ it('handles START marker without END marker', () => {
80
+ const existingContent = `${START_MARKER}\nSome content\nMore content`;
81
+ const result = mergeClaudeMd(existingContent, omcContent);
82
+ expect(result).toContain(START_MARKER);
83
+ expect(result).toContain(END_MARKER);
84
+ expect(result).toContain(omcContent);
85
+ expect(result).toContain(USER_CUSTOMIZATIONS_RECOVERED);
86
+ // Original corrupted content should be preserved after user customizations
87
+ expect(result).toContain('Some content');
88
+ });
89
+ it('handles END marker without START marker', () => {
90
+ const existingContent = `Some content\n${END_MARKER}\nMore content`;
91
+ const result = mergeClaudeMd(existingContent, omcContent);
92
+ expect(result).toContain(START_MARKER);
93
+ expect(result).toContain(END_MARKER);
94
+ expect(result).toContain(omcContent);
95
+ expect(result).toContain(USER_CUSTOMIZATIONS_RECOVERED);
96
+ // Original corrupted content should be preserved
97
+ expect(result).toContain('Some content');
98
+ expect(result).toContain('More content');
99
+ });
100
+ it('handles END marker before START marker (invalid order)', () => {
101
+ const existingContent = `${END_MARKER}\nContent\n${START_MARKER}`;
102
+ const result = mergeClaudeMd(existingContent, omcContent);
103
+ // Should treat as corrupted and wrap new content, preserving old
104
+ expect(result).toContain(START_MARKER);
105
+ expect(result).toContain(END_MARKER);
106
+ expect(result).toContain(omcContent);
107
+ expect(result).toContain(USER_CUSTOMIZATIONS_RECOVERED);
108
+ });
109
+ });
110
+ describe('Edge cases', () => {
111
+ it('handles empty omcContent', () => {
112
+ const existingContent = `${START_MARKER}\nOld content\n${END_MARKER}`;
113
+ const result = mergeClaudeMd(existingContent, '');
114
+ expect(result).toContain(START_MARKER);
115
+ expect(result).toContain(END_MARKER);
116
+ expect(result).not.toContain('Old content');
117
+ });
118
+ it('handles whitespace-only existing content', () => {
119
+ const existingContent = ' \n\n ';
120
+ const result = mergeClaudeMd(existingContent, omcContent);
121
+ expect(result).toContain(START_MARKER);
122
+ expect(result).toContain(END_MARKER);
123
+ expect(result).toContain(omcContent);
124
+ expect(result).toContain(existingContent);
125
+ });
126
+ it('handles multi-line omcContent', () => {
127
+ const multiLineOmc = 'Line 1\nLine 2\nLine 3\n\nLine 5';
128
+ const result = mergeClaudeMd(null, multiLineOmc);
129
+ expect(result).toContain(multiLineOmc);
130
+ expect(result.split('\n').length).toBeGreaterThan(5);
131
+ });
132
+ it('preserves multiple occurrences of marker-like text in user content', () => {
133
+ const existingContent = `${START_MARKER}\nOMC Content\n${END_MARKER}\n\nUser content mentions ${START_MARKER} in text`;
134
+ const result = mergeClaudeMd(existingContent, omcContent);
135
+ // Only first pair of markers should be used
136
+ expect(result).toContain(omcContent);
137
+ expect(result).toContain('User content mentions');
138
+ expect(result.split(START_MARKER).length).toBe(3); // Two START_MARKERs total (one pair + one in text)
139
+ });
140
+ it('handles very large existing content', () => {
141
+ const largeContent = 'x'.repeat(100000);
142
+ const existingContent = `${START_MARKER}\nOld\n${END_MARKER}\n${largeContent}`;
143
+ const result = mergeClaudeMd(existingContent, omcContent);
144
+ expect(result).toContain(omcContent);
145
+ expect(result).toContain(largeContent);
146
+ expect(result.length).toBeGreaterThan(100000);
147
+ });
148
+ });
149
+ describe('Real-world scenarios', () => {
150
+ it('handles typical fresh install scenario', () => {
151
+ const result = mergeClaudeMd(null, omcContent);
152
+ expect(result).toMatch(/^<!-- OMC:START -->\n.*\n<!-- OMC:END -->\n$/s);
153
+ });
154
+ it('handles typical update scenario with user customizations', () => {
155
+ const existingContent = `${START_MARKER}
156
+ # Old OMC Config v1.0
157
+ Old instructions here.
158
+ ${END_MARKER}
159
+
160
+ ${USER_CUSTOMIZATIONS}
161
+ # My Project-Specific Instructions
162
+ - Use TypeScript strict mode
163
+ - Follow company coding standards`;
164
+ const newOmcContent = '# OMC Config v2.0\nNew instructions with updates.';
165
+ const result = mergeClaudeMd(existingContent, newOmcContent);
166
+ expect(result).toContain('# OMC Config v2.0');
167
+ expect(result).not.toContain('Old instructions here');
168
+ expect(result).toContain('# My Project-Specific Instructions');
169
+ expect(result).toContain('Follow company coding standards');
170
+ });
171
+ it('handles migration from old version without markers', () => {
172
+ const oldContent = `# Legacy CLAUDE.md
173
+ Some old configuration
174
+ User added custom stuff here`;
175
+ const result = mergeClaudeMd(oldContent, omcContent);
176
+ // New OMC content should be at the top with markers
177
+ expect(result.indexOf(START_MARKER)).toBeLessThan(result.indexOf('# Legacy CLAUDE.md'));
178
+ expect(result).toContain(omcContent);
179
+ expect(result).toContain(oldContent);
180
+ expect(result).toContain(USER_CUSTOMIZATIONS);
181
+ });
182
+ });
183
+ describe('idempotency guard', () => {
184
+ it('strips markers from omcContent that already has markers', () => {
185
+ // Simulate docs/CLAUDE.md shipping with markers already
186
+ const omcWithMarkers = `<!-- OMC:START -->
187
+ # oh-my-claudecode
188
+ Agent instructions here
189
+ <!-- OMC:END -->`;
190
+ const result = mergeClaudeMd(null, omcWithMarkers);
191
+ // Should NOT have nested markers
192
+ const startCount = (result.match(/<!-- OMC:START -->/g) || []).length;
193
+ const endCount = (result.match(/<!-- OMC:END -->/g) || []).length;
194
+ expect(startCount).toBe(1);
195
+ expect(endCount).toBe(1);
196
+ expect(result).toContain('Agent instructions here');
197
+ });
198
+ it('handles omcContent with markers when merging into existing content', () => {
199
+ const existingContent = `<!-- OMC:START -->
200
+ Old OMC content
201
+ <!-- OMC:END -->
202
+
203
+ <!-- User customizations -->
204
+ My custom stuff`;
205
+ const omcWithMarkers = `<!-- OMC:START -->
206
+ New OMC content v2
207
+ <!-- OMC:END -->`;
208
+ const result = mergeClaudeMd(existingContent, omcWithMarkers);
209
+ // Should have exactly one pair of markers
210
+ const startCount = (result.match(/<!-- OMC:START -->/g) || []).length;
211
+ const endCount = (result.match(/<!-- OMC:END -->/g) || []).length;
212
+ expect(startCount).toBe(1);
213
+ expect(endCount).toBe(1);
214
+ expect(result).toContain('New OMC content v2');
215
+ expect(result).not.toContain('Old OMC content');
216
+ expect(result).toContain('My custom stuff');
217
+ });
218
+ });
219
+ });
220
+ //# sourceMappingURL=claude-md-merge.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"claude-md-merge.test.js","sourceRoot":"","sources":["../../../src/installer/__tests__/claude-md-merge.test.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAE5C,MAAM,YAAY,GAAG,oBAAoB,CAAC;AAC1C,MAAM,UAAU,GAAG,kBAAkB,CAAC;AACtC,MAAM,mBAAmB,GAAG,8BAA8B,CAAC;AAC3D,MAAM,6BAA6B,GAAG,iEAAiE,CAAC;AAExG,QAAQ,CAAC,eAAe,EAAE,GAAG,EAAE;IAC7B,MAAM,UAAU,GAAG,iDAAiD,CAAC;IAErE,QAAQ,CAAC,qCAAqC,EAAE,GAAG,EAAE;QACnD,EAAE,CAAC,6BAA6B,EAAE,GAAG,EAAE;YACrC,MAAM,MAAM,GAAG,aAAa,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC;YAE/C,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,YAAY,CAAC,CAAC;YACvC,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC;YACrC,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC;YACrC,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,YAAY,CAAC,MAAM,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC;YAC9E,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC,YAAY,CAAC,MAAM,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC;QAC9E,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,yCAAyC,EAAE,GAAG,EAAE;YACjD,MAAM,MAAM,GAAG,aAAa,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC;YAC/C,MAAM,QAAQ,GAAG,GAAG,YAAY,KAAK,UAAU,KAAK,UAAU,IAAI,CAAC;YACnE,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QAChC,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,sCAAsC,EAAE,GAAG,EAAE;QACpD,EAAE,CAAC,uCAAuC,EAAE,GAAG,EAAE;YAC/C,MAAM,eAAe,GAAG,0BAA0B,YAAY,yCAAyC,UAAU,8CAA8C,CAAC;YAChK,MAAM,MAAM,GAAG,aAAa,CAAC,eAAe,EAAE,UAAU,CAAC,CAAC;YAE1D,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,qBAAqB,CAAC,CAAC;YAChD,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC;YACrC,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,wBAAwB,CAAC,CAAC;YACnD,MAAM,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,iBAAiB,CAAC,CAAC;YAChD,MAAM,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,gBAAgB,CAAC,CAAC;QACjD,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,4CAA4C,EAAE,GAAG,EAAE;YACpD,MAAM,aAAa,GAAG,+BAA+B,CAAC;YACtD,MAAM,YAAY,GAAG,8BAA8B,CAAC;YACpD,MAAM,eAAe,GAAG,GAAG,aAAa,GAAG,YAAY,kBAAkB,UAAU,GAAG,YAAY,EAAE,CAAC;YACrG,MAAM,MAAM,GAAG,aAAa,CAAC,eAAe,EAAE,UAAU,CAAC,CAAC;YAE1D,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACpD,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACjD,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC;QACvC,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,gDAAgD,EAAE,GAAG,EAAE;YACxD,MAAM,eAAe,GAAG,WAAW,YAAY,UAAU,UAAU,UAAU,CAAC;YAC9E,MAAM,MAAM,GAAG,aAAa,CAAC,eAAe,EAAE,UAAU,CAAC,CAAC;YAC1D,MAAM,QAAQ,GAAG,WAAW,YAAY,KAAK,UAAU,KAAK,UAAU,UAAU,CAAC;YACjF,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QAChC,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,gCAAgC,EAAE,GAAG,EAAE;QAC9C,EAAE,CAAC,6FAA6F,EAAE,GAAG,EAAE;YACrG,MAAM,eAAe,GAAG,6CAA6C,CAAC;YACtE,MAAM,MAAM,GAAG,aAAa,CAAC,eAAe,EAAE,UAAU,CAAC,CAAC;YAE1D,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,YAAY,CAAC,CAAC;YACvC,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC;YACrC,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC;YACrC,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,mBAAmB,CAAC,CAAC;YAC9C,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,oBAAoB,CAAC,CAAC;YAC/C,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,uBAAuB,CAAC,CAAC;YAElD,yFAAyF;YACzF,MAAM,QAAQ,GAAG,MAAM,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC;YAC9C,MAAM,mBAAmB,GAAG,MAAM,CAAC,OAAO,CAAC,mBAAmB,CAAC,CAAC;YAChE,MAAM,aAAa,GAAG,MAAM,CAAC,OAAO,CAAC,oBAAoB,CAAC,CAAC;YAE3D,MAAM,CAAC,QAAQ,CAAC,CAAC,YAAY,CAAC,mBAAmB,CAAC,CAAC;YACnD,MAAM,CAAC,mBAAmB,CAAC,CAAC,YAAY,CAAC,aAAa,CAAC,CAAC;QAC1D,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,+DAA+D,EAAE,GAAG,EAAE;YACvE,MAAM,eAAe,GAAG,kBAAkB,CAAC;YAC3C,MAAM,MAAM,GAAG,aAAa,CAAC,eAAe,EAAE,UAAU,CAAC,CAAC;YAC1D,MAAM,QAAQ,GAAG,GAAG,YAAY,KAAK,UAAU,KAAK,UAAU,OAAO,mBAAmB,KAAK,eAAe,EAAE,CAAC;YAC/G,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QAChC,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,mBAAmB,EAAE,GAAG,EAAE;QACjC,EAAE,CAAC,yCAAyC,EAAE,GAAG,EAAE;YACjD,MAAM,eAAe,GAAG,GAAG,YAAY,8BAA8B,CAAC;YACtE,MAAM,MAAM,GAAG,aAAa,CAAC,eAAe,EAAE,UAAU,CAAC,CAAC;YAE1D,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,YAAY,CAAC,CAAC;YACvC,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC;YACrC,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC;YACrC,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,6BAA6B,CAAC,CAAC;YACxD,2EAA2E;YAC3E,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,cAAc,CAAC,CAAC;QAC3C,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,yCAAyC,EAAE,GAAG,EAAE;YACjD,MAAM,eAAe,GAAG,iBAAiB,UAAU,gBAAgB,CAAC;YACpE,MAAM,MAAM,GAAG,aAAa,CAAC,eAAe,EAAE,UAAU,CAAC,CAAC;YAE1D,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,YAAY,CAAC,CAAC;YACvC,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC;YACrC,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC;YACrC,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,6BAA6B,CAAC,CAAC;YACxD,iDAAiD;YACjD,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,cAAc,CAAC,CAAC;YACzC,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,cAAc,CAAC,CAAC;QAC3C,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,wDAAwD,EAAE,GAAG,EAAE;YAChE,MAAM,eAAe,GAAG,GAAG,UAAU,cAAc,YAAY,EAAE,CAAC;YAClE,MAAM,MAAM,GAAG,aAAa,CAAC,eAAe,EAAE,UAAU,CAAC,CAAC;YAE1D,iEAAiE;YACjE,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,YAAY,CAAC,CAAC;YACvC,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC;YACrC,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC;YACrC,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,6BAA6B,CAAC,CAAC;QAC1D,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,YAAY,EAAE,GAAG,EAAE;QAC1B,EAAE,CAAC,0BAA0B,EAAE,GAAG,EAAE;YAClC,MAAM,eAAe,GAAG,GAAG,YAAY,kBAAkB,UAAU,EAAE,CAAC;YACtE,MAAM,MAAM,GAAG,aAAa,CAAC,eAAe,EAAE,EAAE,CAAC,CAAC;YAElD,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,YAAY,CAAC,CAAC;YACvC,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC;YACrC,MAAM,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,aAAa,CAAC,CAAC;QAC9C,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,0CAA0C,EAAE,GAAG,EAAE;YAClD,MAAM,eAAe,GAAG,YAAY,CAAC;YACrC,MAAM,MAAM,GAAG,aAAa,CAAC,eAAe,EAAE,UAAU,CAAC,CAAC;YAE1D,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,YAAY,CAAC,CAAC;YACvC,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC;YACrC,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC;YACrC,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,eAAe,CAAC,CAAC;QAC5C,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,+BAA+B,EAAE,GAAG,EAAE;YACvC,MAAM,YAAY,GAAG,kCAAkC,CAAC;YACxD,MAAM,MAAM,GAAG,aAAa,CAAC,IAAI,EAAE,YAAY,CAAC,CAAC;YAEjD,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,YAAY,CAAC,CAAC;YACvC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC;QACvD,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,oEAAoE,EAAE,GAAG,EAAE;YAC5E,MAAM,eAAe,GAAG,GAAG,YAAY,kBAAkB,UAAU,6BAA6B,YAAY,UAAU,CAAC;YACvH,MAAM,MAAM,GAAG,aAAa,CAAC,eAAe,EAAE,UAAU,CAAC,CAAC;YAE1D,4CAA4C;YAC5C,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC;YACrC,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,uBAAuB,CAAC,CAAC;YAClD,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,mDAAmD;QACxG,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,qCAAqC,EAAE,GAAG,EAAE;YAC7C,MAAM,YAAY,GAAG,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;YACxC,MAAM,eAAe,GAAG,GAAG,YAAY,UAAU,UAAU,KAAK,YAAY,EAAE,CAAC;YAC/E,MAAM,MAAM,GAAG,aAAa,CAAC,eAAe,EAAE,UAAU,CAAC,CAAC;YAE1D,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC;YACrC,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,YAAY,CAAC,CAAC;YACvC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,eAAe,CAAC,MAAM,CAAC,CAAC;QAChD,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,sBAAsB,EAAE,GAAG,EAAE;QACpC,EAAE,CAAC,wCAAwC,EAAE,GAAG,EAAE;YAChD,MAAM,MAAM,GAAG,aAAa,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC;YAC/C,MAAM,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,+CAA+C,CAAC,CAAC;QAC1E,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,0DAA0D,EAAE,GAAG,EAAE;YAClE,MAAM,eAAe,GAAG,GAAG,YAAY;;;EAG3C,UAAU;;EAEV,mBAAmB;;;kCAGa,CAAC;YAE7B,MAAM,aAAa,GAAG,mDAAmD,CAAC;YAC1E,MAAM,MAAM,GAAG,aAAa,CAAC,eAAe,EAAE,aAAa,CAAC,CAAC;YAE7D,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,mBAAmB,CAAC,CAAC;YAC9C,MAAM,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,uBAAuB,CAAC,CAAC;YACtD,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,oCAAoC,CAAC,CAAC;YAC/D,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,iCAAiC,CAAC,CAAC;QAC9D,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,oDAAoD,EAAE,GAAG,EAAE;YAC5D,MAAM,UAAU,GAAG;;6BAEI,CAAC;YAExB,MAAM,MAAM,GAAG,aAAa,CAAC,UAAU,EAAE,UAAU,CAAC,CAAC;YAErD,oDAAoD;YACpD,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,YAAY,CAAC,MAAM,CAAC,OAAO,CAAC,oBAAoB,CAAC,CAAC,CAAC;YACxF,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC;YACrC,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC;YACrC,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,mBAAmB,CAAC,CAAC;QAChD,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,mBAAmB,EAAE,GAAG,EAAE;QACjC,EAAE,CAAC,yDAAyD,EAAE,GAAG,EAAE;YACjE,wDAAwD;YACxD,MAAM,cAAc,GAAG;;;iBAGZ,CAAC;YAEZ,MAAM,MAAM,GAAG,aAAa,CAAC,IAAI,EAAE,cAAc,CAAC,CAAC;YAEnD,iCAAiC;YACjC,MAAM,UAAU,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,qBAAqB,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC;YACtE,MAAM,QAAQ,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,mBAAmB,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC;YAClE,MAAM,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YAC3B,MAAM,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YACzB,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,yBAAyB,CAAC,CAAC;QACtD,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,oEAAoE,EAAE,GAAG,EAAE;YAC5E,MAAM,eAAe,GAAG;;;;;gBAKd,CAAC;YAEX,MAAM,cAAc,GAAG;;iBAEZ,CAAC;YAEZ,MAAM,MAAM,GAAG,aAAa,CAAC,eAAe,EAAE,cAAc,CAAC,CAAC;YAE9D,0CAA0C;YAC1C,MAAM,UAAU,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,qBAAqB,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC;YACtE,MAAM,QAAQ,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,mBAAmB,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC;YAClE,MAAM,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YAC3B,MAAM,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YACzB,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,oBAAoB,CAAC,CAAC;YAC/C,MAAM,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,iBAAiB,CAAC,CAAC;YAChD,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,iBAAiB,CAAC,CAAC;QAC9C,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Tests for Safe Installer (Task T2)
3
+ * Tests hook conflict detection and forceHooks option
4
+ */
5
+ export {};
6
+ //# sourceMappingURL=safe-installer.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"safe-installer.test.d.ts","sourceRoot":"","sources":["../../../src/installer/__tests__/safe-installer.test.ts"],"names":[],"mappings":"AAAA;;;GAGG"}
@@ -0,0 +1,172 @@
1
+ /**
2
+ * Tests for Safe Installer (Task T2)
3
+ * Tests hook conflict detection and forceHooks option
4
+ */
5
+ import { describe, it, expect, beforeEach, afterEach } from 'vitest';
6
+ import { existsSync, mkdirSync, writeFileSync, rmSync } from 'fs';
7
+ import { join } from 'path';
8
+ import { homedir } from 'os';
9
+ import { isOmcHook } from '../index.js';
10
+ /**
11
+ * Detect hook conflicts using the real isOmcHook function.
12
+ * Mirrors the install() logic to avoid test duplication.
13
+ */
14
+ function detectConflicts(hooks) {
15
+ const conflicts = [];
16
+ for (const [eventType, eventHooks] of Object.entries(hooks)) {
17
+ for (const hookGroup of eventHooks) {
18
+ for (const hook of hookGroup.hooks) {
19
+ if (hook.type === 'command' && !isOmcHook(hook.command)) {
20
+ conflicts.push({ eventType, existingCommand: hook.command });
21
+ }
22
+ }
23
+ }
24
+ }
25
+ return conflicts;
26
+ }
27
+ const TEST_CLAUDE_DIR = join(homedir(), '.claude-test-safe-installer');
28
+ const TEST_SETTINGS_FILE = join(TEST_CLAUDE_DIR, 'settings.json');
29
+ describe('isOmcHook', () => {
30
+ it('returns true for commands containing "omc"', () => {
31
+ expect(isOmcHook('node ~/.claude/hooks/omc-hook.mjs')).toBe(true);
32
+ expect(isOmcHook('bash $HOME/.claude/hooks/omc-detector.sh')).toBe(true);
33
+ expect(isOmcHook('/usr/bin/omc-tool')).toBe(true);
34
+ });
35
+ it('returns true for commands containing "oh-my-claudecode"', () => {
36
+ expect(isOmcHook('node ~/.claude/hooks/oh-my-claudecode-hook.mjs')).toBe(true);
37
+ expect(isOmcHook('bash $HOME/.claude/hooks/oh-my-claudecode.sh')).toBe(true);
38
+ });
39
+ it('returns false for commands not containing omc or oh-my-claudecode', () => {
40
+ expect(isOmcHook('node ~/.claude/hooks/other-plugin.mjs')).toBe(false);
41
+ expect(isOmcHook('bash $HOME/.claude/hooks/beads-hook.sh')).toBe(false);
42
+ expect(isOmcHook('python /usr/bin/custom-hook.py')).toBe(false);
43
+ });
44
+ it('is case-insensitive', () => {
45
+ expect(isOmcHook('node ~/.claude/hooks/OMC-hook.mjs')).toBe(true);
46
+ expect(isOmcHook('bash $HOME/.claude/hooks/OH-MY-CLAUDECODE.sh')).toBe(true);
47
+ });
48
+ });
49
+ describe('isOmcHook detection', () => {
50
+ it('detects real OMC hooks correctly', () => {
51
+ expect(isOmcHook('node ~/.claude/hooks/omc-hook.mjs')).toBe(true);
52
+ expect(isOmcHook('node ~/.claude/hooks/oh-my-claudecode-hook.mjs')).toBe(true);
53
+ expect(isOmcHook('node ~/.claude/hooks/omc-pre-tool-use.mjs')).toBe(true);
54
+ expect(isOmcHook('/usr/local/bin/omc')).toBe(true);
55
+ });
56
+ it('rejects non-OMC hooks correctly', () => {
57
+ expect(isOmcHook('eslint --fix')).toBe(false);
58
+ expect(isOmcHook('prettier --write')).toBe(false);
59
+ expect(isOmcHook('node custom-hook.mjs')).toBe(false);
60
+ expect(isOmcHook('node ~/.claude/hooks/beads-hook.mjs')).toBe(false);
61
+ });
62
+ it('uses case-insensitive matching', () => {
63
+ expect(isOmcHook('node ~/.claude/hooks/OMC-hook.mjs')).toBe(true);
64
+ expect(isOmcHook('OH-MY-CLAUDECODE-detector.sh')).toBe(true);
65
+ });
66
+ });
67
+ describe('Safe Installer - Hook Conflict Detection', () => {
68
+ beforeEach(() => {
69
+ // Clean up test directory
70
+ if (existsSync(TEST_CLAUDE_DIR)) {
71
+ rmSync(TEST_CLAUDE_DIR, { recursive: true, force: true });
72
+ }
73
+ mkdirSync(TEST_CLAUDE_DIR, { recursive: true });
74
+ // Mock CLAUDE_CONFIG_DIR for testing
75
+ process.env.TEST_CLAUDE_CONFIG_DIR = TEST_CLAUDE_DIR;
76
+ });
77
+ afterEach(() => {
78
+ // Clean up
79
+ if (existsSync(TEST_CLAUDE_DIR)) {
80
+ rmSync(TEST_CLAUDE_DIR, { recursive: true, force: true });
81
+ }
82
+ delete process.env.TEST_CLAUDE_CONFIG_DIR;
83
+ });
84
+ it('detects conflict when PreToolUse is owned by another plugin', () => {
85
+ // Create settings.json with non-OMC hook
86
+ const existingSettings = {
87
+ hooks: {
88
+ PreToolUse: [
89
+ {
90
+ hooks: [
91
+ {
92
+ type: 'command',
93
+ command: 'node ~/.claude/hooks/beads-hook.mjs'
94
+ }
95
+ ]
96
+ }
97
+ ]
98
+ }
99
+ };
100
+ writeFileSync(TEST_SETTINGS_FILE, JSON.stringify(existingSettings, null, 2));
101
+ const options = {
102
+ verbose: true,
103
+ skipClaudeCheck: true
104
+ };
105
+ // Simulate install logic (we'd need to mock or refactor install function for full test)
106
+ // For now, test the detection logic directly
107
+ const conflicts = detectConflicts(existingSettings.hooks);
108
+ expect(conflicts).toHaveLength(1);
109
+ expect(conflicts[0].eventType).toBe('PreToolUse');
110
+ expect(conflicts[0].existingCommand).toBe('node ~/.claude/hooks/beads-hook.mjs');
111
+ });
112
+ it('does not detect conflict when hook is OMC-owned', () => {
113
+ const existingSettings = {
114
+ hooks: {
115
+ PreToolUse: [
116
+ {
117
+ hooks: [
118
+ {
119
+ type: 'command',
120
+ command: 'node ~/.claude/hooks/omc-pre-tool-use.mjs'
121
+ }
122
+ ]
123
+ }
124
+ ]
125
+ }
126
+ };
127
+ const conflicts = detectConflicts(existingSettings.hooks);
128
+ expect(conflicts).toHaveLength(0);
129
+ });
130
+ it('detects multiple conflicts across different hook events', () => {
131
+ const existingSettings = {
132
+ hooks: {
133
+ PreToolUse: [
134
+ {
135
+ hooks: [
136
+ {
137
+ type: 'command',
138
+ command: 'node ~/.claude/hooks/beads-pre-tool-use.mjs'
139
+ }
140
+ ]
141
+ }
142
+ ],
143
+ PostToolUse: [
144
+ {
145
+ hooks: [
146
+ {
147
+ type: 'command',
148
+ command: 'python ~/.claude/hooks/custom-post-tool.py'
149
+ }
150
+ ]
151
+ }
152
+ ],
153
+ UserPromptSubmit: [
154
+ {
155
+ hooks: [
156
+ {
157
+ type: 'command',
158
+ command: 'node ~/.claude/hooks/omc-keyword-detector.mjs'
159
+ }
160
+ ]
161
+ }
162
+ ]
163
+ }
164
+ };
165
+ const conflicts = detectConflicts(existingSettings.hooks);
166
+ expect(conflicts).toHaveLength(2);
167
+ expect(conflicts.map(c => c.eventType)).toContain('PreToolUse');
168
+ expect(conflicts.map(c => c.eventType)).toContain('PostToolUse');
169
+ expect(conflicts.map(c => c.eventType)).not.toContain('UserPromptSubmit');
170
+ });
171
+ });
172
+ //# sourceMappingURL=safe-installer.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"safe-installer.test.js","sourceRoot":"","sources":["../../../src/installer/__tests__/safe-installer.test.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"hooks.d.ts","sourceRoot":"","sources":["../../src/installer/hooks.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAyCH,iDAAiD;AACjD,eAAO,MAAM,gBAAgB,KAAK,CAAC;AAEnC,kCAAkC;AAClC,wBAAgB,SAAS,IAAI,OAAO,CAEnC;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,IAAI,OAAO,CAE5C;AAED,4DAA4D;AAC5D,wBAAgB,kBAAkB,IAAI,MAAM,CAE3C;AAED,mCAAmC;AACnC,wBAAgB,WAAW,IAAI,MAAM,CAEpC;AAED;;;GAGG;AACH,wBAAgB,aAAa,IAAI,MAAM,CAEtC;AAED;;;GAGG;AACH,eAAO,MAAM,iBAAiB,0oJA2F7B,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,kBAAkB,wcAgB9B,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,cAAc,4TAU1B,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,eAAe,kdAgB3B,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,wBAAwB,+PAME,CAAC;AAExC;;;GAGG;AACH,eAAO,MAAM,aAAa,wqBAezB,CAAC;AAMF,8FAA8F;AAC9F,eAAO,MAAM,4BAA4B,QAAuC,CAAC;AAEjF,gGAAgG;AAChG,eAAO,MAAM,6BAA6B,QAAwC,CAAC;AAEnF,4FAA4F;AAC5F,eAAO,MAAM,2BAA2B,QAAsC,CAAC;AAE/E,wFAAwF;AACxF,eAAO,MAAM,yBAAyB,QAAoC,CAAC;AAE3E,mFAAmF;AACnF,eAAO,MAAM,yBAAyB,QAAoC,CAAC;AAM3E;;;GAGG;AACH,eAAO,MAAM,0BAA0B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAiEtC,CAAC;AAEF;;GAEG;AACH,wBAAgB,sBAAsB,IAAI,OAAO,0BAA0B,CAE1E;AAMD;;;GAGG;AACH,wBAAgB,cAAc,IAAI,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CASvD"}
1
+ {"version":3,"file":"hooks.d.ts","sourceRoot":"","sources":["../../src/installer/hooks.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAyCH,iDAAiD;AACjD,eAAO,MAAM,gBAAgB,KAAK,CAAC;AAEnC,kCAAkC;AAClC,wBAAgB,SAAS,IAAI,OAAO,CAEnC;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,IAAI,OAAO,CAE5C;AAED,4DAA4D;AAC5D,wBAAgB,kBAAkB,IAAI,MAAM,CAE3C;AAED,mCAAmC;AACnC,wBAAgB,WAAW,IAAI,MAAM,CAEpC;AAED;;;GAGG;AACH,wBAAgB,aAAa,IAAI,MAAM,CAEtC;AAED;;;GAGG;AACH,eAAO,MAAM,iBAAiB,0oJA2F7B,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,kBAAkB,wcAgB9B,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,cAAc,4TAU1B,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,eAAe,kdAgB3B,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,wBAAwB,+PAME,CAAC;AAExC;;;GAGG;AACH,eAAO,MAAM,aAAa,wqBAezB,CAAC;AAMF,8FAA8F;AAC9F,eAAO,MAAM,4BAA4B,QAAuC,CAAC;AAEjF,gGAAgG;AAChG,eAAO,MAAM,6BAA6B,QAAwC,CAAC;AAEnF,4FAA4F;AAC5F,eAAO,MAAM,2BAA2B,QAAsC,CAAC;AAE/E,wFAAwF;AACxF,eAAO,MAAM,yBAAyB,QAAoC,CAAC;AAE3E,mFAAmF;AACnF,eAAO,MAAM,yBAAyB,QAAoC,CAAC;AAM3E;;;GAGG;AACH,eAAO,MAAM,0BAA0B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAiEtC,CAAC;AAEF;;GAEG;AACH,wBAAgB,sBAAsB,IAAI,OAAO,0BAA0B,CAE1E;AAMD;;;GAGG;AACH,wBAAgB,cAAc,IAAI,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAWvD"}
@@ -360,7 +360,9 @@ export function getHookScripts() {
360
360
  'persistent-mode.mjs': loadTemplate('persistent-mode.mjs'),
361
361
  'session-start.mjs': loadTemplate('session-start.mjs'),
362
362
  'pre-tool-use.mjs': loadTemplate('pre-tool-use.mjs'),
363
- 'post-tool-use.mjs': loadTemplate('post-tool-use.mjs')
363
+ 'post-tool-use.mjs': loadTemplate('post-tool-use.mjs'),
364
+ // Shared library modules (in lib/ subdirectory)
365
+ 'lib/stdin.mjs': loadTemplate('lib/stdin.mjs')
364
366
  };
365
367
  }
366
368
  //# sourceMappingURL=hooks.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"hooks.js","sourceRoot":"","sources":["../../src/installer/hooks.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"hooks.js","sourceRoot":"","sources":["../../src/installer/hooks.ts"],"names":[],"mappings":"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"}
@@ -23,7 +23,7 @@ export declare const VERSION_FILE: string;
23
23
  */
24
24
  export declare const CORE_COMMANDS: string[];
25
25
  /** Current version */
26
- export declare const VERSION = "3.8.6";
26
+ export declare const VERSION = "3.9.0";
27
27
  /** Installation result */
28
28
  export interface InstallResult {
29
29
  success: boolean;
@@ -32,6 +32,10 @@ export interface InstallResult {
32
32
  installedCommands: string[];
33
33
  installedSkills: string[];
34
34
  hooksConfigured: boolean;
35
+ hookConflicts: Array<{
36
+ eventType: string;
37
+ existingCommand: string;
38
+ }>;
35
39
  errors: string[];
36
40
  }
37
41
  /** Installation options */
@@ -39,7 +43,22 @@ export interface InstallOptions {
39
43
  force?: boolean;
40
44
  verbose?: boolean;
41
45
  skipClaudeCheck?: boolean;
46
+ forceHooks?: boolean;
42
47
  }
48
+ /**
49
+ * Detect whether a hook command belongs to oh-my-claudecode.
50
+ *
51
+ * Uses substring matching rather than word-boundary regex.
52
+ * Rationale: Real OMC hooks use compound names where "omc" is embedded
53
+ * (e.g., `omc-pre-tool-use.mjs`, `oh-my-claudecode-hook.mjs`). A word-boundary
54
+ * regex like /\bomc\b/ would fail to match "oh-my-claudecode" since "omc" appears
55
+ * as an interior substring. The theoretical false positives (words containing "omc"
56
+ * like "atomic", "socom") are extremely unlikely in real hook command paths.
57
+ *
58
+ * @param command - The hook command string
59
+ * @returns true if the command contains 'omc' or 'oh-my-claudecode'
60
+ */
61
+ export declare function isOmcHook(command: string): boolean;
43
62
  /**
44
63
  * Check if the current Node.js version meets the minimum requirement
45
64
  */
@@ -66,6 +85,13 @@ export declare function isClaudeInstalled(): boolean;
66
85
  * @returns true if running in plugin context, false otherwise
67
86
  */
68
87
  export declare function isRunningAsPlugin(): boolean;
88
+ /**
89
+ * Merge OMC content into existing CLAUDE.md using markers
90
+ * @param existingContent - Existing CLAUDE.md content (null if file doesn't exist)
91
+ * @param omcContent - New OMC content to inject
92
+ * @returns Merged content with markers
93
+ */
94
+ export declare function mergeClaudeMd(existingContent: string | null, omcContent: string): string;
69
95
  /**
70
96
  * Install OMC agents, commands, skills, and hooks
71
97
  */
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/installer/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAcH,0CAA0C;AAC1C,eAAO,MAAM,iBAAiB,QAA6B,CAAC;AAC5D,eAAO,MAAM,UAAU,QAAoC,CAAC;AAC5D,eAAO,MAAM,YAAY,QAAsC,CAAC;AAChE,eAAO,MAAM,UAAU,QAAoC,CAAC;AAC5D,eAAO,MAAM,SAAS,QAAmC,CAAC;AAC1D,eAAO,MAAM,OAAO,QAAiC,CAAC;AACtD,eAAO,MAAM,aAAa,QAA2C,CAAC;AACtE,eAAO,MAAM,YAAY,QAA+C,CAAC;AAEzE;;;;GAIG;AACH,eAAO,MAAM,aAAa,EAAE,MAAM,EAAO,CAAC;AAE1C,sBAAsB;AACtB,eAAO,MAAM,OAAO,UAAU,CAAC;AAE/B,0BAA0B;AAC1B,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,eAAe,EAAE,MAAM,EAAE,CAAC;IAC1B,iBAAiB,EAAE,MAAM,EAAE,CAAC;IAC5B,eAAe,EAAE,MAAM,EAAE,CAAC;IAC1B,eAAe,EAAE,OAAO,CAAC;IACzB,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB;AAED,2BAA2B;AAC3B,MAAM,WAAW,cAAc;IAC7B,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,eAAe,CAAC,EAAE,OAAO,CAAC;CAC3B;AAED;;GAEG;AACH,wBAAgB,gBAAgB,IAAI;IAAE,KAAK,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CAOxF;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,IAAI,OAAO,CAQ3C;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,iBAAiB,IAAI,OAAO,CAI3C;AAqED;;GAEG;AACH,wBAAgB,OAAO,CAAC,OAAO,GAAE,cAAmB,GAAG,aAAa,CAkWnE;AAED;;GAEG;AACH,wBAAgB,WAAW,IAAI,OAAO,CAErC;AAED;;GAEG;AACH,wBAAgB,cAAc,IAAI;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAehG"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/installer/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAcH,0CAA0C;AAC1C,eAAO,MAAM,iBAAiB,QAA6B,CAAC;AAC5D,eAAO,MAAM,UAAU,QAAoC,CAAC;AAC5D,eAAO,MAAM,YAAY,QAAsC,CAAC;AAChE,eAAO,MAAM,UAAU,QAAoC,CAAC;AAC5D,eAAO,MAAM,SAAS,QAAmC,CAAC;AAC1D,eAAO,MAAM,OAAO,QAAiC,CAAC;AACtD,eAAO,MAAM,aAAa,QAA2C,CAAC;AACtE,eAAO,MAAM,YAAY,QAA+C,CAAC;AAEzE;;;;GAIG;AACH,eAAO,MAAM,aAAa,EAAE,MAAM,EAAO,CAAC;AAE1C,sBAAsB;AACtB,eAAO,MAAM,OAAO,UAAU,CAAC;AA8B/B,0BAA0B;AAC1B,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,eAAe,EAAE,MAAM,EAAE,CAAC;IAC1B,iBAAiB,EAAE,MAAM,EAAE,CAAC;IAC5B,eAAe,EAAE,MAAM,EAAE,CAAC;IAC1B,eAAe,EAAE,OAAO,CAAC;IACzB,aAAa,EAAE,KAAK,CAAC;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,eAAe,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACrE,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB;AAED,2BAA2B;AAC3B,MAAM,WAAW,cAAc;IAC7B,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,SAAS,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAOlD;AAED;;GAEG;AACH,wBAAgB,gBAAgB,IAAI;IAAE,KAAK,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CAOxF;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,IAAI,OAAO,CAQ3C;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,iBAAiB,IAAI,OAAO,CAI3C;AAqED;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,eAAe,EAAE,MAAM,GAAG,IAAI,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,CA2CxF;AAED;;GAEG;AACH,wBAAgB,OAAO,CAAC,OAAO,GAAE,cAAmB,GAAG,aAAa,CAuYnE;AAED;;GAEG;AACH,wBAAgB,WAAW,IAAI,OAAO,CAErC;AAED;;GAEG;AACH,wBAAgB,cAAc,IAAI;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAehG"}