oxe-cc 1.5.0 → 1.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.cursor/commands/oxe-dashboard.md +2 -2
- package/.cursor/commands/oxe-execute.md +2 -2
- package/.cursor/commands/oxe-plan.md +2 -2
- package/.github/prompts/oxe-dashboard.prompt.md +2 -2
- package/.github/prompts/oxe-execute.prompt.md +2 -2
- package/.github/prompts/oxe-plan.prompt.md +2 -2
- package/CHANGELOG.md +25 -0
- package/README.md +2 -2
- package/bin/lib/oxe-context-engine.cjs +9 -4
- package/bin/lib/oxe-dashboard.cjs +119 -53
- package/bin/lib/oxe-project-health.cjs +368 -111
- package/bin/lib/oxe-rationality.cjs +385 -0
- package/bin/oxe-cc.js +57 -31
- package/commands/oxe/dashboard.md +2 -2
- package/commands/oxe/execute.md +2 -2
- package/commands/oxe/plan.md +2 -2
- package/docs/RUNTIME-SMOKE-MATRIX.md +1 -1
- package/lib/sdk/index.cjs +10 -6
- package/lib/sdk/index.d.ts +78 -24
- package/oxe/templates/CONFIG.md +1 -1
- package/oxe/templates/EXECUTION-RUNTIME.template.md +1 -1
- package/oxe/templates/FIXTURE-PACK.template.json +34 -0
- package/oxe/templates/FIXTURE-PACK.template.md +21 -0
- package/oxe/templates/IMPLEMENTATION-PACK.template.json +52 -0
- package/oxe/templates/IMPLEMENTATION-PACK.template.md +36 -0
- package/oxe/templates/PLAN.template.md +46 -37
- package/oxe/templates/REFERENCE-ANCHORS.template.md +24 -0
- package/oxe/templates/config.template.json +1 -1
- package/oxe/workflows/execute.md +36 -20
- package/oxe/workflows/next.md +1 -1
- package/oxe/workflows/plan.md +80 -22
- package/oxe/workflows/references/flow-robustness-contract.md +3 -3
- package/oxe/workflows/references/workflow-runtime-contracts.json +127 -95
- package/oxe/workflows/verify.md +4 -4
- package/package.json +1 -1
- package/packages/runtime/package.json +1 -1
- package/vscode-extension/oxe-agents-1.5.1.vsix +0 -0
- package/vscode-extension/package.json +1 -1
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
const fs = require('fs');
|
|
4
|
-
const os = require('os');
|
|
5
|
-
const path = require('path');
|
|
6
|
-
const operational = require('./oxe-operational.cjs');
|
|
7
|
-
const azure = require('./oxe-azure.cjs');
|
|
3
|
+
const fs = require('fs');
|
|
4
|
+
const os = require('os');
|
|
5
|
+
const path = require('path');
|
|
6
|
+
const operational = require('./oxe-operational.cjs');
|
|
7
|
+
const azure = require('./oxe-azure.cjs');
|
|
8
|
+
const rationality = require('./oxe-rationality.cjs');
|
|
8
9
|
|
|
9
10
|
/** @type {string[]} */
|
|
10
11
|
const ALLOWED_CONFIG_KEYS = [
|
|
@@ -55,15 +56,75 @@ const INSTALL_REPO_LAYOUTS = ['nested', 'classic'];
|
|
|
55
56
|
/** @type {string[]} */
|
|
56
57
|
const INSTALL_OBJECT_KEYS = ['profile', 'repo_layout', 'ide_scope', 'vscode', 'include_commands_dir', 'include_agents_md'];
|
|
57
58
|
|
|
58
|
-
const EXPECTED_CODEBASE_MAPS = [
|
|
59
|
-
'OVERVIEW.md',
|
|
60
|
-
'STACK.md',
|
|
61
|
-
'STRUCTURE.md',
|
|
62
|
-
'TESTING.md',
|
|
63
|
-
'INTEGRATIONS.md',
|
|
64
|
-
'CONVENTIONS.md',
|
|
65
|
-
'CONCERNS.md',
|
|
66
|
-
];
|
|
59
|
+
const EXPECTED_CODEBASE_MAPS = [
|
|
60
|
+
'OVERVIEW.md',
|
|
61
|
+
'STACK.md',
|
|
62
|
+
'STRUCTURE.md',
|
|
63
|
+
'TESTING.md',
|
|
64
|
+
'INTEGRATIONS.md',
|
|
65
|
+
'CONVENTIONS.md',
|
|
66
|
+
'CONCERNS.md',
|
|
67
|
+
];
|
|
68
|
+
|
|
69
|
+
const MIN_EXECUTABLE_PLAN_CONFIDENCE = 90;
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* @param {unknown} value
|
|
73
|
+
* @returns {number}
|
|
74
|
+
*/
|
|
75
|
+
function normalizePlanConfidenceThreshold(value) {
|
|
76
|
+
const parsed = Number(value);
|
|
77
|
+
if (!Number.isFinite(parsed)) return MIN_EXECUTABLE_PLAN_CONFIDENCE;
|
|
78
|
+
return Math.max(MIN_EXECUTABLE_PLAN_CONFIDENCE, parsed);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* @param {number | null | undefined} confidence
|
|
83
|
+
* @param {number} threshold
|
|
84
|
+
* @returns {boolean}
|
|
85
|
+
*/
|
|
86
|
+
function isExecutablePlanConfidence(confidence, threshold) {
|
|
87
|
+
return Number.isFinite(confidence) && Number(confidence) > normalizePlanConfidenceThreshold(threshold);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* O gate racional só deve bloquear antes da primeira mutação real.
|
|
92
|
+
* Depois que a execução entrou em curso ou já foi verificada, os packs
|
|
93
|
+
* continuam úteis para diagnóstico, mas não podem reescrever o próximo passo.
|
|
94
|
+
*
|
|
95
|
+
* @param {string | null} phase
|
|
96
|
+
* @returns {boolean}
|
|
97
|
+
*/
|
|
98
|
+
function shouldEnforceExecutionRationalityGate(phase) {
|
|
99
|
+
const low = String(phase || '').trim().toLowerCase();
|
|
100
|
+
return !new Set([
|
|
101
|
+
'executing',
|
|
102
|
+
'verifying',
|
|
103
|
+
'verify_complete',
|
|
104
|
+
'verify_failed',
|
|
105
|
+
'retro_complete',
|
|
106
|
+
]).has(low);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* @param {{
|
|
111
|
+
* hasSection: boolean,
|
|
112
|
+
* bestPlan: string | null,
|
|
113
|
+
* confidence: number | null,
|
|
114
|
+
* warnings: string[],
|
|
115
|
+
* }} info
|
|
116
|
+
* @param {number} threshold
|
|
117
|
+
* @returns {boolean}
|
|
118
|
+
*/
|
|
119
|
+
function hasExecutablePlanSelfEvaluation(info, threshold) {
|
|
120
|
+
return Boolean(
|
|
121
|
+
info
|
|
122
|
+
&& info.hasSection
|
|
123
|
+
&& info.bestPlan === 'sim'
|
|
124
|
+
&& !info.warnings.length
|
|
125
|
+
&& isExecutablePlanConfidence(info.confidence, threshold)
|
|
126
|
+
);
|
|
127
|
+
}
|
|
67
128
|
|
|
68
129
|
/**
|
|
69
130
|
* @param {string} targetProject
|
|
@@ -143,9 +204,9 @@ function loadOxeConfigMerged(targetProject) {
|
|
|
143
204
|
discuss_before_plan: false,
|
|
144
205
|
after_verify_suggest_pr: true,
|
|
145
206
|
after_verify_draft_commit: true,
|
|
146
|
-
after_verify_suggest_uat: false,
|
|
147
|
-
verification_depth: 'standard',
|
|
148
|
-
plan_confidence_threshold:
|
|
207
|
+
after_verify_suggest_uat: false,
|
|
208
|
+
verification_depth: 'standard',
|
|
209
|
+
plan_confidence_threshold: 90,
|
|
149
210
|
default_verify_command: '',
|
|
150
211
|
scan_max_age_days: 0,
|
|
151
212
|
compact_max_age_days: 0,
|
|
@@ -590,10 +651,15 @@ function oxePaths(target) {
|
|
|
590
651
|
events: path.join(oxe, 'OXE-EVENTS.ndjson'),
|
|
591
652
|
copilotManifest: path.join(oxe, 'install', 'copilot-vscode.json'),
|
|
592
653
|
runtimeSemanticsManifest: path.join(oxe, 'install', 'runtime-semantics.json'),
|
|
593
|
-
spec: path.join(oxe, 'SPEC.md'),
|
|
594
|
-
plan: path.join(oxe, 'PLAN.md'),
|
|
595
|
-
|
|
596
|
-
|
|
654
|
+
spec: path.join(oxe, 'SPEC.md'),
|
|
655
|
+
plan: path.join(oxe, 'PLAN.md'),
|
|
656
|
+
implementationPackMd: path.join(oxe, 'IMPLEMENTATION-PACK.md'),
|
|
657
|
+
implementationPackJson: path.join(oxe, 'IMPLEMENTATION-PACK.json'),
|
|
658
|
+
referenceAnchors: path.join(oxe, 'REFERENCE-ANCHORS.md'),
|
|
659
|
+
fixturePackMd: path.join(oxe, 'FIXTURE-PACK.md'),
|
|
660
|
+
fixturePackJson: path.join(oxe, 'FIXTURE-PACK.json'),
|
|
661
|
+
quick: path.join(oxe, 'QUICK.md'),
|
|
662
|
+
verify: path.join(oxe, 'VERIFY.md'),
|
|
597
663
|
discuss: path.join(oxe, 'DISCUSS.md'),
|
|
598
664
|
summary: path.join(oxe, 'SUMMARY.md'),
|
|
599
665
|
codebase: path.join(oxe, 'codebase'),
|
|
@@ -606,11 +672,11 @@ function oxePaths(target) {
|
|
|
606
672
|
* @param {string} target
|
|
607
673
|
* @param {string | null} activeSession
|
|
608
674
|
*/
|
|
609
|
-
function scopedOxePaths(target, activeSession) {
|
|
610
|
-
const base = oxePaths(target);
|
|
611
|
-
if (!activeSession) return { ...base, activeSession: null, scopedRoot: base.oxe };
|
|
612
|
-
const sessionRoot = path.join(base.oxe, ...activeSession.split('/'));
|
|
613
|
-
return {
|
|
675
|
+
function scopedOxePaths(target, activeSession) {
|
|
676
|
+
const base = oxePaths(target);
|
|
677
|
+
if (!activeSession) return { ...base, activeSession: null, scopedRoot: base.oxe };
|
|
678
|
+
const sessionRoot = path.join(base.oxe, ...activeSession.split('/'));
|
|
679
|
+
return {
|
|
614
680
|
...base,
|
|
615
681
|
activeSession,
|
|
616
682
|
scopedRoot: sessionRoot,
|
|
@@ -625,15 +691,61 @@ function scopedOxePaths(target, activeSession) {
|
|
|
625
691
|
events: path.join(sessionRoot, 'execution', 'OXE-EVENTS.ndjson'),
|
|
626
692
|
investigationsIndex: path.join(sessionRoot, 'research', 'INVESTIGATIONS.md'),
|
|
627
693
|
investigationsDir: path.join(sessionRoot, 'research', 'investigations'),
|
|
628
|
-
spec: path.join(sessionRoot, 'spec', 'SPEC.md'),
|
|
629
|
-
discuss: path.join(sessionRoot, 'spec', 'DISCUSS.md'),
|
|
630
|
-
plan: path.join(sessionRoot, 'plan', 'PLAN.md'),
|
|
631
|
-
|
|
632
|
-
|
|
694
|
+
spec: path.join(sessionRoot, 'spec', 'SPEC.md'),
|
|
695
|
+
discuss: path.join(sessionRoot, 'spec', 'DISCUSS.md'),
|
|
696
|
+
plan: path.join(sessionRoot, 'plan', 'PLAN.md'),
|
|
697
|
+
planAgents: path.join(sessionRoot, 'plan', 'plan-agents.json'),
|
|
698
|
+
implementationPackMd: path.join(sessionRoot, 'plan', 'IMPLEMENTATION-PACK.md'),
|
|
699
|
+
implementationPackJson: path.join(sessionRoot, 'plan', 'IMPLEMENTATION-PACK.json'),
|
|
700
|
+
referenceAnchors: path.join(sessionRoot, 'plan', 'REFERENCE-ANCHORS.md'),
|
|
701
|
+
fixturePackMd: path.join(sessionRoot, 'plan', 'FIXTURE-PACK.md'),
|
|
702
|
+
fixturePackJson: path.join(sessionRoot, 'plan', 'FIXTURE-PACK.json'),
|
|
703
|
+
quick: path.join(sessionRoot, 'plan', 'QUICK.md'),
|
|
704
|
+
verify: path.join(sessionRoot, 'verification', 'VERIFY.md'),
|
|
633
705
|
summary: path.join(sessionRoot, 'verification', 'SUMMARY.md'),
|
|
634
|
-
executionState: path.join(sessionRoot, 'execution', 'STATE.md'),
|
|
635
|
-
};
|
|
636
|
-
}
|
|
706
|
+
executionState: path.join(sessionRoot, 'execution', 'STATE.md'),
|
|
707
|
+
};
|
|
708
|
+
}
|
|
709
|
+
|
|
710
|
+
/**
|
|
711
|
+
* Para leitura, preferimos o layout session-scoped quando ele existe.
|
|
712
|
+
* Enquanto a migração não é total, mantemos fallback explícito para os
|
|
713
|
+
* artefatos canónicos ainda materializados na raiz `.oxe/`.
|
|
714
|
+
*
|
|
715
|
+
* @param {string} target
|
|
716
|
+
* @param {string | null} activeSession
|
|
717
|
+
*/
|
|
718
|
+
function resolvedReadableOxePaths(target, activeSession) {
|
|
719
|
+
const base = oxePaths(target);
|
|
720
|
+
const scoped = scopedOxePaths(target, activeSession);
|
|
721
|
+
if (!activeSession) return scoped;
|
|
722
|
+
/**
|
|
723
|
+
* @param {string} key
|
|
724
|
+
* @returns {string}
|
|
725
|
+
*/
|
|
726
|
+
function preferScoped(key) {
|
|
727
|
+
return fs.existsSync(scoped[key]) ? scoped[key] : base[key];
|
|
728
|
+
}
|
|
729
|
+
return {
|
|
730
|
+
...scoped,
|
|
731
|
+
planReview: preferScoped('planReview'),
|
|
732
|
+
planReviewComments: preferScoped('planReviewComments'),
|
|
733
|
+
runtime: preferScoped('runtime'),
|
|
734
|
+
checkpoints: preferScoped('checkpoints'),
|
|
735
|
+
spec: preferScoped('spec'),
|
|
736
|
+
discuss: preferScoped('discuss'),
|
|
737
|
+
plan: preferScoped('plan'),
|
|
738
|
+
planAgents: preferScoped('planAgents'),
|
|
739
|
+
implementationPackMd: preferScoped('implementationPackMd'),
|
|
740
|
+
implementationPackJson: preferScoped('implementationPackJson'),
|
|
741
|
+
referenceAnchors: preferScoped('referenceAnchors'),
|
|
742
|
+
fixturePackMd: preferScoped('fixturePackMd'),
|
|
743
|
+
fixturePackJson: preferScoped('fixturePackJson'),
|
|
744
|
+
quick: preferScoped('quick'),
|
|
745
|
+
verify: preferScoped('verify'),
|
|
746
|
+
summary: preferScoped('summary'),
|
|
747
|
+
};
|
|
748
|
+
}
|
|
637
749
|
|
|
638
750
|
/**
|
|
639
751
|
* @param {string} target
|
|
@@ -1436,10 +1548,10 @@ function planWaveWarningsFixed(planPath, maxPerWave) {
|
|
|
1436
1548
|
* warnings: string[],
|
|
1437
1549
|
* }}
|
|
1438
1550
|
*/
|
|
1439
|
-
function parsePlanSelfEvaluation(planPath) {
|
|
1440
|
-
const empty = { hasSection: false, bestPlan: null, confidence: null, warnings: [] };
|
|
1441
|
-
if (!fs.existsSync(planPath)) return empty;
|
|
1442
|
-
const raw = fs.readFileSync(planPath, 'utf8');
|
|
1551
|
+
function parsePlanSelfEvaluation(planPath) {
|
|
1552
|
+
const empty = { hasSection: false, bestPlan: null, confidence: null, warnings: [] };
|
|
1553
|
+
if (!fs.existsSync(planPath)) return empty;
|
|
1554
|
+
const raw = fs.readFileSync(planPath, 'utf8');
|
|
1443
1555
|
const m = raw.match(/##\s*Autoavaliação do Plano\s*([\s\S]*?)(?=\n## |\n#[^\#]|$)/i);
|
|
1444
1556
|
if (!m) {
|
|
1445
1557
|
return {
|
|
@@ -1447,27 +1559,60 @@ function parsePlanSelfEvaluation(planPath) {
|
|
|
1447
1559
|
warnings: ['PLAN.md sem a seção obrigatória "## Autoavaliação do Plano"'],
|
|
1448
1560
|
};
|
|
1449
1561
|
}
|
|
1450
|
-
const body = m[1];
|
|
1451
|
-
const best = body.match(/\*\*Melhor plano atual:\*\*\s*(sim|não|nao)/i);
|
|
1452
|
-
const confidence = body.match(/\*\*Confiança:\*\*\s*(\d{1,3})\s*%/i);
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
const
|
|
1456
|
-
|
|
1562
|
+
const body = m[1];
|
|
1563
|
+
const best = body.match(/\*\*Melhor plano atual:\*\*\s*(sim|não|nao)/i);
|
|
1564
|
+
const confidence = body.match(/\*\*Confiança:\*\*\s*(\d{1,3})\s*%/i);
|
|
1565
|
+
const confidenceVector = raw.match(/<confidence_vector\b[\s\S]*?<\/confidence_vector>/i);
|
|
1566
|
+
/** @type {string[]} */
|
|
1567
|
+
const warnings = [];
|
|
1568
|
+
const rubricLabels = [
|
|
1569
|
+
'Completude dos requisitos',
|
|
1457
1570
|
'Dependências conhecidas',
|
|
1458
1571
|
'Risco técnico',
|
|
1459
1572
|
'Impacto no código existente',
|
|
1460
1573
|
'Clareza da validação / testes',
|
|
1461
1574
|
'Lacunas externas / decisões pendentes',
|
|
1462
1575
|
];
|
|
1463
|
-
if (!best) warnings.push('PLAN.md: autoavaliação sem "Melhor plano atual: sim|não"');
|
|
1464
|
-
if (!confidence) warnings.push('PLAN.md: autoavaliação sem "Confiança: NN%"');
|
|
1465
|
-
if (!/\*\*Principais incertezas:\*\*/i.test(body)) warnings.push('PLAN.md: autoavaliação sem "Principais incertezas"');
|
|
1466
|
-
if (!/\*\*Alternativas descartadas:\*\*/i.test(body)) warnings.push('PLAN.md: autoavaliação sem "Alternativas descartadas"');
|
|
1467
|
-
if (!/\*\*Condição para replanejar:\*\*/i.test(body)) warnings.push('PLAN.md: autoavaliação sem "Condição para replanejar"');
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
}
|
|
1576
|
+
if (!best) warnings.push('PLAN.md: autoavaliação sem "Melhor plano atual: sim|não"');
|
|
1577
|
+
if (!confidence) warnings.push('PLAN.md: autoavaliação sem "Confiança: NN%"');
|
|
1578
|
+
if (!/\*\*Principais incertezas:\*\*/i.test(body)) warnings.push('PLAN.md: autoavaliação sem "Principais incertezas"');
|
|
1579
|
+
if (!/\*\*Alternativas descartadas:\*\*/i.test(body)) warnings.push('PLAN.md: autoavaliação sem "Alternativas descartadas"');
|
|
1580
|
+
if (!/\*\*Condição para replanejar:\*\*/i.test(body)) warnings.push('PLAN.md: autoavaliação sem "Condição para replanejar"');
|
|
1581
|
+
if (!confidenceVector) {
|
|
1582
|
+
warnings.push('PLAN.md: autoavaliação sem bloco <confidence_vector>');
|
|
1583
|
+
} else {
|
|
1584
|
+
const vectorBlock = confidenceVector[0];
|
|
1585
|
+
const vectorGlobal = vectorBlock.match(/<global\b[^>]*score="([0-9.]+)"/i);
|
|
1586
|
+
const requiredDims = [
|
|
1587
|
+
'requirements',
|
|
1588
|
+
'dependencies',
|
|
1589
|
+
'technical_risk',
|
|
1590
|
+
'code_impact',
|
|
1591
|
+
'validation',
|
|
1592
|
+
'open_gaps',
|
|
1593
|
+
];
|
|
1594
|
+
if (!vectorGlobal) warnings.push('PLAN.md: confidence_vector sem nó <global score="...">');
|
|
1595
|
+
for (const dim of requiredDims) {
|
|
1596
|
+
if (!vectorBlock.includes(`name="${dim}"`)) {
|
|
1597
|
+
warnings.push(`PLAN.md: confidence_vector sem dimensão "${dim}"`);
|
|
1598
|
+
}
|
|
1599
|
+
}
|
|
1600
|
+
if (vectorGlobal) {
|
|
1601
|
+
const vectorGlobalScore = Number(vectorGlobal[1]);
|
|
1602
|
+
if (!Number.isFinite(vectorGlobalScore) || vectorGlobalScore < 0 || vectorGlobalScore > 1) {
|
|
1603
|
+
warnings.push('PLAN.md: confidence_vector com <global score> fora do intervalo 0.0–1.0');
|
|
1604
|
+
} else if (confidence) {
|
|
1605
|
+
const confidencePercent = Number(confidence[1]);
|
|
1606
|
+
const vectorPercent = Math.round(vectorGlobalScore * 100);
|
|
1607
|
+
if (Math.abs(vectorPercent - confidencePercent) > 5) {
|
|
1608
|
+
warnings.push(`PLAN.md: confiança declarada (${confidencePercent}%) diverge do confidence_vector (${vectorPercent}%)`);
|
|
1609
|
+
}
|
|
1610
|
+
}
|
|
1611
|
+
}
|
|
1612
|
+
}
|
|
1613
|
+
for (const label of rubricLabels) {
|
|
1614
|
+
if (!body.includes(label)) warnings.push(`PLAN.md: rubrica sem "${label}"`);
|
|
1615
|
+
}
|
|
1471
1616
|
const parsedConfidence = confidence ? Number(confidence[1]) : null;
|
|
1472
1617
|
if (parsedConfidence != null && (parsedConfidence < 0 || parsedConfidence > 100)) {
|
|
1473
1618
|
warnings.push('PLAN.md: confiança fora do intervalo 0–100%');
|
|
@@ -1478,23 +1623,70 @@ function parsePlanSelfEvaluation(planPath) {
|
|
|
1478
1623
|
confidence: parsedConfidence,
|
|
1479
1624
|
warnings,
|
|
1480
1625
|
};
|
|
1481
|
-
}
|
|
1482
|
-
|
|
1483
|
-
/**
|
|
1484
|
-
* @param {
|
|
1485
|
-
*
|
|
1486
|
-
*
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
|
|
1493
|
-
|
|
1494
|
-
|
|
1495
|
-
|
|
1496
|
-
|
|
1497
|
-
|
|
1626
|
+
}
|
|
1627
|
+
|
|
1628
|
+
/**
|
|
1629
|
+
* @param {{
|
|
1630
|
+
* hasSection: boolean,
|
|
1631
|
+
* bestPlan: string | null,
|
|
1632
|
+
* confidence: number | null,
|
|
1633
|
+
* warnings: string[],
|
|
1634
|
+
* }} info
|
|
1635
|
+
* @param {number} threshold
|
|
1636
|
+
* @returns {string[]}
|
|
1637
|
+
*/
|
|
1638
|
+
function planSelfEvaluationWarningsFromInfo(info, threshold) {
|
|
1639
|
+
const warns = [...info.warnings];
|
|
1640
|
+
if (info.bestPlan === 'não') warns.push('PLAN.md: autoavaliação declara que este não é o melhor plano atual');
|
|
1641
|
+
if (info.confidence != null && !isExecutablePlanConfidence(info.confidence, threshold)) {
|
|
1642
|
+
const normalizedThreshold = normalizePlanConfidenceThreshold(threshold);
|
|
1643
|
+
warns.push(`PLAN.md: confiança ${info.confidence}% não supera o limiar executável (>${normalizedThreshold}%)`);
|
|
1644
|
+
}
|
|
1645
|
+
return warns;
|
|
1646
|
+
}
|
|
1647
|
+
|
|
1648
|
+
/**
|
|
1649
|
+
* @param {string} planPath
|
|
1650
|
+
* @param {number} threshold
|
|
1651
|
+
* @returns {string[]}
|
|
1652
|
+
*/
|
|
1653
|
+
function planSelfEvaluationWarnings(planPath, threshold) {
|
|
1654
|
+
if (!fs.existsSync(planPath)) return [];
|
|
1655
|
+
return planSelfEvaluationWarningsFromInfo(parsePlanSelfEvaluation(planPath), threshold);
|
|
1656
|
+
}
|
|
1657
|
+
|
|
1658
|
+
/**
|
|
1659
|
+
* @param {{
|
|
1660
|
+
* applicable: boolean,
|
|
1661
|
+
* implementationPackReady: boolean,
|
|
1662
|
+
* referenceAnchorsReady: boolean,
|
|
1663
|
+
* fixturePackReady: boolean,
|
|
1664
|
+
* executionRationalityReady: boolean,
|
|
1665
|
+
* criticalExecutionGaps: string[],
|
|
1666
|
+
* implementationPack: { path?: string | null, tasks?: unknown[] } | null,
|
|
1667
|
+
* referenceAnchors: { path?: string | null, anchors?: unknown[], missingCriticalCount?: number } | null,
|
|
1668
|
+
* fixturePack: { path?: string | null, fixtures?: unknown[] } | null,
|
|
1669
|
+
* }} summary
|
|
1670
|
+
* @returns {string[]}
|
|
1671
|
+
*/
|
|
1672
|
+
function executionRationalityWarningsFromSummary(summary) {
|
|
1673
|
+
if (!summary || !summary.applicable) return [];
|
|
1674
|
+
/** @type {string[]} */
|
|
1675
|
+
const warns = [];
|
|
1676
|
+
if (!summary.implementationPackReady) {
|
|
1677
|
+
warns.push(`IMPLEMENTATION-PACK não está pronto em ${summary.implementationPack && summary.implementationPack.path ? summary.implementationPack.path : '.oxe/IMPLEMENTATION-PACK.json'}`);
|
|
1678
|
+
}
|
|
1679
|
+
if (!summary.referenceAnchorsReady) {
|
|
1680
|
+
warns.push(`REFERENCE-ANCHORS não está pronto em ${summary.referenceAnchors && summary.referenceAnchors.path ? summary.referenceAnchors.path : '.oxe/REFERENCE-ANCHORS.md'}`);
|
|
1681
|
+
}
|
|
1682
|
+
if (!summary.fixturePackReady) {
|
|
1683
|
+
warns.push(`FIXTURE-PACK não está pronto em ${summary.fixturePack && summary.fixturePack.path ? summary.fixturePack.path : '.oxe/FIXTURE-PACK.json'}`);
|
|
1684
|
+
}
|
|
1685
|
+
if (Array.isArray(summary.criticalExecutionGaps) && summary.criticalExecutionGaps.length) {
|
|
1686
|
+
warns.push(...summary.criticalExecutionGaps);
|
|
1687
|
+
}
|
|
1688
|
+
return Array.from(new Set(warns));
|
|
1689
|
+
}
|
|
1498
1690
|
|
|
1499
1691
|
/**
|
|
1500
1692
|
* @param {string} target
|
|
@@ -1648,12 +1840,12 @@ function planReviewWarnings(stateText, p) {
|
|
|
1648
1840
|
* @param {string} target
|
|
1649
1841
|
* @param {{ discuss_before_plan?: boolean }} cfg
|
|
1650
1842
|
*/
|
|
1651
|
-
function suggestNextStep(target, cfg = {}) {
|
|
1843
|
+
function suggestNextStep(target, cfg = {}) {
|
|
1652
1844
|
const base = oxePaths(target);
|
|
1653
1845
|
const stateText = fs.existsSync(base.state) ? fs.readFileSync(base.state, 'utf8') : '';
|
|
1654
|
-
const p =
|
|
1846
|
+
const p = resolvedReadableOxePaths(target, parseActiveSession(stateText));
|
|
1655
1847
|
const discussBefore = Boolean(cfg.discuss_before_plan);
|
|
1656
|
-
const threshold =
|
|
1848
|
+
const threshold = normalizePlanConfidenceThreshold(cfg.plan_confidence_threshold);
|
|
1657
1849
|
const has = (/** @type {string} */ f) => fs.existsSync(f);
|
|
1658
1850
|
const mapsComplete = EXPECTED_CODEBASE_MAPS.every((f) => has(path.join(p.codebase, f)));
|
|
1659
1851
|
const azureActive = azure.isAzureContextEnabled(target, cfg);
|
|
@@ -1752,17 +1944,49 @@ function suggestNextStep(target, cfg = {}) {
|
|
|
1752
1944
|
};
|
|
1753
1945
|
}
|
|
1754
1946
|
|
|
1755
|
-
const selfEval = parsePlanSelfEvaluation(p.plan);
|
|
1756
|
-
|
|
1757
|
-
|
|
1758
|
-
|
|
1759
|
-
|
|
1760
|
-
|
|
1761
|
-
|
|
1762
|
-
|
|
1763
|
-
|
|
1764
|
-
|
|
1765
|
-
|
|
1947
|
+
const selfEval = parsePlanSelfEvaluation(p.plan);
|
|
1948
|
+
const selfEvalWarnings = planSelfEvaluationWarningsFromInfo(selfEval, threshold);
|
|
1949
|
+
if (!hasExecutablePlanSelfEvaluation(selfEval, threshold)) {
|
|
1950
|
+
return {
|
|
1951
|
+
step: 'plan',
|
|
1952
|
+
cursorCmd: '/oxe-plan --replan',
|
|
1953
|
+
reason: selfEvalWarnings[0]
|
|
1954
|
+
? `${selfEvalWarnings[0]} — replaneje antes de executar`
|
|
1955
|
+
: `O plano atual ainda não passou no gate executável (> ${threshold}%)`,
|
|
1956
|
+
artifacts: ['.oxe/PLAN.md', '.oxe/STATE.md'],
|
|
1957
|
+
};
|
|
1958
|
+
}
|
|
1959
|
+
|
|
1960
|
+
const executionRationality = rationality.buildExecutionRationality({
|
|
1961
|
+
plan: p.plan,
|
|
1962
|
+
planAgents: p.planAgents,
|
|
1963
|
+
implementationPackJson: p.implementationPackJson,
|
|
1964
|
+
implementationPackMd: p.implementationPackMd,
|
|
1965
|
+
referenceAnchors: p.referenceAnchors,
|
|
1966
|
+
fixturePackJson: p.fixturePackJson,
|
|
1967
|
+
fixturePackMd: p.fixturePackMd,
|
|
1968
|
+
});
|
|
1969
|
+
if (
|
|
1970
|
+
shouldEnforceExecutionRationalityGate(phase)
|
|
1971
|
+
&& executionRationality.applicable
|
|
1972
|
+
&& !executionRationality.executionRationalityReady
|
|
1973
|
+
) {
|
|
1974
|
+
const reason = executionRationality.criticalExecutionGaps[0]
|
|
1975
|
+
|| 'Artefatos racionais de execução ainda não estão íntegros';
|
|
1976
|
+
return {
|
|
1977
|
+
step: 'plan',
|
|
1978
|
+
cursorCmd: '/oxe-plan --replan',
|
|
1979
|
+
reason: `${reason} — replaneje antes de executar`,
|
|
1980
|
+
artifacts: [
|
|
1981
|
+
'.oxe/PLAN.md',
|
|
1982
|
+
'.oxe/IMPLEMENTATION-PACK.json',
|
|
1983
|
+
'.oxe/REFERENCE-ANCHORS.md',
|
|
1984
|
+
'.oxe/FIXTURE-PACK.json',
|
|
1985
|
+
],
|
|
1986
|
+
};
|
|
1987
|
+
}
|
|
1988
|
+
|
|
1989
|
+
const reviewStatus = parsePlanReviewStatus(stateText);
|
|
1766
1990
|
if (phase === 'plan_ready' && (reviewStatus === 'needs_revision' || reviewStatus === 'rejected')) {
|
|
1767
1991
|
return {
|
|
1768
1992
|
step: 'plan',
|
|
@@ -1893,7 +2117,7 @@ function buildHealthReport(target) {
|
|
|
1893
2117
|
}
|
|
1894
2118
|
}
|
|
1895
2119
|
const activeSession = parseActiveSession(stateText);
|
|
1896
|
-
const p =
|
|
2120
|
+
const p = resolvedReadableOxePaths(target, activeSession);
|
|
1897
2121
|
const phase = parseStatePhase(stateText);
|
|
1898
2122
|
const scanDate = parseLastScanDate(stateText);
|
|
1899
2123
|
const stale = isStaleScan(scanDate, Number(config.scan_max_age_days) || 0);
|
|
@@ -1904,23 +2128,43 @@ function buildHealthReport(target) {
|
|
|
1904
2128
|
const phaseWarn = phase ? phaseCoherenceWarnings(phase, p) : [];
|
|
1905
2129
|
const runtimeWarn = runtimeWarnings(stateText, p);
|
|
1906
2130
|
const sumWarn = verifyGapsWithoutSummaryWarning(p.verify, p.summary);
|
|
1907
|
-
const specReq = Array.isArray(config.spec_required_sections) ? config.spec_required_sections : [];
|
|
1908
|
-
const specWarn = specSectionWarnings(p.spec, specReq.map(String));
|
|
1909
|
-
const threshold =
|
|
1910
|
-
const capabilityWarn = capabilityWarnings(p);
|
|
1911
|
-
const investigationWarn = investigationWarnings(p);
|
|
1912
|
-
const
|
|
1913
|
-
|
|
1914
|
-
|
|
1915
|
-
|
|
1916
|
-
|
|
1917
|
-
|
|
2131
|
+
const specReq = Array.isArray(config.spec_required_sections) ? config.spec_required_sections : [];
|
|
2132
|
+
const specWarn = specSectionWarnings(p.spec, specReq.map(String));
|
|
2133
|
+
const threshold = normalizePlanConfidenceThreshold(config.plan_confidence_threshold);
|
|
2134
|
+
const capabilityWarn = capabilityWarnings(p);
|
|
2135
|
+
const investigationWarn = investigationWarnings(p);
|
|
2136
|
+
const parsedPlanSelfEvaluation = parsePlanSelfEvaluation(p.plan);
|
|
2137
|
+
const executionRationality = rationality.buildExecutionRationality({
|
|
2138
|
+
plan: p.plan,
|
|
2139
|
+
planAgents: p.planAgents,
|
|
2140
|
+
implementationPackJson: p.implementationPackJson,
|
|
2141
|
+
implementationPackMd: p.implementationPackMd,
|
|
2142
|
+
referenceAnchors: p.referenceAnchors,
|
|
2143
|
+
fixturePackJson: p.fixturePackJson,
|
|
2144
|
+
fixturePackMd: p.fixturePackMd,
|
|
2145
|
+
});
|
|
2146
|
+
const planWarn = [
|
|
2147
|
+
...planWaveWarningsFixed(p.plan, Number(config.plan_max_tasks_per_wave) || 0),
|
|
2148
|
+
...planTaskAceiteWarnings(p.plan),
|
|
2149
|
+
...planSelfEvaluationWarningsFromInfo(parsedPlanSelfEvaluation, threshold),
|
|
2150
|
+
...executionRationalityWarningsFromSummary(executionRationality),
|
|
2151
|
+
...planAgentsWarnings(target),
|
|
2152
|
+
];
|
|
1918
2153
|
const sessionWarn = sessionWarnings(target, activeSession);
|
|
1919
2154
|
const installWarn = installationCompletenessWarnings(target);
|
|
1920
2155
|
const copilot = copilotIntegrationReport(target);
|
|
1921
2156
|
const copilotWarn = copilot.warnings;
|
|
1922
2157
|
const reviewWarn = planReviewWarnings(stateText, p);
|
|
1923
|
-
const planSelfEvaluation =
|
|
2158
|
+
const planSelfEvaluation = {
|
|
2159
|
+
...parsedPlanSelfEvaluation,
|
|
2160
|
+
best_plan_current: parsedPlanSelfEvaluation.bestPlan === 'sim'
|
|
2161
|
+
? true
|
|
2162
|
+
: parsedPlanSelfEvaluation.bestPlan === 'não'
|
|
2163
|
+
? false
|
|
2164
|
+
: null,
|
|
2165
|
+
threshold,
|
|
2166
|
+
executable: hasExecutablePlanSelfEvaluation(parsedPlanSelfEvaluation, threshold),
|
|
2167
|
+
};
|
|
1924
2168
|
const activeRun = operational.readRunState(target, activeSession);
|
|
1925
2169
|
const eventsSummary = operational.summarizeEvents(operational.readEvents(target, activeSession));
|
|
1926
2170
|
const memoryLayers = operational.buildMemoryLayers(target, activeSession);
|
|
@@ -2135,9 +2379,17 @@ function buildHealthReport(target) {
|
|
|
2135
2379
|
copilot,
|
|
2136
2380
|
summaryGapWarn: sumWarn,
|
|
2137
2381
|
specWarn,
|
|
2138
|
-
planWarn,
|
|
2139
|
-
planSelfEvaluation,
|
|
2140
|
-
|
|
2382
|
+
planWarn,
|
|
2383
|
+
planSelfEvaluation,
|
|
2384
|
+
implementationPackReady: executionRationality.implementationPackReady,
|
|
2385
|
+
referenceAnchorsReady: executionRationality.referenceAnchorsReady,
|
|
2386
|
+
fixturePackReady: executionRationality.fixturePackReady,
|
|
2387
|
+
executionRationalityReady: executionRationality.executionRationalityReady,
|
|
2388
|
+
criticalExecutionGaps: executionRationality.criticalExecutionGaps,
|
|
2389
|
+
executionRationality,
|
|
2390
|
+
planConfidenceThreshold: threshold,
|
|
2391
|
+
planConfidenceExecutable: planSelfEvaluation.executable,
|
|
2392
|
+
planReviewStatus: parsePlanReviewStatus(stateText),
|
|
2141
2393
|
activeRun,
|
|
2142
2394
|
eventsSummary,
|
|
2143
2395
|
memoryLayers,
|
|
@@ -2206,13 +2458,17 @@ module.exports = {
|
|
|
2206
2458
|
isStaleLessons,
|
|
2207
2459
|
copilotWorkspacePaths,
|
|
2208
2460
|
copilotLegacyPaths,
|
|
2209
|
-
copilotIntegrationReport,
|
|
2210
|
-
|
|
2461
|
+
copilotIntegrationReport,
|
|
2462
|
+
normalizePlanConfidenceThreshold,
|
|
2463
|
+
isExecutablePlanConfidence,
|
|
2464
|
+
hasExecutablePlanSelfEvaluation,
|
|
2465
|
+
planAgentsWarnings,
|
|
2211
2466
|
installationCompletenessWarnings,
|
|
2212
|
-
parsePlanSelfEvaluation,
|
|
2213
|
-
planSelfEvaluationWarnings,
|
|
2214
|
-
|
|
2215
|
-
|
|
2467
|
+
parsePlanSelfEvaluation,
|
|
2468
|
+
planSelfEvaluationWarnings,
|
|
2469
|
+
executionRationalityWarningsFromSummary,
|
|
2470
|
+
runtimeWarnings,
|
|
2471
|
+
planReviewWarnings,
|
|
2216
2472
|
capabilityWarnings,
|
|
2217
2473
|
investigationWarnings,
|
|
2218
2474
|
phaseCoherenceWarnings,
|
|
@@ -2220,8 +2476,9 @@ module.exports = {
|
|
|
2220
2476
|
specSectionWarnings,
|
|
2221
2477
|
planWaveWarningsFixed,
|
|
2222
2478
|
planTaskAceiteWarnings,
|
|
2223
|
-
suggestNextStep,
|
|
2224
|
-
buildHealthReport,
|
|
2225
|
-
|
|
2226
|
-
|
|
2227
|
-
|
|
2479
|
+
suggestNextStep,
|
|
2480
|
+
buildHealthReport,
|
|
2481
|
+
buildExecutionRationality: rationality.buildExecutionRationality,
|
|
2482
|
+
oxePaths,
|
|
2483
|
+
scopedOxePaths,
|
|
2484
|
+
};
|