@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.
Files changed (115) hide show
  1. package/CHANGELOG.md +11 -1
  2. package/README.md +20 -13
  3. package/assets/agent-state/EVIDENCE_LOG.md +1 -1
  4. package/assets/agent-state/MODULES/roles/capability-framework.json +41 -0
  5. package/assets/agent-state/MODULES/roles/capability-git.json +33 -0
  6. package/assets/agent-state/MODULES/roles/capability-safety.json +37 -0
  7. package/assets/agent-state/MODULES/schemas/ACE_RUNTIME_PROFILE.schema.json +21 -0
  8. package/assets/agent-state/MODULES/schemas/RUNTIME_EXECUTOR_SESSION_REGISTRY.schema.json +43 -0
  9. package/assets/agent-state/MODULES/schemas/WORKSPACE_SESSION_REGISTRY.schema.json +11 -0
  10. package/assets/agent-state/STATUS.md +2 -2
  11. package/assets/scripts/ace-hook-dispatch.mjs +70 -6
  12. package/assets/scripts/render-mcp-configs.sh +19 -5
  13. package/dist/ace-context.js +22 -1
  14. package/dist/ace-server-instructions.js +3 -3
  15. package/dist/ace-state-resolver.js +5 -3
  16. package/dist/astgrep-index.d.ts +9 -1
  17. package/dist/astgrep-index.js +14 -3
  18. package/dist/cli.js +27 -20
  19. package/dist/handoff-registry.js +5 -5
  20. package/dist/helpers/artifacts.d.ts +19 -0
  21. package/dist/helpers/artifacts.js +152 -0
  22. package/dist/helpers/bootstrap.d.ts +24 -0
  23. package/dist/helpers/bootstrap.js +894 -0
  24. package/dist/helpers/constants.d.ts +53 -0
  25. package/dist/helpers/constants.js +288 -0
  26. package/dist/helpers/drift.d.ts +13 -0
  27. package/dist/helpers/drift.js +45 -0
  28. package/dist/helpers/path-utils.d.ts +17 -0
  29. package/dist/helpers/path-utils.js +104 -0
  30. package/dist/helpers/store-resolution.d.ts +19 -0
  31. package/dist/helpers/store-resolution.js +301 -0
  32. package/dist/helpers/workspace-root.d.ts +3 -0
  33. package/dist/helpers/workspace-root.js +80 -0
  34. package/dist/helpers.d.ts +8 -125
  35. package/dist/helpers.js +8 -1768
  36. package/dist/job-scheduler.js +3 -3
  37. package/dist/local-model-runtime.js +12 -1
  38. package/dist/model-bridge.d.ts +7 -0
  39. package/dist/model-bridge.js +75 -5
  40. package/dist/orchestrator-supervisor.d.ts +14 -0
  41. package/dist/orchestrator-supervisor.js +72 -1
  42. package/dist/run-ledger.js +3 -3
  43. package/dist/runtime-command.d.ts +8 -0
  44. package/dist/runtime-command.js +38 -6
  45. package/dist/runtime-executor.d.ts +14 -0
  46. package/dist/runtime-executor.js +669 -171
  47. package/dist/runtime-profile.d.ts +32 -0
  48. package/dist/runtime-profile.js +89 -13
  49. package/dist/runtime-tool-specs.d.ts +21 -0
  50. package/dist/runtime-tool-specs.js +78 -3
  51. package/dist/safe-edit.d.ts +7 -0
  52. package/dist/safe-edit.js +163 -37
  53. package/dist/schemas.js +19 -0
  54. package/dist/shared.d.ts +2 -2
  55. package/dist/status-events.js +9 -6
  56. package/dist/store/ace-packed-store.d.ts +3 -2
  57. package/dist/store/ace-packed-store.js +188 -110
  58. package/dist/store/bootstrap-store.d.ts +1 -1
  59. package/dist/store/bootstrap-store.js +94 -81
  60. package/dist/store/cache-workspace.js +11 -5
  61. package/dist/store/materializers/context-snapshot-materializer.js +6 -2
  62. package/dist/store/materializers/hook-context-materializer.d.ts +6 -9
  63. package/dist/store/materializers/hook-context-materializer.js +11 -21
  64. package/dist/store/materializers/host-file-materializer.js +6 -0
  65. package/dist/store/materializers/projection-manager.d.ts +0 -1
  66. package/dist/store/materializers/projection-manager.js +5 -13
  67. package/dist/store/materializers/scheduler-projection-materializer.js +1 -1
  68. package/dist/store/materializers/vericify-projector.d.ts +7 -7
  69. package/dist/store/materializers/vericify-projector.js +11 -11
  70. package/dist/store/repositories/local-model-runtime-repository.d.ts +120 -3
  71. package/dist/store/repositories/local-model-runtime-repository.js +242 -6
  72. package/dist/store/skills-install.d.ts +4 -0
  73. package/dist/store/skills-install.js +21 -12
  74. package/dist/store/state-reader.d.ts +2 -0
  75. package/dist/store/state-reader.js +20 -0
  76. package/dist/store/store-artifacts.d.ts +7 -0
  77. package/dist/store/store-artifacts.js +27 -1
  78. package/dist/store/store-authority-audit.d.ts +18 -1
  79. package/dist/store/store-authority-audit.js +115 -5
  80. package/dist/store/store-snapshot.d.ts +3 -0
  81. package/dist/store/store-snapshot.js +22 -2
  82. package/dist/store/workspace-store-paths.d.ts +39 -0
  83. package/dist/store/workspace-store-paths.js +94 -0
  84. package/dist/store/write-coordinator.d.ts +65 -0
  85. package/dist/store/write-coordinator.js +386 -0
  86. package/dist/todo-state.js +5 -5
  87. package/dist/tools-agent.js +268 -14
  88. package/dist/tools-discovery.js +1 -1
  89. package/dist/tools-files.d.ts +7 -0
  90. package/dist/tools-files.js +299 -10
  91. package/dist/tools-framework.js +25 -5
  92. package/dist/tools-handoff.js +2 -2
  93. package/dist/tools-lifecycle.js +4 -4
  94. package/dist/tools-memory.js +6 -6
  95. package/dist/tools-todo.js +2 -2
  96. package/dist/tracker-adapters.d.ts +1 -1
  97. package/dist/tracker-adapters.js +13 -18
  98. package/dist/tracker-sync.js +5 -3
  99. package/dist/tui/agent-runner.js +3 -1
  100. package/dist/tui/chat.js +103 -7
  101. package/dist/tui/dashboard.d.ts +1 -0
  102. package/dist/tui/dashboard.js +43 -0
  103. package/dist/tui/layout.d.ts +20 -0
  104. package/dist/tui/layout.js +31 -1
  105. package/dist/tui/local-model-contract.d.ts +6 -2
  106. package/dist/tui/local-model-contract.js +16 -3
  107. package/dist/vericify-bridge.d.ts +5 -0
  108. package/dist/vericify-bridge.js +27 -3
  109. package/dist/workspace-manager.d.ts +30 -3
  110. package/dist/workspace-manager.js +257 -27
  111. package/package.json +1 -2
  112. package/dist/internal-tool-runtime.d.ts +0 -21
  113. package/dist/internal-tool-runtime.js +0 -136
  114. package/dist/store/workspace-snapshot.d.ts +0 -26
  115. package/dist/store/workspace-snapshot.js +0 -107
@@ -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, safeWrite, } from "./helpers.js";
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 { createWorkspaceSession, listWorkspaceSessions, removeWorkspaceSession, resolveRuntimeWorkspaceRoot, validateManagedWorkspacePath, } from "./workspace-manager.js";
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
- }, async ({ task, context_json, workspace_name, workspace_path, objective_id, tracker_item_id, max_turns, turn_timeout_ms, auto_cleanup, }) => {
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 = Array.isArray(steps) && steps.length > 0 ? "explicit_steps" : "orchestrator_default_step";
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: planSteps,
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: !Boolean(result?.isError),
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
- : null,
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 = createWorkspaceSession({
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 = safeWrite(resolveWritableTaskPath("lessons"), `${existing}${entry}`);
1797
+ const path = await safeWriteAsync(resolveWritableTaskPath("lessons"), `${existing}${entry}`);
1544
1798
  return {
1545
1799
  content: [{ type: "text", text: `✅ Lesson recorded in ${path}` }],
1546
1800
  };
@@ -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,
@@ -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