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
|
@@ -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
|
+
};
|