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.
Files changed (75) hide show
  1. package/.cursor/commands/oxe-checkpoint.md +9 -0
  2. package/.cursor/commands/oxe-compact.md +9 -0
  3. package/.cursor/commands/oxe-debug.md +9 -0
  4. package/.cursor/commands/oxe-forensics.md +9 -0
  5. package/.cursor/commands/oxe-plan-agent.md +9 -0
  6. package/.cursor/commands/oxe-research.md +9 -0
  7. package/.cursor/commands/oxe-route.md +9 -0
  8. package/.cursor/commands/oxe-ui-review.md +9 -0
  9. package/.cursor/commands/oxe-ui-spec.md +9 -0
  10. package/.cursor/commands/oxe-validate-gaps.md +9 -0
  11. package/.github/copilot-instructions.md +14 -4
  12. package/.github/prompts/oxe-checkpoint.prompt.md +12 -0
  13. package/.github/prompts/oxe-compact.prompt.md +11 -0
  14. package/.github/prompts/oxe-debug.prompt.md +12 -0
  15. package/.github/prompts/oxe-forensics.prompt.md +12 -0
  16. package/.github/prompts/oxe-plan-agent.prompt.md +10 -0
  17. package/.github/prompts/oxe-research.prompt.md +12 -0
  18. package/.github/prompts/oxe-route.prompt.md +12 -0
  19. package/.github/prompts/oxe-ui-review.prompt.md +12 -0
  20. package/.github/prompts/oxe-ui-spec.prompt.md +12 -0
  21. package/.github/prompts/oxe-validate-gaps.prompt.md +12 -0
  22. package/AGENTS.md +1 -1
  23. package/README.md +108 -9
  24. package/bin/banner.txt +1 -1
  25. package/bin/lib/oxe-project-health.cjs +33 -0
  26. package/bin/oxe-cc.js +87 -15
  27. package/commands/oxe/checkpoint.md +16 -0
  28. package/commands/oxe/compact.md +10 -0
  29. package/commands/oxe/debug.md +16 -0
  30. package/commands/oxe/forensics.md +16 -0
  31. package/commands/oxe/plan-agent.md +15 -0
  32. package/commands/oxe/research.md +16 -0
  33. package/commands/oxe/route.md +11 -0
  34. package/commands/oxe/ui-review.md +16 -0
  35. package/commands/oxe/ui-spec.md +16 -0
  36. package/commands/oxe/validate-gaps.md +16 -0
  37. package/lib/sdk/README.md +12 -0
  38. package/lib/sdk/index.cjs +1 -0
  39. package/lib/sdk/index.d.ts +34 -1
  40. package/oxe/schemas/plan-agents.schema.json +111 -0
  41. package/oxe/templates/CHECKPOINT.template.md +37 -0
  42. package/oxe/templates/CODEBASE-DELTA.template.md +33 -0
  43. package/oxe/templates/CONFIG.md +1 -0
  44. package/oxe/templates/GIT_HOOKS_OXE.md +52 -0
  45. package/oxe/templates/PLAN.template.md +12 -0
  46. package/oxe/templates/RESEARCH.template.md +50 -0
  47. package/oxe/templates/RESUME.template.md +49 -0
  48. package/oxe/templates/SPEC.template.md +13 -0
  49. package/oxe/templates/STATE.md +14 -0
  50. package/oxe/templates/WORKFLOW_AUTHORING.md +3 -1
  51. package/oxe/templates/config.template.json +1 -0
  52. package/oxe/templates/plan-agent-messages-README.template.md +9 -0
  53. package/oxe/templates/plan-agents.template.json +28 -0
  54. package/oxe/workflows/checkpoint.md +32 -0
  55. package/oxe/workflows/compact.md +44 -0
  56. package/oxe/workflows/debug.md +31 -0
  57. package/oxe/workflows/discuss.md +8 -5
  58. package/oxe/workflows/execute.md +10 -0
  59. package/oxe/workflows/forensics.md +42 -0
  60. package/oxe/workflows/help.md +75 -9
  61. package/oxe/workflows/next.md +3 -2
  62. package/oxe/workflows/plan-agent.md +93 -0
  63. package/oxe/workflows/plan.md +27 -5
  64. package/oxe/workflows/quick.md +16 -2
  65. package/oxe/workflows/references/plan-agent-chat-protocol.md +85 -0
  66. package/oxe/workflows/research.md +35 -0
  67. package/oxe/workflows/route.md +27 -0
  68. package/oxe/workflows/scan.md +2 -0
  69. package/oxe/workflows/spec.md +3 -1
  70. package/oxe/workflows/ui-review.md +26 -0
  71. package/oxe/workflows/ui-spec.md +26 -0
  72. package/oxe/workflows/update.md +1 -1
  73. package/oxe/workflows/validate-gaps.md +34 -0
  74. package/oxe/workflows/verify.md +5 -0
  75. 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 (estilo GSD).
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), estilo GSD. */
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 (config.scan_max_age_days > 0 && r.scanDate && r.stale.stale) {
1081
- console.log(
1082
- ` ${yellow}AVISO${reset} Último scan há ~${r.stale.days} dia(s) (limite: ${config.scan_max_age_days}) — considere ${cyan}/oxe-scan${reset}`
1083
- );
1084
- } else if (config.scan_max_age_days > 0 && !r.scanDate && fs.existsSync(path.join(target, '.oxe', 'STATE.md'))) {
1085
- console.log(
1086
- ` ${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`
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: 1,
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,
@@ -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: Record<string, unknown>;
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.
@@ -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. |