@voybio/ace-swarm 0.2.5 → 2.4.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/CHANGELOG.md +11 -1
- package/README.md +20 -13
- package/assets/agent-state/EVIDENCE_LOG.md +1 -1
- package/assets/agent-state/MODULES/roles/capability-framework.json +41 -0
- package/assets/agent-state/MODULES/roles/capability-git.json +33 -0
- package/assets/agent-state/MODULES/roles/capability-safety.json +37 -0
- package/assets/agent-state/MODULES/schemas/ACE_RUNTIME_PROFILE.schema.json +21 -0
- package/assets/agent-state/MODULES/schemas/RUNTIME_EXECUTOR_SESSION_REGISTRY.schema.json +43 -0
- package/assets/agent-state/MODULES/schemas/WORKSPACE_SESSION_REGISTRY.schema.json +11 -0
- package/assets/agent-state/STATUS.md +2 -2
- package/assets/scripts/ace-hook-dispatch.mjs +70 -6
- package/assets/scripts/render-mcp-configs.sh +19 -5
- package/dist/ace-context.js +22 -1
- package/dist/ace-server-instructions.js +3 -3
- package/dist/ace-state-resolver.js +5 -3
- package/dist/astgrep-index.d.ts +9 -1
- package/dist/astgrep-index.js +14 -3
- package/dist/cli.js +27 -20
- package/dist/handoff-registry.js +5 -5
- package/dist/helpers/artifacts.d.ts +19 -0
- package/dist/helpers/artifacts.js +152 -0
- package/dist/helpers/bootstrap.d.ts +24 -0
- package/dist/helpers/bootstrap.js +894 -0
- package/dist/helpers/constants.d.ts +53 -0
- package/dist/helpers/constants.js +288 -0
- package/dist/helpers/drift.d.ts +13 -0
- package/dist/helpers/drift.js +45 -0
- package/dist/helpers/path-utils.d.ts +17 -0
- package/dist/helpers/path-utils.js +104 -0
- package/dist/helpers/store-resolution.d.ts +19 -0
- package/dist/helpers/store-resolution.js +301 -0
- package/dist/helpers/workspace-root.d.ts +3 -0
- package/dist/helpers/workspace-root.js +80 -0
- package/dist/helpers.d.ts +8 -125
- package/dist/helpers.js +8 -1768
- package/dist/job-scheduler.js +3 -3
- package/dist/local-model-runtime.js +12 -1
- package/dist/model-bridge.d.ts +7 -0
- package/dist/model-bridge.js +75 -5
- package/dist/orchestrator-supervisor.d.ts +14 -0
- package/dist/orchestrator-supervisor.js +72 -1
- package/dist/run-ledger.js +3 -3
- package/dist/runtime-command.d.ts +8 -0
- package/dist/runtime-command.js +38 -6
- package/dist/runtime-executor.d.ts +14 -0
- package/dist/runtime-executor.js +669 -171
- package/dist/runtime-profile.d.ts +32 -0
- package/dist/runtime-profile.js +89 -13
- package/dist/runtime-tool-specs.d.ts +21 -0
- package/dist/runtime-tool-specs.js +78 -3
- package/dist/safe-edit.d.ts +7 -0
- package/dist/safe-edit.js +163 -37
- package/dist/schemas.js +19 -0
- package/dist/shared.d.ts +2 -2
- package/dist/status-events.js +9 -6
- package/dist/store/ace-packed-store.d.ts +3 -2
- package/dist/store/ace-packed-store.js +188 -110
- package/dist/store/bootstrap-store.d.ts +1 -1
- package/dist/store/bootstrap-store.js +94 -81
- package/dist/store/cache-workspace.js +11 -5
- package/dist/store/materializers/context-snapshot-materializer.js +6 -2
- package/dist/store/materializers/hook-context-materializer.d.ts +6 -9
- package/dist/store/materializers/hook-context-materializer.js +11 -21
- package/dist/store/materializers/host-file-materializer.js +6 -0
- package/dist/store/materializers/projection-manager.d.ts +0 -1
- package/dist/store/materializers/projection-manager.js +5 -13
- package/dist/store/materializers/scheduler-projection-materializer.js +1 -1
- package/dist/store/materializers/vericify-projector.d.ts +7 -7
- package/dist/store/materializers/vericify-projector.js +11 -11
- package/dist/store/repositories/local-model-runtime-repository.d.ts +120 -3
- package/dist/store/repositories/local-model-runtime-repository.js +242 -6
- package/dist/store/skills-install.d.ts +4 -0
- package/dist/store/skills-install.js +21 -12
- package/dist/store/state-reader.d.ts +2 -0
- package/dist/store/state-reader.js +20 -0
- package/dist/store/store-artifacts.d.ts +7 -0
- package/dist/store/store-artifacts.js +27 -1
- package/dist/store/store-authority-audit.d.ts +18 -1
- package/dist/store/store-authority-audit.js +115 -5
- package/dist/store/store-snapshot.d.ts +3 -0
- package/dist/store/store-snapshot.js +22 -2
- package/dist/store/workspace-store-paths.d.ts +39 -0
- package/dist/store/workspace-store-paths.js +94 -0
- package/dist/store/write-coordinator.d.ts +65 -0
- package/dist/store/write-coordinator.js +386 -0
- package/dist/todo-state.js +5 -5
- package/dist/tools-agent.js +268 -14
- package/dist/tools-discovery.js +1 -1
- package/dist/tools-files.d.ts +7 -0
- package/dist/tools-files.js +299 -10
- package/dist/tools-framework.js +25 -5
- package/dist/tools-handoff.js +2 -2
- package/dist/tools-lifecycle.js +4 -4
- package/dist/tools-memory.js +6 -6
- package/dist/tools-todo.js +2 -2
- package/dist/tracker-adapters.d.ts +1 -1
- package/dist/tracker-adapters.js +13 -18
- package/dist/tracker-sync.js +5 -3
- package/dist/tui/agent-runner.js +3 -1
- package/dist/tui/chat.js +103 -7
- package/dist/tui/dashboard.d.ts +1 -0
- package/dist/tui/dashboard.js +43 -0
- package/dist/tui/layout.d.ts +20 -0
- package/dist/tui/layout.js +31 -1
- package/dist/tui/local-model-contract.d.ts +6 -2
- package/dist/tui/local-model-contract.js +16 -3
- package/dist/vericify-bridge.d.ts +5 -0
- package/dist/vericify-bridge.js +27 -3
- package/dist/workspace-manager.d.ts +30 -3
- package/dist/workspace-manager.js +257 -27
- package/package.json +1 -2
- package/dist/internal-tool-runtime.d.ts +0 -21
- package/dist/internal-tool-runtime.js +0 -136
- package/dist/store/workspace-snapshot.d.ts +0 -26
- package/dist/store/workspace-snapshot.js +0 -107
package/dist/tools-agent.js
CHANGED
|
@@ -2,16 +2,17 @@
|
|
|
2
2
|
* Agent, skill, kernel, and task-pack tool registrations.
|
|
3
3
|
*/
|
|
4
4
|
import { z } from "zod";
|
|
5
|
-
import { ALL_AGENTS, COMPOSABLE_AGENTS, SWARM_AGENTS, SWARM_SUBAGENT_MAP, classifyPathSource, getAgentInstructionPath, getAgentManifestPath, getKernelArtifactPath, isSwarmRole, listAvailableSkills, readAgentInstructions, readAgentManifest, readKernelArtifact, readSkillInstructions, readTaskArtifact, resolveWorkspaceRoot, resolveWritableTaskPath,
|
|
5
|
+
import { ALL_AGENTS, COMPOSABLE_AGENTS, SWARM_AGENTS, SWARM_SUBAGENT_MAP, classifyPathSource, getAgentInstructionPath, getAgentManifestPath, getKernelArtifactPath, isSwarmRole, listAvailableSkills, readAgentInstructions, readAgentManifest, readKernelArtifact, readSkillInstructions, readTaskArtifact, resolveWorkspaceRoot, resolveWritableTaskPath, safeWriteAsync, } from "./helpers.js";
|
|
6
6
|
import { loadRuntimeProfile, readRuntimePromptTemplate, readRuntimeProfileState, validateRuntimeProfileContent, } from "./runtime-profile.js";
|
|
7
7
|
import { getUnattendedSession, listUnattendedSessions, startUnattendedSession, stopUnattendedSession, validateRuntimeExecutorSessionRegistryContent, waitForUnattendedSession, } from "./runtime-executor.js";
|
|
8
8
|
import { executeRuntimeTool, listRuntimeToolSpecs, loadRuntimeToolRegistry, validateRuntimeToolRegistryContent, } from "./runtime-tool-specs.js";
|
|
9
|
-
import {
|
|
9
|
+
import { createWorkspaceSessionAsync, listWorkspaceSessions, removeWorkspaceSession, resolveRuntimeWorkspaceRoot, validateManagedWorkspacePath, } from "./workspace-manager.js";
|
|
10
10
|
import { getTrackerAdapter, listTrackerAdapterKinds, loadTrackerSnapshot, validateTrackerSnapshotContent, } from "./tracker-adapters.js";
|
|
11
11
|
import { refreshTrackerSnapshot } from "./tracker-sync.js";
|
|
12
12
|
import { appendVericifyProcessPost, loadVericifyBridgeSnapshot, loadVericifyProcessPostLog, refreshVericifyBridgeSnapshot, validateVericifyBridgeSnapshotContent, validateVericifyProcessPostLogContent, } from "./vericify-bridge.js";
|
|
13
13
|
import { getRoleTitle, ROLE_ENUM, KERNEL_KEY_ENUM, ROLE_TITLES } from "./shared.js";
|
|
14
14
|
import { createDefaultModelBridgeClients, resolveLocalModelRuntime, runLocalModelTask, } from "./local-model-runtime.js";
|
|
15
|
+
import { withLocalModelRuntimeRepository } from "./store/repositories/local-model-runtime-repository.js";
|
|
15
16
|
import { executeAceInternalTool } from "./ace-internal-tools.js";
|
|
16
17
|
import { ModelBridge } from "./model-bridge.js";
|
|
17
18
|
import { getVericifyContextPacket, getVericifyDelta } from "./vericify-context.js";
|
|
@@ -52,6 +53,11 @@ function extractToolTextContent(result) {
|
|
|
52
53
|
.filter(Boolean)
|
|
53
54
|
.join("\n");
|
|
54
55
|
}
|
|
56
|
+
function didExecuteGatesPass(result) {
|
|
57
|
+
if (Boolean(result?.isError))
|
|
58
|
+
return false;
|
|
59
|
+
return !extractToolTextContent(result).trimStart().startsWith("❌");
|
|
60
|
+
}
|
|
55
61
|
function mapRoleToTaskType(role) {
|
|
56
62
|
switch (role) {
|
|
57
63
|
case "vos":
|
|
@@ -71,10 +77,164 @@ function extractHandoffId(text) {
|
|
|
71
77
|
const lineMatch = text.match(/handoff_id:\s*([A-Z0-9-]+)/i);
|
|
72
78
|
return lineMatch?.[1];
|
|
73
79
|
}
|
|
80
|
+
function stepLabel(index) {
|
|
81
|
+
return `step-${index + 1}`;
|
|
82
|
+
}
|
|
83
|
+
function isShipBoundaryTask(task) {
|
|
84
|
+
return /\b(ship|release|promot(?:e|ion)|land|merge)\b/i.test(task);
|
|
85
|
+
}
|
|
86
|
+
function isImplementationRole(role) {
|
|
87
|
+
return role === "coders" || role === "builder";
|
|
88
|
+
}
|
|
74
89
|
async function buildOrchestratorSteps(task, sessionId) {
|
|
75
90
|
void sessionId;
|
|
76
91
|
return [{ role: "orchestrator", task }];
|
|
77
92
|
}
|
|
93
|
+
function normalizeExplicitPlanSteps(steps, task) {
|
|
94
|
+
const originalIdByLabel = new Map();
|
|
95
|
+
const normalized = steps.map((step, index) => {
|
|
96
|
+
const id = `explicit-${index + 1}`;
|
|
97
|
+
originalIdByLabel.set(stepLabel(index), id);
|
|
98
|
+
return {
|
|
99
|
+
...step,
|
|
100
|
+
id,
|
|
101
|
+
depends_on_ids: [...(step.depends_on ?? [])],
|
|
102
|
+
};
|
|
103
|
+
});
|
|
104
|
+
for (const step of normalized) {
|
|
105
|
+
step.depends_on_ids = step.depends_on_ids.map((dependency) => originalIdByLabel.get(dependency) ?? dependency);
|
|
106
|
+
}
|
|
107
|
+
let insertedResearch = false;
|
|
108
|
+
for (let index = 0; index < normalized.length; index += 1) {
|
|
109
|
+
const step = normalized[index];
|
|
110
|
+
if (step.role !== "spec")
|
|
111
|
+
continue;
|
|
112
|
+
const hasResearchBefore = normalized.slice(0, index).some((candidate) => candidate.role === "research");
|
|
113
|
+
if (hasResearchBefore)
|
|
114
|
+
continue;
|
|
115
|
+
const researchId = `auto-research-${index + 1}`;
|
|
116
|
+
normalized.splice(index, 0, {
|
|
117
|
+
id: researchId,
|
|
118
|
+
role: "research",
|
|
119
|
+
task: `Validate source-backed claims and gather evidence before spec work: ${step.task}`,
|
|
120
|
+
tool_scope: ["recall_context", "read_workspace_file", "build_continuity_packet"],
|
|
121
|
+
depends_on_ids: [],
|
|
122
|
+
});
|
|
123
|
+
step.depends_on_ids = Array.from(new Set([researchId, ...step.depends_on_ids]));
|
|
124
|
+
insertedResearch = true;
|
|
125
|
+
index += 1;
|
|
126
|
+
}
|
|
127
|
+
const shipFanoutEnabled = isShipBoundaryTask(task) || normalized.some((step) => isShipBoundaryTask(step.task));
|
|
128
|
+
if (shipFanoutEnabled) {
|
|
129
|
+
const hasReviewRole = normalized.some((step) => step.role === "skeptic");
|
|
130
|
+
const hasSecurityRole = normalized.some((step) => step.role === "security");
|
|
131
|
+
const hasQaRole = normalized.some((step) => step.role === "qa");
|
|
132
|
+
const hasReleaseRole = normalized.some((step) => step.role === "release");
|
|
133
|
+
const lastImplementation = [...normalized].reverse().find((step) => isImplementationRole(step.role)) ?? normalized.at(-1);
|
|
134
|
+
const implementationDependency = lastImplementation ? [lastImplementation.id] : [];
|
|
135
|
+
const fanoutStepIds = [];
|
|
136
|
+
if (!hasReviewRole) {
|
|
137
|
+
const reviewId = `auto-review-${normalized.length + 1}`;
|
|
138
|
+
normalized.push({
|
|
139
|
+
id: reviewId,
|
|
140
|
+
role: "skeptic",
|
|
141
|
+
task: `Review ship readiness for: ${task}`,
|
|
142
|
+
tool_scope: ["execute_gates", "validate_framework"],
|
|
143
|
+
depends_on_ids: implementationDependency,
|
|
144
|
+
});
|
|
145
|
+
fanoutStepIds.push(reviewId);
|
|
146
|
+
}
|
|
147
|
+
if (!hasSecurityRole) {
|
|
148
|
+
const securityId = `auto-security-${normalized.length + 1}`;
|
|
149
|
+
normalized.push({
|
|
150
|
+
id: securityId,
|
|
151
|
+
role: "security",
|
|
152
|
+
task: `Assess security readiness for: ${task}`,
|
|
153
|
+
tool_scope: ["execute_gates", "validate_framework"],
|
|
154
|
+
depends_on_ids: implementationDependency,
|
|
155
|
+
});
|
|
156
|
+
fanoutStepIds.push(securityId);
|
|
157
|
+
}
|
|
158
|
+
if (!hasQaRole) {
|
|
159
|
+
const qaId = `auto-qa-${normalized.length + 1}`;
|
|
160
|
+
normalized.push({
|
|
161
|
+
id: qaId,
|
|
162
|
+
role: "qa",
|
|
163
|
+
task: `Validate ship readiness for: ${task}`,
|
|
164
|
+
tool_scope: ["run_tests", "execute_gates", "git_diff"],
|
|
165
|
+
depends_on_ids: implementationDependency,
|
|
166
|
+
});
|
|
167
|
+
fanoutStepIds.push(qaId);
|
|
168
|
+
}
|
|
169
|
+
if (!hasReleaseRole && fanoutStepIds.length > 0) {
|
|
170
|
+
normalized.push({
|
|
171
|
+
id: `auto-release-${normalized.length + 1}`,
|
|
172
|
+
role: "release",
|
|
173
|
+
task: `Finalize ship decision for: ${task}`,
|
|
174
|
+
tool_scope: ["git_status", "execute_gates", "validate_framework"],
|
|
175
|
+
depends_on_ids: fanoutStepIds,
|
|
176
|
+
});
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
const finalIdByInternal = new Map();
|
|
180
|
+
normalized.forEach((step, index) => {
|
|
181
|
+
finalIdByInternal.set(step.id, stepLabel(index));
|
|
182
|
+
});
|
|
183
|
+
return {
|
|
184
|
+
steps: normalized.map((step) => ({
|
|
185
|
+
role: step.role,
|
|
186
|
+
task: step.task,
|
|
187
|
+
depends_on: step.depends_on_ids.length > 0
|
|
188
|
+
? step.depends_on_ids.map((dependency) => finalIdByInternal.get(dependency) ?? dependency)
|
|
189
|
+
: undefined,
|
|
190
|
+
parallel_group: step.parallel_group,
|
|
191
|
+
tool_scope: step.tool_scope,
|
|
192
|
+
})),
|
|
193
|
+
insertedResearch,
|
|
194
|
+
shipFanoutEnabled,
|
|
195
|
+
};
|
|
196
|
+
}
|
|
197
|
+
async function normalizeOrchestratorPlanSteps(task, steps, sessionId) {
|
|
198
|
+
if (!Array.isArray(steps) || steps.length === 0) {
|
|
199
|
+
return {
|
|
200
|
+
planSource: "orchestrator_default_step",
|
|
201
|
+
normalization: {
|
|
202
|
+
steps: await buildOrchestratorSteps(task, sessionId),
|
|
203
|
+
insertedResearch: false,
|
|
204
|
+
shipFanoutEnabled: false,
|
|
205
|
+
},
|
|
206
|
+
};
|
|
207
|
+
}
|
|
208
|
+
return {
|
|
209
|
+
planSource: "explicit_steps",
|
|
210
|
+
normalization: normalizeExplicitPlanSteps(steps, task),
|
|
211
|
+
};
|
|
212
|
+
}
|
|
213
|
+
async function persistAcceptanceTraceMap(input) {
|
|
214
|
+
return safeWriteAsync("agent-state/ACCEPTANCE_TRACE_MAP.json", JSON.stringify({
|
|
215
|
+
version: 1,
|
|
216
|
+
generated_at: new Date().toISOString(),
|
|
217
|
+
plan_id: input.plan.plan_id,
|
|
218
|
+
task: input.task,
|
|
219
|
+
plan_source: input.planSource,
|
|
220
|
+
policies: {
|
|
221
|
+
inserted_research_before_spec: input.insertedResearch,
|
|
222
|
+
ship_fanout_enabled: input.shipFanoutEnabled,
|
|
223
|
+
},
|
|
224
|
+
steps: input.plan.steps.map((step) => ({
|
|
225
|
+
step_id: step.step_id,
|
|
226
|
+
role: step.role,
|
|
227
|
+
task: step.task,
|
|
228
|
+
depends_on: step.depends_on ?? [],
|
|
229
|
+
tool_scope: step.tool_scope ?? [],
|
|
230
|
+
verification_role: step.role === "coders" || step.role === "builder"
|
|
231
|
+
? "qa"
|
|
232
|
+
: step.role === "spec"
|
|
233
|
+
? "research"
|
|
234
|
+
: null,
|
|
235
|
+
})),
|
|
236
|
+
}, null, 2));
|
|
237
|
+
}
|
|
78
238
|
function appendUniqueNote(target, note) {
|
|
79
239
|
if (!target.includes(note)) {
|
|
80
240
|
target.push(note);
|
|
@@ -282,6 +442,45 @@ export function registerAgentTools(server) {
|
|
|
282
442
|
],
|
|
283
443
|
};
|
|
284
444
|
});
|
|
445
|
+
server.tool("get_transition_log", "Read the transition log for a session. Answers 'why stopped?', 'what changed?', and 'what evidence caused it?' from the ACE transition record store.", {
|
|
446
|
+
session_id: z.string().describe("Session ID to read transitions for"),
|
|
447
|
+
limit: z.number().int().positive().optional().default(20).describe("Max transitions to return (default: 20)"),
|
|
448
|
+
}, async ({ session_id, limit }) => {
|
|
449
|
+
try {
|
|
450
|
+
const transitions = await withLocalModelRuntimeRepository(resolveWorkspaceRoot(), (repo) => repo.getTransitionLog(session_id, limit ?? 20));
|
|
451
|
+
return {
|
|
452
|
+
content: [{ type: "text", text: JSON.stringify(transitions, null, 2) }],
|
|
453
|
+
};
|
|
454
|
+
}
|
|
455
|
+
catch (error) {
|
|
456
|
+
return {
|
|
457
|
+
content: [{ type: "text", text: `Error reading transition log: ${error instanceof Error ? error.message : String(error)}` }],
|
|
458
|
+
isError: true,
|
|
459
|
+
};
|
|
460
|
+
}
|
|
461
|
+
});
|
|
462
|
+
server.tool("get_capability_snapshot", "Read the capability snapshot for a specific turn. Shows which tools were available, their cost class, and any unavailable tools with reasons.", {
|
|
463
|
+
session_id: z.string().describe("Session ID"),
|
|
464
|
+
turn_number: z.number().int().positive().describe("Turn number"),
|
|
465
|
+
}, async ({ session_id, turn_number }) => {
|
|
466
|
+
try {
|
|
467
|
+
const snapshot = await withLocalModelRuntimeRepository(resolveWorkspaceRoot(), (repo) => repo.getCapabilitySnapshot(session_id, turn_number));
|
|
468
|
+
if (!snapshot) {
|
|
469
|
+
return {
|
|
470
|
+
content: [{ type: "text", text: `No capability snapshot found for session ${session_id} turn ${turn_number}` }],
|
|
471
|
+
};
|
|
472
|
+
}
|
|
473
|
+
return {
|
|
474
|
+
content: [{ type: "text", text: JSON.stringify(snapshot, null, 2) }],
|
|
475
|
+
};
|
|
476
|
+
}
|
|
477
|
+
catch (error) {
|
|
478
|
+
return {
|
|
479
|
+
content: [{ type: "text", text: `Error reading capability snapshot: ${error instanceof Error ? error.message : String(error)}` }],
|
|
480
|
+
isError: true,
|
|
481
|
+
};
|
|
482
|
+
}
|
|
483
|
+
});
|
|
285
484
|
server.tool("validate_runtime_profile", "Validate ACE runtime profile markdown content or the current ACE_WORKFLOW.md file", {
|
|
286
485
|
content: z
|
|
287
486
|
.string()
|
|
@@ -493,7 +692,19 @@ export function registerAgentTools(server) {
|
|
|
493
692
|
.boolean()
|
|
494
693
|
.optional()
|
|
495
694
|
.describe("If false, keep the managed workspace session after completion"),
|
|
496
|
-
|
|
695
|
+
emit_to: z
|
|
696
|
+
.array(z.enum(["tui", "tracker", "handoff", "vericify"]))
|
|
697
|
+
.optional()
|
|
698
|
+
.describe("Output emission targets for this session. Defaults to ['tui', 'vericify']."),
|
|
699
|
+
silent_unless_blocked: z
|
|
700
|
+
.boolean()
|
|
701
|
+
.optional()
|
|
702
|
+
.describe("If true, turns that produce no tool calls are classified as no_op_success and do not emit."),
|
|
703
|
+
require_approval_before_emit: z
|
|
704
|
+
.boolean()
|
|
705
|
+
.optional()
|
|
706
|
+
.describe("If true, require operator approval before emitting meaningful_completion output."),
|
|
707
|
+
}, async ({ task, context_json, workspace_name, workspace_path, objective_id, tracker_item_id, max_turns, turn_timeout_ms, auto_cleanup, emit_to, silent_unless_blocked, require_approval_before_emit, }) => {
|
|
497
708
|
const result = await startUnattendedSession({
|
|
498
709
|
task,
|
|
499
710
|
context: parseOptionalJsonObject(context_json),
|
|
@@ -504,6 +715,9 @@ export function registerAgentTools(server) {
|
|
|
504
715
|
max_turns,
|
|
505
716
|
turn_timeout_ms,
|
|
506
717
|
auto_cleanup,
|
|
718
|
+
emit_to,
|
|
719
|
+
silent_unless_blocked,
|
|
720
|
+
require_approval_before_emit,
|
|
507
721
|
});
|
|
508
722
|
return {
|
|
509
723
|
content: [
|
|
@@ -716,20 +930,43 @@ export function registerAgentTools(server) {
|
|
|
716
930
|
const effectiveWorkspaceRoot = runtime?.workspaceRoot ??
|
|
717
931
|
(workspace_root ? resolveRuntimeWorkspaceRoot(workspace_root) : resolveWorkspaceRoot());
|
|
718
932
|
const sessionId = typeof extra?.sessionId === "string" ? extra.sessionId : undefined;
|
|
719
|
-
const planSource =
|
|
720
|
-
const planSteps = Array.isArray(steps) && steps.length > 0
|
|
721
|
-
? steps
|
|
722
|
-
: await buildOrchestratorSteps(task, sessionId);
|
|
933
|
+
const { planSource, normalization } = await normalizeOrchestratorPlanSteps(task, steps, sessionId);
|
|
723
934
|
const plan = createTaskPlan({
|
|
724
935
|
task,
|
|
725
|
-
steps:
|
|
936
|
+
steps: normalization.steps,
|
|
726
937
|
execution_mode: execution_mode ?? "sequential",
|
|
727
938
|
});
|
|
939
|
+
const traceArtifactPath = await persistAcceptanceTraceMap({
|
|
940
|
+
plan,
|
|
941
|
+
task,
|
|
942
|
+
planSource,
|
|
943
|
+
insertedResearch: normalization.insertedResearch,
|
|
944
|
+
shipFanoutEnabled: normalization.shipFanoutEnabled,
|
|
945
|
+
});
|
|
728
946
|
const bridge = runtime
|
|
729
947
|
? new ModelBridge(createDefaultModelBridgeClients(runtime))
|
|
730
948
|
: undefined;
|
|
731
949
|
const fallbackHandoffPrefix = `LOCAL-${plan.plan_id}-`;
|
|
732
950
|
const vericifyWarnings = [];
|
|
951
|
+
const appendSessionPlanTransition = async (stepId, from, to, reason, reasonCode) => {
|
|
952
|
+
if (!sessionId)
|
|
953
|
+
return;
|
|
954
|
+
await withLocalModelRuntimeRepository(effectiveWorkspaceRoot, async (repo) => {
|
|
955
|
+
const step = plan.steps.find((candidate) => candidate.step_id === stepId);
|
|
956
|
+
if (!step)
|
|
957
|
+
return;
|
|
958
|
+
await repo.appendTransitionRecord({
|
|
959
|
+
session_id: sessionId,
|
|
960
|
+
subject_kind: "plan_step",
|
|
961
|
+
subject_id: `${plan.plan_id}/${step.step_id}`,
|
|
962
|
+
from,
|
|
963
|
+
to,
|
|
964
|
+
reason,
|
|
965
|
+
reason_code: reasonCode,
|
|
966
|
+
evidence_refs: step.tool_scope ?? [],
|
|
967
|
+
});
|
|
968
|
+
}).catch(() => undefined);
|
|
969
|
+
};
|
|
733
970
|
const supervised = await superviseTaskPlan(plan, {
|
|
734
971
|
async spawnStep(step) {
|
|
735
972
|
if (bridge && runtime) {
|
|
@@ -775,7 +1012,12 @@ export function registerAgentTools(server) {
|
|
|
775
1012
|
note,
|
|
776
1013
|
}, sessionId);
|
|
777
1014
|
},
|
|
778
|
-
amendPlan({ plan: activePlan, step, result }) {
|
|
1015
|
+
async amendPlan({ plan: activePlan, step, result }) {
|
|
1016
|
+
await appendSessionPlanTransition(step.step_id, "running", step.status, `Plan step ${step.step_id} ${step.status}: ${result.summary}`, step.status === "done"
|
|
1017
|
+
? "step_completed"
|
|
1018
|
+
: step.status === "blocked"
|
|
1019
|
+
? "step_blocked"
|
|
1020
|
+
: "step_failed");
|
|
779
1021
|
return buildDefaultOrchestratorAmendment({
|
|
780
1022
|
plan: activePlan,
|
|
781
1023
|
step,
|
|
@@ -807,7 +1049,7 @@ export function registerAgentTools(server) {
|
|
|
807
1049
|
async executeGates() {
|
|
808
1050
|
const result = await executeAceInternalTool("execute_gates", {}, sessionId);
|
|
809
1051
|
return {
|
|
810
|
-
ok:
|
|
1052
|
+
ok: didExecuteGatesPass(result),
|
|
811
1053
|
summary: extractToolTextContent(result),
|
|
812
1054
|
};
|
|
813
1055
|
},
|
|
@@ -822,6 +1064,9 @@ export function registerAgentTools(server) {
|
|
|
822
1064
|
}, sessionId);
|
|
823
1065
|
},
|
|
824
1066
|
async emitStatusEvent(event) {
|
|
1067
|
+
if (event.step_id) {
|
|
1068
|
+
await appendSessionPlanTransition(event.step_id, "planned", "running", `Plan step ${event.step_id} started: ${event.summary}`, "step_started");
|
|
1069
|
+
}
|
|
825
1070
|
await executeAceInternalTool("emit_status_event", {
|
|
826
1071
|
source_module: "capability-ops",
|
|
827
1072
|
event_type: "ORCHESTRATOR_STEP",
|
|
@@ -853,7 +1098,16 @@ export function registerAgentTools(server) {
|
|
|
853
1098
|
plan_source: planSource,
|
|
854
1099
|
planning_note: planSource === "orchestrator_default_step"
|
|
855
1100
|
? "Auto-planning currently starts with ACE-Orchestrator. Pass explicit steps for multi-step orchestration."
|
|
856
|
-
:
|
|
1101
|
+
: normalization.insertedResearch
|
|
1102
|
+
? "Research was inserted ahead of spec work to require source-backed evidence before specification."
|
|
1103
|
+
: normalization.shipFanoutEnabled
|
|
1104
|
+
? "Ship fan-out enforcement added review, security, QA, and release coordination steps."
|
|
1105
|
+
: null,
|
|
1106
|
+
trace_artifact_path: traceArtifactPath,
|
|
1107
|
+
engskills_imports: {
|
|
1108
|
+
inserted_research_before_spec: normalization.insertedResearch,
|
|
1109
|
+
ship_fanout_enabled: normalization.shipFanoutEnabled,
|
|
1110
|
+
},
|
|
857
1111
|
plan: supervised.plan,
|
|
858
1112
|
step_summaries,
|
|
859
1113
|
handoff_ids: supervised.handoff_ids,
|
|
@@ -1153,7 +1407,7 @@ export function registerAgentTools(server) {
|
|
|
1153
1407
|
.optional()
|
|
1154
1408
|
.describe("Optional hook timeout override in milliseconds"),
|
|
1155
1409
|
}, async ({ workspace_name, workspace_path, source, objective_id, tracker_item_id, root, hooks_timeout_ms, }) => {
|
|
1156
|
-
const result =
|
|
1410
|
+
const result = await createWorkspaceSessionAsync({
|
|
1157
1411
|
workspace_name,
|
|
1158
1412
|
workspace_path,
|
|
1159
1413
|
source,
|
|
@@ -1204,7 +1458,7 @@ export function registerAgentTools(server) {
|
|
|
1204
1458
|
.optional()
|
|
1205
1459
|
.describe("Optional hook timeout override in milliseconds"),
|
|
1206
1460
|
}, async ({ session_id, workspace_path, root, hooks_timeout_ms }) => {
|
|
1207
|
-
const result = removeWorkspaceSession({
|
|
1461
|
+
const result = await removeWorkspaceSession({
|
|
1208
1462
|
session_id,
|
|
1209
1463
|
workspace_path,
|
|
1210
1464
|
root,
|
|
@@ -1540,7 +1794,7 @@ export function registerAgentTools(server) {
|
|
|
1540
1794
|
"",
|
|
1541
1795
|
].join("\n");
|
|
1542
1796
|
const existing = readTaskArtifact("lessons");
|
|
1543
|
-
const path =
|
|
1797
|
+
const path = await safeWriteAsync(resolveWritableTaskPath("lessons"), `${existing}${entry}`);
|
|
1544
1798
|
return {
|
|
1545
1799
|
content: [{ type: "text", text: `✅ Lesson recorded in ${path}` }],
|
|
1546
1800
|
};
|
package/dist/tools-discovery.js
CHANGED
|
@@ -25,7 +25,7 @@ export function registerDiscoveryTools(server) {
|
|
|
25
25
|
.optional()
|
|
26
26
|
.describe("Include rep_astgrep.cxml corpus mining when available (default: true)"),
|
|
27
27
|
}, async ({ scope, append_evidence, emit_event, include_rep_corpus }) => {
|
|
28
|
-
const result = refreshAstgrepIndex({
|
|
28
|
+
const result = await refreshAstgrepIndex({
|
|
29
29
|
scope,
|
|
30
30
|
append_evidence,
|
|
31
31
|
emit_event,
|
package/dist/tools-files.d.ts
CHANGED
|
@@ -2,5 +2,12 @@
|
|
|
2
2
|
* File operation tool registrations + new safe-edit and diff tools.
|
|
3
3
|
*/
|
|
4
4
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
5
|
+
export interface AstgrepRewriteTargetPlan {
|
|
6
|
+
ok: boolean;
|
|
7
|
+
affected_files: string[];
|
|
8
|
+
target_file?: string;
|
|
9
|
+
error?: string;
|
|
10
|
+
}
|
|
11
|
+
export declare function planAstgrepRewriteTargets(files: string[]): AstgrepRewriteTargetPlan;
|
|
5
12
|
export declare function registerFileTools(server: McpServer): void;
|
|
6
13
|
//# sourceMappingURL=tools-files.d.ts.map
|