oxe-cc 1.4.1 → 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/.cursor/commands/oxe-verify-audit.md +46 -0
- package/.cursor/commands/oxe-workflow-authoring.md +47 -0
- package/.github/prompts/oxe-compact.prompt.md +1 -1
- package/.github/prompts/oxe-dashboard.prompt.md +2 -2
- package/.github/prompts/oxe-execute.prompt.md +2 -2
- package/.github/prompts/oxe-plan-agent.prompt.md +1 -0
- package/.github/prompts/oxe-plan.prompt.md +2 -2
- package/.github/prompts/oxe-verify-audit.prompt.md +46 -0
- package/.github/prompts/oxe-workflow-authoring.prompt.md +47 -0
- package/.github/workflows/ci.yml +1 -0
- package/.github/workflows/release.yml +1 -0
- package/AGENTS.md +3 -1
- package/CHANGELOG.md +50 -0
- package/QUICKSTART.md +99 -0
- package/README.md +20 -11
- package/bin/lib/oxe-context-engine.cjs +9 -4
- package/bin/lib/oxe-dashboard.cjs +119 -53
- package/bin/lib/oxe-install-resolve.cjs +10 -0
- package/bin/lib/oxe-operational.cjs +34 -28
- package/bin/lib/oxe-project-health.cjs +407 -118
- package/bin/lib/oxe-rationality.cjs +385 -0
- package/bin/lib/oxe-release.cjs +423 -0
- package/bin/oxe-cc.js +446 -325
- package/commands/oxe/dashboard.md +2 -2
- package/commands/oxe/execute.md +2 -2
- package/commands/oxe/plan.md +2 -2
- package/commands/oxe/verify-audit.md +50 -0
- package/commands/oxe/workflow-authoring.md +50 -0
- package/docs/INCIDENT-PLAYBOOK.md +181 -0
- package/docs/RELEASE-READINESS.md +46 -0
- package/docs/ROLES.md +129 -0
- package/docs/RUNTIME-SMOKE-MATRIX.md +128 -0
- package/docs/TEAM-ADOPTION.md +153 -0
- package/docs/WALKTHROUGH.md +241 -0
- package/lib/runtime/scheduler/multi-agent-coordinator.d.ts +28 -0
- package/lib/runtime/scheduler/multi-agent-coordinator.js +152 -26
- package/lib/sdk/README.md +2 -0
- package/lib/sdk/index.cjs +32 -14
- package/lib/sdk/index.d.ts +138 -40
- 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 +2 -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 +28 -20
- package/packages/runtime/package.json +1 -1
- package/packages/runtime/src/scheduler/multi-agent-coordinator.ts +357 -193
- 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/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 = [
|
|
@@ -24,6 +25,7 @@ const ALLOWED_CONFIG_KEYS = [
|
|
|
24
25
|
'verification_depth',
|
|
25
26
|
'plan_confidence_threshold',
|
|
26
27
|
'security_in_verify',
|
|
28
|
+
'adversarial_verify',
|
|
27
29
|
'install',
|
|
28
30
|
'plugins',
|
|
29
31
|
'workstreams',
|
|
@@ -52,17 +54,77 @@ const INSTALL_PROFILES = ['recommended', 'cursor', 'copilot', 'core', 'cli', 'al
|
|
|
52
54
|
const INSTALL_REPO_LAYOUTS = ['nested', 'classic'];
|
|
53
55
|
|
|
54
56
|
/** @type {string[]} */
|
|
55
|
-
const INSTALL_OBJECT_KEYS = ['profile', 'repo_layout', 'vscode', 'include_commands_dir', 'include_agents_md'];
|
|
56
|
-
|
|
57
|
-
const EXPECTED_CODEBASE_MAPS = [
|
|
58
|
-
'OVERVIEW.md',
|
|
59
|
-
'STACK.md',
|
|
60
|
-
'STRUCTURE.md',
|
|
61
|
-
'TESTING.md',
|
|
62
|
-
'INTEGRATIONS.md',
|
|
63
|
-
'CONVENTIONS.md',
|
|
64
|
-
'CONCERNS.md',
|
|
65
|
-
];
|
|
57
|
+
const INSTALL_OBJECT_KEYS = ['profile', 'repo_layout', 'ide_scope', 'vscode', 'include_commands_dir', 'include_agents_md'];
|
|
58
|
+
|
|
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
|
+
}
|
|
66
128
|
|
|
67
129
|
/**
|
|
68
130
|
* @param {string} targetProject
|
|
@@ -142,9 +204,9 @@ function loadOxeConfigMerged(targetProject) {
|
|
|
142
204
|
discuss_before_plan: false,
|
|
143
205
|
after_verify_suggest_pr: true,
|
|
144
206
|
after_verify_draft_commit: true,
|
|
145
|
-
after_verify_suggest_uat: false,
|
|
146
|
-
verification_depth: 'standard',
|
|
147
|
-
plan_confidence_threshold:
|
|
207
|
+
after_verify_suggest_uat: false,
|
|
208
|
+
verification_depth: 'standard',
|
|
209
|
+
plan_confidence_threshold: 90,
|
|
148
210
|
default_verify_command: '',
|
|
149
211
|
scan_max_age_days: 0,
|
|
150
212
|
compact_max_age_days: 0,
|
|
@@ -152,6 +214,8 @@ function loadOxeConfigMerged(targetProject) {
|
|
|
152
214
|
scan_ignore_globs: [],
|
|
153
215
|
spec_required_sections: [],
|
|
154
216
|
plan_max_tasks_per_wave: 0,
|
|
217
|
+
lessons_max_age_days: 0,
|
|
218
|
+
install: {},
|
|
155
219
|
azure: {
|
|
156
220
|
enabled: false,
|
|
157
221
|
default_resource_group: '',
|
|
@@ -212,15 +276,18 @@ function loadOxeConfigMerged(targetProject) {
|
|
|
212
276
|
if (typeof layer.profile === 'string') {
|
|
213
277
|
Object.assign(merged, expandExecutionProfile(layer.profile));
|
|
214
278
|
}
|
|
279
|
+
const layerFlat = { ...layer };
|
|
215
280
|
// Azure: merge aninhado para não sobrescrever campos não especificados
|
|
216
281
|
if (layer.azure && typeof layer.azure === 'object' && !Array.isArray(layer.azure)) {
|
|
217
282
|
merged.azure = { .../** @type {any} */ (merged.azure), ...layer.azure };
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
283
|
+
delete layerFlat.azure;
|
|
284
|
+
}
|
|
285
|
+
// Install: merge aninhado para não sobrescrever campos não especificados
|
|
286
|
+
if (layer.install && typeof layer.install === 'object' && !Array.isArray(layer.install)) {
|
|
287
|
+
merged.install = { .../** @type {any} */ (merged.install || {}), ...layer.install };
|
|
288
|
+
delete layerFlat.install;
|
|
223
289
|
}
|
|
290
|
+
Object.assign(merged, layerFlat);
|
|
224
291
|
}
|
|
225
292
|
|
|
226
293
|
const primaryPath = sources.project || sources.user || sources.system || null;
|
|
@@ -262,6 +329,11 @@ function validateConfigShape(cfg) {
|
|
|
262
329
|
);
|
|
263
330
|
}
|
|
264
331
|
}
|
|
332
|
+
if (inst.ide_scope != null) {
|
|
333
|
+
if (typeof inst.ide_scope !== 'string' || !['global', 'local'].includes(inst.ide_scope)) {
|
|
334
|
+
typeErrors.push('install.ide_scope deve ser "global" ou "local"');
|
|
335
|
+
}
|
|
336
|
+
}
|
|
265
337
|
if (inst.vscode != null && typeof inst.vscode !== 'boolean') {
|
|
266
338
|
typeErrors.push('install.vscode deve ser boolean');
|
|
267
339
|
}
|
|
@@ -314,6 +386,27 @@ function validateConfigShape(cfg) {
|
|
|
314
386
|
if (cfg.scale_adaptive != null && typeof cfg.scale_adaptive !== 'boolean') {
|
|
315
387
|
typeErrors.push('scale_adaptive deve ser boolean');
|
|
316
388
|
}
|
|
389
|
+
if (cfg.discuss_before_plan != null && typeof cfg.discuss_before_plan !== 'boolean') {
|
|
390
|
+
typeErrors.push('discuss_before_plan deve ser boolean');
|
|
391
|
+
}
|
|
392
|
+
if (cfg.after_verify_suggest_pr != null && typeof cfg.after_verify_suggest_pr !== 'boolean') {
|
|
393
|
+
typeErrors.push('after_verify_suggest_pr deve ser boolean');
|
|
394
|
+
}
|
|
395
|
+
if (cfg.after_verify_draft_commit != null && typeof cfg.after_verify_draft_commit !== 'boolean') {
|
|
396
|
+
typeErrors.push('after_verify_draft_commit deve ser boolean');
|
|
397
|
+
}
|
|
398
|
+
if (cfg.security_in_verify != null && typeof cfg.security_in_verify !== 'boolean') {
|
|
399
|
+
typeErrors.push('security_in_verify deve ser boolean');
|
|
400
|
+
}
|
|
401
|
+
if (cfg.adversarial_verify != null && typeof cfg.adversarial_verify !== 'boolean') {
|
|
402
|
+
typeErrors.push('adversarial_verify deve ser boolean');
|
|
403
|
+
}
|
|
404
|
+
if (cfg.lessons_max_age_days != null && typeof cfg.lessons_max_age_days !== 'number') {
|
|
405
|
+
typeErrors.push('lessons_max_age_days deve ser número (use 0 para desligar)');
|
|
406
|
+
}
|
|
407
|
+
if (cfg.default_verify_command != null && typeof cfg.default_verify_command !== 'string') {
|
|
408
|
+
typeErrors.push('default_verify_command deve ser string');
|
|
409
|
+
}
|
|
317
410
|
if (cfg.azure != null) {
|
|
318
411
|
if (typeof cfg.azure !== 'object' || Array.isArray(cfg.azure)) {
|
|
319
412
|
typeErrors.push('azure deve ser um objeto');
|
|
@@ -558,10 +651,15 @@ function oxePaths(target) {
|
|
|
558
651
|
events: path.join(oxe, 'OXE-EVENTS.ndjson'),
|
|
559
652
|
copilotManifest: path.join(oxe, 'install', 'copilot-vscode.json'),
|
|
560
653
|
runtimeSemanticsManifest: path.join(oxe, 'install', 'runtime-semantics.json'),
|
|
561
|
-
spec: path.join(oxe, 'SPEC.md'),
|
|
562
|
-
plan: path.join(oxe, 'PLAN.md'),
|
|
563
|
-
|
|
564
|
-
|
|
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'),
|
|
565
663
|
discuss: path.join(oxe, 'DISCUSS.md'),
|
|
566
664
|
summary: path.join(oxe, 'SUMMARY.md'),
|
|
567
665
|
codebase: path.join(oxe, 'codebase'),
|
|
@@ -574,11 +672,11 @@ function oxePaths(target) {
|
|
|
574
672
|
* @param {string} target
|
|
575
673
|
* @param {string | null} activeSession
|
|
576
674
|
*/
|
|
577
|
-
function scopedOxePaths(target, activeSession) {
|
|
578
|
-
const base = oxePaths(target);
|
|
579
|
-
if (!activeSession) return { ...base, activeSession: null, scopedRoot: base.oxe };
|
|
580
|
-
const sessionRoot = path.join(base.oxe, ...activeSession.split('/'));
|
|
581
|
-
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 {
|
|
582
680
|
...base,
|
|
583
681
|
activeSession,
|
|
584
682
|
scopedRoot: sessionRoot,
|
|
@@ -593,15 +691,61 @@ function scopedOxePaths(target, activeSession) {
|
|
|
593
691
|
events: path.join(sessionRoot, 'execution', 'OXE-EVENTS.ndjson'),
|
|
594
692
|
investigationsIndex: path.join(sessionRoot, 'research', 'INVESTIGATIONS.md'),
|
|
595
693
|
investigationsDir: path.join(sessionRoot, 'research', 'investigations'),
|
|
596
|
-
spec: path.join(sessionRoot, 'spec', 'SPEC.md'),
|
|
597
|
-
discuss: path.join(sessionRoot, 'spec', 'DISCUSS.md'),
|
|
598
|
-
plan: path.join(sessionRoot, 'plan', 'PLAN.md'),
|
|
599
|
-
|
|
600
|
-
|
|
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'),
|
|
601
705
|
summary: path.join(sessionRoot, 'verification', 'SUMMARY.md'),
|
|
602
|
-
executionState: path.join(sessionRoot, 'execution', 'STATE.md'),
|
|
603
|
-
};
|
|
604
|
-
}
|
|
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
|
+
}
|
|
605
749
|
|
|
606
750
|
/**
|
|
607
751
|
* @param {string} target
|
|
@@ -1404,10 +1548,10 @@ function planWaveWarningsFixed(planPath, maxPerWave) {
|
|
|
1404
1548
|
* warnings: string[],
|
|
1405
1549
|
* }}
|
|
1406
1550
|
*/
|
|
1407
|
-
function parsePlanSelfEvaluation(planPath) {
|
|
1408
|
-
const empty = { hasSection: false, bestPlan: null, confidence: null, warnings: [] };
|
|
1409
|
-
if (!fs.existsSync(planPath)) return empty;
|
|
1410
|
-
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');
|
|
1411
1555
|
const m = raw.match(/##\s*Autoavaliação do Plano\s*([\s\S]*?)(?=\n## |\n#[^\#]|$)/i);
|
|
1412
1556
|
if (!m) {
|
|
1413
1557
|
return {
|
|
@@ -1415,27 +1559,60 @@ function parsePlanSelfEvaluation(planPath) {
|
|
|
1415
1559
|
warnings: ['PLAN.md sem a seção obrigatória "## Autoavaliação do Plano"'],
|
|
1416
1560
|
};
|
|
1417
1561
|
}
|
|
1418
|
-
const body = m[1];
|
|
1419
|
-
const best = body.match(/\*\*Melhor plano atual:\*\*\s*(sim|não|nao)/i);
|
|
1420
|
-
const confidence = body.match(/\*\*Confiança:\*\*\s*(\d{1,3})\s*%/i);
|
|
1421
|
-
|
|
1422
|
-
|
|
1423
|
-
const
|
|
1424
|
-
|
|
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',
|
|
1425
1570
|
'Dependências conhecidas',
|
|
1426
1571
|
'Risco técnico',
|
|
1427
1572
|
'Impacto no código existente',
|
|
1428
1573
|
'Clareza da validação / testes',
|
|
1429
1574
|
'Lacunas externas / decisões pendentes',
|
|
1430
1575
|
];
|
|
1431
|
-
if (!best) warnings.push('PLAN.md: autoavaliação sem "Melhor plano atual: sim|não"');
|
|
1432
|
-
if (!confidence) warnings.push('PLAN.md: autoavaliação sem "Confiança: NN%"');
|
|
1433
|
-
if (!/\*\*Principais incertezas:\*\*/i.test(body)) warnings.push('PLAN.md: autoavaliação sem "Principais incertezas"');
|
|
1434
|
-
if (!/\*\*Alternativas descartadas:\*\*/i.test(body)) warnings.push('PLAN.md: autoavaliação sem "Alternativas descartadas"');
|
|
1435
|
-
if (!/\*\*Condição para replanejar:\*\*/i.test(body)) warnings.push('PLAN.md: autoavaliação sem "Condição para replanejar"');
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
}
|
|
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
|
+
}
|
|
1439
1616
|
const parsedConfidence = confidence ? Number(confidence[1]) : null;
|
|
1440
1617
|
if (parsedConfidence != null && (parsedConfidence < 0 || parsedConfidence > 100)) {
|
|
1441
1618
|
warnings.push('PLAN.md: confiança fora do intervalo 0–100%');
|
|
@@ -1446,23 +1623,70 @@ function parsePlanSelfEvaluation(planPath) {
|
|
|
1446
1623
|
confidence: parsedConfidence,
|
|
1447
1624
|
warnings,
|
|
1448
1625
|
};
|
|
1449
|
-
}
|
|
1450
|
-
|
|
1451
|
-
/**
|
|
1452
|
-
* @param {
|
|
1453
|
-
*
|
|
1454
|
-
*
|
|
1455
|
-
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
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
|
+
}
|
|
1466
1690
|
|
|
1467
1691
|
/**
|
|
1468
1692
|
* @param {string} target
|
|
@@ -1616,12 +1840,12 @@ function planReviewWarnings(stateText, p) {
|
|
|
1616
1840
|
* @param {string} target
|
|
1617
1841
|
* @param {{ discuss_before_plan?: boolean }} cfg
|
|
1618
1842
|
*/
|
|
1619
|
-
function suggestNextStep(target, cfg = {}) {
|
|
1843
|
+
function suggestNextStep(target, cfg = {}) {
|
|
1620
1844
|
const base = oxePaths(target);
|
|
1621
1845
|
const stateText = fs.existsSync(base.state) ? fs.readFileSync(base.state, 'utf8') : '';
|
|
1622
|
-
const p =
|
|
1846
|
+
const p = resolvedReadableOxePaths(target, parseActiveSession(stateText));
|
|
1623
1847
|
const discussBefore = Boolean(cfg.discuss_before_plan);
|
|
1624
|
-
const threshold =
|
|
1848
|
+
const threshold = normalizePlanConfidenceThreshold(cfg.plan_confidence_threshold);
|
|
1625
1849
|
const has = (/** @type {string} */ f) => fs.existsSync(f);
|
|
1626
1850
|
const mapsComplete = EXPECTED_CODEBASE_MAPS.every((f) => has(path.join(p.codebase, f)));
|
|
1627
1851
|
const azureActive = azure.isAzureContextEnabled(target, cfg);
|
|
@@ -1720,17 +1944,49 @@ function suggestNextStep(target, cfg = {}) {
|
|
|
1720
1944
|
};
|
|
1721
1945
|
}
|
|
1722
1946
|
|
|
1723
|
-
const selfEval = parsePlanSelfEvaluation(p.plan);
|
|
1724
|
-
|
|
1725
|
-
|
|
1726
|
-
|
|
1727
|
-
|
|
1728
|
-
|
|
1729
|
-
|
|
1730
|
-
|
|
1731
|
-
|
|
1732
|
-
|
|
1733
|
-
|
|
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);
|
|
1734
1990
|
if (phase === 'plan_ready' && (reviewStatus === 'needs_revision' || reviewStatus === 'rejected')) {
|
|
1735
1991
|
return {
|
|
1736
1992
|
step: 'plan',
|
|
@@ -1861,7 +2117,7 @@ function buildHealthReport(target) {
|
|
|
1861
2117
|
}
|
|
1862
2118
|
}
|
|
1863
2119
|
const activeSession = parseActiveSession(stateText);
|
|
1864
|
-
const p =
|
|
2120
|
+
const p = resolvedReadableOxePaths(target, activeSession);
|
|
1865
2121
|
const phase = parseStatePhase(stateText);
|
|
1866
2122
|
const scanDate = parseLastScanDate(stateText);
|
|
1867
2123
|
const stale = isStaleScan(scanDate, Number(config.scan_max_age_days) || 0);
|
|
@@ -1872,23 +2128,43 @@ function buildHealthReport(target) {
|
|
|
1872
2128
|
const phaseWarn = phase ? phaseCoherenceWarnings(phase, p) : [];
|
|
1873
2129
|
const runtimeWarn = runtimeWarnings(stateText, p);
|
|
1874
2130
|
const sumWarn = verifyGapsWithoutSummaryWarning(p.verify, p.summary);
|
|
1875
|
-
const specReq = Array.isArray(config.spec_required_sections) ? config.spec_required_sections : [];
|
|
1876
|
-
const specWarn = specSectionWarnings(p.spec, specReq.map(String));
|
|
1877
|
-
const threshold =
|
|
1878
|
-
const capabilityWarn = capabilityWarnings(p);
|
|
1879
|
-
const investigationWarn = investigationWarnings(p);
|
|
1880
|
-
const
|
|
1881
|
-
|
|
1882
|
-
|
|
1883
|
-
|
|
1884
|
-
|
|
1885
|
-
|
|
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
|
+
];
|
|
1886
2153
|
const sessionWarn = sessionWarnings(target, activeSession);
|
|
1887
2154
|
const installWarn = installationCompletenessWarnings(target);
|
|
1888
2155
|
const copilot = copilotIntegrationReport(target);
|
|
1889
2156
|
const copilotWarn = copilot.warnings;
|
|
1890
2157
|
const reviewWarn = planReviewWarnings(stateText, p);
|
|
1891
|
-
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
|
+
};
|
|
1892
2168
|
const activeRun = operational.readRunState(target, activeSession);
|
|
1893
2169
|
const eventsSummary = operational.summarizeEvents(operational.readEvents(target, activeSession));
|
|
1894
2170
|
const memoryLayers = operational.buildMemoryLayers(target, activeSession);
|
|
@@ -2103,9 +2379,17 @@ function buildHealthReport(target) {
|
|
|
2103
2379
|
copilot,
|
|
2104
2380
|
summaryGapWarn: sumWarn,
|
|
2105
2381
|
specWarn,
|
|
2106
|
-
planWarn,
|
|
2107
|
-
planSelfEvaluation,
|
|
2108
|
-
|
|
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),
|
|
2109
2393
|
activeRun,
|
|
2110
2394
|
eventsSummary,
|
|
2111
2395
|
memoryLayers,
|
|
@@ -2174,13 +2458,17 @@ module.exports = {
|
|
|
2174
2458
|
isStaleLessons,
|
|
2175
2459
|
copilotWorkspacePaths,
|
|
2176
2460
|
copilotLegacyPaths,
|
|
2177
|
-
copilotIntegrationReport,
|
|
2178
|
-
|
|
2461
|
+
copilotIntegrationReport,
|
|
2462
|
+
normalizePlanConfidenceThreshold,
|
|
2463
|
+
isExecutablePlanConfidence,
|
|
2464
|
+
hasExecutablePlanSelfEvaluation,
|
|
2465
|
+
planAgentsWarnings,
|
|
2179
2466
|
installationCompletenessWarnings,
|
|
2180
|
-
parsePlanSelfEvaluation,
|
|
2181
|
-
planSelfEvaluationWarnings,
|
|
2182
|
-
|
|
2183
|
-
|
|
2467
|
+
parsePlanSelfEvaluation,
|
|
2468
|
+
planSelfEvaluationWarnings,
|
|
2469
|
+
executionRationalityWarningsFromSummary,
|
|
2470
|
+
runtimeWarnings,
|
|
2471
|
+
planReviewWarnings,
|
|
2184
2472
|
capabilityWarnings,
|
|
2185
2473
|
investigationWarnings,
|
|
2186
2474
|
phaseCoherenceWarnings,
|
|
@@ -2188,8 +2476,9 @@ module.exports = {
|
|
|
2188
2476
|
specSectionWarnings,
|
|
2189
2477
|
planWaveWarningsFixed,
|
|
2190
2478
|
planTaskAceiteWarnings,
|
|
2191
|
-
suggestNextStep,
|
|
2192
|
-
buildHealthReport,
|
|
2193
|
-
|
|
2194
|
-
|
|
2195
|
-
|
|
2479
|
+
suggestNextStep,
|
|
2480
|
+
buildHealthReport,
|
|
2481
|
+
buildExecutionRationality: rationality.buildExecutionRationality,
|
|
2482
|
+
oxePaths,
|
|
2483
|
+
scopedOxePaths,
|
|
2484
|
+
};
|