claudecode-omc 5.3.0 → 5.5.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 (91) hide show
  1. package/.local/guidelines/CLAUDE.md +31 -0
  2. package/README.md +57 -1
  3. package/bundled/manifest.json +2 -2
  4. package/bundled/upstream/oh-my-claudecode/agents/analyst.md +1 -1
  5. package/bundled/upstream/oh-my-claudecode/agents/architect.md +1 -1
  6. package/bundled/upstream/oh-my-claudecode/agents/code-reviewer.md +1 -1
  7. package/bundled/upstream/oh-my-claudecode/agents/code-simplifier.md +1 -1
  8. package/bundled/upstream/oh-my-claudecode/agents/critic.md +1 -1
  9. package/bundled/upstream/oh-my-claudecode/agents/debugger.md +1 -1
  10. package/bundled/upstream/oh-my-claudecode/agents/designer.md +1 -1
  11. package/bundled/upstream/oh-my-claudecode/agents/document-specialist.md +1 -1
  12. package/bundled/upstream/oh-my-claudecode/agents/executor.md +1 -1
  13. package/bundled/upstream/oh-my-claudecode/agents/explore.md +1 -1
  14. package/bundled/upstream/oh-my-claudecode/agents/git-master.md +3 -3
  15. package/bundled/upstream/oh-my-claudecode/agents/planner.md +1 -1
  16. package/bundled/upstream/oh-my-claudecode/agents/qa-tester.md +1 -1
  17. package/bundled/upstream/oh-my-claudecode/agents/scientist.md +1 -1
  18. package/bundled/upstream/oh-my-claudecode/agents/security-reviewer.md +1 -1
  19. package/bundled/upstream/oh-my-claudecode/agents/test-engineer.md +1 -75
  20. package/bundled/upstream/oh-my-claudecode/agents/tracer.md +1 -1
  21. package/bundled/upstream/oh-my-claudecode/agents/verifier.md +1 -1
  22. package/bundled/upstream/oh-my-claudecode/agents/writer.md +1 -1
  23. package/bundled/upstream/oh-my-claudecode/hooks/hooks.json +21 -1
  24. package/bundled/upstream/oh-my-claudecode/skills/AGENTS.md +200 -0
  25. package/bundled/upstream/oh-my-claudecode/skills/autopilot/SKILL.md +17 -10
  26. package/bundled/upstream/oh-my-claudecode/skills/autoresearch/SKILL.md +90 -0
  27. package/bundled/upstream/oh-my-claudecode/skills/cancel/SKILL.md +15 -6
  28. package/bundled/upstream/oh-my-claudecode/skills/configure-notifications/SKILL.md +12 -12
  29. package/bundled/upstream/oh-my-claudecode/skills/debug/SKILL.md +35 -0
  30. package/bundled/upstream/oh-my-claudecode/skills/deep-dive/SKILL.md +4 -0
  31. package/bundled/upstream/oh-my-claudecode/skills/deep-interview/SKILL.md +23 -18
  32. package/bundled/upstream/oh-my-claudecode/skills/hud/SKILL.md +23 -101
  33. package/bundled/upstream/oh-my-claudecode/skills/learner/SKILL.md +27 -2
  34. package/bundled/upstream/oh-my-claudecode/skills/mcp-setup/SKILL.md +67 -8
  35. package/bundled/upstream/oh-my-claudecode/skills/omc-doctor/SKILL.md +32 -47
  36. package/bundled/upstream/oh-my-claudecode/skills/omc-setup/SKILL.md +4 -2
  37. package/bundled/upstream/oh-my-claudecode/skills/omc-setup/phases/01-install-claude-md.md +15 -4
  38. package/bundled/upstream/oh-my-claudecode/skills/omc-setup/phases/02-configure.md +9 -9
  39. package/bundled/upstream/oh-my-claudecode/skills/omc-setup/phases/03-integrations.md +13 -13
  40. package/bundled/upstream/oh-my-claudecode/skills/omc-setup/phases/04-welcome.md +3 -3
  41. package/bundled/upstream/oh-my-claudecode/skills/omc-teams/SKILL.md +28 -0
  42. package/bundled/upstream/oh-my-claudecode/skills/plan/SKILL.md +1 -0
  43. package/bundled/upstream/oh-my-claudecode/skills/project-session-manager/SKILL.md +25 -5
  44. package/bundled/upstream/oh-my-claudecode/skills/project-session-manager/lib/config.sh +2 -15
  45. package/bundled/upstream/oh-my-claudecode/skills/project-session-manager/lib/providers/github.sh +1 -1
  46. package/bundled/upstream/oh-my-claudecode/skills/project-session-manager/lib/session.sh +2 -2
  47. package/bundled/upstream/oh-my-claudecode/skills/project-session-manager/lib/tmux.sh +109 -4
  48. package/bundled/upstream/oh-my-claudecode/skills/project-session-manager/lib/worktree.sh +26 -0
  49. package/bundled/upstream/oh-my-claudecode/skills/project-session-manager/psm.sh +46 -5
  50. package/bundled/upstream/oh-my-claudecode/skills/project-session-manager/templates/pr-review.md +5 -2
  51. package/bundled/upstream/oh-my-claudecode/skills/project-session-manager/templates/projects.json +1 -1
  52. package/bundled/upstream/oh-my-claudecode/skills/project-session-manager/tests/test-psm-prompt-injection.sh +336 -0
  53. package/bundled/upstream/oh-my-claudecode/skills/ralph/SKILL.md +18 -9
  54. package/bundled/upstream/oh-my-claudecode/skills/ralplan/SKILL.md +2 -0
  55. package/bundled/upstream/oh-my-claudecode/skills/release/SKILL.md +167 -57
  56. package/bundled/upstream/oh-my-claudecode/skills/remember/SKILL.md +41 -0
  57. package/bundled/upstream/oh-my-claudecode/skills/self-improve/SKILL.md +391 -0
  58. package/bundled/upstream/oh-my-claudecode/skills/self-improve/data_contracts.md +274 -0
  59. package/bundled/upstream/oh-my-claudecode/skills/self-improve/scripts/plot_progress.py +128 -0
  60. package/bundled/upstream/oh-my-claudecode/skills/self-improve/scripts/resolve-paths.mjs +192 -0
  61. package/bundled/upstream/oh-my-claudecode/skills/self-improve/scripts/validate.sh +404 -0
  62. package/bundled/upstream/oh-my-claudecode/skills/self-improve/si-benchmark-builder.md +79 -0
  63. package/bundled/upstream/oh-my-claudecode/skills/self-improve/si-goal-clarifier.md +94 -0
  64. package/bundled/upstream/oh-my-claudecode/skills/self-improve/si-researcher.md +73 -0
  65. package/bundled/upstream/oh-my-claudecode/skills/self-improve/templates/agent-settings.json +14 -0
  66. package/bundled/upstream/oh-my-claudecode/skills/self-improve/templates/goal.md +22 -0
  67. package/bundled/upstream/oh-my-claudecode/skills/self-improve/templates/harness.md +18 -0
  68. package/bundled/upstream/oh-my-claudecode/skills/self-improve/templates/idea.md +5 -0
  69. package/bundled/upstream/oh-my-claudecode/skills/self-improve/templates/settings.json +23 -0
  70. package/bundled/upstream/oh-my-claudecode/skills/skill/SKILL.md +46 -77
  71. package/bundled/upstream/oh-my-claudecode/skills/skillify/SKILL.md +53 -0
  72. package/bundled/upstream/oh-my-claudecode/skills/team/SKILL.md +83 -11
  73. package/bundled/upstream/oh-my-claudecode/skills/trace/SKILL.md +1 -0
  74. package/bundled/upstream/oh-my-claudecode/skills/ultraqa/SKILL.md +1 -0
  75. package/bundled/upstream/oh-my-claudecode/skills/ultrawork/SKILL.md +1 -0
  76. package/bundled/upstream/oh-my-claudecode/skills/verify/SKILL.md +37 -0
  77. package/bundled/upstream/oh-my-claudecode/skills/wiki/SKILL.md +67 -0
  78. package/package.json +3 -1
  79. package/src/cli/artifact.js +63 -2
  80. package/src/cli/guidelines.js +83 -0
  81. package/src/cli/index.js +13 -1
  82. package/src/cli/setup.js +48 -18
  83. package/src/cli/source.js +35 -1
  84. package/src/config/artifact-types.js +12 -2
  85. package/src/config/paths.js +95 -4
  86. package/src/config/sources.js +29 -5
  87. package/src/guidelines/apply.js +152 -0
  88. package/src/guidelines/optimizer.js +325 -0
  89. package/src/merge/claude-md-merger.js +35 -12
  90. package/templates/merge-config.json +12 -1
  91. package/bundled/upstream/oh-my-claudecode/skills/omc-doctor/skill-debugger.md +0 -101
@@ -0,0 +1,152 @@
1
+ const fs = require('fs');
2
+ const fsp = require('fs/promises');
3
+ const path = require('path');
4
+ const { getProjectRoot } = require('../config/paths');
5
+ const { sha256 } = require('./optimizer');
6
+
7
+ function assert(condition, message) {
8
+ if (!condition) {
9
+ throw new Error(message);
10
+ }
11
+ }
12
+
13
+ function readJson(filePath) {
14
+ return JSON.parse(fs.readFileSync(filePath, 'utf8'));
15
+ }
16
+
17
+ async function ensureDir(dirPath) {
18
+ await fsp.mkdir(dirPath, { recursive: true });
19
+ }
20
+
21
+ async function writeJson(filePath, value) {
22
+ await ensureDir(path.dirname(filePath));
23
+ await fsp.writeFile(filePath, JSON.stringify(value, null, 2) + '\n', 'utf8');
24
+ }
25
+
26
+ async function writeText(filePath, value) {
27
+ await ensureDir(path.dirname(filePath));
28
+ await fsp.writeFile(filePath, value, 'utf8');
29
+ }
30
+
31
+ function validateResult(result) {
32
+ assert(result && typeof result === 'object', 'Result file must contain a JSON object.');
33
+ assert(result.version === 1, 'Result file must set "version": 1.');
34
+ assert(typeof result.generatedBy === 'string' && result.generatedBy.trim(), 'Result file must include generatedBy.');
35
+ assert(typeof result.summary === 'string' && result.summary.trim(), 'Result file must include summary.');
36
+ assert(
37
+ typeof result.runtimeGuidelinesMarkdown === 'string' &&
38
+ result.runtimeGuidelinesMarkdown.trim().startsWith('# '),
39
+ 'runtimeGuidelinesMarkdown must be markdown starting with a top-level heading.'
40
+ );
41
+ assert(Array.isArray(result.decisions), 'Result file must include a decisions array.');
42
+ assert(Array.isArray(result.conflicts), 'Result file must include a conflicts array.');
43
+
44
+ for (const [index, decision] of result.decisions.entries()) {
45
+ assert(typeof decision === 'object' && decision, `decisions[${index}] must be an object.`);
46
+ assert(typeof decision.action === 'string' && decision.action.trim(), `decisions[${index}].action is required.`);
47
+ assert(Array.isArray(decision.sourceSectionIds), `decisions[${index}].sourceSectionIds must be an array.`);
48
+ assert(typeof decision.title === 'string' && decision.title.trim(), `decisions[${index}].title is required.`);
49
+ assert(typeof decision.rationale === 'string' && decision.rationale.trim(), `decisions[${index}].rationale is required.`);
50
+ }
51
+
52
+ for (const [index, conflict] of result.conflicts.entries()) {
53
+ assert(typeof conflict === 'object' && conflict, `conflicts[${index}] must be an object.`);
54
+ assert(Array.isArray(conflict.sourceSectionIds), `conflicts[${index}].sourceSectionIds must be an array.`);
55
+ assert(typeof conflict.resolution === 'string' && conflict.resolution.trim(), `conflicts[${index}].resolution is required.`);
56
+ }
57
+ }
58
+
59
+ function buildDecisionLog(result) {
60
+ const lines = [
61
+ '# Guideline Optimization Decision Log',
62
+ '',
63
+ `Generated by: ${result.generatedBy}`,
64
+ '',
65
+ `Summary: ${result.summary}`,
66
+ '',
67
+ '## Decisions',
68
+ '',
69
+ ];
70
+
71
+ for (const decision of result.decisions) {
72
+ lines.push(`### ${decision.title}`);
73
+ lines.push(`- Action: ${decision.action}`);
74
+ lines.push(`- Source sections: ${decision.sourceSectionIds.join(', ') || 'none'}`);
75
+ lines.push(`- Rationale: ${decision.rationale}`);
76
+ lines.push('');
77
+ }
78
+
79
+ lines.push('## Conflicts');
80
+ lines.push('');
81
+
82
+ if (result.conflicts.length === 0) {
83
+ lines.push('- None');
84
+ lines.push('');
85
+ return lines.join('\n');
86
+ }
87
+
88
+ for (const conflict of result.conflicts) {
89
+ lines.push(`- Sections: ${conflict.sourceSectionIds.join(', ') || 'none'}`);
90
+ lines.push(` Resolution: ${conflict.resolution}`);
91
+ }
92
+ lines.push('');
93
+
94
+ return lines.join('\n');
95
+ }
96
+
97
+ async function applyGuidelineResult(options = {}) {
98
+ const root = getProjectRoot();
99
+ assert(options.resultFile, 'apply requires --result-file <path>.');
100
+
101
+ const resultFile = path.resolve(root, options.resultFile);
102
+ assert(fs.existsSync(resultFile), `Result file not found: ${resultFile}`);
103
+
104
+ const result = readJson(resultFile);
105
+ validateResult(result);
106
+
107
+ const runtimePath = path.join(root, '.local', 'guidelines', 'CLAUDE.md');
108
+ const outputDir = options.outputDir
109
+ ? path.resolve(root, options.outputDir)
110
+ : path.join(root, '.omc', 'guidelines');
111
+ const latestDir = path.join(outputDir, 'latest');
112
+ const appliedDir = path.join(outputDir, 'applied');
113
+ const appliedRunDir = path.join(appliedDir, new Date().toISOString().replace(/[:.]/g, '-'));
114
+ const runtimeMarkdown = result.runtimeGuidelinesMarkdown.trimEnd() + '\n';
115
+ const appliedSummary = {
116
+ appliedAt: new Date().toISOString(),
117
+ generatedBy: result.generatedBy,
118
+ summary: result.summary,
119
+ resultFile,
120
+ runtimePath,
121
+ runtimeGuidelinesHash: sha256(runtimeMarkdown),
122
+ decisions: result.decisions.length,
123
+ conflicts: result.conflicts.length,
124
+ };
125
+
126
+ if (!options.dryRun) {
127
+ await writeText(runtimePath, runtimeMarkdown);
128
+ await writeText(path.join(latestDir, 'current-local-guidelines.md'), runtimeMarkdown);
129
+ await writeJson(path.join(latestDir, 'result.json'), result);
130
+ await writeText(path.join(latestDir, 'decision-log.md'), buildDecisionLog(result));
131
+ await writeJson(path.join(latestDir, 'applied-summary.json'), appliedSummary);
132
+
133
+ await writeText(path.join(appliedRunDir, 'current-local-guidelines.md'), runtimeMarkdown);
134
+ await writeJson(path.join(appliedRunDir, 'result.json'), result);
135
+ await writeText(path.join(appliedRunDir, 'decision-log.md'), buildDecisionLog(result));
136
+ await writeJson(path.join(appliedRunDir, 'applied-summary.json'), appliedSummary);
137
+ }
138
+
139
+ return {
140
+ resultFile,
141
+ runtimePath,
142
+ latestDir,
143
+ appliedRunDir,
144
+ appliedSummary,
145
+ };
146
+ }
147
+
148
+ module.exports = {
149
+ applyGuidelineResult,
150
+ buildDecisionLog,
151
+ validateResult,
152
+ };
@@ -0,0 +1,325 @@
1
+ /* eslint-disable no-console */
2
+ const fs = require('fs');
3
+ const fsp = require('fs/promises');
4
+ const path = require('path');
5
+ const crypto = require('crypto');
6
+ const { getProjectRoot, getSourceArtifactDir } = require('../config/paths');
7
+ const { readConfig } = require('../config/sources');
8
+ const { loadClaudeMd } = require('../merge/claude-md-merger');
9
+
10
+ function sanitizeSlug(value) {
11
+ return value
12
+ .toLowerCase()
13
+ .replace(/[^a-z0-9]+/g, '-')
14
+ .replace(/^-+|-+$/g, '')
15
+ .slice(0, 64) || 'untitled';
16
+ }
17
+
18
+ function sha256(value) {
19
+ return crypto.createHash('sha256').update(value).digest('hex');
20
+ }
21
+
22
+ function getGuidelineSources(root, requestedSources = []) {
23
+ const config = readConfig();
24
+ const requested = new Set(requestedSources);
25
+
26
+ return Object.entries(config.sources)
27
+ .sort(([, a], [, b]) => a.priority - b.priority)
28
+ .filter(([name, source]) => {
29
+ if (source.role === 'reference') return false;
30
+ if (requested.size > 0 && !requested.has(name)) return false;
31
+ const artifacts = source.artifacts || [];
32
+ return artifacts.includes('guidelines') || artifacts.includes('claude-md');
33
+ })
34
+ .map(([name, source]) => {
35
+ const dir = getSourceArtifactDir(name, 'guidelines', root);
36
+ return { name, source, dir };
37
+ })
38
+ .filter(({ dir }) => fs.existsSync(dir))
39
+ .map(({ name, source, dir }) => {
40
+ const content = loadClaudeMd(dir);
41
+ if (!content) return null;
42
+ return {
43
+ sourceName: name,
44
+ priority: source.priority,
45
+ role: source.role || null,
46
+ dir,
47
+ content,
48
+ };
49
+ })
50
+ .filter(Boolean);
51
+ }
52
+
53
+ function extractDocumentTitle(content) {
54
+ const firstHeader = content.match(/^#\s+(.+)$/m);
55
+ return firstHeader ? firstHeader[1].trim() : 'Guidelines';
56
+ }
57
+
58
+ function splitGuidelineSections(content, sourceName) {
59
+ const normalized = content.replace(/\r\n/g, '\n').trim();
60
+ const docTitle = extractDocumentTitle(normalized);
61
+ const lines = normalized.split('\n');
62
+ const sections = [];
63
+ let current = null;
64
+ let sectionIndex = 0;
65
+
66
+ for (const line of lines) {
67
+ if (/^##\s+/.test(line)) {
68
+ if (current && current.body.trim()) {
69
+ sections.push(current);
70
+ }
71
+ sectionIndex += 1;
72
+ current = {
73
+ id: `${sourceName}:${sectionIndex}`,
74
+ sourceName,
75
+ title: line.replace(/^##\s+/, '').trim(),
76
+ body: '',
77
+ };
78
+ continue;
79
+ }
80
+
81
+ if (!current) {
82
+ current = {
83
+ id: `${sourceName}:0`,
84
+ sourceName,
85
+ title: docTitle,
86
+ body: '',
87
+ };
88
+ }
89
+
90
+ current.body += (current.body ? '\n' : '') + line;
91
+ }
92
+
93
+ if (current && current.body.trim()) {
94
+ sections.push(current);
95
+ }
96
+
97
+ return sections
98
+ .map((section, index) => ({
99
+ ...section,
100
+ id: `${sourceName}:${index + 1}`,
101
+ body: section.body.trim(),
102
+ slug: sanitizeSlug(section.title),
103
+ }))
104
+ .filter(section => section.body.length > 0);
105
+ }
106
+
107
+ function buildOptimizerPrompt({ sources, sections, currentLocalGuidelines, outputPath }) {
108
+ const sourceSummary = sources
109
+ .map(source => `- ${source.sourceName} (priority ${source.priority}${source.role ? `, role ${source.role}` : ''})`)
110
+ .join('\n');
111
+
112
+ const sectionText = sections.map((section) => (
113
+ `### ${section.id} — ${section.title}\n` +
114
+ `Source: ${section.sourceName}\n\n` +
115
+ `${section.body}\n`
116
+ )).join('\n');
117
+
118
+ const currentLocalText = currentLocalGuidelines
119
+ ? currentLocalGuidelines.trim()
120
+ : '_No current local guidelines file found._';
121
+
122
+ return `# Guideline Optimizer Input
123
+
124
+ You are maintaining OMC's canonical runtime guidelines.
125
+
126
+ ## Goal
127
+
128
+ Produce an improved \`CLAUDE.md\` section for OMC by semantically deduplicating,
129
+ merging, rewriting, and prioritizing the guideline material collected below.
130
+
131
+ ## Constraints
132
+
133
+ - This is a maintainer workflow. The optimizer logic itself does not ship to end users.
134
+ - The runtime output must stay concise, high-signal, and suitable for always-on use.
135
+ - Prefer rewriting combined rules over stacking near-duplicates.
136
+ - Preserve behaviorally important constraints even if wording changes.
137
+ - Surface genuine conflicts explicitly instead of silently averaging them away.
138
+ - The final markdown should be written to \`${outputPath}\`.
139
+ - Output markdown body only. Do not include surrounding commentary.
140
+
141
+ ## Source Summary
142
+
143
+ ${sourceSummary}
144
+
145
+ ## Current Local Guidelines
146
+
147
+ ${currentLocalText}
148
+
149
+ ## Extracted Source Sections
150
+
151
+ ${sectionText}
152
+
153
+ ## Required Output Shape
154
+
155
+ 1. A canonical markdown document body suitable for \`${outputPath}\`
156
+ 2. Short internal rationale notes for:
157
+ - merged rules
158
+ - dropped rules
159
+ - unresolved conflicts
160
+
161
+ When two sections are semantically overlapping, prefer a single clearer rule.
162
+ When one section is a stronger, more specific operationalization of another,
163
+ keep the stronger wording and note the collapse in rationale.`;
164
+ }
165
+
166
+ async function ensureDir(dirPath) {
167
+ await fsp.mkdir(dirPath, { recursive: true });
168
+ }
169
+
170
+ async function writeJson(filePath, value) {
171
+ await ensureDir(path.dirname(filePath));
172
+ await fsp.writeFile(filePath, JSON.stringify(value, null, 2) + '\n', 'utf8');
173
+ }
174
+
175
+ async function writeText(filePath, value) {
176
+ await ensureDir(path.dirname(filePath));
177
+ await fsp.writeFile(filePath, value, 'utf8');
178
+ }
179
+
180
+ function buildNextSteps({ summary, latestDir }) {
181
+ const lines = [
182
+ '# Guideline Optimizer Next Steps',
183
+ '',
184
+ 'This workflow is for Claude Code CLI or Codex operating inside the OMC repository.',
185
+ '',
186
+ '## Read First',
187
+ '',
188
+ `- ${path.join(latestDir, 'optimizer-input.md')}`,
189
+ `- ${path.join(latestDir, 'sections.json')}`,
190
+ `- ${path.join(latestDir, 'sources.json')}`,
191
+ `- ${path.join(summary.root, '.maintainer', 'skills', 'guideline-optimizer', 'SKILL.md')}`,
192
+ '',
193
+ '## Edit Target',
194
+ '',
195
+ `- ${summary.outputPath}`,
196
+ '',
197
+ '## Required Verification',
198
+ '',
199
+ '```bash',
200
+ 'node bin/omc-manage.js setup --dry-run --type guidelines',
201
+ 'node bin/omc-manage.js artifact list --type guidelines',
202
+ '```',
203
+ '',
204
+ '## Rules',
205
+ '',
206
+ '- Apply semantic merging, not text-level dedupe.',
207
+ '- Keep maintainer reasoning out of the runtime guideline file.',
208
+ '- Do not move maintainer-only workflow prompts into `.local/skills/`.',
209
+ '',
210
+ '## Structured Result Contract',
211
+ '',
212
+ 'Create a JSON file with this shape, then apply it with the CLI:',
213
+ '',
214
+ '```json',
215
+ '{',
216
+ ' "version": 1,',
217
+ ' "generatedBy": "claude-code | codex | other",',
218
+ ' "summary": "short description of what changed",',
219
+ ' "runtimeGuidelinesMarkdown": "# Coding Discipline\\n...",',
220
+ ' "decisions": [',
221
+ ' {',
222
+ ' "action": "keep | merge | rewrite | drop",',
223
+ ' "sourceSectionIds": ["local:2"],',
224
+ ' "title": "Think Before Coding",',
225
+ ' "rationale": "why this rule stayed or changed"',
226
+ ' }',
227
+ ' ],',
228
+ ' "conflicts": [',
229
+ ' {',
230
+ ' "sourceSectionIds": ["a:2", "b:4"],',
231
+ ' "resolution": "how the conflict was resolved"',
232
+ ' }',
233
+ ' ]',
234
+ '}',
235
+ '```',
236
+ '',
237
+ 'Apply it with:',
238
+ '',
239
+ '```bash',
240
+ 'node bin/omc-manage.js guidelines apply --result-file /absolute/path/to/result.json',
241
+ 'node bin/omc-manage.js setup --dry-run --type guidelines',
242
+ '```',
243
+ ];
244
+
245
+ return lines.join('\n') + '\n';
246
+ }
247
+
248
+ async function optimizeGuidelines(options = {}) {
249
+ const root = getProjectRoot();
250
+ const selectedSources = options.sources || [];
251
+ const sources = getGuidelineSources(root, selectedSources);
252
+
253
+ if (sources.length === 0) {
254
+ throw new Error('No guideline sources found. Add a guidelines source or create .local/guidelines/CLAUDE.md.');
255
+ }
256
+
257
+ const sections = sources.flatMap(source => splitGuidelineSections(source.content, source.sourceName));
258
+ const localGuidelinesPath = path.join(root, '.local', 'guidelines', 'CLAUDE.md');
259
+ const currentLocalGuidelines = fs.existsSync(localGuidelinesPath)
260
+ ? fs.readFileSync(localGuidelinesPath, 'utf8')
261
+ : '';
262
+
263
+ const runId = new Date().toISOString().replace(/[:.]/g, '-');
264
+ const baseOutputDir = options.outputDir
265
+ ? path.resolve(root, options.outputDir)
266
+ : path.join(root, '.omc', 'guidelines');
267
+ const latestDir = path.join(baseOutputDir, 'latest');
268
+ const runDir = path.join(baseOutputDir, 'runs', runId);
269
+
270
+ const summary = {
271
+ runId,
272
+ root,
273
+ sourceCount: sources.length,
274
+ sectionCount: sections.length,
275
+ outputPath: localGuidelinesPath,
276
+ currentLocalGuidelinesHash: sha256(currentLocalGuidelines || ''),
277
+ latestDir,
278
+ runDir,
279
+ sources: sources.map(source => ({
280
+ sourceName: source.sourceName,
281
+ priority: source.priority,
282
+ role: source.role,
283
+ dir: source.dir,
284
+ title: extractDocumentTitle(source.content),
285
+ contentHash: sha256(source.content),
286
+ })),
287
+ };
288
+
289
+ const prompt = buildOptimizerPrompt({
290
+ sources: summary.sources,
291
+ sections,
292
+ currentLocalGuidelines,
293
+ outputPath: localGuidelinesPath,
294
+ });
295
+
296
+ if (!options.dryRun) {
297
+ await ensureDir(latestDir);
298
+ await ensureDir(runDir);
299
+ const nextSteps = buildNextSteps({ summary, latestDir });
300
+
301
+ await writeJson(path.join(latestDir, 'summary.json'), summary);
302
+ await writeJson(path.join(latestDir, 'sections.json'), sections);
303
+ await writeJson(path.join(latestDir, 'sources.json'), summary.sources);
304
+ await writeText(path.join(latestDir, 'optimizer-input.md'), prompt);
305
+ await writeText(path.join(latestDir, 'current-local-guidelines.md'), currentLocalGuidelines || '');
306
+ await writeText(path.join(latestDir, 'next-steps.md'), nextSteps);
307
+
308
+ await writeJson(path.join(runDir, 'summary.json'), summary);
309
+ await writeJson(path.join(runDir, 'sections.json'), sections);
310
+ await writeJson(path.join(runDir, 'sources.json'), summary.sources);
311
+ await writeText(path.join(runDir, 'optimizer-input.md'), prompt);
312
+ await writeText(path.join(runDir, 'current-local-guidelines.md'), currentLocalGuidelines || '');
313
+ await writeText(path.join(runDir, 'next-steps.md'), nextSteps);
314
+ }
315
+
316
+ return { summary, prompt };
317
+ }
318
+
319
+ module.exports = {
320
+ optimizeGuidelines,
321
+ getGuidelineSources,
322
+ splitGuidelineSections,
323
+ buildOptimizerPrompt,
324
+ sha256,
325
+ };
@@ -25,28 +25,51 @@ function assembleSections(sections) {
25
25
  return sections.map(s => s.content).join('\n\n').trimEnd() + '\n';
26
26
  }
27
27
 
28
+ function getMarkers(markerKey) {
29
+ return {
30
+ start: `<!-- OMC:${markerKey}:START -->`,
31
+ end: `<!-- OMC:${markerKey}:END -->`,
32
+ };
33
+ }
34
+
35
+ function replaceFirstMatchingBlock(result, markerKeys, block) {
36
+ for (const markerKey of markerKeys) {
37
+ const { start, end } = getMarkers(markerKey);
38
+ const startIdx = result.indexOf(start);
39
+ const endIdx = result.indexOf(end);
40
+
41
+ if (startIdx !== -1 && endIdx !== -1) {
42
+ return result.slice(0, startIdx) + block + result.slice(endIdx + end.length);
43
+ }
44
+ }
45
+
46
+ return null;
47
+ }
48
+
28
49
  /**
29
50
  * Merge new sections into an existing CLAUDE.md
30
51
  * Wraps each source block in OMC markers to allow idempotent updates
31
52
  */
32
- function mergeIntoExisting(existing, sections) {
53
+ function mergeIntoExisting(existing, sections, options = {}) {
54
+ const markerNamespace = options.markerNamespace || 'claude-md';
33
55
  let result = existing;
34
56
 
35
57
  for (const { sourceName, content } of sections) {
36
- const startMarker = `<!-- OMC:${sourceName}:START -->`;
37
- const endMarker = `<!-- OMC:${sourceName}:END -->`;
58
+ const markerKey = `${markerNamespace}:${sourceName}`;
59
+ const { start: startMarker, end: endMarker } = getMarkers(markerKey);
38
60
  const block = `${startMarker}\n${content.trimEnd()}\n${endMarker}`;
61
+ const legacyMarkerKeys = options.legacyMarkerKeys
62
+ ? options.legacyMarkerKeys(sourceName)
63
+ : [sourceName];
64
+ const replaced = replaceFirstMatchingBlock(result, [markerKey, ...legacyMarkerKeys], block);
39
65
 
40
- const startIdx = result.indexOf(startMarker);
41
- const endIdx = result.indexOf(endMarker);
42
-
43
- if (startIdx !== -1 && endIdx !== -1) {
44
- // Replace existing block
45
- result = result.slice(0, startIdx) + block + result.slice(endIdx + endMarker.length);
46
- } else {
47
- // Append new block
48
- result = result.trimEnd() + '\n\n' + block + '\n';
66
+ if (replaced !== null) {
67
+ result = replaced;
68
+ continue;
49
69
  }
70
+
71
+ // Append new block
72
+ result = result.trimEnd() + '\n\n' + block + '\n';
50
73
  }
51
74
 
52
75
  return result;
@@ -7,5 +7,16 @@
7
7
  { "name": "oh-my-claudecode", "priority": 2 },
8
8
  { "name": "superpowers", "priority": 3 }
9
9
  ],
10
- "preferences": {}
10
+ "preferences": {},
11
+ "exclude": {
12
+ "skills": [
13
+ "ask",
14
+ "ccg",
15
+ "multi-model-research",
16
+ "test-gen",
17
+ "release",
18
+ "omc-teams",
19
+ "using-superpowers"
20
+ ]
21
+ }
11
22
  }
@@ -1,101 +0,0 @@
1
- ---
2
- description: Debug why a Claude Code skill isn't triggering when expected
3
- ---
4
-
5
- # Skill Debugger
6
-
7
- [SKILL DEBUG MODE ACTIVATED]
8
-
9
- ## Objective
10
-
11
- Systematically diagnose why a skill isn't triggering as expected. Identify root causes and provide actionable fixes.
12
-
13
- ## Debugging Workflow
14
-
15
- ### Step 1: Identify Target Skill
16
-
17
- Ask the user which skill isn't working, or infer from context. Then verify it exists:
18
-
19
- ```bash
20
- # Check plugin skills
21
- ls ~/.claude/plugins/cache/omc/oh-my-claudecode/*/skills/<skill-name>/ 2>/dev/null
22
-
23
- # Check global skills
24
- ls ~/.claude/skills/<skill-name>/ 2>/dev/null
25
- ```
26
-
27
- ### Step 2: Validate SKILL.md
28
-
29
- Use the `Read` tool to read the target skill's `SKILL.md` and check:
30
-
31
- - [ ] File exists and is readable
32
- - [ ] YAML frontmatter has `---` delimiters
33
- - [ ] `name:` field matches folder name
34
- - [ ] `description:` is 50-150 characters, specific, not vague
35
- - [ ] No vague words ("helps", "assists", "various")
36
-
37
- ### Step 3: Analyze Description Quality
38
-
39
- Compare the skill description against what the user asked. Check:
40
-
41
- - Does the description contain keywords the user would naturally say?
42
- - Is there a `<Use_When>` or "When to Use" section?
43
- - Are there at least 3 usage examples?
44
-
45
- ### Step 4: Check for Conflicts
46
-
47
- Scan all installed skills for overlapping descriptions:
48
-
49
- ```bash
50
- # List all skill descriptions
51
- for dir in ~/.claude/plugins/cache/omc/oh-my-claudecode/*/skills/*/; do
52
- if [ -f "$dir/SKILL.md" ]; then
53
- echo "=== $(basename $dir) ==="
54
- head -5 "$dir/SKILL.md"
55
- echo
56
- fi
57
- done
58
- ```
59
-
60
- Look for skills with similar keywords or overlapping use cases.
61
-
62
- ### Step 5: Check Command Registration
63
-
64
- Verify if the skill has a corresponding slash command:
65
-
66
- ```bash
67
- ls ~/.claude/plugins/cache/omc/oh-my-claudecode/*/commands/<skill-name>.md 2>/dev/null
68
- ```
69
-
70
- If no command exists, the skill relies purely on semantic matching.
71
-
72
- ## Diagnosis Report Format
73
-
74
- ```
75
- ## Skill Debug Report
76
-
77
- Skill: <name>
78
- Path: <location>
79
- Status: OK / NOT TRIGGERING / CONFLICT
80
-
81
- ### Issues Found
82
- | Priority | Issue | Fix |
83
- |----------|-------|-----|
84
- | CRITICAL | ... | ... |
85
- | HIGH | ... | ... |
86
- | MEDIUM | ... | ... |
87
-
88
- ### Recommendations
89
- 1. [Specific fix with before/after examples]
90
- 2. [...]
91
- ```
92
-
93
- ## Common Fixes
94
-
95
- | Problem | Fix |
96
- |---------|-----|
97
- | Description too vague | Add specific keywords and use cases |
98
- | No trigger keywords | Add words users would naturally say |
99
- | Wrong skill triggers | Differentiate descriptions between conflicting skills |
100
- | Skill not found | Check installation path and folder name |
101
- | No slash command | Create `commands/<name>.md` for explicit triggering |