@voybio/ace-swarm 2.4.8 → 2.4.10

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 (187) hide show
  1. package/CHANGELOG.md +52 -14
  2. package/README.md +14 -10
  3. package/assets/.agents/ACE/ACE_coders/AGENTS.md +23 -30
  4. package/assets/.agents/ACE/ACE_coders/INSTRUCTIONS.md +21 -30
  5. package/assets/.agents/skills/landing-review-watcher/SKILL.md +1 -1
  6. package/assets/.agents/skills/learn-from-work/SKILL.md +41 -0
  7. package/assets/agent-state/ACE_WORKFLOW.md +25 -2
  8. package/assets/agent-state/MODULES/schemas/ACE_RUNTIME_PROFILE.schema.json +143 -2
  9. package/assets/agent-state/MODULES/schemas/RUNTIME_EXECUTOR_SESSION_REGISTRY.schema.json +2 -2
  10. package/assets/agent-state/MODULES/schemas/SWARM_HANDOFF.schema.json +10 -0
  11. package/assets/eval-battery/battery.json +1 -1
  12. package/assets/instructions/ACE_Coder.instructions.md +9 -13
  13. package/assets/scripts/ace-hook-dispatch.mjs +16 -411
  14. package/assets/tasks/SWARM_HANDOFF.example_ui_to_coders.json +1 -2
  15. package/assets/vendor/README.md +9 -0
  16. package/assets/vendor/vericify-reader.mjs +272 -0
  17. package/assets/vendor/vericify-reader.provenance.json +10 -0
  18. package/dist/ace-autonomy.d.ts +58 -0
  19. package/dist/ace-autonomy.js +211 -6
  20. package/dist/ace-internal-tools.d.ts +1 -0
  21. package/dist/ace-internal-tools.js +3 -3
  22. package/dist/ace-server-instructions.d.ts +3 -3
  23. package/dist/ace-server-instructions.js +46 -192
  24. package/dist/cli.js +44 -6
  25. package/dist/experience-reflector.d.ts +7 -0
  26. package/dist/experience-reflector.js +39 -0
  27. package/dist/goal-engine.d.ts +64 -7
  28. package/dist/goal-engine.js +197 -41
  29. package/dist/handoff-registry.d.ts +10 -0
  30. package/dist/handoff-registry.js +59 -0
  31. package/dist/helpers/artifacts.d.ts +6 -2
  32. package/dist/helpers/artifacts.js +8 -6
  33. package/dist/helpers/bootstrap.js +13 -20
  34. package/dist/helpers/path-utils.js +2 -0
  35. package/dist/helpers/store-resolution.js +18 -3
  36. package/dist/helpers/workspace-root.d.ts +2 -0
  37. package/dist/helpers/workspace-root.js +9 -0
  38. package/dist/helpers.d.ts +1 -0
  39. package/dist/helpers.js +1 -0
  40. package/dist/hermes/bridge-protocol.d.ts +1 -1
  41. package/dist/hermes/session-manager.d.ts +17 -0
  42. package/dist/hermes/session-manager.js +67 -14
  43. package/dist/host-goal-engine.d.ts +138 -0
  44. package/dist/host-goal-engine.js +793 -0
  45. package/dist/host-goal-status.d.ts +113 -0
  46. package/dist/host-goal-status.js +175 -0
  47. package/dist/host-learning.d.ts +68 -0
  48. package/dist/host-learning.js +115 -0
  49. package/dist/host-observation.d.ts +12 -0
  50. package/dist/host-observation.js +91 -0
  51. package/dist/host-plan-revision.d.ts +14 -0
  52. package/dist/host-plan-revision.js +101 -0
  53. package/dist/host-verification-job.d.ts +12 -0
  54. package/dist/host-verification-job.js +183 -0
  55. package/dist/host-work-context.d.ts +12 -0
  56. package/dist/host-work-context.js +8 -0
  57. package/dist/job-scheduler.d.ts +58 -13
  58. package/dist/job-scheduler.js +298 -48
  59. package/dist/job-worker.d.ts +3 -1
  60. package/dist/job-worker.js +10 -3
  61. package/dist/kanban.d.ts +4 -1
  62. package/dist/kanban.js +44 -16
  63. package/dist/learned-artifacts.d.ts +64 -0
  64. package/dist/learned-artifacts.js +321 -0
  65. package/dist/learning-controls.d.ts +142 -0
  66. package/dist/learning-controls.js +135 -0
  67. package/dist/learning-input-context.d.ts +9 -0
  68. package/dist/learning-input-context.js +62 -0
  69. package/dist/learning-lifecycle.d.ts +10 -0
  70. package/dist/learning-lifecycle.js +11 -0
  71. package/dist/learning-overlays.d.ts +3 -0
  72. package/dist/learning-overlays.js +17 -0
  73. package/dist/learning-policy.d.ts +40 -0
  74. package/dist/learning-policy.js +38 -0
  75. package/dist/learning-records.d.ts +35 -0
  76. package/dist/learning-records.js +17 -0
  77. package/dist/learning-scorecard.d.ts +82 -0
  78. package/dist/learning-scorecard.js +86 -0
  79. package/dist/learning-serving.d.ts +29 -0
  80. package/dist/learning-serving.js +134 -0
  81. package/dist/linked-work.d.ts +9 -0
  82. package/dist/linked-work.js +28 -0
  83. package/dist/local-model-runtime.js +1 -1
  84. package/dist/mcp-command-progress.d.ts +16 -0
  85. package/dist/mcp-command-progress.js +70 -0
  86. package/dist/model-bridge.d.ts +14 -13
  87. package/dist/model-bridge.js +73 -41
  88. package/dist/orchestrator-supervisor.d.ts +111 -6
  89. package/dist/orchestrator-supervisor.js +67 -43
  90. package/dist/plan-proposal.js +3 -3
  91. package/dist/playbook-curator.d.ts +1 -0
  92. package/dist/playbook-curator.js +11 -9
  93. package/dist/process-identity.d.ts +8 -0
  94. package/dist/process-identity.js +38 -0
  95. package/dist/progress-command.d.ts +34 -0
  96. package/dist/progress-command.js +153 -0
  97. package/dist/prompts.js +15 -15
  98. package/dist/resources.js +2 -2
  99. package/dist/runtime-command.d.ts +8 -1
  100. package/dist/runtime-command.js +48 -7
  101. package/dist/runtime-executor.js +33 -11
  102. package/dist/runtime-profile-syntax.d.ts +6 -0
  103. package/dist/runtime-profile-syntax.js +121 -0
  104. package/dist/runtime-profile.d.ts +37 -5
  105. package/dist/runtime-profile.js +36 -129
  106. package/dist/runtime-tool-specs.js +1 -1
  107. package/dist/safe-edit.d.ts +7 -3
  108. package/dist/safe-edit.js +40 -47
  109. package/dist/schemas.js +4 -2
  110. package/dist/server.d.ts +2 -16
  111. package/dist/server.js +14 -20
  112. package/dist/shared.d.ts +2 -0
  113. package/dist/shared.js +2 -0
  114. package/dist/skill-auditor.d.ts +19 -0
  115. package/dist/skill-auditor.js +32 -2
  116. package/dist/skill-catalog.d.ts +4 -1
  117. package/dist/skill-catalog.js +6 -5
  118. package/dist/store/ace-packed-store.d.ts +5 -1
  119. package/dist/store/ace-packed-store.js +33 -1
  120. package/dist/store/bootstrap-store.js +19 -12
  121. package/dist/store/cache-workspace.d.ts +8 -0
  122. package/dist/store/cache-workspace.js +94 -27
  123. package/dist/store/importer.js +11 -20
  124. package/dist/store/knowledge-bake.d.ts +3 -1
  125. package/dist/store/knowledge-bake.js +10 -1
  126. package/dist/store/legacy-vericify-posts.d.ts +8 -0
  127. package/dist/store/legacy-vericify-posts.js +76 -0
  128. package/dist/store/materializers/hook-context-materializer.d.ts +2 -1
  129. package/dist/store/materializers/hook-context-materializer.js +6 -2
  130. package/dist/store/materializers/host-file-materializer.js +2 -2
  131. package/dist/store/materializers/projection-manager.d.ts +4 -1
  132. package/dist/store/materializers/projection-manager.js +10 -3
  133. package/dist/store/materializers/todo-syncer.d.ts +39 -20
  134. package/dist/store/materializers/todo-syncer.js +208 -110
  135. package/dist/store/materializers/vericify-projector.js +15 -26
  136. package/dist/store/repositories/goal-repository.d.ts +51 -2
  137. package/dist/store/repositories/goal-repository.js +114 -48
  138. package/dist/store/repositories/playbook-repository.d.ts +41 -3
  139. package/dist/store/repositories/playbook-repository.js +61 -5
  140. package/dist/store/repositories/todo-repository.d.ts +8 -2
  141. package/dist/store/repositories/todo-repository.js +1 -1
  142. package/dist/store/repositories/vericify-repository.d.ts +4 -0
  143. package/dist/store/repositories/vericify-repository.js +46 -0
  144. package/dist/store/skills-install.d.ts +1 -0
  145. package/dist/store/skills-install.js +20 -16
  146. package/dist/store/source-preservation.d.ts +24 -0
  147. package/dist/store/source-preservation.js +79 -0
  148. package/dist/store/store-artifacts.js +8 -1
  149. package/dist/store/test-write-boundary.d.ts +16 -0
  150. package/dist/store/test-write-boundary.js +175 -0
  151. package/dist/store/types.d.ts +5 -1
  152. package/dist/store/write-coordinator.js +16 -0
  153. package/dist/task-plan-context.d.ts +11 -0
  154. package/dist/task-plan-context.js +59 -0
  155. package/dist/todo-state.d.ts +19 -9
  156. package/dist/todo-state.js +204 -321
  157. package/dist/tools-agent.d.ts +1 -1
  158. package/dist/tools-agent.js +38 -62
  159. package/dist/tools-files.d.ts +0 -3
  160. package/dist/tools-files.js +21 -11
  161. package/dist/tools-framework.js +16 -25
  162. package/dist/tools-goal.d.ts +2 -4
  163. package/dist/tools-goal.js +119 -16
  164. package/dist/tools-handoff.d.ts +3 -2
  165. package/dist/tools-handoff.js +53 -23
  166. package/dist/tools-lifecycle.js +1 -1
  167. package/dist/tools-memory.d.ts +0 -3
  168. package/dist/tools-memory.js +51 -6
  169. package/dist/tools-scheduler.js +20 -17
  170. package/dist/tools-todo.js +160 -148
  171. package/dist/vericify-bridge.d.ts +8 -0
  172. package/dist/vericify-bridge.js +18 -0
  173. package/dist/vericify-context.d.ts +4 -0
  174. package/dist/vericify-context.js +26 -5
  175. package/dist/vericify-native.d.ts +101 -0
  176. package/dist/vericify-native.js +221 -0
  177. package/dist/verification-worker.d.ts +2 -0
  178. package/dist/verification-worker.js +31 -0
  179. package/docs/mcp-tool-reference.md +50 -10
  180. package/docs/troubleshooting.md +29 -0
  181. package/package.json +19 -6
  182. package/scripts/dev/run-tests-isolated.mjs +165 -0
  183. package/scripts/dev/run_hermes_crispr_live.mjs +1 -0
  184. package/scripts/dev/test-isolation-guard.mjs +20 -0
  185. package/scripts/dev/test-preload.mjs +153 -0
  186. package/scripts/dev/test-source-inventory.mjs +31 -0
  187. package/docs/development.md +0 -46
@@ -1,3 +1,4 @@
1
+ export { formatStepTaskForBridge } from "./task-plan-context.js";
1
2
  /**
2
3
  * Agent, skill, kernel, and task-pack tool registrations.
3
4
  */
@@ -6,7 +7,6 @@ import { type BridgeResult } from "./model-bridge.js";
6
7
  import { proposePlan as proposePlanImpl, validatePlan as validatePlanImpl, loadAcceptanceTraceContract as loadAcceptanceTraceContractImpl } from "./plan-proposal.js";
7
8
  import { type TaskPlan, type TaskStep } from "./orchestrator-supervisor.js";
8
9
  export type { TaskPlan, TaskStep } from "./orchestrator-supervisor.js";
9
- export declare function formatStepTaskForBridge(step: Pick<TaskStep, "task" | "upstream_outputs">): string;
10
10
  type IntentVerificationOutcome = "ok" | "revisit_step" | "replan_required";
11
11
  type IntentDriftReasonCode = "contract_missing" | "contract_invalid" | "bridge_output_malformed_json" | "role_drift_ui_off_topic" | "coder_artifact_stub" | "qa_rewrote_artifact" | "artifact_mismatch" | "forbidden_pattern" | "required_evidence_missing";
12
12
  interface IntentVerificationResult {
@@ -1,6 +1,5 @@
1
- /**
2
- * Agent, skill, kernel, and task-pack tool registrations.
3
- */
1
+ import { formatStepTaskForBridge } from "./task-plan-context.js";
2
+ export { formatStepTaskForBridge } from "./task-plan-context.js";
4
3
  import { z } from "zod";
5
4
  import { ALL_AGENTS, COMPOSABLE_AGENTS, SWARM_AGENTS, SWARM_SUBAGENT_MAP, classifyPathSource, getAgentInstructionPath, getAgentManifestPath, getKernelArtifactPath, isSwarmRole, listAvailableSkills, readAgentInstructions, readAgentManifest, readKernelArtifact, readSkillInstructions, readTaskArtifact, resolveWorkspaceRoot, } from "./helpers.js";
6
5
  import { loadRuntimeProfile, readRuntimePromptTemplate, readRuntimeProfileState, validateRuntimeProfileContent, } from "./runtime-profile.js";
@@ -79,21 +78,6 @@ function extractHandoffId(text) {
79
78
  const lineMatch = text.match(/handoff_id:\s*([A-Z0-9-]+)/i);
80
79
  return lineMatch?.[1];
81
80
  }
82
- export function formatStepTaskForBridge(step) {
83
- const upstreamOutputs = step.upstream_outputs ?? [];
84
- if (upstreamOutputs.length === 0) {
85
- return step.task;
86
- }
87
- const renderedOutputs = upstreamOutputs
88
- .map((output) => `- ${output.step_id}: ${output.result_summary || "[no summary]"}${output.evidence_refs.length > 0 ? ` (evidence: ${output.evidence_refs.join(", ")})` : ""}`)
89
- .join("\n");
90
- return [
91
- step.task,
92
- "",
93
- "Upstream outputs:",
94
- renderedOutputs,
95
- ].join("\n");
96
- }
97
81
  // ── Re-export plan-proposal API ────────────────────────────────────────────
98
82
  export { loadAcceptanceTraceContractImpl as loadAcceptanceTraceContract };
99
83
  export { proposePlanImpl as proposePlan, validatePlanImpl as validatePlan };
@@ -658,7 +642,7 @@ export function registerAgentTools(server) {
658
642
  server.tool("get_agent_instructions", "Load the full instruction file for a specific ACE agent role", {
659
643
  role: ROLE_ENUM.describe("Which agent role to load"),
660
644
  }, async ({ role }) => {
661
- const content = readAgentInstructions(role);
645
+ const content = readAgentInstructions(role, { includeLearned: true });
662
646
  const sourcePath = getAgentInstructionPath(role);
663
647
  const source = classifyPathSource(sourcePath);
664
648
  return {
@@ -1046,15 +1030,15 @@ export function registerAgentTools(server) {
1046
1030
  max_turns: z
1047
1031
  .number()
1048
1032
  .int()
1049
- .positive()
1033
+ .nonnegative()
1050
1034
  .optional()
1051
- .describe("Optional max-turn override"),
1035
+ .describe("Explicit maximum turn allowance; 0 means unlimited (default)"),
1052
1036
  turn_timeout_ms: z
1053
1037
  .number()
1054
1038
  .int()
1055
- .positive()
1039
+ .nonnegative()
1056
1040
  .optional()
1057
- .describe("Optional per-turn timeout override in milliseconds"),
1041
+ .describe("Explicit per-turn deadline in milliseconds; 0 means unlimited (default)"),
1058
1042
  auto_cleanup: z
1059
1043
  .boolean()
1060
1044
  .optional()
@@ -1152,7 +1136,7 @@ export function registerAgentTools(server) {
1152
1136
  ],
1153
1137
  };
1154
1138
  });
1155
- server.tool("validate_plan", "Run shape checks against a PlanProposal (coverage, verification chain, tool-scope realism, acceptance criteria presence, stop conditions visibility). Returns { ok, score, blocking_findings, soft_findings }. Persists a transition record and Vericify process post.", {
1139
+ server.tool("validate_plan", "Run shape checks against a PlanProposal (coverage, verification chain, tool-scope realism, acceptance criteria presence, stop conditions visibility). Returns { ok, score, blocking_findings, soft_findings }. Persists an ACE transition record; legacy Vericify process posts require explicit opt-in.", {
1156
1140
  plan_id: z.string().optional().describe("ID of a previously proposed plan to validate"),
1157
1141
  proposal: z
1158
1142
  .object({
@@ -1194,9 +1178,9 @@ export function registerAgentTools(server) {
1194
1178
  max_turns: z
1195
1179
  .number()
1196
1180
  .int()
1197
- .positive()
1181
+ .nonnegative()
1198
1182
  .optional()
1199
- .describe("Optional max-turn override; defaults by role"),
1183
+ .describe("Explicit turn cap; 0/unset is unlimited for the native bridge. Hermes uses its adapter policy."),
1200
1184
  tier: z
1201
1185
  .enum(["auto", "full", "compressed", "brief"])
1202
1186
  .optional()
@@ -1348,9 +1332,9 @@ export function registerAgentTools(server) {
1348
1332
  max_turns_per_step: z
1349
1333
  .number()
1350
1334
  .int()
1351
- .positive()
1335
+ .nonnegative()
1352
1336
  .optional()
1353
- .describe("Optional max-turn limit applied to each child bridge step"),
1337
+ .describe("Explicit child bridge turn cap; 0/unset is unlimited"),
1354
1338
  provider: z
1355
1339
  .string()
1356
1340
  .optional()
@@ -1483,7 +1467,7 @@ export function registerAgentTools(server) {
1483
1467
  role: step.role,
1484
1468
  workspace: runtime.workspaceRoot,
1485
1469
  tier: resolveTier(undefined, runtime.provider, runtime.model, step.role),
1486
- maxTurns: max_turns_per_step ?? 6,
1470
+ maxTurns: max_turns_per_step ?? 0,
1487
1471
  provider: runtime.provider,
1488
1472
  model: runtime.model,
1489
1473
  toolScope: step.tool_scope,
@@ -1549,11 +1533,13 @@ export function registerAgentTools(server) {
1549
1533
  },
1550
1534
  async getVericifyContext() {
1551
1535
  return tryVericifyPacket(() => getVericifyContextPacket({
1536
+ mode: "configured",
1552
1537
  workspaceRoot: effectiveWorkspaceRoot,
1553
1538
  }), (message) => appendUniqueNote(vericifyWarnings, `Vericify context unavailable for ${plan.plan_id}: ${message}`));
1554
1539
  },
1555
1540
  async getVericifyDelta(since) {
1556
1541
  return tryVericifyPacket(() => getVericifyDelta({
1542
+ mode: "configured",
1557
1543
  since,
1558
1544
  workspaceRoot: effectiveWorkspaceRoot,
1559
1545
  }), (message) => appendUniqueNote(vericifyWarnings, `Vericify delta unavailable for ${plan.plan_id}: ${message}`));
@@ -1680,7 +1666,8 @@ export function registerAgentTools(server) {
1680
1666
  ],
1681
1667
  };
1682
1668
  });
1683
- server.tool("get_vericify_context", "Build a compact Vericify context packet for workspace:current or a specified run", {
1669
+ server.tool("get_vericify_context", "Read configured native Vericify metadata, or explicitly request legacy context compatibility", {
1670
+ mode: z.enum(["configured", "legacy"]).optional().describe("Defaults to configured; legacy explicitly enables historical API discovery"),
1684
1671
  run_id: z
1685
1672
  .string()
1686
1673
  .optional()
@@ -1689,9 +1676,10 @@ export function registerAgentTools(server) {
1689
1676
  .string()
1690
1677
  .optional()
1691
1678
  .describe("Optional workspace root override used to locate the Vericify workspace"),
1692
- }, async ({ run_id, workspace_root }) => {
1679
+ }, async ({ run_id, workspace_root, mode }) => {
1693
1680
  try {
1694
1681
  const packet = await getVericifyContextPacket({
1682
+ mode: mode ?? "configured",
1695
1683
  runId: run_id,
1696
1684
  workspaceRoot: workspace_root,
1697
1685
  });
@@ -1716,7 +1704,8 @@ export function registerAgentTools(server) {
1716
1704
  };
1717
1705
  }
1718
1706
  });
1719
- server.tool("get_vericify_delta", "Build a compact Vericify delta from a prior vcx cursor or checkpoint reference", {
1707
+ server.tool("get_vericify_delta", "Read a configured native delta, or explicitly request a legacy vcx/checkpoint delta", {
1708
+ mode: z.enum(["configured", "legacy"]).optional().describe("Defaults to configured; legacy explicitly enables historical API discovery"),
1720
1709
  since: z
1721
1710
  .string()
1722
1711
  .describe("Required prior vcx cursor or compatible checkpoint reference"),
@@ -1728,9 +1717,10 @@ export function registerAgentTools(server) {
1728
1717
  .string()
1729
1718
  .optional()
1730
1719
  .describe("Optional workspace root override used to locate the Vericify workspace"),
1731
- }, async ({ since, run_id, workspace_root }) => {
1720
+ }, async ({ since, run_id, workspace_root, mode }) => {
1732
1721
  try {
1733
1722
  const delta = await getVericifyDelta({
1723
+ mode: mode ?? "configured",
1734
1724
  since,
1735
1725
  runId: run_id,
1736
1726
  workspaceRoot: workspace_root,
@@ -2294,9 +2284,15 @@ export function registerAgentTools(server) {
2294
2284
  });
2295
2285
  server.tool("get_skill_instructions", "Load SKILL.md for a specific ACE skill", {
2296
2286
  name: z.string().describe("Skill name (e.g., codemunch, codesnipe)"),
2297
- }, async ({ name }) => {
2287
+ }, async ({ name }, extra) => {
2298
2288
  const skills = listAvailableSkills();
2299
2289
  const match = skills.find((skill) => skill.name.toLowerCase() === name.trim().toLowerCase());
2290
+ const { getHostBinding } = await import('./host-work-context.js');
2291
+ const binding = getHostBinding(extra.sessionId);
2292
+ if (match && binding?.goal_id && binding.step_id && binding.attempt) {
2293
+ const { recordSkillUse } = await import('./learning-serving.js');
2294
+ await recordSkillUse(resolveWorkspaceRoot(), { goal_id: binding.goal_id, step_id: binding.step_id, attempt: binding.attempt, agent: binding.agent }, match.name);
2295
+ }
2300
2296
  const prefix = match
2301
2297
  ? `# Skill: ${match.name}\n\nSource: ${match.source} (${match.path})\n\n`
2302
2298
  : `# Skill: ${name}\n\n`;
@@ -2304,7 +2300,7 @@ export function registerAgentTools(server) {
2304
2300
  content: [
2305
2301
  {
2306
2302
  type: "text",
2307
- text: `${prefix}${readSkillInstructions(name)}`,
2303
+ text: `${prefix}${readSkillInstructions(name, { includeLearned: true })}`,
2308
2304
  },
2309
2305
  ],
2310
2306
  };
@@ -2350,33 +2346,13 @@ export function registerAgentTools(server) {
2350
2346
  failure_pattern: z.string().describe("What went wrong"),
2351
2347
  guardrail: z.string().describe("Rule to prevent recurrence"),
2352
2348
  verification_check: z.string().describe("How to verify compliance"),
2353
- }, async ({ context, failure_pattern, guardrail, verification_check }) => {
2354
- const knownReasonCodes = [
2355
- "false_completion_no_evidence",
2356
- "forward_pacing_incomplete",
2357
- "bridge_tool_doom_loop",
2358
- "bridge_text_doom_loop",
2359
- "context_overflow",
2360
- "tool_timeout",
2361
- "role_contract_violation",
2362
- ];
2363
- const scope = {};
2364
- const lowered = failure_pattern.toLowerCase();
2365
- const reason = knownReasonCodes.find((code) => lowered.includes(code));
2366
- if (reason)
2367
- scope.reason_code = reason;
2368
- const root = resolveWorkspaceRoot();
2369
- const bullet = new PlaybookRepository(root).createBullet({
2370
- section: "failure_modes",
2371
- scope,
2372
- content: `${guardrail} Verify: ${verification_check}`,
2373
- evidence_refs: [],
2374
- provenance: { source: "operator" },
2375
- });
2376
- const path = materializePlaybookMarkdown(root);
2377
- return {
2378
- content: [{ type: "text", text: `✅ Lesson recorded as ${bullet.bullet_id} (${bullet.status}) in ${path}. Context: ${context}` }],
2379
- };
2349
+ evidence_refs: z.array(z.string()).optional(),
2350
+ step_ref: z.object({ goal_id: z.string(), step_id: z.string() }).optional(),
2351
+ paths: z.array(z.string()).optional(),
2352
+ }, async ({ context, failure_pattern, guardrail, verification_check, evidence_refs, step_ref, paths }) => {
2353
+ const { addHostLesson } = await import('./host-learning.js');
2354
+ const result = await addHostLesson(resolveWorkspaceRoot(), { context, failure_pattern, guardrail, verification_check, evidence_refs, step_ref, paths });
2355
+ return { content: [{ type: 'text', text: JSON.stringify(result) }], structuredContent: result };
2380
2356
  });
2381
2357
  // ── CLI Work Split ────────────────────────────────────────────────
2382
2358
  server.tool("get_cli_split", "Get the CLI work split contract (Codex vs Gemini routing)", {}, async () => ({
@@ -1,6 +1,3 @@
1
- /**
2
- * File operation tool registrations + new safe-edit and diff tools.
3
- */
4
1
  import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
5
2
  export interface AstgrepRewriteTargetPlan {
6
3
  ok: boolean;
@@ -1,3 +1,5 @@
1
+ import { commandPolicySchema, withMcpCommandProgress } from "./mcp-command-progress.js";
2
+ import { formatKanbanRefresh } from "./kanban.js";
1
3
  /**
2
4
  * File operation tool registrations + new safe-edit and diff tools.
3
5
  */
@@ -1047,13 +1049,16 @@ export function registerFileTools(server) {
1047
1049
  let todoStateSuffix = "";
1048
1050
  if (normalizedPath === `${ACE_TASKS_ROOT_REL}/todo.md`) {
1049
1051
  const synced = await syncTodoStateSafe(content);
1050
- todoStateSuffix = `\nTODO state synced: ${synced.path}`;
1052
+ todoStateSuffix = `\nTODO state synced: ${synced.path}${synced.import_warnings.map((warning) => `\nImport warning: ${warning}`).join("")}${synced.projection_pending ? "\nTodo markdown refresh pending." : ""}`;
1051
1053
  }
1052
1054
  const storeFallbackKeys = resolveStoreFallbackKeysForPath(normalizedPath);
1053
1055
  const useAsyncStoreAdmission = storeFallbackKeys.length > 0 && workspaceRoot === WORKSPACE_ROOT;
1054
1056
  // Keep the file as a materialized projection after the canonical store update.
1055
1057
  let abs;
1056
- if (useAsyncStoreAdmission) {
1058
+ if (normalizedPath === `${ACE_TASKS_ROOT_REL}/todo.md`) {
1059
+ abs = targetPath; // The todo owner already committed and projected this import.
1060
+ }
1061
+ else if (useAsyncStoreAdmission) {
1057
1062
  abs = await safeWriteAsync(path, content);
1058
1063
  }
1059
1064
  else if (workspaceRoot === WORKSPACE_ROOT) {
@@ -1068,7 +1073,7 @@ export function registerFileTools(server) {
1068
1073
  const shouldRefreshKanban = shouldAutoRefreshKanbanForPath(normalizedPath);
1069
1074
  if (shouldRefreshKanban) {
1070
1075
  const kanban = refreshKanbanArtifacts(`tool:write_workspace_file:${normalizedPath}`);
1071
- kanbanSuffix = `\nKanban updated: ${kanban.html_path}\nKanban counts: backlog=${kanban.counts.backlog}, blocked=${kanban.counts.blocked}, in_progress=${kanban.counts.in_progress}, gated=${kanban.counts.gated}, done=${kanban.counts.done}`;
1076
+ kanbanSuffix = `\n${formatKanbanRefresh(kanban)}\nKanban counts: backlog=${kanban.counts.backlog}, blocked=${kanban.counts.blocked}, in_progress=${kanban.counts.in_progress}, gated=${kanban.counts.gated}, done=${kanban.counts.done}`;
1072
1077
  }
1073
1078
  const runLedger = await appendRunLedgerEntrySafe({
1074
1079
  tool: "write_workspace_file",
@@ -1165,6 +1170,7 @@ export function registerFileTools(server) {
1165
1170
  .string()
1166
1171
  .optional()
1167
1172
  .describe("Shell command for tests (e.g. 'npm test')"),
1173
+ command_policy: commandPolicySchema.optional(),
1168
1174
  backup: z
1169
1175
  .boolean()
1170
1176
  .optional()
@@ -1173,15 +1179,16 @@ export function registerFileTools(server) {
1173
1179
  .string()
1174
1180
  .optional()
1175
1181
  .describe("Optional source precondition checked immediately before promotion; prefer full sha256:<hex>"),
1176
- }, async ({ path, content, validation_command, test_command, backup, expected_base_hash }) => {
1177
- const result = safeEditFile({
1182
+ }, async ({ path, content, validation_command, test_command, backup, expected_base_hash, command_policy }, extra) => {
1183
+ const result = await withMcpCommandProgress(extra, "safe_edit_file checks", (onProgress, workSignal) => safeEditFile({
1178
1184
  path,
1179
1185
  content,
1180
1186
  expected_base_hash,
1181
1187
  validation_command,
1182
1188
  test_command,
1183
1189
  backup,
1184
- });
1190
+ command_policy: { ...command_policy, signal: workSignal, onProgress },
1191
+ }), () => Boolean(server.server?.transport));
1185
1192
  const ledger = await appendRunLedgerEntrySafe({
1186
1193
  tool: "safe_edit_file",
1187
1194
  category: result.ok ? "major_update" : "regression",
@@ -1605,8 +1612,9 @@ export function registerFileTools(server) {
1605
1612
  confirm_multi_file: z.boolean().optional().describe("Deprecated; multi-file rewrites are always refused"),
1606
1613
  validation_command: z.string().optional().describe("Shell command to validate the staged rewrite before promotion"),
1607
1614
  test_command: z.string().optional().describe("Shell command to test the staged rewrite before promotion"),
1615
+ command_policy: commandPolicySchema.optional(),
1608
1616
  session_id: z.string().optional().describe("Optional runtime session id for transition-record emission"),
1609
- }, async ({ plan_id, pattern, rewrite, lang, scope, validation_command, test_command, session_id }) => {
1617
+ }, async ({ plan_id, pattern, rewrite, lang, scope, validation_command, test_command, session_id, command_policy }, extra) => {
1610
1618
  let compiledPlan;
1611
1619
  if (plan_id) {
1612
1620
  compiledPlan = loadStructuralEditPlan(plan_id);
@@ -1700,13 +1708,14 @@ export function registerFileTools(server) {
1700
1708
  isError: true,
1701
1709
  };
1702
1710
  }
1703
- const safeResult = safeEditFile({
1711
+ const safeResult = await withMcpCommandProgress(extra, "astgrep_rewrite checks", (onProgress, workSignal) => safeEditFile({
1704
1712
  path: compiledPlan.target.file,
1705
1713
  content: preview.rewritten_content,
1706
1714
  expected_base_hash: compiledPlan.target.file_hash,
1707
1715
  validation_command: validation_command ?? compiledPlan.validation_command,
1708
1716
  test_command: test_command ?? compiledPlan.test_command,
1709
- });
1717
+ command_policy: { ...command_policy, signal: workSignal, onProgress },
1718
+ }), () => Boolean(server.server?.transport));
1710
1719
  if (!safeResult.ok) {
1711
1720
  await appendAstgrepRewriteTransition(session_id, "failed", `astgrep_rewrite failed before promotion for ${compiledPlan.target.file}: ${safeResult.error ?? "unknown error"}`, [compiledPlan.artifact_path, preview.artifact.artifact_path, compiledPlan.target.file]);
1712
1721
  return {
@@ -1749,13 +1758,14 @@ export function registerFileTools(server) {
1749
1758
  };
1750
1759
  });
1751
1760
  server.tool("apply_patch", "Apply a unified diff patch to a workspace file. Applies the patch to staged content, runs optional validation/tests, and promotes to the target only on success. Cost: moderate.", {
1761
+ command_policy: commandPolicySchema.optional(),
1752
1762
  path: z.string().describe("Workspace-relative file path to patch"),
1753
1763
  patch: z.string().describe("Unified diff patch (output of diff -u or similar)"),
1754
1764
  expected_base_hash: z.string().optional().describe("Optional source precondition checked immediately before promotion; prefer full sha256:<hex>"),
1755
1765
  validation_command: z.string().optional().describe("Shell command to validate after applying (e.g. 'npx tsc --noEmit')"),
1756
1766
  test_command: z.string().optional().describe("Shell command to run tests after applying"),
1757
- }, async ({ path: relPath, patch, expected_base_hash, validation_command, test_command }) => {
1758
- const result = applyPatch({ path: relPath, patch, expected_base_hash, validation_command, test_command });
1767
+ }, async ({ path: relPath, patch, expected_base_hash, validation_command, test_command, command_policy }, extra) => {
1768
+ const result = await withMcpCommandProgress(extra, "apply_patch checks", (onProgress, workSignal) => applyPatch({ path: relPath, patch, expected_base_hash, validation_command, test_command, command_policy: { ...command_policy, signal: workSignal, onProgress } }), () => Boolean(server.server?.transport));
1759
1769
  if (!result.ok) {
1760
1770
  return {
1761
1771
  content: [{ type: "text", text: `apply_patch failed: ${result.error ?? "unknown error"}\n${result.validation_output ?? ""}` }],
@@ -1,7 +1,5 @@
1
- /**
2
- * Framework tool registrations: bootstrap, status, config, routing,
3
- * plus new run_tests and validate_framework tools.
4
- */
1
+ import { commandPolicySchema, withMcpCommandProgress } from "./mcp-command-progress.js";
2
+ import { resolveCurrentWork, formatCurrentWork } from "./ace-autonomy.js";
5
3
  import { z } from "zod";
6
4
  import { bootstrapStoreWorkspace } from "./store/bootstrap-store.js";
7
5
  import { ACE_ROOT_REL, ACE_TASKS_ROOT_REL, ALL_MCP_CLIENTS, ALL_LLM_PROVIDERS, ALL_AGENTS, COMPOSABLE_AGENTS, SWARM_AGENTS, SWARM_SUBAGENT_MAP, WORKSPACE_ROOT, classifyPathSource, detectAssetDrift, getAllMcpServerConfigSnippets, getAgentInstructionPath, getAgentManifestPath, getKernelArtifactPath, getMcpClientInstallHint, getMcpServerConfigSnippet, getTaskArtifactPath, isSwarmRole, listAvailableSkills, normalizePathForValidation, resolveWorkspaceRoot, safeRead, safeWriteAsync, withFileLock, wsPath, } from "./helpers.js";
@@ -123,11 +121,11 @@ function hasArtifactEvidence(reference) {
123
121
  return !content.startsWith("[FILE NOT FOUND]") && !content.startsWith("[ACCESS DENIED]");
124
122
  });
125
123
  }
126
- function evaluateGateTargets(targets) {
124
+ async function evaluateGateTargets(targets, policy = {}) {
127
125
  const results = [];
128
126
  for (const gate of targets) {
129
127
  if (gate.type === "executable" && gate.command.trim().length > 0) {
130
- const testResult = runTestSuite(gate.command);
128
+ const testResult = await runTestSuite(gate.command, policy);
131
129
  results.push({
132
130
  id: gate.id,
133
131
  type: gate.type,
@@ -545,7 +543,6 @@ export function registerFrameworkTools(server) {
545
543
  structuredContent: {
546
544
  detected_domain: detected,
547
545
  suggested_execution_role: executionRoleForDomain(detected),
548
- default_entry_agent: "orchestrator",
549
546
  task_contract_ok: taskContract.ok,
550
547
  },
551
548
  content: [
@@ -559,11 +556,7 @@ export function registerFrameworkTools(server) {
559
556
  `**Primary Swarm Agent(s):** ${activeRoute.swarm_agents
560
557
  .map((agent) => `ACE-${getRoleTitle(agent)}`)
561
558
  .join(", ")}`,
562
- "**Default Entry Agent:** ACE-Orchestrator",
563
- "**Hierarchy Rule:** Top-level work starts with ACE-Orchestrator. VOS, UI, and Coders are delegated specialists, not peer replacements.",
564
- `**Preflight Owner:** ACE-Orchestrator`,
565
559
  `**Task Contract:** ${taskContract.ok ? "aligned" : "attention required"}`,
566
- `**Composable Subagents (Universal):** ${[...COMPOSABLE_AGENTS].join(", ")}`,
567
560
  `**Recommended Delegated Subagents:** ${[...recommendedSubagents].join(", ")}`,
568
561
  `**Pipeline:** ${activeRoute.pipeline}`,
569
562
  `**Recommended Prompt:** ${activeRoute.prompt}`,
@@ -579,16 +572,9 @@ export function registerFrameworkTools(server) {
579
572
  ]
580
573
  : []),
581
574
  "",
582
- "## Preflight Expectations",
583
- "1. Recall current ACE context from TASK, SCOPE, QUALITY_GATES, STATUS, HANDOFF, and EVIDENCE artifacts.",
584
- "2. Validate the ACE quartet before dispatching substantial work.",
585
- "3. Route ambiguity or contract drift through skeptic/validation before handoff.",
586
- "",
587
- "## Next Steps",
588
- `1. Activate prompt: \`${activeRoute.prompt}\``,
589
- "2. Run `validate_framework` and inspect current ACE state before cross-role dispatch.",
590
- "3. Load shared kernel context with `get_kernel_artifact` (`directive_kernel`, `agent_registry`)",
591
- "4. Generate a structured handoff with `create_handoff` only after preflight clears",
575
+ "## Next",
576
+ formatCurrentWork(resolveCurrentWork(), "block"),
577
+ "Role, pipeline, prompt and skill suggestions above are optional aids for this work.",
592
578
  ]
593
579
  .filter(Boolean)
594
580
  .join("\n"),
@@ -927,12 +913,13 @@ export function registerFrameworkTools(server) {
927
913
  });
928
914
  // ── Run Tests (new P0 tool) ───────────────────────────────────────
929
915
  server.tool("run_tests", "Execute the project test suite and report results", {
916
+ ...commandPolicySchema.shape,
930
917
  command: z
931
918
  .string()
932
919
  .optional()
933
920
  .describe("Custom test command (auto-detected from package.json if omitted)"),
934
- }, async ({ command }) => {
935
- const result = runTestSuite(command);
921
+ }, async ({ command, stall_min, kill_min, deadline_min }, extra) => {
922
+ const result = await withMcpCommandProgress(extra, "run_tests", (onProgress, workSignal) => runTestSuite(command, { stall_min, kill_min, deadline_min, signal: workSignal, onProgress }), () => Boolean(server.server?.transport));
936
923
  appendStatusEventSafe({
937
924
  source_module: "capability-safety",
938
925
  event_type: result.ok ? "TESTS_PASSED" : "TESTS_FAILED",
@@ -956,6 +943,7 @@ export function registerFrameworkTools(server) {
956
943
  },
957
944
  });
958
945
  return {
946
+ structuredContent: { ...result },
959
947
  content: [
960
948
  {
961
949
  type: "text",
@@ -964,6 +952,7 @@ export function registerFrameworkTools(server) {
964
952
  `Command: ${result.command}`,
965
953
  `Exit code: ${result.exit_code}`,
966
954
  `Duration: ${result.duration_ms}ms`,
955
+ ...(result.reason_code ? [`Reason: ${result.reason_code}`] : []),
967
956
  `Run ledger: ${ledger.path} (${ledger.entry.id})`,
968
957
  "",
969
958
  "```",
@@ -1444,6 +1433,7 @@ export function registerFrameworkTools(server) {
1444
1433
  });
1445
1434
  // ── Execute Gates (manifest-driven gate runner) ───────────────────
1446
1435
  server.tool("execute_gates", "Run quality gates from agent-state/MODULES/gates/*.json manifests (single source of truth)", {
1436
+ command_policy: commandPolicySchema.optional(),
1447
1437
  gate_ids: z
1448
1438
  .array(z.string())
1449
1439
  .optional()
@@ -1456,7 +1446,7 @@ export function registerFrameworkTools(server) {
1456
1446
  .string()
1457
1447
  .optional()
1458
1448
  .describe("Optional short focus string persisted with skeptic adversarial review evidence."),
1459
- }, async ({ gate_ids, review_mode, review_focus }) => {
1449
+ }, async ({ gate_ids, review_mode, review_focus, command_policy }, extra) => {
1460
1450
  const gatesDir = wsPath("agent-state", "MODULES", "gates");
1461
1451
  const resolved = resolveGateManifests(gatesDir);
1462
1452
  const allGates = resolved.gates;
@@ -1556,7 +1546,7 @@ export function registerFrameworkTools(server) {
1556
1546
  };
1557
1547
  }
1558
1548
  const gateArtifactRefs = targets.map((gate) => gate.source_ref ?? manifestEvidenceRef);
1559
- const results = evaluateGateTargets(targets);
1549
+ const results = await withMcpCommandProgress(extra, "execute_gates", (onProgress, workSignal) => evaluateGateTargets(targets, { ...command_policy, signal: workSignal, onProgress }), () => Boolean(server.server?.transport));
1560
1550
  const passed = results.filter((r) => r.ok).length;
1561
1551
  const failed = results.filter((r) => !r.ok).length;
1562
1552
  const review = review_mode === "skeptic_adversarial"
@@ -1646,6 +1636,7 @@ export function registerFrameworkTools(server) {
1646
1636
  },
1647
1637
  });
1648
1638
  return {
1639
+ structuredContent: { ok: allOk, results },
1649
1640
  content: [
1650
1641
  {
1651
1642
  type: "text",
@@ -1,10 +1,8 @@
1
1
  /**
2
2
  * ACE Goal Engine tool registrations (WS-F).
3
3
  *
4
- * These let a premium host delegate a long-running objective to ACE and poll
5
- * it. `start_goal`/`resume_goal` never block the MCP server for the life of the
6
- * goal: they compile/prepare, then hand execution to a detached `ace goal run`
7
- * child and return immediately. The host polls `get_goal_status`.
4
+ * Engine goals delegate to the existing detached runner. Host goals return
5
+ * assignments to the connected participant and never invoke that executor.
8
6
  */
9
7
  import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
10
8
  export declare function registerGoalTools(server: McpServer): void;