oxe-cc 0.3.6 → 0.3.8
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-checkpoint.md +9 -0
- package/.cursor/commands/oxe-compact.md +9 -0
- package/.cursor/commands/oxe-debug.md +9 -0
- package/.cursor/commands/oxe-forensics.md +9 -0
- package/.cursor/commands/oxe-plan-agent.md +9 -0
- package/.cursor/commands/oxe-research.md +9 -0
- package/.cursor/commands/oxe-route.md +9 -0
- package/.cursor/commands/oxe-ui-review.md +9 -0
- package/.cursor/commands/oxe-ui-spec.md +9 -0
- package/.cursor/commands/oxe-validate-gaps.md +9 -0
- package/.github/copilot-instructions.md +14 -4
- package/.github/prompts/oxe-checkpoint.prompt.md +12 -0
- package/.github/prompts/oxe-compact.prompt.md +11 -0
- package/.github/prompts/oxe-debug.prompt.md +12 -0
- package/.github/prompts/oxe-forensics.prompt.md +12 -0
- package/.github/prompts/oxe-plan-agent.prompt.md +10 -0
- package/.github/prompts/oxe-research.prompt.md +12 -0
- package/.github/prompts/oxe-route.prompt.md +12 -0
- package/.github/prompts/oxe-ui-review.prompt.md +12 -0
- package/.github/prompts/oxe-ui-spec.prompt.md +12 -0
- package/.github/prompts/oxe-validate-gaps.prompt.md +12 -0
- package/AGENTS.md +1 -1
- package/README.md +108 -9
- package/bin/banner.txt +1 -1
- package/bin/lib/oxe-project-health.cjs +33 -0
- package/bin/oxe-cc.js +87 -15
- package/commands/oxe/checkpoint.md +16 -0
- package/commands/oxe/compact.md +10 -0
- package/commands/oxe/debug.md +16 -0
- package/commands/oxe/forensics.md +16 -0
- package/commands/oxe/plan-agent.md +15 -0
- package/commands/oxe/research.md +16 -0
- package/commands/oxe/route.md +11 -0
- package/commands/oxe/ui-review.md +16 -0
- package/commands/oxe/ui-spec.md +16 -0
- package/commands/oxe/validate-gaps.md +16 -0
- package/lib/sdk/README.md +12 -0
- package/lib/sdk/index.cjs +1 -0
- package/lib/sdk/index.d.ts +34 -1
- package/oxe/schemas/plan-agents.schema.json +111 -0
- package/oxe/templates/CHECKPOINT.template.md +37 -0
- package/oxe/templates/CODEBASE-DELTA.template.md +33 -0
- package/oxe/templates/CONFIG.md +1 -0
- package/oxe/templates/GIT_HOOKS_OXE.md +52 -0
- package/oxe/templates/PLAN.template.md +12 -0
- package/oxe/templates/RESEARCH.template.md +50 -0
- package/oxe/templates/RESUME.template.md +49 -0
- package/oxe/templates/SPEC.template.md +13 -0
- package/oxe/templates/STATE.md +14 -0
- package/oxe/templates/WORKFLOW_AUTHORING.md +3 -1
- package/oxe/templates/config.template.json +1 -0
- package/oxe/templates/plan-agent-messages-README.template.md +9 -0
- package/oxe/templates/plan-agents.template.json +28 -0
- package/oxe/workflows/checkpoint.md +32 -0
- package/oxe/workflows/compact.md +44 -0
- package/oxe/workflows/debug.md +31 -0
- package/oxe/workflows/discuss.md +8 -5
- package/oxe/workflows/execute.md +10 -0
- package/oxe/workflows/forensics.md +42 -0
- package/oxe/workflows/help.md +75 -9
- package/oxe/workflows/next.md +3 -2
- package/oxe/workflows/plan-agent.md +93 -0
- package/oxe/workflows/plan.md +27 -5
- package/oxe/workflows/quick.md +16 -2
- package/oxe/workflows/references/plan-agent-chat-protocol.md +85 -0
- package/oxe/workflows/research.md +35 -0
- package/oxe/workflows/route.md +27 -0
- package/oxe/workflows/scan.md +2 -0
- package/oxe/workflows/spec.md +3 -1
- package/oxe/workflows/ui-review.md +26 -0
- package/oxe/workflows/ui-spec.md +26 -0
- package/oxe/workflows/update.md +1 -1
- package/oxe/workflows/validate-gaps.md +34 -0
- package/oxe/workflows/verify.md +5 -0
- package/package.json +1 -1
package/bin/oxe-cc.js
CHANGED
|
@@ -326,6 +326,8 @@ function parseInstallArgs(argv) {
|
|
|
326
326
|
ignoreInstallConfig: false,
|
|
327
327
|
/** Saída JSON em `status` (CI / agentes). */
|
|
328
328
|
jsonOutput: false,
|
|
329
|
+
/** Lembretes agregados scan/compact em `status`. */
|
|
330
|
+
statusHints: false,
|
|
329
331
|
restPositional: [],
|
|
330
332
|
};
|
|
331
333
|
for (let i = 0; i < argv.length; i++) {
|
|
@@ -369,6 +371,7 @@ function parseInstallArgs(argv) {
|
|
|
369
371
|
else if (a === '--dir' && argv[i + 1]) {
|
|
370
372
|
out.dir = path.resolve(argv[++i]);
|
|
371
373
|
} else if (a === '--json') out.jsonOutput = true;
|
|
374
|
+
else if (a === '--hints') out.statusHints = true;
|
|
372
375
|
else if (!a.startsWith('-')) out.restPositional.push(a);
|
|
373
376
|
else {
|
|
374
377
|
out.parseError = true;
|
|
@@ -669,7 +672,7 @@ function applyInstallFromOxeConfig(opts, targetDir) {
|
|
|
669
672
|
}
|
|
670
673
|
|
|
671
674
|
/**
|
|
672
|
-
* Mapa número da lista → chaves de runtime
|
|
675
|
+
* Mapa número da lista → chaves de runtime
|
|
673
676
|
* @param {string} input
|
|
674
677
|
* @returns {string[]}
|
|
675
678
|
*/
|
|
@@ -765,7 +768,7 @@ async function promptRuntimeSelection() {
|
|
|
765
768
|
}
|
|
766
769
|
}
|
|
767
770
|
|
|
768
|
-
/** Global vs local (pastas do projeto)
|
|
771
|
+
/** Global vs local (pastas do projeto) */
|
|
769
772
|
async function promptIdeLocation(opts) {
|
|
770
773
|
const rl = readlinePromises.createInterface({ input: process.stdin, output: process.stdout });
|
|
771
774
|
const c = useAnsiColors();
|
|
@@ -1048,12 +1051,47 @@ function bootstrapOxe(target, opts) {
|
|
|
1048
1051
|
ensureGitignoreIgnoresOxeDir(target, { dryRun: false });
|
|
1049
1052
|
}
|
|
1050
1053
|
|
|
1054
|
+
/**
|
|
1055
|
+
* Lembretes de rotina (scan/compact antigos) para `status --hints` ou JSON.
|
|
1056
|
+
* @param {string} target
|
|
1057
|
+
* @param {ReturnType<typeof oxeHealth.buildHealthReport>} r
|
|
1058
|
+
* @param {ReturnType<typeof oxeHealth.loadOxeConfigMerged>['config']} config
|
|
1059
|
+
* @returns {string[]}
|
|
1060
|
+
*/
|
|
1061
|
+
function collectOxeRoutineHints(target, r, config) {
|
|
1062
|
+
/** @type {string[]} */
|
|
1063
|
+
const out = [];
|
|
1064
|
+
const statePath = path.join(target, '.oxe', 'STATE.md');
|
|
1065
|
+
const hasState = fs.existsSync(statePath);
|
|
1066
|
+
if (config.scan_max_age_days > 0 && r.scanDate && r.stale.stale) {
|
|
1067
|
+
out.push(
|
|
1068
|
+
`Último scan há ~${r.stale.days} dia(s) (limite: ${config.scan_max_age_days}) — considere /oxe-scan`
|
|
1069
|
+
);
|
|
1070
|
+
} else if (config.scan_max_age_days > 0 && !r.scanDate && hasState) {
|
|
1071
|
+
out.push(
|
|
1072
|
+
'Preencha **Data:** em STATE.md (secção Último scan) para o aviso de scan antigo, ou use scan_max_age_days: 0'
|
|
1073
|
+
);
|
|
1074
|
+
}
|
|
1075
|
+
if (config.compact_max_age_days > 0 && r.compactDate && r.staleCompact.stale) {
|
|
1076
|
+
out.push(
|
|
1077
|
+
`Último compact há ~${r.staleCompact.days} dia(s) (limite: ${config.compact_max_age_days}) — considere /oxe-compact se .oxe/codebase/ divergiu do código`
|
|
1078
|
+
);
|
|
1079
|
+
} else if (config.compact_max_age_days > 0 && !r.compactDate && hasState) {
|
|
1080
|
+
out.push(
|
|
1081
|
+
'Preencha **Data:** em STATE.md (secção Último compact) para o aviso de compact antigo, ou use compact_max_age_days: 0'
|
|
1082
|
+
);
|
|
1083
|
+
}
|
|
1084
|
+
return out;
|
|
1085
|
+
}
|
|
1086
|
+
|
|
1051
1087
|
/**
|
|
1052
1088
|
* Doctor / status: config estendida, fase STATE, scan antigo, SUMMARY, SPEC/PLAN.
|
|
1053
1089
|
* @param {string} target
|
|
1054
1090
|
* @param {boolean} c
|
|
1091
|
+
* @param {{ skipScanCompactAgeWarnings?: boolean }} [diagOpts]
|
|
1055
1092
|
*/
|
|
1056
|
-
function printOxeHealthDiagnostics(target, c) {
|
|
1093
|
+
function printOxeHealthDiagnostics(target, c, diagOpts = {}) {
|
|
1094
|
+
const skipAge = Boolean(diagOpts.skipScanCompactAgeWarnings);
|
|
1057
1095
|
const r = oxeHealth.buildHealthReport(target);
|
|
1058
1096
|
const { config } = oxeHealth.loadOxeConfigMerged(target);
|
|
1059
1097
|
|
|
@@ -1077,14 +1115,30 @@ function printOxeHealthDiagnostics(target, c) {
|
|
|
1077
1115
|
console.log(` ${c ? dim : ''}Fase (STATE.md):${c ? reset : ''} ${r.phase}`);
|
|
1078
1116
|
}
|
|
1079
1117
|
|
|
1080
|
-
if (
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1118
|
+
if (!skipAge) {
|
|
1119
|
+
if (config.scan_max_age_days > 0 && r.scanDate && r.stale.stale) {
|
|
1120
|
+
console.log(
|
|
1121
|
+
` ${yellow}AVISO${reset} Último scan há ~${r.stale.days} dia(s) (limite: ${config.scan_max_age_days}) — considere ${cyan}/oxe-scan${reset}`
|
|
1122
|
+
);
|
|
1123
|
+
} else if (config.scan_max_age_days > 0 && !r.scanDate && fs.existsSync(path.join(target, '.oxe', 'STATE.md'))) {
|
|
1124
|
+
console.log(
|
|
1125
|
+
` ${dim}Obs.:${reset} Preencha **Data:** em STATE.md (secção Último scan) para o aviso de scan antigo, ou use scan_max_age_days: 0`
|
|
1126
|
+
);
|
|
1127
|
+
}
|
|
1128
|
+
|
|
1129
|
+
if (config.compact_max_age_days > 0 && r.compactDate && r.staleCompact.stale) {
|
|
1130
|
+
console.log(
|
|
1131
|
+
` ${yellow}AVISO${reset} Último compact há ~${r.staleCompact.days} dia(s) (limite: ${config.compact_max_age_days}) — considere ${cyan}/oxe-compact${reset} se .oxe/codebase/ estiver desatualizado`
|
|
1132
|
+
);
|
|
1133
|
+
} else if (
|
|
1134
|
+
config.compact_max_age_days > 0 &&
|
|
1135
|
+
!r.compactDate &&
|
|
1136
|
+
fs.existsSync(path.join(target, '.oxe', 'STATE.md'))
|
|
1137
|
+
) {
|
|
1138
|
+
console.log(
|
|
1139
|
+
` ${dim}Obs.:${reset} Preencha **Data:** em STATE.md (secção Último compact) para o aviso de compact antigo, ou use compact_max_age_days: 0`
|
|
1140
|
+
);
|
|
1141
|
+
}
|
|
1088
1142
|
}
|
|
1089
1143
|
|
|
1090
1144
|
if (Array.isArray(config.scan_focus_globs) && config.scan_focus_globs.length) {
|
|
@@ -1110,17 +1164,18 @@ function printOxeHealthDiagnostics(target, c) {
|
|
|
1110
1164
|
|
|
1111
1165
|
/**
|
|
1112
1166
|
* @param {string} target
|
|
1113
|
-
* @param {{ json?: boolean }} [opts]
|
|
1167
|
+
* @param {{ json?: boolean, hints?: boolean }} [opts]
|
|
1114
1168
|
*/
|
|
1115
1169
|
function runStatus(target, opts = {}) {
|
|
1116
1170
|
const { config } = oxeHealth.loadOxeConfigMerged(target);
|
|
1117
1171
|
const next = oxeHealth.suggestNextStep(target, { discuss_before_plan: config.discuss_before_plan });
|
|
1118
1172
|
const report = oxeHealth.buildHealthReport(target);
|
|
1173
|
+
const routineHints = collectOxeRoutineHints(target, report, config);
|
|
1119
1174
|
|
|
1120
1175
|
if (opts.json) {
|
|
1121
1176
|
/** @type {Record<string, unknown>} */
|
|
1122
1177
|
const payload = {
|
|
1123
|
-
oxeStatusSchema:
|
|
1178
|
+
oxeStatusSchema: 2,
|
|
1124
1179
|
projectRoot: path.resolve(target),
|
|
1125
1180
|
nextStep: report.next.step,
|
|
1126
1181
|
cursorCmd: report.next.cursorCmd,
|
|
@@ -1129,6 +1184,8 @@ function runStatus(target, opts = {}) {
|
|
|
1129
1184
|
phase: report.phase,
|
|
1130
1185
|
scanDate: report.scanDate,
|
|
1131
1186
|
staleScan: report.stale,
|
|
1187
|
+
compactDate: report.compactDate,
|
|
1188
|
+
staleCompact: report.staleCompact,
|
|
1132
1189
|
diagnostics: {
|
|
1133
1190
|
configParseError: report.configParseError,
|
|
1134
1191
|
typeErrors: report.typeErrors,
|
|
@@ -1139,6 +1196,9 @@ function runStatus(target, opts = {}) {
|
|
|
1139
1196
|
planWarnings: report.planWarn,
|
|
1140
1197
|
},
|
|
1141
1198
|
};
|
|
1199
|
+
if (opts.hints) {
|
|
1200
|
+
payload.hints = routineHints;
|
|
1201
|
+
}
|
|
1142
1202
|
console.log(JSON.stringify(payload));
|
|
1143
1203
|
return;
|
|
1144
1204
|
}
|
|
@@ -1152,7 +1212,18 @@ function runStatus(target, opts = {}) {
|
|
|
1152
1212
|
console.log(` ${yellow}AVISO${reset} Workflows OXE não encontrados — ${cyan}npx oxe-cc@latest${reset}`);
|
|
1153
1213
|
}
|
|
1154
1214
|
|
|
1155
|
-
printOxeHealthDiagnostics(target, c);
|
|
1215
|
+
printOxeHealthDiagnostics(target, c, { skipScanCompactAgeWarnings: Boolean(opts.hints) });
|
|
1216
|
+
|
|
1217
|
+
if (opts.hints) {
|
|
1218
|
+
console.log(`\n ${c ? cyan : ''}Lembretes (rotina OXE)${reset}`);
|
|
1219
|
+
if (routineHints.length) {
|
|
1220
|
+
for (const h of routineHints) {
|
|
1221
|
+
console.log(` ${c ? dim : ''}•${c ? reset : ''} ${h}`);
|
|
1222
|
+
}
|
|
1223
|
+
} else {
|
|
1224
|
+
console.log(` ${c ? dim : ''}•${c ? reset : ''} Nenhum (ajuste scan_max_age_days / compact_max_age_days em .oxe/config.json se quiser lembretes por idade)${reset}`);
|
|
1225
|
+
}
|
|
1226
|
+
}
|
|
1156
1227
|
|
|
1157
1228
|
console.log(`\n ${c ? yellow : ''}Próximo passo sugerido (único)${reset}`);
|
|
1158
1229
|
console.log(` ${c ? dim : ''}Passo:${c ? reset : ''} ${c ? green : ''}${next.step}${reset}`);
|
|
@@ -1451,6 +1522,7 @@ ${green}Opções da instalação:${reset}
|
|
|
1451
1522
|
${green}status${reset} (coerência .oxe/ + um próximo passo sugerido; não exige pacote de workflows completo)
|
|
1452
1523
|
--dir <pasta> raiz do projeto (padrão: diretório atual)
|
|
1453
1524
|
--json imprime um único objeto JSON (próximo passo + diagnósticos) em stdout; adequado a CI
|
|
1525
|
+
--hints lembretes de rotina (idade scan/compact quando configurado em config.json); com --json inclui array \`hints\`
|
|
1454
1526
|
|
|
1455
1527
|
${green}Atualizar (projeto já tem OXE):${reset}
|
|
1456
1528
|
/oxe-update no Cursor (outras IDEs: mesmo fluxo pelo terminal)
|
|
@@ -2442,7 +2514,7 @@ async function main() {
|
|
|
2442
2514
|
console.error(`${yellow}Diretório não encontrado: ${target}${reset}`);
|
|
2443
2515
|
process.exit(1);
|
|
2444
2516
|
}
|
|
2445
|
-
runStatus(target, { json: opts.jsonOutput });
|
|
2517
|
+
runStatus(target, { json: opts.jsonOutput, hints: opts.statusHints });
|
|
2446
2518
|
return;
|
|
2447
2519
|
}
|
|
2448
2520
|
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: oxe:checkpoint
|
|
3
|
+
description: OXE — Marco em .oxe/checkpoints/ + CHECKPOINTS.md
|
|
4
|
+
argument-hint: "<slug> [nota]"
|
|
5
|
+
allowed-tools:
|
|
6
|
+
- Read
|
|
7
|
+
- Bash
|
|
8
|
+
- Glob
|
|
9
|
+
- Grep
|
|
10
|
+
- Write
|
|
11
|
+
- Task
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
**Workflow canónico:** `oxe/workflows/checkpoint.md`
|
|
15
|
+
|
|
16
|
+
Execute integralmente. `$ARGUMENTS` = slug obrigatório + nota opcional.
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: oxe:compact
|
|
3
|
+
description: OXE — refresh codebase vs repo + CODEBASE-DELTA + RESUME (rotina de projeto)
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# OXE — compact
|
|
7
|
+
|
|
8
|
+
**Workflow canónico:** `oxe/workflows/compact.md`
|
|
9
|
+
|
|
10
|
+
Execute integralmente. Atualiza **`.oxe/codebase/*.md`**, **`.oxe/CODEBASE-DELTA.md`** e **`.oxe/RESUME.md`**. `$ARGUMENTS` = foco opcional (ex. módulo) ou notas para Decisões/Bloqueios no RESUME.
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: oxe:debug
|
|
3
|
+
description: OXE — Debug técnico durante execute (.oxe/DEBUG.md)
|
|
4
|
+
argument-hint: "[Tn ou erro/stack]"
|
|
5
|
+
allowed-tools:
|
|
6
|
+
- Read
|
|
7
|
+
- Bash
|
|
8
|
+
- Glob
|
|
9
|
+
- Grep
|
|
10
|
+
- Write
|
|
11
|
+
- Task
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
**Workflow canónico:** `oxe/workflows/debug.md`
|
|
15
|
+
|
|
16
|
+
Execute integralmente esse ficheiro na raiz do repositório. Usa `$ARGUMENTS` como sintoma ou tarefa **Tn**.
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: oxe:forensics
|
|
3
|
+
description: OXE — Forensics pós-falha (.oxe/FORENSICS.md + próximo passo scan/plan/execute)
|
|
4
|
+
argument-hint: "[sintoma opcional]"
|
|
5
|
+
allowed-tools:
|
|
6
|
+
- Read
|
|
7
|
+
- Bash
|
|
8
|
+
- Glob
|
|
9
|
+
- Grep
|
|
10
|
+
- Write
|
|
11
|
+
- Task
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
**Workflow canónico:** `oxe/workflows/forensics.md`
|
|
15
|
+
|
|
16
|
+
Execute integralmente esse ficheiro na raiz do repositório. Usa `$ARGUMENTS` como contexto do sintoma.
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: oxe:plan-agent
|
|
3
|
+
description: Gera PLAN.md e plan-agents.json (blueprint de agentes e ondas)
|
|
4
|
+
argument-hint: "[--replan se já existe PLAN.md]"
|
|
5
|
+
allowed-tools:
|
|
6
|
+
- Read
|
|
7
|
+
- Write
|
|
8
|
+
- Glob
|
|
9
|
+
- Grep
|
|
10
|
+
- Bash
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
**Workflow canónico:** `oxe/workflows/plan-agent.md`
|
|
14
|
+
|
|
15
|
+
Execute integralmente esse ficheiro. Se `$ARGUMENTS` contiver `--replan`, seguir a variante de replanejamento descrita no workflow.
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: oxe:research
|
|
3
|
+
description: OXE — Pesquisa exploratória (notas datadas em .oxe/research/ + RESEARCH.md)
|
|
4
|
+
argument-hint: "[âmbito: spike, mapa sistema, reversa, modernização, …]"
|
|
5
|
+
allowed-tools:
|
|
6
|
+
- Read
|
|
7
|
+
- Bash
|
|
8
|
+
- Glob
|
|
9
|
+
- Grep
|
|
10
|
+
- Write
|
|
11
|
+
- Task
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
**Workflow canónico:** `oxe/workflows/research.md`
|
|
15
|
+
|
|
16
|
+
Execute integralmente esse ficheiro na raiz do repositório. Usa `$ARGUMENTS` como âmbito e perguntas.
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: oxe:route
|
|
3
|
+
description: OXE — Router linguagem natural → um comando/workflow
|
|
4
|
+
argument-hint: "[frase do utilizador]"
|
|
5
|
+
allowed-tools:
|
|
6
|
+
- Read
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
**Workflow canónico:** `oxe/workflows/route.md`
|
|
10
|
+
|
|
11
|
+
Execute integralmente esse ficheiro. Usa `$ARGUMENTS` como pedido a classificar (ver tabela Router em `help.md`).
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: oxe:ui-review
|
|
3
|
+
description: OXE — Auditoria UI (.oxe/UI-REVIEW.md)
|
|
4
|
+
argument-hint: "[paths ou Tn opcional]"
|
|
5
|
+
allowed-tools:
|
|
6
|
+
- Read
|
|
7
|
+
- Bash
|
|
8
|
+
- Glob
|
|
9
|
+
- Grep
|
|
10
|
+
- Write
|
|
11
|
+
- Task
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
**Workflow canónico:** `oxe/workflows/ui-review.md`
|
|
15
|
+
|
|
16
|
+
Execute integralmente esse ficheiro na raiz do repositório. Usa `$ARGUMENTS` como âmbito da revisão.
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: oxe:ui-spec
|
|
3
|
+
description: OXE — Contrato UI (.oxe/UI-SPEC.md) a partir da SPEC
|
|
4
|
+
argument-hint: "[âmbito UI opcional]"
|
|
5
|
+
allowed-tools:
|
|
6
|
+
- Read
|
|
7
|
+
- Bash
|
|
8
|
+
- Glob
|
|
9
|
+
- Grep
|
|
10
|
+
- Write
|
|
11
|
+
- Task
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
**Workflow canónico:** `oxe/workflows/ui-spec.md`
|
|
15
|
+
|
|
16
|
+
Execute integralmente esse ficheiro na raiz do repositório. Usa `$ARGUMENTS` como foco opcional de UI.
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: oxe:validate-gaps
|
|
3
|
+
description: OXE — Auditoria Nyquist-lite (.oxe/VALIDATION-GAPS.md) após verify
|
|
4
|
+
argument-hint: "[opcional: Tn ou A*]"
|
|
5
|
+
allowed-tools:
|
|
6
|
+
- Read
|
|
7
|
+
- Bash
|
|
8
|
+
- Glob
|
|
9
|
+
- Grep
|
|
10
|
+
- Write
|
|
11
|
+
- Task
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
**Workflow canónico:** `oxe/workflows/validate-gaps.md`
|
|
15
|
+
|
|
16
|
+
Execute integralmente esse ficheiro na raiz do repositório. Pré-requisito: `VERIFY.md` e `PLAN.md`. `$ARGUMENTS` = foco opcional.
|
package/lib/sdk/README.md
CHANGED
|
@@ -52,3 +52,15 @@ const { options, warnings: w } = oxe.install.resolveOptionsFromConfig(dir, {
|
|
|
52
52
|
| **doctor** | `runDoctorChecks` — resultado estruturado (erros + avisos + diff de workflows + `workflowShape` com lint leve dos `.md`) |
|
|
53
53
|
|
|
54
54
|
TypeScript: ver `index.d.ts` junto deste ficheiro.
|
|
55
|
+
|
|
56
|
+
## `health.buildHealthReport` e `parseLastCompactDate`
|
|
57
|
+
|
|
58
|
+
- **`parseLastCompactDate(stateText)`** — lê a data em **`.oxe/STATE.md`** na secção **Último compact** (mesma convenção que **Último scan**). Devolve `Date | null` se a linha for placeholder ou ilegível.
|
|
59
|
+
- **`buildHealthReport(projectRoot)`** — agrega fase, datas, avisos de SPEC/PLAN/VERIFY e o próximo passo sugerido. Campos usados em CI e em `oxe-cc status --json`:
|
|
60
|
+
- **`scanDate`**, **`stale`** — último scan e idade face a `scan_max_age_days` (`stale: { stale, days }`).
|
|
61
|
+
- **`compactDate`**, **`staleCompact`** — último compact e idade face a `compact_max_age_days`.
|
|
62
|
+
- **`next`** — `{ step, cursorCmd, reason, artifacts }` (espelha a lógica de `suggestNextStep`).
|
|
63
|
+
|
|
64
|
+
## `runDoctorChecks` e relatório de saúde
|
|
65
|
+
|
|
66
|
+
O resultado inclui **`healthReport`** com a mesma forma que `buildHealthReport` — útil em pipelines para falhar ou avisar quando `healthReport.stale.stale` ou `healthReport.staleCompact.stale` é verdadeiro (alinhado aos avisos do `oxe-cc doctor`).
|
package/lib/sdk/index.cjs
CHANGED
|
@@ -193,6 +193,7 @@ module.exports = {
|
|
|
193
193
|
oxePaths: health.oxePaths,
|
|
194
194
|
parseStatePhase: health.parseStatePhase,
|
|
195
195
|
parseLastScanDate: health.parseLastScanDate,
|
|
196
|
+
parseLastCompactDate: health.parseLastCompactDate,
|
|
196
197
|
isStaleScan: health.isStaleScan,
|
|
197
198
|
phaseCoherenceWarnings: health.phaseCoherenceWarnings,
|
|
198
199
|
specSectionWarnings: health.specSectionWarnings,
|
package/lib/sdk/index.d.ts
CHANGED
|
@@ -32,6 +32,39 @@ export interface WorkflowShapeResult {
|
|
|
32
32
|
warnings: DoctorIssue[];
|
|
33
33
|
}
|
|
34
34
|
|
|
35
|
+
/** Idade do scan ou do compact face a `scan_max_age_days` / `compact_max_age_days`. */
|
|
36
|
+
export interface HealthStaleInfo {
|
|
37
|
+
stale: boolean;
|
|
38
|
+
days: number | null;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export interface OxeNextSuggestion {
|
|
42
|
+
step: string;
|
|
43
|
+
cursorCmd: string;
|
|
44
|
+
reason: string;
|
|
45
|
+
artifacts: string[];
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/** Relatório retornado por `health.buildHealthReport` e incluído em `runDoctorChecks`.healthReport. */
|
|
49
|
+
export interface OxeHealthReport {
|
|
50
|
+
configPath: string | null;
|
|
51
|
+
configParseError: string | null;
|
|
52
|
+
unknownConfigKeys: string[];
|
|
53
|
+
typeErrors: string[];
|
|
54
|
+
phase: string | null;
|
|
55
|
+
scanDate: Date | null;
|
|
56
|
+
stale: HealthStaleInfo;
|
|
57
|
+
compactDate: Date | null;
|
|
58
|
+
staleCompact: HealthStaleInfo;
|
|
59
|
+
phaseWarn: string[];
|
|
60
|
+
summaryGapWarn: string | null;
|
|
61
|
+
specWarn: string[];
|
|
62
|
+
planWarn: string[];
|
|
63
|
+
next: OxeNextSuggestion;
|
|
64
|
+
scanFocusGlobs?: unknown;
|
|
65
|
+
scanIgnoreGlobs?: unknown;
|
|
66
|
+
}
|
|
67
|
+
|
|
35
68
|
export interface DoctorChecksResult {
|
|
36
69
|
ok: boolean;
|
|
37
70
|
errors: DoctorIssue[];
|
|
@@ -46,7 +79,7 @@ export interface DoctorChecksResult {
|
|
|
46
79
|
parseError: string | null;
|
|
47
80
|
};
|
|
48
81
|
validation: { unknownKeys: string[]; typeErrors: string[] };
|
|
49
|
-
healthReport:
|
|
82
|
+
healthReport: OxeHealthReport;
|
|
50
83
|
workflowShape: WorkflowShapeResult | null;
|
|
51
84
|
}
|
|
52
85
|
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "https://oxe-cc.local/schemas/plan-agents.schema.json",
|
|
4
|
+
"title": "OXE plan-agents blueprint",
|
|
5
|
+
"type": "object",
|
|
6
|
+
"additionalProperties": false,
|
|
7
|
+
"required": ["oxePlanAgentsSchema", "goal", "agents", "execution"],
|
|
8
|
+
"properties": {
|
|
9
|
+
"oxePlanAgentsSchema": {
|
|
10
|
+
"type": "integer",
|
|
11
|
+
"enum": [1, 2]
|
|
12
|
+
},
|
|
13
|
+
"goal": { "type": "string", "minLength": 1 },
|
|
14
|
+
"specRef": { "type": "string" },
|
|
15
|
+
"runId": {
|
|
16
|
+
"type": "string",
|
|
17
|
+
"minLength": 8,
|
|
18
|
+
"description": "Obrigatório quando oxePlanAgentsSchema === 2"
|
|
19
|
+
},
|
|
20
|
+
"lifecycle": {
|
|
21
|
+
"type": "object",
|
|
22
|
+
"additionalProperties": false,
|
|
23
|
+
"required": ["status", "since"],
|
|
24
|
+
"properties": {
|
|
25
|
+
"status": {
|
|
26
|
+
"type": "string",
|
|
27
|
+
"enum": ["pending_execute", "executing", "closed", "invalidated"]
|
|
28
|
+
},
|
|
29
|
+
"since": { "type": "string", "minLength": 1 },
|
|
30
|
+
"invalidatedReason": { "type": "string" },
|
|
31
|
+
"invalidatedBy": {
|
|
32
|
+
"type": "string",
|
|
33
|
+
"enum": ["quick", "out_of_scope", "new_plan", "manual"]
|
|
34
|
+
}
|
|
35
|
+
},
|
|
36
|
+
"description": "Obrigatório quando oxePlanAgentsSchema === 2"
|
|
37
|
+
},
|
|
38
|
+
"agents": {
|
|
39
|
+
"type": "array",
|
|
40
|
+
"minItems": 1,
|
|
41
|
+
"items": {
|
|
42
|
+
"type": "object",
|
|
43
|
+
"additionalProperties": false,
|
|
44
|
+
"required": ["id", "role", "scope", "taskIds"],
|
|
45
|
+
"properties": {
|
|
46
|
+
"id": {
|
|
47
|
+
"type": "string",
|
|
48
|
+
"pattern": "^[a-z0-9][a-z0-9-]*$"
|
|
49
|
+
},
|
|
50
|
+
"role": { "type": "string", "minLength": 1 },
|
|
51
|
+
"scope": {
|
|
52
|
+
"type": "array",
|
|
53
|
+
"items": { "type": "string" },
|
|
54
|
+
"minItems": 1
|
|
55
|
+
},
|
|
56
|
+
"taskIds": {
|
|
57
|
+
"type": "array",
|
|
58
|
+
"items": {
|
|
59
|
+
"type": "string",
|
|
60
|
+
"pattern": "^T[1-9][0-9]*$"
|
|
61
|
+
},
|
|
62
|
+
"minItems": 1
|
|
63
|
+
},
|
|
64
|
+
"dependencies": {
|
|
65
|
+
"type": "array",
|
|
66
|
+
"items": { "type": "string" }
|
|
67
|
+
},
|
|
68
|
+
"inputs": {
|
|
69
|
+
"type": "array",
|
|
70
|
+
"items": { "type": "string" }
|
|
71
|
+
},
|
|
72
|
+
"outputs": {
|
|
73
|
+
"type": "array",
|
|
74
|
+
"items": { "type": "string" }
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
},
|
|
79
|
+
"execution": {
|
|
80
|
+
"type": "object",
|
|
81
|
+
"additionalProperties": false,
|
|
82
|
+
"required": ["strategy", "waves"],
|
|
83
|
+
"properties": {
|
|
84
|
+
"strategy": {
|
|
85
|
+
"type": "string",
|
|
86
|
+
"enum": ["sequential", "parallel_per_wave", "hybrid"]
|
|
87
|
+
},
|
|
88
|
+
"waves": {
|
|
89
|
+
"type": "array",
|
|
90
|
+
"minItems": 1,
|
|
91
|
+
"items": {
|
|
92
|
+
"type": "array",
|
|
93
|
+
"minItems": 1,
|
|
94
|
+
"items": { "type": "string" }
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
},
|
|
100
|
+
"allOf": [
|
|
101
|
+
{
|
|
102
|
+
"if": {
|
|
103
|
+
"properties": { "oxePlanAgentsSchema": { "const": 2 } },
|
|
104
|
+
"required": ["oxePlanAgentsSchema"]
|
|
105
|
+
},
|
|
106
|
+
"then": {
|
|
107
|
+
"required": ["oxePlanAgentsSchema", "goal", "agents", "execution", "runId", "lifecycle"]
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
]
|
|
111
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
---
|
|
2
|
+
oxe_checkpoint: true
|
|
3
|
+
created: YYYY-MM-DDTHH:mm
|
|
4
|
+
slug: short-slug
|
|
5
|
+
linked:
|
|
6
|
+
- .oxe/STATE.md
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# Checkpoint OXE — <slug>
|
|
10
|
+
|
|
11
|
+
> Marco **nomeado** em disco. Para retomar: lê este ficheiro + os **linked** acima; não substitui o fluxo canónico.
|
|
12
|
+
|
|
13
|
+
## Nota do utilizador
|
|
14
|
+
|
|
15
|
+
(O que o utilizador pediu a gravar em `$ARGUMENTS`, ou *—*.)
|
|
16
|
+
|
|
17
|
+
## Snapshot (colado ou resumido)
|
|
18
|
+
|
|
19
|
+
### STATE (trecho relevante)
|
|
20
|
+
|
|
21
|
+
```text
|
|
22
|
+
(colar cabeçalho / fase / próximo passo)
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
### SPEC — objetivo (uma linha)
|
|
26
|
+
|
|
27
|
+
…
|
|
28
|
+
|
|
29
|
+
### PLAN — resumo
|
|
30
|
+
|
|
31
|
+
- Ondas: …
|
|
32
|
+
- Tarefas abertas (Tn): …
|
|
33
|
+
|
|
34
|
+
## Restaurar
|
|
35
|
+
|
|
36
|
+
1. Abrir ficheiros em `linked` no frontmatter (atualizar paths se renomeaste).
|
|
37
|
+
2. Próximo comando OXE: (preencher, ex. `oxe:execute` onda N)
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# OXE — Delta do codebase (último compact)
|
|
2
|
+
|
|
3
|
+
> Gerado por **`/oxe-compact`**: o que **mudou na documentação** em `.oxe/codebase/` face à leitura anterior do repo. **Não** é diff de Git; é **sincronização documentação ↔ código**.
|
|
4
|
+
|
|
5
|
+
## Meta
|
|
6
|
+
|
|
7
|
+
- **Atualizado:** YYYY-MM-DD (ISO)
|
|
8
|
+
- **Modo:** incremental | bootstrap-completo *(bootstrap = faltavam mapas ou scan equivalente foi aplicado)*
|
|
9
|
+
|
|
10
|
+
## Resumo executivo
|
|
11
|
+
|
|
12
|
+
- (3–7 bullets: principais divergências corrigidas, novos módulos/pastas, stack ou testes que mudaram)
|
|
13
|
+
- (ex.: *STACK: migração Angular 17 → 21 refletida; TESTING: `ng test` / CI atualizados*)
|
|
14
|
+
|
|
15
|
+
## Por ficheiro em `.oxe/codebase/`
|
|
16
|
+
|
|
17
|
+
| Ficheiro | Mudança na doc |
|
|
18
|
+
|----------|------------------|
|
|
19
|
+
| OVERVIEW.md | ex.: atualizado — novo domínio X |
|
|
20
|
+
| STACK.md | ex.: **Angular 17 → 21** conforme repo; ou *sem alteração relevante* |
|
|
21
|
+
| STRUCTURE.md | … |
|
|
22
|
+
| TESTING.md | … |
|
|
23
|
+
| INTEGRATIONS.md | … |
|
|
24
|
+
| CONVENTIONS.md | … |
|
|
25
|
+
| CONCERNS.md | … |
|
|
26
|
+
|
|
27
|
+
## Lacunas / não verificado aqui
|
|
28
|
+
|
|
29
|
+
- (comandos não corridos, paths não abertos, incertezas — ou *Nenhuma*)
|
|
30
|
+
|
|
31
|
+
## Ligação à trilha OXE
|
|
32
|
+
|
|
33
|
+
- Ver também **`.oxe/RESUME.md`** para fase, SPEC/PLAN e próximo passo.
|
package/oxe/templates/CONFIG.md
CHANGED
|
@@ -9,6 +9,7 @@ Copie `oxe/templates/config.template.json` para **`.oxe/config.json`** no seu pr
|
|
|
9
9
|
| `after_verify_draft_commit` | boolean | Se `true`, o **verify** propõe rascunho de mensagem de commit alinhado aos critérios de aceite. |
|
|
10
10
|
| `default_verify_command` | string | Comando guarda-chuva opcional (ex.: `npm test`) sugerido em **plan**/**verify** quando o projeto não define outro. |
|
|
11
11
|
| `scan_max_age_days` | number | Se **> 0**, `oxe-cc doctor` / `status` avisam quando a **Data** do último scan em `STATE.md` é mais antiga que esse número de dias. Use **0** para desligar. |
|
|
12
|
+
| `compact_max_age_days` | number | Se **> 0**, `oxe-cc doctor` / `status` avisam quando a **Data** em **Último compact (codebase + RESUME)** em `STATE.md` é mais antiga que esse número de dias (preenchida por **`/oxe-compact`**). Use **0** para desligar. |
|
|
12
13
|
| `scan_focus_globs` | string[] | Padrões (ex.: `src/api/**`) que o workflow **scan** deve priorizar; só orientação para o agente. |
|
|
13
14
|
| `scan_ignore_globs` | string[] | Padrões a tratar como baixa prioridade ou omitir no scan (ex.: `**/dist/**`). |
|
|
14
15
|
| `spec_required_sections` | string[] | Cabeçalhos que **devem** existir em `SPEC.md` (ex.: `"## Critérios de aceite"`). `doctor` / `status` emitem aviso se faltar. |
|