oxe-cc 1.12.0 → 1.16.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 (40) hide show
  1. package/.github/dependabot.yml +31 -0
  2. package/.github/workflows/ci.yml +141 -56
  3. package/.github/workflows/release.yml +114 -89
  4. package/CHANGELOG.md +866 -754
  5. package/README.md +600 -736
  6. package/bin/lib/oxe-agent-install.cjs +299 -284
  7. package/bin/lib/oxe-artifact-catalog.cjs +376 -0
  8. package/bin/lib/oxe-command-registry.cjs +31 -0
  9. package/bin/lib/oxe-context-engine.cjs +11 -11
  10. package/bin/lib/oxe-core-command-handlers.cjs +82 -0
  11. package/bin/lib/oxe-dashboard.cjs +140 -140
  12. package/bin/lib/oxe-manifest.cjs +20 -20
  13. package/bin/lib/oxe-npm-version.cjs +6 -4
  14. package/bin/lib/oxe-plugin-cli.cjs +95 -0
  15. package/bin/lib/oxe-plugins.cjs +94 -3
  16. package/bin/lib/oxe-process.cjs +67 -0
  17. package/bin/lib/oxe-project-health.cjs +2846 -2781
  18. package/bin/lib/oxe-runtime-semantics.cjs +68 -69
  19. package/bin/oxe-cc.js +369 -353
  20. package/docs/INTEGRATION.md +182 -0
  21. package/docs/QUALITY-GATES.md +46 -0
  22. package/docs/RELEASE-READINESS.md +86 -61
  23. package/docs/RUNTIME-SMOKE-MATRIX.md +137 -135
  24. package/docs/oxe-artifact-map.html +1172 -0
  25. package/lib/sdk/index.cjs +20 -0
  26. package/lib/sdk/index.d.ts +971 -876
  27. package/lib/sdk/index.types.ts +933 -0
  28. package/oxe/templates/PLUGINS.md +8 -1
  29. package/oxe/templates/STATE-REFERENCE.md +125 -0
  30. package/oxe/templates/STATE.md +11 -121
  31. package/oxe/workflows/help.md +2 -0
  32. package/package.json +129 -108
  33. package/packages/runtime/package.json +18 -18
  34. package/packages/runtime/src/evidence/evidence-store.ts +2 -2
  35. package/packages/runtime/src/scheduler/multi-agent-coordinator.ts +728 -728
  36. package/packages/runtime/src/workspace/strategies/git-worktree.ts +24 -24
  37. package/packages/runtime/tsconfig.json +8 -2
  38. package/vscode-extension/.vscodeignore +2 -0
  39. package/vscode-extension/package.json +193 -185
  40. package/vscode-extension/src/extension.js +11 -1
@@ -13,13 +13,13 @@ const path = require('path');
13
13
  const os = require('os');
14
14
  const runtimeSemantics = require('./oxe-runtime-semantics.cjs');
15
15
 
16
- const OXE_MANAGED_HTML = '<!-- oxe-cc managed -->';
17
- const OXE_MANAGED_TOML = '# oxe-cc managed';
18
-
19
- /** @param {string} name */
20
- function isOxeCommandMarkdownName(name) {
21
- return (name === 'oxe.md' || name.startsWith('oxe-')) && name.endsWith('.md');
22
- }
16
+ const OXE_MANAGED_HTML = '<!-- oxe-cc managed -->';
17
+ const OXE_MANAGED_TOML = '# oxe-cc managed';
18
+
19
+ /** @param {string} name */
20
+ function isOxeCommandMarkdownName(name) {
21
+ return (name === 'oxe.md' || name.startsWith('oxe-')) && name.endsWith('.md');
22
+ }
23
23
 
24
24
  function expandTilde(p) {
25
25
  if (typeof p !== 'string') return p;
@@ -34,20 +34,21 @@ function expandTilde(p) {
34
34
  * opencodeCommandDirs: string[],
35
35
  * geminiCommandsBase: string,
36
36
  * windsurfWorkflowsDir: string,
37
- * codexPromptsDir: string,
38
- * codexAgentsSkillsRoot: string,
39
- * antigravitySkillsRoot: string,
40
- * claudeAgentsDir: string,
41
- * }} AgentInstallPaths
37
+ * codexPromptsDir: string,
38
+ * codexAgentsSkillsRoot: string,
39
+ * antigravitySkillsRoot: string,
40
+ * claudeAgentsDir: string,
41
+ * }} AgentInstallPaths
42
42
  */
43
43
 
44
44
  /**
45
- * @param {boolean} ideGlobal
46
- * @param {string} projectRoot
47
- * @returns {AgentInstallPaths}
48
- */
49
- function buildAgentInstallPaths(ideGlobal, projectRoot) {
50
- const home = os.homedir();
45
+ * @param {boolean} ideGlobal
46
+ * @param {string} projectRoot
47
+ * @param {{ home?: string }} [options]
48
+ * @returns {AgentInstallPaths}
49
+ */
50
+ function buildAgentInstallPaths(ideGlobal, projectRoot, options = {}) {
51
+ const home = options.home ? path.resolve(options.home) : os.homedir();
51
52
  const root = path.resolve(projectRoot);
52
53
  if (ideGlobal) {
53
54
  const xdg = process.env.XDG_CONFIG_HOME || path.join(home, '.config');
@@ -57,23 +58,23 @@ function buildAgentInstallPaths(ideGlobal, projectRoot) {
57
58
  opencodeCommandDirs: [path.join(xdg, 'opencode', 'commands'), path.join(home, '.opencode', 'commands')],
58
59
  geminiCommandsBase: path.join(home, '.gemini', 'commands'),
59
60
  windsurfWorkflowsDir: path.join(home, '.codeium', 'windsurf', 'global_workflows'),
60
- codexPromptsDir: path.join(codexHome, 'prompts'),
61
- codexAgentsSkillsRoot: path.join(home, '.agents', 'skills'),
62
- antigravitySkillsRoot: path.join(home, '.gemini', 'antigravity', 'skills'),
63
- claudeAgentsDir: path.join(home, '.claude', 'agents'),
64
- };
65
- }
61
+ codexPromptsDir: path.join(codexHome, 'prompts'),
62
+ codexAgentsSkillsRoot: path.join(home, '.agents', 'skills'),
63
+ antigravitySkillsRoot: path.join(home, '.gemini', 'antigravity', 'skills'),
64
+ claudeAgentsDir: path.join(home, '.claude', 'agents'),
65
+ };
66
+ }
66
67
  return {
67
68
  ideGlobal: false,
68
69
  opencodeCommandDirs: [path.join(root, '.opencode', 'commands')],
69
70
  geminiCommandsBase: path.join(root, '.gemini', 'commands'),
70
71
  windsurfWorkflowsDir: path.join(root, '.windsurf', 'global_workflows'),
71
- codexPromptsDir: path.join(root, '.codex', 'prompts'),
72
- codexAgentsSkillsRoot: path.join(root, '.agents', 'skills'),
73
- antigravitySkillsRoot: path.join(root, '.gemini', 'antigravity', 'skills'),
74
- claudeAgentsDir: path.join(root, '.claude', 'agents'),
75
- };
76
- }
72
+ codexPromptsDir: path.join(root, '.codex', 'prompts'),
73
+ codexAgentsSkillsRoot: path.join(root, '.agents', 'skills'),
74
+ antigravitySkillsRoot: path.join(root, '.gemini', 'antigravity', 'skills'),
75
+ claudeAgentsDir: path.join(root, '.claude', 'agents'),
76
+ };
77
+ }
77
78
 
78
79
  /** @param {string} content */
79
80
  function adjustWorkflowPathsForNestedLayout(content) {
@@ -95,30 +96,30 @@ function parseCursorCommandFrontmatter(text) {
95
96
  if (end === -1) {
96
97
  return { description: '', body: normalized.trim(), frontmatter: {} };
97
98
  }
98
- const yamlBlock = normalized.slice(4, end);
99
- const frontmatter = {};
100
- let description = '';
101
- const yamlLines = yamlBlock.split('\n');
102
- for (let i = 0; i < yamlLines.length; i++) {
103
- const line = yamlLines[i];
104
- const foldedDescription = line.match(/^description:\s*[>|]\s*$/);
105
- if (foldedDescription) {
106
- const parts = [];
107
- let j = i + 1;
108
- while (j < yamlLines.length && /^\s+/.test(yamlLines[j])) {
109
- const value = yamlLines[j].trim();
110
- if (value) parts.push(value);
111
- j += 1;
112
- }
113
- description = parts.join(' ').trim();
114
- frontmatter.description = description;
115
- i = j - 1;
116
- continue;
117
- }
118
- const m = line.match(/^description:\s*(.+)$/);
119
- if (m) {
120
- description = m[1].trim().replace(/^["']|["']$/g, '');
121
- }
99
+ const yamlBlock = normalized.slice(4, end);
100
+ const frontmatter = {};
101
+ let description = '';
102
+ const yamlLines = yamlBlock.split('\n');
103
+ for (let i = 0; i < yamlLines.length; i++) {
104
+ const line = yamlLines[i];
105
+ const foldedDescription = line.match(/^description:\s*[>|]\s*$/);
106
+ if (foldedDescription) {
107
+ const parts = [];
108
+ let j = i + 1;
109
+ while (j < yamlLines.length && /^\s+/.test(yamlLines[j])) {
110
+ const value = yamlLines[j].trim();
111
+ if (value) parts.push(value);
112
+ j += 1;
113
+ }
114
+ description = parts.join(' ').trim();
115
+ frontmatter.description = description;
116
+ i = j - 1;
117
+ continue;
118
+ }
119
+ const m = line.match(/^description:\s*(.+)$/);
120
+ if (m) {
121
+ description = m[1].trim().replace(/^["']|["']$/g, '');
122
+ }
122
123
  const kv = line.match(/^([A-Za-z0-9_-]+):\s*(.+)$/);
123
124
  if (kv) frontmatter[kv[1]] = kv[2].trim().replace(/^["']|["']$/g, '');
124
125
  }
@@ -132,7 +133,7 @@ function parseCursorCommandFrontmatter(text) {
132
133
  * @param {string} body
133
134
  * @param {Record<string, string>} [metadata]
134
135
  */
135
- function buildAgentSkillMarkdown(skillName, description, body, metadata) {
136
+ function buildAgentSkillMarkdown(skillName, description, body, metadata) {
136
137
  const desc = description.trim() || `Comando OXE — ${skillName}`;
137
138
  const meta = metadata ? runtimeSemantics.pickRuntimeMetadata(metadata) : {};
138
139
  const metaLines = Object.keys(meta).length
@@ -147,91 +148,91 @@ function buildAgentSkillMarkdown(skillName, description, body, metadata) {
147
148
  `---\n\n` +
148
149
  `${OXE_MANAGED_HTML}\n\n` +
149
150
  `${body}\n`
150
- );
151
- }
152
-
153
- /** @param {string} name */
154
- function isOxeAgentMarkdownName(name) {
155
- return name.startsWith('oxe-') && name.endsWith('.md');
156
- }
157
-
158
- /**
159
- * @param {string} text
160
- * @returns {{ name: string, description: string, body: string, frontmatter: Record<string, string> }}
161
- */
162
- function parseCanonicalAgentMarkdown(text) {
163
- const parsed = parseCursorCommandFrontmatter(text);
164
- return {
165
- name: parsed.frontmatter.name || '',
166
- description: parsed.description || parsed.frontmatter.description || '',
167
- body: parsed.body,
168
- frontmatter: parsed.frontmatter,
169
- };
170
- }
171
-
172
- /**
173
- * Instala agentes especializados OXE como markdown nativo para runtimes que suportam agentes.
174
- * @param {string} agentsSrc
175
- * @param {string} destDir
176
- * @param {{ dryRun: boolean, force: boolean }} opts
177
- * @param {(s: string) => void} [logOmitido]
178
- * @param {(s: string) => void} [logWrite]
179
- */
180
- function installCanonicalAgentMarkdowns(agentsSrc, destDir, opts, logOmitido, logWrite) {
181
- if (!fs.existsSync(agentsSrc)) return;
182
- for (const name of fs.readdirSync(agentsSrc)) {
183
- if (!isOxeAgentMarkdownName(name)) continue;
184
- const src = path.join(agentsSrc, name);
185
- const dest = path.join(destDir, name);
186
- if (opts.dryRun) {
187
- if (logWrite) logWrite(`${src} → ${dest}`);
188
- continue;
189
- }
190
- if (fs.existsSync(dest) && !opts.force) {
191
- if (logOmitido) logOmitido(dest);
192
- continue;
193
- }
194
- const raw = fs.readFileSync(src, 'utf8');
195
- const out = raw.includes(OXE_MANAGED_HTML) ? raw : raw.replace(/\n?$/, `\n\n${OXE_MANAGED_HTML}\n`);
196
- fs.mkdirSync(destDir, { recursive: true });
197
- fs.writeFileSync(dest, out, 'utf8');
198
- }
199
- }
200
-
201
- /**
202
- * Instala agentes especializados OXE como skills Codex/Antigravity.
203
- * @param {string} agentsSrc
204
- * @param {string} skillsRoot
205
- * @param {{ dryRun: boolean, force: boolean }} opts
206
- * @param {(s: string) => void} [logOmitido]
207
- * @param {(s: string) => void} [logWrite]
208
- */
209
- function installCanonicalAgentSkills(agentsSrc, skillsRoot, opts, logOmitido, logWrite) {
210
- if (!fs.existsSync(agentsSrc)) return;
211
- for (const name of fs.readdirSync(agentsSrc)) {
212
- if (!isOxeAgentMarkdownName(name)) continue;
213
- const src = path.join(agentsSrc, name);
214
- const raw = fs.readFileSync(src, 'utf8');
215
- const parsed = parseCanonicalAgentMarkdown(raw);
216
- const skillName = parsed.name || name.replace(/\.md$/i, '');
217
- const md = buildAgentSkillMarkdown(skillName, parsed.description, parsed.body, parsed.frontmatter);
218
- const destDir = path.join(skillsRoot, skillName);
219
- const dest = path.join(destDir, 'SKILL.md');
220
- if (opts.dryRun) {
221
- if (logWrite) logWrite(`${src} → ${dest}`);
222
- continue;
223
- }
224
- if (fs.existsSync(dest) && !opts.force) {
225
- if (logOmitido) logOmitido(dest);
226
- continue;
227
- }
228
- fs.mkdirSync(destDir, { recursive: true });
229
- fs.writeFileSync(dest, md, 'utf8');
230
- }
231
- }
232
-
233
- /**
234
- * @returns {string[]}
151
+ );
152
+ }
153
+
154
+ /** @param {string} name */
155
+ function isOxeAgentMarkdownName(name) {
156
+ return name.startsWith('oxe-') && name.endsWith('.md');
157
+ }
158
+
159
+ /**
160
+ * @param {string} text
161
+ * @returns {{ name: string, description: string, body: string, frontmatter: Record<string, string> }}
162
+ */
163
+ function parseCanonicalAgentMarkdown(text) {
164
+ const parsed = parseCursorCommandFrontmatter(text);
165
+ return {
166
+ name: parsed.frontmatter.name || '',
167
+ description: parsed.description || parsed.frontmatter.description || '',
168
+ body: parsed.body,
169
+ frontmatter: parsed.frontmatter,
170
+ };
171
+ }
172
+
173
+ /**
174
+ * Instala agentes especializados OXE como markdown nativo para runtimes que suportam agentes.
175
+ * @param {string} agentsSrc
176
+ * @param {string} destDir
177
+ * @param {{ dryRun: boolean, force: boolean }} opts
178
+ * @param {(s: string) => void} [logOmitido]
179
+ * @param {(s: string) => void} [logWrite]
180
+ */
181
+ function installCanonicalAgentMarkdowns(agentsSrc, destDir, opts, logOmitido, logWrite) {
182
+ if (!fs.existsSync(agentsSrc)) return;
183
+ for (const name of fs.readdirSync(agentsSrc)) {
184
+ if (!isOxeAgentMarkdownName(name)) continue;
185
+ const src = path.join(agentsSrc, name);
186
+ const dest = path.join(destDir, name);
187
+ if (opts.dryRun) {
188
+ if (logWrite) logWrite(`${src} → ${dest}`);
189
+ continue;
190
+ }
191
+ if (fs.existsSync(dest) && !opts.force) {
192
+ if (logOmitido) logOmitido(dest);
193
+ continue;
194
+ }
195
+ const raw = fs.readFileSync(src, 'utf8');
196
+ const out = raw.includes(OXE_MANAGED_HTML) ? raw : raw.replace(/\n?$/, `\n\n${OXE_MANAGED_HTML}\n`);
197
+ fs.mkdirSync(destDir, { recursive: true });
198
+ fs.writeFileSync(dest, out, 'utf8');
199
+ }
200
+ }
201
+
202
+ /**
203
+ * Instala agentes especializados OXE como skills Codex/Antigravity.
204
+ * @param {string} agentsSrc
205
+ * @param {string} skillsRoot
206
+ * @param {{ dryRun: boolean, force: boolean }} opts
207
+ * @param {(s: string) => void} [logOmitido]
208
+ * @param {(s: string) => void} [logWrite]
209
+ */
210
+ function installCanonicalAgentSkills(agentsSrc, skillsRoot, opts, logOmitido, logWrite) {
211
+ if (!fs.existsSync(agentsSrc)) return;
212
+ for (const name of fs.readdirSync(agentsSrc)) {
213
+ if (!isOxeAgentMarkdownName(name)) continue;
214
+ const src = path.join(agentsSrc, name);
215
+ const raw = fs.readFileSync(src, 'utf8');
216
+ const parsed = parseCanonicalAgentMarkdown(raw);
217
+ const skillName = parsed.name || name.replace(/\.md$/i, '');
218
+ const md = buildAgentSkillMarkdown(skillName, parsed.description, parsed.body, parsed.frontmatter);
219
+ const destDir = path.join(skillsRoot, skillName);
220
+ const dest = path.join(destDir, 'SKILL.md');
221
+ if (opts.dryRun) {
222
+ if (logWrite) logWrite(`${src} → ${dest}`);
223
+ continue;
224
+ }
225
+ if (fs.existsSync(dest) && !opts.force) {
226
+ if (logOmitido) logOmitido(dest);
227
+ continue;
228
+ }
229
+ fs.mkdirSync(destDir, { recursive: true });
230
+ fs.writeFileSync(dest, md, 'utf8');
231
+ }
232
+ }
233
+
234
+ /**
235
+ * @returns {string[]}
235
236
  */
236
237
  function opencodeCommandDirs() {
237
238
  return buildAgentInstallPaths(true, process.cwd()).opencodeCommandDirs;
@@ -328,12 +329,12 @@ function installSkillTreeFromCursorCommands(cCmdSrc, skillsRoot, opts, pathRewri
328
329
  * @param {AgentInstallPaths} paths
329
330
  */
330
331
  function installOpenCodeCommands(cCmdSrc, paths, opts, pathRewriteNested, logOmitido, logWrite) {
331
- if (!fs.existsSync(cCmdSrc)) return;
332
+ if (!fs.existsSync(cCmdSrc)) return;
332
333
  for (const destDir of paths.opencodeCommandDirs) {
333
- for (const name of fs.readdirSync(cCmdSrc)) {
334
- if (!isOxeCommandMarkdownName(name)) continue;
335
- const src = path.join(cCmdSrc, name);
336
- const dest = path.join(destDir, name);
334
+ for (const name of fs.readdirSync(cCmdSrc)) {
335
+ if (!isOxeCommandMarkdownName(name)) continue;
336
+ const src = path.join(cCmdSrc, name);
337
+ const dest = path.join(destDir, name);
337
338
  if (opts.dryRun) {
338
339
  if (logWrite) logWrite(`opencode ${src} → ${dest}`);
339
340
  continue;
@@ -345,10 +346,24 @@ function installOpenCodeCommands(cCmdSrc, paths, opts, pathRewriteNested, logOmi
345
346
  const raw = fs.readFileSync(src, 'utf8');
346
347
  const out = injectManagedAfterFrontmatter(raw, pathRewriteNested);
347
348
  fs.mkdirSync(destDir, { recursive: true });
348
- fs.writeFileSync(dest, out, 'utf8');
349
- }
350
- }
351
- }
349
+ fs.writeFileSync(dest, out, 'utf8');
350
+ }
351
+ const helpSrc = path.join(cCmdSrc, 'oxe-help.md');
352
+ const rootDest = path.join(destDir, 'oxe.md');
353
+ if (fs.existsSync(helpSrc) && (opts.force || !fs.existsSync(rootDest))) {
354
+ const raw = fs.readFileSync(helpSrc, 'utf8');
355
+ const out = injectManagedAfterFrontmatter(raw, pathRewriteNested);
356
+ if (opts.dryRun) {
357
+ if (logWrite) logWrite(`opencode ${helpSrc} → ${rootDest}`);
358
+ } else {
359
+ fs.mkdirSync(destDir, { recursive: true });
360
+ fs.writeFileSync(rootDest, out, 'utf8');
361
+ }
362
+ } else if (fs.existsSync(rootDest) && logOmitido) {
363
+ logOmitido(rootDest);
364
+ }
365
+ }
366
+ }
352
367
 
353
368
  /**
354
369
  * ~/.gemini/commands/oxe.toml → /oxe ; oxe/scan.toml → /oxe:scan
@@ -449,13 +464,13 @@ function installWindsurfGlobalWorkflows(cCmdSrc, paths, opts, pathRewriteNested,
449
464
  * Codex: prompts em ~/.codex/prompts ou ./.codex/prompts (local).
450
465
  * @param {AgentInstallPaths} paths
451
466
  */
452
- function installCodexPrompts(cCmdSrc, paths, opts, pathRewriteNested, logOmitido, logWrite) {
453
- if (!fs.existsSync(cCmdSrc)) return;
454
- const destDir = paths.codexPromptsDir;
455
- for (const name of fs.readdirSync(cCmdSrc)) {
456
- if (!isOxeCommandMarkdownName(name)) continue;
457
- const src = path.join(cCmdSrc, name);
458
- const dest = path.join(destDir, name);
467
+ function installCodexPrompts(cCmdSrc, paths, opts, pathRewriteNested, logOmitido, logWrite) {
468
+ if (!fs.existsSync(cCmdSrc)) return;
469
+ const destDir = paths.codexPromptsDir;
470
+ for (const name of fs.readdirSync(cCmdSrc)) {
471
+ if (!isOxeCommandMarkdownName(name)) continue;
472
+ const src = path.join(cCmdSrc, name);
473
+ const dest = path.join(destDir, name);
459
474
  if (opts.dryRun) {
460
475
  if (logWrite) logWrite(`codex prompts ${src} → ${dest}`);
461
476
  continue;
@@ -489,10 +504,10 @@ function installCodexPrompts(cCmdSrc, paths, opts, pathRewriteNested, logOmitido
489
504
  * @param {{ dryRun: boolean }} u
490
505
  * @param {AgentInstallPaths} [paths] omissão = instalação global (HOME)
491
506
  */
492
- function cleanupMarkedUnifiedArtifacts(u, paths) {
493
- const p = paths || buildAgentInstallPaths(true, process.cwd());
494
- const targets = u && typeof u === 'object' && u.targets && typeof u.targets === 'object' ? u.targets : null;
495
- const shouldClean = (name) => !targets || targets[name] !== false;
507
+ function cleanupMarkedUnifiedArtifacts(u, paths) {
508
+ const p = paths || buildAgentInstallPaths(true, process.cwd());
509
+ const targets = u && typeof u === 'object' && u.targets && typeof u.targets === 'object' ? u.targets : null;
510
+ const shouldClean = (name) => !targets || targets[name] !== false;
496
511
 
497
512
  const unlinkQuiet = (filePath) => {
498
513
  if (!fs.existsSync(filePath)) return;
@@ -522,119 +537,119 @@ function cleanupMarkedUnifiedArtifacts(u, paths) {
522
537
  }
523
538
  };
524
539
 
525
- if (shouldClean('opencode')) {
526
- for (const dir of p.opencodeCommandDirs) {
527
- if (!fs.existsSync(dir)) continue;
528
- for (const name of fs.readdirSync(dir)) {
529
- if (!isOxeCommandMarkdownName(name)) continue;
530
- const filePath = path.join(dir, name);
531
- let txt = '';
532
- try {
533
- txt = fs.readFileSync(filePath, 'utf8');
534
- } catch {
535
- continue;
536
- }
537
- if (txt.includes(OXE_MANAGED_HTML)) unlinkQuiet(filePath);
538
- }
539
- }
540
- }
541
-
542
- if (shouldClean('gemini')) {
543
- const gBase = p.geminiCommandsBase;
544
- const oxeToml = path.join(gBase, 'oxe.toml');
545
- if (fs.existsSync(oxeToml)) {
546
- try {
547
- if (fs.readFileSync(oxeToml, 'utf8').includes(OXE_MANAGED_TOML)) unlinkQuiet(oxeToml);
548
- } catch {
549
- /* ignore */
550
- }
551
- }
552
- const oxeSub = path.join(gBase, 'oxe');
553
- if (fs.existsSync(oxeSub)) {
554
- for (const name of fs.readdirSync(oxeSub)) {
555
- if (!name.endsWith('.toml')) continue;
556
- const filePath = path.join(oxeSub, name);
557
- try {
558
- if (fs.readFileSync(filePath, 'utf8').includes(OXE_MANAGED_TOML)) unlinkQuiet(filePath);
559
- } catch {
560
- /* ignore */
561
- }
562
- }
563
- try {
564
- if (!u.dryRun && fs.existsSync(oxeSub) && fs.readdirSync(oxeSub).length === 0) fs.rmdirSync(oxeSub);
565
- } catch {
566
- /* ignore */
567
- }
568
- }
569
- }
570
-
571
- if (shouldClean('windsurf')) {
572
- const wfDir = p.windsurfWorkflowsDir;
573
- if (fs.existsSync(wfDir)) {
574
- for (const name of fs.readdirSync(wfDir)) {
575
- if (!isOxeCommandMarkdownName(name)) continue;
576
- const filePath = path.join(wfDir, name);
577
- try {
578
- if (fs.readFileSync(filePath, 'utf8').includes(OXE_MANAGED_HTML)) unlinkQuiet(filePath);
579
- } catch {
580
- /* ignore */
581
- }
582
- }
583
- }
584
- }
585
-
586
- if (shouldClean('codex')) {
587
- const cpDir = p.codexPromptsDir;
588
- if (fs.existsSync(cpDir)) {
589
- for (const name of fs.readdirSync(cpDir)) {
590
- if (!isOxeCommandMarkdownName(name)) continue;
591
- const filePath = path.join(cpDir, name);
592
- try {
593
- if (fs.readFileSync(filePath, 'utf8').includes(OXE_MANAGED_HTML)) unlinkQuiet(filePath);
594
- } catch {
595
- /* ignore */
596
- }
597
- }
598
- }
599
- }
600
-
601
- if (shouldClean('claude')) {
602
- const clAgents = p.claudeAgentsDir;
603
- if (fs.existsSync(clAgents)) {
604
- for (const name of fs.readdirSync(clAgents)) {
605
- if (!isOxeAgentMarkdownName(name)) continue;
606
- const filePath = path.join(clAgents, name);
607
- try {
608
- if (fs.readFileSync(filePath, 'utf8').includes(OXE_MANAGED_HTML)) unlinkQuiet(filePath);
609
- } catch {
610
- /* ignore */
611
- }
612
- }
613
- }
614
- }
615
-
616
- if (shouldClean('antigravity')) {
617
- const agRoot = p.antigravitySkillsRoot;
618
- if (fs.existsSync(agRoot)) {
619
- for (const name of fs.readdirSync(agRoot, { withFileTypes: true })) {
620
- if (!name.isDirectory()) continue;
621
- if (!/^oxe($|-)/.test(name.name)) continue;
622
- rmDirIfOxeSkill(path.join(agRoot, name.name));
623
- }
624
- }
625
- }
626
-
627
- if (shouldClean('codex')) {
628
- const cxRoot = p.codexAgentsSkillsRoot;
629
- if (fs.existsSync(cxRoot)) {
630
- for (const name of fs.readdirSync(cxRoot, { withFileTypes: true })) {
631
- if (!name.isDirectory()) continue;
632
- if (!/^oxe($|-)/.test(name.name)) continue;
633
- rmDirIfOxeSkill(path.join(cxRoot, name.name));
634
- }
635
- }
636
- }
637
- }
540
+ if (shouldClean('opencode')) {
541
+ for (const dir of p.opencodeCommandDirs) {
542
+ if (!fs.existsSync(dir)) continue;
543
+ for (const name of fs.readdirSync(dir)) {
544
+ if (!isOxeCommandMarkdownName(name)) continue;
545
+ const filePath = path.join(dir, name);
546
+ let txt = '';
547
+ try {
548
+ txt = fs.readFileSync(filePath, 'utf8');
549
+ } catch {
550
+ continue;
551
+ }
552
+ if (txt.includes(OXE_MANAGED_HTML)) unlinkQuiet(filePath);
553
+ }
554
+ }
555
+ }
556
+
557
+ if (shouldClean('gemini')) {
558
+ const gBase = p.geminiCommandsBase;
559
+ const oxeToml = path.join(gBase, 'oxe.toml');
560
+ if (fs.existsSync(oxeToml)) {
561
+ try {
562
+ if (fs.readFileSync(oxeToml, 'utf8').includes(OXE_MANAGED_TOML)) unlinkQuiet(oxeToml);
563
+ } catch {
564
+ /* ignore */
565
+ }
566
+ }
567
+ const oxeSub = path.join(gBase, 'oxe');
568
+ if (fs.existsSync(oxeSub)) {
569
+ for (const name of fs.readdirSync(oxeSub)) {
570
+ if (!name.endsWith('.toml')) continue;
571
+ const filePath = path.join(oxeSub, name);
572
+ try {
573
+ if (fs.readFileSync(filePath, 'utf8').includes(OXE_MANAGED_TOML)) unlinkQuiet(filePath);
574
+ } catch {
575
+ /* ignore */
576
+ }
577
+ }
578
+ try {
579
+ if (!u.dryRun && fs.existsSync(oxeSub) && fs.readdirSync(oxeSub).length === 0) fs.rmdirSync(oxeSub);
580
+ } catch {
581
+ /* ignore */
582
+ }
583
+ }
584
+ }
585
+
586
+ if (shouldClean('windsurf')) {
587
+ const wfDir = p.windsurfWorkflowsDir;
588
+ if (fs.existsSync(wfDir)) {
589
+ for (const name of fs.readdirSync(wfDir)) {
590
+ if (!isOxeCommandMarkdownName(name)) continue;
591
+ const filePath = path.join(wfDir, name);
592
+ try {
593
+ if (fs.readFileSync(filePath, 'utf8').includes(OXE_MANAGED_HTML)) unlinkQuiet(filePath);
594
+ } catch {
595
+ /* ignore */
596
+ }
597
+ }
598
+ }
599
+ }
600
+
601
+ if (shouldClean('codex')) {
602
+ const cpDir = p.codexPromptsDir;
603
+ if (fs.existsSync(cpDir)) {
604
+ for (const name of fs.readdirSync(cpDir)) {
605
+ if (!isOxeCommandMarkdownName(name)) continue;
606
+ const filePath = path.join(cpDir, name);
607
+ try {
608
+ if (fs.readFileSync(filePath, 'utf8').includes(OXE_MANAGED_HTML)) unlinkQuiet(filePath);
609
+ } catch {
610
+ /* ignore */
611
+ }
612
+ }
613
+ }
614
+ }
615
+
616
+ if (shouldClean('claude')) {
617
+ const clAgents = p.claudeAgentsDir;
618
+ if (fs.existsSync(clAgents)) {
619
+ for (const name of fs.readdirSync(clAgents)) {
620
+ if (!isOxeAgentMarkdownName(name)) continue;
621
+ const filePath = path.join(clAgents, name);
622
+ try {
623
+ if (fs.readFileSync(filePath, 'utf8').includes(OXE_MANAGED_HTML)) unlinkQuiet(filePath);
624
+ } catch {
625
+ /* ignore */
626
+ }
627
+ }
628
+ }
629
+ }
630
+
631
+ if (shouldClean('antigravity')) {
632
+ const agRoot = p.antigravitySkillsRoot;
633
+ if (fs.existsSync(agRoot)) {
634
+ for (const name of fs.readdirSync(agRoot, { withFileTypes: true })) {
635
+ if (!name.isDirectory()) continue;
636
+ if (!/^oxe($|-)/.test(name.name)) continue;
637
+ rmDirIfOxeSkill(path.join(agRoot, name.name));
638
+ }
639
+ }
640
+ }
641
+
642
+ if (shouldClean('codex')) {
643
+ const cxRoot = p.codexAgentsSkillsRoot;
644
+ if (fs.existsSync(cxRoot)) {
645
+ for (const name of fs.readdirSync(cxRoot, { withFileTypes: true })) {
646
+ if (!name.isDirectory()) continue;
647
+ if (!/^oxe($|-)/.test(name.name)) continue;
648
+ rmDirIfOxeSkill(path.join(cxRoot, name.name));
649
+ }
650
+ }
651
+ }
652
+ }
638
653
 
639
654
  module.exports = {
640
655
  OXE_MANAGED_HTML,
@@ -645,18 +660,18 @@ module.exports = {
645
660
  buildAgentSkillMarkdown,
646
661
  installSkillTreeFromCursorCommands,
647
662
  installOpenCodeCommands,
648
- installGeminiTomlCommands,
649
- installWindsurfGlobalWorkflows,
650
- installCodexPrompts,
651
- installCanonicalAgentMarkdowns,
652
- installCanonicalAgentSkills,
653
- opencodeCommandDirs,
663
+ installGeminiTomlCommands,
664
+ installWindsurfGlobalWorkflows,
665
+ installCodexPrompts,
666
+ installCanonicalAgentMarkdowns,
667
+ installCanonicalAgentSkills,
668
+ opencodeCommandDirs,
654
669
  windsurfGlobalWorkflowsDir,
655
670
  geminiUserDir,
656
671
  codexAgentsSkillsRoot,
657
672
  codexPromptsDir,
658
- antigravitySkillsRoot,
659
- isOxeCommandMarkdownName,
660
- isOxeAgentMarkdownName,
661
- cleanupMarkedUnifiedArtifacts,
662
- };
673
+ antigravitySkillsRoot,
674
+ isOxeCommandMarkdownName,
675
+ isOxeAgentMarkdownName,
676
+ cleanupMarkedUnifiedArtifacts,
677
+ };