oxe-cc 1.2.1 → 1.3.0
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-ask.md +2 -2
- package/.cursor/commands/oxe-capabilities.md +2 -2
- package/.cursor/commands/oxe-checkpoint.md +2 -2
- package/.cursor/commands/oxe-compact.md +2 -2
- package/.cursor/commands/oxe-dashboard.md +2 -2
- package/.cursor/commands/oxe-debug.md +2 -2
- package/.cursor/commands/oxe-discuss.md +2 -2
- package/.cursor/commands/oxe-execute.md +5 -2
- package/.cursor/commands/oxe-forensics.md +2 -2
- package/.cursor/commands/oxe-help.md +2 -2
- package/.cursor/commands/oxe-loop.md +2 -2
- package/.cursor/commands/oxe-milestone.md +2 -2
- package/.cursor/commands/oxe-next.md +2 -2
- package/.cursor/commands/oxe-obs.md +2 -2
- package/.cursor/commands/oxe-plan-agent.md +2 -2
- package/.cursor/commands/oxe-plan.md +2 -2
- package/.cursor/commands/oxe-project.md +2 -2
- package/.cursor/commands/oxe-quick.md +2 -2
- package/.cursor/commands/oxe-research.md +2 -2
- package/.cursor/commands/oxe-retro.md +2 -2
- package/.cursor/commands/oxe-review-pr.md +2 -2
- package/.cursor/commands/oxe-route.md +2 -2
- package/.cursor/commands/oxe-scan.md +2 -2
- package/.cursor/commands/oxe-security.md +2 -2
- package/.cursor/commands/oxe-session.md +2 -2
- package/.cursor/commands/oxe-ship.md +2 -2
- package/.cursor/commands/oxe-skill.md +2 -2
- package/.cursor/commands/oxe-spec.md +2 -2
- package/.cursor/commands/oxe-ui-review.md +2 -2
- package/.cursor/commands/oxe-ui-spec.md +2 -2
- package/.cursor/commands/oxe-update.md +2 -2
- package/.cursor/commands/oxe-validate-gaps.md +2 -2
- package/.cursor/commands/oxe-verify.md +5 -2
- package/.cursor/commands/oxe-workstream.md +2 -2
- package/.cursor/commands/oxe.md +2 -2
- package/.github/copilot-instructions.md +13 -13
- package/.github/prompts/oxe-ask.prompt.md +2 -2
- package/.github/prompts/oxe-capabilities.prompt.md +2 -2
- package/.github/prompts/oxe-checkpoint.prompt.md +2 -2
- package/.github/prompts/oxe-compact.prompt.md +2 -2
- package/.github/prompts/oxe-dashboard.prompt.md +2 -2
- package/.github/prompts/oxe-debug.prompt.md +2 -2
- package/.github/prompts/oxe-discuss.prompt.md +2 -2
- package/.github/prompts/oxe-execute.prompt.md +5 -2
- package/.github/prompts/oxe-forensics.prompt.md +2 -2
- package/.github/prompts/oxe-help.prompt.md +2 -2
- package/.github/prompts/oxe-loop.prompt.md +2 -2
- package/.github/prompts/oxe-milestone.prompt.md +2 -2
- package/.github/prompts/oxe-next.prompt.md +2 -2
- package/.github/prompts/oxe-obs.prompt.md +2 -2
- package/.github/prompts/oxe-plan-agent.prompt.md +2 -2
- package/.github/prompts/oxe-plan.prompt.md +2 -2
- package/.github/prompts/oxe-project.prompt.md +2 -2
- package/.github/prompts/oxe-quick.prompt.md +2 -2
- package/.github/prompts/oxe-research.prompt.md +2 -2
- package/.github/prompts/oxe-retro.prompt.md +2 -2
- package/.github/prompts/oxe-review-pr.prompt.md +2 -2
- package/.github/prompts/oxe-route.prompt.md +2 -2
- package/.github/prompts/oxe-scan.prompt.md +2 -2
- package/.github/prompts/oxe-security.prompt.md +2 -2
- package/.github/prompts/oxe-session.prompt.md +2 -2
- package/.github/prompts/oxe-ship.prompt.md +2 -2
- package/.github/prompts/oxe-skill.prompt.md +2 -2
- package/.github/prompts/oxe-spec.prompt.md +2 -2
- package/.github/prompts/oxe-ui-review.prompt.md +2 -2
- package/.github/prompts/oxe-ui-spec.prompt.md +2 -2
- package/.github/prompts/oxe-update.prompt.md +2 -2
- package/.github/prompts/oxe-validate-gaps.prompt.md +2 -2
- package/.github/prompts/oxe-verify.prompt.md +5 -2
- package/.github/prompts/oxe-workstream.prompt.md +2 -2
- package/.github/prompts/oxe.prompt.md +2 -2
- package/CHANGELOG.md +52 -17
- package/README.md +610 -551
- package/bin/banner.txt +1 -1
- package/bin/lib/oxe-agent-install.cjs +69 -69
- package/bin/lib/oxe-azure.cjs +1445 -1445
- package/bin/lib/oxe-context-engine.cjs +867 -867
- package/bin/lib/oxe-dashboard.cjs +76 -28
- package/bin/lib/oxe-operational.cjs +2144 -1340
- package/bin/lib/oxe-project-health.cjs +483 -1
- package/bin/lib/oxe-runtime-semantics.cjs +12 -0
- package/bin/oxe-cc.js +554 -152
- package/commands/oxe/ask.md +2 -2
- package/commands/oxe/capabilities.md +2 -2
- package/commands/oxe/checkpoint.md +2 -2
- package/commands/oxe/compact.md +2 -2
- package/commands/oxe/dashboard.md +2 -2
- package/commands/oxe/debug.md +2 -2
- package/commands/oxe/discuss.md +2 -2
- package/commands/oxe/execute.md +5 -2
- package/commands/oxe/forensics.md +2 -2
- package/commands/oxe/help.md +2 -2
- package/commands/oxe/loop.md +2 -2
- package/commands/oxe/milestone.md +2 -2
- package/commands/oxe/next.md +2 -2
- package/commands/oxe/obs.md +2 -2
- package/commands/oxe/oxe.md +2 -2
- package/commands/oxe/plan-agent.md +2 -2
- package/commands/oxe/plan.md +2 -2
- package/commands/oxe/project.md +2 -2
- package/commands/oxe/quick.md +2 -2
- package/commands/oxe/research.md +2 -2
- package/commands/oxe/retro.md +2 -2
- package/commands/oxe/review-pr.md +2 -2
- package/commands/oxe/route.md +2 -2
- package/commands/oxe/scan.md +2 -2
- package/commands/oxe/security.md +2 -2
- package/commands/oxe/session.md +2 -2
- package/commands/oxe/ship.md +2 -2
- package/commands/oxe/skill.md +2 -2
- package/commands/oxe/spec.md +2 -2
- package/commands/oxe/ui-review.md +2 -2
- package/commands/oxe/ui-spec.md +2 -2
- package/commands/oxe/update.md +2 -2
- package/commands/oxe/validate-gaps.md +2 -2
- package/commands/oxe/verify.md +5 -2
- package/commands/oxe/workstream.md +2 -2
- package/lib/runtime/delivery/branch-manager.d.ts +1 -0
- package/lib/runtime/delivery/branch-manager.js +7 -0
- package/lib/runtime/delivery/ci-checks.js +34 -1
- package/lib/runtime/delivery/delivery-records.d.ts +34 -0
- package/lib/runtime/delivery/delivery-records.js +48 -0
- package/lib/runtime/delivery/index.d.ts +1 -0
- package/lib/runtime/delivery/index.js +1 -0
- package/lib/runtime/delivery/promotion-pipeline.d.ts +26 -2
- package/lib/runtime/delivery/promotion-pipeline.js +111 -14
- package/lib/runtime/gate/gate-manager.d.ts +41 -0
- package/lib/runtime/gate/gate-manager.js +108 -1
- package/lib/runtime/index.d.ts +2 -2
- package/lib/runtime/index.js +3 -1
- package/lib/runtime/models/gate-decision.d.ts +4 -1
- package/lib/runtime/models/workspace.d.ts +3 -0
- package/lib/runtime/plugins/capability-adapter.d.ts +12 -0
- package/lib/runtime/plugins/capability-adapter.js +204 -0
- package/lib/runtime/plugins/capability-matrix.d.ts +5 -0
- package/lib/runtime/plugins/capability-matrix.js +48 -17
- package/lib/runtime/plugins/index.d.ts +1 -0
- package/lib/runtime/plugins/index.js +1 -0
- package/lib/runtime/plugins/plugin-abi.d.ts +2 -0
- package/lib/runtime/plugins/plugin-manifest.d.ts +1 -1
- package/lib/runtime/plugins/plugin-manifest.js +6 -2
- package/lib/runtime/plugins/plugin-registry.d.ts +46 -0
- package/lib/runtime/plugins/plugin-registry.js +79 -2
- package/lib/runtime/policy/policy-engine.d.ts +19 -0
- package/lib/runtime/policy/policy-engine.js +76 -4
- package/lib/runtime/projection/projection-engine.d.ts +9 -1
- package/lib/runtime/projection/projection-engine.js +73 -3
- package/lib/runtime/scheduler/multi-agent-coordinator.d.ts +43 -1
- package/lib/runtime/scheduler/multi-agent-coordinator.js +151 -39
- package/lib/runtime/scheduler/run-journal.d.ts +1 -1
- package/lib/runtime/scheduler/scheduler.d.ts +19 -1
- package/lib/runtime/scheduler/scheduler.js +258 -13
- package/lib/runtime/verification/verification-compiler.d.ts +43 -0
- package/lib/runtime/verification/verification-compiler.js +137 -0
- package/lib/runtime/verification/verification-manifest.d.ts +9 -0
- package/lib/runtime/verification/verification-manifest.js +56 -6
- package/lib/runtime/workspace/strategies/ephemeral-container.d.ts +1 -0
- package/lib/runtime/workspace/strategies/ephemeral-container.js +4 -0
- package/lib/runtime/workspace/strategies/git-worktree.d.ts +1 -0
- package/lib/runtime/workspace/strategies/git-worktree.js +2 -0
- package/lib/runtime/workspace/strategies/inplace.d.ts +1 -0
- package/lib/runtime/workspace/strategies/inplace.js +2 -0
- package/lib/runtime/workspace/workspace-manager.d.ts +2 -1
- package/lib/sdk/README.md +9 -9
- package/lib/sdk/index.cjs +33 -24
- package/lib/sdk/index.d.ts +149 -14
- package/oxe/templates/ACTIVE-RUN.template.json +32 -32
- package/oxe/templates/CAPABILITIES.template.md +7 -7
- package/oxe/templates/CAPABILITY.template.md +45 -45
- package/oxe/templates/CHECKPOINTS.template.md +7 -7
- package/oxe/templates/EXECUTION-RUNTIME.template.md +68 -68
- package/oxe/templates/HYPOTHESES.template.md +33 -33
- package/oxe/templates/LESSONS-METRICS.template.json +13 -13
- package/oxe/templates/NOTES.template.md +16 -16
- package/oxe/templates/PLAN-REVIEW.template.md +31 -31
- package/oxe/templates/SESSION.template.md +34 -34
- package/oxe/templates/SKILL.template.md +26 -26
- package/oxe/templates/STATE.md +55 -55
- package/oxe/templates/WORKFLOW_AUTHORING.md +18 -18
- package/oxe/workflows/ask.md +96 -96
- package/oxe/workflows/capabilities.md +25 -25
- package/oxe/workflows/dashboard.md +33 -33
- package/oxe/workflows/discuss.md +12 -12
- package/oxe/workflows/execute.md +14 -0
- package/oxe/workflows/help.md +352 -352
- package/oxe/workflows/next.md +22 -22
- package/oxe/workflows/oxe.md +6 -6
- package/oxe/workflows/plan-agent.md +9 -9
- package/oxe/workflows/quick.md +10 -10
- package/oxe/workflows/references/reasoning-discovery.md +28 -28
- package/oxe/workflows/references/reasoning-execution.md +29 -29
- package/oxe/workflows/references/reasoning-planning.md +32 -32
- package/oxe/workflows/references/reasoning-review.md +29 -29
- package/oxe/workflows/references/reasoning-status.md +24 -24
- package/oxe/workflows/references/robustness-elevation.md +295 -295
- package/oxe/workflows/references/workflow-runtime-contracts.json +952 -930
- package/oxe/workflows/route.md +16 -16
- package/oxe/workflows/session.md +213 -213
- package/oxe/workflows/ship.md +142 -142
- package/oxe/workflows/skill.md +44 -44
- package/oxe/workflows/ui-review.md +36 -36
- package/oxe/workflows/verify-audit.md +73 -73
- package/oxe/workflows/verify.md +10 -0
- package/package.json +92 -92
- package/packages/runtime/package.json +17 -17
- package/packages/runtime/src/audit/audit-trail.ts +243 -243
- package/packages/runtime/src/audit/index.ts +2 -2
- package/packages/runtime/src/audit/policy-pack.ts +62 -62
- package/packages/runtime/src/compiler/graph-compiler.ts +245 -245
- package/packages/runtime/src/compiler/index.ts +1 -1
- package/packages/runtime/src/context/context-pack-builder.ts +259 -259
- package/packages/runtime/src/context/context-pack-store.ts +197 -197
- package/packages/runtime/src/context/context-profiles.ts +60 -60
- package/packages/runtime/src/context/index.ts +3 -3
- package/packages/runtime/src/decision/decision-engine.ts +174 -174
- package/packages/runtime/src/decision/decision-memo.ts +211 -211
- package/packages/runtime/src/decision/index.ts +2 -2
- package/packages/runtime/src/delivery/branch-manager.ts +91 -84
- package/packages/runtime/src/delivery/ci-checks.ts +285 -252
- package/packages/runtime/src/delivery/delivery-records.ts +75 -0
- package/packages/runtime/src/delivery/index.ts +5 -4
- package/packages/runtime/src/delivery/pr-manager.ts +112 -112
- package/packages/runtime/src/delivery/promotion-pipeline.ts +334 -180
- package/packages/runtime/src/events/bus.ts +92 -92
- package/packages/runtime/src/events/catalog.ts +29 -29
- package/packages/runtime/src/events/envelope.ts +14 -14
- package/packages/runtime/src/events/index.ts +3 -3
- package/packages/runtime/src/evidence/evidence-store.ts +130 -130
- package/packages/runtime/src/evidence/index.ts +1 -1
- package/packages/runtime/src/gate/gate-manager.ts +289 -137
- package/packages/runtime/src/gate/index.ts +1 -1
- package/packages/runtime/src/index.ts +41 -37
- package/packages/runtime/src/models/attempt.ts +19 -19
- package/packages/runtime/src/models/evidence.ts +21 -21
- package/packages/runtime/src/models/gate-decision.ts +25 -21
- package/packages/runtime/src/models/index.ts +8 -8
- package/packages/runtime/src/models/run.ts +24 -24
- package/packages/runtime/src/models/session.ts +11 -11
- package/packages/runtime/src/models/verification-result.ts +10 -10
- package/packages/runtime/src/models/work-item.ts +25 -25
- package/packages/runtime/src/models/workspace.ts +31 -28
- package/packages/runtime/src/plugins/capability-adapter.ts +206 -0
- package/packages/runtime/src/plugins/capability-matrix.ts +126 -83
- package/packages/runtime/src/plugins/index.ts +5 -4
- package/packages/runtime/src/plugins/plugin-abi.ts +97 -95
- package/packages/runtime/src/plugins/plugin-manifest.ts +118 -113
- package/packages/runtime/src/plugins/plugin-registry.ts +232 -124
- package/packages/runtime/src/policy/index.ts +1 -1
- package/packages/runtime/src/policy/policy-engine.ts +330 -244
- package/packages/runtime/src/projection/index.ts +1 -1
- package/packages/runtime/src/projection/projection-engine.ts +328 -249
- package/packages/runtime/src/reducers/debug-reducer.ts +36 -36
- package/packages/runtime/src/reducers/index.ts +2 -2
- package/packages/runtime/src/reducers/run-state-reducer.ts +269 -269
- package/packages/runtime/src/scheduler/agent-registry.ts +132 -132
- package/packages/runtime/src/scheduler/agent-roles.ts +109 -109
- package/packages/runtime/src/scheduler/index.ts +4 -4
- package/packages/runtime/src/scheduler/multi-agent-coordinator.ts +521 -333
- package/packages/runtime/src/scheduler/run-journal.ts +62 -62
- package/packages/runtime/src/scheduler/scheduler.ts +722 -441
- package/packages/runtime/src/verification/index.ts +2 -2
- package/packages/runtime/src/verification/verification-compiler.ts +436 -225
- package/packages/runtime/src/verification/verification-manifest.ts +252 -192
- package/packages/runtime/src/workspace/index.ts +5 -5
- package/packages/runtime/src/workspace/strategies/ephemeral-container.ts +126 -121
- package/packages/runtime/src/workspace/strategies/git-worktree.ts +79 -77
- package/packages/runtime/src/workspace/strategies/inplace.ts +38 -35
- package/packages/runtime/src/workspace/workspace-manager.ts +16 -15
- package/packages/runtime/tsconfig.json +17 -17
- package/vscode-extension/.vscodeignore +7 -7
- package/vscode-extension/oxe-agents-1.0.0.vsix +0 -0
- package/vscode-extension/package.json +185 -185
- package/vscode-extension/src/extension.js +310 -310
- package/vscode-extension/src/shared/contextLoader.js +137 -137
- package/vscode-extension/src/shared/contractBuilder.js +159 -159
- package/vscode-extension/src/shared/stateReader.js +101 -101
|
@@ -1,26 +1,86 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
2
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
6
|
exports.MultiAgentCoordinator = void 0;
|
|
7
|
+
exports.multiAgentStatePath = multiAgentStatePath;
|
|
8
|
+
exports.loadMultiAgentState = loadMultiAgentState;
|
|
9
|
+
const fs_1 = __importDefault(require("fs"));
|
|
10
|
+
const path_1 = __importDefault(require("path"));
|
|
4
11
|
const bus_1 = require("../events/bus");
|
|
5
12
|
const scheduler_1 = require("./scheduler");
|
|
6
13
|
const agent_roles_1 = require("./agent-roles");
|
|
14
|
+
function ensureRunDir(projectRoot, runId) {
|
|
15
|
+
const dir = path_1.default.join(projectRoot, '.oxe', 'runs', runId);
|
|
16
|
+
fs_1.default.mkdirSync(dir, { recursive: true });
|
|
17
|
+
return dir;
|
|
18
|
+
}
|
|
19
|
+
function persistMultiAgentArtifacts(projectRoot, runId, state, handoffs = [], arbitrationResults = []) {
|
|
20
|
+
const runDir = ensureRunDir(projectRoot, runId);
|
|
21
|
+
fs_1.default.writeFileSync(path_1.default.join(runDir, 'multi-agent-state.json'), JSON.stringify(state, null, 2), 'utf8');
|
|
22
|
+
fs_1.default.writeFileSync(path_1.default.join(runDir, 'handoffs.json'), JSON.stringify(handoffs, null, 2), 'utf8');
|
|
23
|
+
fs_1.default.writeFileSync(path_1.default.join(runDir, 'arbitration-results.json'), JSON.stringify(arbitrationResults, null, 2), 'utf8');
|
|
24
|
+
}
|
|
25
|
+
function ensureIsolatedAgents(agents) {
|
|
26
|
+
const shared = agents.filter((agent) => agent.workspaceManager.isolation_level !== 'isolated');
|
|
27
|
+
if (shared.length === 0)
|
|
28
|
+
return;
|
|
29
|
+
const ids = shared.map((agent) => `${agent.id}:${agent.workspaceManager.isolation_level}`).join(', ');
|
|
30
|
+
throw new Error(`Multi-agent requires isolated workspaces. Invalid agents: ${ids}`);
|
|
31
|
+
}
|
|
32
|
+
function buildOwnership(agents, partitions) {
|
|
33
|
+
const ownership = [];
|
|
34
|
+
for (let idx = 0; idx < agents.length; idx += 1) {
|
|
35
|
+
for (const workItemId of partitions[idx] ?? []) {
|
|
36
|
+
ownership.push({
|
|
37
|
+
work_item_id: workItemId,
|
|
38
|
+
owner_agent_id: agents[idx].id,
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
return ownership;
|
|
43
|
+
}
|
|
44
|
+
function makeState(mode, runId, agents, partitions, agentResults, completed, failed, blocked, orphanReassignments) {
|
|
45
|
+
return {
|
|
46
|
+
run_id: runId,
|
|
47
|
+
mode,
|
|
48
|
+
workspace_isolation_required: 'isolated',
|
|
49
|
+
workspace_isolation_enforced: true,
|
|
50
|
+
agent_count: agents.length,
|
|
51
|
+
ownership: buildOwnership(agents, partitions),
|
|
52
|
+
completed,
|
|
53
|
+
failed,
|
|
54
|
+
blocked,
|
|
55
|
+
agent_results: agents.map((agent, idx) => {
|
|
56
|
+
const result = agentResults.find((entry) => entry.agent_id === agent.id);
|
|
57
|
+
return {
|
|
58
|
+
agent_id: agent.id,
|
|
59
|
+
isolation_level: agent.workspaceManager.isolation_level,
|
|
60
|
+
assigned_task_ids: partitions[idx] ?? agent.assignedTaskIds ?? [],
|
|
61
|
+
completed: result?.completed ?? [],
|
|
62
|
+
failed: result?.failed ?? [],
|
|
63
|
+
};
|
|
64
|
+
}),
|
|
65
|
+
orphan_reassignments: orphanReassignments,
|
|
66
|
+
updated_at: new Date().toISOString(),
|
|
67
|
+
};
|
|
68
|
+
}
|
|
7
69
|
// ─── Parallel mode ───────────────────────────────────────────────────────────
|
|
8
|
-
// Tasks are partitioned across agents. Each agent runs its own Scheduler
|
|
9
|
-
// on a sub-graph. Results are merged.
|
|
10
70
|
async function runParallel(graph, opts) {
|
|
11
71
|
const { agents, projectRoot, sessionId, runId } = opts;
|
|
12
|
-
|
|
13
|
-
const partitions = agents.map((
|
|
14
|
-
if (partitions.every((
|
|
72
|
+
ensureIsolatedAgents(agents);
|
|
73
|
+
const partitions = agents.map((agent) => [...(agent.assignedTaskIds ?? [])]);
|
|
74
|
+
if (partitions.every((partition) => partition.length === 0)) {
|
|
15
75
|
const allIds = [...graph.nodes.keys()];
|
|
16
|
-
allIds.forEach((id,
|
|
17
|
-
partitions[
|
|
76
|
+
allIds.forEach((id, index) => {
|
|
77
|
+
partitions[index % agents.length].push(id);
|
|
18
78
|
});
|
|
19
79
|
}
|
|
20
80
|
(0, bus_1.appendEvent)(projectRoot, sessionId, {
|
|
21
81
|
type: 'RunStarted',
|
|
22
82
|
run_id: runId,
|
|
23
|
-
payload: { mode: 'parallel', agent_count: agents.length },
|
|
83
|
+
payload: { mode: 'parallel', agent_count: agents.length, isolation_level: 'isolated' },
|
|
24
84
|
});
|
|
25
85
|
const agentResults = await Promise.all(agents.map(async (agent, idx) => {
|
|
26
86
|
const subGraph = subGraphFor(graph, partitions[idx]);
|
|
@@ -39,35 +99,49 @@ async function runParallel(graph, opts) {
|
|
|
39
99
|
const result = await scheduler.run(subGraph, ctx);
|
|
40
100
|
return { agent_id: agent.id, completed: result.completed, failed: result.failed };
|
|
41
101
|
}));
|
|
42
|
-
const completed = agentResults.flatMap((
|
|
43
|
-
const failed = agentResults.flatMap((
|
|
102
|
+
const completed = agentResults.flatMap((result) => result.completed);
|
|
103
|
+
const failed = agentResults.flatMap((result) => result.failed);
|
|
104
|
+
const blocked = [];
|
|
105
|
+
const orphanReassignments = [];
|
|
106
|
+
const state = makeState('parallel', runId, agents, partitions, agentResults, completed, failed, blocked, orphanReassignments);
|
|
107
|
+
persistMultiAgentArtifacts(projectRoot, runId, state);
|
|
44
108
|
(0, bus_1.appendEvent)(projectRoot, sessionId, {
|
|
45
109
|
type: 'RunCompleted',
|
|
46
110
|
run_id: runId,
|
|
47
111
|
payload: { mode: 'parallel', completed: completed.length, failed: failed.length },
|
|
48
112
|
});
|
|
49
|
-
return {
|
|
113
|
+
return {
|
|
114
|
+
mode: 'parallel',
|
|
115
|
+
run_id: runId,
|
|
116
|
+
completed,
|
|
117
|
+
failed,
|
|
118
|
+
blocked,
|
|
119
|
+
agent_results: agentResults,
|
|
120
|
+
arbitration_results: [],
|
|
121
|
+
state,
|
|
122
|
+
};
|
|
50
123
|
}
|
|
51
124
|
// ─── Competitive mode ────────────────────────────────────────────────────────
|
|
52
|
-
// Two agents attempt the same task. First success wins; the loser's workspace
|
|
53
|
-
// is disposed. Requires exactly 2 agents.
|
|
54
125
|
async function runCompetitive(graph, opts) {
|
|
55
126
|
if (opts.agents.length < 2) {
|
|
56
127
|
throw new Error('Competitive mode requires at least 2 agents');
|
|
57
128
|
}
|
|
129
|
+
ensureIsolatedAgents(opts.agents);
|
|
58
130
|
const [agentA, agentB] = opts.agents;
|
|
59
131
|
const { projectRoot, sessionId, runId } = opts;
|
|
60
132
|
(0, bus_1.appendEvent)(projectRoot, sessionId, {
|
|
61
133
|
type: 'RunStarted',
|
|
62
134
|
run_id: runId,
|
|
63
|
-
payload: { mode: 'competitive' },
|
|
135
|
+
payload: { mode: 'competitive', isolation_level: 'isolated' },
|
|
64
136
|
});
|
|
65
137
|
const completed = [];
|
|
66
138
|
const failed = [];
|
|
139
|
+
const blocked = [];
|
|
140
|
+
const arbitrationResults = [];
|
|
67
141
|
for (const wave of graph.waves) {
|
|
68
142
|
for (const nodeId of wave.node_ids) {
|
|
69
143
|
const node = graph.nodes.get(nodeId);
|
|
70
|
-
const result = await competeTwoAgents(nodeId, node, agentA, agentB, opts);
|
|
144
|
+
const result = await competeTwoAgents(nodeId, node, agentA, agentB, opts, arbitrationResults);
|
|
71
145
|
if (result.success)
|
|
72
146
|
completed.push(nodeId);
|
|
73
147
|
else
|
|
@@ -78,6 +152,12 @@ async function runCompetitive(graph, opts) {
|
|
|
78
152
|
if (failed.length > 0)
|
|
79
153
|
break;
|
|
80
154
|
}
|
|
155
|
+
const partitions = [Array.from(graph.nodes.keys()), Array.from(graph.nodes.keys())];
|
|
156
|
+
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, []);
|
|
160
|
+
persistMultiAgentArtifacts(projectRoot, runId, state, [], arbitrationResults);
|
|
81
161
|
(0, bus_1.appendEvent)(projectRoot, sessionId, {
|
|
82
162
|
type: 'RunCompleted',
|
|
83
163
|
run_id: runId,
|
|
@@ -88,14 +168,16 @@ async function runCompetitive(graph, opts) {
|
|
|
88
168
|
run_id: runId,
|
|
89
169
|
completed,
|
|
90
170
|
failed,
|
|
91
|
-
blocked
|
|
171
|
+
blocked,
|
|
92
172
|
agent_results: [
|
|
93
173
|
{ agent_id: agentA.id, completed, failed },
|
|
94
174
|
{ agent_id: agentB.id, completed: [], failed: [] },
|
|
95
175
|
],
|
|
176
|
+
arbitration_results: arbitrationResults,
|
|
177
|
+
state,
|
|
96
178
|
};
|
|
97
179
|
}
|
|
98
|
-
async function competeTwoAgents(nodeId, node, agentA, agentB, opts) {
|
|
180
|
+
async function competeTwoAgents(nodeId, node, agentA, agentB, opts, arbitrationResults) {
|
|
99
181
|
const { projectRoot, sessionId, runId } = opts;
|
|
100
182
|
const allocA = await agentA.workspaceManager.allocate({
|
|
101
183
|
work_item_id: nodeId, attempt_number: 1, strategy: node.workspace_strategy, mutation_scope: node.mutation_scope,
|
|
@@ -109,51 +191,58 @@ async function competeTwoAgents(nodeId, node, agentA, agentB, opts) {
|
|
|
109
191
|
work_item_id: nodeId,
|
|
110
192
|
payload: { mode: 'competitive', agents: [agentA.id, agentB.id] },
|
|
111
193
|
});
|
|
112
|
-
// Race both agents — first success wins
|
|
113
194
|
const [resultA, resultB] = await Promise.all([
|
|
114
|
-
agentA.executor.execute(node, allocA, runId, 1).catch((
|
|
115
|
-
success: false, failure_class: 'env', evidence: [], output: String(
|
|
195
|
+
agentA.executor.execute(node, allocA, runId, 1).catch((error) => ({
|
|
196
|
+
success: false, failure_class: 'env', evidence: [], output: String(error),
|
|
116
197
|
})),
|
|
117
|
-
agentB.executor.execute(node, allocB, runId, 1).catch((
|
|
118
|
-
success: false, failure_class: 'env', evidence: [], output: String(
|
|
198
|
+
agentB.executor.execute(node, allocB, runId, 1).catch((error) => ({
|
|
199
|
+
success: false, failure_class: 'env', evidence: [], output: String(error),
|
|
119
200
|
})),
|
|
120
201
|
]);
|
|
121
|
-
// Clean up both workspaces
|
|
122
202
|
await Promise.all([
|
|
123
203
|
agentA.workspaceManager.dispose(allocA.workspace_id).catch(() => { }),
|
|
124
204
|
agentB.workspaceManager.dispose(allocB.workspace_id).catch(() => { }),
|
|
125
205
|
]);
|
|
126
|
-
// Pick winner: prefer success; if both succeed, prefer A (primary agent)
|
|
127
206
|
const winner = resultA.success ? resultA : resultB.success ? resultB : resultA;
|
|
207
|
+
const winnerAgentId = resultA.success ? agentA.id : resultB.success ? agentB.id : agentA.id;
|
|
208
|
+
arbitrationResults.push({
|
|
209
|
+
work_item_id: nodeId,
|
|
210
|
+
mode: 'competitive',
|
|
211
|
+
winner_agent_id: winnerAgentId,
|
|
212
|
+
participant_agent_ids: [agentA.id, agentB.id],
|
|
213
|
+
success: winner.success,
|
|
214
|
+
failure_class: winner.failure_class,
|
|
215
|
+
evidence_count: winner.evidence.length,
|
|
216
|
+
recorded_at: new Date().toISOString(),
|
|
217
|
+
});
|
|
128
218
|
if (winner.success) {
|
|
129
|
-
(0, bus_1.appendEvent)(projectRoot, sessionId, { type: 'WorkItemCompleted', run_id: runId, work_item_id: nodeId, payload: { mode: 'competitive' } });
|
|
219
|
+
(0, bus_1.appendEvent)(projectRoot, sessionId, { type: 'WorkItemCompleted', run_id: runId, work_item_id: nodeId, payload: { mode: 'competitive', winner_agent_id: winnerAgentId } });
|
|
130
220
|
}
|
|
131
221
|
else {
|
|
132
|
-
(0, bus_1.appendEvent)(projectRoot, sessionId, { type: 'WorkItemBlocked', run_id: runId, work_item_id: nodeId, payload: { mode: 'competitive', failure_class: winner.failure_class } });
|
|
222
|
+
(0, bus_1.appendEvent)(projectRoot, sessionId, { type: 'WorkItemBlocked', run_id: runId, work_item_id: nodeId, payload: { mode: 'competitive', failure_class: winner.failure_class, winner_agent_id: winnerAgentId } });
|
|
133
223
|
}
|
|
134
224
|
return winner;
|
|
135
225
|
}
|
|
136
226
|
// ─── Cooperative mode ────────────────────────────────────────────────────────
|
|
137
|
-
// planner (agent[0]) does a dry-run to collect context, then hands off to
|
|
138
|
-
// executor (agent[1]) which performs the real run. Handoffs are recorded.
|
|
139
227
|
async function runCooperative(graph, opts) {
|
|
140
228
|
if (opts.agents.length < 2) {
|
|
141
229
|
throw new Error('Cooperative mode requires at least 2 agents');
|
|
142
230
|
}
|
|
231
|
+
ensureIsolatedAgents(opts.agents);
|
|
143
232
|
const [planner, executor] = opts.agents;
|
|
144
233
|
const { projectRoot, sessionId, runId } = opts;
|
|
145
234
|
const handoffs = [];
|
|
146
235
|
(0, bus_1.appendEvent)(projectRoot, sessionId, {
|
|
147
236
|
type: 'RunStarted',
|
|
148
237
|
run_id: runId,
|
|
149
|
-
payload: { mode: 'cooperative', planner: planner.id, executor: executor.id },
|
|
238
|
+
payload: { mode: 'cooperative', planner: planner.id, executor: executor.id, isolation_level: 'isolated' },
|
|
150
239
|
});
|
|
151
240
|
const completed = [];
|
|
152
241
|
const failed = [];
|
|
242
|
+
const blocked = [];
|
|
153
243
|
for (const wave of graph.waves) {
|
|
154
244
|
for (const nodeId of wave.node_ids) {
|
|
155
245
|
const node = graph.nodes.get(nodeId);
|
|
156
|
-
// Phase 1: planner allocates workspace + signals readiness (no output used)
|
|
157
246
|
const planAlloc = await planner.workspaceManager.allocate({
|
|
158
247
|
work_item_id: nodeId,
|
|
159
248
|
attempt_number: 1,
|
|
@@ -176,7 +265,6 @@ async function runCooperative(graph, opts) {
|
|
|
176
265
|
work_item_id: nodeId,
|
|
177
266
|
payload: { mode: 'cooperative', handoff_id: handoff.handoff_id },
|
|
178
267
|
});
|
|
179
|
-
// Phase 2: executor performs the real task
|
|
180
268
|
const execAlloc = await executor.workspaceManager.allocate({
|
|
181
269
|
work_item_id: nodeId,
|
|
182
270
|
attempt_number: 1,
|
|
@@ -187,8 +275,8 @@ async function runCooperative(graph, opts) {
|
|
|
187
275
|
try {
|
|
188
276
|
result = await executor.executor.execute(node, execAlloc, runId, 1);
|
|
189
277
|
}
|
|
190
|
-
catch (
|
|
191
|
-
result = { success: false, failure_class: 'env', evidence: [], output: String(
|
|
278
|
+
catch (error) {
|
|
279
|
+
result = { success: false, failure_class: 'env', evidence: [], output: String(error) };
|
|
192
280
|
}
|
|
193
281
|
await executor.workspaceManager.dispose(execAlloc.workspace_id).catch(() => { });
|
|
194
282
|
if (result.success) {
|
|
@@ -204,6 +292,12 @@ async function runCooperative(graph, opts) {
|
|
|
204
292
|
if (failed.length > 0)
|
|
205
293
|
break;
|
|
206
294
|
}
|
|
295
|
+
const partitions = [Array.from(graph.nodes.keys()), Array.from(graph.nodes.keys())];
|
|
296
|
+
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, []);
|
|
300
|
+
persistMultiAgentArtifacts(projectRoot, runId, state, handoffs, []);
|
|
207
301
|
(0, bus_1.appendEvent)(projectRoot, sessionId, {
|
|
208
302
|
type: 'RunCompleted',
|
|
209
303
|
run_id: runId,
|
|
@@ -214,12 +308,14 @@ async function runCooperative(graph, opts) {
|
|
|
214
308
|
run_id: runId,
|
|
215
309
|
completed,
|
|
216
310
|
failed,
|
|
217
|
-
blocked
|
|
311
|
+
blocked,
|
|
218
312
|
agent_results: [
|
|
219
313
|
{ agent_id: planner.id, completed: [], failed: [] },
|
|
220
314
|
{ agent_id: executor.id, completed, failed },
|
|
221
315
|
],
|
|
222
316
|
handoffs,
|
|
317
|
+
arbitration_results: [],
|
|
318
|
+
state,
|
|
223
319
|
};
|
|
224
320
|
}
|
|
225
321
|
// ─── Public API ──────────────────────────────────────────────────────────────
|
|
@@ -235,15 +331,31 @@ class MultiAgentCoordinator {
|
|
|
235
331
|
}
|
|
236
332
|
}
|
|
237
333
|
exports.MultiAgentCoordinator = MultiAgentCoordinator;
|
|
334
|
+
function multiAgentStatePath(projectRoot, runId) {
|
|
335
|
+
return path_1.default.join(projectRoot, '.oxe', 'runs', runId, 'multi-agent-state.json');
|
|
336
|
+
}
|
|
337
|
+
function loadMultiAgentState(projectRoot, runId) {
|
|
338
|
+
const statePath = multiAgentStatePath(projectRoot, runId);
|
|
339
|
+
if (!fs_1.default.existsSync(statePath))
|
|
340
|
+
return null;
|
|
341
|
+
try {
|
|
342
|
+
return JSON.parse(fs_1.default.readFileSync(statePath, 'utf8'));
|
|
343
|
+
}
|
|
344
|
+
catch {
|
|
345
|
+
return null;
|
|
346
|
+
}
|
|
347
|
+
}
|
|
238
348
|
// ─── Helpers ─────────────────────────────────────────────────────────────────
|
|
239
349
|
function subGraphFor(graph, nodeIds) {
|
|
240
350
|
const ids = new Set(nodeIds);
|
|
241
351
|
const nodes = new Map([...graph.nodes].filter(([id]) => ids.has(id)));
|
|
242
|
-
const edges = graph.edges.filter((
|
|
243
|
-
const waves = graph.waves
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
352
|
+
const edges = graph.edges.filter((edge) => ids.has(edge.from) && ids.has(edge.to));
|
|
353
|
+
const waves = graph.waves
|
|
354
|
+
.map((wave) => ({
|
|
355
|
+
wave_number: wave.wave_number,
|
|
356
|
+
node_ids: wave.node_ids.filter((id) => ids.has(id)),
|
|
357
|
+
}))
|
|
358
|
+
.filter((wave) => wave.node_ids.length > 0);
|
|
247
359
|
return {
|
|
248
360
|
nodes,
|
|
249
361
|
edges,
|
|
@@ -9,7 +9,7 @@ export interface RunJournal {
|
|
|
9
9
|
blocked_work_items: string[];
|
|
10
10
|
pending_gates: string[];
|
|
11
11
|
replay_cursor: string | null;
|
|
12
|
-
scheduler_state: 'running' | 'paused' | 'cancelled' | 'completed';
|
|
12
|
+
scheduler_state: 'running' | 'paused' | 'cancelled' | 'completed' | 'blocked';
|
|
13
13
|
partial_result: Omit<RunResult, 'status'> | null;
|
|
14
14
|
}
|
|
15
15
|
export declare function saveJournal(projectRoot: string, runId: string, journal: RunJournal): void;
|
|
@@ -2,6 +2,11 @@ import type { OxeEvent } from '../events/envelope';
|
|
|
2
2
|
import type { ExecutionGraph, GraphNode } from '../compiler/graph-compiler';
|
|
3
3
|
import type { WorkspaceManager } from '../workspace/workspace-manager';
|
|
4
4
|
import type { WorkspaceLease } from '../models/workspace';
|
|
5
|
+
import type { GateManager } from '../gate/gate-manager';
|
|
6
|
+
import type { PolicyEngine } from '../policy/policy-engine';
|
|
7
|
+
import type { PluginRegistry } from '../plugins/plugin-registry';
|
|
8
|
+
import type { AuditTrail } from '../audit/audit-trail';
|
|
9
|
+
import type { RunQuota } from '../audit/audit-trail';
|
|
5
10
|
import type { RunJournal } from './run-journal';
|
|
6
11
|
export interface TaskResult {
|
|
7
12
|
success: boolean;
|
|
@@ -18,14 +23,21 @@ export interface SchedulerContext {
|
|
|
18
23
|
runId: string;
|
|
19
24
|
executor: TaskExecutor;
|
|
20
25
|
workspaceManager: WorkspaceManager;
|
|
26
|
+
gateManager?: GateManager;
|
|
27
|
+
policyEngine?: PolicyEngine;
|
|
28
|
+
pluginRegistry?: PluginRegistry;
|
|
29
|
+
auditTrail?: AuditTrail;
|
|
30
|
+
quota?: RunQuota;
|
|
31
|
+
policyActor?: string;
|
|
21
32
|
onEvent?: (event: OxeEvent) => void;
|
|
22
33
|
}
|
|
23
34
|
export interface RunResult {
|
|
24
35
|
run_id: string;
|
|
25
|
-
status: 'completed' | 'failed' | 'cancelled' | 'paused';
|
|
36
|
+
status: 'completed' | 'failed' | 'blocked' | 'cancelled' | 'paused';
|
|
26
37
|
completed: string[];
|
|
27
38
|
failed: string[];
|
|
28
39
|
blocked: string[];
|
|
40
|
+
pending_gates?: string[];
|
|
29
41
|
}
|
|
30
42
|
export declare class Scheduler {
|
|
31
43
|
private cancelled;
|
|
@@ -45,5 +57,11 @@ export declare class Scheduler {
|
|
|
45
57
|
cancel(): void;
|
|
46
58
|
getJournal(): RunJournal | null;
|
|
47
59
|
static loadJournal(projectRoot: string, runId: string): RunJournal | null;
|
|
60
|
+
private executeNode;
|
|
61
|
+
private evaluatePolicyForNode;
|
|
62
|
+
private requestGateForNode;
|
|
63
|
+
private blockNode;
|
|
64
|
+
private consumeQuotaForNode;
|
|
65
|
+
private consumeRetryQuota;
|
|
48
66
|
private emit;
|
|
49
67
|
}
|