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
|
@@ -5,12 +5,15 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.MultiAgentCoordinator = void 0;
|
|
7
7
|
exports.multiAgentStatePath = multiAgentStatePath;
|
|
8
|
+
exports.multiAgentSummaryPath = multiAgentSummaryPath;
|
|
8
9
|
exports.loadMultiAgentState = loadMultiAgentState;
|
|
10
|
+
exports.loadMultiAgentSummary = loadMultiAgentSummary;
|
|
9
11
|
const fs_1 = __importDefault(require("fs"));
|
|
10
12
|
const path_1 = __importDefault(require("path"));
|
|
11
13
|
const bus_1 = require("../events/bus");
|
|
12
14
|
const scheduler_1 = require("./scheduler");
|
|
13
15
|
const agent_roles_1 = require("./agent-roles");
|
|
16
|
+
const agent_registry_1 = require("./agent-registry");
|
|
14
17
|
function ensureRunDir(projectRoot, runId) {
|
|
15
18
|
const dir = path_1.default.join(projectRoot, '.oxe', 'runs', runId);
|
|
16
19
|
fs_1.default.mkdirSync(dir, { recursive: true });
|
|
@@ -21,6 +24,24 @@ function persistMultiAgentArtifacts(projectRoot, runId, state, handoffs = [], ar
|
|
|
21
24
|
fs_1.default.writeFileSync(path_1.default.join(runDir, 'multi-agent-state.json'), JSON.stringify(state, null, 2), 'utf8');
|
|
22
25
|
fs_1.default.writeFileSync(path_1.default.join(runDir, 'handoffs.json'), JSON.stringify(handoffs, null, 2), 'utf8');
|
|
23
26
|
fs_1.default.writeFileSync(path_1.default.join(runDir, 'arbitration-results.json'), JSON.stringify(arbitrationResults, null, 2), 'utf8');
|
|
27
|
+
const summary = {
|
|
28
|
+
run_id: state.run_id,
|
|
29
|
+
mode: state.mode,
|
|
30
|
+
workspace_isolation_enforced: state.workspace_isolation_enforced,
|
|
31
|
+
agent_count: state.agent_count,
|
|
32
|
+
completed_count: state.completed.length,
|
|
33
|
+
failed_count: state.failed.length,
|
|
34
|
+
blocked_count: state.blocked.length,
|
|
35
|
+
ownership_count: state.ownership.length,
|
|
36
|
+
handoff_count: handoffs.length,
|
|
37
|
+
arbitration_count: arbitrationResults.length,
|
|
38
|
+
orphan_reassignment_count: state.orphan_reassignments.length,
|
|
39
|
+
timeout_count: state.timed_out_agents.length,
|
|
40
|
+
participating_agents: state.agent_results.map((entry) => entry.agent_id),
|
|
41
|
+
health: state.timed_out_agents.length > 0 || state.failed.length > 0 ? 'degraded' : 'healthy',
|
|
42
|
+
updated_at: state.updated_at,
|
|
43
|
+
};
|
|
44
|
+
fs_1.default.writeFileSync(path_1.default.join(runDir, 'multi-agent-summary.json'), JSON.stringify(summary, null, 2), 'utf8');
|
|
24
45
|
}
|
|
25
46
|
function ensureIsolatedAgents(agents) {
|
|
26
47
|
const shared = agents.filter((agent) => agent.workspaceManager.isolation_level !== 'isolated');
|
|
@@ -41,7 +62,7 @@ function buildOwnership(agents, partitions) {
|
|
|
41
62
|
}
|
|
42
63
|
return ownership;
|
|
43
64
|
}
|
|
44
|
-
function makeState(mode, runId, agents, partitions, agentResults, completed, failed, blocked, orphanReassignments) {
|
|
65
|
+
function makeState(mode, runId, agents, partitions, agentResults, completed, failed, blocked, orphanReassignments, timedOutAgents) {
|
|
45
66
|
return {
|
|
46
67
|
run_id: runId,
|
|
47
68
|
mode,
|
|
@@ -60,16 +81,82 @@ function makeState(mode, runId, agents, partitions, agentResults, completed, fai
|
|
|
60
81
|
assigned_task_ids: partitions[idx] ?? agent.assignedTaskIds ?? [],
|
|
61
82
|
completed: result?.completed ?? [],
|
|
62
83
|
failed: result?.failed ?? [],
|
|
84
|
+
timed_out: Boolean(result?.timed_out),
|
|
85
|
+
reassigned_task_ids: result?.reassigned_task_ids ?? [],
|
|
63
86
|
};
|
|
64
87
|
}),
|
|
65
88
|
orphan_reassignments: orphanReassignments,
|
|
89
|
+
timed_out_agents: timedOutAgents,
|
|
66
90
|
updated_at: new Date().toISOString(),
|
|
67
91
|
};
|
|
68
92
|
}
|
|
93
|
+
async function runGraphForAgent(graph, nodeIds, agent, idx, opts, heartbeatTimeoutMs) {
|
|
94
|
+
const subGraph = subGraphFor(graph, nodeIds);
|
|
95
|
+
if (subGraph.nodes.size === 0) {
|
|
96
|
+
return {
|
|
97
|
+
agent_id: agent.id,
|
|
98
|
+
completed: [],
|
|
99
|
+
failed: [],
|
|
100
|
+
timed_out: false,
|
|
101
|
+
assigned_task_ids: nodeIds,
|
|
102
|
+
reassigned_task_ids: [],
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
const ctx = {
|
|
106
|
+
projectRoot: opts.projectRoot,
|
|
107
|
+
sessionId: opts.sessionId,
|
|
108
|
+
runId: `${opts.runId}-agent${idx}`,
|
|
109
|
+
executor: agent.executor,
|
|
110
|
+
workspaceManager: agent.workspaceManager,
|
|
111
|
+
onEvent: opts.onEvent,
|
|
112
|
+
};
|
|
113
|
+
const scheduler = new scheduler_1.Scheduler();
|
|
114
|
+
const work = scheduler.run(subGraph, ctx);
|
|
115
|
+
if (!heartbeatTimeoutMs || heartbeatTimeoutMs <= 0) {
|
|
116
|
+
const result = await work;
|
|
117
|
+
return {
|
|
118
|
+
agent_id: agent.id,
|
|
119
|
+
completed: result.completed,
|
|
120
|
+
failed: result.failed,
|
|
121
|
+
timed_out: false,
|
|
122
|
+
assigned_task_ids: nodeIds,
|
|
123
|
+
reassigned_task_ids: [],
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
let timer = null;
|
|
127
|
+
const raced = await Promise.race([
|
|
128
|
+
work.then((result) => ({ type: 'result', result })),
|
|
129
|
+
new Promise((resolve) => {
|
|
130
|
+
timer = setTimeout(() => resolve({ type: 'timeout' }), heartbeatTimeoutMs);
|
|
131
|
+
}),
|
|
132
|
+
]);
|
|
133
|
+
if (timer)
|
|
134
|
+
clearTimeout(timer);
|
|
135
|
+
if (raced && raced.type === 'timeout') {
|
|
136
|
+
return {
|
|
137
|
+
agent_id: agent.id,
|
|
138
|
+
completed: [],
|
|
139
|
+
failed: [],
|
|
140
|
+
timed_out: true,
|
|
141
|
+
assigned_task_ids: nodeIds,
|
|
142
|
+
reassigned_task_ids: [],
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
const result = raced.result;
|
|
146
|
+
return {
|
|
147
|
+
agent_id: agent.id,
|
|
148
|
+
completed: result.completed,
|
|
149
|
+
failed: result.failed,
|
|
150
|
+
timed_out: false,
|
|
151
|
+
assigned_task_ids: nodeIds,
|
|
152
|
+
reassigned_task_ids: [],
|
|
153
|
+
};
|
|
154
|
+
}
|
|
69
155
|
// ─── Parallel mode ───────────────────────────────────────────────────────────
|
|
70
156
|
async function runParallel(graph, opts) {
|
|
71
157
|
const { agents, projectRoot, sessionId, runId } = opts;
|
|
72
158
|
ensureIsolatedAgents(agents);
|
|
159
|
+
const heartbeatTimeoutMs = opts.heartbeatTimeoutMs ?? null;
|
|
73
160
|
const partitions = agents.map((agent) => [...(agent.assignedTaskIds ?? [])]);
|
|
74
161
|
if (partitions.every((partition) => partition.length === 0)) {
|
|
75
162
|
const allIds = [...graph.nodes.keys()];
|
|
@@ -77,33 +164,55 @@ async function runParallel(graph, opts) {
|
|
|
77
164
|
partitions[index % agents.length].push(id);
|
|
78
165
|
});
|
|
79
166
|
}
|
|
167
|
+
const registry = new agent_registry_1.AgentRegistry(heartbeatTimeoutMs == null ? 30000 : heartbeatTimeoutMs);
|
|
168
|
+
agents.forEach((agent, idx) => {
|
|
169
|
+
registry.register(agent.id, agent.executor, agent.workspaceManager, partitions[idx] ?? []);
|
|
170
|
+
});
|
|
80
171
|
(0, bus_1.appendEvent)(projectRoot, sessionId, {
|
|
81
172
|
type: 'RunStarted',
|
|
82
173
|
run_id: runId,
|
|
83
174
|
payload: { mode: 'parallel', agent_count: agents.length, isolation_level: 'isolated' },
|
|
84
175
|
});
|
|
85
|
-
const
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
const ctx = {
|
|
91
|
-
projectRoot,
|
|
92
|
-
sessionId,
|
|
93
|
-
runId: `${runId}-agent${idx}`,
|
|
94
|
-
executor: agent.executor,
|
|
95
|
-
workspaceManager: agent.workspaceManager,
|
|
96
|
-
onEvent: opts.onEvent,
|
|
97
|
-
};
|
|
98
|
-
const scheduler = new scheduler_1.Scheduler();
|
|
99
|
-
const result = await scheduler.run(subGraph, ctx);
|
|
100
|
-
return { agent_id: agent.id, completed: result.completed, failed: result.failed };
|
|
176
|
+
const initialResults = await Promise.all(agents.map(async (agent, idx) => {
|
|
177
|
+
registry.beat(agent.id, partitions[idx][0] || null);
|
|
178
|
+
const result = await runGraphForAgent(graph, partitions[idx], agent, idx, opts, heartbeatTimeoutMs);
|
|
179
|
+
registry.setStatus(agent.id, result.timed_out ? 'timeout' : 'idle');
|
|
180
|
+
return result;
|
|
101
181
|
}));
|
|
102
|
-
const
|
|
103
|
-
const failed = agentResults.flatMap((result) => result.failed);
|
|
182
|
+
const timedOutAgents = [];
|
|
104
183
|
const blocked = [];
|
|
105
184
|
const orphanReassignments = [];
|
|
106
|
-
const
|
|
185
|
+
const agentResults = initialResults.map((entry) => ({
|
|
186
|
+
...entry,
|
|
187
|
+
reassigned_task_ids: entry.reassigned_task_ids || [],
|
|
188
|
+
}));
|
|
189
|
+
const liveAgents = agentResults.filter((entry) => !entry.timed_out);
|
|
190
|
+
for (const timedOut of agentResults.filter((entry) => entry.timed_out)) {
|
|
191
|
+
timedOutAgents.push({
|
|
192
|
+
agent_id: timedOut.agent_id,
|
|
193
|
+
work_item_ids: timedOut.assigned_task_ids,
|
|
194
|
+
detected_at: new Date().toISOString(),
|
|
195
|
+
});
|
|
196
|
+
const fallback = liveAgents.find((entry) => entry.agent_id !== timedOut.agent_id);
|
|
197
|
+
if (!fallback || timedOut.assigned_task_ids.length === 0)
|
|
198
|
+
continue;
|
|
199
|
+
const fallbackIdx = agents.findIndex((agent) => agent.id === fallback.agent_id);
|
|
200
|
+
const timeoutIdx = agents.findIndex((agent) => agent.id === timedOut.agent_id);
|
|
201
|
+
const rerun = await runGraphForAgent(graph, timedOut.assigned_task_ids, agents[fallbackIdx], fallbackIdx, opts, null);
|
|
202
|
+
fallback.completed.push(...rerun.completed);
|
|
203
|
+
fallback.failed.push(...rerun.failed);
|
|
204
|
+
fallback.reassigned_task_ids.push(...timedOut.assigned_task_ids);
|
|
205
|
+
partitions[fallbackIdx] = [...partitions[fallbackIdx], ...timedOut.assigned_task_ids];
|
|
206
|
+
partitions[timeoutIdx] = [];
|
|
207
|
+
orphanReassignments.push({
|
|
208
|
+
from_agent_id: timedOut.agent_id,
|
|
209
|
+
to_agent_id: fallback.agent_id,
|
|
210
|
+
work_item_ids: timedOut.assigned_task_ids,
|
|
211
|
+
});
|
|
212
|
+
}
|
|
213
|
+
const completed = Array.from(new Set(agentResults.flatMap((result) => result.completed)));
|
|
214
|
+
const failed = Array.from(new Set(agentResults.flatMap((result) => result.failed)));
|
|
215
|
+
const state = makeState('parallel', runId, agents, partitions, agentResults, completed, failed, blocked, orphanReassignments, timedOutAgents);
|
|
107
216
|
persistMultiAgentArtifacts(projectRoot, runId, state);
|
|
108
217
|
(0, bus_1.appendEvent)(projectRoot, sessionId, {
|
|
109
218
|
type: 'RunCompleted',
|
|
@@ -119,6 +228,7 @@ async function runParallel(graph, opts) {
|
|
|
119
228
|
agent_results: agentResults,
|
|
120
229
|
arbitration_results: [],
|
|
121
230
|
state,
|
|
231
|
+
summary: loadMultiAgentSummary(projectRoot, runId) || undefined,
|
|
122
232
|
};
|
|
123
233
|
}
|
|
124
234
|
// ─── Competitive mode ────────────────────────────────────────────────────────
|
|
@@ -154,9 +264,9 @@ async function runCompetitive(graph, opts) {
|
|
|
154
264
|
}
|
|
155
265
|
const partitions = [Array.from(graph.nodes.keys()), Array.from(graph.nodes.keys())];
|
|
156
266
|
const state = makeState('competitive', runId, opts.agents, partitions, [
|
|
157
|
-
{ agent_id: agentA.id, completed, failed },
|
|
158
|
-
{ agent_id: agentB.id, completed: [], failed: [] },
|
|
159
|
-
], completed, failed, blocked, []);
|
|
267
|
+
{ agent_id: agentA.id, completed, failed, timed_out: false, reassigned_task_ids: [] },
|
|
268
|
+
{ agent_id: agentB.id, completed: [], failed: [], timed_out: false, reassigned_task_ids: [] },
|
|
269
|
+
], completed, failed, blocked, [], []);
|
|
160
270
|
persistMultiAgentArtifacts(projectRoot, runId, state, [], arbitrationResults);
|
|
161
271
|
(0, bus_1.appendEvent)(projectRoot, sessionId, {
|
|
162
272
|
type: 'RunCompleted',
|
|
@@ -175,6 +285,7 @@ async function runCompetitive(graph, opts) {
|
|
|
175
285
|
],
|
|
176
286
|
arbitration_results: arbitrationResults,
|
|
177
287
|
state,
|
|
288
|
+
summary: loadMultiAgentSummary(projectRoot, runId) || undefined,
|
|
178
289
|
};
|
|
179
290
|
}
|
|
180
291
|
async function competeTwoAgents(nodeId, node, agentA, agentB, opts, arbitrationResults) {
|
|
@@ -294,9 +405,9 @@ async function runCooperative(graph, opts) {
|
|
|
294
405
|
}
|
|
295
406
|
const partitions = [Array.from(graph.nodes.keys()), Array.from(graph.nodes.keys())];
|
|
296
407
|
const state = makeState('cooperative', runId, opts.agents, partitions, [
|
|
297
|
-
{ agent_id: planner.id, completed: [], failed: [] },
|
|
298
|
-
{ agent_id: executor.id, completed, failed },
|
|
299
|
-
], completed, failed, blocked, []);
|
|
408
|
+
{ agent_id: planner.id, completed: [], failed: [], timed_out: false, reassigned_task_ids: [] },
|
|
409
|
+
{ agent_id: executor.id, completed, failed, timed_out: false, reassigned_task_ids: [] },
|
|
410
|
+
], completed, failed, blocked, [], []);
|
|
300
411
|
persistMultiAgentArtifacts(projectRoot, runId, state, handoffs, []);
|
|
301
412
|
(0, bus_1.appendEvent)(projectRoot, sessionId, {
|
|
302
413
|
type: 'RunCompleted',
|
|
@@ -316,6 +427,7 @@ async function runCooperative(graph, opts) {
|
|
|
316
427
|
handoffs,
|
|
317
428
|
arbitration_results: [],
|
|
318
429
|
state,
|
|
430
|
+
summary: loadMultiAgentSummary(projectRoot, runId) || undefined,
|
|
319
431
|
};
|
|
320
432
|
}
|
|
321
433
|
// ─── Public API ──────────────────────────────────────────────────────────────
|
|
@@ -334,6 +446,9 @@ exports.MultiAgentCoordinator = MultiAgentCoordinator;
|
|
|
334
446
|
function multiAgentStatePath(projectRoot, runId) {
|
|
335
447
|
return path_1.default.join(projectRoot, '.oxe', 'runs', runId, 'multi-agent-state.json');
|
|
336
448
|
}
|
|
449
|
+
function multiAgentSummaryPath(projectRoot, runId) {
|
|
450
|
+
return path_1.default.join(projectRoot, '.oxe', 'runs', runId, 'multi-agent-summary.json');
|
|
451
|
+
}
|
|
337
452
|
function loadMultiAgentState(projectRoot, runId) {
|
|
338
453
|
const statePath = multiAgentStatePath(projectRoot, runId);
|
|
339
454
|
if (!fs_1.default.existsSync(statePath))
|
|
@@ -345,6 +460,17 @@ function loadMultiAgentState(projectRoot, runId) {
|
|
|
345
460
|
return null;
|
|
346
461
|
}
|
|
347
462
|
}
|
|
463
|
+
function loadMultiAgentSummary(projectRoot, runId) {
|
|
464
|
+
const summaryPath = multiAgentSummaryPath(projectRoot, runId);
|
|
465
|
+
if (!fs_1.default.existsSync(summaryPath))
|
|
466
|
+
return null;
|
|
467
|
+
try {
|
|
468
|
+
return JSON.parse(fs_1.default.readFileSync(summaryPath, 'utf8'));
|
|
469
|
+
}
|
|
470
|
+
catch {
|
|
471
|
+
return null;
|
|
472
|
+
}
|
|
473
|
+
}
|
|
348
474
|
// ─── Helpers ─────────────────────────────────────────────────────────────────
|
|
349
475
|
function subGraphFor(graph, nodeIds) {
|
|
350
476
|
const ids = new Set(nodeIds);
|
package/lib/sdk/README.md
CHANGED
|
@@ -76,5 +76,7 @@ O SDK já expõe os helpers usados pela operação enterprise do OXE:
|
|
|
76
76
|
- `operational.readRuntimeGates(...)` / `operational.resolveRuntimeGate(...)`
|
|
77
77
|
- `operational.recoverRuntimeState(...)` / `operational.replayRuntimeState(...)`
|
|
78
78
|
- `operational.readRuntimeMultiAgentStatus(...)` / `operational.multiAgentStatus(...)`
|
|
79
|
+
- `release.checkReleaseConsistency(...)` / `release.buildReleaseManifest(...)`
|
|
80
|
+
- `release.loadRuntimeSmokeReport(...)` / `release.loadRecoveryFixtureReport(...)` / `release.loadMultiAgentSoakReport(...)`
|
|
79
81
|
|
|
80
82
|
Use esses helpers quando quiser integrar gates, verify, recovery e multi-agent a scripts de CI, automações internas ou observabilidade.
|
package/lib/sdk/index.cjs
CHANGED
|
@@ -17,8 +17,10 @@ const plugins = require('../../bin/lib/oxe-plugins.cjs');
|
|
|
17
17
|
const dashboard = require('../../bin/lib/oxe-dashboard.cjs');
|
|
18
18
|
const operational = require('../../bin/lib/oxe-operational.cjs');
|
|
19
19
|
const azure = require('../../bin/lib/oxe-azure.cjs');
|
|
20
|
-
const context = require('../../bin/lib/oxe-context-engine.cjs');
|
|
21
|
-
const runtimeSemantics = require('../../bin/lib/oxe-runtime-semantics.cjs');
|
|
20
|
+
const context = require('../../bin/lib/oxe-context-engine.cjs');
|
|
21
|
+
const runtimeSemantics = require('../../bin/lib/oxe-runtime-semantics.cjs');
|
|
22
|
+
const release = require('../../bin/lib/oxe-release.cjs');
|
|
23
|
+
const rationality = require('../../bin/lib/oxe-rationality.cjs');
|
|
22
24
|
|
|
23
25
|
const PACKAGE_ROOT = path.join(__dirname, '..', '..');
|
|
24
26
|
|
|
@@ -540,9 +542,10 @@ module.exports = {
|
|
|
540
542
|
/** Parsing de artefatos OXE (PLAN, SPEC, STATE, hypotheses, confidence, lessons). */
|
|
541
543
|
parsePlan,
|
|
542
544
|
parseSpec,
|
|
543
|
-
parseHypotheses: context.parseHypotheses,
|
|
544
|
-
parseConfidenceVector: context.parseConfidenceVector,
|
|
545
|
-
|
|
545
|
+
parseHypotheses: context.parseHypotheses,
|
|
546
|
+
parseConfidenceVector: context.parseConfidenceVector,
|
|
547
|
+
parseExecutionPlanTasks: rationality.parsePlanTasks,
|
|
548
|
+
parseState,
|
|
546
549
|
validateDecisionFidelity,
|
|
547
550
|
parseLessonsMetrics,
|
|
548
551
|
updateLessonMetric,
|
|
@@ -567,9 +570,11 @@ module.exports = {
|
|
|
567
570
|
planAgentsWarnings: health.planAgentsWarnings,
|
|
568
571
|
phaseCoherenceWarnings: health.phaseCoherenceWarnings,
|
|
569
572
|
specSectionWarnings: health.specSectionWarnings,
|
|
570
|
-
planWaveWarningsFixed: health.planWaveWarningsFixed,
|
|
571
|
-
planTaskAceiteWarnings: health.planTaskAceiteWarnings,
|
|
572
|
-
|
|
573
|
+
planWaveWarningsFixed: health.planWaveWarningsFixed,
|
|
574
|
+
planTaskAceiteWarnings: health.planTaskAceiteWarnings,
|
|
575
|
+
buildExecutionRationality: health.buildExecutionRationality,
|
|
576
|
+
executionRationalityWarningsFromSummary: health.executionRationalityWarningsFromSummary,
|
|
577
|
+
verifyGapsWithoutSummaryWarning: health.verifyGapsWithoutSummaryWarning,
|
|
573
578
|
expandExecutionProfile: health.expandExecutionProfile,
|
|
574
579
|
ALLOWED_CONFIG_KEYS: health.ALLOWED_CONFIG_KEYS,
|
|
575
580
|
EXECUTION_PROFILES: health.EXECUTION_PROFILES,
|
|
@@ -636,12 +641,25 @@ module.exports = {
|
|
|
636
641
|
},
|
|
637
642
|
|
|
638
643
|
/** Dashboard local: contexto consolidado e persistência de revisão do plano. */
|
|
639
|
-
dashboard: {
|
|
640
|
-
loadDashboardContext: dashboard.loadDashboardContext,
|
|
641
|
-
savePlanReviewStatus: dashboard.savePlanReviewStatus,
|
|
642
|
-
addPlanReviewComment: dashboard.addPlanReviewComment,
|
|
643
|
-
updatePlanReviewCommentStatus: dashboard.updatePlanReviewCommentStatus,
|
|
644
|
-
},
|
|
644
|
+
dashboard: {
|
|
645
|
+
loadDashboardContext: dashboard.loadDashboardContext,
|
|
646
|
+
savePlanReviewStatus: dashboard.savePlanReviewStatus,
|
|
647
|
+
addPlanReviewComment: dashboard.addPlanReviewComment,
|
|
648
|
+
updatePlanReviewCommentStatus: dashboard.updatePlanReviewCommentStatus,
|
|
649
|
+
},
|
|
650
|
+
|
|
651
|
+
/** Release readiness: manifest, smoke matrix e checks de consistência antes de publicar. */
|
|
652
|
+
release: {
|
|
653
|
+
REQUIRED_RUNTIMES: release.REQUIRED_RUNTIMES,
|
|
654
|
+
WRAPPER_TARGETS: release.WRAPPER_TARGETS,
|
|
655
|
+
releasePaths: release.releasePaths,
|
|
656
|
+
collectWrapperHashes: release.collectWrapperHashes,
|
|
657
|
+
loadRuntimeSmokeReport: release.loadRuntimeSmokeReport,
|
|
658
|
+
loadRecoveryFixtureReport: release.loadRecoveryFixtureReport,
|
|
659
|
+
loadMultiAgentSoakReport: release.loadMultiAgentSoakReport,
|
|
660
|
+
buildReleaseManifest: release.buildReleaseManifest,
|
|
661
|
+
checkReleaseConsistency: release.checkReleaseConsistency,
|
|
662
|
+
},
|
|
645
663
|
|
|
646
664
|
/** Runtime operacional: tracing, active run, catálogo de capabilities e memória em camadas. */
|
|
647
665
|
operational: {
|
package/lib/sdk/index.d.ts
CHANGED
|
@@ -146,18 +146,50 @@ export interface GateQueueSnapshot {
|
|
|
146
146
|
all?: Array<Record<string, unknown>>;
|
|
147
147
|
}
|
|
148
148
|
|
|
149
|
-
export interface MultiAgentStatusSummary {
|
|
150
|
-
path: string | null;
|
|
151
|
-
enabled: boolean;
|
|
152
|
-
runId: string | null;
|
|
153
|
-
mode: string | null;
|
|
149
|
+
export interface MultiAgentStatusSummary {
|
|
150
|
+
path: string | null;
|
|
151
|
+
enabled: boolean;
|
|
152
|
+
runId: string | null;
|
|
153
|
+
mode: string | null;
|
|
154
154
|
workspaceIsolationEnforced: boolean;
|
|
155
155
|
agents: Array<Record<string, unknown>>;
|
|
156
|
-
ownership: Array<Record<string, unknown>>;
|
|
157
|
-
orphanReassignments: Array<Record<string, unknown>>;
|
|
158
|
-
handoffs: Array<Record<string, unknown>>;
|
|
159
|
-
arbitrationResults: Array<Record<string, unknown>>;
|
|
160
|
-
|
|
156
|
+
ownership: Array<Record<string, unknown>>;
|
|
157
|
+
orphanReassignments: Array<Record<string, unknown>>;
|
|
158
|
+
handoffs: Array<Record<string, unknown>>;
|
|
159
|
+
arbitrationResults: Array<Record<string, unknown>>;
|
|
160
|
+
summary?: Record<string, unknown> | null;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
export interface ReleaseManifest {
|
|
164
|
+
schema_version: number;
|
|
165
|
+
generated_at: string;
|
|
166
|
+
project_root: string;
|
|
167
|
+
package_root: string;
|
|
168
|
+
release_contract: Record<string, unknown>;
|
|
169
|
+
versions: Record<string, unknown>;
|
|
170
|
+
runtime_compiled: { path: string; ok: boolean };
|
|
171
|
+
wrappers: Record<string, unknown>;
|
|
172
|
+
reports: Record<string, unknown>;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
export interface ReleaseConsistencyResult {
|
|
176
|
+
ok: boolean;
|
|
177
|
+
blockers: string[];
|
|
178
|
+
warnings: string[];
|
|
179
|
+
manifest: ReleaseManifest;
|
|
180
|
+
manifestPath: string;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
export interface RuntimeSmokeReport {
|
|
184
|
+
path: string;
|
|
185
|
+
present: boolean;
|
|
186
|
+
ok: boolean;
|
|
187
|
+
total: number;
|
|
188
|
+
failures: string[];
|
|
189
|
+
missingRequired: string[];
|
|
190
|
+
results: Array<Record<string, unknown>>;
|
|
191
|
+
raw: Record<string, unknown> | null;
|
|
192
|
+
}
|
|
161
193
|
|
|
162
194
|
export interface PolicyDecisionSummary {
|
|
163
195
|
total: number;
|
|
@@ -193,17 +225,62 @@ export interface AuditSummary {
|
|
|
193
225
|
actions: Record<string, number>;
|
|
194
226
|
}
|
|
195
227
|
|
|
196
|
-
export interface PromotionSummary {
|
|
197
|
-
status: string | null;
|
|
198
|
-
targetKind: string | null;
|
|
199
|
-
remote: string | null;
|
|
200
|
-
targetRef: string | null;
|
|
201
|
-
prUrl: string | null;
|
|
202
|
-
prNumber: number | null;
|
|
203
|
-
coveragePercent: number | null;
|
|
204
|
-
reasons: string[];
|
|
205
|
-
path: string;
|
|
206
|
-
}
|
|
228
|
+
export interface PromotionSummary {
|
|
229
|
+
status: string | null;
|
|
230
|
+
targetKind: string | null;
|
|
231
|
+
remote: string | null;
|
|
232
|
+
targetRef: string | null;
|
|
233
|
+
prUrl: string | null;
|
|
234
|
+
prNumber: number | null;
|
|
235
|
+
coveragePercent: number | null;
|
|
236
|
+
reasons: string[];
|
|
237
|
+
path: string;
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
export interface ExecutionImplementationPackSummary {
|
|
241
|
+
path: string | null;
|
|
242
|
+
exists: boolean;
|
|
243
|
+
parseError: string | null;
|
|
244
|
+
ready: boolean;
|
|
245
|
+
tasks: Array<Record<string, unknown>>;
|
|
246
|
+
taskCount: number;
|
|
247
|
+
mutatingTasks: number;
|
|
248
|
+
criticalGaps: string[];
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
export interface ExecutionReferenceAnchorsSummary {
|
|
252
|
+
path: string | null;
|
|
253
|
+
exists: boolean;
|
|
254
|
+
ready: boolean;
|
|
255
|
+
anchors: Array<Record<string, unknown>>;
|
|
256
|
+
missingCriticalCount: number;
|
|
257
|
+
staleCount: number;
|
|
258
|
+
criticalGaps: string[];
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
export interface ExecutionFixturePackSummary {
|
|
262
|
+
path: string | null;
|
|
263
|
+
exists: boolean;
|
|
264
|
+
parseError: string | null;
|
|
265
|
+
ready: boolean;
|
|
266
|
+
fixtures: Array<Record<string, unknown>>;
|
|
267
|
+
fixtureCount: number;
|
|
268
|
+
criticalGaps: string[];
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
export interface ExecutionRationalitySummary {
|
|
272
|
+
applicable: boolean;
|
|
273
|
+
planTaskCount: number;
|
|
274
|
+
externalReferenceCount: number;
|
|
275
|
+
implementationPackReady: boolean;
|
|
276
|
+
referenceAnchorsReady: boolean;
|
|
277
|
+
fixturePackReady: boolean;
|
|
278
|
+
executionRationalityReady: boolean;
|
|
279
|
+
criticalExecutionGaps: string[];
|
|
280
|
+
implementationPack: ExecutionImplementationPackSummary;
|
|
281
|
+
referenceAnchors: ExecutionReferenceAnchorsSummary;
|
|
282
|
+
fixturePack: ExecutionFixturePackSummary;
|
|
283
|
+
}
|
|
207
284
|
|
|
208
285
|
/** Relatório retornado por `health.buildHealthReport` e incluído em `runDoctorChecks`.healthReport. */
|
|
209
286
|
export interface OxeHealthReport {
|
|
@@ -228,10 +305,16 @@ export interface OxeHealthReport {
|
|
|
228
305
|
copilotWarn?: string[];
|
|
229
306
|
copilot?: CopilotIntegrationReport | null;
|
|
230
307
|
summaryGapWarn: string | null;
|
|
231
|
-
specWarn: string[];
|
|
232
|
-
planWarn: string[];
|
|
233
|
-
planSelfEvaluation?: Record<string, unknown> | null;
|
|
234
|
-
|
|
308
|
+
specWarn: string[];
|
|
309
|
+
planWarn: string[];
|
|
310
|
+
planSelfEvaluation?: Record<string, unknown> | null;
|
|
311
|
+
implementationPackReady?: boolean;
|
|
312
|
+
referenceAnchorsReady?: boolean;
|
|
313
|
+
fixturePackReady?: boolean;
|
|
314
|
+
executionRationalityReady?: boolean;
|
|
315
|
+
criticalExecutionGaps?: string[];
|
|
316
|
+
executionRationality?: ExecutionRationalitySummary | null;
|
|
317
|
+
planReviewStatus?: string | null;
|
|
235
318
|
activeRun?: Record<string, unknown> | null;
|
|
236
319
|
eventsSummary?: Record<string, unknown> | null;
|
|
237
320
|
memoryLayers?: Record<string, unknown> | null;
|
|
@@ -584,11 +667,12 @@ export interface OxeSdk {
|
|
|
584
667
|
readMinNode: (packageRoot: string) => number;
|
|
585
668
|
|
|
586
669
|
/** Parsing de artefatos OXE. */
|
|
587
|
-
parsePlan: (planMd: string) => ParsedPlan;
|
|
588
|
-
parseHypotheses: (planText: string) => CriticalHypothesis[];
|
|
589
|
-
parseConfidenceVector: (planText: string) => ConfidenceVector | null;
|
|
590
|
-
|
|
591
|
-
|
|
670
|
+
parsePlan: (planMd: string) => ParsedPlan;
|
|
671
|
+
parseHypotheses: (planText: string) => CriticalHypothesis[];
|
|
672
|
+
parseConfidenceVector: (planText: string) => ConfidenceVector | null;
|
|
673
|
+
parseExecutionPlanTasks: (planPath: string | null) => Array<Record<string, unknown>>;
|
|
674
|
+
parseSpec: (specMd: string) => ParsedSpec;
|
|
675
|
+
parseState: (stateMd: string) => ParsedState;
|
|
592
676
|
validateDecisionFidelity: (discussMd: string, planMd: string) => DecisionFidelityResult;
|
|
593
677
|
parseLessonsMetrics: (metricsJson: string) => LessonMetric[];
|
|
594
678
|
updateLessonMetric: (metrics: LessonMetric[], lessonId: string, outcome: LessonOutcome) => LessonMetric[];
|
|
@@ -622,10 +706,12 @@ export interface OxeSdk {
|
|
|
622
706
|
copilotIntegrationReport: (target: string) => CopilotIntegrationReport;
|
|
623
707
|
planAgentsWarnings: (target: string) => string[];
|
|
624
708
|
phaseCoherenceWarnings: (phase: string, paths: Record<string, string>) => string[];
|
|
625
|
-
specSectionWarnings: (specPath: string, requiredHeadings: string[]) => string[];
|
|
626
|
-
planWaveWarningsFixed: (planPath: string, maxPerWave: number) => string[];
|
|
627
|
-
planTaskAceiteWarnings: (planPath: string) => string[];
|
|
628
|
-
|
|
709
|
+
specSectionWarnings: (specPath: string, requiredHeadings: string[]) => string[];
|
|
710
|
+
planWaveWarningsFixed: (planPath: string, maxPerWave: number) => string[];
|
|
711
|
+
planTaskAceiteWarnings: (planPath: string) => string[];
|
|
712
|
+
buildExecutionRationality: (paths?: Record<string, string | null | undefined>) => ExecutionRationalitySummary;
|
|
713
|
+
executionRationalityWarningsFromSummary: (summary: ExecutionRationalitySummary) => string[];
|
|
714
|
+
verifyGapsWithoutSummaryWarning: (verifyPath: string, summaryPath: string) => string | null;
|
|
629
715
|
expandExecutionProfile: (profile: string) => Record<string, unknown>;
|
|
630
716
|
ALLOWED_CONFIG_KEYS: string[];
|
|
631
717
|
EXECUTION_PROFILES: string[];
|
|
@@ -685,12 +771,24 @@ export interface OxeSdk {
|
|
|
685
771
|
installNpmPlugin: (projectRoot: string, pkgName: string, version?: string) => { ok: boolean; path: string; error: string };
|
|
686
772
|
};
|
|
687
773
|
|
|
688
|
-
dashboard: {
|
|
689
|
-
loadDashboardContext: (projectRoot: string, opts?: { activeSession?: string | null }) => Record<string, unknown>;
|
|
690
|
-
savePlanReviewStatus: (projectRoot: string, input?: Record<string, unknown>) => Record<string, unknown>;
|
|
691
|
-
addPlanReviewComment: (projectRoot: string, input?: Record<string, unknown>) => Record<string, unknown>;
|
|
692
|
-
updatePlanReviewCommentStatus: (projectRoot: string, input?: Record<string, unknown>) => Record<string, unknown> | null;
|
|
693
|
-
};
|
|
774
|
+
dashboard: {
|
|
775
|
+
loadDashboardContext: (projectRoot: string, opts?: { activeSession?: string | null }) => Record<string, unknown>;
|
|
776
|
+
savePlanReviewStatus: (projectRoot: string, input?: Record<string, unknown>) => Record<string, unknown>;
|
|
777
|
+
addPlanReviewComment: (projectRoot: string, input?: Record<string, unknown>) => Record<string, unknown>;
|
|
778
|
+
updatePlanReviewCommentStatus: (projectRoot: string, input?: Record<string, unknown>) => Record<string, unknown> | null;
|
|
779
|
+
};
|
|
780
|
+
|
|
781
|
+
release: {
|
|
782
|
+
REQUIRED_RUNTIMES: string[];
|
|
783
|
+
WRAPPER_TARGETS: Array<Record<string, unknown>>;
|
|
784
|
+
releasePaths: (projectRoot: string) => Record<string, string>;
|
|
785
|
+
collectWrapperHashes: (projectRoot: string) => Record<string, unknown>;
|
|
786
|
+
loadRuntimeSmokeReport: (projectRoot: string) => RuntimeSmokeReport;
|
|
787
|
+
loadRecoveryFixtureReport: (projectRoot: string) => RuntimeSmokeReport;
|
|
788
|
+
loadMultiAgentSoakReport: (projectRoot: string) => RuntimeSmokeReport;
|
|
789
|
+
buildReleaseManifest: (projectRoot: string, options?: Record<string, unknown>) => ReleaseManifest;
|
|
790
|
+
checkReleaseConsistency: (projectRoot: string, options?: Record<string, unknown>) => ReleaseConsistencyResult;
|
|
791
|
+
};
|
|
694
792
|
|
|
695
793
|
context: ContextAPI;
|
|
696
794
|
runtimeSemantics: RuntimeSemanticsAPI;
|
package/oxe/templates/CONFIG.md
CHANGED
|
@@ -9,7 +9,7 @@ Copie `oxe/templates/config.template.json` para **`.oxe/config.json`** no seu pr
|
|
|
9
9
|
| `profile` | string | Profile de execução: `balanced` (padrão) \| `strict` \| `fast` \| `legacy`. Expande automaticamente outras keys — keys explícitas prevalecem. Ver tabela abaixo. |
|
|
10
10
|
| `discuss_before_plan` | boolean | Se `true`, o fluxo recomenda **`oxe:discuss`** entre spec e plan. |
|
|
11
11
|
| `verification_depth` | string | Profundidade da verificação: `standard` (padrão) \| `thorough` (ativa Camada 5 — validate-gaps automático) \| `quick` (skip camadas 3–4 e UAT). |
|
|
12
|
-
| `plan_confidence_threshold` | number | Limiar mínimo de confiança para o `execute` aceitar um `PLAN.md`. Padrão: `
|
|
12
|
+
| `plan_confidence_threshold` | number | Limiar mínimo de confiança para o `execute` aceitar um `PLAN.md`. Padrão canónico: `90`, com gate estrito (`Confiança` precisa ser **maior que** o limiar). Valores menores que 90 não reduzem esse gate. |
|
|
13
13
|
| `security_in_verify` | boolean | Se `true`, executa auditoria OWASP automaticamente no **verify** como **Camada 6** (produz `.oxe/SECURITY.md`). Achados P0 bloqueiam `verify_complete`. Padrão: `false`. |
|
|
14
14
|
| `after_verify_suggest_pr` | boolean | Se `true`, o workflow **verify** inclui checklist de PR no fim. |
|
|
15
15
|
| `after_verify_draft_commit` | boolean | Se `true`, o **verify** propõe rascunho de mensagem de commit alinhado aos critérios de aceite. |
|
|
@@ -16,7 +16,7 @@ updated: YYYY-MM-DD
|
|
|
16
16
|
- **Active run:** `.oxe/ACTIVE-RUN.json` ou artefato equivalente de sessão
|
|
17
17
|
- **Trace log:** `.oxe/OXE-EVENTS.ndjson` ou artefato equivalente de sessão
|
|
18
18
|
- **Autoavaliação do plano:** melhor=`sim|não` | confiança=`NN%`
|
|
19
|
-
- **Limiar de execução:**
|
|
19
|
+
- **Limiar de execução:** `>90%`
|
|
20
20
|
|
|
21
21
|
## Onda atual
|
|
22
22
|
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schema_version": "1",
|
|
3
|
+
"generated_at": "YYYY-MM-DDTHH:MM:SSZ",
|
|
4
|
+
"ready": false,
|
|
5
|
+
"critical_gaps": [],
|
|
6
|
+
"fixtures": [
|
|
7
|
+
{
|
|
8
|
+
"id": "FX-01",
|
|
9
|
+
"task_id": "T1",
|
|
10
|
+
"status": "ready",
|
|
11
|
+
"inputs": [
|
|
12
|
+
{
|
|
13
|
+
"kind": "payload",
|
|
14
|
+
"ref": ".oxe/investigations/fixtures/example-input.json",
|
|
15
|
+
"summary": "payload base para validar o fluxo"
|
|
16
|
+
}
|
|
17
|
+
],
|
|
18
|
+
"expected_outputs": [
|
|
19
|
+
{
|
|
20
|
+
"kind": "status",
|
|
21
|
+
"summary": "deve concluir sem erro e persistir o artefato esperado"
|
|
22
|
+
}
|
|
23
|
+
],
|
|
24
|
+
"expected_checks": [
|
|
25
|
+
"npm test -- example"
|
|
26
|
+
],
|
|
27
|
+
"critical_fields": [
|
|
28
|
+
"id",
|
|
29
|
+
"status"
|
|
30
|
+
],
|
|
31
|
+
"critical_gaps": []
|
|
32
|
+
}
|
|
33
|
+
]
|
|
34
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# OXE — Fixture Pack
|
|
2
|
+
|
|
3
|
+
> Fixtures mínimos para reduzir improviso em parsing, integração, transformação, migração e builders.
|
|
4
|
+
|
|
5
|
+
## Status
|
|
6
|
+
|
|
7
|
+
- **Status:** ready | not_ready | not_applicable
|
|
8
|
+
- **Critical gaps abertos:** nenhum | listar
|
|
9
|
+
|
|
10
|
+
## Fixtures
|
|
11
|
+
|
|
12
|
+
### FX-01 — T1
|
|
13
|
+
|
|
14
|
+
- **Task:** T1
|
|
15
|
+
- **Status:** ready | missing | not_applicable
|
|
16
|
+
- **Inputs:** payload, arquivo exemplo, query, blob ou mensagem
|
|
17
|
+
- **Expected outputs:** linha, evento, arquivo, rowset, status etc.
|
|
18
|
+
- **Expected checks:** `...`
|
|
19
|
+
- **Campos críticos / offsets:** ...
|
|
20
|
+
- **Smoke command:** `...`
|
|
21
|
+
- **Critical gaps:** nenhum | listar
|