oh-my-claude-sisyphus 3.5.7 → 3.6.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.
- package/agents/executor-high.md +2 -0
- package/agents/executor-low.md +2 -0
- package/agents/executor.md +2 -0
- package/agents/templates/base-agent.md +9 -0
- package/commands/cancel.md +8 -8
- package/commands/swarm.md +350 -148
- package/dist/__tests__/hooks/auto-slash-command/executor.test.d.ts +7 -0
- package/dist/__tests__/hooks/auto-slash-command/executor.test.d.ts.map +1 -0
- package/dist/__tests__/hooks/auto-slash-command/executor.test.js +374 -0
- package/dist/__tests__/hooks/auto-slash-command/executor.test.js.map +1 -0
- package/dist/__tests__/hooks/learner/bridge.test.d.ts +11 -0
- package/dist/__tests__/hooks/learner/bridge.test.d.ts.map +1 -0
- package/dist/__tests__/hooks/learner/bridge.test.js +199 -0
- package/dist/__tests__/hooks/learner/bridge.test.js.map +1 -0
- package/dist/__tests__/hooks.test.js +10 -9
- package/dist/__tests__/hooks.test.js.map +1 -1
- package/dist/__tests__/installer.test.js +1 -1
- package/dist/agents/codex-agents.d.ts +20 -0
- package/dist/agents/codex-agents.d.ts.map +1 -0
- package/dist/agents/codex-agents.js +36 -0
- package/dist/agents/codex-agents.js.map +1 -0
- package/dist/agents/preamble.d.ts +14 -0
- package/dist/agents/preamble.d.ts.map +1 -0
- package/dist/agents/preamble.js +26 -0
- package/dist/agents/preamble.js.map +1 -0
- package/dist/hooks/autopilot/__tests__/cancel.test.js +14 -4
- package/dist/hooks/autopilot/__tests__/cancel.test.js.map +1 -1
- package/dist/hooks/autopilot/__tests__/state.test.js +1 -0
- package/dist/hooks/autopilot/__tests__/state.test.js.map +1 -1
- package/dist/hooks/autopilot/__tests__/summary.test.js +38 -3
- package/dist/hooks/autopilot/__tests__/summary.test.js.map +1 -1
- package/dist/hooks/autopilot/state.d.ts +1 -1
- package/dist/hooks/autopilot/state.d.ts.map +1 -1
- package/dist/hooks/autopilot/state.js +15 -8
- package/dist/hooks/autopilot/state.js.map +1 -1
- package/dist/hooks/index.d.ts +2 -0
- package/dist/hooks/index.d.ts.map +1 -1
- package/dist/hooks/index.js +7 -0
- package/dist/hooks/index.js.map +1 -1
- package/dist/hooks/learner/bridge.d.ts +71 -0
- package/dist/hooks/learner/bridge.d.ts.map +1 -0
- package/dist/hooks/learner/bridge.js +426 -0
- package/dist/hooks/learner/bridge.js.map +1 -0
- package/dist/hooks/mode-registry/index.d.ts +135 -0
- package/dist/hooks/mode-registry/index.d.ts.map +1 -0
- package/dist/hooks/mode-registry/index.js +445 -0
- package/dist/hooks/mode-registry/index.js.map +1 -0
- package/dist/hooks/mode-registry/types.d.ts +31 -0
- package/dist/hooks/mode-registry/types.d.ts.map +1 -0
- package/dist/hooks/mode-registry/types.js +7 -0
- package/dist/hooks/mode-registry/types.js.map +1 -0
- package/dist/hooks/ralph/loop.js +6 -6
- package/dist/hooks/ralph/loop.js.map +1 -1
- package/dist/hooks/skill-bridge.cjs +349 -0
- package/dist/hooks/swarm/__tests__/claiming.test.d.ts +2 -0
- package/dist/hooks/swarm/__tests__/claiming.test.d.ts.map +1 -0
- package/dist/hooks/swarm/__tests__/claiming.test.js +170 -0
- package/dist/hooks/swarm/__tests__/claiming.test.js.map +1 -0
- package/dist/hooks/swarm/__tests__/index.test.d.ts +2 -0
- package/dist/hooks/swarm/__tests__/index.test.d.ts.map +1 -0
- package/dist/hooks/swarm/__tests__/index.test.js +157 -0
- package/dist/hooks/swarm/__tests__/index.test.js.map +1 -0
- package/dist/hooks/swarm/__tests__/mode-registry.test.d.ts +2 -0
- package/dist/hooks/swarm/__tests__/mode-registry.test.d.ts.map +1 -0
- package/dist/hooks/swarm/__tests__/mode-registry.test.js +177 -0
- package/dist/hooks/swarm/__tests__/mode-registry.test.js.map +1 -0
- package/dist/hooks/swarm/claiming.d.ts +101 -0
- package/dist/hooks/swarm/claiming.d.ts.map +1 -0
- package/dist/hooks/swarm/claiming.js +460 -0
- package/dist/hooks/swarm/claiming.js.map +1 -0
- package/dist/hooks/swarm/index.d.ts +221 -0
- package/dist/hooks/swarm/index.d.ts.map +1 -0
- package/dist/hooks/swarm/index.js +413 -0
- package/dist/hooks/swarm/index.js.map +1 -0
- package/dist/hooks/swarm/state.d.ts +94 -0
- package/dist/hooks/swarm/state.d.ts.map +1 -0
- package/dist/hooks/swarm/state.js +530 -0
- package/dist/hooks/swarm/state.js.map +1 -0
- package/dist/hooks/swarm/types.d.ts +116 -0
- package/dist/hooks/swarm/types.d.ts.map +1 -0
- package/dist/hooks/swarm/types.js +22 -0
- package/dist/hooks/swarm/types.js.map +1 -0
- package/dist/hooks/ultrapilot/decomposer.d.ts +141 -0
- package/dist/hooks/ultrapilot/decomposer.d.ts.map +1 -0
- package/dist/hooks/ultrapilot/decomposer.js +377 -0
- package/dist/hooks/ultrapilot/decomposer.js.map +1 -0
- package/dist/hooks/ultrapilot/index.d.ts +31 -0
- package/dist/hooks/ultrapilot/index.d.ts.map +1 -1
- package/dist/hooks/ultrapilot/index.js +43 -2
- package/dist/hooks/ultrapilot/index.js.map +1 -1
- package/dist/hooks/ultrapilot/state.d.ts +1 -1
- package/dist/hooks/ultrapilot/state.d.ts.map +1 -1
- package/dist/hooks/ultrapilot/state.js +7 -0
- package/dist/hooks/ultrapilot/state.js.map +1 -1
- package/dist/hooks/ultraqa/index.js +5 -5
- package/dist/hooks/ultraqa/index.js.map +1 -1
- package/dist/hooks/ultrawork/index.js +3 -3
- package/dist/hooks/ultrawork/index.js.map +1 -1
- package/dist/installer/index.d.ts +1 -1
- package/dist/installer/index.js +1 -1
- package/package.json +6 -2
- package/scripts/build-skill-bridge.mjs +32 -0
- package/scripts/skill-injector.mjs +77 -26
- package/skills/autopilot/SKILL.md +18 -0
- package/skills/cancel/SKILL.md +166 -141
- package/skills/ecomode/SKILL.md +14 -0
- package/skills/pipeline/SKILL.md +13 -0
- package/skills/ralph/SKILL.md +22 -1
- package/skills/swarm/SKILL.md +521 -197
- package/skills/ultrapilot/SKILL.md +82 -13
- package/skills/ultraqa/SKILL.md +13 -0
- package/skills/ultrawork/SKILL.md +14 -0
|
@@ -0,0 +1,374 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Integration tests for learned skill discovery
|
|
3
|
+
*
|
|
4
|
+
* Tests the discoverAllCommands() functionality with project and user-scoped skills
|
|
5
|
+
*/
|
|
6
|
+
import { describe, it, expect, beforeEach, afterEach } from 'vitest';
|
|
7
|
+
import { mkdirSync, writeFileSync, rmSync, existsSync, readdirSync } from 'fs';
|
|
8
|
+
import { join } from 'path';
|
|
9
|
+
import { tmpdir } from 'os';
|
|
10
|
+
import { discoverAllCommands, findCommand, executeSlashCommand } from '../../../hooks/auto-slash-command/executor.js';
|
|
11
|
+
describe('Learned Skill Discovery', () => {
|
|
12
|
+
let testProjectRoot;
|
|
13
|
+
let testUserSkillsDir;
|
|
14
|
+
let originalCwd;
|
|
15
|
+
beforeEach(() => {
|
|
16
|
+
// Save original CWD
|
|
17
|
+
originalCwd = process.cwd();
|
|
18
|
+
// Create temp project root
|
|
19
|
+
testProjectRoot = join(tmpdir(), `omc-test-${Date.now()}`);
|
|
20
|
+
mkdirSync(testProjectRoot, { recursive: true });
|
|
21
|
+
// Create temp user skills directory
|
|
22
|
+
testUserSkillsDir = join(tmpdir(), `omc-user-skills-${Date.now()}`);
|
|
23
|
+
mkdirSync(testUserSkillsDir, { recursive: true });
|
|
24
|
+
// Change to test project root
|
|
25
|
+
process.chdir(testProjectRoot);
|
|
26
|
+
});
|
|
27
|
+
afterEach(() => {
|
|
28
|
+
// Restore original CWD
|
|
29
|
+
process.chdir(originalCwd);
|
|
30
|
+
// Clean up temp directories
|
|
31
|
+
if (existsSync(testProjectRoot)) {
|
|
32
|
+
rmSync(testProjectRoot, { recursive: true, force: true });
|
|
33
|
+
}
|
|
34
|
+
if (existsSync(testUserSkillsDir)) {
|
|
35
|
+
rmSync(testUserSkillsDir, { recursive: true, force: true });
|
|
36
|
+
}
|
|
37
|
+
});
|
|
38
|
+
it('should discover skills in project .omc/skills/', () => {
|
|
39
|
+
// Create project skills directory
|
|
40
|
+
const projectSkillsDir = join(testProjectRoot, '.omc', 'skills');
|
|
41
|
+
mkdirSync(projectSkillsDir, { recursive: true });
|
|
42
|
+
// Create a test skill file
|
|
43
|
+
const skillContent = `---
|
|
44
|
+
name: test-project-skill
|
|
45
|
+
description: A test project skill
|
|
46
|
+
model: sonnet
|
|
47
|
+
---
|
|
48
|
+
|
|
49
|
+
This is a test project skill template.
|
|
50
|
+
|
|
51
|
+
User request: $ARGUMENTS
|
|
52
|
+
`;
|
|
53
|
+
writeFileSync(join(projectSkillsDir, 'test-project-skill.md'), skillContent);
|
|
54
|
+
// Discover commands
|
|
55
|
+
const commands = discoverAllCommands();
|
|
56
|
+
// Verify skill is discovered
|
|
57
|
+
const projectSkill = commands.find(cmd => cmd.name === 'test-project-skill');
|
|
58
|
+
expect(projectSkill).toBeDefined();
|
|
59
|
+
expect(projectSkill?.scope).toBe('project-skill');
|
|
60
|
+
expect(projectSkill?.metadata.description).toBe('A test project skill');
|
|
61
|
+
expect(projectSkill?.metadata.model).toBe('sonnet');
|
|
62
|
+
});
|
|
63
|
+
it('should discover skills in user ~/.claude/skills/omc-learned/', () => {
|
|
64
|
+
// Mock the user skills directory by creating it in our test location
|
|
65
|
+
// Note: This test would need to mock homedir() or use environment variables
|
|
66
|
+
// For now, we'll test the discoverCommandsFromDir function indirectly
|
|
67
|
+
// Create user skills directory (simulated)
|
|
68
|
+
const userSkillsDir = join(testProjectRoot, '.test-user-skills');
|
|
69
|
+
mkdirSync(userSkillsDir, { recursive: true });
|
|
70
|
+
// Create a test user skill file
|
|
71
|
+
const skillContent = `---
|
|
72
|
+
name: test-user-skill
|
|
73
|
+
description: A test user skill
|
|
74
|
+
agent: executor
|
|
75
|
+
---
|
|
76
|
+
|
|
77
|
+
This is a test user skill template.
|
|
78
|
+
|
|
79
|
+
Arguments provided: $ARGUMENTS
|
|
80
|
+
`;
|
|
81
|
+
writeFileSync(join(userSkillsDir, 'test-user-skill.md'), skillContent);
|
|
82
|
+
// Manually test discovery logic (since we can't easily mock homedir)
|
|
83
|
+
const entries = readdirSync(userSkillsDir, { withFileTypes: true });
|
|
84
|
+
const mdFiles = entries.filter((e) => e.isFile() && e.name.endsWith('.md'));
|
|
85
|
+
expect(mdFiles.length).toBeGreaterThan(0);
|
|
86
|
+
expect(mdFiles[0].name).toBe('test-user-skill.md');
|
|
87
|
+
});
|
|
88
|
+
it('should prioritize project skills over user skills with same name', () => {
|
|
89
|
+
// Create both project and user skills directories
|
|
90
|
+
const projectSkillsDir = join(testProjectRoot, '.omc', 'skills');
|
|
91
|
+
mkdirSync(projectSkillsDir, { recursive: true });
|
|
92
|
+
// Create project skill
|
|
93
|
+
const projectSkillContent = `---
|
|
94
|
+
name: duplicate-skill
|
|
95
|
+
description: Project version
|
|
96
|
+
---
|
|
97
|
+
|
|
98
|
+
This is the PROJECT version.
|
|
99
|
+
`;
|
|
100
|
+
writeFileSync(join(projectSkillsDir, 'duplicate-skill.md'), projectSkillContent);
|
|
101
|
+
// Create .claude/commands user skill (simulating user-level command)
|
|
102
|
+
const userCommandsDir = join(testProjectRoot, '.claude-user-sim', 'commands');
|
|
103
|
+
mkdirSync(userCommandsDir, { recursive: true });
|
|
104
|
+
const userSkillContent = `---
|
|
105
|
+
name: duplicate-skill
|
|
106
|
+
description: User version
|
|
107
|
+
---
|
|
108
|
+
|
|
109
|
+
This is the USER version.
|
|
110
|
+
`;
|
|
111
|
+
writeFileSync(join(userCommandsDir, 'duplicate-skill.md'), userSkillContent);
|
|
112
|
+
// Discover all commands
|
|
113
|
+
const commands = discoverAllCommands();
|
|
114
|
+
// Find all instances of duplicate-skill
|
|
115
|
+
const duplicateSkills = commands.filter(cmd => cmd.name === 'duplicate-skill');
|
|
116
|
+
// The first one should be the project skill (higher priority)
|
|
117
|
+
if (duplicateSkills.length > 0) {
|
|
118
|
+
expect(duplicateSkills[0].scope).toBe('project-skill');
|
|
119
|
+
expect(duplicateSkills[0].metadata.description).toBe('Project version');
|
|
120
|
+
}
|
|
121
|
+
});
|
|
122
|
+
it('should parse flat .md format with frontmatter correctly', () => {
|
|
123
|
+
const projectSkillsDir = join(testProjectRoot, '.omc', 'skills');
|
|
124
|
+
mkdirSync(projectSkillsDir, { recursive: true });
|
|
125
|
+
// Create skill with comprehensive frontmatter
|
|
126
|
+
const skillContent = `---
|
|
127
|
+
name: comprehensive-skill
|
|
128
|
+
description: A comprehensive test skill
|
|
129
|
+
argument-hint: <task description>
|
|
130
|
+
model: opus
|
|
131
|
+
agent: architect
|
|
132
|
+
---
|
|
133
|
+
|
|
134
|
+
# Comprehensive Skill Template
|
|
135
|
+
|
|
136
|
+
This template uses all metadata fields.
|
|
137
|
+
|
|
138
|
+
## Task
|
|
139
|
+
$ARGUMENTS
|
|
140
|
+
|
|
141
|
+
## Instructions
|
|
142
|
+
1. Analyze the task
|
|
143
|
+
2. Execute with precision
|
|
144
|
+
3. Verify results
|
|
145
|
+
`;
|
|
146
|
+
writeFileSync(join(projectSkillsDir, 'comprehensive-skill.md'), skillContent);
|
|
147
|
+
const commands = discoverAllCommands();
|
|
148
|
+
const skill = commands.find(cmd => cmd.name === 'comprehensive-skill');
|
|
149
|
+
expect(skill).toBeDefined();
|
|
150
|
+
expect(skill?.metadata.name).toBe('comprehensive-skill');
|
|
151
|
+
expect(skill?.metadata.description).toBe('A comprehensive test skill');
|
|
152
|
+
expect(skill?.metadata.argumentHint).toBe('<task description>');
|
|
153
|
+
expect(skill?.metadata.model).toBe('opus');
|
|
154
|
+
expect(skill?.metadata.agent).toBe('architect');
|
|
155
|
+
expect(skill?.content).toContain('# Comprehensive Skill Template');
|
|
156
|
+
expect(skill?.content).toContain('$ARGUMENTS');
|
|
157
|
+
});
|
|
158
|
+
it('should fallback to filename if no name field in frontmatter', () => {
|
|
159
|
+
const projectSkillsDir = join(testProjectRoot, '.omc', 'skills');
|
|
160
|
+
mkdirSync(projectSkillsDir, { recursive: true });
|
|
161
|
+
// Create skill WITHOUT name field
|
|
162
|
+
const skillContent = `---
|
|
163
|
+
description: Skill without explicit name
|
|
164
|
+
---
|
|
165
|
+
|
|
166
|
+
This skill has no name field.
|
|
167
|
+
`;
|
|
168
|
+
writeFileSync(join(projectSkillsDir, 'unnamed-skill.md'), skillContent);
|
|
169
|
+
const commands = discoverAllCommands();
|
|
170
|
+
const skill = commands.find(cmd => cmd.name === 'unnamed-skill');
|
|
171
|
+
expect(skill).toBeDefined();
|
|
172
|
+
expect(skill?.metadata.name).toBe('unnamed-skill'); // Should use filename
|
|
173
|
+
expect(skill?.metadata.description).toBe('Skill without explicit name');
|
|
174
|
+
});
|
|
175
|
+
it('should find learned skill by name via findCommand()', () => {
|
|
176
|
+
const projectSkillsDir = join(testProjectRoot, '.omc', 'skills');
|
|
177
|
+
mkdirSync(projectSkillsDir, { recursive: true });
|
|
178
|
+
const skillContent = `---
|
|
179
|
+
name: findable-skill
|
|
180
|
+
description: A skill that can be found
|
|
181
|
+
---
|
|
182
|
+
|
|
183
|
+
This skill should be findable.
|
|
184
|
+
`;
|
|
185
|
+
writeFileSync(join(projectSkillsDir, 'findable-skill.md'), skillContent);
|
|
186
|
+
// Use findCommand to locate it
|
|
187
|
+
const found = findCommand('findable-skill');
|
|
188
|
+
expect(found).not.toBeNull();
|
|
189
|
+
expect(found?.name).toBe('findable-skill');
|
|
190
|
+
expect(found?.scope).toBe('project-skill');
|
|
191
|
+
expect(found?.metadata.description).toBe('A skill that can be found');
|
|
192
|
+
});
|
|
193
|
+
it('should execute learned skill slash command correctly', () => {
|
|
194
|
+
const projectSkillsDir = join(testProjectRoot, '.omc', 'skills');
|
|
195
|
+
mkdirSync(projectSkillsDir, { recursive: true });
|
|
196
|
+
const skillContent = `---
|
|
197
|
+
name: executable-skill
|
|
198
|
+
description: An executable skill
|
|
199
|
+
model: sonnet
|
|
200
|
+
agent: executor
|
|
201
|
+
---
|
|
202
|
+
|
|
203
|
+
Execute the following task:
|
|
204
|
+
|
|
205
|
+
$ARGUMENTS
|
|
206
|
+
|
|
207
|
+
Please proceed with care.
|
|
208
|
+
`;
|
|
209
|
+
writeFileSync(join(projectSkillsDir, 'executable-skill.md'), skillContent);
|
|
210
|
+
// Simulate slash command execution
|
|
211
|
+
const parsed = {
|
|
212
|
+
command: 'executable-skill',
|
|
213
|
+
args: 'implement feature X',
|
|
214
|
+
raw: '/executable-skill implement feature X',
|
|
215
|
+
};
|
|
216
|
+
const result = executeSlashCommand(parsed);
|
|
217
|
+
expect(result.success).toBe(true);
|
|
218
|
+
expect(result.replacementText).toBeDefined();
|
|
219
|
+
expect(result.replacementText).toContain('executable-skill');
|
|
220
|
+
expect(result.replacementText).toContain('An executable skill');
|
|
221
|
+
expect(result.replacementText).toContain('**Model**: sonnet');
|
|
222
|
+
expect(result.replacementText).toContain('**Agent**: executor');
|
|
223
|
+
expect(result.replacementText).toContain('**Scope**: project-skill');
|
|
224
|
+
expect(result.replacementText).toContain('implement feature X');
|
|
225
|
+
expect(result.replacementText).toContain('Execute the following task:');
|
|
226
|
+
});
|
|
227
|
+
it('should handle $ARGUMENTS placeholder replacement', () => {
|
|
228
|
+
const projectSkillsDir = join(testProjectRoot, '.omc', 'skills');
|
|
229
|
+
mkdirSync(projectSkillsDir, { recursive: true });
|
|
230
|
+
const skillContent = `---
|
|
231
|
+
name: args-test
|
|
232
|
+
description: Test argument replacement
|
|
233
|
+
---
|
|
234
|
+
|
|
235
|
+
Task: $ARGUMENTS
|
|
236
|
+
Context: Processing $ARGUMENTS
|
|
237
|
+
Result: Completed $ARGUMENTS
|
|
238
|
+
`;
|
|
239
|
+
writeFileSync(join(projectSkillsDir, 'args-test.md'), skillContent);
|
|
240
|
+
const parsed = {
|
|
241
|
+
command: 'args-test',
|
|
242
|
+
args: 'build authentication system',
|
|
243
|
+
raw: '/args-test build authentication system',
|
|
244
|
+
};
|
|
245
|
+
const result = executeSlashCommand(parsed);
|
|
246
|
+
expect(result.success).toBe(true);
|
|
247
|
+
expect(result.replacementText).toContain('Task: build authentication system');
|
|
248
|
+
expect(result.replacementText).toContain('Context: Processing build authentication system');
|
|
249
|
+
expect(result.replacementText).toContain('Result: Completed build authentication system');
|
|
250
|
+
});
|
|
251
|
+
it('should handle skills without $ARGUMENTS placeholder', () => {
|
|
252
|
+
const projectSkillsDir = join(testProjectRoot, '.omc', 'skills');
|
|
253
|
+
mkdirSync(projectSkillsDir, { recursive: true });
|
|
254
|
+
const skillContent = `---
|
|
255
|
+
name: no-args-placeholder
|
|
256
|
+
description: Skill without placeholder
|
|
257
|
+
---
|
|
258
|
+
|
|
259
|
+
This is a static template.
|
|
260
|
+
It does not use argument placeholders.
|
|
261
|
+
`;
|
|
262
|
+
writeFileSync(join(projectSkillsDir, 'no-args-placeholder.md'), skillContent);
|
|
263
|
+
const parsed = {
|
|
264
|
+
command: 'no-args-placeholder',
|
|
265
|
+
args: 'some user input',
|
|
266
|
+
raw: '/no-args-placeholder some user input',
|
|
267
|
+
};
|
|
268
|
+
const result = executeSlashCommand(parsed);
|
|
269
|
+
expect(result.success).toBe(true);
|
|
270
|
+
// Should append user request section when no $ARGUMENTS found
|
|
271
|
+
expect(result.replacementText).toContain('This is a static template');
|
|
272
|
+
expect(result.replacementText).toContain('## User Request');
|
|
273
|
+
expect(result.replacementText).toContain('some user input');
|
|
274
|
+
});
|
|
275
|
+
it('should return error for non-existent skill', () => {
|
|
276
|
+
const parsed = {
|
|
277
|
+
command: 'non-existent-skill',
|
|
278
|
+
args: 'test',
|
|
279
|
+
raw: '/non-existent-skill test',
|
|
280
|
+
};
|
|
281
|
+
const result = executeSlashCommand(parsed);
|
|
282
|
+
expect(result.success).toBe(false);
|
|
283
|
+
expect(result.error).toBeDefined();
|
|
284
|
+
expect(result.error).toContain('not found');
|
|
285
|
+
});
|
|
286
|
+
it('should handle empty arguments gracefully', () => {
|
|
287
|
+
const projectSkillsDir = join(testProjectRoot, '.omc', 'skills');
|
|
288
|
+
mkdirSync(projectSkillsDir, { recursive: true });
|
|
289
|
+
const skillContent = `---
|
|
290
|
+
name: empty-args-skill
|
|
291
|
+
description: Test empty arguments
|
|
292
|
+
---
|
|
293
|
+
|
|
294
|
+
Arguments: $ARGUMENTS
|
|
295
|
+
`;
|
|
296
|
+
writeFileSync(join(projectSkillsDir, 'empty-args-skill.md'), skillContent);
|
|
297
|
+
const parsed = {
|
|
298
|
+
command: 'empty-args-skill',
|
|
299
|
+
args: '',
|
|
300
|
+
raw: '/empty-args-skill',
|
|
301
|
+
};
|
|
302
|
+
const result = executeSlashCommand(parsed);
|
|
303
|
+
expect(result.success).toBe(true);
|
|
304
|
+
expect(result.replacementText).toContain('Arguments: (no arguments provided)');
|
|
305
|
+
});
|
|
306
|
+
it('should discover multiple skills from same directory', () => {
|
|
307
|
+
const projectSkillsDir = join(testProjectRoot, '.omc', 'skills');
|
|
308
|
+
mkdirSync(projectSkillsDir, { recursive: true });
|
|
309
|
+
// Create multiple skills
|
|
310
|
+
for (let i = 1; i <= 3; i++) {
|
|
311
|
+
const skillContent = `---
|
|
312
|
+
name: multi-skill-${i}
|
|
313
|
+
description: Skill number ${i}
|
|
314
|
+
---
|
|
315
|
+
|
|
316
|
+
Template ${i}
|
|
317
|
+
`;
|
|
318
|
+
writeFileSync(join(projectSkillsDir, `multi-skill-${i}.md`), skillContent);
|
|
319
|
+
}
|
|
320
|
+
const commands = discoverAllCommands();
|
|
321
|
+
const multiSkills = commands.filter(cmd => cmd.name.startsWith('multi-skill-'));
|
|
322
|
+
expect(multiSkills.length).toBe(3);
|
|
323
|
+
expect(multiSkills.every(s => s.scope === 'project-skill')).toBe(true);
|
|
324
|
+
});
|
|
325
|
+
it('should ignore non-.md files in skills directory', () => {
|
|
326
|
+
const projectSkillsDir = join(testProjectRoot, '.omc', 'skills');
|
|
327
|
+
mkdirSync(projectSkillsDir, { recursive: true });
|
|
328
|
+
// Create .md file
|
|
329
|
+
writeFileSync(join(projectSkillsDir, 'valid-skill.md'), '---\nname: valid\n---\nContent');
|
|
330
|
+
// Create non-.md files
|
|
331
|
+
writeFileSync(join(projectSkillsDir, 'invalid.txt'), 'Should be ignored');
|
|
332
|
+
writeFileSync(join(projectSkillsDir, 'README'), 'Should be ignored');
|
|
333
|
+
const commands = discoverAllCommands();
|
|
334
|
+
const projectSkills = commands.filter(cmd => cmd.scope === 'project-skill');
|
|
335
|
+
expect(projectSkills.length).toBe(1);
|
|
336
|
+
expect(projectSkills[0].name).toBe('valid-skill');
|
|
337
|
+
});
|
|
338
|
+
it('should handle malformed frontmatter gracefully', () => {
|
|
339
|
+
const projectSkillsDir = join(testProjectRoot, '.omc', 'skills');
|
|
340
|
+
mkdirSync(projectSkillsDir, { recursive: true });
|
|
341
|
+
// Create skill with malformed frontmatter
|
|
342
|
+
const malformedContent = `---
|
|
343
|
+
this is not valid yaml
|
|
344
|
+
no colons here
|
|
345
|
+
---
|
|
346
|
+
|
|
347
|
+
Body content
|
|
348
|
+
`;
|
|
349
|
+
writeFileSync(join(projectSkillsDir, 'malformed.md'), malformedContent);
|
|
350
|
+
// Should not throw, just skip the malformed file
|
|
351
|
+
const commands = discoverAllCommands();
|
|
352
|
+
const malformed = commands.find(cmd => cmd.name === 'malformed');
|
|
353
|
+
// Should still parse (frontmatter parsing is lenient)
|
|
354
|
+
// It will have empty metadata but valid name from filename
|
|
355
|
+
expect(malformed?.metadata.name).toBe('malformed');
|
|
356
|
+
});
|
|
357
|
+
it('should handle skills without frontmatter', () => {
|
|
358
|
+
const projectSkillsDir = join(testProjectRoot, '.omc', 'skills');
|
|
359
|
+
mkdirSync(projectSkillsDir, { recursive: true });
|
|
360
|
+
// Create skill without frontmatter
|
|
361
|
+
const noFrontmatter = `This is just plain markdown content.
|
|
362
|
+
|
|
363
|
+
No frontmatter at all.
|
|
364
|
+
`;
|
|
365
|
+
writeFileSync(join(projectSkillsDir, 'no-frontmatter.md'), noFrontmatter);
|
|
366
|
+
const commands = discoverAllCommands();
|
|
367
|
+
const skill = commands.find(cmd => cmd.name === 'no-frontmatter');
|
|
368
|
+
expect(skill).toBeDefined();
|
|
369
|
+
expect(skill?.metadata.name).toBe('no-frontmatter');
|
|
370
|
+
expect(skill?.metadata.description).toBe(''); // Empty string for missing description
|
|
371
|
+
expect(skill?.content).toContain('This is just plain markdown content');
|
|
372
|
+
});
|
|
373
|
+
});
|
|
374
|
+
//# sourceMappingURL=executor.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"executor.test.js","sourceRoot":"","sources":["../../../../src/__tests__/hooks/auto-slash-command/executor.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Integration tests for Skill Bridge Module
|
|
3
|
+
*
|
|
4
|
+
* Tests the bridge API used by skill-injector.mjs for:
|
|
5
|
+
* - Skill file discovery (recursive)
|
|
6
|
+
* - YAML frontmatter parsing
|
|
7
|
+
* - Trigger-based matching
|
|
8
|
+
* - Session cache persistence
|
|
9
|
+
*/
|
|
10
|
+
export {};
|
|
11
|
+
//# sourceMappingURL=bridge.test.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bridge.test.d.ts","sourceRoot":"","sources":["../../../../src/__tests__/hooks/learner/bridge.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG"}
|
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Integration tests for Skill Bridge Module
|
|
3
|
+
*
|
|
4
|
+
* Tests the bridge API used by skill-injector.mjs for:
|
|
5
|
+
* - Skill file discovery (recursive)
|
|
6
|
+
* - YAML frontmatter parsing
|
|
7
|
+
* - Trigger-based matching
|
|
8
|
+
* - Session cache persistence
|
|
9
|
+
*/
|
|
10
|
+
import { describe, it, expect, beforeEach, afterEach } from 'vitest';
|
|
11
|
+
import { mkdirSync, writeFileSync, rmSync, existsSync, readFileSync } from 'fs';
|
|
12
|
+
import { join } from 'path';
|
|
13
|
+
import { tmpdir } from 'os';
|
|
14
|
+
import { findSkillFiles, parseSkillFile, matchSkillsForInjection, getInjectedSkillPaths, markSkillsInjected, } from '../../../hooks/learner/bridge.js';
|
|
15
|
+
describe('Skill Bridge Module', () => {
|
|
16
|
+
let testProjectRoot;
|
|
17
|
+
let originalCwd;
|
|
18
|
+
beforeEach(() => {
|
|
19
|
+
originalCwd = process.cwd();
|
|
20
|
+
testProjectRoot = join(tmpdir(), `omc-bridge-test-${Date.now()}`);
|
|
21
|
+
mkdirSync(testProjectRoot, { recursive: true });
|
|
22
|
+
process.chdir(testProjectRoot);
|
|
23
|
+
});
|
|
24
|
+
afterEach(() => {
|
|
25
|
+
process.chdir(originalCwd);
|
|
26
|
+
if (existsSync(testProjectRoot)) {
|
|
27
|
+
rmSync(testProjectRoot, { recursive: true, force: true });
|
|
28
|
+
}
|
|
29
|
+
});
|
|
30
|
+
describe('findSkillFiles', () => {
|
|
31
|
+
it('should discover skills in project .omc/skills/', () => {
|
|
32
|
+
const skillsDir = join(testProjectRoot, '.omc', 'skills');
|
|
33
|
+
mkdirSync(skillsDir, { recursive: true });
|
|
34
|
+
writeFileSync(join(skillsDir, 'test-skill.md'), '---\nname: Test Skill\ntriggers:\n - test\n---\nContent');
|
|
35
|
+
const files = findSkillFiles(testProjectRoot);
|
|
36
|
+
expect(files).toHaveLength(1);
|
|
37
|
+
expect(files[0].scope).toBe('project');
|
|
38
|
+
expect(files[0].path).toContain('test-skill.md');
|
|
39
|
+
});
|
|
40
|
+
it('should discover skills recursively in subdirectories', () => {
|
|
41
|
+
const skillsDir = join(testProjectRoot, '.omc', 'skills');
|
|
42
|
+
const subDir = join(skillsDir, 'subdir', 'nested');
|
|
43
|
+
mkdirSync(subDir, { recursive: true });
|
|
44
|
+
writeFileSync(join(skillsDir, 'root-skill.md'), '---\nname: Root\ntriggers:\n - root\n---\nRoot content');
|
|
45
|
+
writeFileSync(join(subDir, 'nested-skill.md'), '---\nname: Nested\ntriggers:\n - nested\n---\nNested content');
|
|
46
|
+
const files = findSkillFiles(testProjectRoot);
|
|
47
|
+
expect(files).toHaveLength(2);
|
|
48
|
+
const names = files.map((f) => f.path);
|
|
49
|
+
expect(names.some((n) => n.includes('root-skill.md'))).toBe(true);
|
|
50
|
+
expect(names.some((n) => n.includes('nested-skill.md'))).toBe(true);
|
|
51
|
+
});
|
|
52
|
+
it('should ignore non-.md files', () => {
|
|
53
|
+
const skillsDir = join(testProjectRoot, '.omc', 'skills');
|
|
54
|
+
mkdirSync(skillsDir, { recursive: true });
|
|
55
|
+
writeFileSync(join(skillsDir, 'valid.md'), '---\nname: Valid\n---\nContent');
|
|
56
|
+
writeFileSync(join(skillsDir, 'invalid.txt'), 'Not a skill');
|
|
57
|
+
writeFileSync(join(skillsDir, 'README'), 'Documentation');
|
|
58
|
+
const files = findSkillFiles(testProjectRoot);
|
|
59
|
+
expect(files).toHaveLength(1);
|
|
60
|
+
expect(files[0].path).toContain('valid.md');
|
|
61
|
+
});
|
|
62
|
+
});
|
|
63
|
+
describe('parseSkillFile', () => {
|
|
64
|
+
it('should parse valid frontmatter with all fields', () => {
|
|
65
|
+
const content = `---
|
|
66
|
+
name: Comprehensive Skill
|
|
67
|
+
description: A test skill
|
|
68
|
+
triggers:
|
|
69
|
+
- trigger1
|
|
70
|
+
- trigger2
|
|
71
|
+
tags:
|
|
72
|
+
- tag1
|
|
73
|
+
matching: fuzzy
|
|
74
|
+
model: opus
|
|
75
|
+
agent: architect
|
|
76
|
+
---
|
|
77
|
+
|
|
78
|
+
# Skill Content
|
|
79
|
+
|
|
80
|
+
This is the skill body.`;
|
|
81
|
+
const result = parseSkillFile(content);
|
|
82
|
+
expect(result).not.toBeNull();
|
|
83
|
+
expect(result?.valid).toBe(true);
|
|
84
|
+
expect(result?.metadata.name).toBe('Comprehensive Skill');
|
|
85
|
+
expect(result?.metadata.description).toBe('A test skill');
|
|
86
|
+
expect(result?.metadata.triggers).toEqual(['trigger1', 'trigger2']);
|
|
87
|
+
expect(result?.metadata.tags).toEqual(['tag1']);
|
|
88
|
+
expect(result?.metadata.matching).toBe('fuzzy');
|
|
89
|
+
expect(result?.metadata.model).toBe('opus');
|
|
90
|
+
expect(result?.metadata.agent).toBe('architect');
|
|
91
|
+
expect(result?.content).toContain('# Skill Content');
|
|
92
|
+
});
|
|
93
|
+
it('should handle files without frontmatter', () => {
|
|
94
|
+
const content = `This is just plain content without frontmatter.`;
|
|
95
|
+
const result = parseSkillFile(content);
|
|
96
|
+
expect(result).not.toBeNull();
|
|
97
|
+
expect(result?.valid).toBe(true);
|
|
98
|
+
expect(result?.content).toBe(content);
|
|
99
|
+
});
|
|
100
|
+
it('should parse inline array syntax', () => {
|
|
101
|
+
const content = `---
|
|
102
|
+
name: Inline Triggers
|
|
103
|
+
triggers: ["alpha", "beta", "gamma"]
|
|
104
|
+
---
|
|
105
|
+
Content`;
|
|
106
|
+
const result = parseSkillFile(content);
|
|
107
|
+
expect(result?.metadata.triggers).toEqual(['alpha', 'beta', 'gamma']);
|
|
108
|
+
});
|
|
109
|
+
});
|
|
110
|
+
describe('matchSkillsForInjection', () => {
|
|
111
|
+
it('should match skills by trigger substring', () => {
|
|
112
|
+
const skillsDir = join(testProjectRoot, '.omc', 'skills');
|
|
113
|
+
mkdirSync(skillsDir, { recursive: true });
|
|
114
|
+
writeFileSync(join(skillsDir, 'deploy-skill.md'), '---\nname: Deploy Skill\ntriggers:\n - deploy\n - deployment\n---\nDeployment instructions');
|
|
115
|
+
const matches = matchSkillsForInjection('I need to deploy the application', testProjectRoot, 'test-session');
|
|
116
|
+
expect(matches).toHaveLength(1);
|
|
117
|
+
expect(matches[0].name).toBe('Deploy Skill');
|
|
118
|
+
expect(matches[0].score).toBeGreaterThan(0);
|
|
119
|
+
});
|
|
120
|
+
it('should not match when triggers dont match', () => {
|
|
121
|
+
const skillsDir = join(testProjectRoot, '.omc', 'skills');
|
|
122
|
+
mkdirSync(skillsDir, { recursive: true });
|
|
123
|
+
writeFileSync(join(skillsDir, 'database-skill.md'), '---\nname: Database\ntriggers:\n - database\n - sql\n---\nDB instructions');
|
|
124
|
+
const matches = matchSkillsForInjection('Help me with React components', testProjectRoot, 'test-session');
|
|
125
|
+
expect(matches).toHaveLength(0);
|
|
126
|
+
});
|
|
127
|
+
it('should use fuzzy matching when opt-in', () => {
|
|
128
|
+
const skillsDir = join(testProjectRoot, '.omc', 'skills');
|
|
129
|
+
mkdirSync(skillsDir, { recursive: true });
|
|
130
|
+
// Skill with fuzzy matching enabled
|
|
131
|
+
writeFileSync(join(skillsDir, 'fuzzy-skill.md'), '---\nname: Fuzzy Skill\nmatching: fuzzy\ntriggers:\n - deployment\n---\nFuzzy content');
|
|
132
|
+
// "deploy" is similar to "deployment" - should match with fuzzy
|
|
133
|
+
const matches = matchSkillsForInjection('I need to deploy', testProjectRoot, 'test-session-fuzzy');
|
|
134
|
+
// Note: exact substring "deploy" is in "deployment", so it matches anyway
|
|
135
|
+
// To truly test fuzzy, we'd need a trigger that's close but not substring
|
|
136
|
+
expect(matches.length).toBeGreaterThanOrEqual(0);
|
|
137
|
+
});
|
|
138
|
+
it('should respect skill limit', () => {
|
|
139
|
+
const skillsDir = join(testProjectRoot, '.omc', 'skills');
|
|
140
|
+
mkdirSync(skillsDir, { recursive: true });
|
|
141
|
+
// Create 10 skills that all match "test"
|
|
142
|
+
for (let i = 0; i < 10; i++) {
|
|
143
|
+
writeFileSync(join(skillsDir, `skill-${i}.md`), `---\nname: Skill ${i}\ntriggers:\n - test\n---\nContent ${i}`);
|
|
144
|
+
}
|
|
145
|
+
const matches = matchSkillsForInjection('run the test', testProjectRoot, 'limit-session', {
|
|
146
|
+
maxResults: 3,
|
|
147
|
+
});
|
|
148
|
+
expect(matches).toHaveLength(3);
|
|
149
|
+
});
|
|
150
|
+
});
|
|
151
|
+
describe('Session Cache', () => {
|
|
152
|
+
it('should track injected skills via file-based cache', () => {
|
|
153
|
+
markSkillsInjected('session-1', ['/path/to/skill1.md', '/path/to/skill2.md'], testProjectRoot);
|
|
154
|
+
const injected = getInjectedSkillPaths('session-1', testProjectRoot);
|
|
155
|
+
expect(injected).toContain('/path/to/skill1.md');
|
|
156
|
+
expect(injected).toContain('/path/to/skill2.md');
|
|
157
|
+
});
|
|
158
|
+
it('should not return skills for different session', () => {
|
|
159
|
+
markSkillsInjected('session-A', ['/path/to/skillA.md'], testProjectRoot);
|
|
160
|
+
const injected = getInjectedSkillPaths('session-B', testProjectRoot);
|
|
161
|
+
expect(injected).toHaveLength(0);
|
|
162
|
+
});
|
|
163
|
+
it('should persist state to file', () => {
|
|
164
|
+
markSkillsInjected('persist-test', ['/path/to/persist.md'], testProjectRoot);
|
|
165
|
+
const stateFile = join(testProjectRoot, '.omc', 'state', 'skill-sessions.json');
|
|
166
|
+
expect(existsSync(stateFile)).toBe(true);
|
|
167
|
+
const state = JSON.parse(readFileSync(stateFile, 'utf-8'));
|
|
168
|
+
expect(state.sessions['persist-test']).toBeDefined();
|
|
169
|
+
expect(state.sessions['persist-test'].injectedPaths).toContain('/path/to/persist.md');
|
|
170
|
+
});
|
|
171
|
+
it('should not re-inject already injected skills', () => {
|
|
172
|
+
const skillsDir = join(testProjectRoot, '.omc', 'skills');
|
|
173
|
+
mkdirSync(skillsDir, { recursive: true });
|
|
174
|
+
writeFileSync(join(skillsDir, 'once-skill.md'), '---\nname: Once Only\ntriggers:\n - once\n---\nOnce content');
|
|
175
|
+
// First match
|
|
176
|
+
const first = matchSkillsForInjection('test once', testProjectRoot, 'cache-session');
|
|
177
|
+
expect(first).toHaveLength(1);
|
|
178
|
+
// Mark as injected
|
|
179
|
+
markSkillsInjected('cache-session', [first[0].path], testProjectRoot);
|
|
180
|
+
// Second match - should be empty
|
|
181
|
+
const second = matchSkillsForInjection('test once again', testProjectRoot, 'cache-session');
|
|
182
|
+
expect(second).toHaveLength(0);
|
|
183
|
+
});
|
|
184
|
+
});
|
|
185
|
+
describe('Priority', () => {
|
|
186
|
+
it('should return project skills before user skills', () => {
|
|
187
|
+
// We can't easily test user skills dir in isolation, but we can verify
|
|
188
|
+
// that project skills come first in the returned array
|
|
189
|
+
const skillsDir = join(testProjectRoot, '.omc', 'skills');
|
|
190
|
+
mkdirSync(skillsDir, { recursive: true });
|
|
191
|
+
writeFileSync(join(skillsDir, 'project-skill.md'), '---\nname: Project Skill\ntriggers:\n - priority\n---\nProject content');
|
|
192
|
+
const files = findSkillFiles(testProjectRoot);
|
|
193
|
+
const projectSkills = files.filter((f) => f.scope === 'project');
|
|
194
|
+
expect(projectSkills.length).toBeGreaterThan(0);
|
|
195
|
+
expect(projectSkills[0].scope).toBe('project');
|
|
196
|
+
});
|
|
197
|
+
});
|
|
198
|
+
});
|
|
199
|
+
//# sourceMappingURL=bridge.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bridge.test.js","sourceRoot":"","sources":["../../../../src/__tests__/hooks/learner/bridge.test.ts"],"names":[],"mappings":"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"}
|