oxe-cc 1.8.0 → 1.8.3
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/CHANGELOG.md +63 -0
- package/README.md +1 -1
- package/bin/lib/oxe-manifest.cjs +20 -13
- package/bin/lib/oxe-operational.cjs +96 -10
- package/bin/lib/oxe-project-health.cjs +77 -18
- package/bin/lib/oxe-rationality.cjs +9 -7
- package/bin/oxe-cc.js +202 -39
- package/lib/runtime/compiler/graph-compiler.js +1 -1
- package/lib/runtime/executor/action-tool-map.js +4 -0
- package/lib/runtime/executor/built-in-tools.js +27 -0
- package/lib/runtime/executor/llm-task-executor.d.ts +4 -1
- package/lib/runtime/executor/llm-task-executor.js +41 -5
- package/lib/runtime/executor/node-prompt-builder.d.ts +4 -1
- package/lib/runtime/executor/node-prompt-builder.js +13 -2
- package/lib/runtime/models/failure.d.ts +1 -1
- package/lib/runtime/scheduler/scheduler.d.ts +5 -1
- package/lib/runtime/scheduler/scheduler.js +82 -14
- package/lib/runtime/verification/verification-compiler.js +7 -5
- package/lib/sdk/index.cjs +48 -44
- package/oxe/templates/PLAN.template.md +23 -9
- package/oxe/templates/SPEC.template.md +55 -22
- package/oxe/workflows/plan.md +18 -6
- package/oxe/workflows/spec.md +31 -9
- package/package.json +103 -100
- package/packages/runtime/package.json +18 -18
- package/packages/runtime/src/compiler/graph-compiler.ts +1 -1
- package/packages/runtime/src/evidence/evidence-store.ts +2 -2
- package/packages/runtime/src/executor/action-tool-map.ts +4 -0
- package/packages/runtime/src/executor/built-in-tools.ts +29 -0
- package/packages/runtime/src/executor/llm-task-executor.ts +46 -4
- package/packages/runtime/src/executor/node-prompt-builder.ts +18 -1
- package/packages/runtime/src/models/failure.ts +2 -0
- package/packages/runtime/src/scheduler/scheduler.ts +93 -15
- package/packages/runtime/src/verification/verification-compiler.ts +7 -5
- package/vscode-extension/package.json +185 -185
- package/vscode-extension/oxe-agents-0.9.1.vsix +0 -0
- package/vscode-extension/oxe-agents-0.9.2.vsix +0 -0
- package/vscode-extension/oxe-agents-1.0.0.vsix +0 -0
- package/vscode-extension/oxe-agents-1.4.0.vsix +0 -0
- package/vscode-extension/oxe-agents-1.5.0.vsix +0 -0
- package/vscode-extension/oxe-agents-1.5.1.vsix +0 -0
- package/vscode-extension/oxe-agents-1.6.0.vsix +0 -0
- package/vscode-extension/oxe-agents-1.7.0.vsix +0 -0
- package/vscode-extension/oxe-agents-1.8.0.vsix +0 -0
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,69 @@ Todas as versões seguem [Semantic Versioning](https://semver.org/). As mudança
|
|
|
4
4
|
|
|
5
5
|
---
|
|
6
6
|
|
|
7
|
+
## [1.8.3] — 2026-05-04
|
|
8
|
+
|
|
9
|
+
### Release readiness e higiene de publicação
|
|
10
|
+
|
|
11
|
+
Esta release consolida a linha `1.8.3` para publicação no npm com foco em consistência de versão, alinhamento documental e pacote distribuído mais limpo.
|
|
12
|
+
|
|
13
|
+
#### Publicação
|
|
14
|
+
|
|
15
|
+
- alinhamento da versão `1.8.3` entre manifesto raiz, runtime, extensão VS Code, README e changelog
|
|
16
|
+
- fechamento do gate oficial `doctor --release` para a linha atual
|
|
17
|
+
- preparação do pacote npm para sair sem drift entre versão publicada e documentação principal
|
|
18
|
+
|
|
19
|
+
#### Higiene do pacote
|
|
20
|
+
|
|
21
|
+
- exclusão dos arquivos `.vsix` históricos da extensão VS Code do tarball npm
|
|
22
|
+
- manutenção apenas do código-fonte da extensão dentro do pacote, evitando distribuir binários legados desnecessários
|
|
23
|
+
|
|
24
|
+
## [1.8.2] — 2026-04-30
|
|
25
|
+
|
|
26
|
+
### Fluxo inicial mais coerente e geração de `spec`/`plan` mais forte
|
|
27
|
+
|
|
28
|
+
Esta release fecha a linha de robustez do ciclo `install -> status/doctor -> /oxe -> spec -> plan -> execute -> verify` sem abrir nova superfície pública. O foco foi remover ruído operacional em projetos novos e aumentar a densidade executável dos artefatos que o OXE induz.
|
|
29
|
+
|
|
30
|
+
#### Fluxo operacional
|
|
31
|
+
|
|
32
|
+
- `install`, `status` e `doctor` passam a convergir em `/oxe` como próximo passo canônico para projetos recém-inicializados
|
|
33
|
+
- `doctor` e `status` deixam de tratar `IMPLEMENTATION-PACK`, `REFERENCE-ANCHORS` e `FIXTURE-PACK` como blocker primário antes de existir `PLAN.md`
|
|
34
|
+
- o relatório racional agora marca o estado sem plano como `não aplicável ainda`, sem contaminar o próximo passo
|
|
35
|
+
- instalações e desinstalações locais por runtime continuam simétricas, com inferência de artefatos locais preservada
|
|
36
|
+
|
|
37
|
+
#### Indução mais forte de SPEC e PLAN
|
|
38
|
+
|
|
39
|
+
- `SPEC.template.md` passou a exigir outcome observável, público-alvo, restrições técnicas, setup externo, conteúdo/fluxos obrigatórios e contratos esperados para o plano
|
|
40
|
+
- `PLAN.template.md` ganhou contrato operacional da solução, densidade operacional mínima, `symbols alvo`, `estado/fluxo coberto` e `fixture/anchor obrigatório` por tarefa
|
|
41
|
+
- `oxe/workflows/spec.md` agora força extração explícita de blocos de interface, conteúdo mínimo, interações, responsividade e acessibilidade em demandas de produto/app/UI
|
|
42
|
+
- `oxe/workflows/plan.md` agora endurece o gate de confiança `>90%` para tarefas mutáveis vagas e exige fechamento mais forte de interface, conteúdo, estado persistido, anchors e fixtures em apps/UI estáticos
|
|
43
|
+
|
|
44
|
+
#### Testes
|
|
45
|
+
|
|
46
|
+
- novo teste cobrindo o estado racional não bloqueante antes da existência de `PLAN.md`
|
|
47
|
+
- suíte focada de CLI/health atualizada para manter o comportamento novo estável
|
|
48
|
+
|
|
49
|
+
## [1.8.1] — 2026-04-30
|
|
50
|
+
|
|
51
|
+
### Hotfix — Gaps implementados no fonte TypeScript (não em arquivos compilados)
|
|
52
|
+
|
|
53
|
+
A v1.8.0 aplicou as 5 correções críticas diretamente nos arquivos `.js` compilados (`lib/runtime/`), que são sobrescritos a cada `npm run build:runtime`. Esta release porta todas as correções para o fonte TypeScript em `packages/runtime/src/`, tornando-as permanentes.
|
|
54
|
+
|
|
55
|
+
#### Correções portadas para TypeScript
|
|
56
|
+
|
|
57
|
+
- **`models/failure.ts`**: `FailureClass` agora inclui `'verify'` e `'llm'` como classes canônicas
|
|
58
|
+
- **`scheduler/scheduler.ts`**: `TaskResult` com campo opcional `completed_by`; `TaskExecutor.execute()` aceita `options?: { previousError? }`; `verifyNode()` importa e chama `verifyRun` da fonte TS; `executeNode()` repassa `options`; `requestGateForNode()` com warning quando manager ausente
|
|
59
|
+
- **`executor/built-in-tools.ts`**: `finishTask` handler + registro em `BUILT_IN_TOOLS`
|
|
60
|
+
- **`executor/action-tool-map.ts`**: `finish_task` injetado universalmente em `selectToolsForActions()`
|
|
61
|
+
- **`executor/node-prompt-builder.ts`**: parâmetro `options`, seção de retry context, instrução `finish_task`
|
|
62
|
+
- **`executor/llm-task-executor.ts`**: detecção de `finish_task`, `completed_by` no retorno, `turn_limit_exhausted` retorna `success: false`
|
|
63
|
+
|
|
64
|
+
#### Testes
|
|
65
|
+
- 542 testes passando (era 542 na v1.8.0, nenhuma regressão)
|
|
66
|
+
- 36 testes de gaps (gap1–gap5) todos passando contra o código compilado
|
|
67
|
+
|
|
68
|
+
---
|
|
69
|
+
|
|
7
70
|
## [1.8.0] — 2026-04-29
|
|
8
71
|
|
|
9
72
|
### Autonomous Execution — 5 Critical Gaps Resolved
|
package/README.md
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
[](https://www.npmjs.com/package/oxe-cc)
|
|
8
8
|
[](LICENSE)
|
|
9
9
|
|
|
10
|
-
**Versão:** `1.8.
|
|
10
|
+
**Versão:** `1.8.3` · [package.json](package.json)
|
|
11
11
|
|
|
12
12
|
**Framework OXE — Orchestrated eXperience Engineering**
|
|
13
13
|
|
package/bin/lib/oxe-manifest.cjs
CHANGED
|
@@ -51,19 +51,26 @@ function writeFileManifest(home, files, version) {
|
|
|
51
51
|
* Before overwriting with --force, backup files that diverged from last manifest.
|
|
52
52
|
* @param {string} home
|
|
53
53
|
* @param {Record<string, string>} prevManifest
|
|
54
|
-
* @param {{ dryRun: boolean, force: boolean }} opts
|
|
55
|
-
* @param {{ yellow: string, cyan: string, dim: string, reset: string }} colors
|
|
56
|
-
* @
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
54
|
+
* @param {{ dryRun: boolean, force: boolean }} opts
|
|
55
|
+
* @param {{ yellow: string, cyan: string, dim: string, reset: string }} colors
|
|
56
|
+
* @param {{ scopeRoots?: string[] }} [scope]
|
|
57
|
+
* @returns {string[]} modified paths
|
|
58
|
+
*/
|
|
59
|
+
function backupModifiedFromManifest(home, prevManifest, opts, colors, scope = {}) {
|
|
60
|
+
const { yellow, cyan, dim, reset } = colors;
|
|
61
|
+
if (!opts.force || opts.dryRun) return [];
|
|
62
|
+
const normalizedRoots = Array.isArray(scope.scopeRoots)
|
|
63
|
+
? scope.scopeRoots.map((root) => path.resolve(root))
|
|
64
|
+
: [];
|
|
65
|
+
const modified = [];
|
|
66
|
+
for (const [absPath, oldHash] of Object.entries(prevManifest)) {
|
|
67
|
+
if (normalizedRoots.length > 0 && !normalizedRoots.some((root) => absPath === root || absPath.startsWith(`${root}${path.sep}`))) {
|
|
68
|
+
continue;
|
|
69
|
+
}
|
|
70
|
+
if (!fs.existsSync(absPath)) continue;
|
|
71
|
+
let now;
|
|
72
|
+
try {
|
|
73
|
+
now = sha256File(absPath);
|
|
67
74
|
} catch {
|
|
68
75
|
continue;
|
|
69
76
|
}
|
|
@@ -456,6 +456,61 @@ function reduceCanonicalRunState(projectRoot, activeSession, options = {}) {
|
|
|
456
456
|
return serializeCanonicalState(reduceCanonicalRunStateLive(projectRoot, activeSession, options));
|
|
457
457
|
}
|
|
458
458
|
|
|
459
|
+
/**
|
|
460
|
+
* Static-analysis lints for common pitfalls detectable before execution.
|
|
461
|
+
* Returns hint strings to be appended to validationErrors (shown at compile time).
|
|
462
|
+
*/
|
|
463
|
+
function lintPlanForCommonPitfalls(parsedPlan, parsedSpec, projectRoot, rawSpecText = '') {
|
|
464
|
+
const hints = [];
|
|
465
|
+
const specText = (parsedSpec && parsedSpec.objective ? parsedSpec.objective : '') +
|
|
466
|
+
JSON.stringify(parsedSpec && parsedSpec.criteria ? parsedSpec.criteria : []) +
|
|
467
|
+
(rawSpecText || '');
|
|
468
|
+
const planTasks = parsedPlan && Array.isArray(parsedPlan.tasks) ? parsedPlan.tasks : [];
|
|
469
|
+
|
|
470
|
+
// ── Lint 1: HTML/JS SPA sem restrição de file:// ──────────────────────────
|
|
471
|
+
// Detects: spec mentions HTML/SPA + no files restriction, but no verify command
|
|
472
|
+
// checks for fetch() absence. Warns to add a fetch-detection verify.
|
|
473
|
+
const isHtmlApp = /html|spa|browser|page|frontend|estático|static|aplicação web|web app|web page|interface web|\.html/i.test(specText);
|
|
474
|
+
if (isHtmlApp) {
|
|
475
|
+
const hasFetchGuard = planTasks.some(t =>
|
|
476
|
+
t.verifyCommand && /fetch|XMLHttpRequest|file:\/\//i.test(t.verifyCommand)
|
|
477
|
+
);
|
|
478
|
+
const specMentionsServer = /servidor|server|http-server|localhost|npx serve|vite|webpack/i.test(specText);
|
|
479
|
+
const specMentionsFileProtocol = /file:\/\/|sem servidor|without server|no.server/i.test(specText);
|
|
480
|
+
if (!hasFetchGuard && !specMentionsServer && !specMentionsFileProtocol) {
|
|
481
|
+
hints.push(
|
|
482
|
+
'HINT(html-fetch): SPEC não declara se o app precisa de servidor HTTP. ' +
|
|
483
|
+
'Se abrir em file://, adicione à SPEC: "sem servidor HTTP" e um verify que detecte fetch(): ' +
|
|
484
|
+
'`node -e "if(require(\'fs\').readFileSync(\'app.js\',\'utf8\').includes(\'fetch(\'))throw new Error(\'fetch not allowed in file://\')"`'
|
|
485
|
+
);
|
|
486
|
+
}
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
// ── Lint 2: Verify commands que só verificam existência de função, não comportamento ──
|
|
490
|
+
const existenceOnlyVerify = planTasks.filter(t =>
|
|
491
|
+
t.verifyCommand &&
|
|
492
|
+
/s\.includes\(/.test(t.verifyCommand) &&
|
|
493
|
+
!/existsSync|readFileSync.*utf8|require\(/.test(t.verifyCommand)
|
|
494
|
+
);
|
|
495
|
+
if (existenceOnlyVerify.length > 2) {
|
|
496
|
+
hints.push(
|
|
497
|
+
`HINT(verify-depth): ${existenceOnlyVerify.length} tarefa(s) verificam apenas presença de string no código ` +
|
|
498
|
+
`(s.includes). Considere adicionar verificações de comportamento: executar o código, não só inspecioná-lo.`
|
|
499
|
+
);
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
// ── Lint 3: Tarefas sem verify command (T-level) ──────────────────────────
|
|
503
|
+
const noVerify = planTasks.filter(t => !t.verifyCommand && !t.done);
|
|
504
|
+
if (noVerify.length > 0) {
|
|
505
|
+
hints.push(
|
|
506
|
+
`HINT(no-verify): ${noVerify.length} tarefa(s) sem Comando de verificação: ${noVerify.map(t => t.id).join(', ')}. ` +
|
|
507
|
+
`Tarefas sem verify não serão testadas inline pelo scheduler.`
|
|
508
|
+
);
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
return hints;
|
|
512
|
+
}
|
|
513
|
+
|
|
459
514
|
function compileExecutionGraphFromArtifacts(projectRoot, activeSession, options = {}) {
|
|
460
515
|
const runtime = loadRuntimeModule();
|
|
461
516
|
const parsers = loadSdkParsers();
|
|
@@ -468,12 +523,17 @@ function compileExecutionGraphFromArtifacts(projectRoot, activeSession, options
|
|
|
468
523
|
const artifactPaths = resolveRuntimeArtifactPaths(projectRoot, activeSession);
|
|
469
524
|
const specText = readTextIfExists(artifactPaths.spec);
|
|
470
525
|
const planText = readTextIfExists(artifactPaths.plan);
|
|
471
|
-
if (!specText) throw new Error(`SPEC.md ausente em ${artifactPaths.spec}`);
|
|
472
|
-
if (!planText) throw new Error(`PLAN.md ausente em ${artifactPaths.plan}`);
|
|
526
|
+
if (!specText) throw new Error(`SPEC.md ausente em ${artifactPaths.spec}\n Crie .oxe/SPEC.md com /oxe-spec no seu agente, ou use o template em oxe/templates/SPEC.template.md`);
|
|
527
|
+
if (!planText) throw new Error(`PLAN.md ausente em ${artifactPaths.plan}\n Crie .oxe/PLAN.md com /oxe-plan no seu agente (requer SPEC.md), ou use o template em oxe/templates/PLAN.template.md`);
|
|
473
528
|
const parsedSpec = parsers.parseSpec(specText);
|
|
474
529
|
const parsedPlan = parsers.parsePlan(planText);
|
|
475
530
|
const graph = runtime.compile(parsedPlan, parsedSpec, options.compilerOptions || {});
|
|
476
531
|
const validationErrors = typeof runtime.validateGraph === 'function' ? runtime.validateGraph(graph) : [];
|
|
532
|
+
|
|
533
|
+
// Static-analysis lints: detect common patterns that cause runtime failures
|
|
534
|
+
const lintHints = lintPlanForCommonPitfalls(parsedPlan, parsedSpec, projectRoot, specText);
|
|
535
|
+
if (lintHints.length) validationErrors.push(...lintHints);
|
|
536
|
+
|
|
477
537
|
const compiledGraph = runtime.toSerializable(graph);
|
|
478
538
|
const current = options.runState || readRunState(projectRoot, activeSession) || {};
|
|
479
539
|
const runId = current.run_id || makeRunId();
|
|
@@ -669,6 +729,20 @@ async function runRuntimeExecute(projectRoot, activeSession, options = {}) {
|
|
|
669
729
|
const parsers = loadSdkParsers();
|
|
670
730
|
if (!parsers) throw new Error('SDK parsers não disponíveis.');
|
|
671
731
|
|
|
732
|
+
// Auto-wire LlmTaskExecutor if providerConfig is supplied
|
|
733
|
+
let executor = options.executor || null;
|
|
734
|
+
if (!executor && options.providerConfig) {
|
|
735
|
+
if (typeof runtime.LlmTaskExecutor !== 'function') throw new Error('Runtime não exporta LlmTaskExecutor.');
|
|
736
|
+
executor = new runtime.LlmTaskExecutor(options.providerConfig, null, options.onProgress || null);
|
|
737
|
+
}
|
|
738
|
+
// Auto-wire InplaceWorkspaceManager as default
|
|
739
|
+
let workspaceManager = options.workspaceManager || null;
|
|
740
|
+
if (!workspaceManager) {
|
|
741
|
+
if (typeof runtime.InplaceWorkspaceManager === 'function') {
|
|
742
|
+
workspaceManager = new runtime.InplaceWorkspaceManager(projectRoot);
|
|
743
|
+
}
|
|
744
|
+
}
|
|
745
|
+
|
|
672
746
|
// Resolve compiled graph from run state or compile on demand
|
|
673
747
|
let current = options.runState || readRunState(projectRoot, activeSession);
|
|
674
748
|
if (!current || !current.compiled_graph) {
|
|
@@ -693,11 +767,14 @@ async function runRuntimeExecute(projectRoot, activeSession, options = {}) {
|
|
|
693
767
|
// Build ctx with GateManager (Gap 1)
|
|
694
768
|
const ctx = createExecutionContext(projectRoot, activeSession, {
|
|
695
769
|
runId: current.run_id,
|
|
696
|
-
executor
|
|
697
|
-
workspaceManager
|
|
770
|
+
executor,
|
|
771
|
+
workspaceManager,
|
|
698
772
|
pluginRegistry: options.pluginRegistry || buildRuntimePluginRegistry(projectRoot),
|
|
699
773
|
schedulerOptions: options.schedulerOptions || {},
|
|
700
|
-
onEvent: (event) =>
|
|
774
|
+
onEvent: (event) => {
|
|
775
|
+
appendEvent(projectRoot, activeSession, event);
|
|
776
|
+
options.onProgress?.(event);
|
|
777
|
+
},
|
|
701
778
|
});
|
|
702
779
|
|
|
703
780
|
// Gap 5: multi-agent path if plan-agents.json exists
|
|
@@ -906,6 +983,11 @@ function buildRecoveryConsistency(projectRoot, activeSession, runState, journal,
|
|
|
906
983
|
const runDir = runState && runState.run_id ? path.join(projectRoot, '.oxe', 'runs', runState.run_id) : null;
|
|
907
984
|
const allEvents = readEvents(projectRoot, activeSession);
|
|
908
985
|
const runEvents = runState && runState.run_id ? allEvents.filter((event) => event.run_id === runState.run_id) : [];
|
|
986
|
+
// Detect if execution has ever started (at least one attempt recorded)
|
|
987
|
+
const attemptCount = runState && runState.canonical_state && runState.canonical_state.summary
|
|
988
|
+
? (runState.canonical_state.summary.attempt_count || 0)
|
|
989
|
+
: 0;
|
|
990
|
+
const executionStarted = attemptCount > 0;
|
|
909
991
|
const issues = [];
|
|
910
992
|
if (!activeRunRef || activeRunRef.run_id !== (runState && runState.run_id)) {
|
|
911
993
|
issues.push('ACTIVE-RUN.json não referencia o mesmo run persistido em .oxe/runs/.');
|
|
@@ -913,10 +995,12 @@ function buildRecoveryConsistency(projectRoot, activeSession, runState, journal,
|
|
|
913
995
|
if (!runFile || !fs.existsSync(runFile)) {
|
|
914
996
|
issues.push('Arquivo canónico da run ausente em .oxe/runs/<run>.json.');
|
|
915
997
|
}
|
|
916
|
-
|
|
998
|
+
// Journal is only created after execution starts — skip this check pre-execution
|
|
999
|
+
if (!journal && executionStarted) {
|
|
917
1000
|
issues.push('Journal ausente para recover/replay.');
|
|
918
1001
|
}
|
|
919
|
-
|
|
1002
|
+
// Events for this run only exist after execution — skip pre-execution
|
|
1003
|
+
if (runEvents.length === 0 && executionStarted) {
|
|
920
1004
|
issues.push('Nenhum evento NDJSON encontrado para a run ativa.');
|
|
921
1005
|
}
|
|
922
1006
|
if (!runState || !runState.canonical_state) {
|
|
@@ -1146,7 +1230,7 @@ function projectRuntimeArtifacts(projectRoot, activeSession, options = {}) {
|
|
|
1146
1230
|
const paths = resolveRuntimeArtifactPaths(projectRoot, activeSession);
|
|
1147
1231
|
const op = operationalPaths(projectRoot, activeSession);
|
|
1148
1232
|
const projectionRefs = {
|
|
1149
|
-
plan_ref: path.relative(projectRoot, paths.plan).replace(/\\/g, '/'),
|
|
1233
|
+
plan_ref: path.relative(projectRoot, paths.plan.replace(/PLAN\.md$/, 'PLAN-STATUS.md')).replace(/\\/g, '/'),
|
|
1150
1234
|
verify_ref: path.relative(projectRoot, paths.verify).replace(/\\/g, '/'),
|
|
1151
1235
|
state_ref: path.relative(projectRoot, paths.state).replace(/\\/g, '/'),
|
|
1152
1236
|
run_summary_ref: path.relative(projectRoot, path.join(op.executionRoot, 'RUN-SUMMARY.md')).replace(/\\/g, '/'),
|
|
@@ -1156,10 +1240,12 @@ function projectRuntimeArtifacts(projectRoot, activeSession, options = {}) {
|
|
|
1156
1240
|
generated_at: new Date().toISOString(),
|
|
1157
1241
|
};
|
|
1158
1242
|
if (options.write !== false) {
|
|
1159
|
-
|
|
1243
|
+
// Write plan projection to PLAN-STATUS.md — never overwrite the source PLAN.md
|
|
1244
|
+
const planStatusPath = paths.plan.replace(/PLAN\.md$/, 'PLAN-STATUS.md');
|
|
1245
|
+
ensureDirForFile(planStatusPath);
|
|
1160
1246
|
ensureDirForFile(paths.verify);
|
|
1161
1247
|
ensureDirForFile(paths.state);
|
|
1162
|
-
fs.writeFileSync(
|
|
1248
|
+
fs.writeFileSync(planStatusPath, projections.plan + '\n', 'utf8');
|
|
1163
1249
|
fs.writeFileSync(paths.verify, projections.verify + '\n', 'utf8');
|
|
1164
1250
|
fs.writeFileSync(paths.state, projections.state + '\n', 'utf8');
|
|
1165
1251
|
fs.writeFileSync(path.join(op.executionRoot, 'RUN-SUMMARY.md'), projections.runSummary + '\n', 'utf8');
|
|
@@ -839,6 +839,18 @@ function codexIntegrationPaths() {
|
|
|
839
839
|
};
|
|
840
840
|
}
|
|
841
841
|
|
|
842
|
+
/**
|
|
843
|
+
* @param {string} target
|
|
844
|
+
*/
|
|
845
|
+
function codexWorkspacePaths(target) {
|
|
846
|
+
const root = path.resolve(target);
|
|
847
|
+
return {
|
|
848
|
+
root,
|
|
849
|
+
promptsDir: path.join(root, '.codex', 'prompts'),
|
|
850
|
+
skillsRoot: path.join(root, '.agents', 'skills'),
|
|
851
|
+
};
|
|
852
|
+
}
|
|
853
|
+
|
|
842
854
|
/**
|
|
843
855
|
* @param {string} filePath
|
|
844
856
|
*/
|
|
@@ -1108,11 +1120,21 @@ function summarizeRecoveryState(target, activeSession, activeRun, verificationAr
|
|
|
1108
1120
|
};
|
|
1109
1121
|
}
|
|
1110
1122
|
|
|
1111
|
-
function summarizeEnterpriseRuntime(target, activeRun, activeSession, config) {
|
|
1112
|
-
const pendingGates = readExecutionGates(target, activeSession);
|
|
1113
|
-
const auditSummary = summarizeAuditTrail(target, activeRun && activeRun.run_id ? activeRun.run_id : null);
|
|
1114
|
-
const
|
|
1115
|
-
const providerCatalog = operational.buildRuntimeProviderCatalog(target);
|
|
1123
|
+
function summarizeEnterpriseRuntime(target, activeRun, activeSession, config) {
|
|
1124
|
+
const pendingGates = readExecutionGates(target, activeSession);
|
|
1125
|
+
const auditSummary = summarizeAuditTrail(target, activeRun && activeRun.run_id ? activeRun.run_id : null);
|
|
1126
|
+
const runtimeModeBase = operational.buildRuntimeModeStatus(activeRun);
|
|
1127
|
+
const providerCatalog = operational.buildRuntimeProviderCatalog(target);
|
|
1128
|
+
const enterprisePackageAvailable = Boolean(providerCatalog && providerCatalog.available);
|
|
1129
|
+
const runtimeMode = enterprisePackageAvailable && runtimeModeBase.enterprise_available === false
|
|
1130
|
+
? {
|
|
1131
|
+
...runtimeModeBase,
|
|
1132
|
+
enterprise_available: true,
|
|
1133
|
+
reason: runtimeModeBase.reason === 'Nenhum ACTIVE-RUN encontrado para o escopo atual.'
|
|
1134
|
+
? 'Runtime enterprise disponível no pacote, mas ainda sem ACTIVE-RUN canónico neste escopo.'
|
|
1135
|
+
: 'Runtime enterprise disponível no pacote; a run atual ainda não materializou artefatos canónicos.',
|
|
1136
|
+
}
|
|
1137
|
+
: runtimeModeBase;
|
|
1116
1138
|
if (!activeRun || !activeRun.run_id) {
|
|
1117
1139
|
return {
|
|
1118
1140
|
runtimeMode,
|
|
@@ -1484,9 +1506,16 @@ function copilotIntegrationReport(target) {
|
|
|
1484
1506
|
* @param {string} target
|
|
1485
1507
|
*/
|
|
1486
1508
|
function codexIntegrationReport(target) {
|
|
1487
|
-
const
|
|
1488
|
-
const
|
|
1489
|
-
const
|
|
1509
|
+
const workspace = codexWorkspacePaths(target);
|
|
1510
|
+
const globalPaths = codexIntegrationPaths();
|
|
1511
|
+
const workspacePromptFiles = listOxeCodexPromptFiles(workspace.promptsDir);
|
|
1512
|
+
const workspaceSkillDirs = listOxeSkillDirs(workspace.skillsRoot);
|
|
1513
|
+
const globalPromptFiles = listOxeCodexPromptFiles(globalPaths.promptsDir);
|
|
1514
|
+
const globalSkillDirs = listOxeSkillDirs(globalPaths.skillsRoot);
|
|
1515
|
+
const workspaceDetected = workspacePromptFiles.length > 0 || workspaceSkillDirs.length > 0;
|
|
1516
|
+
const globalDetected = globalPromptFiles.length > 0 || globalSkillDirs.length > 0;
|
|
1517
|
+
const promptFiles = workspaceDetected ? workspacePromptFiles : globalPromptFiles;
|
|
1518
|
+
const skillDirs = workspaceDetected ? workspaceSkillDirs : globalSkillDirs;
|
|
1490
1519
|
const promptNames = promptFiles.map((filePath) => path.basename(filePath));
|
|
1491
1520
|
const skillNames = skillDirs.map((dirPath) => path.basename(dirPath));
|
|
1492
1521
|
const promptPathWarnings = [];
|
|
@@ -1496,11 +1525,15 @@ function codexIntegrationReport(target) {
|
|
|
1496
1525
|
|
|
1497
1526
|
/** @type {string[]} */
|
|
1498
1527
|
const warnings = [];
|
|
1499
|
-
const detected =
|
|
1528
|
+
const detected = workspaceDetected || globalDetected;
|
|
1529
|
+
const promptSource = workspaceDetected ? 'workspace' : globalDetected ? 'global' : 'missing';
|
|
1500
1530
|
const commandsReady = promptNames.includes('oxe.md');
|
|
1501
1531
|
const skillsReady = skillNames.includes('oxe');
|
|
1532
|
+
if (!workspaceDetected && globalDetected) {
|
|
1533
|
+
warnings.push('Codex OXE foi encontrado apenas no ambiente global do usuário; este projeto não tem integração local instalada.');
|
|
1534
|
+
}
|
|
1502
1535
|
if (detected && promptFiles.length === 0) {
|
|
1503
|
-
warnings.push('Codex tem skills OXE instaladas, mas
|
|
1536
|
+
warnings.push('Codex tem skills OXE instaladas, mas o diretório de prompts ativo não contém prompts OXE; a barra / não listará /oxe.');
|
|
1504
1537
|
}
|
|
1505
1538
|
if (promptFiles.length > 0 && !commandsReady) {
|
|
1506
1539
|
warnings.push('Codex prompts OXE existem, mas o entrypoint principal oxe.md está ausente.');
|
|
@@ -1525,11 +1558,28 @@ function codexIntegrationReport(target) {
|
|
|
1525
1558
|
detected,
|
|
1526
1559
|
commandsReady,
|
|
1527
1560
|
skillsReady,
|
|
1528
|
-
|
|
1529
|
-
|
|
1530
|
-
|
|
1561
|
+
promptSource,
|
|
1562
|
+
root: workspaceDetected ? workspace.root : globalPaths.root,
|
|
1563
|
+
promptsDir: workspaceDetected ? workspace.promptsDir : globalPaths.promptsDir,
|
|
1564
|
+
skillsRoot: workspaceDetected ? workspace.skillsRoot : globalPaths.skillsRoot,
|
|
1531
1565
|
promptFiles,
|
|
1532
1566
|
skillDirs,
|
|
1567
|
+
workspace: {
|
|
1568
|
+
root: workspace.root,
|
|
1569
|
+
promptsDir: workspace.promptsDir,
|
|
1570
|
+
skillsRoot: workspace.skillsRoot,
|
|
1571
|
+
promptFiles: workspacePromptFiles,
|
|
1572
|
+
skillDirs: workspaceSkillDirs,
|
|
1573
|
+
detected: workspaceDetected,
|
|
1574
|
+
},
|
|
1575
|
+
global: {
|
|
1576
|
+
root: globalPaths.root,
|
|
1577
|
+
promptsDir: globalPaths.promptsDir,
|
|
1578
|
+
skillsRoot: globalPaths.skillsRoot,
|
|
1579
|
+
promptFiles: globalPromptFiles,
|
|
1580
|
+
skillDirs: globalSkillDirs,
|
|
1581
|
+
detected: globalDetected,
|
|
1582
|
+
},
|
|
1533
1583
|
warnings,
|
|
1534
1584
|
};
|
|
1535
1585
|
}
|
|
@@ -2026,12 +2076,21 @@ function suggestNextStep(target, cfg = {}) {
|
|
|
2026
2076
|
};
|
|
2027
2077
|
}
|
|
2028
2078
|
|
|
2079
|
+
if (!mapsComplete && !has(p.quick) && !has(p.spec) && !has(p.plan)) {
|
|
2080
|
+
return {
|
|
2081
|
+
step: 'oxe',
|
|
2082
|
+
cursorCmd: '/oxe',
|
|
2083
|
+
reason: 'Projeto recém-inicializado e sem SPEC/PLAN — use a entrada universal para começar o fluxo e escolher o primeiro scan.',
|
|
2084
|
+
artifacts: ['.oxe/STATE.md', '.oxe/codebase/'],
|
|
2085
|
+
};
|
|
2086
|
+
}
|
|
2087
|
+
|
|
2029
2088
|
if (!mapsComplete && !has(p.quick)) {
|
|
2030
|
-
return {
|
|
2031
|
-
step: 'scan',
|
|
2032
|
-
cursorCmd: '/oxe-scan',
|
|
2033
|
-
reason: 'Mapas do codebase incompletos e sem QUICK.md — atualize o contexto com scan',
|
|
2034
|
-
artifacts: ['.oxe/codebase/'],
|
|
2089
|
+
return {
|
|
2090
|
+
step: 'scan',
|
|
2091
|
+
cursorCmd: '/oxe-scan',
|
|
2092
|
+
reason: 'Mapas do codebase incompletos e sem QUICK.md — atualize o contexto com scan',
|
|
2093
|
+
artifacts: ['.oxe/codebase/'],
|
|
2035
2094
|
};
|
|
2036
2095
|
}
|
|
2037
2096
|
|
|
@@ -350,14 +350,16 @@ function buildExecutionRationality(paths = {}) {
|
|
|
350
350
|
const implementationPack = summarizeImplementationPack(paths.implementationPackJson || null, planTasks);
|
|
351
351
|
const referenceAnchors = summarizeReferenceAnchors(paths.referenceAnchors || null, externalRefs);
|
|
352
352
|
const fixturePack = summarizeFixturePack(paths.fixturePackJson || null, planTasks, implementationPack);
|
|
353
|
-
const criticalExecutionGaps = Array.from(
|
|
354
|
-
new Set([
|
|
355
|
-
...implementationPack.criticalGaps,
|
|
356
|
-
...referenceAnchors.criticalGaps,
|
|
357
|
-
...fixturePack.criticalGaps,
|
|
358
|
-
])
|
|
359
|
-
);
|
|
360
353
|
const applicable = Boolean(paths.plan && fs.existsSync(paths.plan));
|
|
354
|
+
const criticalExecutionGaps = applicable
|
|
355
|
+
? Array.from(
|
|
356
|
+
new Set([
|
|
357
|
+
...implementationPack.criticalGaps,
|
|
358
|
+
...referenceAnchors.criticalGaps,
|
|
359
|
+
...fixturePack.criticalGaps,
|
|
360
|
+
])
|
|
361
|
+
)
|
|
362
|
+
: [];
|
|
361
363
|
return {
|
|
362
364
|
applicable,
|
|
363
365
|
planTaskCount: planTasks.length,
|