oxe-cc 1.5.1 → 1.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +1 -1
- package/CHANGELOG.md +27 -0
- package/README.md +16 -14
- package/bin/lib/oxe-dashboard.cjs +21 -5
- package/bin/lib/oxe-project-health.cjs +120 -42
- package/bin/lib/oxe-release.cjs +76 -4
- package/bin/oxe-cc.js +68 -39
- package/docs/RELEASE-READINESS.md +8 -0
- package/docs/RUNTIME-SMOKE-MATRIX.md +9 -2
- package/lib/sdk/index.cjs +10 -5
- package/lib/sdk/index.d.ts +21 -10
- package/oxe/templates/CONFIG.md +3 -3
- package/oxe/templates/EXECUTION-RUNTIME.template.md +1 -1
- package/oxe/templates/FIXTURE-PACK.template.json +34 -34
- package/oxe/templates/FIXTURE-PACK.template.md +21 -21
- package/oxe/templates/IMPLEMENTATION-PACK.template.json +52 -52
- package/oxe/templates/IMPLEMENTATION-PACK.template.md +36 -36
- package/oxe/templates/INVESTIGATION.template.md +38 -38
- package/oxe/templates/PLAN.template.md +46 -46
- package/oxe/templates/REFERENCE-ANCHORS.template.md +24 -24
- package/oxe/templates/RESEARCH.template.md +11 -11
- package/oxe/templates/SPEC.template.md +6 -6
- package/oxe/templates/SUMMARY.template.md +20 -20
- package/oxe/templates/config.template.json +1 -1
- package/oxe/workflows/execute.md +36 -36
- package/oxe/workflows/milestone.md +12 -12
- package/oxe/workflows/next.md +1 -1
- package/oxe/workflows/plan.md +132 -132
- package/oxe/workflows/references/adaptive-discovery.md +27 -27
- package/oxe/workflows/references/flow-robustness-contract.md +80 -80
- package/oxe/workflows/references/session-path-resolution.md +71 -71
- package/oxe/workflows/references/workflow-runtime-contracts.json +127 -127
- package/oxe/workflows/verify.md +4 -4
- package/oxe/workflows/workstream.md +16 -16
- package/package.json +1 -1
- package/packages/runtime/package.json +1 -1
- package/vscode-extension/oxe-agents-1.6.0.vsix +0 -0
- package/vscode-extension/package.json +1 -1
package/AGENTS.md
CHANGED
|
@@ -99,4 +99,4 @@ Os wrappers por runtime podem carregar metadata cognitiva (`oxe_reasoning_mode`,
|
|
|
99
99
|
|
|
100
100
|
Para `execute` e `verify`, o comportamento atual esperado é **runtime-first**: se `oxe-cc runtime` estiver disponível, preferir `runtime compile/project/verify/gates` e tratar markdown como projeção derivada; se o runtime não puder ser executado, declarar `fallback legado` explicitamente.
|
|
101
101
|
|
|
102
|
-
Para publicação, o gate local esperado passa por `oxe-cc doctor --release --write-manifest`. Essa verificação deve falhar se houver drift de versão, topo inválido no `CHANGELOG`, wrapper dirty após sync, runtime não compilado ou ausência dos relatórios `.oxe/release/*.json` exigidos pela release.
|
|
102
|
+
Para publicação, o gate local esperado passa por `oxe-cc doctor --release --write-manifest`. Essa verificação deve falhar se houver drift de versão, topo inválido no `CHANGELOG`, ausência da árvore canónica `oxe/`, `workflow-runtime-contracts.json` inválido, wrapper dirty após sync, runtime não compilado ou ausência dos relatórios `.oxe/release/*.json` exigidos pela release.
|
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,33 @@ Todas as versões seguem [Semantic Versioning](https://semver.org/). As mudança
|
|
|
4
4
|
|
|
5
5
|
---
|
|
6
6
|
|
|
7
|
+
## [1.6.0] — 2026-04-23
|
|
8
|
+
|
|
9
|
+
### Product Reconciliation
|
|
10
|
+
|
|
11
|
+
- a árvore canónica `oxe/` foi restaurada como source of truth da release, incluindo `oxe/workflows/`, `oxe/workflows/references/`, `oxe/templates/` e `commands/oxe/` como superfície derivada sincronizada
|
|
12
|
+
- `workflow-runtime-contracts.json` voltou a ser contrato obrigatório da release; `sync-runtime-metadata` agora falha fechado quando a fonte canónica ou o registry semântico estão ausentes/inválidos
|
|
13
|
+
- `doctor --release` passou a bloquear explicitamente por topologia canónica ausente, contrato semântico inválido e drift entre workflows e wrappers
|
|
14
|
+
|
|
15
|
+
### Package-vs-Workspace Health
|
|
16
|
+
|
|
17
|
+
- `status`, `status --full`, dashboard e SDK agora distinguem `workspaceMode: product_package` de `workspaceMode: oxe_project`
|
|
18
|
+
- no repositório do pacote, o próximo passo deixa de cair em `plan/replan` por ruído de manutenção e passa a apontar para `doctor --release --write-manifest`
|
|
19
|
+
- `status --json` passou a expor `workspaceMode` e `releaseReadiness` como contrato estável da linha `1.6.0`
|
|
20
|
+
|
|
21
|
+
### Multi-runtime Edge Hardening
|
|
22
|
+
|
|
23
|
+
- a smoke matrix de release passou a validar a instalação do Codex de forma completa: prompts em `.codex/prompts/` e skills em `.agents/skills/oxe/`
|
|
24
|
+
- documentação de instalação foi ajustada para separar `--local` (layout do repo) de `--ide-local` (escopo da integração), eliminando a ambiguidade operacional em runtimes como Codex
|
|
25
|
+
|
|
26
|
+
### Validation
|
|
27
|
+
|
|
28
|
+
- `node --test tests/oxe-project-health.test.cjs`
|
|
29
|
+
- `node --test tests/oxe-cli-edge.test.cjs`
|
|
30
|
+
- `npm test`
|
|
31
|
+
- `npm run scan:assets`
|
|
32
|
+
- `npm run release:doctor`
|
|
33
|
+
|
|
7
34
|
## [1.5.1] — 2026-04-22
|
|
8
35
|
|
|
9
36
|
### Rational Execution Readiness
|
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.
|
|
10
|
+
**Versão:** `1.6.0` · [package.json](package.json)
|
|
11
11
|
|
|
12
12
|
**Framework OXE — Orchestrated eXperience Engineering**
|
|
13
13
|
|
|
@@ -52,7 +52,7 @@ O OXE agora distingue cinco famílias de raciocínio:
|
|
|
52
52
|
- `review` — findings primeiro, severidade, evidência e risco residual
|
|
53
53
|
- `status` — leitura curta do estado, recomendação única e motivo
|
|
54
54
|
|
|
55
|
-
Essas regras vivem no núcleo canónico em `oxe/workflows/references/reasoning-*.md`, sobem para os workflows em `oxe/workflows/` e são renderizadas para cada runtime em `.github/prompts/`, `.cursor/commands/`, `commands/oxe/`, `.codex/prompts/` e skills multiagente.
|
|
55
|
+
Essas regras vivem no núcleo canónico em `oxe/workflows/references/reasoning-*.md`, sobem para os workflows em `oxe/workflows/` e são renderizadas para cada runtime em `.github/prompts/`, `.cursor/commands/`, `commands/oxe/`, `.codex/prompts/` e skills multiagente. Nesta linha, `oxe/workflows/**` e `workflow-runtime-contracts.json` voltam a ser o contrato obrigatório da release; superfícies geradas permanecem derivadas e sincronizadas.
|
|
56
56
|
|
|
57
57
|
---
|
|
58
58
|
|
|
@@ -522,14 +522,16 @@ npx oxe-cc@latest
|
|
|
522
522
|
| Flag | Efeito |
|
|
523
523
|
|------|--------|
|
|
524
524
|
| `--cursor` / `--copilot` | Só uma das stacks da IDE |
|
|
525
|
-
| `--copilot-cli` | Skills globais do Copilot CLI em `~/.copilot/skills/` |
|
|
526
|
-
| `--all-agents` | Cursor + Copilot + Claude + OpenCode + Gemini + Codex + Windsurf + Antigravity |
|
|
527
|
-
| `--global` | Layout clássico: `oxe/` na raiz + `.oxe/` |
|
|
528
|
-
| `--local` | Layout
|
|
529
|
-
| `--
|
|
530
|
-
| `--
|
|
531
|
-
| `--
|
|
532
|
-
| `--
|
|
525
|
+
| `--copilot-cli` | Skills globais do Copilot CLI em `~/.copilot/skills/` |
|
|
526
|
+
| `--all-agents` | Cursor + Copilot + Claude + OpenCode + Gemini + Codex + Windsurf + Antigravity |
|
|
527
|
+
| `--global` | Layout clássico: `oxe/` na raiz + `.oxe/` |
|
|
528
|
+
| `--local` | Layout do repositório: mínimo, só `.oxe/` (padrão). Não controla onde a integração da IDE é instalada. |
|
|
529
|
+
| `--ide-local` | Instala a integração no próprio repositório (`.cursor/`, `.github/`, `.claude/`, `.codex/` etc.) |
|
|
530
|
+
| `--ide-global` | Instala a integração no HOME do utilizador quando o runtime suportar esse escopo |
|
|
531
|
+
| `--force` / `-f` | Sobrescreve arquivos existentes (use para atualizar) |
|
|
532
|
+
| `--dry-run` | Lista ações sem escrever |
|
|
533
|
+
| `--oxe-only` | Só workflows em `.oxe/`, sem integrações IDE |
|
|
534
|
+
| `--no-global-cli` / `-l` | Não instala `oxe-cc` globalmente (útil em CI) |
|
|
533
535
|
| `OXE_NO_PROMPT=1` | Modo não-interativo (CI) |
|
|
534
536
|
|
|
535
537
|
</details>
|
|
@@ -568,10 +570,10 @@ node bin/oxe-cc.js --help
|
|
|
568
570
|
|---------|-----------|
|
|
569
571
|
| `oxe-cc` / `oxe-cc install` | Instala workflows e integrações |
|
|
570
572
|
| `oxe-cc doctor` | Diagnóstico completo: Node, workflows, config, bootstrap `.oxe/`, sessão ativa, autoavaliação do plano, saúde lógica (`healthy` \| `warning` \| `broken`), drift semântico multi-runtime e workflows sem contrato no registry |
|
|
571
|
-
| `oxe-cc doctor --release --write-manifest` | Gate de publicação: valida versões, topo do `CHANGELOG`, runtime compilado, wrapper sync e relatórios obrigatórios; persiste `release-manifest.json` |
|
|
572
|
-
| `oxe-cc status` | Próximo passo sugerido + saúde lógica do fluxo |
|
|
573
|
-
| `oxe-cc status --full` | Coverage matrix + readiness gate + active run no terminal (ANSI) |
|
|
574
|
-
| `oxe-cc status --json` | Mesmo, em JSON (schema v5), com `healthStatus`, `activeSession`, `planSelfEvaluation`, `contextPacks`, `contextQuality`, `semanticsDrift`, `verificationSummary`, `residualRiskSummary`, `evidenceCoverage`, `pendingGates`, `policyDecisionSummary`, `quotaSummary`, `auditSummary`, `promotionSummary`, `runtimeMode`, `fallbackMode`, `gateQueue`, `policyCoverage`, `promotionReadiness`, `recoveryState`, `multiAgent` e `providerCatalog` |
|
|
573
|
+
| `oxe-cc doctor --release --write-manifest` | Gate de publicação: valida árvore canónica `oxe/`, `workflow-runtime-contracts.json`, versões, topo do `CHANGELOG`, runtime compilado, wrapper sync e relatórios obrigatórios; persiste `release-manifest.json` |
|
|
574
|
+
| `oxe-cc status` | Próximo passo sugerido + saúde lógica do fluxo |
|
|
575
|
+
| `oxe-cc status --full` | Coverage matrix + readiness gate + active run no terminal (ANSI); em repositório do pacote, troca para release readiness em vez de plan readiness |
|
|
576
|
+
| `oxe-cc status --json` | Mesmo, em JSON (schema v5), com `workspaceMode`, `releaseReadiness`, `healthStatus`, `activeSession`, `planSelfEvaluation`, `contextPacks`, `contextQuality`, `semanticsDrift`, `verificationSummary`, `residualRiskSummary`, `evidenceCoverage`, `pendingGates`, `policyDecisionSummary`, `quotaSummary`, `auditSummary`, `promotionSummary`, `runtimeMode`, `fallbackMode`, `gateQueue`, `policyCoverage`, `promotionReadiness`, `recoveryState`, `multiAgent` e `providerCatalog` |
|
|
575
577
|
| `oxe-cc context build [--workflow <slug>] [--tier <minimal\|standard\|full>]` | Gera context pack(s) em `.oxe/context/packs/` — seleção determinística de artefatos por contrato de workflow |
|
|
576
578
|
| `oxe-cc context inspect [--workflow <slug>]` | Inspeciona um context pack existente ou resolve sob demanda (sem escrita); útil para diagnóstico antes de iniciar um passo |
|
|
577
579
|
| `oxe-cc update` | Atualiza workflows para a versão mais recente |
|
|
@@ -162,6 +162,20 @@ function confidenceBand(confidence, threshold) {
|
|
|
162
162
|
}
|
|
163
163
|
|
|
164
164
|
function computeReadiness(ctx, threshold) {
|
|
165
|
+
if (ctx.workspaceMode === 'product_package' && ctx.releaseReadiness) {
|
|
166
|
+
const blockers = Array.isArray(ctx.releaseReadiness.blockers) ? ctx.releaseReadiness.blockers.slice() : [];
|
|
167
|
+
const warnings = Array.isArray(ctx.releaseReadiness.warnings) ? ctx.releaseReadiness.warnings.slice() : [];
|
|
168
|
+
return {
|
|
169
|
+
go: Boolean(ctx.releaseReadiness.ok),
|
|
170
|
+
decision: ctx.releaseReadiness.ok ? 'go' : 'no-go',
|
|
171
|
+
threshold: health.normalizePlanConfidenceThreshold(threshold),
|
|
172
|
+
confidence: ctx.plan && ctx.plan.selfEvaluation ? ctx.plan.selfEvaluation.confidence : null,
|
|
173
|
+
confidenceBand: confidenceBand(ctx.plan && ctx.plan.selfEvaluation ? ctx.plan.selfEvaluation.confidence : null, threshold),
|
|
174
|
+
checkpointPending: false,
|
|
175
|
+
blockers,
|
|
176
|
+
warnings,
|
|
177
|
+
};
|
|
178
|
+
}
|
|
165
179
|
const normalizedThreshold = health.normalizePlanConfidenceThreshold(threshold);
|
|
166
180
|
const blockers = [];
|
|
167
181
|
const warnings = [...ctx.diagnostics.reviewWarnings, ...ctx.diagnostics.runtimeWarnings, ...ctx.diagnostics.planWarnings];
|
|
@@ -349,7 +363,7 @@ function loadDashboardContext(projectRoot, opts = {}) {
|
|
|
349
363
|
const activeSession = opts.activeSession === undefined ? health.parseActiveSession(stateText) : opts.activeSession;
|
|
350
364
|
const p = reviewPaths(projectRoot, activeSession || null);
|
|
351
365
|
const rootScoped = reviewPaths(projectRoot, null);
|
|
352
|
-
const report = health.buildHealthReport(projectRoot);
|
|
366
|
+
const report = health.buildHealthReport(projectRoot);
|
|
353
367
|
const specText = readScopedText(p.spec, rootScoped.spec);
|
|
354
368
|
const planText = readScopedText(p.plan, rootScoped.plan);
|
|
355
369
|
const verifyText = readScopedText(p.verify, rootScoped.verify);
|
|
@@ -373,9 +387,11 @@ function loadDashboardContext(projectRoot, opts = {}) {
|
|
|
373
387
|
const sessions = parseSessionsIndex(sessionsRaw);
|
|
374
388
|
const sessionPath = activeSession ? path.join(projectRoot, '.oxe', activeSession, 'SESSION.md') : null;
|
|
375
389
|
const sessionRaw = sessionPath ? readTextIfExists(sessionPath) || '' : '';
|
|
376
|
-
const ctx = {
|
|
377
|
-
projectRoot: path.resolve(projectRoot),
|
|
378
|
-
|
|
390
|
+
const ctx = {
|
|
391
|
+
projectRoot: path.resolve(projectRoot),
|
|
392
|
+
workspaceMode: report.workspaceMode || 'oxe_project',
|
|
393
|
+
releaseReadiness: report.releaseReadiness || null,
|
|
394
|
+
activeSession: activeSession || null,
|
|
379
395
|
phase: report.phase || health.parseStatePhase(stateText),
|
|
380
396
|
healthStatus: report.healthStatus,
|
|
381
397
|
nextStep: report.next,
|
|
@@ -388,7 +404,7 @@ function loadDashboardContext(projectRoot, opts = {}) {
|
|
|
388
404
|
activeRun: activeRunState,
|
|
389
405
|
runtimeCanonical: activeRunState && activeRunState.canonical_state ? activeRunState.canonical_state : null,
|
|
390
406
|
compiledGraph: activeRunState && activeRunState.compiled_graph ? activeRunState.compiled_graph : null,
|
|
391
|
-
enterprise: {
|
|
407
|
+
enterprise: {
|
|
392
408
|
runtimeMode: report.runtimeMode || null,
|
|
393
409
|
fallbackMode: report.fallbackMode || null,
|
|
394
410
|
verificationSummary: report.verificationSummary || null,
|
|
@@ -746,6 +746,50 @@ function resolvedReadableOxePaths(target, activeSession) {
|
|
|
746
746
|
summary: preferScoped('summary'),
|
|
747
747
|
};
|
|
748
748
|
}
|
|
749
|
+
|
|
750
|
+
/**
|
|
751
|
+
* @param {string} target
|
|
752
|
+
* @returns {{ workspaceMode: 'product_package' | 'oxe_project', packageName: string | null, canonicalTreePresent: boolean, commandsTreePresent: boolean }}
|
|
753
|
+
*/
|
|
754
|
+
function detectWorkspaceMode(target) {
|
|
755
|
+
const packageJsonPath = path.join(target, 'package.json');
|
|
756
|
+
let packageName = null;
|
|
757
|
+
try {
|
|
758
|
+
if (fs.existsSync(packageJsonPath)) {
|
|
759
|
+
const parsed = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
|
|
760
|
+
packageName = parsed && typeof parsed.name === 'string' ? parsed.name : null;
|
|
761
|
+
}
|
|
762
|
+
} catch {
|
|
763
|
+
packageName = null;
|
|
764
|
+
}
|
|
765
|
+
const canonicalTreePresent = fs.existsSync(path.join(target, 'oxe', 'workflows'));
|
|
766
|
+
const commandsTreePresent = fs.existsSync(path.join(target, 'commands', 'oxe'));
|
|
767
|
+
const packageRepo =
|
|
768
|
+
packageName === 'oxe-cc'
|
|
769
|
+
&& fs.existsSync(path.join(target, 'bin', 'oxe-cc.js'))
|
|
770
|
+
&& fs.existsSync(path.join(target, 'packages', 'runtime', 'package.json'))
|
|
771
|
+
&& canonicalTreePresent;
|
|
772
|
+
return {
|
|
773
|
+
workspaceMode: packageRepo ? 'product_package' : 'oxe_project',
|
|
774
|
+
packageName,
|
|
775
|
+
canonicalTreePresent,
|
|
776
|
+
commandsTreePresent,
|
|
777
|
+
};
|
|
778
|
+
}
|
|
779
|
+
|
|
780
|
+
/**
|
|
781
|
+
* @param {'product_package' | 'oxe_project'} workspaceMode
|
|
782
|
+
* @param {string | null} phase
|
|
783
|
+
* @param {string | null} activeSession
|
|
784
|
+
* @param {Record<string, unknown> | null} activeRun
|
|
785
|
+
* @returns {boolean}
|
|
786
|
+
*/
|
|
787
|
+
function shouldSuppressExecutionWorkspaceGates(workspaceMode, phase, activeSession, activeRun) {
|
|
788
|
+
if (workspaceMode !== 'product_package') return false;
|
|
789
|
+
if (activeSession) return false;
|
|
790
|
+
if (activeRun && typeof activeRun === 'object') return false;
|
|
791
|
+
return !phase || phase === 'initial';
|
|
792
|
+
}
|
|
749
793
|
|
|
750
794
|
/**
|
|
751
795
|
* @param {string} target
|
|
@@ -1841,16 +1885,19 @@ function planReviewWarnings(stateText, p) {
|
|
|
1841
1885
|
* @param {{ discuss_before_plan?: boolean }} cfg
|
|
1842
1886
|
*/
|
|
1843
1887
|
function suggestNextStep(target, cfg = {}) {
|
|
1844
|
-
const base = oxePaths(target);
|
|
1845
|
-
const stateText = fs.existsSync(base.state) ? fs.readFileSync(base.state, 'utf8') : '';
|
|
1846
|
-
const
|
|
1847
|
-
const
|
|
1888
|
+
const base = oxePaths(target);
|
|
1889
|
+
const stateText = fs.existsSync(base.state) ? fs.readFileSync(base.state, 'utf8') : '';
|
|
1890
|
+
const activeSession = parseActiveSession(stateText);
|
|
1891
|
+
const p = resolvedReadableOxePaths(target, activeSession);
|
|
1892
|
+
const discussBefore = Boolean(cfg.discuss_before_plan);
|
|
1848
1893
|
const threshold = normalizePlanConfidenceThreshold(cfg.plan_confidence_threshold);
|
|
1849
|
-
const has = (/** @type {string} */ f) => fs.existsSync(f);
|
|
1850
|
-
const mapsComplete = EXPECTED_CODEBASE_MAPS.every((f) => has(path.join(p.codebase, f)));
|
|
1851
|
-
const azureActive = azure.isAzureContextEnabled(target, cfg);
|
|
1852
|
-
|
|
1853
|
-
|
|
1894
|
+
const has = (/** @type {string} */ f) => fs.existsSync(f);
|
|
1895
|
+
const mapsComplete = EXPECTED_CODEBASE_MAPS.every((f) => has(path.join(p.codebase, f)));
|
|
1896
|
+
const azureActive = azure.isAzureContextEnabled(target, cfg);
|
|
1897
|
+
const activeRun = operational.readRunState(target, activeSession);
|
|
1898
|
+
const workspaceInfo = detectWorkspaceMode(target);
|
|
1899
|
+
|
|
1900
|
+
if (!has(p.oxe) || !has(p.state)) {
|
|
1854
1901
|
return {
|
|
1855
1902
|
step: 'scan',
|
|
1856
1903
|
cursorCmd: '/oxe-scan',
|
|
@@ -1858,10 +1905,27 @@ function suggestNextStep(target, cfg = {}) {
|
|
|
1858
1905
|
artifacts: ['.oxe/'],
|
|
1859
1906
|
};
|
|
1860
1907
|
}
|
|
1861
|
-
|
|
1862
|
-
const phase = parseStatePhase(stateText);
|
|
1863
|
-
|
|
1864
|
-
|
|
1908
|
+
|
|
1909
|
+
const phase = parseStatePhase(stateText);
|
|
1910
|
+
if (shouldSuppressExecutionWorkspaceGates(workspaceInfo.workspaceMode, phase, activeSession, activeRun)) {
|
|
1911
|
+
const release = require('./oxe-release.cjs');
|
|
1912
|
+
const readiness = release.inspectReleaseReadiness(target, { packageRoot: target });
|
|
1913
|
+
return {
|
|
1914
|
+
step: 'doctor',
|
|
1915
|
+
cursorCmd: 'oxe-cc doctor --release --write-manifest',
|
|
1916
|
+
reason: readiness.ok
|
|
1917
|
+
? 'Repositório do pacote OXE detectado — o próximo passo operacional é validar/publicar a release, não replanejar um workspace de entrega.'
|
|
1918
|
+
: `Repositório do pacote OXE detectado — trate primeiro os blockers de release (${readiness.blockers[0] || 'release readiness incompleta'}).`,
|
|
1919
|
+
artifacts: [
|
|
1920
|
+
'.oxe/release/release-manifest.json',
|
|
1921
|
+
'.oxe/release/runtime-smoke-report.json',
|
|
1922
|
+
'.oxe/release/recovery-fixture-report.json',
|
|
1923
|
+
'.oxe/release/multi-agent-soak-report.json',
|
|
1924
|
+
],
|
|
1925
|
+
};
|
|
1926
|
+
}
|
|
1927
|
+
|
|
1928
|
+
if (!mapsComplete && !has(p.quick)) {
|
|
1865
1929
|
return {
|
|
1866
1930
|
step: 'scan',
|
|
1867
1931
|
cursorCmd: '/oxe-scan',
|
|
@@ -2003,9 +2067,7 @@ function suggestNextStep(target, cfg = {}) {
|
|
|
2003
2067
|
artifacts: ['.oxe/PLAN.md', '.oxe/PLAN-REVIEW.md', '.oxe/STATE.md'],
|
|
2004
2068
|
};
|
|
2005
2069
|
}
|
|
2006
|
-
|
|
2007
|
-
const activeRun = operational.readRunState(target, parseActiveSession(stateText));
|
|
2008
|
-
if (activeRun && activeRun.status === 'waiting_approval') {
|
|
2070
|
+
if (activeRun && activeRun.status === 'waiting_approval') {
|
|
2009
2071
|
return {
|
|
2010
2072
|
step: 'dashboard',
|
|
2011
2073
|
cursorCmd: '/oxe-dashboard',
|
|
@@ -2102,7 +2164,7 @@ function suggestNextStep(target, cfg = {}) {
|
|
|
2102
2164
|
/**
|
|
2103
2165
|
* @param {string} target
|
|
2104
2166
|
*/
|
|
2105
|
-
function buildHealthReport(target) {
|
|
2167
|
+
function buildHealthReport(target) {
|
|
2106
2168
|
const contextEngine = require('./oxe-context-engine.cjs');
|
|
2107
2169
|
const runtimeSemantics = require('./oxe-runtime-semantics.cjs');
|
|
2108
2170
|
const { config, path: cfgPath, parseError } = loadOxeConfigMerged(target);
|
|
@@ -2116,10 +2178,11 @@ function buildHealthReport(target) {
|
|
|
2116
2178
|
stateText = '';
|
|
2117
2179
|
}
|
|
2118
2180
|
}
|
|
2119
|
-
const activeSession = parseActiveSession(stateText);
|
|
2181
|
+
const activeSession = parseActiveSession(stateText);
|
|
2120
2182
|
const p = resolvedReadableOxePaths(target, activeSession);
|
|
2121
|
-
const phase = parseStatePhase(stateText);
|
|
2122
|
-
const
|
|
2183
|
+
const phase = parseStatePhase(stateText);
|
|
2184
|
+
const workspaceInfo = detectWorkspaceMode(target);
|
|
2185
|
+
const scanDate = parseLastScanDate(stateText);
|
|
2123
2186
|
const stale = isStaleScan(scanDate, Number(config.scan_max_age_days) || 0);
|
|
2124
2187
|
const compactDate = parseLastCompactDate(stateText);
|
|
2125
2188
|
const staleCompact = isStaleScan(compactDate, Number(config.compact_max_age_days) || 0);
|
|
@@ -2134,6 +2197,7 @@ function buildHealthReport(target) {
|
|
|
2134
2197
|
const capabilityWarn = capabilityWarnings(p);
|
|
2135
2198
|
const investigationWarn = investigationWarnings(p);
|
|
2136
2199
|
const parsedPlanSelfEvaluation = parsePlanSelfEvaluation(p.plan);
|
|
2200
|
+
const activeRun = operational.readRunState(target, activeSession);
|
|
2137
2201
|
const executionRationality = rationality.buildExecutionRationality({
|
|
2138
2202
|
plan: p.plan,
|
|
2139
2203
|
planAgents: p.planAgents,
|
|
@@ -2143,18 +2207,25 @@ function buildHealthReport(target) {
|
|
|
2143
2207
|
fixturePackJson: p.fixturePackJson,
|
|
2144
2208
|
fixturePackMd: p.fixturePackMd,
|
|
2145
2209
|
});
|
|
2146
|
-
const
|
|
2210
|
+
const suppressExecutionWorkspaceGates = shouldSuppressExecutionWorkspaceGates(
|
|
2211
|
+
workspaceInfo.workspaceMode,
|
|
2212
|
+
phase,
|
|
2213
|
+
activeSession,
|
|
2214
|
+
activeRun
|
|
2215
|
+
);
|
|
2216
|
+
const executionPlanWarn = [
|
|
2147
2217
|
...planWaveWarningsFixed(p.plan, Number(config.plan_max_tasks_per_wave) || 0),
|
|
2148
2218
|
...planTaskAceiteWarnings(p.plan),
|
|
2149
2219
|
...planSelfEvaluationWarningsFromInfo(parsedPlanSelfEvaluation, threshold),
|
|
2150
2220
|
...executionRationalityWarningsFromSummary(executionRationality),
|
|
2151
2221
|
...planAgentsWarnings(target),
|
|
2152
2222
|
];
|
|
2223
|
+
const planWarn = suppressExecutionWorkspaceGates ? [] : executionPlanWarn;
|
|
2153
2224
|
const sessionWarn = sessionWarnings(target, activeSession);
|
|
2154
|
-
const installWarn = installationCompletenessWarnings(target);
|
|
2155
|
-
const copilot = copilotIntegrationReport(target);
|
|
2156
|
-
const copilotWarn = copilot.warnings;
|
|
2157
|
-
const reviewWarn = planReviewWarnings(stateText, p);
|
|
2225
|
+
const installWarn = installationCompletenessWarnings(target);
|
|
2226
|
+
const copilot = copilotIntegrationReport(target);
|
|
2227
|
+
const copilotWarn = copilot.warnings;
|
|
2228
|
+
const reviewWarn = suppressExecutionWorkspaceGates ? [] : planReviewWarnings(stateText, p);
|
|
2158
2229
|
const planSelfEvaluation = {
|
|
2159
2230
|
...parsedPlanSelfEvaluation,
|
|
2160
2231
|
best_plan_current: parsedPlanSelfEvaluation.bestPlan === 'sim'
|
|
@@ -2165,7 +2236,9 @@ function buildHealthReport(target) {
|
|
|
2165
2236
|
threshold,
|
|
2166
2237
|
executable: hasExecutablePlanSelfEvaluation(parsedPlanSelfEvaluation, threshold),
|
|
2167
2238
|
};
|
|
2168
|
-
const
|
|
2239
|
+
const releaseReadiness = workspaceInfo.workspaceMode === 'product_package'
|
|
2240
|
+
? require('./oxe-release.cjs').inspectReleaseReadiness(target, { packageRoot: target })
|
|
2241
|
+
: null;
|
|
2169
2242
|
const eventsSummary = operational.summarizeEvents(operational.readEvents(target, activeSession));
|
|
2170
2243
|
const memoryLayers = operational.buildMemoryLayers(target, activeSession);
|
|
2171
2244
|
const enterpriseRuntime = summarizeEnterpriseRuntime(target, activeRun, activeSession, config);
|
|
@@ -2312,7 +2385,7 @@ function buildHealthReport(target) {
|
|
|
2312
2385
|
if (semanticsAudit.mismatches.length) {
|
|
2313
2386
|
semanticsWarn.push(`${semanticsAudit.mismatches.length} wrapper(s) com drift semântico detectado.`);
|
|
2314
2387
|
}
|
|
2315
|
-
const semanticsDrift = {
|
|
2388
|
+
const semanticsDrift = {
|
|
2316
2389
|
ok: semanticsWarn.length === 0 && semanticsAudit.ok,
|
|
2317
2390
|
contractVersion: runtimeSemantics.CONTRACT_VERSION,
|
|
2318
2391
|
manifestPath: base.runtimeSemanticsManifest,
|
|
@@ -2334,15 +2407,16 @@ function buildHealthReport(target) {
|
|
|
2334
2407
|
),
|
|
2335
2408
|
},
|
|
2336
2409
|
};
|
|
2337
|
-
const hardFailure = Boolean(parseError) || sessionWarn.some((w) => /não existe|sem SESSION\.md/i.test(w));
|
|
2338
|
-
const
|
|
2339
|
-
|
|
2340
|
-
|
|
2341
|
-
|
|
2342
|
-
|
|
2343
|
-
|
|
2344
|
-
|
|
2345
|
-
|
|
2410
|
+
const hardFailure = Boolean(parseError) || sessionWarn.some((w) => /não existe|sem SESSION\.md/i.test(w));
|
|
2411
|
+
const planWarningCount = suppressExecutionWorkspaceGates ? 0 : planWarn.length;
|
|
2412
|
+
const warningCount =
|
|
2413
|
+
phaseWarn.length +
|
|
2414
|
+
runtimeWarn.length +
|
|
2415
|
+
reviewWarn.length +
|
|
2416
|
+
enterpriseRuntime.enterpriseWarnings.length +
|
|
2417
|
+
specWarn.length +
|
|
2418
|
+
planWarningCount +
|
|
2419
|
+
capabilityWarn.length +
|
|
2346
2420
|
investigationWarn.length +
|
|
2347
2421
|
sessionWarn.length +
|
|
2348
2422
|
installWarn.length +
|
|
@@ -2353,8 +2427,9 @@ function buildHealthReport(target) {
|
|
|
2353
2427
|
(sumWarn ? 1 : 0);
|
|
2354
2428
|
const healthStatus = hardFailure ? 'broken' : warningCount > 0 ? 'warning' : 'healthy';
|
|
2355
2429
|
|
|
2356
|
-
return {
|
|
2357
|
-
|
|
2430
|
+
return {
|
|
2431
|
+
workspaceMode: workspaceInfo.workspaceMode,
|
|
2432
|
+
configPath: cfgPath,
|
|
2358
2433
|
configParseError: parseError,
|
|
2359
2434
|
unknownConfigKeys: shape.unknownKeys,
|
|
2360
2435
|
typeErrors: shape.typeErrors,
|
|
@@ -2427,8 +2502,9 @@ function buildHealthReport(target) {
|
|
|
2427
2502
|
: null,
|
|
2428
2503
|
contextPacks,
|
|
2429
2504
|
contextQuality,
|
|
2430
|
-
semanticsDrift,
|
|
2431
|
-
|
|
2505
|
+
semanticsDrift,
|
|
2506
|
+
releaseReadiness,
|
|
2507
|
+
packFreshness,
|
|
2432
2508
|
activeSummaryRefs,
|
|
2433
2509
|
healthStatus,
|
|
2434
2510
|
next,
|
|
@@ -2474,8 +2550,10 @@ module.exports = {
|
|
|
2474
2550
|
phaseCoherenceWarnings,
|
|
2475
2551
|
verifyGapsWithoutSummaryWarning,
|
|
2476
2552
|
specSectionWarnings,
|
|
2477
|
-
planWaveWarningsFixed,
|
|
2478
|
-
planTaskAceiteWarnings,
|
|
2553
|
+
planWaveWarningsFixed,
|
|
2554
|
+
planTaskAceiteWarnings,
|
|
2555
|
+
detectWorkspaceMode,
|
|
2556
|
+
shouldSuppressExecutionWorkspaceGates,
|
|
2479
2557
|
suggestNextStep,
|
|
2480
2558
|
buildHealthReport,
|
|
2481
2559
|
buildExecutionRationality: rationality.buildExecutionRationality,
|
package/bin/lib/oxe-release.cjs
CHANGED
|
@@ -5,6 +5,7 @@ const path = require('path');
|
|
|
5
5
|
const { spawnSync } = require('child_process');
|
|
6
6
|
|
|
7
7
|
const oxeManifest = require('./oxe-manifest.cjs');
|
|
8
|
+
const runtimeSemantics = require('./oxe-runtime-semantics.cjs');
|
|
8
9
|
|
|
9
10
|
const REQUIRED_RUNTIMES = [
|
|
10
11
|
'cursor',
|
|
@@ -269,6 +270,7 @@ function loadRuntimeSmokeReport(projectRoot) {
|
|
|
269
270
|
&& item.oxe_present
|
|
270
271
|
&& item.workflow_resolution_ok
|
|
271
272
|
&& item.wrapper_drift_ok !== false
|
|
273
|
+
&& item.extra_checks_ok !== false
|
|
272
274
|
&& item.uninstall_ok
|
|
273
275
|
);
|
|
274
276
|
});
|
|
@@ -301,11 +303,42 @@ function readVersionSnapshot(projectRoot) {
|
|
|
301
303
|
};
|
|
302
304
|
}
|
|
303
305
|
|
|
306
|
+
function inspectCanonicalSource(projectRoot) {
|
|
307
|
+
const workflowsDir = path.join(projectRoot, 'oxe', 'workflows');
|
|
308
|
+
const referencesDir = path.join(workflowsDir, 'references');
|
|
309
|
+
const contractsPath = path.join(referencesDir, 'workflow-runtime-contracts.json');
|
|
310
|
+
const commandsDir = path.join(projectRoot, 'commands', 'oxe');
|
|
311
|
+
const workflowFiles = fs.existsSync(workflowsDir)
|
|
312
|
+
? fs.readdirSync(workflowsDir).filter((name) => name.endsWith('.md'))
|
|
313
|
+
: [];
|
|
314
|
+
const registryIssues = runtimeSemantics.validateWorkflowContractsRegistry();
|
|
315
|
+
return {
|
|
316
|
+
workflowsDir,
|
|
317
|
+
referencesDir,
|
|
318
|
+
contractsPath,
|
|
319
|
+
commandsDir,
|
|
320
|
+
workflowsPresent: fs.existsSync(workflowsDir),
|
|
321
|
+
referencesPresent: fs.existsSync(referencesDir),
|
|
322
|
+
commandsPresent: fs.existsSync(commandsDir),
|
|
323
|
+
contractsPresent: fs.existsSync(contractsPath),
|
|
324
|
+
workflowCount: workflowFiles.length,
|
|
325
|
+
contractVersion: runtimeSemantics.CONTRACT_VERSION,
|
|
326
|
+
registryIssues,
|
|
327
|
+
ok: fs.existsSync(workflowsDir)
|
|
328
|
+
&& fs.existsSync(referencesDir)
|
|
329
|
+
&& fs.existsSync(commandsDir)
|
|
330
|
+
&& fs.existsSync(contractsPath)
|
|
331
|
+
&& workflowFiles.length > 0
|
|
332
|
+
&& registryIssues.length === 0,
|
|
333
|
+
};
|
|
334
|
+
}
|
|
335
|
+
|
|
304
336
|
function buildReleaseManifest(projectRoot, options = {}) {
|
|
305
337
|
const packageRoot = path.resolve(options.packageRoot || projectRoot);
|
|
306
338
|
const paths = releasePaths(projectRoot);
|
|
307
339
|
const versions = readVersionSnapshot(projectRoot);
|
|
308
340
|
const runtimeEntry = path.join(packageRoot, 'lib', 'runtime', 'index.js');
|
|
341
|
+
const canonicalSource = inspectCanonicalSource(projectRoot);
|
|
309
342
|
const wrapperSync = options.skipWrapperSync ? {
|
|
310
343
|
before: collectWrapperHashes(projectRoot),
|
|
311
344
|
after: collectWrapperHashes(projectRoot),
|
|
@@ -313,6 +346,7 @@ function buildReleaseManifest(projectRoot, options = {}) {
|
|
|
313
346
|
mismatches: [],
|
|
314
347
|
ok: true,
|
|
315
348
|
} : syncWrappers(projectRoot, packageRoot);
|
|
349
|
+
const semanticsAudit = runtimeSemantics.auditRuntimeTargets(projectRoot);
|
|
316
350
|
const smoke = loadRuntimeSmokeReport(projectRoot);
|
|
317
351
|
const recovery = loadRecoveryFixtureReport(projectRoot);
|
|
318
352
|
const multiAgent = loadMultiAgentSoakReport(projectRoot);
|
|
@@ -332,6 +366,12 @@ function buildReleaseManifest(projectRoot, options = {}) {
|
|
|
332
366
|
path: runtimeEntry,
|
|
333
367
|
ok: fs.existsSync(runtimeEntry),
|
|
334
368
|
},
|
|
369
|
+
canonical_source: canonicalSource,
|
|
370
|
+
semantics: {
|
|
371
|
+
contractVersion: runtimeSemantics.CONTRACT_VERSION,
|
|
372
|
+
registryPath: runtimeSemantics.CONTRACTS_PATH,
|
|
373
|
+
audit: semanticsAudit,
|
|
374
|
+
},
|
|
335
375
|
wrappers: {
|
|
336
376
|
hash_before_sync: wrapperSync.before,
|
|
337
377
|
hash_after_sync: wrapperSync.after,
|
|
@@ -354,8 +394,8 @@ function buildReleaseManifest(projectRoot, options = {}) {
|
|
|
354
394
|
return manifest;
|
|
355
395
|
}
|
|
356
396
|
|
|
357
|
-
function
|
|
358
|
-
const
|
|
397
|
+
function evaluateReleaseManifest(manifest, options = {}) {
|
|
398
|
+
const enforceSync = options.enforceSync !== false;
|
|
359
399
|
const blockers = [];
|
|
360
400
|
const warnings = [];
|
|
361
401
|
const versions = manifest.versions;
|
|
@@ -378,10 +418,22 @@ function checkReleaseConsistency(projectRoot, options = {}) {
|
|
|
378
418
|
if (!versions.changelog.date) blockers.push('CHANGELOG.md topo sem data');
|
|
379
419
|
if (!versions.changelog.hasHighlights) blockers.push('CHANGELOG.md topo sem highlights');
|
|
380
420
|
}
|
|
421
|
+
const canonical = manifest.canonical_source || {};
|
|
422
|
+
if (!canonical.ok) {
|
|
423
|
+
blockers.push('árvore canónica ausente ou inválida');
|
|
424
|
+
}
|
|
425
|
+
if (!canonical.workflowsPresent) blockers.push('oxe/workflows ausente');
|
|
426
|
+
if (!canonical.referencesPresent) blockers.push('oxe/workflows/references ausente');
|
|
427
|
+
if (!canonical.commandsPresent) blockers.push('commands/oxe ausente');
|
|
428
|
+
if (!canonical.contractsPresent) blockers.push('workflow-runtime-contracts.json ausente');
|
|
429
|
+
if (canonical.workflowCount === 0) blockers.push('oxe/workflows sem workflows canónicos');
|
|
430
|
+
if (Array.isArray(canonical.registryIssues) && canonical.registryIssues.length) {
|
|
431
|
+
blockers.push('workflow-runtime-contracts.json inválido');
|
|
432
|
+
}
|
|
381
433
|
if (!manifest.runtime_compiled.ok) {
|
|
382
434
|
blockers.push('runtime não compilado (lib/runtime/index.js ausente)');
|
|
383
435
|
}
|
|
384
|
-
if (!manifest.wrappers.sync.ok) {
|
|
436
|
+
if (enforceSync && !manifest.wrappers.sync.ok) {
|
|
385
437
|
if (manifest.wrappers.sync.scripts.some((entry) => !entry.ok)) {
|
|
386
438
|
blockers.push('sync de wrappers falhou');
|
|
387
439
|
}
|
|
@@ -389,6 +441,10 @@ function checkReleaseConsistency(projectRoot, options = {}) {
|
|
|
389
441
|
blockers.push('wrappers ficam dirty após sync-runtime-metadata/sync:cursor');
|
|
390
442
|
}
|
|
391
443
|
}
|
|
444
|
+
const semanticsAudit = manifest.semantics && manifest.semantics.audit;
|
|
445
|
+
if (!semanticsAudit || semanticsAudit.ok !== true) {
|
|
446
|
+
blockers.push('drift semântico entre workflows e wrappers');
|
|
447
|
+
}
|
|
392
448
|
if (!manifest.reports.runtime_smoke.present || !manifest.reports.runtime_smoke.ok) {
|
|
393
449
|
blockers.push('runtime smoke matrix incompleta ou com falhas');
|
|
394
450
|
}
|
|
@@ -406,10 +462,23 @@ function checkReleaseConsistency(projectRoot, options = {}) {
|
|
|
406
462
|
blockers,
|
|
407
463
|
warnings,
|
|
408
464
|
manifest,
|
|
409
|
-
manifestPath: releasePaths(
|
|
465
|
+
manifestPath: releasePaths(manifest.project_root).manifest,
|
|
410
466
|
};
|
|
411
467
|
}
|
|
412
468
|
|
|
469
|
+
function checkReleaseConsistency(projectRoot, options = {}) {
|
|
470
|
+
const manifest = buildReleaseManifest(projectRoot, options);
|
|
471
|
+
return evaluateReleaseManifest(manifest, { enforceSync: true });
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
function inspectReleaseReadiness(projectRoot, options = {}) {
|
|
475
|
+
const manifest = buildReleaseManifest(projectRoot, {
|
|
476
|
+
...options,
|
|
477
|
+
skipWrapperSync: true,
|
|
478
|
+
});
|
|
479
|
+
return evaluateReleaseManifest(manifest, { enforceSync: false });
|
|
480
|
+
}
|
|
481
|
+
|
|
413
482
|
module.exports = {
|
|
414
483
|
REQUIRED_RUNTIMES,
|
|
415
484
|
WRAPPER_TARGETS,
|
|
@@ -419,5 +488,8 @@ module.exports = {
|
|
|
419
488
|
loadRecoveryFixtureReport,
|
|
420
489
|
loadMultiAgentSoakReport,
|
|
421
490
|
buildReleaseManifest,
|
|
491
|
+
inspectCanonicalSource,
|
|
492
|
+
evaluateReleaseManifest,
|
|
493
|
+
inspectReleaseReadiness,
|
|
422
494
|
checkReleaseConsistency,
|
|
423
495
|
};
|