oxe-cc 1.4.1 → 1.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 (36) hide show
  1. package/.cursor/commands/oxe-verify-audit.md +46 -0
  2. package/.cursor/commands/oxe-workflow-authoring.md +47 -0
  3. package/.github/prompts/oxe-compact.prompt.md +1 -1
  4. package/.github/prompts/oxe-plan-agent.prompt.md +1 -0
  5. package/.github/prompts/oxe-verify-audit.prompt.md +46 -0
  6. package/.github/prompts/oxe-workflow-authoring.prompt.md +47 -0
  7. package/.github/workflows/ci.yml +1 -0
  8. package/.github/workflows/release.yml +1 -0
  9. package/AGENTS.md +3 -1
  10. package/CHANGELOG.md +25 -0
  11. package/QUICKSTART.md +99 -0
  12. package/README.md +19 -10
  13. package/bin/lib/oxe-install-resolve.cjs +10 -0
  14. package/bin/lib/oxe-operational.cjs +34 -28
  15. package/bin/lib/oxe-project-health.cjs +38 -6
  16. package/bin/lib/oxe-release.cjs +423 -0
  17. package/bin/oxe-cc.js +389 -294
  18. package/commands/oxe/verify-audit.md +50 -0
  19. package/commands/oxe/workflow-authoring.md +50 -0
  20. package/docs/INCIDENT-PLAYBOOK.md +181 -0
  21. package/docs/RELEASE-READINESS.md +46 -0
  22. package/docs/ROLES.md +129 -0
  23. package/docs/RUNTIME-SMOKE-MATRIX.md +128 -0
  24. package/docs/TEAM-ADOPTION.md +153 -0
  25. package/docs/WALKTHROUGH.md +241 -0
  26. package/lib/runtime/scheduler/multi-agent-coordinator.d.ts +28 -0
  27. package/lib/runtime/scheduler/multi-agent-coordinator.js +152 -26
  28. package/lib/sdk/README.md +2 -0
  29. package/lib/sdk/index.cjs +22 -8
  30. package/lib/sdk/index.d.ts +60 -16
  31. package/oxe/templates/config.template.json +1 -0
  32. package/package.json +28 -20
  33. package/packages/runtime/package.json +1 -1
  34. package/packages/runtime/src/scheduler/multi-agent-coordinator.ts +357 -193
  35. package/vscode-extension/oxe-agents-1.5.0.vsix +0 -0
  36. package/vscode-extension/package.json +1 -1
package/bin/oxe-cc.js CHANGED
@@ -24,6 +24,7 @@ const oxeAzure = require(path.join(__dirname, 'lib', 'oxe-azure.cjs'));
24
24
  const oxePlugins = require(path.join(__dirname, 'lib', 'oxe-plugins.cjs'));
25
25
  const oxeContext = require(path.join(__dirname, 'lib', 'oxe-context-engine.cjs'));
26
26
  const oxeRuntimeSemantics = require(path.join(__dirname, 'lib', 'oxe-runtime-semantics.cjs'));
27
+ const oxeRelease = require(path.join(__dirname, 'lib', 'oxe-release.cjs'));
27
28
 
28
29
  /** Merge markers for ~/.copilot/copilot-instructions.md (bloco OXE). */
29
30
  const OXE_INST_BEGIN = '<!-- oxe-cc:install-begin -->';
@@ -247,35 +248,35 @@ function buildInstallSummary(opts, fullLayout) {
247
248
  /**
248
249
  * @param {UninstallOpts} u
249
250
  */
250
- function buildUninstallFooter(u) {
251
- const bullets = [];
252
- const p = u.dryRun ? '[simulação] ' : '';
253
- const rm = u.dryRun ? 'Seriam removidos' : 'Removidos';
254
- const granularAgents = [
255
- u.agentOpenCode ? 'OpenCode' : null,
256
- u.agentGemini ? 'Gemini' : null,
257
- u.agentCodex ? 'Codex' : null,
258
- u.agentWindsurf ? 'Windsurf' : null,
259
- u.agentAntigravity ? 'Antigravity' : null,
260
- ].filter(Boolean);
261
- if (u.cursor) bullets.push(`${p}${rm} artefatos OXE em ~/.cursor (comandos e regras).`);
262
- if (u.copilot) {
263
- bullets.push(`${p}${rm} prompt files OXE em .github/prompts/ e o bloco OXE em .github/copilot-instructions.md.`);
264
- }
251
+ function buildUninstallFooter(u) {
252
+ const bullets = [];
253
+ const p = u.dryRun ? '[simulação] ' : '';
254
+ const rm = u.dryRun ? 'Seriam removidos' : 'Removidos';
255
+ const granularAgents = [
256
+ u.agentOpenCode ? 'OpenCode' : null,
257
+ u.agentGemini ? 'Gemini' : null,
258
+ u.agentCodex ? 'Codex' : null,
259
+ u.agentWindsurf ? 'Windsurf' : null,
260
+ u.agentAntigravity ? 'Antigravity' : null,
261
+ ].filter(Boolean);
262
+ if (u.cursor) bullets.push(`${p}${rm} artefatos OXE em ~/.cursor (comandos e regras).`);
263
+ if (u.copilot) {
264
+ bullets.push(`${p}${rm} prompt files OXE em .github/prompts/ e o bloco OXE em .github/copilot-instructions.md.`);
265
+ }
265
266
  if (u.copilotLegacyClean) {
266
267
  bullets.push(`${p}${rm} apenas o legado global do Copilot VS Code em ~/.copilot/ (prompts oxe-* e bloco OXE global).`);
267
268
  }
268
- if (u.copilotCli) {
269
- bullets.push(`${p}${rm} comandos oxe/oxe-* em ~/.claude/commands e ~/.copilot/commands.`);
270
- bullets.push(`${p}${rm} skills OXE (marcadas oxe-cc) em ~/.copilot/skills/oxe*/.`);
271
- }
272
- if (u.allAgents) {
273
- bullets.push(
274
- `${p}${rm} extensões multi-agente marcadas oxe-cc (OpenCode, Gemini TOML, Windsurf workflows, Codex prompts/skills, Antigravity), se existirem.`
275
- );
276
- } else if (granularAgents.length) {
277
- bullets.push(`${p}${rm} apenas as integrações selecionadas: ${granularAgents.join(', ')}.`);
278
- }
269
+ if (u.copilotCli) {
270
+ bullets.push(`${p}${rm} comandos oxe/oxe-* em ~/.claude/commands e ~/.copilot/commands.`);
271
+ bullets.push(`${p}${rm} skills OXE (marcadas oxe-cc) em ~/.copilot/skills/oxe*/.`);
272
+ }
273
+ if (u.allAgents) {
274
+ bullets.push(
275
+ `${p}${rm} extensões multi-agente marcadas oxe-cc (OpenCode, Gemini TOML, Windsurf workflows, Codex prompts/skills, Antigravity), se existirem.`
276
+ );
277
+ } else if (granularAgents.length) {
278
+ bullets.push(`${p}${rm} apenas as integrações selecionadas: ${granularAgents.join(', ')}.`);
279
+ }
279
280
  if (u.ideLocal) {
280
281
  bullets.push(
281
282
  `${p}${rm} integrações OXE no repositório (.cursor, .github, .claude, .copilot, .opencode, … conforme flags).`
@@ -296,29 +297,29 @@ function buildUninstallFooter(u) {
296
297
  return { bullets, nextSteps, dryRun: u.dryRun };
297
298
  }
298
299
 
299
- /** @typedef {{ help: boolean, version: boolean, cursor: boolean, copilot: boolean, copilotCli: boolean, allAgents: boolean, agentOpenCode: boolean, agentGemini: boolean, agentCodex: boolean, agentWindsurf: boolean, agentAntigravity: boolean, vscode: boolean, commands: boolean, agents: boolean, force: boolean, dryRun: boolean, dir: string, all: boolean, noInitOxe: boolean, oxeOnly: boolean, globalCli: boolean, noGlobalCli: boolean, installAssetsGlobal: boolean, explicitScope: boolean, integrationsUnset: boolean, ideLocal: boolean, explicitIdeScope: boolean, explicitConfigDir: string | null, parseError: boolean, unknownFlag: string, conflictFlags: string, ignoreInstallConfig: boolean }} InstallOpts */
300
-
301
- /** @param {InstallOpts} o */
302
- function anyGranularAgent(o) {
303
- return !!(o.agentOpenCode || o.agentGemini || o.agentCodex || o.agentWindsurf || o.agentAntigravity);
304
- }
305
-
306
- /** @param {UninstallOpts} o */
307
- function anyGranularUninstallAgent(o) {
308
- return !!(o.agentOpenCode || o.agentGemini || o.agentCodex || o.agentWindsurf || o.agentAntigravity);
309
- }
310
-
311
- /** @param {UninstallOpts} u */
312
- function buildAgentCleanupTargets(u) {
313
- if (u.allAgents || !anyGranularUninstallAgent(u)) return null;
314
- return {
315
- opencode: Boolean(u.agentOpenCode),
316
- gemini: Boolean(u.agentGemini),
317
- windsurf: Boolean(u.agentWindsurf),
318
- codex: Boolean(u.agentCodex),
319
- antigravity: Boolean(u.agentAntigravity),
320
- };
321
- }
300
+ /** @typedef {{ help: boolean, version: boolean, cursor: boolean, copilot: boolean, copilotCli: boolean, allAgents: boolean, agentOpenCode: boolean, agentGemini: boolean, agentCodex: boolean, agentWindsurf: boolean, agentAntigravity: boolean, vscode: boolean, commands: boolean, agents: boolean, force: boolean, dryRun: boolean, dir: string, all: boolean, noInitOxe: boolean, oxeOnly: boolean, globalCli: boolean, noGlobalCli: boolean, installAssetsGlobal: boolean, explicitScope: boolean, integrationsUnset: boolean, ideLocal: boolean, explicitIdeScope: boolean, explicitConfigDir: string | null, parseError: boolean, unknownFlag: string, conflictFlags: string, ignoreInstallConfig: boolean, releaseDoctor: boolean, writeManifest: boolean }} InstallOpts */
301
+
302
+ /** @param {InstallOpts} o */
303
+ function anyGranularAgent(o) {
304
+ return !!(o.agentOpenCode || o.agentGemini || o.agentCodex || o.agentWindsurf || o.agentAntigravity);
305
+ }
306
+
307
+ /** @param {UninstallOpts} o */
308
+ function anyGranularUninstallAgent(o) {
309
+ return !!(o.agentOpenCode || o.agentGemini || o.agentCodex || o.agentWindsurf || o.agentAntigravity);
310
+ }
311
+
312
+ /** @param {UninstallOpts} u */
313
+ function buildAgentCleanupTargets(u) {
314
+ if (u.allAgents || !anyGranularUninstallAgent(u)) return null;
315
+ return {
316
+ opencode: Boolean(u.agentOpenCode),
317
+ gemini: Boolean(u.agentGemini),
318
+ windsurf: Boolean(u.agentWindsurf),
319
+ codex: Boolean(u.agentCodex),
320
+ antigravity: Boolean(u.agentAntigravity),
321
+ };
322
+ }
322
323
 
323
324
  /** @param {InstallOpts} o */
324
325
  function anyIdeIntegration(o) {
@@ -364,6 +365,8 @@ function parseInstallArgs(argv) {
364
365
  unknownFlag: '',
365
366
  conflictFlags: '',
366
367
  ignoreInstallConfig: false,
368
+ releaseDoctor: false,
369
+ writeManifest: false,
367
370
  /** Saída JSON em `status` (CI / agentes). */
368
371
  jsonOutput: false,
369
372
  /** Lembretes agregados scan/compact em `status`. */
@@ -415,6 +418,8 @@ function parseInstallArgs(argv) {
415
418
  } else if (a === '--json') out.jsonOutput = true;
416
419
  else if (a === '--hints') out.statusHints = true;
417
420
  else if (a === '--full') out.statusFull = true;
421
+ else if (a === '--release') out.releaseDoctor = true;
422
+ else if (a === '--write-manifest') out.writeManifest = true;
418
423
  else if (!a.startsWith('-')) out.restPositional.push(a);
419
424
  else {
420
425
  out.parseError = true;
@@ -457,6 +462,14 @@ function parseInstallArgs(argv) {
457
462
  out.agentWindsurf = true;
458
463
  out.agentAntigravity = true;
459
464
  }
465
+ if (!out.conflictFlags && out.oxeOnly) {
466
+ const IDE_FLAGS = ['--cursor', '--copilot', '--copilot-vscode', '--copilot-cli', '--all-agents',
467
+ '--opencode', '--gemini', '--codex', '--windsurf', '--antigravity', '--vscode'];
468
+ const conflicting = IDE_FLAGS.filter((f) => argv.includes(f));
469
+ if (conflicting.length > 0) {
470
+ out.conflictFlags = `--oxe-only não combina com flags de IDE (${conflicting.join(', ')})`;
471
+ }
472
+ }
460
473
  if (out.oxeOnly) {
461
474
  out.cursor = false;
462
475
  out.copilot = false;
@@ -777,7 +790,11 @@ function writeCopilotVsCodeManifest(opts, info) {
777
790
  const promptFiles = fs.existsSync(promptsDir)
778
791
  ? fs
779
792
  .readdirSync(promptsDir, { withFileTypes: true })
780
- .filter((entry) => entry.isFile() && /^oxe-.*\.prompt\.md$/i.test(entry.name))
793
+ .filter(
794
+ (entry) =>
795
+ entry.isFile() &&
796
+ (entry.name === 'oxe.prompt.md' || /^oxe-.*\.prompt\.md$/i.test(entry.name))
797
+ )
781
798
  .map((entry) => entry.name)
782
799
  .sort()
783
800
  : [];
@@ -1038,6 +1055,27 @@ async function promptInstallScope(opts) {
1038
1055
  }
1039
1056
  }
1040
1057
 
1058
+ /**
1059
+ * Grava a escolha resolvida de ide_scope de volta em .oxe/config.json para que
1060
+ * futuras reinstalações/updates não precisem perguntar novamente.
1061
+ * @param {InstallOpts} opts
1062
+ */
1063
+ function persistIdeScope(opts) {
1064
+ if (opts.dryRun || opts.oxeOnly) return;
1065
+ const configPath = path.join(opts.dir, '.oxe', 'config.json');
1066
+ if (!fs.existsSync(configPath)) return;
1067
+ try {
1068
+ const cfg = JSON.parse(fs.readFileSync(configPath, 'utf8'));
1069
+ const scope = opts.ideLocal ? 'local' : 'global';
1070
+ if (!cfg.install || typeof cfg.install !== 'object') cfg.install = {};
1071
+ if (cfg.install.ide_scope === scope) return;
1072
+ cfg.install.ide_scope = scope;
1073
+ fs.writeFileSync(configPath, JSON.stringify(cfg, null, 2) + '\n', 'utf8');
1074
+ } catch {
1075
+ /* silêncio — não bloquear instalação por falha ao persistir config */
1076
+ }
1077
+ }
1078
+
1041
1079
  /** @param {InstallOpts} opts */
1042
1080
  async function resolveInteractiveInstall(opts) {
1043
1081
  if (!opts.ignoreInstallConfig) {
@@ -1280,7 +1318,13 @@ function bootstrapOxe(target, opts) {
1280
1318
 
1281
1319
  if (fs.existsSync(configSrc)) {
1282
1320
  if (!fs.existsSync(configDest) || opts.force) {
1283
- copyFile(configSrc, configDest, { dryRun: false });
1321
+ try {
1322
+ const cfgRaw = JSON.parse(fs.readFileSync(configSrc, 'utf8'));
1323
+ delete cfgRaw._comment;
1324
+ fs.writeFileSync(configDest, JSON.stringify(cfgRaw, null, 2) + '\n', 'utf8');
1325
+ } catch {
1326
+ copyFile(configSrc, configDest, { dryRun: false });
1327
+ }
1284
1328
  console.log(`${green}init${reset} ${configDest}`);
1285
1329
  } else {
1286
1330
  console.log(`${dim}omitido${reset} ${configDest} (já existe — use --force para substituir)`);
@@ -1926,7 +1970,46 @@ function runStatus(target, opts = {}) {
1926
1970
  }
1927
1971
 
1928
1972
  /** @param {string} target */
1929
- function runDoctor(target) {
1973
+ function runDoctor(target, options = {}) {
1974
+ if (options.release) {
1975
+ if (!options.json) printSection('OXE ▸ doctor --release');
1976
+ const c = useAnsiColors();
1977
+ const result = oxeRelease.checkReleaseConsistency(target, {
1978
+ packageRoot: PKG_ROOT,
1979
+ writeManifest: Boolean(options.writeManifest),
1980
+ });
1981
+ if (options.json) {
1982
+ console.log(
1983
+ JSON.stringify(
1984
+ {
1985
+ status: result.ok ? 'ok' : 'blocked',
1986
+ blockers: result.blockers,
1987
+ warnings: result.warnings,
1988
+ manifestPath: result.manifestPath,
1989
+ manifest: result.manifest,
1990
+ },
1991
+ null,
1992
+ 2
1993
+ )
1994
+ );
1995
+ } else {
1996
+ console.log(` ${c ? green : ''}Projeto:${c ? reset : ''} ${c ? cyan : ''}${target}${c ? reset : ''}`);
1997
+ console.log(` ${c ? green : ''}Versão alvo:${c ? reset : ''} ${result.manifest.versions.rootPackage.version || '—'}`);
1998
+ console.log(` ${c ? green : ''}Manifest:${c ? reset : ''} ${result.manifestPath}`);
1999
+ if (result.ok) {
2000
+ console.log(` ${c ? green : ''}✓${c ? reset : ''} release readiness OK`);
2001
+ } else {
2002
+ console.log(` ${c ? red : ''}✗${c ? reset : ''} release readiness bloqueada`);
2003
+ for (const blocker of result.blockers) {
2004
+ console.log(` - ${blocker}`);
2005
+ }
2006
+ }
2007
+ for (const warning of result.warnings) {
2008
+ console.log(` ${c ? yellow : ''}!${c ? reset : ''} ${warning}`);
2009
+ }
2010
+ }
2011
+ process.exit(result.ok ? 0 : 1);
2012
+ }
1930
2013
  printSection('OXE ▸ doctor');
1931
2014
  const v = process.versions.node;
1932
2015
  const major = parseInt(v.split('.')[0], 10);
@@ -2147,6 +2230,12 @@ function installGlobalCliPackage() {
2147
2230
  shell: true,
2148
2231
  env: process.env,
2149
2232
  });
2233
+ if (r.error) {
2234
+ console.log(
2235
+ `\n ${c ? yellow : ''}⚠${c ? reset : ''} npm install -g falhou (${r.error.message}). Tente manualmente: ${c ? cyan : ''}npm install -g ${spec}${c ? reset : ''}\n`
2236
+ );
2237
+ return false;
2238
+ }
2150
2239
  if (r.status === 0) {
2151
2240
  console.log(
2152
2241
  `\n ${c ? green : ''}✓${c ? reset : ''} ${c ? cyan : ''}oxe-cc${c ? reset : ''} disponível globalmente (execute ${c ? cyan : ''}oxe-cc --help${c ? reset : ''} em qualquer pasta).\n`
@@ -2328,34 +2417,39 @@ function usage() {
2328
2417
  console.log(`
2329
2418
  ${cyan}oxe-cc${reset} — instala workflows OXE (núcleo .oxe/ + integrações: Cursor, Copilot, Claude, OpenCode, Gemini, Codex, Windsurf, Antigravity, …)
2330
2419
 
2331
- ${green}Uso:${reset}
2332
- npx oxe-cc@latest [opções] [pasta-do-projeto]
2333
- npx oxe-cc@latest install [opções] [pasta-do-projeto] ${dim}(equivalente à instalação predefinida)${reset}
2334
- npx oxe-cc@latest --dir /caminho/do/projeto
2335
- npx oxe-cc doctor [opções] [pasta-do-projeto]
2336
- npx oxe-cc status [opções] [pasta-do-projeto]
2337
- npx oxe-cc init-oxe [opções] [pasta-do-projeto]
2338
- npx oxe-cc context <build|inspect> [opções] [pasta-do-projeto]
2339
- npx oxe-cc dashboard [opções] [pasta-do-projeto]
2340
- npx oxe-cc runtime <status|start|pause|resume|replay|compile|verify|project|ci|promote|recover|gates> [opções] [pasta-do-projeto]
2341
- npx oxe-cc azure <status|doctor|auth|sync|find|servicebus|eventgrid|sql|operations> [opções] [pasta-do-projeto]
2342
- npx oxe-cc capabilities <list|install|remove|update> [opções] [id]
2343
- npx oxe-cc uninstall [opções] [pasta-do-projeto]
2344
- npx oxe-cc update [opções] [argumentos extras…]
2345
-
2346
- ${green}uninstall${reset} (remove OXE da pasta do usuário + pastas de workflows no repo)
2347
- --cursor / --copilot / --copilot-cli só essa integração (omissão = todas)
2348
- --copilot-vscode alias explícito de --copilot
2349
- --copilot-legacy-clean limpa o legado antigo do Copilot VS Code em ~/.copilot/
2350
- --all-agents também remove ficheiros multi-plataforma (com --copilot-cli implícito)
2351
- --opencode / --gemini / --codex / --windsurf / --antigravity
2352
- removeesse agente multi-runtime
2353
- --ide-local remove integrações IDE neste repositório (.cursor, .github, .claude, .copilot, …)
2354
- --ide-only não apagar .oxe/workflows, oxe/, etc. no projeto
2355
- --global-cli, -g também executa npm uninstall -g oxe-cc
2356
- --config-dir <caminho> com exatamente uma flag IDE acima (não combina com --ide-local, --copilot nem agentes granulares)
2357
- --dry-run
2358
- --dir <pasta> raiz do projeto (padrão: diretório atual)
2420
+ ${green}Uso:${reset}
2421
+ npx oxe-cc@latest [opções] [pasta-do-projeto]
2422
+ npx oxe-cc@latest install [opções] [pasta-do-projeto] ${dim}(equivalente à instalação predefinida)${reset}
2423
+ npx oxe-cc@latest --dir /caminho/do/projeto
2424
+ npx oxe-cc doctor [--release] [--write-manifest] [opções] [pasta-do-projeto]
2425
+ npx oxe-cc status [opções] [pasta-do-projeto]
2426
+ npx oxe-cc init-oxe [opções] [pasta-do-projeto]
2427
+ npx oxe-cc context <build|inspect> [opções] [pasta-do-projeto]
2428
+ npx oxe-cc dashboard [opções] [pasta-do-projeto]
2429
+ npx oxe-cc runtime <status|start|pause|resume|replay|compile|verify|project|ci|promote|recover|gates|agents> [opções] [pasta-do-projeto]
2430
+ npx oxe-cc azure <status|doctor|auth|sync|find|servicebus|eventgrid|sql|operations> [opções] [pasta-do-projeto]
2431
+ npx oxe-cc capabilities <list|install|remove|update> [opções] [id]
2432
+ npx oxe-cc uninstall [opções] [pasta-do-projeto]
2433
+ npx oxe-cc update [opções] [argumentos extras…]
2434
+
2435
+ ${green}doctor${reset}
2436
+ --release valida release readiness: versões, changelog, wrappers, runtime build e relatórios obrigatórios
2437
+ --write-manifest persiste .oxe/release/release-manifest.json durante doctor --release
2438
+ --json saída estruturada para CI
2439
+
2440
+ ${green}uninstall${reset} (remove OXE da pasta do usuário + pastas de workflows no repo)
2441
+ --cursor / --copilot / --copilot-cli essa integração (omissão = todas)
2442
+ --copilot-vscode alias explícito de --copilot
2443
+ --copilot-legacy-clean limpa o legado antigo do Copilot VS Code em ~/.copilot/
2444
+ --all-agents também remove ficheiros multi-plataforma (com --copilot-cli implícito)
2445
+ --opencode / --gemini / --codex / --windsurf / --antigravity
2446
+ remove só esse agente multi-runtime
2447
+ --ide-local remove integrações IDE neste repositório (.cursor, .github, .claude, .copilot, …)
2448
+ --ide-only não apagar .oxe/workflows, oxe/, etc. no projeto
2449
+ --global-cli, -g também executa npm uninstall -g oxe-cc
2450
+ --config-dir <caminho> com exatamente uma flag IDE acima (não combina com --ide-local, --copilot nem agentes granulares)
2451
+ --dry-run
2452
+ --dir <pasta> raiz do projeto (padrão: diretório atual)
2359
2453
 
2360
2454
  ${green}update${reset} (executa npx oxe-cc@latest --force na pasta do projeto)
2361
2455
  --check só consulta npm: compara versão em execução com latest (saída 0=ok, 1=há mais nova, 2=erro; incompatível com --dry-run)
@@ -2748,11 +2842,11 @@ function runInstall(opts) {
2748
2842
  addTracked(copilotPromptsDirPath(opts), (n) => n.startsWith('oxe-'));
2749
2843
  trackFile(copilotWorkspaceManifestPath(opts));
2750
2844
  }
2751
- trackFile(runtimeSemanticsManifestPath(opts));
2752
- if (opts.copilotCli || opts.allAgents) {
2753
- addTracked(path.join(installClaudeBase(opts), 'commands'), (n) => oxeAgentInstall.isOxeCommandMarkdownName(n));
2754
- addTracked(path.join(cpCliHome, 'commands'), (n) => oxeAgentInstall.isOxeCommandMarkdownName(n));
2755
- const skRoot = path.join(cpCliHome, 'skills');
2845
+ trackFile(runtimeSemanticsManifestPath(opts));
2846
+ if (opts.copilotCli || opts.allAgents) {
2847
+ addTracked(path.join(installClaudeBase(opts), 'commands'), (n) => oxeAgentInstall.isOxeCommandMarkdownName(n));
2848
+ addTracked(path.join(cpCliHome, 'commands'), (n) => oxeAgentInstall.isOxeCommandMarkdownName(n));
2849
+ const skRoot = path.join(cpCliHome, 'skills');
2756
2850
  if (fs.existsSync(skRoot)) {
2757
2851
  for (const sub of fs.readdirSync(skRoot, { withFileTypes: true })) {
2758
2852
  if (!sub.isDirectory() || !/^oxe($|-)/.test(sub.name)) continue;
@@ -2767,11 +2861,11 @@ function runInstall(opts) {
2767
2861
  }
2768
2862
  }
2769
2863
  }
2770
- if (opts.agentOpenCode || opts.allAgents) {
2771
- for (const d of agentPaths.opencodeCommandDirs) {
2772
- addTracked(d, (n) => oxeAgentInstall.isOxeCommandMarkdownName(n));
2773
- }
2774
- }
2864
+ if (opts.agentOpenCode || opts.allAgents) {
2865
+ for (const d of agentPaths.opencodeCommandDirs) {
2866
+ addTracked(d, (n) => oxeAgentInstall.isOxeCommandMarkdownName(n));
2867
+ }
2868
+ }
2775
2869
  if (opts.agentGemini || opts.allAgents) {
2776
2870
  const gCmd = agentPaths.geminiCommandsBase;
2777
2871
  trackFile(path.join(gCmd, 'oxe.toml'));
@@ -2785,12 +2879,12 @@ function runInstall(opts) {
2785
2879
  if (opts.agentWindsurf || opts.allAgents) {
2786
2880
  addTracked(agentPaths.windsurfWorkflowsDir, (n) => n === 'oxe.md' || (n.startsWith('oxe-') && n.endsWith('.md')));
2787
2881
  }
2788
- if (opts.agentCodex || opts.allAgents) {
2789
- const cxPrompts = agentPaths.codexPromptsDir;
2790
- if (fs.existsSync(cxPrompts)) {
2791
- addTracked(cxPrompts, (n) => oxeAgentInstall.isOxeCommandMarkdownName(n));
2792
- }
2793
- }
2882
+ if (opts.agentCodex || opts.allAgents) {
2883
+ const cxPrompts = agentPaths.codexPromptsDir;
2884
+ if (fs.existsSync(cxPrompts)) {
2885
+ addTracked(cxPrompts, (n) => oxeAgentInstall.isOxeCommandMarkdownName(n));
2886
+ }
2887
+ }
2794
2888
  if (opts.agentAntigravity || opts.allAgents) {
2795
2889
  const root = agentPaths.antigravitySkillsRoot;
2796
2890
  if (fs.existsSync(root)) {
@@ -2833,26 +2927,26 @@ function runInstall(opts) {
2833
2927
  console.log(` ${c ? green : ''}✓${c ? reset : ''} Instalação concluída com sucesso.\n`);
2834
2928
  }
2835
2929
 
2836
- /** @typedef {{ help: boolean, dryRun: boolean, cursor: boolean, copilot: boolean, copilotCli: boolean, allAgents: boolean, agentOpenCode: boolean, agentGemini: boolean, agentCodex: boolean, agentWindsurf: boolean, agentAntigravity: boolean, globalCli: boolean, ideLocal: boolean, ideExplicit: boolean, noProject: boolean, copilotLegacyClean: boolean, dir: string, explicitConfigDir: string | null, parseError: boolean, unknownFlag: string, conflictFlags: string }} UninstallOpts */
2930
+ /** @typedef {{ help: boolean, dryRun: boolean, cursor: boolean, copilot: boolean, copilotCli: boolean, allAgents: boolean, agentOpenCode: boolean, agentGemini: boolean, agentCodex: boolean, agentWindsurf: boolean, agentAntigravity: boolean, globalCli: boolean, ideLocal: boolean, ideExplicit: boolean, noProject: boolean, copilotLegacyClean: boolean, dir: string, explicitConfigDir: string | null, parseError: boolean, unknownFlag: string, conflictFlags: string }} UninstallOpts */
2837
2931
 
2838
2932
  /**
2839
2933
  * @param {UninstallOpts} u
2840
2934
  * @param {string[]} removedPaths
2841
2935
  */
2842
- function uninstallLocalIdeFromProject(u, removedPaths) {
2843
- const proj = path.resolve(u.dir);
2844
- const track = (p) => {
2845
- if (removedPaths.indexOf(p) === -1) removedPaths.push(p);
2846
- };
2847
-
2848
- if (u.cursor) {
2849
- const cmdDir = path.join(proj, '.cursor', 'commands');
2850
- if (fs.existsSync(cmdDir)) {
2851
- for (const name of fs.readdirSync(cmdDir)) {
2852
- if (oxeAgentInstall.isOxeCommandMarkdownName(name)) {
2853
- const p = path.join(cmdDir, name);
2854
- unlinkQuiet(p, u);
2855
- track(p);
2936
+ function uninstallLocalIdeFromProject(u, removedPaths) {
2937
+ const proj = path.resolve(u.dir);
2938
+ const track = (p) => {
2939
+ if (removedPaths.indexOf(p) === -1) removedPaths.push(p);
2940
+ };
2941
+
2942
+ if (u.cursor) {
2943
+ const cmdDir = path.join(proj, '.cursor', 'commands');
2944
+ if (fs.existsSync(cmdDir)) {
2945
+ for (const name of fs.readdirSync(cmdDir)) {
2946
+ if (oxeAgentInstall.isOxeCommandMarkdownName(name)) {
2947
+ const p = path.join(cmdDir, name);
2948
+ unlinkQuiet(p, u);
2949
+ track(p);
2856
2950
  }
2857
2951
  }
2858
2952
  }
@@ -2875,7 +2969,7 @@ function uninstallLocalIdeFromProject(u, removedPaths) {
2875
2969
  const pr = path.join(proj, '.github', 'prompts');
2876
2970
  if (fs.existsSync(pr)) {
2877
2971
  for (const name of fs.readdirSync(pr)) {
2878
- if (/^oxe-.*\.prompt\.md$/i.test(name)) {
2972
+ if (name === 'oxe.prompt.md' || /^oxe-.*\.prompt\.md$/i.test(name)) {
2879
2973
  const p = path.join(pr, name);
2880
2974
  unlinkQuiet(p, u);
2881
2975
  track(p);
@@ -2887,15 +2981,15 @@ function uninstallLocalIdeFromProject(u, removedPaths) {
2887
2981
  track(manifest);
2888
2982
  }
2889
2983
 
2890
- if (u.copilotCli || u.allAgents) {
2891
- for (const base of [path.join(proj, '.claude'), path.join(proj, '.copilot')]) {
2892
- const cmdDir = path.join(base, 'commands');
2893
- if (!fs.existsSync(cmdDir)) continue;
2894
- for (const name of fs.readdirSync(cmdDir)) {
2895
- if (oxeAgentInstall.isOxeCommandMarkdownName(name)) {
2896
- const p = path.join(cmdDir, name);
2897
- unlinkQuiet(p, u);
2898
- track(p);
2984
+ if (u.copilotCli || u.allAgents) {
2985
+ for (const base of [path.join(proj, '.claude'), path.join(proj, '.copilot')]) {
2986
+ const cmdDir = path.join(base, 'commands');
2987
+ if (!fs.existsSync(cmdDir)) continue;
2988
+ for (const name of fs.readdirSync(cmdDir)) {
2989
+ if (oxeAgentInstall.isOxeCommandMarkdownName(name)) {
2990
+ const p = path.join(cmdDir, name);
2991
+ unlinkQuiet(p, u);
2992
+ track(p);
2899
2993
  }
2900
2994
  }
2901
2995
  }
@@ -2923,25 +3017,25 @@ function uninstallLocalIdeFromProject(u, removedPaths) {
2923
3017
  }
2924
3018
  }
2925
3019
 
2926
- if (u.allAgents || anyGranularUninstallAgent(u)) {
2927
- const localPaths = oxeAgentInstall.buildAgentInstallPaths(false, proj);
2928
- const cleanupTargets = buildAgentCleanupTargets(u);
2929
- if (!u.dryRun) {
2930
- oxeAgentInstall.cleanupMarkedUnifiedArtifacts({ dryRun: u.dryRun, targets: cleanupTargets }, localPaths);
2931
- } else {
2932
- const label = cleanupTargets
2933
- ? Object.keys(cleanupTargets).filter((key) => cleanupTargets[key]).join(', ')
2934
- : 'OpenCode, Gemini, Windsurf, Codex, Antigravity';
2935
- console.log(`${dim}agents${reset} (dry-run) limparia marcadores oxe-cc em pastas locais do projeto (${label})`);
2936
- }
2937
- }
2938
-
2939
- if (u.cursor || u.copilot || u.copilotCli || u.allAgents || anyGranularUninstallAgent(u)) {
2940
- const runtimeManifest = path.join(proj, '.oxe', 'install', 'runtime-semantics.json');
2941
- unlinkQuiet(runtimeManifest, u);
2942
- track(runtimeManifest);
2943
- }
2944
- }
3020
+ if (u.allAgents || anyGranularUninstallAgent(u)) {
3021
+ const localPaths = oxeAgentInstall.buildAgentInstallPaths(false, proj);
3022
+ const cleanupTargets = buildAgentCleanupTargets(u);
3023
+ if (!u.dryRun) {
3024
+ oxeAgentInstall.cleanupMarkedUnifiedArtifacts({ dryRun: u.dryRun, targets: cleanupTargets }, localPaths);
3025
+ } else {
3026
+ const label = cleanupTargets
3027
+ ? Object.keys(cleanupTargets).filter((key) => cleanupTargets[key]).join(', ')
3028
+ : 'OpenCode, Gemini, Windsurf, Codex, Antigravity';
3029
+ console.log(`${dim}agents${reset} (dry-run) limparia marcadores oxe-cc em pastas locais do projeto (${label})`);
3030
+ }
3031
+ }
3032
+
3033
+ if (u.cursor || u.copilot || u.copilotCli || u.allAgents || anyGranularUninstallAgent(u)) {
3034
+ const runtimeManifest = path.join(proj, '.oxe', 'install', 'runtime-semantics.json');
3035
+ unlinkQuiet(runtimeManifest, u);
3036
+ track(runtimeManifest);
3037
+ }
3038
+ }
2945
3039
 
2946
3040
  /**
2947
3041
  * @param {string[]} argv
@@ -2949,21 +3043,21 @@ function uninstallLocalIdeFromProject(u, removedPaths) {
2949
3043
  */
2950
3044
  function parseUninstallArgs(argv) {
2951
3045
  /** @type {UninstallOpts} */
2952
- const out = {
2953
- help: false,
2954
- dryRun: false,
2955
- cursor: false,
2956
- copilot: false,
2957
- copilotCli: false,
2958
- allAgents: false,
2959
- agentOpenCode: false,
2960
- agentGemini: false,
2961
- agentCodex: false,
2962
- agentWindsurf: false,
2963
- agentAntigravity: false,
2964
- globalCli: false,
2965
- ideLocal: false,
2966
- ideExplicit: false,
3046
+ const out = {
3047
+ help: false,
3048
+ dryRun: false,
3049
+ cursor: false,
3050
+ copilot: false,
3051
+ copilotCli: false,
3052
+ allAgents: false,
3053
+ agentOpenCode: false,
3054
+ agentGemini: false,
3055
+ agentCodex: false,
3056
+ agentWindsurf: false,
3057
+ agentAntigravity: false,
3058
+ globalCli: false,
3059
+ ideLocal: false,
3060
+ ideExplicit: false,
2967
3061
  noProject: false,
2968
3062
  copilotLegacyClean: false,
2969
3063
  dir: process.cwd(),
@@ -2985,35 +3079,35 @@ function parseUninstallArgs(argv) {
2985
3079
  } else if (a === '--copilot' || a === '--copilot-vscode') {
2986
3080
  out.copilot = true;
2987
3081
  out.ideExplicit = true;
2988
- } else if (a === '--copilot-cli') {
2989
- out.copilotCli = true;
2990
- out.ideExplicit = true;
2991
- } else if (a === '--opencode') {
2992
- out.agentOpenCode = true;
2993
- out.ideExplicit = true;
2994
- } else if (a === '--gemini') {
2995
- out.agentGemini = true;
2996
- out.ideExplicit = true;
2997
- } else if (a === '--codex') {
2998
- out.agentCodex = true;
2999
- out.ideExplicit = true;
3000
- } else if (a === '--windsurf') {
3001
- out.agentWindsurf = true;
3002
- out.ideExplicit = true;
3003
- } else if (a === '--antigravity') {
3004
- out.agentAntigravity = true;
3005
- out.ideExplicit = true;
3006
- } else if (a === '--copilot-legacy-clean') {
3007
- out.copilotLegacyClean = true;
3008
- } else if (a === '--all-agents') {
3009
- out.allAgents = true;
3010
- out.copilotCli = true;
3011
- out.agentOpenCode = true;
3012
- out.agentGemini = true;
3013
- out.agentCodex = true;
3014
- out.agentWindsurf = true;
3015
- out.agentAntigravity = true;
3016
- out.ideExplicit = true;
3082
+ } else if (a === '--copilot-cli') {
3083
+ out.copilotCli = true;
3084
+ out.ideExplicit = true;
3085
+ } else if (a === '--opencode') {
3086
+ out.agentOpenCode = true;
3087
+ out.ideExplicit = true;
3088
+ } else if (a === '--gemini') {
3089
+ out.agentGemini = true;
3090
+ out.ideExplicit = true;
3091
+ } else if (a === '--codex') {
3092
+ out.agentCodex = true;
3093
+ out.ideExplicit = true;
3094
+ } else if (a === '--windsurf') {
3095
+ out.agentWindsurf = true;
3096
+ out.ideExplicit = true;
3097
+ } else if (a === '--antigravity') {
3098
+ out.agentAntigravity = true;
3099
+ out.ideExplicit = true;
3100
+ } else if (a === '--copilot-legacy-clean') {
3101
+ out.copilotLegacyClean = true;
3102
+ } else if (a === '--all-agents') {
3103
+ out.allAgents = true;
3104
+ out.copilotCli = true;
3105
+ out.agentOpenCode = true;
3106
+ out.agentGemini = true;
3107
+ out.agentCodex = true;
3108
+ out.agentWindsurf = true;
3109
+ out.agentAntigravity = true;
3110
+ out.ideExplicit = true;
3017
3111
  } else if (a === '--global-cli' || a === '-g') {
3018
3112
  out.globalCli = true;
3019
3113
  } else if (a === '--ide-local') out.ideLocal = true;
@@ -3027,24 +3121,24 @@ function parseUninstallArgs(argv) {
3027
3121
  }
3028
3122
  }
3029
3123
  if (rest.length) out.dir = rest[0];
3030
- if (!out.ideExplicit && !out.copilotLegacyClean) {
3031
- out.cursor = true;
3032
- out.copilot = true;
3033
- out.copilotCli = true;
3034
- out.allAgents = true;
3035
- } else if (out.copilotLegacyClean && !out.ideExplicit && !out.noProject) {
3036
- out.noProject = true;
3037
- }
3038
- if (!out.conflictFlags && out.explicitConfigDir) {
3039
- if (out.ideLocal) {
3040
- out.conflictFlags = '--config-dir não combina com --ide-local';
3041
- } else if (out.allAgents) {
3042
- out.conflictFlags = '--config-dir não combina com --all-agents';
3043
- } else if (anyGranularUninstallAgent(out)) {
3044
- out.conflictFlags = '--config-dir só é suportado com exatamente um entre --cursor, --copilot e --copilot-cli';
3045
- } else if (out.copilot && !out.cursor && !out.copilotCli) {
3046
- out.conflictFlags =
3047
- '--config-dir não combina com --copilot porque o GitHub Copilot no VS Code usa .github/ no workspace';
3124
+ if (!out.ideExplicit && !out.copilotLegacyClean) {
3125
+ out.cursor = true;
3126
+ out.copilot = true;
3127
+ out.copilotCli = true;
3128
+ out.allAgents = true;
3129
+ } else if (out.copilotLegacyClean && !out.ideExplicit && !out.noProject) {
3130
+ out.noProject = true;
3131
+ }
3132
+ if (!out.conflictFlags && out.explicitConfigDir) {
3133
+ if (out.ideLocal) {
3134
+ out.conflictFlags = '--config-dir não combina com --ide-local';
3135
+ } else if (out.allAgents) {
3136
+ out.conflictFlags = '--config-dir não combina com --all-agents';
3137
+ } else if (anyGranularUninstallAgent(out)) {
3138
+ out.conflictFlags = '--config-dir só é suportado com exatamente um entre --cursor, --copilot e --copilot-cli';
3139
+ } else if (out.copilot && !out.cursor && !out.copilotCli) {
3140
+ out.conflictFlags =
3141
+ '--config-dir não combina com --copilot porque o GitHub Copilot no VS Code usa .github/ no workspace';
3048
3142
  } else {
3049
3143
  const n = [out.cursor, out.copilot, out.copilotCli].filter(Boolean).length;
3050
3144
  if (n !== 1) {
@@ -3088,7 +3182,7 @@ function cleanupLegacyCopilotVsCode(ideOpts, opts, removedPaths) {
3088
3182
  const pr = copilotLegacyPromptDir(ideOpts);
3089
3183
  if (!fs.existsSync(pr)) return;
3090
3184
  for (const name of fs.readdirSync(pr)) {
3091
- if (!/^oxe-.*\.prompt\.md$/i.test(name)) continue;
3185
+ if (name !== 'oxe.prompt.md' && !/^oxe-.*\.prompt\.md$/i.test(name)) continue;
3092
3186
  const promptPath = path.join(pr, name);
3093
3187
  unlinkQuiet(promptPath, opts);
3094
3188
  removedPaths.push(promptPath);
@@ -3133,15 +3227,15 @@ function runUninstall(u) {
3133
3227
  help: false,
3134
3228
  version: false,
3135
3229
  cursor: u.cursor,
3136
- copilot: u.copilot,
3137
- copilotCli: u.copilotCli,
3138
- allAgents: u.allAgents,
3139
- agentOpenCode: u.agentOpenCode,
3140
- agentGemini: u.agentGemini,
3141
- agentCodex: u.agentCodex,
3142
- agentWindsurf: u.agentWindsurf,
3143
- agentAntigravity: u.agentAntigravity,
3144
- vscode: false,
3230
+ copilot: u.copilot,
3231
+ copilotCli: u.copilotCli,
3232
+ allAgents: u.allAgents,
3233
+ agentOpenCode: u.agentOpenCode,
3234
+ agentGemini: u.agentGemini,
3235
+ agentCodex: u.agentCodex,
3236
+ agentWindsurf: u.agentWindsurf,
3237
+ agentAntigravity: u.agentAntigravity,
3238
+ vscode: false,
3145
3239
  commands: false,
3146
3240
  agents: false,
3147
3241
  force: true,
@@ -3175,16 +3269,16 @@ function runUninstall(u) {
3175
3269
 
3176
3270
  const removedPaths = [];
3177
3271
 
3178
- if (u.cursor) {
3272
+ if (u.cursor) {
3179
3273
  const base = cursorUserDir(ideOpts);
3180
3274
  const cmdDir = path.join(base, 'commands');
3181
3275
  const ruleDir = path.join(base, 'rules');
3182
3276
  if (fs.existsSync(cmdDir)) {
3183
- for (const name of fs.readdirSync(cmdDir)) {
3184
- if (oxeAgentInstall.isOxeCommandMarkdownName(name)) {
3185
- const p = path.join(cmdDir, name);
3186
- unlinkQuiet(p, u);
3187
- removedPaths.push(p);
3277
+ for (const name of fs.readdirSync(cmdDir)) {
3278
+ if (oxeAgentInstall.isOxeCommandMarkdownName(name)) {
3279
+ const p = path.join(cmdDir, name);
3280
+ unlinkQuiet(p, u);
3281
+ removedPaths.push(p);
3188
3282
  }
3189
3283
  }
3190
3284
  }
@@ -3206,7 +3300,7 @@ function runUninstall(u) {
3206
3300
  const pr = path.join(u.dir, '.github', 'prompts');
3207
3301
  if (fs.existsSync(pr)) {
3208
3302
  for (const name of fs.readdirSync(pr)) {
3209
- if (/^oxe-.*\.prompt\.md$/i.test(name)) {
3303
+ if (name === 'oxe.prompt.md' || /^oxe-.*\.prompt\.md$/i.test(name)) {
3210
3304
  const p = path.join(pr, name);
3211
3305
  unlinkQuiet(p, u);
3212
3306
  removedPaths.push(p);
@@ -3222,15 +3316,15 @@ function runUninstall(u) {
3222
3316
  cleanupLegacyCopilotVsCode(ideOpts, u, removedPaths);
3223
3317
  }
3224
3318
 
3225
- if (u.copilotCli) {
3226
- for (const base of [claudeUserDir(ideOpts), copilotUserDir(ideOpts)]) {
3227
- const cmdDir = path.join(base, 'commands');
3228
- if (!fs.existsSync(cmdDir)) continue;
3229
- for (const name of fs.readdirSync(cmdDir)) {
3230
- if (oxeAgentInstall.isOxeCommandMarkdownName(name)) {
3231
- const p = path.join(cmdDir, name);
3232
- unlinkQuiet(p, u);
3233
- removedPaths.push(p);
3319
+ if (u.copilotCli) {
3320
+ for (const base of [claudeUserDir(ideOpts), copilotUserDir(ideOpts)]) {
3321
+ const cmdDir = path.join(base, 'commands');
3322
+ if (!fs.existsSync(cmdDir)) continue;
3323
+ for (const name of fs.readdirSync(cmdDir)) {
3324
+ if (oxeAgentInstall.isOxeCommandMarkdownName(name)) {
3325
+ const p = path.join(cmdDir, name);
3326
+ unlinkQuiet(p, u);
3327
+ removedPaths.push(p);
3234
3328
  }
3235
3329
  }
3236
3330
  }
@@ -3256,68 +3350,68 @@ function runUninstall(u) {
3256
3350
  removedPaths.push(skillFile);
3257
3351
  }
3258
3352
  }
3259
- }
3260
-
3261
- if (u.allAgents || anyGranularUninstallAgent(u)) {
3262
- const cleanupTargets = buildAgentCleanupTargets(u);
3263
- if (u.dryRun) {
3264
- const label = cleanupTargets
3265
- ? Object.keys(cleanupTargets).filter((key) => cleanupTargets[key]).join(', ')
3266
- : 'OpenCode, Gemini, Windsurf, Codex, Antigravity';
3267
- console.log(`${dim}agents${reset} (dry-run) limparia ${label || 'OpenCode, Gemini, Windsurf, Codex, Antigravity'} (marcadores oxe-cc)`);
3268
- } else {
3269
- oxeAgentInstall.cleanupMarkedUnifiedArtifacts({ dryRun: u.dryRun, targets: cleanupTargets });
3270
- }
3271
- const globalAgentPaths = oxeAgentInstall.buildAgentInstallPaths(true, u.dir);
3272
- const shouldTrack = (name) => !cleanupTargets || cleanupTargets[name] !== false;
3273
- const pushRemoved = (filePath) => {
3274
- if (removedPaths.indexOf(filePath) === -1) removedPaths.push(filePath);
3275
- };
3276
- if (shouldTrack('opencode')) {
3277
- for (const dir of globalAgentPaths.opencodeCommandDirs) {
3278
- if (!fs.existsSync(dir)) continue;
3279
- for (const name of fs.readdirSync(dir)) {
3280
- if (!oxeAgentInstall.isOxeCommandMarkdownName(name)) continue;
3281
- pushRemoved(path.join(dir, name));
3282
- }
3283
- }
3284
- }
3285
- if (shouldTrack('gemini')) {
3286
- pushRemoved(path.join(globalAgentPaths.geminiCommandsBase, 'oxe.toml'));
3287
- const geminiSub = path.join(globalAgentPaths.geminiCommandsBase, 'oxe');
3288
- if (fs.existsSync(geminiSub)) {
3289
- for (const name of fs.readdirSync(geminiSub)) {
3290
- if (name.endsWith('.toml')) pushRemoved(path.join(geminiSub, name));
3291
- }
3292
- }
3293
- }
3294
- if (shouldTrack('windsurf') && fs.existsSync(globalAgentPaths.windsurfWorkflowsDir)) {
3295
- for (const name of fs.readdirSync(globalAgentPaths.windsurfWorkflowsDir)) {
3296
- if (!oxeAgentInstall.isOxeCommandMarkdownName(name)) continue;
3297
- pushRemoved(path.join(globalAgentPaths.windsurfWorkflowsDir, name));
3298
- }
3299
- }
3300
- if (shouldTrack('codex')) {
3301
- if (fs.existsSync(globalAgentPaths.codexPromptsDir)) {
3302
- for (const name of fs.readdirSync(globalAgentPaths.codexPromptsDir)) {
3303
- if (!oxeAgentInstall.isOxeCommandMarkdownName(name)) continue;
3304
- pushRemoved(path.join(globalAgentPaths.codexPromptsDir, name));
3305
- }
3306
- }
3307
- if (fs.existsSync(globalAgentPaths.codexAgentsSkillsRoot)) {
3308
- for (const entry of fs.readdirSync(globalAgentPaths.codexAgentsSkillsRoot, { withFileTypes: true })) {
3309
- if (!entry.isDirectory() || !/^oxe($|-)/.test(entry.name)) continue;
3310
- pushRemoved(path.join(globalAgentPaths.codexAgentsSkillsRoot, entry.name, 'SKILL.md'));
3311
- }
3312
- }
3313
- }
3314
- if (shouldTrack('antigravity') && fs.existsSync(globalAgentPaths.antigravitySkillsRoot)) {
3315
- for (const entry of fs.readdirSync(globalAgentPaths.antigravitySkillsRoot, { withFileTypes: true })) {
3316
- if (!entry.isDirectory() || !/^oxe($|-)/.test(entry.name)) continue;
3317
- pushRemoved(path.join(globalAgentPaths.antigravitySkillsRoot, entry.name, 'SKILL.md'));
3318
- }
3319
- }
3320
- }
3353
+ }
3354
+
3355
+ if (u.allAgents || anyGranularUninstallAgent(u)) {
3356
+ const cleanupTargets = buildAgentCleanupTargets(u);
3357
+ if (u.dryRun) {
3358
+ const label = cleanupTargets
3359
+ ? Object.keys(cleanupTargets).filter((key) => cleanupTargets[key]).join(', ')
3360
+ : 'OpenCode, Gemini, Windsurf, Codex, Antigravity';
3361
+ console.log(`${dim}agents${reset} (dry-run) limparia ${label || 'OpenCode, Gemini, Windsurf, Codex, Antigravity'} (marcadores oxe-cc)`);
3362
+ } else {
3363
+ oxeAgentInstall.cleanupMarkedUnifiedArtifacts({ dryRun: u.dryRun, targets: cleanupTargets });
3364
+ }
3365
+ const globalAgentPaths = oxeAgentInstall.buildAgentInstallPaths(true, u.dir);
3366
+ const shouldTrack = (name) => !cleanupTargets || cleanupTargets[name] !== false;
3367
+ const pushRemoved = (filePath) => {
3368
+ if (removedPaths.indexOf(filePath) === -1) removedPaths.push(filePath);
3369
+ };
3370
+ if (shouldTrack('opencode')) {
3371
+ for (const dir of globalAgentPaths.opencodeCommandDirs) {
3372
+ if (!fs.existsSync(dir)) continue;
3373
+ for (const name of fs.readdirSync(dir)) {
3374
+ if (!oxeAgentInstall.isOxeCommandMarkdownName(name)) continue;
3375
+ pushRemoved(path.join(dir, name));
3376
+ }
3377
+ }
3378
+ }
3379
+ if (shouldTrack('gemini')) {
3380
+ pushRemoved(path.join(globalAgentPaths.geminiCommandsBase, 'oxe.toml'));
3381
+ const geminiSub = path.join(globalAgentPaths.geminiCommandsBase, 'oxe');
3382
+ if (fs.existsSync(geminiSub)) {
3383
+ for (const name of fs.readdirSync(geminiSub)) {
3384
+ if (name.endsWith('.toml')) pushRemoved(path.join(geminiSub, name));
3385
+ }
3386
+ }
3387
+ }
3388
+ if (shouldTrack('windsurf') && fs.existsSync(globalAgentPaths.windsurfWorkflowsDir)) {
3389
+ for (const name of fs.readdirSync(globalAgentPaths.windsurfWorkflowsDir)) {
3390
+ if (!oxeAgentInstall.isOxeCommandMarkdownName(name)) continue;
3391
+ pushRemoved(path.join(globalAgentPaths.windsurfWorkflowsDir, name));
3392
+ }
3393
+ }
3394
+ if (shouldTrack('codex')) {
3395
+ if (fs.existsSync(globalAgentPaths.codexPromptsDir)) {
3396
+ for (const name of fs.readdirSync(globalAgentPaths.codexPromptsDir)) {
3397
+ if (!oxeAgentInstall.isOxeCommandMarkdownName(name)) continue;
3398
+ pushRemoved(path.join(globalAgentPaths.codexPromptsDir, name));
3399
+ }
3400
+ }
3401
+ if (fs.existsSync(globalAgentPaths.codexAgentsSkillsRoot)) {
3402
+ for (const entry of fs.readdirSync(globalAgentPaths.codexAgentsSkillsRoot, { withFileTypes: true })) {
3403
+ if (!entry.isDirectory() || !/^oxe($|-)/.test(entry.name)) continue;
3404
+ pushRemoved(path.join(globalAgentPaths.codexAgentsSkillsRoot, entry.name, 'SKILL.md'));
3405
+ }
3406
+ }
3407
+ }
3408
+ if (shouldTrack('antigravity') && fs.existsSync(globalAgentPaths.antigravitySkillsRoot)) {
3409
+ for (const entry of fs.readdirSync(globalAgentPaths.antigravitySkillsRoot, { withFileTypes: true })) {
3410
+ if (!entry.isDirectory() || !/^oxe($|-)/.test(entry.name)) continue;
3411
+ pushRemoved(path.join(globalAgentPaths.antigravitySkillsRoot, entry.name, 'SKILL.md'));
3412
+ }
3413
+ }
3414
+ }
3321
3415
 
3322
3416
  if (u.ideLocal) {
3323
3417
  uninstallLocalIdeFromProject(u, removedPaths);
@@ -3350,7 +3444,7 @@ function runUninstall(u) {
3350
3444
  }
3351
3445
  }
3352
3446
 
3353
- if (!u.dryRun && (u.cursor || u.copilot || u.copilotCli || u.copilotLegacyClean || anyGranularUninstallAgent(u))) {
3447
+ if (!u.dryRun && (u.cursor || u.copilot || u.copilotCli || u.copilotLegacyClean || anyGranularUninstallAgent(u))) {
3354
3448
  const prev = oxeManifest.loadFileManifest(home);
3355
3449
  const next = { ...prev };
3356
3450
  for (const p of removedPaths) delete next[p];
@@ -3557,7 +3651,7 @@ function runUpdate(u) {
3557
3651
  const r = spawnSync('npx', args, {
3558
3652
  cwd: u.dir,
3559
3653
  stdio: 'inherit',
3560
- env: { ...process.env },
3654
+ env: { ...process.env, OXE_NO_PROMPT: '1' },
3561
3655
  shell: process.platform === 'win32',
3562
3656
  });
3563
3657
  if (r.error) {
@@ -5271,7 +5365,7 @@ async function main() {
5271
5365
  process.exit(0);
5272
5366
  }
5273
5367
 
5274
- if (!(command === 'status' && opts.jsonOutput)) {
5368
+ if (!((command === 'status' && opts.jsonOutput) || (command === 'doctor' && opts.jsonOutput))) {
5275
5369
  printBanner();
5276
5370
  }
5277
5371
 
@@ -5281,7 +5375,7 @@ async function main() {
5281
5375
  console.error(`${yellow}Diretório não encontrado: ${target}${reset}`);
5282
5376
  process.exit(1);
5283
5377
  }
5284
- runDoctor(target);
5378
+ runDoctor(target, { release: opts.releaseDoctor, json: opts.jsonOutput, writeManifest: opts.writeManifest });
5285
5379
  return;
5286
5380
  }
5287
5381
 
@@ -5324,6 +5418,7 @@ async function main() {
5324
5418
  }
5325
5419
 
5326
5420
  await resolveInteractiveInstall(opts);
5421
+ persistIdeScope(opts);
5327
5422
  runInstall(opts);
5328
5423
  await maybePromptGlobalCli(opts);
5329
5424
  }