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
|
@@ -0,0 +1,385 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const fs = require('fs');
|
|
4
|
+
|
|
5
|
+
function readTextIfExists(filePath) {
|
|
6
|
+
try {
|
|
7
|
+
return filePath && fs.existsSync(filePath) ? fs.readFileSync(filePath, 'utf8') : null;
|
|
8
|
+
} catch {
|
|
9
|
+
return null;
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
function readJsonIfExists(filePath) {
|
|
14
|
+
const text = readTextIfExists(filePath);
|
|
15
|
+
if (!text) return { ok: false, data: null, error: null };
|
|
16
|
+
try {
|
|
17
|
+
return { ok: true, data: JSON.parse(text), error: null };
|
|
18
|
+
} catch (error) {
|
|
19
|
+
return {
|
|
20
|
+
ok: false,
|
|
21
|
+
data: null,
|
|
22
|
+
error: error instanceof Error ? error.message : String(error),
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function parseAttrs(fragment) {
|
|
28
|
+
/** @type {Record<string, string>} */
|
|
29
|
+
const attrs = {};
|
|
30
|
+
const raw = String(fragment || '');
|
|
31
|
+
for (const match of raw.matchAll(/([A-Za-z0-9_:-]+)="([^"]*)"/g)) {
|
|
32
|
+
attrs[match[1]] = match[2];
|
|
33
|
+
}
|
|
34
|
+
return attrs;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function normalizeTaskMode(value) {
|
|
38
|
+
const mode = String(value || '').trim().toLowerCase();
|
|
39
|
+
if (!mode) return 'mutating';
|
|
40
|
+
return mode;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function isMutatingMode(mode) {
|
|
44
|
+
return !new Set(['docs_only', 'not_applicable', 'external', 'docs-only']).has(normalizeTaskMode(mode));
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function isTaskRiskKeyword(task) {
|
|
48
|
+
const text = `${task.title || ''} ${task.body || ''}`.toLowerCase();
|
|
49
|
+
return /(parser|parse|layout|integra|integration|contrato|contract|migra|migration|fila|queue|service bus|event grid|builder|payload|transform|cnab|listener|schema|ddl)/.test(text);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* @param {string | null} planPath
|
|
54
|
+
* @returns {Array<{
|
|
55
|
+
* id: string,
|
|
56
|
+
* title: string,
|
|
57
|
+
* files: string[],
|
|
58
|
+
* complexity: string | null,
|
|
59
|
+
* body: string,
|
|
60
|
+
* }>}
|
|
61
|
+
*/
|
|
62
|
+
function parsePlanTasks(planPath) {
|
|
63
|
+
const raw = readTextIfExists(planPath);
|
|
64
|
+
if (!raw) return [];
|
|
65
|
+
const parts = raw.split(/^###\s+(T\d+)\s*[—-]?\s*/m);
|
|
66
|
+
if (parts.length < 3) return [];
|
|
67
|
+
/** @type {ReturnType<typeof parsePlanTasks>} */
|
|
68
|
+
const tasks = [];
|
|
69
|
+
for (let i = 1; i < parts.length; i += 2) {
|
|
70
|
+
const id = String(parts[i] || '').trim();
|
|
71
|
+
const rest = String(parts[i + 1] || '').split(/^###\s+T\d+/m)[0];
|
|
72
|
+
const title = (((rest.match(/^([^\n]+)/) || [null, ''])[1]) || '').trim();
|
|
73
|
+
const filesLine = (((rest.match(/\*\*Arquivos\s+prov[aá]veis:\*\*\s*([^\n]+)/i) || [null, ''])[1]) || '').trim();
|
|
74
|
+
const backtickPaths = Array.from(filesLine.matchAll(/`([^`]+)`/g)).map((match) => match[1].trim()).filter(Boolean);
|
|
75
|
+
const files = backtickPaths.length
|
|
76
|
+
? backtickPaths
|
|
77
|
+
: filesLine.split(',').map((entry) => entry.trim()).filter(Boolean);
|
|
78
|
+
const complexity = (((rest.match(/\*\*Complexidade:\*\*\s*([A-Z]+)/i) || [null, ''])[1]) || '').trim() || null;
|
|
79
|
+
tasks.push({ id, title, files, complexity, body: rest });
|
|
80
|
+
}
|
|
81
|
+
return tasks;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* @param {string | null} planAgentsPath
|
|
86
|
+
* @returns {string[]}
|
|
87
|
+
*/
|
|
88
|
+
function readExternalRefs(planAgentsPath) {
|
|
89
|
+
const parsed = readJsonIfExists(planAgentsPath);
|
|
90
|
+
if (!parsed.ok || !parsed.data || typeof parsed.data !== 'object') return [];
|
|
91
|
+
const agents = Array.isArray(parsed.data.agents) ? parsed.data.agents : [];
|
|
92
|
+
return agents
|
|
93
|
+
.flatMap((agent) => Array.isArray(agent && agent.inputs) ? agent.inputs : [])
|
|
94
|
+
.map((input) => String(input || '').trim())
|
|
95
|
+
.filter((input) => /^external-ref:/i.test(input));
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
function summarizeImplementationPack(filePath, planTasks) {
|
|
99
|
+
const parsed = readJsonIfExists(filePath);
|
|
100
|
+
/** @type {string[]} */
|
|
101
|
+
const criticalGaps = [];
|
|
102
|
+
if (!parsed.ok) {
|
|
103
|
+
return {
|
|
104
|
+
path: filePath,
|
|
105
|
+
exists: Boolean(readTextIfExists(filePath)),
|
|
106
|
+
parseError: parsed.error,
|
|
107
|
+
ready: false,
|
|
108
|
+
tasks: [],
|
|
109
|
+
taskCount: 0,
|
|
110
|
+
mutatingTasks: 0,
|
|
111
|
+
criticalGaps: [`IMPLEMENTATION-PACK.json inválido ou ausente${parsed.error ? `: ${parsed.error}` : ''}`],
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
const data = parsed.data && typeof parsed.data === 'object' ? parsed.data : {};
|
|
115
|
+
const tasks = Array.isArray(data.tasks) ? data.tasks : [];
|
|
116
|
+
const byId = new Map(tasks.map((task) => [String(task && task.id || task && task.task_id || '').trim(), task]).filter((entry) => entry[0]));
|
|
117
|
+
const allowedModes = new Set(['mutating', 'docs_only', 'not_applicable', 'external', 'docs-only']);
|
|
118
|
+
for (const planTask of planTasks) {
|
|
119
|
+
if (!byId.has(planTask.id)) {
|
|
120
|
+
criticalGaps.push(`IMPLEMENTATION-PACK.json sem contrato para ${planTask.id}`);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
let mutatingTasks = 0;
|
|
124
|
+
for (const task of tasks) {
|
|
125
|
+
const id = String(task && task.id || task && task.task_id || '').trim();
|
|
126
|
+
const mode = normalizeTaskMode(task && task.mode);
|
|
127
|
+
const exactPaths = Array.isArray(task && task.exact_paths) ? task.exact_paths.map((entry) => String(entry || '').trim()).filter(Boolean) : [];
|
|
128
|
+
const symbols = Array.isArray(task && task.symbols) ? task.symbols : [];
|
|
129
|
+
const contracts = Array.isArray(task && task.contracts) ? task.contracts : [];
|
|
130
|
+
const expectedChecks = Array.isArray(task && task.expected_checks) ? task.expected_checks : [];
|
|
131
|
+
const gaps = Array.isArray(task && task.critical_gaps) ? task.critical_gaps : [];
|
|
132
|
+
if (!id) {
|
|
133
|
+
criticalGaps.push('IMPLEMENTATION-PACK.json com task sem id');
|
|
134
|
+
continue;
|
|
135
|
+
}
|
|
136
|
+
if (!allowedModes.has(mode)) {
|
|
137
|
+
criticalGaps.push(`IMPLEMENTATION-PACK.json tarefa ${id} com mode inválido: ${mode}`);
|
|
138
|
+
}
|
|
139
|
+
if (task && task.ready === false) {
|
|
140
|
+
criticalGaps.push(`IMPLEMENTATION-PACK.json tarefa ${id} marcada como not ready`);
|
|
141
|
+
}
|
|
142
|
+
if (gaps.length) {
|
|
143
|
+
criticalGaps.push(`IMPLEMENTATION-PACK.json tarefa ${id} com critical_gaps abertos`);
|
|
144
|
+
}
|
|
145
|
+
if (isMutatingMode(mode)) {
|
|
146
|
+
mutatingTasks += 1;
|
|
147
|
+
if (!exactPaths.length) {
|
|
148
|
+
criticalGaps.push(`IMPLEMENTATION-PACK.json tarefa ${id} sem exact_paths`);
|
|
149
|
+
}
|
|
150
|
+
if (exactPaths.some((entry) => entry.includes('...'))) {
|
|
151
|
+
criticalGaps.push(`IMPLEMENTATION-PACK.json tarefa ${id} com exact_paths ambíguos (...)`);
|
|
152
|
+
}
|
|
153
|
+
if (String(task && task.write_set || '').trim().toLowerCase() !== 'closed') {
|
|
154
|
+
criticalGaps.push(`IMPLEMENTATION-PACK.json tarefa ${id} com write_set aberto`);
|
|
155
|
+
}
|
|
156
|
+
if (!symbols.length) {
|
|
157
|
+
criticalGaps.push(`IMPLEMENTATION-PACK.json tarefa ${id} sem symbols`);
|
|
158
|
+
}
|
|
159
|
+
if (!contracts.length) {
|
|
160
|
+
criticalGaps.push(`IMPLEMENTATION-PACK.json tarefa ${id} sem contracts`);
|
|
161
|
+
}
|
|
162
|
+
if (!expectedChecks.length) {
|
|
163
|
+
criticalGaps.push(`IMPLEMENTATION-PACK.json tarefa ${id} sem expected_checks`);
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
if (data.ready === false) {
|
|
168
|
+
criticalGaps.push('IMPLEMENTATION-PACK.json com ready=false');
|
|
169
|
+
}
|
|
170
|
+
if (Array.isArray(data.critical_gaps) && data.critical_gaps.length) {
|
|
171
|
+
criticalGaps.push(...data.critical_gaps.map((gap) => `IMPLEMENTATION-PACK.json: ${String(gap)}`));
|
|
172
|
+
}
|
|
173
|
+
return {
|
|
174
|
+
path: filePath,
|
|
175
|
+
exists: true,
|
|
176
|
+
parseError: null,
|
|
177
|
+
ready: Boolean(data.ready) && criticalGaps.length === 0,
|
|
178
|
+
tasks,
|
|
179
|
+
taskCount: tasks.length,
|
|
180
|
+
mutatingTasks,
|
|
181
|
+
criticalGaps: Array.from(new Set(criticalGaps)),
|
|
182
|
+
};
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
function summarizeReferenceAnchors(filePath, externalRefs) {
|
|
186
|
+
const raw = readTextIfExists(filePath);
|
|
187
|
+
/** @type {string[]} */
|
|
188
|
+
const criticalGaps = [];
|
|
189
|
+
if (!raw) {
|
|
190
|
+
return {
|
|
191
|
+
path: filePath,
|
|
192
|
+
exists: false,
|
|
193
|
+
ready: false,
|
|
194
|
+
anchors: [],
|
|
195
|
+
missingCriticalCount: externalRefs.length,
|
|
196
|
+
staleCount: 0,
|
|
197
|
+
criticalGaps: ['REFERENCE-ANCHORS.md ausente'],
|
|
198
|
+
};
|
|
199
|
+
}
|
|
200
|
+
const rootMatch = raw.match(/<reference_anchors\b([^>]*)>([\s\S]*?)<\/reference_anchors>/i);
|
|
201
|
+
if (!rootMatch) {
|
|
202
|
+
return {
|
|
203
|
+
path: filePath,
|
|
204
|
+
exists: true,
|
|
205
|
+
ready: false,
|
|
206
|
+
anchors: [],
|
|
207
|
+
missingCriticalCount: externalRefs.length,
|
|
208
|
+
staleCount: 0,
|
|
209
|
+
criticalGaps: ['REFERENCE-ANCHORS.md sem bloco <reference_anchors>'],
|
|
210
|
+
};
|
|
211
|
+
}
|
|
212
|
+
const rootAttrs = parseAttrs(rootMatch[1]);
|
|
213
|
+
const status = String(rootAttrs.status || '').toLowerCase();
|
|
214
|
+
/** @type {Array<Record<string, unknown>>} */
|
|
215
|
+
const anchors = [];
|
|
216
|
+
for (const match of rootMatch[2].matchAll(/<anchor\b([^>]*)>([\s\S]*?)<\/anchor>/gi)) {
|
|
217
|
+
const attrs = parseAttrs(match[1]);
|
|
218
|
+
anchors.push({
|
|
219
|
+
id: attrs.id || null,
|
|
220
|
+
task: attrs.task || null,
|
|
221
|
+
critical: String(attrs.critical || '').toLowerCase() === 'true',
|
|
222
|
+
status: String(attrs.status || 'missing').toLowerCase(),
|
|
223
|
+
sourceType: attrs.source_type || null,
|
|
224
|
+
path: attrs.path || null,
|
|
225
|
+
sourceRef: attrs.source_ref || null,
|
|
226
|
+
relevance: (((match[2].match(/<relevance>([\s\S]*?)<\/relevance>/i) || [null, ''])[1]) || '').trim(),
|
|
227
|
+
action: (((match[2].match(/<action>([\s\S]*?)<\/action>/i) || [null, ''])[1]) || '').trim(),
|
|
228
|
+
summary: (((match[2].match(/<summary>([\s\S]*?)<\/summary>/i) || [null, ''])[1]) || '').trim(),
|
|
229
|
+
});
|
|
230
|
+
}
|
|
231
|
+
if (status === 'not_applicable' && externalRefs.length) {
|
|
232
|
+
criticalGaps.push('REFERENCE-ANCHORS.md marcado como not_applicable, mas há external-ref no blueprint');
|
|
233
|
+
}
|
|
234
|
+
let missingCriticalCount = 0;
|
|
235
|
+
let staleCount = 0;
|
|
236
|
+
for (const anchor of anchors) {
|
|
237
|
+
const anchorStatus = String(anchor.status || 'missing').toLowerCase();
|
|
238
|
+
if (anchorStatus === 'stale') staleCount += 1;
|
|
239
|
+
if (anchor.critical && anchorStatus !== 'resolved') {
|
|
240
|
+
missingCriticalCount += 1;
|
|
241
|
+
criticalGaps.push(`REFERENCE-ANCHORS.md âncora crítica ${anchor.id || anchor.sourceRef || '?'} em estado ${anchorStatus}`);
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
for (const ref of externalRefs) {
|
|
245
|
+
const matched = anchors.find((anchor) => String(anchor.sourceRef || '').trim() === ref);
|
|
246
|
+
if (!matched) {
|
|
247
|
+
missingCriticalCount += 1;
|
|
248
|
+
criticalGaps.push(`REFERENCE-ANCHORS.md sem âncora materializada para ${ref}`);
|
|
249
|
+
} else if (String(matched.status || '').toLowerCase() !== 'resolved') {
|
|
250
|
+
missingCriticalCount += 1;
|
|
251
|
+
criticalGaps.push(`REFERENCE-ANCHORS.md com ${ref} em estado ${matched.status}`);
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
if (String(rootAttrs.ready || '').toLowerCase() === 'false') {
|
|
255
|
+
criticalGaps.push('REFERENCE-ANCHORS.md com ready=false');
|
|
256
|
+
}
|
|
257
|
+
return {
|
|
258
|
+
path: filePath,
|
|
259
|
+
exists: true,
|
|
260
|
+
ready: status === 'not_applicable'
|
|
261
|
+
? criticalGaps.length === 0
|
|
262
|
+
: Boolean(String(rootAttrs.ready || '').toLowerCase() !== 'false') && criticalGaps.length === 0,
|
|
263
|
+
anchors,
|
|
264
|
+
missingCriticalCount,
|
|
265
|
+
staleCount,
|
|
266
|
+
criticalGaps: Array.from(new Set(criticalGaps)),
|
|
267
|
+
};
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
function summarizeFixturePack(filePath, planTasks, implementationPack) {
|
|
271
|
+
const parsed = readJsonIfExists(filePath);
|
|
272
|
+
/** @type {string[]} */
|
|
273
|
+
const criticalGaps = [];
|
|
274
|
+
if (!parsed.ok) {
|
|
275
|
+
return {
|
|
276
|
+
path: filePath,
|
|
277
|
+
exists: Boolean(readTextIfExists(filePath)),
|
|
278
|
+
parseError: parsed.error,
|
|
279
|
+
ready: false,
|
|
280
|
+
fixtures: [],
|
|
281
|
+
fixtureCount: 0,
|
|
282
|
+
criticalGaps: [`FIXTURE-PACK.json inválido ou ausente${parsed.error ? `: ${parsed.error}` : ''}`],
|
|
283
|
+
};
|
|
284
|
+
}
|
|
285
|
+
const data = parsed.data && typeof parsed.data === 'object' ? parsed.data : {};
|
|
286
|
+
const fixtures = Array.isArray(data.fixtures) ? data.fixtures : [];
|
|
287
|
+
const byTask = new Map();
|
|
288
|
+
for (const fixture of fixtures) {
|
|
289
|
+
const taskId = String(fixture && fixture.task_id || fixture && fixture.taskId || '').trim();
|
|
290
|
+
if (!taskId) continue;
|
|
291
|
+
if (!byTask.has(taskId)) byTask.set(taskId, []);
|
|
292
|
+
byTask.get(taskId).push(fixture);
|
|
293
|
+
}
|
|
294
|
+
if (data.ready === false) {
|
|
295
|
+
criticalGaps.push('FIXTURE-PACK.json com ready=false');
|
|
296
|
+
}
|
|
297
|
+
if (Array.isArray(data.critical_gaps) && data.critical_gaps.length) {
|
|
298
|
+
criticalGaps.push(...data.critical_gaps.map((gap) => `FIXTURE-PACK.json: ${String(gap)}`));
|
|
299
|
+
}
|
|
300
|
+
const implementationTasks = Array.isArray(implementationPack.tasks) ? implementationPack.tasks : [];
|
|
301
|
+
for (const task of implementationTasks) {
|
|
302
|
+
const taskId = String(task && task.id || task && task.task_id || '').trim();
|
|
303
|
+
if (!taskId) continue;
|
|
304
|
+
const planTask = planTasks.find((candidate) => candidate.id === taskId);
|
|
305
|
+
const requiresFixture = task && task.requires_fixture === true
|
|
306
|
+
|| (planTask ? isTaskRiskKeyword(planTask) : false);
|
|
307
|
+
if (!requiresFixture) continue;
|
|
308
|
+
const entries = byTask.get(taskId) || [];
|
|
309
|
+
if (!entries.length) {
|
|
310
|
+
criticalGaps.push(`FIXTURE-PACK.json sem fixture para ${taskId}`);
|
|
311
|
+
continue;
|
|
312
|
+
}
|
|
313
|
+
const readyFixture = entries.find((entry) => String(entry && entry.status || '').toLowerCase() === 'ready');
|
|
314
|
+
if (!readyFixture) {
|
|
315
|
+
criticalGaps.push(`FIXTURE-PACK.json sem fixture ready para ${taskId}`);
|
|
316
|
+
continue;
|
|
317
|
+
}
|
|
318
|
+
if (!Array.isArray(readyFixture.expected_checks) || readyFixture.expected_checks.length === 0) {
|
|
319
|
+
criticalGaps.push(`FIXTURE-PACK.json fixture de ${taskId} sem expected_checks`);
|
|
320
|
+
}
|
|
321
|
+
if (Array.isArray(readyFixture.critical_gaps) && readyFixture.critical_gaps.length) {
|
|
322
|
+
criticalGaps.push(`FIXTURE-PACK.json fixture de ${taskId} com critical_gaps abertos`);
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
return {
|
|
326
|
+
path: filePath,
|
|
327
|
+
exists: true,
|
|
328
|
+
parseError: null,
|
|
329
|
+
ready: Boolean(data.ready) && criticalGaps.length === 0,
|
|
330
|
+
fixtures,
|
|
331
|
+
fixtureCount: fixtures.length,
|
|
332
|
+
criticalGaps: Array.from(new Set(criticalGaps)),
|
|
333
|
+
};
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
/**
|
|
337
|
+
* @param {{
|
|
338
|
+
* plan?: string | null,
|
|
339
|
+
* planAgents?: string | null,
|
|
340
|
+
* implementationPackJson?: string | null,
|
|
341
|
+
* implementationPackMd?: string | null,
|
|
342
|
+
* referenceAnchors?: string | null,
|
|
343
|
+
* fixturePackJson?: string | null,
|
|
344
|
+
* fixturePackMd?: string | null,
|
|
345
|
+
* }} paths
|
|
346
|
+
*/
|
|
347
|
+
function buildExecutionRationality(paths = {}) {
|
|
348
|
+
const planTasks = parsePlanTasks(paths.plan || null);
|
|
349
|
+
const externalRefs = readExternalRefs(paths.planAgents || null);
|
|
350
|
+
const implementationPack = summarizeImplementationPack(paths.implementationPackJson || null, planTasks);
|
|
351
|
+
const referenceAnchors = summarizeReferenceAnchors(paths.referenceAnchors || null, externalRefs);
|
|
352
|
+
const fixturePack = summarizeFixturePack(paths.fixturePackJson || null, planTasks, implementationPack);
|
|
353
|
+
const criticalExecutionGaps = Array.from(
|
|
354
|
+
new Set([
|
|
355
|
+
...implementationPack.criticalGaps,
|
|
356
|
+
...referenceAnchors.criticalGaps,
|
|
357
|
+
...fixturePack.criticalGaps,
|
|
358
|
+
])
|
|
359
|
+
);
|
|
360
|
+
const applicable = Boolean(paths.plan && fs.existsSync(paths.plan));
|
|
361
|
+
return {
|
|
362
|
+
applicable,
|
|
363
|
+
planTaskCount: planTasks.length,
|
|
364
|
+
externalReferenceCount: externalRefs.length,
|
|
365
|
+
implementationPackReady: applicable ? implementationPack.ready : false,
|
|
366
|
+
referenceAnchorsReady: applicable ? referenceAnchors.ready : false,
|
|
367
|
+
fixturePackReady: applicable ? fixturePack.ready : false,
|
|
368
|
+
executionRationalityReady: applicable
|
|
369
|
+
? implementationPack.ready && referenceAnchors.ready && fixturePack.ready && criticalExecutionGaps.length === 0
|
|
370
|
+
: false,
|
|
371
|
+
criticalExecutionGaps,
|
|
372
|
+
implementationPack,
|
|
373
|
+
referenceAnchors,
|
|
374
|
+
fixturePack,
|
|
375
|
+
};
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
module.exports = {
|
|
379
|
+
buildExecutionRationality,
|
|
380
|
+
parsePlanTasks,
|
|
381
|
+
readExternalRefs,
|
|
382
|
+
summarizeImplementationPack,
|
|
383
|
+
summarizeReferenceAnchors,
|
|
384
|
+
summarizeFixturePack,
|
|
385
|
+
};
|
package/bin/oxe-cc.js
CHANGED
|
@@ -1527,15 +1527,20 @@ function printOxeHealthDiagnostics(target, c, diagOpts = {}) {
|
|
|
1527
1527
|
if (r.eventsSummary) {
|
|
1528
1528
|
console.log(` ${c ? dim : ''}Tracing:${c ? reset : ''} ${r.eventsSummary.total} evento(s)`);
|
|
1529
1529
|
}
|
|
1530
|
-
if (r.planSelfEvaluation && r.planSelfEvaluation.hasSection) {
|
|
1531
|
-
const best = r.planSelfEvaluation.bestPlan || '—';
|
|
1532
|
-
const conf =
|
|
1533
|
-
typeof r.planSelfEvaluation.confidence === 'number' ? `${r.planSelfEvaluation.confidence}%` : '—';
|
|
1534
|
-
console.log(` ${c ? dim : ''}Plano (autoavaliação):${c ? reset : ''} melhor=${best} | confiança=${conf}`);
|
|
1535
|
-
}
|
|
1536
|
-
if (r.
|
|
1537
|
-
console.log(
|
|
1538
|
-
` ${c ? dim : ''}
|
|
1530
|
+
if (r.planSelfEvaluation && r.planSelfEvaluation.hasSection) {
|
|
1531
|
+
const best = r.planSelfEvaluation.bestPlan || '—';
|
|
1532
|
+
const conf =
|
|
1533
|
+
typeof r.planSelfEvaluation.confidence === 'number' ? `${r.planSelfEvaluation.confidence}%` : '—';
|
|
1534
|
+
console.log(` ${c ? dim : ''}Plano (autoavaliação):${c ? reset : ''} melhor=${best} | confiança=${conf}`);
|
|
1535
|
+
}
|
|
1536
|
+
if (typeof r.executionRationalityReady === 'boolean') {
|
|
1537
|
+
console.log(
|
|
1538
|
+
` ${c ? dim : ''}Prontidão racional:${c ? reset : ''} implementation=${r.implementationPackReady ? 'ok' : 'pendente'} | anchors=${r.referenceAnchorsReady ? 'ok' : 'pendente'} | fixtures=${r.fixturePackReady ? 'ok' : 'pendente'}`
|
|
1539
|
+
);
|
|
1540
|
+
}
|
|
1541
|
+
if (r.contextQuality) {
|
|
1542
|
+
console.log(
|
|
1543
|
+
` ${c ? dim : ''}Contexto:${c ? reset : ''} score=${r.contextQuality.primaryScore != null ? r.contextQuality.primaryScore : '—'} | workflow=${r.contextQuality.primaryWorkflow || '—'} | status=${r.contextQuality.primaryStatus || '—'}`
|
|
1539
1544
|
);
|
|
1540
1545
|
}
|
|
1541
1546
|
if (r.semanticsDrift) {
|
|
@@ -1696,17 +1701,24 @@ function runStatusFull(target) {
|
|
|
1696
1701
|
console.log(` ${coverageCell(codebaseExists, 'codebase scan')} ${coverageCell(specExists, 'SPEC.md')} ${coverageCell(planExists, 'PLAN.md')} ${coverageCell(verifyExists, 'VERIFY.md')} ${coverageCell(lessonsExists, 'LESSONS.md')}`);
|
|
1697
1702
|
|
|
1698
1703
|
// Readiness gate
|
|
1699
|
-
const ready = specExists
|
|
1704
|
+
const ready = specExists
|
|
1705
|
+
&& planExists
|
|
1706
|
+
&& report.executionRationalityReady
|
|
1707
|
+
&& !report.planWarn.length
|
|
1708
|
+
&& !report.runtimeWarn.length;
|
|
1700
1709
|
const gateColor = ready ? green : yellow;
|
|
1701
1710
|
console.log(`\n ${c ? yellow : ''}Readiness gate${c ? reset : ''}`);
|
|
1702
1711
|
console.log(` ${c ? gateColor : ''}${ready ? '✓ Pronto para executar' : '✗ Não pronto para executar'}${c ? reset : ''}`);
|
|
1703
1712
|
if (!specExists) console.log(` ${c ? dim : ''} • SPEC.md ausente — rode /oxe-spec${c ? reset : ''}`);
|
|
1704
1713
|
if (!planExists) console.log(` ${c ? dim : ''} • PLAN.md ausente — rode /oxe-plan${c ? reset : ''}`);
|
|
1705
|
-
if (report.planWarn.length) {
|
|
1706
|
-
for (const w of report.planWarn) {
|
|
1707
|
-
console.log(` ${c ? yellow : ''} • ${w}${c ? reset : ''}`);
|
|
1708
|
-
}
|
|
1709
|
-
}
|
|
1714
|
+
if (report.planWarn.length) {
|
|
1715
|
+
for (const w of report.planWarn) {
|
|
1716
|
+
console.log(` ${c ? yellow : ''} • ${w}${c ? reset : ''}`);
|
|
1717
|
+
}
|
|
1718
|
+
}
|
|
1719
|
+
if (planExists) {
|
|
1720
|
+
console.log(` ${c ? dim : ''} • Artefatos racionais:${c ? reset : ''} implementation=${report.implementationPackReady ? 'ok' : 'pendente'} · anchors=${report.referenceAnchorsReady ? 'ok' : 'pendente'} · fixtures=${report.fixturePackReady ? 'ok' : 'pendente'}`);
|
|
1721
|
+
}
|
|
1710
1722
|
|
|
1711
1723
|
// Active run summary
|
|
1712
1724
|
if (report.activeRun) {
|
|
@@ -1792,18 +1804,24 @@ function runStatusFull(target) {
|
|
|
1792
1804
|
}
|
|
1793
1805
|
|
|
1794
1806
|
// Plan self-evaluation
|
|
1795
|
-
if (report.planSelfEvaluation) {
|
|
1796
|
-
const pse = report.planSelfEvaluation;
|
|
1797
|
-
|
|
1798
|
-
|
|
1799
|
-
|
|
1800
|
-
|
|
1801
|
-
|
|
1802
|
-
|
|
1803
|
-
|
|
1804
|
-
|
|
1805
|
-
|
|
1806
|
-
|
|
1807
|
+
if (report.planSelfEvaluation) {
|
|
1808
|
+
const pse = report.planSelfEvaluation;
|
|
1809
|
+
const threshold = report.planConfidenceThreshold || 90;
|
|
1810
|
+
console.log(`\n ${c ? yellow : ''}Autoavaliação do plano${c ? reset : ''}`);
|
|
1811
|
+
if (pse.best_plan_current != null) {
|
|
1812
|
+
const bestColor = pse.best_plan_current ? green : red;
|
|
1813
|
+
console.log(` ${c ? dim : ''}Melhor plano atual:${c ? reset : ''} ${c ? bestColor : ''}${pse.best_plan_current ? 'sim' : 'não'}${c ? reset : ''}`);
|
|
1814
|
+
}
|
|
1815
|
+
if (pse.confidence != null) {
|
|
1816
|
+
const confColor = report.planConfidenceExecutable
|
|
1817
|
+
? green
|
|
1818
|
+
: Number(pse.confidence) >= Math.max(80, threshold - 10)
|
|
1819
|
+
? yellow
|
|
1820
|
+
: red;
|
|
1821
|
+
console.log(` ${c ? dim : ''}Confiança:${c ? reset : ''} ${c ? confColor : ''}${pse.confidence}%${c ? reset : ''}`);
|
|
1822
|
+
console.log(` ${c ? dim : ''}Gate executável:${c ? reset : ''} > ${threshold}%${pse.executable ? ' (atingido)' : ' (ainda não atingido)'}`);
|
|
1823
|
+
}
|
|
1824
|
+
}
|
|
1807
1825
|
|
|
1808
1826
|
console.log(`\n ${c ? dim : ''}Próximo passo:${c ? reset : ''} ${c ? cyan : ''}${report.next && report.next.cursorCmd ? report.next.cursorCmd : '—'}${c ? reset : ''}`);
|
|
1809
1827
|
console.log(` ${c ? dim : ''}Motivo:${c ? reset : ''} ${report.next && report.next.reason ? report.next.reason : '—'}`);
|
|
@@ -1835,10 +1853,18 @@ function runStatus(target, opts = {}) {
|
|
|
1835
1853
|
activeSession: report.activeSession,
|
|
1836
1854
|
scanDate: report.scanDate,
|
|
1837
1855
|
staleScan: report.stale,
|
|
1838
|
-
compactDate: report.compactDate,
|
|
1839
|
-
|
|
1840
|
-
|
|
1841
|
-
|
|
1856
|
+
compactDate: report.compactDate,
|
|
1857
|
+
staleCompact: report.staleCompact,
|
|
1858
|
+
planSelfEvaluation: report.planSelfEvaluation,
|
|
1859
|
+
planConfidenceThreshold: report.planConfidenceThreshold,
|
|
1860
|
+
planConfidenceExecutable: report.planConfidenceExecutable,
|
|
1861
|
+
implementationPackReady: report.implementationPackReady,
|
|
1862
|
+
referenceAnchorsReady: report.referenceAnchorsReady,
|
|
1863
|
+
fixturePackReady: report.fixturePackReady,
|
|
1864
|
+
executionRationalityReady: report.executionRationalityReady,
|
|
1865
|
+
criticalExecutionGaps: report.criticalExecutionGaps,
|
|
1866
|
+
executionRationality: report.executionRationality,
|
|
1867
|
+
planReviewStatus: report.planReviewStatus,
|
|
1842
1868
|
activeRun: report.activeRun,
|
|
1843
1869
|
eventsSummary: report.eventsSummary,
|
|
1844
1870
|
runtimeMode: report.runtimeMode,
|
|
@@ -15,7 +15,7 @@ oxe_tool_profile: read_heavy
|
|
|
15
15
|
oxe_confidence_policy: explicit
|
|
16
16
|
oxe_context_tier: standard
|
|
17
17
|
oxe_contract_version: 2.0.0
|
|
18
|
-
oxe_semantics_hash:
|
|
18
|
+
oxe_semantics_hash: ebb4473c14e5b080
|
|
19
19
|
---
|
|
20
20
|
|
|
21
21
|
<!-- oxe-reasoning-contract:start -->
|
|
@@ -29,7 +29,7 @@ oxe_semantics_hash: 37f74d8be3442fe1
|
|
|
29
29
|
- **Política de confiança:** explícita
|
|
30
30
|
- **Tier de contexto padrão:** padrão
|
|
31
31
|
- **Versão do contrato:** 2.0.0
|
|
32
|
-
- **Checksum semântico:** `
|
|
32
|
+
- **Checksum semântico:** `ebb4473c14e5b080`
|
|
33
33
|
- **Entrada de contexto prioritária:** `.oxe/context/packs/dashboard.md` e `.oxe/context/packs/dashboard.json`
|
|
34
34
|
- **Regra pack-first:** ler o context pack primeiro; se estiver stale, incompleto ou ausente, cair para leitura direta com fallback explícito.
|
|
35
35
|
- **Inspeção estruturada:** `oxe-cc context inspect --workflow dashboard --json`
|
package/commands/oxe/execute.md
CHANGED
|
@@ -17,7 +17,7 @@ oxe_tool_profile: write_bounded
|
|
|
17
17
|
oxe_confidence_policy: explicit
|
|
18
18
|
oxe_context_tier: standard
|
|
19
19
|
oxe_contract_version: 2.0.0
|
|
20
|
-
oxe_semantics_hash:
|
|
20
|
+
oxe_semantics_hash: 7b3446b77aef9353
|
|
21
21
|
---
|
|
22
22
|
|
|
23
23
|
<!-- oxe-reasoning-contract:start -->
|
|
@@ -31,7 +31,7 @@ oxe_semantics_hash: 14ddb483209b28b3
|
|
|
31
31
|
- **Política de confiança:** explícita
|
|
32
32
|
- **Tier de contexto padrão:** padrão
|
|
33
33
|
- **Versão do contrato:** 2.0.0
|
|
34
|
-
- **Checksum semântico:** `
|
|
34
|
+
- **Checksum semântico:** `7b3446b77aef9353`
|
|
35
35
|
- **Entrada de contexto prioritária:** `.oxe/context/packs/execute.md` e `.oxe/context/packs/execute.json`
|
|
36
36
|
- **Regra pack-first:** ler o context pack primeiro; se estiver stale, incompleto ou ausente, cair para leitura direta com fallback explícito.
|
|
37
37
|
- **Inspeção estruturada:** `oxe-cc context inspect --workflow execute --json`
|
package/commands/oxe/plan.md
CHANGED
|
@@ -16,7 +16,7 @@ oxe_tool_profile: mixed
|
|
|
16
16
|
oxe_confidence_policy: rubric
|
|
17
17
|
oxe_context_tier: standard
|
|
18
18
|
oxe_contract_version: 2.0.0
|
|
19
|
-
oxe_semantics_hash:
|
|
19
|
+
oxe_semantics_hash: 5c589398cb807029
|
|
20
20
|
---
|
|
21
21
|
|
|
22
22
|
<!-- oxe-reasoning-contract:start -->
|
|
@@ -30,7 +30,7 @@ oxe_semantics_hash: 7809d830a5f5ff4a
|
|
|
30
30
|
- **Política de confiança:** rubrica
|
|
31
31
|
- **Tier de contexto padrão:** padrão
|
|
32
32
|
- **Versão do contrato:** 2.0.0
|
|
33
|
-
- **Checksum semântico:** `
|
|
33
|
+
- **Checksum semântico:** `5c589398cb807029`
|
|
34
34
|
- **Entrada de contexto prioritária:** `.oxe/context/packs/plan.md` e `.oxe/context/packs/plan.json`
|
|
35
35
|
- **Regra pack-first:** ler o context pack primeiro; se estiver stale, incompleto ou ausente, cair para leitura direta com fallback explícito.
|
|
36
36
|
- **Inspeção estruturada:** `oxe-cc context inspect --workflow plan --json`
|
package/lib/sdk/index.cjs
CHANGED
|
@@ -20,6 +20,7 @@ const azure = require('../../bin/lib/oxe-azure.cjs');
|
|
|
20
20
|
const context = require('../../bin/lib/oxe-context-engine.cjs');
|
|
21
21
|
const runtimeSemantics = require('../../bin/lib/oxe-runtime-semantics.cjs');
|
|
22
22
|
const release = require('../../bin/lib/oxe-release.cjs');
|
|
23
|
+
const rationality = require('../../bin/lib/oxe-rationality.cjs');
|
|
23
24
|
|
|
24
25
|
const PACKAGE_ROOT = path.join(__dirname, '..', '..');
|
|
25
26
|
|
|
@@ -541,9 +542,10 @@ module.exports = {
|
|
|
541
542
|
/** Parsing de artefatos OXE (PLAN, SPEC, STATE, hypotheses, confidence, lessons). */
|
|
542
543
|
parsePlan,
|
|
543
544
|
parseSpec,
|
|
544
|
-
parseHypotheses: context.parseHypotheses,
|
|
545
|
-
parseConfidenceVector: context.parseConfidenceVector,
|
|
546
|
-
|
|
545
|
+
parseHypotheses: context.parseHypotheses,
|
|
546
|
+
parseConfidenceVector: context.parseConfidenceVector,
|
|
547
|
+
parseExecutionPlanTasks: rationality.parsePlanTasks,
|
|
548
|
+
parseState,
|
|
547
549
|
validateDecisionFidelity,
|
|
548
550
|
parseLessonsMetrics,
|
|
549
551
|
updateLessonMetric,
|
|
@@ -568,9 +570,11 @@ module.exports = {
|
|
|
568
570
|
planAgentsWarnings: health.planAgentsWarnings,
|
|
569
571
|
phaseCoherenceWarnings: health.phaseCoherenceWarnings,
|
|
570
572
|
specSectionWarnings: health.specSectionWarnings,
|
|
571
|
-
planWaveWarningsFixed: health.planWaveWarningsFixed,
|
|
572
|
-
planTaskAceiteWarnings: health.planTaskAceiteWarnings,
|
|
573
|
-
|
|
573
|
+
planWaveWarningsFixed: health.planWaveWarningsFixed,
|
|
574
|
+
planTaskAceiteWarnings: health.planTaskAceiteWarnings,
|
|
575
|
+
buildExecutionRationality: health.buildExecutionRationality,
|
|
576
|
+
executionRationalityWarningsFromSummary: health.executionRationalityWarningsFromSummary,
|
|
577
|
+
verifyGapsWithoutSummaryWarning: health.verifyGapsWithoutSummaryWarning,
|
|
574
578
|
expandExecutionProfile: health.expandExecutionProfile,
|
|
575
579
|
ALLOWED_CONFIG_KEYS: health.ALLOWED_CONFIG_KEYS,
|
|
576
580
|
EXECUTION_PROFILES: health.EXECUTION_PROFILES,
|