oxe-cc 0.6.4 → 0.6.6
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/.cursor/commands/oxe-ask.md +11 -0
- package/.cursor/commands/oxe-execute.md +1 -1
- package/.cursor/commands/oxe-session.md +11 -0
- package/.github/prompts/oxe-ask.prompt.md +12 -0
- package/.github/prompts/oxe-execute.prompt.md +1 -1
- package/.github/prompts/oxe-session.prompt.md +12 -0
- package/README.md +363 -323
- package/bin/banner.txt +1 -1
- package/bin/lib/oxe-project-health.cjs +284 -91
- package/bin/oxe-cc.js +305 -123
- package/commands/oxe/ask.md +14 -0
- package/commands/oxe/session.md +16 -0
- package/oxe/templates/CONFIG.md +3 -2
- package/oxe/templates/PLAN.template.md +22 -7
- package/oxe/templates/SESSION.template.md +32 -0
- package/oxe/templates/STATE.md +10 -5
- package/oxe/templates/config.template.json +3 -2
- package/oxe/workflows/ask.md +62 -0
- package/oxe/workflows/checkpoint.md +10 -9
- package/oxe/workflows/debug.md +6 -5
- package/oxe/workflows/discuss.md +8 -7
- package/oxe/workflows/execute.md +37 -28
- package/oxe/workflows/forensics.md +6 -6
- package/oxe/workflows/help.md +39 -19
- package/oxe/workflows/milestone.md +12 -13
- package/oxe/workflows/next.md +16 -13
- package/oxe/workflows/obs.md +9 -8
- package/oxe/workflows/plan-agent.md +6 -4
- package/oxe/workflows/plan.md +73 -32
- package/oxe/workflows/project.md +1 -1
- package/oxe/workflows/quick.md +11 -7
- package/oxe/workflows/references/flow-robustness-contract.md +80 -0
- package/oxe/workflows/references/session-path-resolution.md +71 -0
- package/oxe/workflows/research.md +9 -8
- package/oxe/workflows/security.md +7 -6
- package/oxe/workflows/session.md +153 -0
- package/oxe/workflows/spec.md +41 -27
- package/oxe/workflows/ui-review.md +3 -3
- package/oxe/workflows/ui-spec.md +3 -3
- package/oxe/workflows/validate-gaps.md +5 -4
- package/oxe/workflows/verify.md +37 -21
- package/oxe/workflows/workstream.md +16 -15
- package/package.json +1 -1
package/bin/oxe-cc.js
CHANGED
|
@@ -254,12 +254,13 @@ function buildUninstallFooter(u) {
|
|
|
254
254
|
`${p}${rm} extensões multi-agente marcadas oxe-cc (OpenCode, Gemini TOML, Windsurf workflows, Codex prompts/skills, Antigravity), se existirem.`
|
|
255
255
|
);
|
|
256
256
|
}
|
|
257
|
-
if (u.ideLocal) {
|
|
258
|
-
bullets.push(
|
|
259
|
-
`${p}${rm} integrações OXE no repositório (.cursor, .github, .claude, .copilot, .opencode, … conforme flags).`
|
|
260
|
-
);
|
|
261
|
-
}
|
|
262
|
-
if (
|
|
257
|
+
if (u.ideLocal) {
|
|
258
|
+
bullets.push(
|
|
259
|
+
`${p}${rm} integrações OXE no repositório (.cursor, .github, .claude, .copilot, .opencode, … conforme flags).`
|
|
260
|
+
);
|
|
261
|
+
}
|
|
262
|
+
if (u.globalCli) bullets.push(`${p}${rm} também o pacote npm global oxe-cc do PATH.`);
|
|
263
|
+
if (!u.noProject) {
|
|
263
264
|
bullets.push(
|
|
264
265
|
`${p}${u.dryRun ? 'Seriam removidas' : 'Removidas'} no repositório: .oxe/workflows, .oxe/templates, oxe/ e commands/oxe (o que existir).`
|
|
265
266
|
);
|
|
@@ -1049,9 +1050,9 @@ function bootstrapOxe(target, opts) {
|
|
|
1049
1050
|
}
|
|
1050
1051
|
|
|
1051
1052
|
// Criar estruturas opcionais: plugins/, workstreams/, memory/
|
|
1052
|
-
const pluginsDir = path.join(oxeDir, 'plugins');
|
|
1053
|
-
if (!fs.existsSync(pluginsDir)) {
|
|
1054
|
-
ensureDir(pluginsDir);
|
|
1053
|
+
const pluginsDir = path.join(oxeDir, 'plugins');
|
|
1054
|
+
if (!fs.existsSync(pluginsDir)) {
|
|
1055
|
+
ensureDir(pluginsDir);
|
|
1055
1056
|
const pluginsReadme = path.join(PKG_ROOT, 'oxe', 'templates', 'PLUGINS.md');
|
|
1056
1057
|
if (fs.existsSync(pluginsReadme)) {
|
|
1057
1058
|
const destPluginsReadme = path.join(pluginsDir, 'README.md');
|
|
@@ -1062,15 +1063,44 @@ function bootstrapOxe(target, opts) {
|
|
|
1062
1063
|
}
|
|
1063
1064
|
}
|
|
1064
1065
|
|
|
1065
|
-
const workstreamsDir = path.join(oxeDir, 'workstreams');
|
|
1066
|
-
if (!fs.existsSync(workstreamsDir)) {
|
|
1067
|
-
ensureDir(workstreamsDir);
|
|
1068
|
-
}
|
|
1069
|
-
|
|
1070
|
-
const
|
|
1071
|
-
if (!fs.existsSync(
|
|
1072
|
-
ensureDir(
|
|
1073
|
-
}
|
|
1066
|
+
const workstreamsDir = path.join(oxeDir, 'workstreams');
|
|
1067
|
+
if (!fs.existsSync(workstreamsDir)) {
|
|
1068
|
+
ensureDir(workstreamsDir);
|
|
1069
|
+
}
|
|
1070
|
+
|
|
1071
|
+
const sessionsDir = path.join(oxeDir, 'sessions');
|
|
1072
|
+
if (!fs.existsSync(sessionsDir)) {
|
|
1073
|
+
ensureDir(sessionsDir);
|
|
1074
|
+
}
|
|
1075
|
+
|
|
1076
|
+
const globalDir = path.join(oxeDir, 'global');
|
|
1077
|
+
if (!fs.existsSync(globalDir)) {
|
|
1078
|
+
ensureDir(globalDir);
|
|
1079
|
+
}
|
|
1080
|
+
|
|
1081
|
+
const globalMilestonesDir = path.join(globalDir, 'milestones');
|
|
1082
|
+
if (!fs.existsSync(globalMilestonesDir)) {
|
|
1083
|
+
ensureDir(globalMilestonesDir);
|
|
1084
|
+
}
|
|
1085
|
+
|
|
1086
|
+
const lessonsSrc = path.join(PKG_ROOT, 'oxe', 'templates', 'LESSONS.template.md');
|
|
1087
|
+
const lessonsDest = path.join(globalDir, 'LESSONS.md');
|
|
1088
|
+
if (fs.existsSync(lessonsSrc) && !fs.existsSync(lessonsDest)) {
|
|
1089
|
+
copyFile(lessonsSrc, lessonsDest, { dryRun: false });
|
|
1090
|
+
console.log(`${green}init${reset} ${lessonsDest}`);
|
|
1091
|
+
}
|
|
1092
|
+
|
|
1093
|
+
const milestonesSrc = path.join(PKG_ROOT, 'oxe', 'templates', 'MILESTONES.template.md');
|
|
1094
|
+
const milestonesDest = path.join(globalDir, 'MILESTONES.md');
|
|
1095
|
+
if (fs.existsSync(milestonesSrc) && !fs.existsSync(milestonesDest)) {
|
|
1096
|
+
copyFile(milestonesSrc, milestonesDest, { dryRun: false });
|
|
1097
|
+
console.log(`${green}init${reset} ${milestonesDest}`);
|
|
1098
|
+
}
|
|
1099
|
+
|
|
1100
|
+
const memoryDir = path.join(oxeDir, 'memory');
|
|
1101
|
+
if (!fs.existsSync(memoryDir)) {
|
|
1102
|
+
ensureDir(memoryDir);
|
|
1103
|
+
}
|
|
1074
1104
|
|
|
1075
1105
|
ensureGitignoreIgnoresOxeDir(target, { dryRun: false });
|
|
1076
1106
|
}
|
|
@@ -1114,12 +1144,13 @@ function collectOxeRoutineHints(target, r, config) {
|
|
|
1114
1144
|
* @param {boolean} c
|
|
1115
1145
|
* @param {{ skipScanCompactAgeWarnings?: boolean }} [diagOpts]
|
|
1116
1146
|
*/
|
|
1117
|
-
function printOxeHealthDiagnostics(target, c, diagOpts = {}) {
|
|
1118
|
-
const skipAge = Boolean(diagOpts.skipScanCompactAgeWarnings);
|
|
1119
|
-
const r = oxeHealth.buildHealthReport(target);
|
|
1120
|
-
const { config } = oxeHealth.loadOxeConfigMerged(target);
|
|
1121
|
-
|
|
1122
|
-
console.log(`\n ${c ? cyan : ''}▸ Coerência .oxe/ e config${reset}`);
|
|
1147
|
+
function printOxeHealthDiagnostics(target, c, diagOpts = {}) {
|
|
1148
|
+
const skipAge = Boolean(diagOpts.skipScanCompactAgeWarnings);
|
|
1149
|
+
const r = oxeHealth.buildHealthReport(target);
|
|
1150
|
+
const { config } = oxeHealth.loadOxeConfigMerged(target);
|
|
1151
|
+
|
|
1152
|
+
console.log(`\n ${c ? cyan : ''}▸ Coerência .oxe/ e config${reset}`);
|
|
1153
|
+
console.log(` ${c ? dim : ''}Saúde lógica:${c ? reset : ''} ${r.healthStatus}`);
|
|
1123
1154
|
|
|
1124
1155
|
if (r.configParseError) {
|
|
1125
1156
|
console.log(` ${red}FALHA${reset} config.json: ${r.configParseError}`);
|
|
@@ -1135,9 +1166,18 @@ function printOxeHealthDiagnostics(target, c, diagOpts = {}) {
|
|
|
1135
1166
|
);
|
|
1136
1167
|
}
|
|
1137
1168
|
|
|
1138
|
-
if (r.phase) {
|
|
1139
|
-
console.log(` ${c ? dim : ''}Fase (STATE.md):${c ? reset : ''} ${r.phase}`);
|
|
1140
|
-
}
|
|
1169
|
+
if (r.phase) {
|
|
1170
|
+
console.log(` ${c ? dim : ''}Fase (STATE.md):${c ? reset : ''} ${r.phase}`);
|
|
1171
|
+
}
|
|
1172
|
+
if (r.activeSession) {
|
|
1173
|
+
console.log(` ${c ? dim : ''}Sessão ativa:${c ? reset : ''} ${r.activeSession}`);
|
|
1174
|
+
}
|
|
1175
|
+
if (r.planSelfEvaluation && r.planSelfEvaluation.hasSection) {
|
|
1176
|
+
const best = r.planSelfEvaluation.bestPlan || '—';
|
|
1177
|
+
const conf =
|
|
1178
|
+
typeof r.planSelfEvaluation.confidence === 'number' ? `${r.planSelfEvaluation.confidence}%` : '—';
|
|
1179
|
+
console.log(` ${c ? dim : ''}Plano (autoavaliação):${c ? reset : ''} melhor=${best} | confiança=${conf}`);
|
|
1180
|
+
}
|
|
1141
1181
|
|
|
1142
1182
|
if (!skipAge) {
|
|
1143
1183
|
if (config.scan_max_age_days > 0 && r.scanDate && r.stale.stale) {
|
|
@@ -1172,12 +1212,18 @@ function printOxeHealthDiagnostics(target, c, diagOpts = {}) {
|
|
|
1172
1212
|
console.log(` ${c ? dim : ''}Scan (ignorar):${c ? reset : ''} ${config.scan_ignore_globs.join(', ')}`);
|
|
1173
1213
|
}
|
|
1174
1214
|
|
|
1175
|
-
for (const w of r.phaseWarn) {
|
|
1176
|
-
console.log(` ${yellow}AVISO${reset} ${w}`);
|
|
1177
|
-
}
|
|
1178
|
-
|
|
1179
|
-
console.log(` ${yellow}AVISO${reset} ${
|
|
1180
|
-
}
|
|
1215
|
+
for (const w of r.phaseWarn) {
|
|
1216
|
+
console.log(` ${yellow}AVISO${reset} ${w}`);
|
|
1217
|
+
}
|
|
1218
|
+
for (const w of r.sessionWarn) {
|
|
1219
|
+
console.log(` ${yellow}AVISO${reset} ${w}`);
|
|
1220
|
+
}
|
|
1221
|
+
for (const w of r.installWarn) {
|
|
1222
|
+
console.log(` ${yellow}AVISO${reset} ${w}`);
|
|
1223
|
+
}
|
|
1224
|
+
if (r.summaryGapWarn) {
|
|
1225
|
+
console.log(` ${yellow}AVISO${reset} ${r.summaryGapWarn}`);
|
|
1226
|
+
}
|
|
1181
1227
|
for (const w of r.specWarn) {
|
|
1182
1228
|
console.log(` ${yellow}AVISO${reset} ${w}`);
|
|
1183
1229
|
}
|
|
@@ -1204,20 +1250,25 @@ function runStatus(target, opts = {}) {
|
|
|
1204
1250
|
nextStep: report.next.step,
|
|
1205
1251
|
cursorCmd: report.next.cursorCmd,
|
|
1206
1252
|
reason: report.next.reason,
|
|
1207
|
-
artifacts: report.next.artifacts,
|
|
1208
|
-
phase: report.phase,
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1253
|
+
artifacts: report.next.artifacts,
|
|
1254
|
+
phase: report.phase,
|
|
1255
|
+
healthStatus: report.healthStatus,
|
|
1256
|
+
activeSession: report.activeSession,
|
|
1257
|
+
scanDate: report.scanDate,
|
|
1258
|
+
staleScan: report.stale,
|
|
1259
|
+
compactDate: report.compactDate,
|
|
1260
|
+
staleCompact: report.staleCompact,
|
|
1261
|
+
planSelfEvaluation: report.planSelfEvaluation,
|
|
1262
|
+
diagnostics: {
|
|
1263
|
+
configParseError: report.configParseError,
|
|
1264
|
+
typeErrors: report.typeErrors,
|
|
1265
|
+
unknownConfigKeys: report.unknownConfigKeys,
|
|
1266
|
+
phaseWarnings: report.phaseWarn,
|
|
1267
|
+
sessionWarnings: report.sessionWarn,
|
|
1268
|
+
installWarnings: report.installWarn,
|
|
1269
|
+
summaryGapWarning: report.summaryGapWarn,
|
|
1270
|
+
specWarnings: report.specWarn,
|
|
1271
|
+
planWarnings: report.planWarn,
|
|
1221
1272
|
},
|
|
1222
1273
|
};
|
|
1223
1274
|
if (opts.hints) {
|
|
@@ -1254,9 +1305,12 @@ function runStatus(target, opts = {}) {
|
|
|
1254
1305
|
console.log(` ${c ? dim : ''}No Cursor (referência):${c ? reset : ''} ${c ? cyan : ''}${next.cursorCmd}${reset}`);
|
|
1255
1306
|
console.log(` ${c ? dim : ''}Motivo:${c ? reset : ''} ${next.reason}`);
|
|
1256
1307
|
|
|
1257
|
-
printSummaryAndNextSteps(c, {
|
|
1258
|
-
bullets: [
|
|
1259
|
-
|
|
1308
|
+
printSummaryAndNextSteps(c, {
|
|
1309
|
+
bullets: [
|
|
1310
|
+
`Saúde lógica: ${report.healthStatus}`,
|
|
1311
|
+
`Artefatos em jogo: ${next.artifacts.join(', ')}`,
|
|
1312
|
+
],
|
|
1313
|
+
nextSteps: [
|
|
1260
1314
|
{ desc: 'Diagnóstico completo (inclui pacote de workflows):', cmd: 'npx oxe-cc doctor' },
|
|
1261
1315
|
{ desc: 'Ação sugerida no agente:', cmd: next.cursorCmd },
|
|
1262
1316
|
],
|
|
@@ -1355,7 +1409,7 @@ function runDoctor(target) {
|
|
|
1355
1409
|
'CONVENTIONS.md',
|
|
1356
1410
|
'CONCERNS.md',
|
|
1357
1411
|
];
|
|
1358
|
-
if (fs.existsSync(cbDir)) {
|
|
1412
|
+
if (fs.existsSync(cbDir)) {
|
|
1359
1413
|
const missingMaps = expectedMaps.filter((f) => !fs.existsSync(path.join(cbDir, f)));
|
|
1360
1414
|
if (missingMaps.length) {
|
|
1361
1415
|
console.log(
|
|
@@ -1364,17 +1418,21 @@ function runDoctor(target) {
|
|
|
1364
1418
|
} else {
|
|
1365
1419
|
console.log(`${green}OK${reset} .oxe/codebase/ com os ${expectedMaps.length} mapas esperados`);
|
|
1366
1420
|
}
|
|
1367
|
-
}
|
|
1368
|
-
|
|
1369
|
-
printOxeHealthDiagnostics(target, c);
|
|
1370
|
-
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
|
|
1421
|
+
}
|
|
1422
|
+
|
|
1423
|
+
printOxeHealthDiagnostics(target, c);
|
|
1424
|
+
const report = oxeHealth.buildHealthReport(target);
|
|
1425
|
+
const statusColor = report.healthStatus === 'healthy' ? green : report.healthStatus === 'warning' ? yellow : red;
|
|
1426
|
+
console.log(`\n ${statusColor}Diagnóstico ${report.healthStatus}${reset}`);
|
|
1427
|
+
if (report.healthStatus === 'broken') {
|
|
1428
|
+
process.exitCode = 1;
|
|
1429
|
+
}
|
|
1430
|
+
printSummaryAndNextSteps(c, {
|
|
1431
|
+
bullets: [
|
|
1432
|
+
`Projeto em ${target}`,
|
|
1433
|
+
`Workflows conferidos em ${wfLabel}`,
|
|
1434
|
+
`Saúde lógica: ${report.healthStatus}`,
|
|
1435
|
+
],
|
|
1378
1436
|
nextSteps: [
|
|
1379
1437
|
{ desc: 'Mapear ou atualizar o codebase no agente:', cmd: '/oxe-scan' },
|
|
1380
1438
|
{ desc: 'Ver ajuda e ordem dos passos OXE:', cmd: '/oxe-help' },
|
|
@@ -1388,7 +1446,7 @@ function runDoctor(target) {
|
|
|
1388
1446
|
* npm install -g oxe-cc@version (same version as this running CLI).
|
|
1389
1447
|
* @returns {boolean}
|
|
1390
1448
|
*/
|
|
1391
|
-
function installGlobalCliPackage() {
|
|
1449
|
+
function installGlobalCliPackage() {
|
|
1392
1450
|
const name = readPkgName();
|
|
1393
1451
|
const ver = readPkgVersion();
|
|
1394
1452
|
const spec = `${name}@${ver}`;
|
|
@@ -1411,7 +1469,99 @@ function installGlobalCliPackage() {
|
|
|
1411
1469
|
`\n ${c ? yellow : ''}⚠${c ? reset : ''} npm install -g falhou. Tente manualmente: ${c ? cyan : ''}npm install -g ${spec}${c ? reset : ''}\n`
|
|
1412
1470
|
);
|
|
1413
1471
|
return false;
|
|
1414
|
-
}
|
|
1472
|
+
}
|
|
1473
|
+
|
|
1474
|
+
/**
|
|
1475
|
+
* `npm uninstall -g oxe-cc` com a mesma semântica cross-platform do instalador.
|
|
1476
|
+
* @returns {boolean}
|
|
1477
|
+
*/
|
|
1478
|
+
function uninstallGlobalCliPackage() {
|
|
1479
|
+
const name = readPkgName();
|
|
1480
|
+
const c = useAnsiColors();
|
|
1481
|
+
const dimOrEmpty = c ? dim : '';
|
|
1482
|
+
const resetOrEmpty = c ? reset : '';
|
|
1483
|
+
console.log(`\n ${dimOrEmpty}npm uninstall -g ${name}${resetOrEmpty}\n`);
|
|
1484
|
+
const r = spawnSync('npm', ['uninstall', '-g', name], {
|
|
1485
|
+
stdio: 'inherit',
|
|
1486
|
+
shell: true,
|
|
1487
|
+
env: process.env,
|
|
1488
|
+
});
|
|
1489
|
+
if (r.status === 0) {
|
|
1490
|
+
console.log(
|
|
1491
|
+
`\n ${c ? green : ''}✓${c ? reset : ''} pacote global ${c ? cyan : ''}${name}${c ? reset : ''} removido do npm global.\n`
|
|
1492
|
+
);
|
|
1493
|
+
return true;
|
|
1494
|
+
}
|
|
1495
|
+
console.log(
|
|
1496
|
+
`\n ${c ? yellow : ''}⚠${c ? reset : ''} npm uninstall -g falhou. Remova manualmente: ${c ? cyan : ''}npm uninstall -g ${name}${c ? reset : ''}\n`
|
|
1497
|
+
);
|
|
1498
|
+
return false;
|
|
1499
|
+
}
|
|
1500
|
+
|
|
1501
|
+
/**
|
|
1502
|
+
* Best-effort: detecta se esta execução vem de uma instalação global do npm.
|
|
1503
|
+
* Usa `npm root -g` para evitar confundir execução local do repositório com pacote global.
|
|
1504
|
+
* @returns {boolean}
|
|
1505
|
+
*/
|
|
1506
|
+
function isRunningFromGlobalNpmInstall() {
|
|
1507
|
+
try {
|
|
1508
|
+
const r = spawnSync('npm', ['root', '-g'], {
|
|
1509
|
+
encoding: 'utf8',
|
|
1510
|
+
shell: true,
|
|
1511
|
+
env: process.env,
|
|
1512
|
+
});
|
|
1513
|
+
if (r.status !== 0) return false;
|
|
1514
|
+
const root = String(r.stdout || '').trim();
|
|
1515
|
+
if (!root) return false;
|
|
1516
|
+
const rel = path.relative(path.resolve(root), PKG_ROOT);
|
|
1517
|
+
return rel && !rel.startsWith('..') && !path.isAbsolute(rel);
|
|
1518
|
+
} catch {
|
|
1519
|
+
return false;
|
|
1520
|
+
}
|
|
1521
|
+
}
|
|
1522
|
+
|
|
1523
|
+
/** @returns {string[]} */
|
|
1524
|
+
function updateForwardedInstallFlags() {
|
|
1525
|
+
return [
|
|
1526
|
+
'--cursor',
|
|
1527
|
+
'--copilot',
|
|
1528
|
+
'--copilot-cli',
|
|
1529
|
+
'--all-agents',
|
|
1530
|
+
'--opencode',
|
|
1531
|
+
'--gemini',
|
|
1532
|
+
'--codex',
|
|
1533
|
+
'--windsurf',
|
|
1534
|
+
'--antigravity',
|
|
1535
|
+
'--vscode',
|
|
1536
|
+
'--no-commands',
|
|
1537
|
+
'--no-agents',
|
|
1538
|
+
'--no-init-oxe',
|
|
1539
|
+
'--oxe-only',
|
|
1540
|
+
'--global',
|
|
1541
|
+
'--local',
|
|
1542
|
+
'--ide-global',
|
|
1543
|
+
'--ide-local',
|
|
1544
|
+
'--global-cli',
|
|
1545
|
+
'-g',
|
|
1546
|
+
'--no-global-cli',
|
|
1547
|
+
'-l',
|
|
1548
|
+
'--no-install-config',
|
|
1549
|
+
'--force',
|
|
1550
|
+
'-f',
|
|
1551
|
+
'--all',
|
|
1552
|
+
'-a',
|
|
1553
|
+
'--config-dir',
|
|
1554
|
+
'-c',
|
|
1555
|
+
];
|
|
1556
|
+
}
|
|
1557
|
+
|
|
1558
|
+
/**
|
|
1559
|
+
* @param {string[]} rest
|
|
1560
|
+
* @returns {boolean}
|
|
1561
|
+
*/
|
|
1562
|
+
function updateArgsExplicitlyControlGlobalCli(rest) {
|
|
1563
|
+
return rest.includes('--global-cli') || rest.includes('-g') || rest.includes('--no-global-cli') || rest.includes('-l');
|
|
1564
|
+
}
|
|
1415
1565
|
|
|
1416
1566
|
/**
|
|
1417
1567
|
* After copying OXE into the project: optionally install the CLI globally (pergunta interativa ou flags).
|
|
@@ -1499,21 +1649,22 @@ ${green}Uso:${reset}
|
|
|
1499
1649
|
npx oxe-cc uninstall [opções] [pasta-do-projeto]
|
|
1500
1650
|
npx oxe-cc update [opções] [argumentos extras…]
|
|
1501
1651
|
|
|
1502
|
-
${green}uninstall${reset} (remove OXE da pasta do usuário + pastas de workflows no repo)
|
|
1503
|
-
--cursor / --copilot / --copilot-cli só essa integração (omissão = todas)
|
|
1504
|
-
--all-agents também remove ficheiros multi-plataforma (com --copilot-cli implícito)
|
|
1505
|
-
--ide-local remove integrações IDE neste repositório (.cursor, .github, .claude, .copilot, …)
|
|
1506
|
-
--ide-only não apagar .oxe/workflows, oxe/, etc. no projeto
|
|
1507
|
-
--
|
|
1508
|
-
--
|
|
1509
|
-
--
|
|
1652
|
+
${green}uninstall${reset} (remove OXE da pasta do usuário + pastas de workflows no repo)
|
|
1653
|
+
--cursor / --copilot / --copilot-cli só essa integração (omissão = todas)
|
|
1654
|
+
--all-agents também remove ficheiros multi-plataforma (com --copilot-cli implícito)
|
|
1655
|
+
--ide-local remove integrações IDE neste repositório (.cursor, .github, .claude, .copilot, …)
|
|
1656
|
+
--ide-only não apagar .oxe/workflows, oxe/, etc. no projeto
|
|
1657
|
+
--global-cli, -g também executa npm uninstall -g oxe-cc
|
|
1658
|
+
--config-dir <caminho> com exatamente uma flag IDE acima (não combina com --ide-local)
|
|
1659
|
+
--dry-run
|
|
1660
|
+
--dir <pasta> raiz do projeto (padrão: diretório atual)
|
|
1510
1661
|
|
|
1511
1662
|
${green}update${reset} (executa npx oxe-cc@latest --force na pasta do projeto)
|
|
1512
1663
|
--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)
|
|
1513
1664
|
--if-newer só executa o npx se existir versão mais nova no npm (falha de rede/registry: saída 2, sem npx)
|
|
1514
1665
|
--dir <pasta> pasta em que o npx roda (padrão: atual; ignorada com --check)
|
|
1515
1666
|
--dry-run mostra o comando sem executar
|
|
1516
|
-
[argumentos extras…] repassados ao oxe-cc (ex.: --cursor --global)
|
|
1667
|
+
[argumentos extras…] repassados ao oxe-cc (ex.: --cursor --global, --ide-local, --global-cli)
|
|
1517
1668
|
${dim}CI / sem rede:${reset} OXE_UPDATE_SKIP_REGISTRY=1 desativa consultas (--check sai 2; --if-newer sai 2 sem npx)
|
|
1518
1669
|
|
|
1519
1670
|
${green}Opções da instalação:${reset}
|
|
@@ -1856,7 +2007,7 @@ function runInstall(opts) {
|
|
|
1856
2007
|
console.log(` ${c ? green : ''}✓${c ? reset : ''} Instalação concluída com sucesso.\n`);
|
|
1857
2008
|
}
|
|
1858
2009
|
|
|
1859
|
-
/** @typedef {{ help: boolean, dryRun: boolean, cursor: boolean, copilot: boolean, copilotCli: boolean, allAgents: boolean, ideLocal: boolean, ideExplicit: boolean, noProject: boolean, dir: string, explicitConfigDir: string | null, parseError: boolean, unknownFlag: string, conflictFlags: string }} UninstallOpts */
|
|
2010
|
+
/** @typedef {{ help: boolean, dryRun: boolean, cursor: boolean, copilot: boolean, copilotCli: boolean, allAgents: boolean, globalCli: boolean, ideLocal: boolean, ideExplicit: boolean, noProject: boolean, dir: string, explicitConfigDir: string | null, parseError: boolean, unknownFlag: string, conflictFlags: string }} UninstallOpts */
|
|
1860
2011
|
|
|
1861
2012
|
/**
|
|
1862
2013
|
* @param {UninstallOpts} u
|
|
@@ -1953,10 +2104,10 @@ function uninstallLocalIdeFromProject(u, removedPaths) {
|
|
|
1953
2104
|
}
|
|
1954
2105
|
|
|
1955
2106
|
/**
|
|
1956
|
-
* @param {string[]} argv
|
|
1957
|
-
* @returns {UninstallOpts}
|
|
1958
|
-
*/
|
|
1959
|
-
function parseUninstallArgs(argv) {
|
|
2107
|
+
* @param {string[]} argv
|
|
2108
|
+
* @returns {UninstallOpts}
|
|
2109
|
+
*/
|
|
2110
|
+
function parseUninstallArgs(argv) {
|
|
1960
2111
|
/** @type {UninstallOpts} */
|
|
1961
2112
|
const out = {
|
|
1962
2113
|
help: false,
|
|
@@ -1964,10 +2115,11 @@ function parseUninstallArgs(argv) {
|
|
|
1964
2115
|
cursor: false,
|
|
1965
2116
|
copilot: false,
|
|
1966
2117
|
copilotCli: false,
|
|
1967
|
-
allAgents: false,
|
|
1968
|
-
|
|
1969
|
-
|
|
1970
|
-
|
|
2118
|
+
allAgents: false,
|
|
2119
|
+
globalCli: false,
|
|
2120
|
+
ideLocal: false,
|
|
2121
|
+
ideExplicit: false,
|
|
2122
|
+
noProject: false,
|
|
1971
2123
|
dir: process.cwd(),
|
|
1972
2124
|
explicitConfigDir: null,
|
|
1973
2125
|
parseError: false,
|
|
@@ -1990,13 +2142,15 @@ function parseUninstallArgs(argv) {
|
|
|
1990
2142
|
} else if (a === '--copilot-cli') {
|
|
1991
2143
|
out.copilotCli = true;
|
|
1992
2144
|
out.ideExplicit = true;
|
|
1993
|
-
} else if (a === '--all-agents') {
|
|
1994
|
-
out.allAgents = true;
|
|
1995
|
-
out.copilotCli = true;
|
|
1996
|
-
out.ideExplicit = true;
|
|
1997
|
-
} else if (a === '--
|
|
1998
|
-
|
|
1999
|
-
else if (a === '--
|
|
2145
|
+
} else if (a === '--all-agents') {
|
|
2146
|
+
out.allAgents = true;
|
|
2147
|
+
out.copilotCli = true;
|
|
2148
|
+
out.ideExplicit = true;
|
|
2149
|
+
} else if (a === '--global-cli' || a === '-g') {
|
|
2150
|
+
out.globalCli = true;
|
|
2151
|
+
} else if (a === '--ide-local') out.ideLocal = true;
|
|
2152
|
+
else if (a === '--ide-only') out.noProject = true;
|
|
2153
|
+
else if (a === '--dir' && argv[i + 1]) out.dir = path.resolve(argv[++i]);
|
|
2000
2154
|
else if (!a.startsWith('-')) rest.push(path.resolve(a));
|
|
2001
2155
|
else {
|
|
2002
2156
|
out.parseError = true;
|
|
@@ -2076,7 +2230,7 @@ function rmDirIfEmpty(dirPath, opts) {
|
|
|
2076
2230
|
/**
|
|
2077
2231
|
* @param {UninstallOpts} u
|
|
2078
2232
|
*/
|
|
2079
|
-
function runUninstall(u) {
|
|
2233
|
+
function runUninstall(u) {
|
|
2080
2234
|
assertNotWslWindowsNode();
|
|
2081
2235
|
const c = useAnsiColors();
|
|
2082
2236
|
const home = os.homedir();
|
|
@@ -2233,7 +2387,7 @@ function runUninstall(u) {
|
|
|
2233
2387
|
}
|
|
2234
2388
|
}
|
|
2235
2389
|
|
|
2236
|
-
if (!u.dryRun && (u.cursor || u.copilot || u.copilotCli)) {
|
|
2390
|
+
if (!u.dryRun && (u.cursor || u.copilot || u.copilotCli)) {
|
|
2237
2391
|
const prev = oxeManifest.loadFileManifest(home);
|
|
2238
2392
|
const next = { ...prev };
|
|
2239
2393
|
for (const p of removedPaths) delete next[p];
|
|
@@ -2249,20 +2403,31 @@ function runUninstall(u) {
|
|
|
2249
2403
|
delete next[instPath];
|
|
2250
2404
|
}
|
|
2251
2405
|
}
|
|
2252
|
-
oxeManifest.writeFileManifest(home, next, readPkgVersion());
|
|
2253
|
-
}
|
|
2254
|
-
|
|
2255
|
-
|
|
2256
|
-
|
|
2257
|
-
}
|
|
2258
|
-
|
|
2259
|
-
|
|
2406
|
+
oxeManifest.writeFileManifest(home, next, readPkgVersion());
|
|
2407
|
+
}
|
|
2408
|
+
|
|
2409
|
+
if (u.globalCli && !u.dryRun) {
|
|
2410
|
+
uninstallGlobalCliPackage();
|
|
2411
|
+
} else if (u.globalCli && u.dryRun) {
|
|
2412
|
+
console.log(`${dim}npm${reset} npm uninstall -g ${readPkgName()}`);
|
|
2413
|
+
}
|
|
2414
|
+
|
|
2415
|
+
printSummaryAndNextSteps(c, buildUninstallFooter(u));
|
|
2416
|
+
if (!u.globalCli) {
|
|
2417
|
+
console.log(
|
|
2418
|
+
` ${c ? yellow : ''}Nota:${c ? reset : ''} o pacote npm global ${c ? cyan : ''}${readPkgName()}${c ? reset : ''} não é removido por padrão. Use ${c ? cyan : ''}oxe-cc uninstall --global-cli${c ? reset : ''} ou ${c ? cyan : ''}npm uninstall -g ${readPkgName()}${c ? reset : ''}.\n`
|
|
2419
|
+
);
|
|
2420
|
+
}
|
|
2421
|
+
console.log(` ${c ? green : ''}✓${c ? reset : ''} Desinstalação concluída com sucesso.\n`);
|
|
2422
|
+
}
|
|
2423
|
+
|
|
2424
|
+
/** @typedef {{ help: boolean, dryRun: boolean, check: boolean, ifNewer: boolean, dir: string, rest: string[], parseError: boolean, unknownFlag: string, conflictFlags: string|null }} UpdateOpts */
|
|
2260
2425
|
|
|
2261
2426
|
/**
|
|
2262
2427
|
* @param {string[]} argv
|
|
2263
2428
|
* @returns {UpdateOpts}
|
|
2264
2429
|
*/
|
|
2265
|
-
function parseUpdateArgs(argv) {
|
|
2430
|
+
function parseUpdateArgs(argv) {
|
|
2266
2431
|
/** @type {UpdateOpts} */
|
|
2267
2432
|
const out = {
|
|
2268
2433
|
help: false,
|
|
@@ -2275,25 +2440,31 @@ function parseUpdateArgs(argv) {
|
|
|
2275
2440
|
unknownFlag: '',
|
|
2276
2441
|
conflictFlags: null,
|
|
2277
2442
|
};
|
|
2278
|
-
let dirExplicit = false;
|
|
2279
|
-
let firstPositionalConsumed = false;
|
|
2280
|
-
|
|
2281
|
-
|
|
2282
|
-
|
|
2443
|
+
let dirExplicit = false;
|
|
2444
|
+
let firstPositionalConsumed = false;
|
|
2445
|
+
const passthroughFlags = new Set(updateForwardedInstallFlags());
|
|
2446
|
+
for (let i = 0; i < argv.length; i++) {
|
|
2447
|
+
const a = argv[i];
|
|
2448
|
+
if (a === '-h' || a === '--help') out.help = true;
|
|
2283
2449
|
else if (a === '--dry-run') out.dryRun = true;
|
|
2284
2450
|
else if (a === '--check') out.check = true;
|
|
2285
2451
|
else if (a === '--if-newer') out.ifNewer = true;
|
|
2286
2452
|
else if (a === '--dir' && argv[i + 1]) {
|
|
2287
2453
|
out.dir = path.resolve(argv[++i]);
|
|
2288
2454
|
dirExplicit = true;
|
|
2289
|
-
} else if (!a.startsWith('-')) {
|
|
2290
|
-
if (!dirExplicit && !firstPositionalConsumed) {
|
|
2291
|
-
out.dir = path.resolve(a);
|
|
2292
|
-
firstPositionalConsumed = true;
|
|
2293
|
-
} else out.rest.push(a);
|
|
2294
|
-
} else {
|
|
2295
|
-
out.
|
|
2296
|
-
|
|
2455
|
+
} else if (!a.startsWith('-')) {
|
|
2456
|
+
if (!dirExplicit && !firstPositionalConsumed) {
|
|
2457
|
+
out.dir = path.resolve(a);
|
|
2458
|
+
firstPositionalConsumed = true;
|
|
2459
|
+
} else out.rest.push(a);
|
|
2460
|
+
} else if (passthroughFlags.has(a)) {
|
|
2461
|
+
out.rest.push(a);
|
|
2462
|
+
if ((a === '--config-dir' || a === '-c') && argv[i + 1]) {
|
|
2463
|
+
out.rest.push(argv[++i]);
|
|
2464
|
+
}
|
|
2465
|
+
} else {
|
|
2466
|
+
out.parseError = true;
|
|
2467
|
+
out.unknownFlag = a;
|
|
2297
2468
|
break;
|
|
2298
2469
|
}
|
|
2299
2470
|
}
|
|
@@ -2348,7 +2519,7 @@ function runUpdateVersionCheck(u) {
|
|
|
2348
2519
|
/**
|
|
2349
2520
|
* @param {UpdateOpts} u
|
|
2350
2521
|
*/
|
|
2351
|
-
function runUpdate(u) {
|
|
2522
|
+
function runUpdate(u) {
|
|
2352
2523
|
assertNotWslWindowsNode();
|
|
2353
2524
|
const c = useAnsiColors();
|
|
2354
2525
|
if (u.dryRun) {
|
|
@@ -2359,8 +2530,12 @@ function runUpdate(u) {
|
|
|
2359
2530
|
);
|
|
2360
2531
|
}
|
|
2361
2532
|
console.log(` ${dim}Comando que seria executado (instalação):${reset}`);
|
|
2362
|
-
|
|
2363
|
-
|
|
2533
|
+
const dryRunArgs = ['-y', 'oxe-cc@latest', '--force'];
|
|
2534
|
+
if (updateArgsExplicitlyControlGlobalCli(u.rest)) dryRunArgs.push(...u.rest);
|
|
2535
|
+
else if (isRunningFromGlobalNpmInstall()) dryRunArgs.push('--global-cli');
|
|
2536
|
+
else dryRunArgs.push('--no-global-cli', '-l');
|
|
2537
|
+
console.log(` ${cyan}npx ${dryRunArgs.join(' ')}${reset}`);
|
|
2538
|
+
console.log(` ${dim}Diretório:${reset} ${u.dir}`);
|
|
2364
2539
|
printSummaryAndNextSteps(c, {
|
|
2365
2540
|
bullets: [
|
|
2366
2541
|
'[simulação] O npx baixaria o pacote oxe-cc@latest e rodaria a instalação com --force.',
|
|
@@ -2405,13 +2580,20 @@ function runUpdate(u) {
|
|
|
2405
2580
|
console.log(
|
|
2406
2581
|
` ${dim}Há versão mais nova no npm (${res.version} > ${current}); a executar npx…${reset}\n`
|
|
2407
2582
|
);
|
|
2408
|
-
}
|
|
2409
|
-
|
|
2410
|
-
printSection('OXE ▸ update');
|
|
2411
|
-
const args = ['-y', 'oxe-cc@latest', '--force'
|
|
2412
|
-
|
|
2413
|
-
|
|
2414
|
-
|
|
2583
|
+
}
|
|
2584
|
+
|
|
2585
|
+
printSection('OXE ▸ update');
|
|
2586
|
+
const args = ['-y', 'oxe-cc@latest', '--force'];
|
|
2587
|
+
if (updateArgsExplicitlyControlGlobalCli(u.rest)) {
|
|
2588
|
+
args.push(...u.rest);
|
|
2589
|
+
} else if (isRunningFromGlobalNpmInstall()) {
|
|
2590
|
+
args.push('--global-cli', ...u.rest);
|
|
2591
|
+
} else {
|
|
2592
|
+
args.push('--no-global-cli', '-l', ...u.rest);
|
|
2593
|
+
}
|
|
2594
|
+
const r = spawnSync('npx', args, {
|
|
2595
|
+
cwd: u.dir,
|
|
2596
|
+
stdio: 'inherit',
|
|
2415
2597
|
env: { ...process.env },
|
|
2416
2598
|
shell: process.platform === 'win32',
|
|
2417
2599
|
});
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: oxe:ask
|
|
3
|
+
description: "Perguntar ao OXE sobre a situação atual com leitura robusta de STATE, sessão ativa e artefatos da trilha"
|
|
4
|
+
argument-hint: "[pergunta em texto livre]"
|
|
5
|
+
allowed-tools:
|
|
6
|
+
- Read
|
|
7
|
+
- Bash
|
|
8
|
+
- Glob
|
|
9
|
+
- Grep
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
**Workflow canónico:** `oxe/workflows/ask.md`
|
|
13
|
+
|
|
14
|
+
Execute integralmente esse ficheiro na raiz do repositório em que estás a trabalhar. Usa o texto em `$ARGUMENTS` como pergunta e foco.
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: oxe:session
|
|
3
|
+
description: "Gerir sessões OXE: new, list, switch, resume, status, close, migrate"
|
|
4
|
+
argument-hint: "[new <nome> | list | switch <id> | resume <id> | status | close | migrate <nome>]"
|
|
5
|
+
allowed-tools:
|
|
6
|
+
- Read
|
|
7
|
+
- Bash
|
|
8
|
+
- Glob
|
|
9
|
+
- Grep
|
|
10
|
+
- Write
|
|
11
|
+
- Task
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
**Workflow canónico:** `oxe/workflows/session.md`
|
|
15
|
+
|
|
16
|
+
Executa integralmente esse ficheiro na raiz do repositório em que estás a trabalhar. Usa `$ARGUMENTS` como subcomando e foco da operação da sessão ativa.
|
package/oxe/templates/CONFIG.md
CHANGED
|
@@ -8,8 +8,9 @@ Copie `oxe/templates/config.template.json` para **`.oxe/config.json`** no seu pr
|
|
|
8
8
|
|-------|------|-------------|
|
|
9
9
|
| `profile` | string | Profile de execução: `balanced` (padrão) \| `strict` \| `fast` \| `legacy`. Expande automaticamente outras keys — keys explícitas prevalecem. Ver tabela abaixo. |
|
|
10
10
|
| `discuss_before_plan` | boolean | Se `true`, o fluxo recomenda **`oxe:discuss`** entre spec e plan. |
|
|
11
|
-
| `verification_depth` | string | Profundidade da verificação: `standard` (padrão) \| `thorough` (ativa Camada 5 — validate-gaps automático) \| `quick` (skip camadas 3–4 e UAT). |
|
|
12
|
-
| `
|
|
11
|
+
| `verification_depth` | string | Profundidade da verificação: `standard` (padrão) \| `thorough` (ativa Camada 5 — validate-gaps automático) \| `quick` (skip camadas 3–4 e UAT). |
|
|
12
|
+
| `plan_confidence_threshold` | number | Limiar mínimo de confiança para o `execute` aceitar um `PLAN.md`. Padrão: `70`. Abaixo disso, o fluxo deve reduzir incerteza antes de implementar. |
|
|
13
|
+
| `security_in_verify` | boolean | Se `true`, executa auditoria OWASP automaticamente no **verify** como **Camada 6** (produz `.oxe/SECURITY.md`). Achados P0 bloqueiam `verify_complete`. Padrão: `false`. |
|
|
13
14
|
| `after_verify_suggest_pr` | boolean | Se `true`, o workflow **verify** inclui checklist de PR no fim. |
|
|
14
15
|
| `after_verify_draft_commit` | boolean | Se `true`, o **verify** propõe rascunho de mensagem de commit alinhado aos critérios de aceite. |
|
|
15
16
|
| `after_verify_suggest_uat` | boolean | Se `true`, o **verify** gera checklist UAT (Camada 4). Ativo automaticamente com `profile: strict`. |
|