oxe-cc 1.14.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.
- package/.github/dependabot.yml +31 -0
- package/.github/workflows/ci.yml +141 -56
- package/.github/workflows/release.yml +114 -89
- package/CHANGELOG.md +866 -779
- package/README.md +600 -736
- package/bin/lib/oxe-agent-install.cjs +299 -284
- package/bin/lib/oxe-artifact-catalog.cjs +376 -0
- package/bin/lib/oxe-command-registry.cjs +31 -0
- package/bin/lib/oxe-context-engine.cjs +11 -11
- package/bin/lib/oxe-core-command-handlers.cjs +82 -0
- package/bin/lib/oxe-dashboard.cjs +140 -140
- package/bin/lib/oxe-manifest.cjs +20 -20
- package/bin/lib/oxe-npm-version.cjs +6 -4
- package/bin/lib/oxe-plugin-cli.cjs +95 -0
- package/bin/lib/oxe-plugins.cjs +94 -3
- package/bin/lib/oxe-process.cjs +67 -0
- package/bin/lib/oxe-project-health.cjs +2846 -2856
- package/bin/lib/oxe-runtime-semantics.cjs +68 -69
- package/bin/oxe-cc.js +179 -325
- package/docs/INTEGRATION.md +182 -152
- package/docs/QUALITY-GATES.md +46 -0
- package/docs/RELEASE-READINESS.md +86 -61
- package/docs/RUNTIME-SMOKE-MATRIX.md +137 -135
- package/docs/oxe-artifact-map.html +1172 -1172
- package/lib/sdk/index.cjs +18 -0
- package/lib/sdk/index.d.ts +969 -900
- package/lib/sdk/index.types.ts +933 -0
- package/oxe/templates/PLUGINS.md +8 -1
- package/oxe/templates/STATE-REFERENCE.md +125 -0
- package/oxe/templates/STATE.md +11 -121
- package/oxe/workflows/help.md +2 -0
- package/package.json +129 -108
- package/packages/runtime/package.json +18 -18
- package/packages/runtime/src/evidence/evidence-store.ts +2 -2
- package/packages/runtime/src/scheduler/multi-agent-coordinator.ts +728 -728
- package/packages/runtime/src/workspace/strategies/git-worktree.ts +24 -24
- package/packages/runtime/tsconfig.json +8 -2
- package/vscode-extension/.vscodeignore +2 -0
- package/vscode-extension/package.json +193 -185
- package/vscode-extension/src/extension.js +11 -1
package/bin/oxe-cc.js
CHANGED
|
@@ -21,10 +21,13 @@ const oxeNpmVersion = require(path.join(__dirname, 'lib', 'oxe-npm-version.cjs')
|
|
|
21
21
|
const oxeDashboard = require(path.join(__dirname, 'lib', 'oxe-dashboard.cjs'));
|
|
22
22
|
const oxeOperational = require(path.join(__dirname, 'lib', 'oxe-operational.cjs'));
|
|
23
23
|
const oxeAzure = require(path.join(__dirname, 'lib', 'oxe-azure.cjs'));
|
|
24
|
-
const
|
|
24
|
+
const oxePluginCli = require(path.join(__dirname, 'lib', 'oxe-plugin-cli.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
27
|
const oxeRelease = require(path.join(__dirname, 'lib', 'oxe-release.cjs'));
|
|
28
|
+
const oxeArtifactCatalog = require(path.join(__dirname, 'lib', 'oxe-artifact-catalog.cjs'));
|
|
29
|
+
const { runPackageManagerSync } = require(path.join(__dirname, 'lib', 'oxe-process.cjs'));
|
|
30
|
+
const { createCoreCommandRegistry } = require(path.join(__dirname, 'lib', 'oxe-core-command-handlers.cjs'));
|
|
28
31
|
|
|
29
32
|
/** Merge markers for ~/.copilot/copilot-instructions.md (bloco OXE). */
|
|
30
33
|
const OXE_INST_BEGIN = '<!-- oxe-cc:install-begin -->';
|
|
@@ -935,7 +938,7 @@ function applyInstallFromOxeConfig(opts, targetDir) {
|
|
|
935
938
|
}
|
|
936
939
|
|
|
937
940
|
/**
|
|
938
|
-
* Mapa número da lista → chaves de runtime
|
|
941
|
+
* Mapa número da lista → chaves de runtime
|
|
939
942
|
* @param {string} input
|
|
940
943
|
* @returns {string[]}
|
|
941
944
|
*/
|
|
@@ -1291,20 +1294,48 @@ function ensureGitignoreIgnoresOxeDir(projectRoot, opts = {}) {
|
|
|
1291
1294
|
}
|
|
1292
1295
|
|
|
1293
1296
|
/**
|
|
1294
|
-
*
|
|
1297
|
+
* Ensure a subdirectory under `.oxe/` exists, creating it (and parents) on
|
|
1298
|
+
* demand. This is the lazy-scaffolding primitive: writers call it right before
|
|
1299
|
+
* persisting so the `.oxe/` tree only grows as features are actually used,
|
|
1300
|
+
* instead of being scaffolded eagerly at install time.
|
|
1301
|
+
* @param {string} target project root
|
|
1302
|
+
* @param {string} sub path relative to `.oxe/` (e.g. 'runs', 'global/milestones')
|
|
1303
|
+
* @returns {string} absolute path of the ensured directory
|
|
1304
|
+
*/
|
|
1305
|
+
function ensureOxeSubdir(target, sub) {
|
|
1306
|
+
const dir = path.join(target, '.oxe', ...String(sub).split(/[\\/]/).filter(Boolean));
|
|
1307
|
+
ensureDir(dir);
|
|
1308
|
+
return dir;
|
|
1309
|
+
}
|
|
1310
|
+
|
|
1311
|
+
/**
|
|
1312
|
+
* (Re)generate the `.oxe/README.md` legend from the single artifact catalog.
|
|
1313
|
+
* Written at init and refreshed by `doctor`, so the local documentation always
|
|
1314
|
+
* reflects the canonical structure without the empty folders cluttering disk.
|
|
1315
|
+
* @param {string} target project root
|
|
1316
|
+
* @param {{ quiet?: boolean }} [opts]
|
|
1317
|
+
*/
|
|
1318
|
+
function writeOxeLegend(target, opts = {}) {
|
|
1319
|
+
const oxeDir = path.join(target, '.oxe');
|
|
1320
|
+
const dest = path.join(oxeDir, 'README.md');
|
|
1321
|
+
try {
|
|
1322
|
+
ensureDir(oxeDir);
|
|
1323
|
+
fs.writeFileSync(dest, oxeArtifactCatalog.renderLegend(), 'utf8');
|
|
1324
|
+
if (!opts.quiet) console.log(`${green}init${reset} ${dest}`);
|
|
1325
|
+
} catch {
|
|
1326
|
+
/* best-effort: a missing legend is never fatal */
|
|
1327
|
+
}
|
|
1328
|
+
}
|
|
1329
|
+
|
|
1330
|
+
/**
|
|
1331
|
+
* Create the lean `.oxe/` core: STATE.md, config.json and the generated
|
|
1332
|
+
* README.md legend. Every other artifact/folder is created lazily, on first
|
|
1333
|
+
* use, by the workflow that owns it (see `bin/lib/oxe-artifact-catalog.cjs`).
|
|
1295
1334
|
* @param {string} target
|
|
1296
1335
|
* @param {{ dryRun: boolean, force: boolean }} opts
|
|
1297
1336
|
*/
|
|
1298
1337
|
function bootstrapOxe(target, opts) {
|
|
1299
1338
|
const oxeDir = path.join(target, '.oxe');
|
|
1300
|
-
const codebaseDir = path.join(oxeDir, 'codebase');
|
|
1301
|
-
const capabilitiesDir = path.join(oxeDir, 'capabilities');
|
|
1302
|
-
const investigationsDir = path.join(oxeDir, 'investigations');
|
|
1303
|
-
const dashboardDir = path.join(oxeDir, 'dashboard');
|
|
1304
|
-
const contextDir = path.join(oxeDir, 'context');
|
|
1305
|
-
const contextPacksDir = path.join(contextDir, 'packs');
|
|
1306
|
-
const contextSummariesDir = path.join(contextDir, 'summaries');
|
|
1307
|
-
const installDir = path.join(oxeDir, 'install');
|
|
1308
1339
|
const stateSrc = path.join(PKG_ROOT, 'oxe', 'templates', 'STATE.md');
|
|
1309
1340
|
const stateDest = path.join(oxeDir, 'STATE.md');
|
|
1310
1341
|
const configSrc = path.join(PKG_ROOT, 'oxe', 'templates', 'config.template.json');
|
|
@@ -1316,18 +1347,12 @@ function bootstrapOxe(target, opts) {
|
|
|
1316
1347
|
}
|
|
1317
1348
|
|
|
1318
1349
|
if (opts.dryRun) {
|
|
1319
|
-
console.log(`${dim}init${reset} ${oxeDir}/ (STATE.md, config.json,
|
|
1350
|
+
console.log(`${dim}init${reset} ${oxeDir}/ (STATE.md, config.json, README.md — demais artefatos sob demanda)`);
|
|
1320
1351
|
ensureGitignoreIgnoresOxeDir(target, { dryRun: true });
|
|
1321
1352
|
return;
|
|
1322
1353
|
}
|
|
1323
1354
|
|
|
1324
|
-
ensureDir(
|
|
1325
|
-
ensureDir(capabilitiesDir);
|
|
1326
|
-
ensureDir(investigationsDir);
|
|
1327
|
-
ensureDir(dashboardDir);
|
|
1328
|
-
ensureDir(contextPacksDir);
|
|
1329
|
-
ensureDir(contextSummariesDir);
|
|
1330
|
-
ensureDir(installDir);
|
|
1355
|
+
ensureDir(oxeDir);
|
|
1331
1356
|
|
|
1332
1357
|
if (!fs.existsSync(stateDest) || opts.force) {
|
|
1333
1358
|
copyFile(stateSrc, stateDest, { dryRun: false });
|
|
@@ -1351,107 +1376,8 @@ function bootstrapOxe(target, opts) {
|
|
|
1351
1376
|
}
|
|
1352
1377
|
}
|
|
1353
1378
|
|
|
1354
|
-
//
|
|
1355
|
-
|
|
1356
|
-
if (!fs.existsSync(pluginsDir)) {
|
|
1357
|
-
ensureDir(pluginsDir);
|
|
1358
|
-
const pluginsReadme = path.join(PKG_ROOT, 'oxe', 'templates', 'PLUGINS.md');
|
|
1359
|
-
if (fs.existsSync(pluginsReadme)) {
|
|
1360
|
-
const destPluginsReadme = path.join(pluginsDir, 'README.md');
|
|
1361
|
-
if (!fs.existsSync(destPluginsReadme)) {
|
|
1362
|
-
copyFile(pluginsReadme, destPluginsReadme, { dryRun: false });
|
|
1363
|
-
console.log(`${green}init${reset} ${destPluginsReadme}`);
|
|
1364
|
-
}
|
|
1365
|
-
}
|
|
1366
|
-
}
|
|
1367
|
-
|
|
1368
|
-
const workstreamsDir = path.join(oxeDir, 'workstreams');
|
|
1369
|
-
if (!fs.existsSync(workstreamsDir)) {
|
|
1370
|
-
ensureDir(workstreamsDir);
|
|
1371
|
-
}
|
|
1372
|
-
|
|
1373
|
-
const sessionsDir = path.join(oxeDir, 'sessions');
|
|
1374
|
-
if (!fs.existsSync(sessionsDir)) {
|
|
1375
|
-
ensureDir(sessionsDir);
|
|
1376
|
-
}
|
|
1377
|
-
|
|
1378
|
-
const globalDir = path.join(oxeDir, 'global');
|
|
1379
|
-
if (!fs.existsSync(globalDir)) {
|
|
1380
|
-
ensureDir(globalDir);
|
|
1381
|
-
}
|
|
1382
|
-
|
|
1383
|
-
const globalMilestonesDir = path.join(globalDir, 'milestones');
|
|
1384
|
-
if (!fs.existsSync(globalMilestonesDir)) {
|
|
1385
|
-
ensureDir(globalMilestonesDir);
|
|
1386
|
-
}
|
|
1387
|
-
|
|
1388
|
-
const lessonsSrc = path.join(PKG_ROOT, 'oxe', 'templates', 'LESSONS.template.md');
|
|
1389
|
-
const lessonsDest = path.join(globalDir, 'LESSONS.md');
|
|
1390
|
-
if (fs.existsSync(lessonsSrc) && !fs.existsSync(lessonsDest)) {
|
|
1391
|
-
copyFile(lessonsSrc, lessonsDest, { dryRun: false });
|
|
1392
|
-
console.log(`${green}init${reset} ${lessonsDest}`);
|
|
1393
|
-
}
|
|
1394
|
-
|
|
1395
|
-
const milestonesSrc = path.join(PKG_ROOT, 'oxe', 'templates', 'MILESTONES.template.md');
|
|
1396
|
-
const milestonesDest = path.join(globalDir, 'MILESTONES.md');
|
|
1397
|
-
if (fs.existsSync(milestonesSrc) && !fs.existsSync(milestonesDest)) {
|
|
1398
|
-
copyFile(milestonesSrc, milestonesDest, { dryRun: false });
|
|
1399
|
-
console.log(`${green}init${reset} ${milestonesDest}`);
|
|
1400
|
-
}
|
|
1401
|
-
|
|
1402
|
-
const memoryDir = path.join(oxeDir, 'memory');
|
|
1403
|
-
if (!fs.existsSync(memoryDir)) {
|
|
1404
|
-
ensureDir(memoryDir);
|
|
1405
|
-
}
|
|
1406
|
-
|
|
1407
|
-
const runsDir = path.join(oxeDir, 'runs');
|
|
1408
|
-
if (!fs.existsSync(runsDir)) {
|
|
1409
|
-
ensureDir(runsDir);
|
|
1410
|
-
}
|
|
1411
|
-
|
|
1412
|
-
const runtimeSrc = path.join(PKG_ROOT, 'oxe', 'templates', 'EXECUTION-RUNTIME.template.md');
|
|
1413
|
-
const runtimeDest = path.join(oxeDir, 'EXECUTION-RUNTIME.md');
|
|
1414
|
-
if (fs.existsSync(runtimeSrc) && !fs.existsSync(runtimeDest)) {
|
|
1415
|
-
copyFile(runtimeSrc, runtimeDest, { dryRun: false });
|
|
1416
|
-
console.log(`${green}init${reset} ${runtimeDest}`);
|
|
1417
|
-
}
|
|
1418
|
-
|
|
1419
|
-
const activeRunSrc = path.join(PKG_ROOT, 'oxe', 'templates', 'ACTIVE-RUN.template.json');
|
|
1420
|
-
const activeRunDest = path.join(oxeDir, 'ACTIVE-RUN.json');
|
|
1421
|
-
if (fs.existsSync(activeRunSrc) && !fs.existsSync(activeRunDest)) {
|
|
1422
|
-
copyFile(activeRunSrc, activeRunDest, { dryRun: false });
|
|
1423
|
-
console.log(`${green}init${reset} ${activeRunDest}`);
|
|
1424
|
-
}
|
|
1425
|
-
|
|
1426
|
-
const eventsDest = path.join(oxeDir, 'OXE-EVENTS.ndjson');
|
|
1427
|
-
if (!fs.existsSync(eventsDest)) {
|
|
1428
|
-
fs.writeFileSync(eventsDest, '', 'utf8');
|
|
1429
|
-
console.log(`${green}init${reset} ${eventsDest}`);
|
|
1430
|
-
}
|
|
1431
|
-
|
|
1432
|
-
const checkpointsSrc = path.join(PKG_ROOT, 'oxe', 'templates', 'CHECKPOINTS.template.md');
|
|
1433
|
-
const checkpointsDest = path.join(oxeDir, 'CHECKPOINTS.md');
|
|
1434
|
-
if (fs.existsSync(checkpointsSrc) && !fs.existsSync(checkpointsDest)) {
|
|
1435
|
-
copyFile(checkpointsSrc, checkpointsDest, { dryRun: false });
|
|
1436
|
-
console.log(`${green}init${reset} ${checkpointsDest}`);
|
|
1437
|
-
}
|
|
1438
|
-
|
|
1439
|
-
const capabilitiesSrc = path.join(PKG_ROOT, 'oxe', 'templates', 'CAPABILITIES.template.md');
|
|
1440
|
-
const capabilitiesDest = path.join(oxeDir, 'CAPABILITIES.md');
|
|
1441
|
-
if (fs.existsSync(capabilitiesSrc) && !fs.existsSync(capabilitiesDest)) {
|
|
1442
|
-
copyFile(capabilitiesSrc, capabilitiesDest, { dryRun: false });
|
|
1443
|
-
console.log(`${green}init${reset} ${capabilitiesDest}`);
|
|
1444
|
-
}
|
|
1445
|
-
|
|
1446
|
-
const investigationsIndexDest = path.join(oxeDir, 'INVESTIGATIONS.md');
|
|
1447
|
-
if (!fs.existsSync(investigationsIndexDest)) {
|
|
1448
|
-
fs.writeFileSync(
|
|
1449
|
-
investigationsIndexDest,
|
|
1450
|
-
'# OXE — Investigações\n\n| Data | Ficheiro | Objetivo | Modo | Estado |\n|------|----------|----------|------|--------|\n',
|
|
1451
|
-
'utf8'
|
|
1452
|
-
);
|
|
1453
|
-
console.log(`${green}init${reset} ${investigationsIndexDest}`);
|
|
1454
|
-
}
|
|
1379
|
+
// Generated legend — always (re)written so it tracks the current catalog.
|
|
1380
|
+
writeOxeLegend(target);
|
|
1455
1381
|
|
|
1456
1382
|
ensureGitignoreIgnoresOxeDir(target, { dryRun: false });
|
|
1457
1383
|
}
|
|
@@ -2135,6 +2061,11 @@ function runDoctor(target, options = {}) {
|
|
|
2135
2061
|
}
|
|
2136
2062
|
console.log(`${green}OK${reset} Node.js`);
|
|
2137
2063
|
|
|
2064
|
+
// Keep the generated `.oxe/README.md` legend fresh against the current catalog.
|
|
2065
|
+
if (fs.existsSync(path.join(target, '.oxe'))) {
|
|
2066
|
+
writeOxeLegend(target, { quiet: true });
|
|
2067
|
+
}
|
|
2068
|
+
|
|
2138
2069
|
const wfPkg = path.join(PKG_ROOT, 'oxe', 'workflows');
|
|
2139
2070
|
const wfTgt = oxeWorkflows.resolveWorkflowsDir(target);
|
|
2140
2071
|
if (!fs.existsSync(wfPkg)) {
|
|
@@ -2368,9 +2299,8 @@ function installGlobalCliPackage() {
|
|
|
2368
2299
|
const dimOrEmpty = c ? dim : '';
|
|
2369
2300
|
const resetOrEmpty = c ? reset : '';
|
|
2370
2301
|
console.log(`\n ${dimOrEmpty}npm install -g ${spec}${resetOrEmpty}\n`);
|
|
2371
|
-
const r =
|
|
2302
|
+
const r = runPackageManagerSync('npm', ['install', '-g', spec], {
|
|
2372
2303
|
stdio: 'inherit',
|
|
2373
|
-
shell: true,
|
|
2374
2304
|
env: process.env,
|
|
2375
2305
|
});
|
|
2376
2306
|
if (r.error) {
|
|
@@ -2401,9 +2331,8 @@ function uninstallGlobalCliPackage() {
|
|
|
2401
2331
|
const dimOrEmpty = c ? dim : '';
|
|
2402
2332
|
const resetOrEmpty = c ? reset : '';
|
|
2403
2333
|
console.log(`\n ${dimOrEmpty}npm uninstall -g ${name}${resetOrEmpty}\n`);
|
|
2404
|
-
const r =
|
|
2334
|
+
const r = runPackageManagerSync('npm', ['uninstall', '-g', name], {
|
|
2405
2335
|
stdio: 'inherit',
|
|
2406
|
-
shell: true,
|
|
2407
2336
|
env: process.env,
|
|
2408
2337
|
});
|
|
2409
2338
|
if (r.status === 0) {
|
|
@@ -2425,9 +2354,8 @@ function uninstallGlobalCliPackage() {
|
|
|
2425
2354
|
*/
|
|
2426
2355
|
function isRunningFromGlobalNpmInstall() {
|
|
2427
2356
|
try {
|
|
2428
|
-
const r =
|
|
2357
|
+
const r = runPackageManagerSync('npm', ['root', '-g'], {
|
|
2429
2358
|
encoding: 'utf8',
|
|
2430
|
-
shell: true,
|
|
2431
2359
|
env: process.env,
|
|
2432
2360
|
});
|
|
2433
2361
|
if (r.status !== 0) return false;
|
|
@@ -2570,12 +2498,14 @@ ${cyan}oxe-cc${reset} — instala workflows OXE (núcleo .oxe/ + integrações:
|
|
|
2570
2498
|
npx oxe-cc context <build|inspect> [opções] [pasta-do-projeto]
|
|
2571
2499
|
npx oxe-cc dashboard [opções] [pasta-do-projeto]
|
|
2572
2500
|
npx oxe-cc events [--tail N] [--since <evt_id>] [--json] [opções] [pasta-do-projeto]
|
|
2501
|
+
npx oxe-cc map [--json] [opções] [pasta-do-projeto]
|
|
2573
2502
|
npx oxe-cc runtime <status|start|pause|resume|replay|compile|verify|project|ci|promote|recover|gates|agents|execute> [opções] [pasta-do-projeto]
|
|
2574
2503
|
npx oxe-cc azure <status|doctor|auth|sync|find|servicebus|eventgrid|sql|operations> [opções] [pasta-do-projeto]
|
|
2575
2504
|
npx oxe-cc capabilities <list|install|remove|update> [opções] [id]
|
|
2505
|
+
npx oxe-cc plugins <list|install|remove> [opções]
|
|
2576
2506
|
npx oxe-cc uninstall [opções] [pasta-do-projeto]
|
|
2577
2507
|
npx oxe-cc update [opções] [argumentos extras…]
|
|
2578
|
-
|
|
2508
|
+
|
|
2579
2509
|
${green}doctor${reset}
|
|
2580
2510
|
--release valida release readiness: versões, changelog, wrappers, runtime build e relatórios obrigatórios
|
|
2581
2511
|
--write-manifest persiste .oxe/release/release-manifest.json durante doctor --release
|
|
@@ -2628,6 +2558,13 @@ ${green}context${reset} (Context Engine V2: seleção, compressão e inspeção
|
|
|
2628
2558
|
--json saída estruturada em JSON
|
|
2629
2559
|
--dir <pasta> raiz do projeto (padrão: diretório atual)
|
|
2630
2560
|
|
|
2561
|
+
${green}plugins${reset} (plugins de lifecycle locais ou publicados no npm)
|
|
2562
|
+
list lista plugins carregados e erros de resolução
|
|
2563
|
+
install <npm-package> [version] instala somente pacote npm; prefixo npm: é opcional
|
|
2564
|
+
remove <id> mostra como remover a referência e os arquivos npm
|
|
2565
|
+
--dir <pasta> raiz do projeto (padrão: diretório atual)
|
|
2566
|
+
${dim}Plugins por path:${reset} crie o .cjs localmente e referencie-o em .oxe/config.json; o comando install não aceita paths
|
|
2567
|
+
|
|
2631
2568
|
${green}runtime${reset} (controle operacional explícito do ACTIVE-RUN)
|
|
2632
2569
|
status mostra o run ativo resolvido para a sessão atual
|
|
2633
2570
|
start cria um novo run com tracing inicial
|
|
@@ -3484,11 +3421,6 @@ function runUninstall(u) {
|
|
|
3484
3421
|
ignoreInstallConfig: false,
|
|
3485
3422
|
ideLocal: false,
|
|
3486
3423
|
explicitIdeScope: true,
|
|
3487
|
-
agentOpenCode: false,
|
|
3488
|
-
agentGemini: false,
|
|
3489
|
-
agentCodex: false,
|
|
3490
|
-
agentWindsurf: false,
|
|
3491
|
-
agentAntigravity: false,
|
|
3492
3424
|
});
|
|
3493
3425
|
|
|
3494
3426
|
printSection('OXE ▸ uninstall');
|
|
@@ -3887,11 +3819,10 @@ function runUpdate(u) {
|
|
|
3887
3819
|
} else {
|
|
3888
3820
|
args.push('--no-global-cli', '-l', ...u.rest);
|
|
3889
3821
|
}
|
|
3890
|
-
const r =
|
|
3822
|
+
const r = runPackageManagerSync('npx', args, {
|
|
3891
3823
|
cwd: u.dir,
|
|
3892
3824
|
stdio: 'inherit',
|
|
3893
3825
|
env: { ...process.env, OXE_NO_PROMPT: '1' },
|
|
3894
|
-
shell: process.platform === 'win32',
|
|
3895
3826
|
});
|
|
3896
3827
|
if (r.error) {
|
|
3897
3828
|
console.error(`${red}Falha ao executar npx:${reset}`, r.error.message);
|
|
@@ -4526,6 +4457,70 @@ function runEvents(opts) {
|
|
|
4526
4457
|
console.log('');
|
|
4527
4458
|
}
|
|
4528
4459
|
|
|
4460
|
+
/**
|
|
4461
|
+
* @typedef {{ help: boolean, dir: string, json: boolean, parseError: boolean, unknownFlag: string }} MapOpts
|
|
4462
|
+
* @param {string[]} argv
|
|
4463
|
+
* @returns {MapOpts}
|
|
4464
|
+
*/
|
|
4465
|
+
function parseMapArgs(argv) {
|
|
4466
|
+
/** @type {MapOpts} */
|
|
4467
|
+
const out = { help: false, dir: process.cwd(), json: false, parseError: false, unknownFlag: '' };
|
|
4468
|
+
for (let i = 0; i < argv.length; i++) {
|
|
4469
|
+
const a = argv[i];
|
|
4470
|
+
if (a === '-h' || a === '--help') out.help = true;
|
|
4471
|
+
else if (a === '--dir' && argv[i + 1]) out.dir = path.resolve(argv[++i]);
|
|
4472
|
+
else if (a === '--json') out.json = true;
|
|
4473
|
+
else if (!a.startsWith('-') && i === 0) out.dir = path.resolve(a);
|
|
4474
|
+
else {
|
|
4475
|
+
out.parseError = true;
|
|
4476
|
+
out.unknownFlag = a;
|
|
4477
|
+
break;
|
|
4478
|
+
}
|
|
4479
|
+
}
|
|
4480
|
+
return out;
|
|
4481
|
+
}
|
|
4482
|
+
|
|
4483
|
+
/**
|
|
4484
|
+
* Live, annotated map of the `.oxe/` artifacts: what already exists, what is
|
|
4485
|
+
* available on demand, and the state of each (active/empty/stale). Built from
|
|
4486
|
+
* the single artifact catalog so it never drifts from the legend or docs.
|
|
4487
|
+
* @param {MapOpts} opts
|
|
4488
|
+
*/
|
|
4489
|
+
function runMap(opts) {
|
|
4490
|
+
const target = opts.dir;
|
|
4491
|
+
if (!fs.existsSync(target)) {
|
|
4492
|
+
if (opts.json) console.log(JSON.stringify({ oxeMapSchema: 1, projectRoot: path.resolve(target), error: 'dir-not-found', groups: [] }));
|
|
4493
|
+
else console.error(`${yellow}Diretório não encontrado: ${target}${reset}`);
|
|
4494
|
+
process.exit(1);
|
|
4495
|
+
}
|
|
4496
|
+
// Stale-scan signal reuses the same health helpers `status`/`doctor` rely on.
|
|
4497
|
+
let staleScan = false;
|
|
4498
|
+
try {
|
|
4499
|
+
const statePath = oxeHealth.oxePaths(target).state;
|
|
4500
|
+
const stateText = fs.existsSync(statePath) ? fs.readFileSync(statePath, 'utf8') : '';
|
|
4501
|
+
const cfg = oxeHealth.loadOxeConfigMerged(target);
|
|
4502
|
+
const scanDate = oxeHealth.parseLastScanDate(stateText);
|
|
4503
|
+
staleScan = oxeHealth.isStaleScan(scanDate, cfg.scan_max_age_days || 0);
|
|
4504
|
+
} catch {
|
|
4505
|
+
staleScan = false;
|
|
4506
|
+
}
|
|
4507
|
+
const model = oxeArtifactCatalog.buildMapModel(target, { staleScan });
|
|
4508
|
+
|
|
4509
|
+
if (opts.json) {
|
|
4510
|
+
console.log(JSON.stringify({ oxeMapSchema: 1, ...model }));
|
|
4511
|
+
return;
|
|
4512
|
+
}
|
|
4513
|
+
|
|
4514
|
+
const c = useAnsiColors();
|
|
4515
|
+
const palette = { active: green, empty: yellow, stale: yellow, absent: dim, group: cyan, dim, root: green };
|
|
4516
|
+
const paint = (s, kind) => (c && palette[kind] ? `${palette[kind]}${s}${reset}` : s);
|
|
4517
|
+
printSection('OXE ▸ map');
|
|
4518
|
+
console.log(` ${paint('Projeto:', 'group')} ${paint(model.projectRoot, 'group')}`);
|
|
4519
|
+
console.log('');
|
|
4520
|
+
console.log(oxeArtifactCatalog.renderMap(model, { paint }));
|
|
4521
|
+
console.log('');
|
|
4522
|
+
}
|
|
4523
|
+
|
|
4529
4524
|
/**
|
|
4530
4525
|
* @param {RuntimeOpts} opts
|
|
4531
4526
|
*/
|
|
@@ -5617,6 +5612,7 @@ async function main() {
|
|
|
5617
5612
|
argv[0] === 'context' ||
|
|
5618
5613
|
argv[0] === 'dashboard' ||
|
|
5619
5614
|
argv[0] === 'events' ||
|
|
5615
|
+
argv[0] === 'map' ||
|
|
5620
5616
|
argv[0] === 'runtime' ||
|
|
5621
5617
|
argv[0] === 'azure' ||
|
|
5622
5618
|
argv[0] === 'uninstall' ||
|
|
@@ -5631,103 +5627,67 @@ async function main() {
|
|
|
5631
5627
|
argv.shift();
|
|
5632
5628
|
}
|
|
5633
5629
|
|
|
5634
|
-
|
|
5635
|
-
|
|
5636
|
-
|
|
5637
|
-
|
|
5638
|
-
|
|
5639
|
-
|
|
5640
|
-
|
|
5641
|
-
|
|
5642
|
-
|
|
5643
|
-
|
|
5644
|
-
|
|
5645
|
-
|
|
5646
|
-
|
|
5647
|
-
|
|
5648
|
-
|
|
5649
|
-
|
|
5650
|
-
|
|
5651
|
-
|
|
5652
|
-
|
|
5653
|
-
|
|
5654
|
-
|
|
5655
|
-
|
|
5656
|
-
|
|
5657
|
-
|
|
5658
|
-
|
|
5659
|
-
|
|
5660
|
-
|
|
5661
|
-
|
|
5662
|
-
if (command === 'update') {
|
|
5663
|
-
const u = parseUpdateArgs(argv);
|
|
5664
|
-
if (u.help) {
|
|
5665
|
-
printBanner();
|
|
5666
|
-
usage();
|
|
5667
|
-
process.exit(0);
|
|
5668
|
-
}
|
|
5669
|
-
if (u.conflictFlags) {
|
|
5670
|
-
printBanner();
|
|
5671
|
-
console.error(`${red}${u.conflictFlags}${reset}`);
|
|
5672
|
-
usage();
|
|
5673
|
-
process.exit(1);
|
|
5674
|
-
}
|
|
5675
|
-
if (u.parseError) {
|
|
5676
|
-
printBanner();
|
|
5677
|
-
console.error(`${red}Opção desconhecida:${reset} ${u.unknownFlag}`);
|
|
5678
|
-
usage();
|
|
5679
|
-
process.exit(1);
|
|
5680
|
-
}
|
|
5681
|
-
printBanner();
|
|
5682
|
-
if (u.check) {
|
|
5683
|
-
runUpdateVersionCheck(u);
|
|
5684
|
-
return;
|
|
5685
|
-
}
|
|
5686
|
-
if (!u.dryRun && !fs.existsSync(u.dir)) {
|
|
5687
|
-
console.error(`${yellow}Diretório não encontrado: ${u.dir}${reset}`);
|
|
5688
|
-
process.exit(1);
|
|
5689
|
-
}
|
|
5690
|
-
runUpdate(u);
|
|
5691
|
-
return;
|
|
5692
|
-
}
|
|
5630
|
+
const coreRegistry = createCoreCommandRegistry({
|
|
5631
|
+
existsSync: fs.existsSync,
|
|
5632
|
+
printBanner,
|
|
5633
|
+
usage,
|
|
5634
|
+
log: console.log,
|
|
5635
|
+
error: console.error,
|
|
5636
|
+
exit: process.exit,
|
|
5637
|
+
colors: { red, yellow, reset },
|
|
5638
|
+
readPkgVersion,
|
|
5639
|
+
parseUninstallArgs,
|
|
5640
|
+
parseUpdateArgs,
|
|
5641
|
+
parseCapabilitiesArgs,
|
|
5642
|
+
parseRuntimeArgs,
|
|
5643
|
+
parseAzureArgs,
|
|
5644
|
+
parseInstallArgs,
|
|
5645
|
+
runUninstall,
|
|
5646
|
+
runUpdateVersionCheck,
|
|
5647
|
+
runUpdate,
|
|
5648
|
+
runCapabilities,
|
|
5649
|
+
runRuntime,
|
|
5650
|
+
runAzure,
|
|
5651
|
+
runDoctor,
|
|
5652
|
+
runStatus,
|
|
5653
|
+
runStatusFull,
|
|
5654
|
+
});
|
|
5655
|
+
const coreDispatch = await coreRegistry.dispatch(command, argv);
|
|
5656
|
+
if (coreDispatch.handled) return;
|
|
5693
5657
|
|
|
5694
|
-
if (command === '
|
|
5695
|
-
const
|
|
5696
|
-
if (
|
|
5658
|
+
if (command === 'dashboard') {
|
|
5659
|
+
const d = parseDashboardArgs(argv);
|
|
5660
|
+
if (d.help) {
|
|
5697
5661
|
printBanner();
|
|
5698
5662
|
usage();
|
|
5699
5663
|
process.exit(0);
|
|
5700
5664
|
}
|
|
5701
|
-
if (
|
|
5665
|
+
if (d.parseError) {
|
|
5702
5666
|
printBanner();
|
|
5703
|
-
console.error(`${red}Opção desconhecida:${reset} ${
|
|
5667
|
+
console.error(`${red}Opção desconhecida:${reset} ${d.unknownFlag}`);
|
|
5704
5668
|
usage();
|
|
5705
5669
|
process.exit(1);
|
|
5706
5670
|
}
|
|
5707
|
-
printBanner();
|
|
5708
|
-
|
|
5709
|
-
console.error(`${yellow}Diretório não encontrado: ${cap.dir}${reset}`);
|
|
5710
|
-
process.exit(1);
|
|
5711
|
-
}
|
|
5712
|
-
runCapabilities(cap);
|
|
5671
|
+
if (!d.json) printBanner();
|
|
5672
|
+
await runDashboard(d);
|
|
5713
5673
|
return;
|
|
5714
5674
|
}
|
|
5715
5675
|
|
|
5716
|
-
if (command === '
|
|
5717
|
-
const
|
|
5718
|
-
if (
|
|
5676
|
+
if (command === 'map') {
|
|
5677
|
+
const m = parseMapArgs(argv);
|
|
5678
|
+
if (m.help) {
|
|
5719
5679
|
printBanner();
|
|
5720
5680
|
usage();
|
|
5721
5681
|
process.exit(0);
|
|
5722
5682
|
}
|
|
5723
|
-
if (
|
|
5683
|
+
if (m.parseError) {
|
|
5724
5684
|
printBanner();
|
|
5725
|
-
console.error(`${red}Opção desconhecida:${reset} ${
|
|
5685
|
+
console.error(`${red}Opção desconhecida:${reset} ${m.unknownFlag}`);
|
|
5726
5686
|
usage();
|
|
5727
5687
|
process.exit(1);
|
|
5728
5688
|
}
|
|
5729
|
-
if (!
|
|
5730
|
-
|
|
5689
|
+
if (!m.json) printBanner();
|
|
5690
|
+
runMap(m);
|
|
5731
5691
|
return;
|
|
5732
5692
|
}
|
|
5733
5693
|
|
|
@@ -5767,95 +5727,13 @@ async function main() {
|
|
|
5767
5727
|
return;
|
|
5768
5728
|
}
|
|
5769
5729
|
|
|
5770
|
-
if (command === 'runtime') {
|
|
5771
|
-
const runtime = parseRuntimeArgs(argv);
|
|
5772
|
-
if (runtime.help) {
|
|
5773
|
-
printBanner();
|
|
5774
|
-
usage();
|
|
5775
|
-
process.exit(0);
|
|
5776
|
-
}
|
|
5777
|
-
if (runtime.parseError) {
|
|
5778
|
-
printBanner();
|
|
5779
|
-
console.error(`${red}Opção desconhecida:${reset} ${runtime.unknownFlag}`);
|
|
5780
|
-
usage();
|
|
5781
|
-
process.exit(1);
|
|
5782
|
-
}
|
|
5783
|
-
printBanner();
|
|
5784
|
-
if (!fs.existsSync(runtime.dir)) {
|
|
5785
|
-
console.error(`${yellow}Diretório não encontrado: ${runtime.dir}${reset}`);
|
|
5786
|
-
process.exit(1);
|
|
5787
|
-
}
|
|
5788
|
-
runRuntime(runtime).catch((err) => {
|
|
5789
|
-
console.error(`${red}${err && err.message ? err.message : 'Falha ao executar runtime.'}${reset}`);
|
|
5790
|
-
process.exit(1);
|
|
5791
|
-
});
|
|
5792
|
-
return;
|
|
5793
|
-
}
|
|
5794
|
-
|
|
5795
5730
|
if (command === 'plugins') {
|
|
5796
5731
|
printBanner();
|
|
5797
|
-
|
|
5798
|
-
|
|
5799
|
-
|
|
5800
|
-
|
|
5801
|
-
|
|
5802
|
-
pluginsDir = path.resolve(pluginsArgv[++i]);
|
|
5803
|
-
pluginsArgv.splice(i - 1, 2);
|
|
5804
|
-
i -= 2;
|
|
5805
|
-
}
|
|
5806
|
-
}
|
|
5807
|
-
const c = useAnsiColors();
|
|
5808
|
-
const subCmd = pluginsArgv[0] || 'list';
|
|
5809
|
-
const pluginTarget = pluginsArgv[1] || '';
|
|
5810
|
-
|
|
5811
|
-
if (subCmd === 'list') {
|
|
5812
|
-
const result = oxePlugins.loadPlugins(pluginsDir);
|
|
5813
|
-
console.log(`\n ${c ? green : ''}Plugins carregados:${c ? reset : ''} ${result.plugins.length}`);
|
|
5814
|
-
for (const p of result.plugins) {
|
|
5815
|
-
console.log(` • ${p.name}${p.version ? ` (${p.version})` : ''} — hooks: ${Object.keys(p.hooks).join(', ')}`);
|
|
5816
|
-
}
|
|
5817
|
-
if (result.errors.length) {
|
|
5818
|
-
console.log(`\n ${c ? yellow : ''}Erros:${c ? reset : ''}`);
|
|
5819
|
-
for (const e of result.errors) {
|
|
5820
|
-
console.log(` ✗ ${e.file}: ${e.error}`);
|
|
5821
|
-
}
|
|
5822
|
-
}
|
|
5823
|
-
} else if (subCmd === 'install' && pluginTarget) {
|
|
5824
|
-
const src = pluginTarget.startsWith('npm:') ? pluginTarget.slice(4) : pluginTarget;
|
|
5825
|
-
const ver = pluginsArgv[2] || '';
|
|
5826
|
-
console.log(` Instalando plugin: ${src}${ver ? `@${ver}` : ''}...`);
|
|
5827
|
-
const result = oxePlugins.installNpmPlugin(pluginsDir, src, ver || undefined);
|
|
5828
|
-
if (result.ok) {
|
|
5829
|
-
console.log(` ${c ? green : ''}✓${c ? reset : ''} Instalado em: ${result.path}`);
|
|
5830
|
-
console.log(` ${c ? dim : ''}Adicione ao .oxe/config.json: "plugins": [{ "source": "npm:${src}" }]${c ? reset : ''}`);
|
|
5831
|
-
} else {
|
|
5832
|
-
console.error(` ${c ? red : ''}✗ Falha:${c ? reset : ''} ${result.error}`);
|
|
5833
|
-
process.exit(1);
|
|
5834
|
-
}
|
|
5835
|
-
} else if (subCmd === 'remove' && pluginTarget) {
|
|
5836
|
-
console.log(` ${c ? yellow : ''}Remove "${pluginTarget}" de .oxe/config.json → plugins[] manualmente.${c ? reset : ''}`);
|
|
5837
|
-
console.log(` ${c ? dim : ''}Arquivos npm: rm -rf .oxe/plugins/_npm/node_modules/${pluginTarget}${c ? reset : ''}`);
|
|
5838
|
-
} else {
|
|
5839
|
-
console.log(` ${c ? yellow : ''}Uso: oxe-cc plugins list | install <npm:pkg|path> | remove <id>${c ? reset : ''}`);
|
|
5840
|
-
}
|
|
5841
|
-
return;
|
|
5842
|
-
}
|
|
5843
|
-
|
|
5844
|
-
if (command === 'azure') {
|
|
5845
|
-
const azure = parseAzureArgs(argv);
|
|
5846
|
-
if (azure.help) {
|
|
5847
|
-
printBanner();
|
|
5848
|
-
usage();
|
|
5849
|
-
process.exit(0);
|
|
5850
|
-
}
|
|
5851
|
-
if (azure.parseError) {
|
|
5852
|
-
printBanner();
|
|
5853
|
-
console.error(`${red}Opção desconhecida:${reset} ${azure.unknownFlag}`);
|
|
5854
|
-
usage();
|
|
5855
|
-
process.exit(1);
|
|
5856
|
-
}
|
|
5857
|
-
printBanner();
|
|
5858
|
-
runAzure(azure);
|
|
5732
|
+
const exitCode = oxePluginCli.runPluginCommand(argv, {
|
|
5733
|
+
useAnsiColors,
|
|
5734
|
+
colors: { green, yellow, dim, red, reset },
|
|
5735
|
+
});
|
|
5736
|
+
if (exitCode !== 0) process.exit(exitCode);
|
|
5859
5737
|
return;
|
|
5860
5738
|
}
|
|
5861
5739
|
|
|
@@ -5908,33 +5786,9 @@ async function main() {
|
|
|
5908
5786
|
process.exit(0);
|
|
5909
5787
|
}
|
|
5910
5788
|
|
|
5911
|
-
|
|
5912
|
-
printBanner();
|
|
5913
|
-
}
|
|
5789
|
+
printBanner();
|
|
5914
5790
|
|
|
5915
5791
|
const target = opts.dir;
|
|
5916
|
-
if (command === 'doctor') {
|
|
5917
|
-
if (!fs.existsSync(target)) {
|
|
5918
|
-
console.error(`${yellow}Diretório não encontrado: ${target}${reset}`);
|
|
5919
|
-
process.exit(1);
|
|
5920
|
-
}
|
|
5921
|
-
runDoctor(target, { release: opts.releaseDoctor, json: opts.jsonOutput, writeManifest: opts.writeManifest });
|
|
5922
|
-
return;
|
|
5923
|
-
}
|
|
5924
|
-
|
|
5925
|
-
if (command === 'status') {
|
|
5926
|
-
if (!fs.existsSync(target)) {
|
|
5927
|
-
console.error(`${yellow}Diretório não encontrado: ${target}${reset}`);
|
|
5928
|
-
process.exit(1);
|
|
5929
|
-
}
|
|
5930
|
-
if (opts.statusFull) {
|
|
5931
|
-
runStatusFull(target);
|
|
5932
|
-
} else {
|
|
5933
|
-
runStatus(target, { json: opts.jsonOutput, hints: opts.statusHints, summary: opts.statusSummary });
|
|
5934
|
-
}
|
|
5935
|
-
return;
|
|
5936
|
-
}
|
|
5937
|
-
|
|
5938
5792
|
if (command === 'init-oxe') {
|
|
5939
5793
|
if (!opts.dryRun && !fs.existsSync(target)) {
|
|
5940
5794
|
console.error(`${yellow}Diretório não encontrado: ${target}${reset}`);
|
|
@@ -5947,8 +5801,8 @@ async function main() {
|
|
|
5947
5801
|
bootstrapOxe(target, { dryRun: opts.dryRun, force: opts.force });
|
|
5948
5802
|
printSummaryAndNextSteps(c0, {
|
|
5949
5803
|
bullets: opts.dryRun
|
|
5950
|
-
? ['[simulação] Seriam criados
|
|
5951
|
-
: ['.oxe/STATE.md, .oxe/config.json
|
|
5804
|
+
? ['[simulação] Seriam criados .oxe/STATE.md, .oxe/config.json e .oxe/README.md (legenda) — demais artefatos nascem sob demanda; veja com oxe-cc map']
|
|
5805
|
+
: ['.oxe/STATE.md, .oxe/config.json e .oxe/README.md (legenda) — núcleo enxuto; demais pastas/artefatos são criados sob demanda pelo workflow correspondente (veja oxe-cc map)'],
|
|
5952
5806
|
nextSteps: [
|
|
5953
5807
|
{ desc: 'Validar o projeto:', cmd: 'npx oxe-cc doctor' },
|
|
5954
5808
|
{ desc: 'Instalar integrações IDE/CLI (se ainda não fez):', cmd: 'npx oxe-cc@latest' },
|