@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.
- package/CHANGELOG.md +52 -14
- package/README.md +14 -10
- package/assets/.agents/ACE/ACE_coders/AGENTS.md +23 -30
- package/assets/.agents/ACE/ACE_coders/INSTRUCTIONS.md +21 -30
- package/assets/.agents/skills/landing-review-watcher/SKILL.md +1 -1
- package/assets/.agents/skills/learn-from-work/SKILL.md +41 -0
- package/assets/agent-state/ACE_WORKFLOW.md +25 -2
- package/assets/agent-state/MODULES/schemas/ACE_RUNTIME_PROFILE.schema.json +143 -2
- package/assets/agent-state/MODULES/schemas/RUNTIME_EXECUTOR_SESSION_REGISTRY.schema.json +2 -2
- package/assets/agent-state/MODULES/schemas/SWARM_HANDOFF.schema.json +10 -0
- package/assets/eval-battery/battery.json +1 -1
- package/assets/instructions/ACE_Coder.instructions.md +9 -13
- package/assets/scripts/ace-hook-dispatch.mjs +16 -411
- package/assets/tasks/SWARM_HANDOFF.example_ui_to_coders.json +1 -2
- package/assets/vendor/README.md +9 -0
- package/assets/vendor/vericify-reader.mjs +272 -0
- package/assets/vendor/vericify-reader.provenance.json +10 -0
- package/dist/ace-autonomy.d.ts +58 -0
- package/dist/ace-autonomy.js +211 -6
- package/dist/ace-internal-tools.d.ts +1 -0
- package/dist/ace-internal-tools.js +3 -3
- package/dist/ace-server-instructions.d.ts +3 -3
- package/dist/ace-server-instructions.js +46 -192
- package/dist/cli.js +44 -6
- package/dist/experience-reflector.d.ts +7 -0
- package/dist/experience-reflector.js +39 -0
- package/dist/goal-engine.d.ts +64 -7
- package/dist/goal-engine.js +197 -41
- package/dist/handoff-registry.d.ts +10 -0
- package/dist/handoff-registry.js +59 -0
- package/dist/helpers/artifacts.d.ts +6 -2
- package/dist/helpers/artifacts.js +8 -6
- package/dist/helpers/bootstrap.js +13 -20
- package/dist/helpers/path-utils.js +2 -0
- package/dist/helpers/store-resolution.js +18 -3
- package/dist/helpers/workspace-root.d.ts +2 -0
- package/dist/helpers/workspace-root.js +9 -0
- package/dist/helpers.d.ts +1 -0
- package/dist/helpers.js +1 -0
- package/dist/hermes/bridge-protocol.d.ts +1 -1
- package/dist/hermes/session-manager.d.ts +17 -0
- package/dist/hermes/session-manager.js +67 -14
- package/dist/host-goal-engine.d.ts +138 -0
- package/dist/host-goal-engine.js +793 -0
- package/dist/host-goal-status.d.ts +113 -0
- package/dist/host-goal-status.js +175 -0
- package/dist/host-learning.d.ts +68 -0
- package/dist/host-learning.js +115 -0
- package/dist/host-observation.d.ts +12 -0
- package/dist/host-observation.js +91 -0
- package/dist/host-plan-revision.d.ts +14 -0
- package/dist/host-plan-revision.js +101 -0
- package/dist/host-verification-job.d.ts +12 -0
- package/dist/host-verification-job.js +183 -0
- package/dist/host-work-context.d.ts +12 -0
- package/dist/host-work-context.js +8 -0
- package/dist/job-scheduler.d.ts +58 -13
- package/dist/job-scheduler.js +298 -48
- package/dist/job-worker.d.ts +3 -1
- package/dist/job-worker.js +10 -3
- package/dist/kanban.d.ts +4 -1
- package/dist/kanban.js +44 -16
- package/dist/learned-artifacts.d.ts +64 -0
- package/dist/learned-artifacts.js +321 -0
- package/dist/learning-controls.d.ts +142 -0
- package/dist/learning-controls.js +135 -0
- package/dist/learning-input-context.d.ts +9 -0
- package/dist/learning-input-context.js +62 -0
- package/dist/learning-lifecycle.d.ts +10 -0
- package/dist/learning-lifecycle.js +11 -0
- package/dist/learning-overlays.d.ts +3 -0
- package/dist/learning-overlays.js +17 -0
- package/dist/learning-policy.d.ts +40 -0
- package/dist/learning-policy.js +38 -0
- package/dist/learning-records.d.ts +35 -0
- package/dist/learning-records.js +17 -0
- package/dist/learning-scorecard.d.ts +82 -0
- package/dist/learning-scorecard.js +86 -0
- package/dist/learning-serving.d.ts +29 -0
- package/dist/learning-serving.js +134 -0
- package/dist/linked-work.d.ts +9 -0
- package/dist/linked-work.js +28 -0
- package/dist/local-model-runtime.js +1 -1
- package/dist/mcp-command-progress.d.ts +16 -0
- package/dist/mcp-command-progress.js +70 -0
- package/dist/model-bridge.d.ts +14 -13
- package/dist/model-bridge.js +73 -41
- package/dist/orchestrator-supervisor.d.ts +111 -6
- package/dist/orchestrator-supervisor.js +67 -43
- package/dist/plan-proposal.js +3 -3
- package/dist/playbook-curator.d.ts +1 -0
- package/dist/playbook-curator.js +11 -9
- package/dist/process-identity.d.ts +8 -0
- package/dist/process-identity.js +38 -0
- package/dist/progress-command.d.ts +34 -0
- package/dist/progress-command.js +153 -0
- package/dist/prompts.js +15 -15
- package/dist/resources.js +2 -2
- package/dist/runtime-command.d.ts +8 -1
- package/dist/runtime-command.js +48 -7
- package/dist/runtime-executor.js +33 -11
- package/dist/runtime-profile-syntax.d.ts +6 -0
- package/dist/runtime-profile-syntax.js +121 -0
- package/dist/runtime-profile.d.ts +37 -5
- package/dist/runtime-profile.js +36 -129
- package/dist/runtime-tool-specs.js +1 -1
- package/dist/safe-edit.d.ts +7 -3
- package/dist/safe-edit.js +40 -47
- package/dist/schemas.js +4 -2
- package/dist/server.d.ts +2 -16
- package/dist/server.js +14 -20
- package/dist/shared.d.ts +2 -0
- package/dist/shared.js +2 -0
- package/dist/skill-auditor.d.ts +19 -0
- package/dist/skill-auditor.js +32 -2
- package/dist/skill-catalog.d.ts +4 -1
- package/dist/skill-catalog.js +6 -5
- package/dist/store/ace-packed-store.d.ts +5 -1
- package/dist/store/ace-packed-store.js +33 -1
- package/dist/store/bootstrap-store.js +19 -12
- package/dist/store/cache-workspace.d.ts +8 -0
- package/dist/store/cache-workspace.js +94 -27
- package/dist/store/importer.js +11 -20
- package/dist/store/knowledge-bake.d.ts +3 -1
- package/dist/store/knowledge-bake.js +10 -1
- package/dist/store/legacy-vericify-posts.d.ts +8 -0
- package/dist/store/legacy-vericify-posts.js +76 -0
- package/dist/store/materializers/hook-context-materializer.d.ts +2 -1
- package/dist/store/materializers/hook-context-materializer.js +6 -2
- package/dist/store/materializers/host-file-materializer.js +2 -2
- package/dist/store/materializers/projection-manager.d.ts +4 -1
- package/dist/store/materializers/projection-manager.js +10 -3
- package/dist/store/materializers/todo-syncer.d.ts +39 -20
- package/dist/store/materializers/todo-syncer.js +208 -110
- package/dist/store/materializers/vericify-projector.js +15 -26
- package/dist/store/repositories/goal-repository.d.ts +51 -2
- package/dist/store/repositories/goal-repository.js +114 -48
- package/dist/store/repositories/playbook-repository.d.ts +41 -3
- package/dist/store/repositories/playbook-repository.js +61 -5
- package/dist/store/repositories/todo-repository.d.ts +8 -2
- package/dist/store/repositories/todo-repository.js +1 -1
- package/dist/store/repositories/vericify-repository.d.ts +4 -0
- package/dist/store/repositories/vericify-repository.js +46 -0
- package/dist/store/skills-install.d.ts +1 -0
- package/dist/store/skills-install.js +20 -16
- package/dist/store/source-preservation.d.ts +24 -0
- package/dist/store/source-preservation.js +79 -0
- package/dist/store/store-artifacts.js +8 -1
- package/dist/store/test-write-boundary.d.ts +16 -0
- package/dist/store/test-write-boundary.js +175 -0
- package/dist/store/types.d.ts +5 -1
- package/dist/store/write-coordinator.js +16 -0
- package/dist/task-plan-context.d.ts +11 -0
- package/dist/task-plan-context.js +59 -0
- package/dist/todo-state.d.ts +19 -9
- package/dist/todo-state.js +204 -321
- package/dist/tools-agent.d.ts +1 -1
- package/dist/tools-agent.js +38 -62
- package/dist/tools-files.d.ts +0 -3
- package/dist/tools-files.js +21 -11
- package/dist/tools-framework.js +16 -25
- package/dist/tools-goal.d.ts +2 -4
- package/dist/tools-goal.js +119 -16
- package/dist/tools-handoff.d.ts +3 -2
- package/dist/tools-handoff.js +53 -23
- package/dist/tools-lifecycle.js +1 -1
- package/dist/tools-memory.d.ts +0 -3
- package/dist/tools-memory.js +51 -6
- package/dist/tools-scheduler.js +20 -17
- package/dist/tools-todo.js +160 -148
- package/dist/vericify-bridge.d.ts +8 -0
- package/dist/vericify-bridge.js +18 -0
- package/dist/vericify-context.d.ts +4 -0
- package/dist/vericify-context.js +26 -5
- package/dist/vericify-native.d.ts +101 -0
- package/dist/vericify-native.js +221 -0
- package/dist/verification-worker.d.ts +2 -0
- package/dist/verification-worker.js +31 -0
- package/docs/mcp-tool-reference.md +50 -10
- package/docs/troubleshooting.md +29 -0
- package/package.json +19 -6
- package/scripts/dev/run-tests-isolated.mjs +165 -0
- package/scripts/dev/run_hermes_crispr_live.mjs +1 -0
- package/scripts/dev/test-isolation-guard.mjs +20 -0
- package/scripts/dev/test-preload.mjs +153 -0
- package/scripts/dev/test-source-inventory.mjs +31 -0
- package/docs/development.md +0 -46
|
@@ -1,27 +1,17 @@
|
|
|
1
|
-
import { existsSync
|
|
1
|
+
import { existsSync } from "node:fs";
|
|
2
2
|
import { resolve } from "node:path";
|
|
3
|
-
import {
|
|
3
|
+
import { formatCurrentWork, resolveCurrentWork } from "./ace-autonomy.js";
|
|
4
|
+
import { withWorkspaceRoot } from "./helpers/workspace-root.js";
|
|
5
|
+
import { readAceLogicalFile, } from "./ace-state-resolver.js";
|
|
6
|
+
import { getHostBinding } from './host-work-context.js';
|
|
4
7
|
const ACE_ROOT_REL = ".agents/ACE";
|
|
5
|
-
const CORE_FILES = [
|
|
6
|
-
"agent-state/TASK.md",
|
|
7
|
-
"agent-state/STATUS.md",
|
|
8
|
-
"agent-state/SCOPE.md",
|
|
9
|
-
"agent-state/EVIDENCE_LOG.md",
|
|
10
|
-
];
|
|
11
|
-
const STATE_DIRS = [
|
|
12
|
-
"agent-state",
|
|
13
|
-
"global-state",
|
|
14
|
-
"venture-state",
|
|
15
|
-
"brand-state",
|
|
16
|
-
"engineering-state",
|
|
17
|
-
];
|
|
18
8
|
const BOOTSTRAP_TOOLS = new Set([
|
|
19
9
|
"bootstrap_state",
|
|
20
10
|
"recall_context",
|
|
21
11
|
"build_continuity_packet",
|
|
22
12
|
]);
|
|
23
13
|
// Named set — new refresh_* tools must be added here explicitly.
|
|
24
|
-
//
|
|
14
|
+
// Refreshes invalidate the current-work digest too.
|
|
25
15
|
const REFRESH_TOOLS = new Set([
|
|
26
16
|
"refresh_astgrep_index",
|
|
27
17
|
"refresh_tracker_snapshot",
|
|
@@ -30,6 +20,7 @@ const REFRESH_TOOLS = new Set([
|
|
|
30
20
|
// Named set — tools that mutate state but do not match any MUTATION_PREFIXES entry.
|
|
31
21
|
// New mutation tools with non-standard prefixes must be added here explicitly.
|
|
32
22
|
const NAMED_MUTATION_TOOLS = new Set([
|
|
23
|
+
'next_step',
|
|
33
24
|
"rewrite_targets",
|
|
34
25
|
"apply_patch",
|
|
35
26
|
"astgrep_rewrite",
|
|
@@ -64,18 +55,8 @@ const MUTATION_PREFIXES = [
|
|
|
64
55
|
"update_",
|
|
65
56
|
"write_",
|
|
66
57
|
];
|
|
67
|
-
const DIGEST_CACHE_TTL_MS =
|
|
58
|
+
const DIGEST_CACHE_TTL_MS = 2_000;
|
|
68
59
|
const digestCache = new Map();
|
|
69
|
-
function readIfPresent(filePath) {
|
|
70
|
-
if (!existsSync(filePath))
|
|
71
|
-
return undefined;
|
|
72
|
-
try {
|
|
73
|
-
return readFileSync(filePath, "utf-8");
|
|
74
|
-
}
|
|
75
|
-
catch {
|
|
76
|
-
return undefined;
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
60
|
function nonEmptyLines(input) {
|
|
80
61
|
return input
|
|
81
62
|
.split(/\r?\n/)
|
|
@@ -90,34 +71,6 @@ function truncate(input, max = 140) {
|
|
|
90
71
|
return input;
|
|
91
72
|
return `${input.slice(0, Math.max(0, max - 1)).trimEnd()}…`;
|
|
92
73
|
}
|
|
93
|
-
function resolveWorkspacePath(workspaceRoot, relativePath) {
|
|
94
|
-
if (relativePath === "agent-state") {
|
|
95
|
-
const layout = resolveAceStateLayout(workspaceRoot);
|
|
96
|
-
if (layout.physicalMode === "top_level") {
|
|
97
|
-
return resolve(workspaceRoot, "agent-state");
|
|
98
|
-
}
|
|
99
|
-
return resolve(workspaceRoot, ACE_ROOT_REL, "agent-state");
|
|
100
|
-
}
|
|
101
|
-
if (relativePath.startsWith("agent-state/")) {
|
|
102
|
-
return (resolveAceLogicalPath(workspaceRoot, relativePath) ??
|
|
103
|
-
resolve(workspaceRoot, ACE_ROOT_REL, relativePath));
|
|
104
|
-
}
|
|
105
|
-
const canonicalRel = relativePath.startsWith(`${ACE_ROOT_REL}/`)
|
|
106
|
-
? relativePath
|
|
107
|
-
: `agent-state|global-state|venture-state|brand-state|engineering-state`
|
|
108
|
-
.split("|")
|
|
109
|
-
.some((prefix) => relativePath === prefix || relativePath.startsWith(`${prefix}/`))
|
|
110
|
-
? `${ACE_ROOT_REL}/${relativePath}`
|
|
111
|
-
: relativePath;
|
|
112
|
-
const canonicalPath = resolve(workspaceRoot, canonicalRel);
|
|
113
|
-
if (canonicalRel !== relativePath) {
|
|
114
|
-
const legacyPath = resolve(workspaceRoot, relativePath);
|
|
115
|
-
if (!existsSync(canonicalPath) && existsSync(legacyPath)) {
|
|
116
|
-
return legacyPath;
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
return canonicalPath;
|
|
120
|
-
}
|
|
121
74
|
function displayWorkspacePath(workspaceRoot, relativePath) {
|
|
122
75
|
if (relativePath === "agent-state" || relativePath.startsWith("agent-state/")) {
|
|
123
76
|
return relativePath;
|
|
@@ -138,64 +91,8 @@ function displayWorkspacePath(workspaceRoot, relativePath) {
|
|
|
138
91
|
}
|
|
139
92
|
return canonicalRel;
|
|
140
93
|
}
|
|
141
|
-
function listExistingCoreFiles(workspaceRoot) {
|
|
142
|
-
return CORE_FILES.filter((relativePath) => Boolean(resolveAceLogicalPath(workspaceRoot, relativePath)))
|
|
143
|
-
.map((relativePath) => displayWorkspacePath(workspaceRoot, relativePath));
|
|
144
|
-
}
|
|
145
|
-
function listExistingStateDirs(workspaceRoot) {
|
|
146
|
-
return STATE_DIRS.filter((relativePath) => existsSync(resolveWorkspacePath(workspaceRoot, relativePath)))
|
|
147
|
-
.map((relativePath) => displayWorkspacePath(workspaceRoot, relativePath));
|
|
148
|
-
}
|
|
149
|
-
function extractObjective(taskRaw) {
|
|
150
|
-
if (!taskRaw)
|
|
151
|
-
return undefined;
|
|
152
|
-
const match = taskRaw.match(/## Objective\s+([\s\S]*?)(?:\n## |\n# |$)/);
|
|
153
|
-
if (match?.[1]) {
|
|
154
|
-
return truncate(oneLine(match[1]));
|
|
155
|
-
}
|
|
156
|
-
const bodyLine = nonEmptyLines(taskRaw).find((line) => !line.startsWith("#"));
|
|
157
|
-
if (bodyLine) {
|
|
158
|
-
return truncate(oneLine(bodyLine));
|
|
159
|
-
}
|
|
160
|
-
const heading = taskRaw.match(/^#\s+(.+)$/m)?.[1];
|
|
161
|
-
return heading ? truncate(oneLine(heading)) : undefined;
|
|
162
|
-
}
|
|
163
|
-
function extractStatusValue(statusRaw, label) {
|
|
164
|
-
if (!statusRaw)
|
|
165
|
-
return undefined;
|
|
166
|
-
const pattern = new RegExp(`^- ${label}:\\s*(.+)$`, "m");
|
|
167
|
-
const match = statusRaw.match(pattern);
|
|
168
|
-
return match?.[1] ? truncate(oneLine(match[1])) : undefined;
|
|
169
|
-
}
|
|
170
|
-
function extractAutonomyHint(workspaceRoot) {
|
|
171
|
-
const workflowRaw = readAceLogicalFile(workspaceRoot, "agent-state/ACE_WORKFLOW.md");
|
|
172
|
-
if (!workflowRaw)
|
|
173
|
-
return undefined;
|
|
174
|
-
const hints = [];
|
|
175
|
-
if (/^\s*orchestrator_preflight:\s*true\s*$/m.test(workflowRaw)) {
|
|
176
|
-
hints.push("orchestrator preflight");
|
|
177
|
-
}
|
|
178
|
-
if (/^\s*recall_context:\s*true\s*$/m.test(workflowRaw)) {
|
|
179
|
-
hints.push("context recall");
|
|
180
|
-
}
|
|
181
|
-
const reviewMode = workflowRaw.match(/^\s*review_mode:\s*["']?([A-Za-z0-9_-]+)["']?\s*$/m)?.[1];
|
|
182
|
-
if (reviewMode) {
|
|
183
|
-
hints.push(`review mode ${reviewMode}`);
|
|
184
|
-
}
|
|
185
|
-
return hints.length > 0 ? hints.join(", ") : undefined;
|
|
186
|
-
}
|
|
187
94
|
export function buildAceDigest(workspaceRoot) {
|
|
188
|
-
|
|
189
|
-
const statusRaw = readAceLogicalFile(workspaceRoot, "agent-state/STATUS.md");
|
|
190
|
-
const objective = extractObjective(taskRaw);
|
|
191
|
-
const phase = extractStatusValue(statusRaw, "Current phase");
|
|
192
|
-
const blockers = extractStatusValue(statusRaw, "Blockers");
|
|
193
|
-
const parts = [
|
|
194
|
-
objective ? `task=${objective}` : undefined,
|
|
195
|
-
phase ? `phase=${phase}` : undefined,
|
|
196
|
-
blockers ? `blockers=${blockers}` : undefined,
|
|
197
|
-
].filter((value) => Boolean(value));
|
|
198
|
-
return parts.length > 0 ? parts.join(" | ") : "ACE state detected; load recall_context for task and status.";
|
|
95
|
+
return formatCurrentWork(resolveCurrentWork({ workspaceRoot }), "line");
|
|
199
96
|
}
|
|
200
97
|
function buildAceDigestCached(workspaceRoot) {
|
|
201
98
|
const now = Date.now();
|
|
@@ -207,87 +104,34 @@ function buildAceDigestCached(workspaceRoot) {
|
|
|
207
104
|
return value;
|
|
208
105
|
}
|
|
209
106
|
export function buildServerInstructions(workspaceRoot) {
|
|
210
|
-
const coreFiles = listExistingCoreFiles(workspaceRoot);
|
|
211
|
-
const stateDirs = listExistingStateDirs(workspaceRoot);
|
|
212
|
-
const digest = buildAceDigest(workspaceRoot);
|
|
213
|
-
const autonomyHint = extractAutonomyHint(workspaceRoot);
|
|
214
|
-
const lines = [
|
|
215
|
-
"You are operating in an ACE-governed workspace.",
|
|
216
|
-
coreFiles.length > 0
|
|
217
|
-
? `Ground truth for task/status/scope/evidence is store-backed under ${coreFiles.join(", ")} (canonical store: ${ACE_ROOT_REL}/agent-state/ace-state.ace).`
|
|
218
|
-
: `Ground truth is store-backed under ${ACE_ROOT_REL}/agent-state/* artifacts (canonical store: ${ACE_ROOT_REL}/agent-state/ace-state.ace), not chat history.`,
|
|
219
|
-
"`ace compact` and the automatic lifecycle sweep intentionally remove loose agent-state/* files from disk after folding them into the store — this is expected, not data loss, and applies to every swept artifact (kanban, run-ledger, handoffs, playbook, tracker snapshots, etc.), not only TASK/STATUS/SCOPE/EVIDENCE_LOG. If a path is not on disk, call list_workspace on its directory to see the full store-backed listing (or `ace ls` from the CLI), then read it back with read_workspace_file (or `ace read <path>`); never recreate swept files.",
|
|
220
|
-
stateDirs.length > 0
|
|
221
|
-
? `Durable artifacts belong under ${stateDirs.map((entry) => `${entry}/`).join(", ")} and are persisted into the store; the loose copies are sweep inputs, not the source of truth.`
|
|
222
|
-
: undefined,
|
|
223
|
-
"Before significant work, call recall_context to load current task, scope, and status.",
|
|
224
|
-
"Use route_task and get_agent_instructions for role guidance; do not self-assign by guesswork.",
|
|
225
|
-
"After meaningful edits or state changes, call execute_gates and persist evidence/handoffs in ACE artifacts.",
|
|
226
|
-
"For delegated or long-running work, use create_handoff / ack_handoff and append_vericify_process_post instead of ad-hoc status notes.",
|
|
227
|
-
"For self-paced, evidence-gated multi-step objectives beyond this session, use start_goal / get_goal_status / resume_goal / stop_goal (or `ace goal` from the CLI).",
|
|
228
|
-
"Prefer the matching MCP tool over ad-hoc shell/chat tracking: git_status / git_diff / git_log / git_commit for git; enqueue_job / dispatch_jobs / heartbeat_job / get_lock_table for background jobs; snapshot_state / semantic_diff / drift_report / rewrite_targets for change intelligence.",
|
|
229
|
-
"skill_catalog_summary / skill_audit / problem_triage surface packaged skills; get_todo / update_todo / get_run_ledger is the human-facing todo surface; scan_workspace_delta / web_research_packet / codemunch_snapshot / codemunch_index cover workspace-wide search and indexing.",
|
|
230
|
-
`Current ACE digest: ${digest}.`,
|
|
231
|
-
autonomyHint ? `Runtime autonomy signals: ${autonomyHint}.` : undefined,
|
|
232
|
-
];
|
|
233
|
-
return lines.filter((line) => Boolean(line)).join("\n");
|
|
234
|
-
}
|
|
235
|
-
export function buildHostInstructionText(host, workspaceRoot) {
|
|
236
|
-
const hostLabel = {
|
|
237
|
-
claude: "Claude Code",
|
|
238
|
-
copilot: "GitHub Copilot",
|
|
239
|
-
cursor: "Cursor",
|
|
240
|
-
codex: "Codex",
|
|
241
|
-
}[host];
|
|
242
107
|
return [
|
|
243
|
-
|
|
244
|
-
"",
|
|
245
|
-
"This is a thin ACE bootstrap stub.",
|
|
246
|
-
"Full instructions, skills, task packs, and runtime state live in ACE artifacts and should be accessed through the ACE MCP server.",
|
|
247
|
-
"",
|
|
248
|
-
"Session start protocol:",
|
|
249
|
-
"1. Call `recall_context` to load task, scope, and status through the ACE MCP server.",
|
|
250
|
-
"2. Call `route_task` and `get_agent_instructions` before choosing a role.",
|
|
251
|
-
"3. Prefer ACE prompts/resources (`ace-orchestrator`, `get_task_pack`, `get_skill_instructions`) over relying on this file.",
|
|
252
|
-
"4. Read/write task state through MCP tools (`recall_context`, `read_workspace_file`, `write_workspace_file`, lifecycle append tools); do not create files under `agent-state/` directly.",
|
|
253
|
-
"5. For self-paced, evidence-gated multi-step objectives beyond this session, use `start_goal` / `get_goal_status` / `resume_goal` / `stop_goal` (or `ace goal` from the CLI).",
|
|
254
|
-
"6. Also prefer the matching MCP domain over ad-hoc equivalents for git, background jobs/scheduler, change intelligence, discovery/indexing, skills, and todo — see docs/mcp-tool-reference.md for the full per-domain tool catalog.",
|
|
108
|
+
"You are working in an ACE workspace. ACE keeps the durable state of the work so you can spend your turns doing it.",
|
|
255
109
|
"",
|
|
256
|
-
|
|
257
|
-
"- ACE MCP tools are the authoritative interface for task state and lifecycle updates.",
|
|
258
|
-
"- `agent-state/ace-state.ace` is the canonical store path; visible `agent-state/*` files are compatibility projections or sweep inputs.",
|
|
259
|
-
"- `ace compact` and the automatic lifecycle sweep intentionally remove loose `agent-state/*` files from disk after folding them into the store — this is expected, not data loss, for any swept artifact. Do NOT recreate them; if a path isn't on disk, call `list_workspace` on its directory (or `ace ls`) to see the full store-backed listing, then retrieve it via `ace read <path>` or the `read_workspace_file` / `recall_context` MCP tools.",
|
|
260
|
-
"- `.agents/ACE/tasks/todo.md` is the human-facing todo surface.",
|
|
261
|
-
"- Hook context is store-backed in `agent-state/ace-state.ace` and consumed without extra workspace projections.",
|
|
110
|
+
formatCurrentWork(resolveCurrentWork({ workspaceRoot }), "block"),
|
|
262
111
|
"",
|
|
263
|
-
|
|
112
|
+
"Goal work: next_step → do the work with your own tools → complete_step (updates linked work and returns the next step). Create a host-authored plan with start_goal executor:host.",
|
|
113
|
+
"Verification runs in the background. A pending receipt is not goal completion: use get_goal_status view:compact; retain live work. Goals have no default time or step ceiling. Budget increases require operator approval; operator_proposal is not authorization. Never approve your own increase. stop_goal pauses work; resume_goal preserves accepted attempts.",
|
|
114
|
+
"Standalone tasks: update_todo to start or finish; create_handoff to delegate to another agent.",
|
|
115
|
+
"After a restart or compaction: recall_context returns the current work.",
|
|
116
|
+
"State lives in agent-state/ace-state.ace. For a missing file, inspect list_workspace/read_workspace_file; report failed readback as missing history. Claim preservation only with verified readback.",
|
|
117
|
+
"Other ACE tools are optional; see docs/mcp-tool-reference.md.",
|
|
264
118
|
].join("\n");
|
|
265
119
|
}
|
|
120
|
+
export function buildHostInstructionText(host, workspaceRoot) {
|
|
121
|
+
const hostLabel = { claude: "Claude Code", copilot: "GitHub Copilot", cursor: "Cursor", codex: "Codex" }[host];
|
|
122
|
+
return `# ACE Bootstrap For ${hostLabel}\n\n${buildServerInstructions(workspaceRoot)}\n`;
|
|
123
|
+
}
|
|
266
124
|
export function buildBootstrapNudge(workspaceRoot) {
|
|
267
|
-
|
|
268
|
-
return [
|
|
269
|
-
"ACE bootstrap hint: call `recall_context` before significant work so task and scope come from file-backed state.",
|
|
270
|
-
`ACE digest: ${buildAceDigestCached(workspaceRoot)}.`,
|
|
271
|
-
coreFiles.length > 0 ? `Current core files: ${coreFiles.join(", ")}.` : undefined,
|
|
272
|
-
]
|
|
273
|
-
.filter((value) => Boolean(value))
|
|
274
|
-
.join(" ");
|
|
125
|
+
return buildAceDigestCached(workspaceRoot);
|
|
275
126
|
}
|
|
276
|
-
export function buildBootstrapGuidance(workspaceRoot,
|
|
277
|
-
return
|
|
127
|
+
export function buildBootstrapGuidance(workspaceRoot, _toolName) {
|
|
128
|
+
return buildAceDigest(workspaceRoot);
|
|
278
129
|
}
|
|
279
|
-
export function buildMutationGuidance(workspaceRoot,
|
|
280
|
-
|
|
281
|
-
return [
|
|
282
|
-
`ACE digest after \`${toolName}\`: ${buildAceDigestCached(workspaceRoot)}.`,
|
|
283
|
-
`If this changed code or state, reconcile \`${evidencePath}\`, run \`execute_gates\` when appropriate, and use structured handoffs/process posts for delegated follow-up.`,
|
|
284
|
-
].join(" ");
|
|
130
|
+
export function buildMutationGuidance(workspaceRoot, _toolName) {
|
|
131
|
+
return buildAceDigest(workspaceRoot);
|
|
285
132
|
}
|
|
286
|
-
export function buildRefreshGuidance(workspaceRoot,
|
|
287
|
-
return
|
|
288
|
-
`ACE snapshot refresh completed via \`${toolName}\`.`,
|
|
289
|
-
`Current digest: ${buildAceDigestCached(workspaceRoot)}.`,
|
|
290
|
-
].join(" ");
|
|
133
|
+
export function buildRefreshGuidance(workspaceRoot, _toolName) {
|
|
134
|
+
return buildAceDigest(workspaceRoot);
|
|
291
135
|
}
|
|
292
136
|
function isBootstrapTool(toolName) {
|
|
293
137
|
return BOOTSTRAP_TOOLS.has(toolName);
|
|
@@ -329,7 +173,21 @@ export function installAceToolGovernance(server, workspaceRoot) {
|
|
|
329
173
|
const wrapToolCallback = (toolName, callback) => async (...args) => {
|
|
330
174
|
const extra = args.at(-1);
|
|
331
175
|
const sessionId = typeof extra?.sessionId === "string" ? extra.sessionId : undefined;
|
|
332
|
-
const
|
|
176
|
+
const activeStep = withWorkspaceRoot(workspaceRoot, () => getHostBinding(sessionId));
|
|
177
|
+
if (activeStep && !['next_step', 'complete_step', 'start_goal'].includes(toolName)) {
|
|
178
|
+
const { recordHostContact } = await import('./host-goal-engine.js');
|
|
179
|
+
await withWorkspaceRoot(workspaceRoot, () => recordHostContact(activeStep)).catch(error => console.error(`ACE contact pending: ${String(error)}`));
|
|
180
|
+
}
|
|
181
|
+
const rawResult = await withWorkspaceRoot(workspaceRoot, () => callback(...args));
|
|
182
|
+
if (['run_tests', 'execute_gates', 'safe_edit_file', 'apply_patch'].includes(toolName)) {
|
|
183
|
+
const { recordHostToolEvidence } = await import('./host-goal-engine.js');
|
|
184
|
+
await withWorkspaceRoot(workspaceRoot, () => recordHostToolEvidence(toolName, rawResult, activeStep)).catch(error => console.error(`ACE step evidence pending: ${error instanceof Error ? error.message : String(error)}`));
|
|
185
|
+
}
|
|
186
|
+
if (isMutationTool(toolName) || isRefreshTool(toolName) || isBootstrapTool(toolName))
|
|
187
|
+
digestCache.delete(workspaceRoot);
|
|
188
|
+
// These responses already contain current work. Replays must remain byte-for-byte stable.
|
|
189
|
+
if (['next_step', 'complete_step'].includes(toolName) || (toolName === 'start_goal' && args[0]?.executor === 'host'))
|
|
190
|
+
return rawResult;
|
|
333
191
|
const failed = Boolean(rawResult && typeof rawResult === "object" && rawResult.isError);
|
|
334
192
|
if (sessionId && !failed && isBootstrapTool(toolName)) {
|
|
335
193
|
bootstrappedSessions.add(sessionId);
|
|
@@ -345,7 +203,7 @@ export function installAceToolGovernance(server, workspaceRoot) {
|
|
|
345
203
|
next = appendTextContent(next, buildBootstrapNudge(workspaceRoot));
|
|
346
204
|
}
|
|
347
205
|
}
|
|
348
|
-
if (isBootstrapTool(toolName)) {
|
|
206
|
+
if (isBootstrapTool(toolName) && !failed) {
|
|
349
207
|
next = appendTextContent(next, buildBootstrapGuidance(workspaceRoot, toolName));
|
|
350
208
|
}
|
|
351
209
|
else if (isRefreshTool(toolName)) {
|
|
@@ -353,7 +211,7 @@ export function installAceToolGovernance(server, workspaceRoot) {
|
|
|
353
211
|
}
|
|
354
212
|
else if (isMutationTool(toolName)) {
|
|
355
213
|
const mutationKey = sessionId ?? "__global__";
|
|
356
|
-
const currentDigest =
|
|
214
|
+
const currentDigest = buildAceDigest(workspaceRoot);
|
|
357
215
|
const state = mutationGuidanceState.get(mutationKey) ?? { count: 0 };
|
|
358
216
|
state.count += 1;
|
|
359
217
|
const shouldAppend = state.lastDigest === undefined || state.lastDigest !== currentDigest || state.count % 10 === 0;
|
|
@@ -382,11 +240,7 @@ export function installAceToolGovernance(server, workspaceRoot) {
|
|
|
382
240
|
};
|
|
383
241
|
}
|
|
384
242
|
export function buildHookAdditionalContext(workspaceRoot) {
|
|
385
|
-
|
|
386
|
-
buildServerInstructions(workspaceRoot),
|
|
387
|
-
`State digest: ${buildAceDigest(workspaceRoot)}.`,
|
|
388
|
-
];
|
|
389
|
-
return parts.join("\n");
|
|
243
|
+
return formatCurrentWork(resolveCurrentWork({ workspaceRoot }), "block");
|
|
390
244
|
}
|
|
391
245
|
export function buildScopeReminder(workspaceRoot) {
|
|
392
246
|
const scopeRaw = readAceLogicalFile(workspaceRoot, "agent-state/SCOPE.md");
|
package/dist/cli.js
CHANGED
|
@@ -37,6 +37,7 @@ Usage:
|
|
|
37
37
|
ace turnkey [options] Project minimal workspace bootstrap stubs from the ACE store
|
|
38
38
|
ace doctor [options] Validate ACE runtime + MCP readiness
|
|
39
39
|
ace goal <sub> [options] Drive a self-paced, evidence-gated goal loop
|
|
40
|
+
ace learn <sub> [args] List, show, approve, retire, export or report learned artifacts
|
|
40
41
|
ace playbook <sub> [args] Inspect and curate the experience playbook (experimental)
|
|
41
42
|
ace eval [--adapt] [options] Run the eval harness / playbook adaptation cycle (experimental)
|
|
42
43
|
ace compact [--no-sweep] Compact the store and sweep loose generated artifacts
|
|
@@ -57,7 +58,8 @@ Options for goal:
|
|
|
57
58
|
[--max-ticks N] [--goal-id <id>] [--plan-only] [--detach]
|
|
58
59
|
status [<goal_id>] List goals, or show one goal's plan and escalations
|
|
59
60
|
run <goal_id> Drive an already-executing goal to a terminal state
|
|
60
|
-
resume <goal_id>
|
|
61
|
+
resume <goal_id> [--budget-hours N] [--max-replans N]
|
|
62
|
+
Raise explicit allowances if authorized, then resume
|
|
61
63
|
stop <goal_id> Request a cooperative stop (honoured between steps)
|
|
62
64
|
|
|
63
65
|
A goal only reaches \`done\` when its success contract is satisfied: every
|
|
@@ -1019,7 +1021,6 @@ async function runDoctor(args) {
|
|
|
1019
1021
|
if (provider === "ollama" && !hasModel && repairOllama) {
|
|
1020
1022
|
const repair = await runShellCommand(`ollama pull ${model}`, {
|
|
1021
1023
|
cwd: WORKSPACE_ROOT,
|
|
1022
|
-
timeout_ms: 10 * 60_000,
|
|
1023
1024
|
});
|
|
1024
1025
|
await appendRunLedgerEntrySafe({
|
|
1025
1026
|
tool: "doctor",
|
|
@@ -1429,7 +1430,7 @@ async function runGoalCliInner(args) {
|
|
|
1429
1430
|
console.error(`Usage: ace goal ${sub} <goal_id>`);
|
|
1430
1431
|
process.exit(1);
|
|
1431
1432
|
}
|
|
1432
|
-
const run = sub === "resume" ? await engine.resumeGoal(goalId) : await engine.runGoal(goalId);
|
|
1433
|
+
const run = sub === "resume" ? await engine.resumeGoal(goalId, {}, { budget_hours: readNumberFlag(args, "--budget-hours"), max_replans: readNumberFlag(args, "--max-replans") }) : await engine.runGoal(goalId);
|
|
1433
1434
|
console.log(`Goal ${run.goal.goal_id}: ${run.goal.status}${run.goal.reason_code ? ` (${run.goal.reason_code})` : ""}`);
|
|
1434
1435
|
return;
|
|
1435
1436
|
}
|
|
@@ -1439,7 +1440,7 @@ async function runGoalCliInner(args) {
|
|
|
1439
1440
|
console.error("Usage: ace goal stop <goal_id>");
|
|
1440
1441
|
process.exit(1);
|
|
1441
1442
|
}
|
|
1442
|
-
const goal = engine.stopGoal(goalId);
|
|
1443
|
+
const goal = await engine.stopGoal(goalId);
|
|
1443
1444
|
console.log(`Goal ${goal.goal_id}: stop requested (status ${goal.status}).`);
|
|
1444
1445
|
return;
|
|
1445
1446
|
}
|
|
@@ -1703,8 +1704,10 @@ async function main() {
|
|
|
1703
1704
|
if (result.sweep) {
|
|
1704
1705
|
console.log(`Sweep: folded ${result.sweep.cached_files} artifact(s) into the store, freed ${result.sweep.removed_files} loose file(s) from disk, semantic GC removed ${result.sweep.removed_semantic_cache_files}`);
|
|
1705
1706
|
if (result.sweep.removed_files > 0) {
|
|
1706
|
-
console.log(
|
|
1707
|
+
console.log(` Verified source readbacks: ${result.sweep.verified_sources.filter((source) => source.removed).length}. Receipts and exact source bytes are retained under state/migrations/.`);
|
|
1707
1708
|
}
|
|
1709
|
+
for (const warning of result.sweep.warnings)
|
|
1710
|
+
console.warn(` ! ${warning}`);
|
|
1708
1711
|
}
|
|
1709
1712
|
return;
|
|
1710
1713
|
}
|
|
@@ -1747,7 +1750,7 @@ async function main() {
|
|
|
1747
1750
|
console.log(`Cached files: ${result.cached_files}`);
|
|
1748
1751
|
console.log(`Kept projected files: ${result.kept_projected_files}`);
|
|
1749
1752
|
console.log(`Skipped files: ${result.skipped_files}`);
|
|
1750
|
-
console.log(`Removed files: ${result.removed_files}
|
|
1753
|
+
console.log(`Removed files: ${result.removed_files}; verified source readbacks: ${result.verified_sources.filter((source) => source.removed).length}`);
|
|
1751
1754
|
console.log(`Semantic cache GC removed files: ${result.removed_semantic_cache_files}`);
|
|
1752
1755
|
console.log(`Staging GC removed entries: ${stagingGc.removed_entries}`);
|
|
1753
1756
|
if (result.warnings.length > 0) {
|
|
@@ -1775,6 +1778,41 @@ async function main() {
|
|
|
1775
1778
|
await runEvalCli(args.slice(1));
|
|
1776
1779
|
return;
|
|
1777
1780
|
}
|
|
1781
|
+
if (command === 'learn') {
|
|
1782
|
+
const rest = args.slice(1);
|
|
1783
|
+
try {
|
|
1784
|
+
const { listLearning, showLearning, approveLearning, retireLearning, exportLearning, learningReport } = await import('./learning-controls.js');
|
|
1785
|
+
const sub = rest[0] ?? 'list';
|
|
1786
|
+
let result;
|
|
1787
|
+
if (sub === 'list')
|
|
1788
|
+
result = listLearning(WORKSPACE_ROOT);
|
|
1789
|
+
else if (sub === 'show') {
|
|
1790
|
+
result = showLearning(WORKSPACE_ROOT, rest[1]);
|
|
1791
|
+
if (!result)
|
|
1792
|
+
throw Error('Learning item not found: ' + rest[1]);
|
|
1793
|
+
}
|
|
1794
|
+
else if (sub === 'approve') {
|
|
1795
|
+
await approveLearning(WORKSPACE_ROOT, rest[1]);
|
|
1796
|
+
result = { approved: rest[1] };
|
|
1797
|
+
}
|
|
1798
|
+
else if (sub === 'retire') {
|
|
1799
|
+
await retireLearning(WORKSPACE_ROOT, rest[1], readFlagValue(rest, '--reason') ?? '');
|
|
1800
|
+
result = { retired: rest[1] };
|
|
1801
|
+
}
|
|
1802
|
+
else if (sub === 'export')
|
|
1803
|
+
result = await exportLearning(WORKSPACE_ROOT, readFlagValue(rest, '--to') ?? 'docs/learned');
|
|
1804
|
+
else if (sub === 'report')
|
|
1805
|
+
result = learningReport(WORKSPACE_ROOT);
|
|
1806
|
+
else
|
|
1807
|
+
throw Error('Usage: ace learn list|show <id>|approve <id>|retire <id> --reason <text>|export --to docs/learned|report');
|
|
1808
|
+
console.log(JSON.stringify(result, null, 2));
|
|
1809
|
+
}
|
|
1810
|
+
catch (error) {
|
|
1811
|
+
console.error(String(error));
|
|
1812
|
+
process.exitCode = 1;
|
|
1813
|
+
}
|
|
1814
|
+
return;
|
|
1815
|
+
}
|
|
1778
1816
|
if (command === "playbook") {
|
|
1779
1817
|
await runPlaybookCli(args.slice(1));
|
|
1780
1818
|
return;
|
|
@@ -10,4 +10,11 @@ export interface ReflectDeterministicInput {
|
|
|
10
10
|
maxOpsPerRun?: number;
|
|
11
11
|
}
|
|
12
12
|
export declare function reflectDeterministic(input: ReflectDeterministicInput): PlaybookDeltaOp[];
|
|
13
|
+
import type { TaskStep, ObservedRun } from './orchestrator-supervisor.js';
|
|
14
|
+
import type { GoalRecord } from './store/repositories/goal-repository.js';
|
|
15
|
+
export declare function normalizedFailureLines(text: string): string[];
|
|
16
|
+
export declare function failureSignature(text: string): string | undefined;
|
|
17
|
+
export declare function exactRedGreen(runs: ObservedRun[]): Array<[ObservedRun, ObservedRun]>;
|
|
18
|
+
export declare function learningTaskText(step: TaskStep): string;
|
|
19
|
+
export declare function reflectFromStepOutcome(step: TaskStep, goal: Pick<GoalRecord, 'goal_id'>): PlaybookDeltaOp[];
|
|
13
20
|
//# sourceMappingURL=experience-reflector.d.ts.map
|
|
@@ -59,4 +59,43 @@ export function reflectDeterministic(input) {
|
|
|
59
59
|
}
|
|
60
60
|
return ops.slice(0, input.maxOpsPerRun ?? 3);
|
|
61
61
|
}
|
|
62
|
+
// Attached hosts use their existing plan attempts, never local bridge traces.
|
|
63
|
+
import { createHash } from 'node:crypto';
|
|
64
|
+
export function normalizedFailureLines(text) {
|
|
65
|
+
return text.split(/\r?\n/).filter(line => /(error|fail|assert|exception|not ok|✗|denied|timeout)/i.test(line)).map(line => line
|
|
66
|
+
.replace(/\b\d{4}-\d\d-\d\d[T ][\d:.]+Z?\b/g, '<time>')
|
|
67
|
+
.replace(/(?:[A-Za-z]:[\\/]|\/)[^\s'"`:)]+(?::\d+(?::\d+)?)?/g, '<path>')
|
|
68
|
+
.replace(/:\d+(?::\d+)?/g, ':<line>')
|
|
69
|
+
.replace(/\b[0-9a-f]{8,}\b/gi, '<id>')
|
|
70
|
+
.replace(/"[^"\n]*"|'[^'\n]*'|`[^`\n]*`/g, '<value>')
|
|
71
|
+
.replace(/\s+/g, ' ').trim()).filter(Boolean);
|
|
72
|
+
}
|
|
73
|
+
export function failureSignature(text) {
|
|
74
|
+
const lines = normalizedFailureLines(text).slice(0, 3);
|
|
75
|
+
return lines.length ? createHash('sha256').update(lines.join('\n')).digest('hex').slice(0, 12) : undefined;
|
|
76
|
+
}
|
|
77
|
+
export function exactRedGreen(runs) {
|
|
78
|
+
return runs.flatMap((run, index) => {
|
|
79
|
+
if (run.attribution !== 'Linked' || run.outcome !== 'failed' || run.exit_code === null || run.exit_code === 0)
|
|
80
|
+
return [];
|
|
81
|
+
const pass = runs.slice(index + 1).find(next => next.attribution === 'Linked' && next.command === run.command && next.cwd === run.cwd && next.outcome === 'ok' && next.exit_code === 0 && next.at >= run.at);
|
|
82
|
+
return pass ? [[run, pass]] : [];
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
export function learningTaskText(step) {
|
|
86
|
+
const owned = step.attempts_log?.flatMap(a => a.checks ?? []);
|
|
87
|
+
return owned?.length ? owned.map(c => c.command).join('\n') : step.task;
|
|
88
|
+
}
|
|
89
|
+
export function reflectFromStepOutcome(step, goal) {
|
|
90
|
+
const log = step.attempts_log ?? [], current = log.at(-1), previous = log.at(-2);
|
|
91
|
+
if (!current)
|
|
92
|
+
return [];
|
|
93
|
+
const paths = [...new Set([...(step.expected_artifacts ?? []).map(a => a.path), ...current.evidence_refs, ...(previous?.evidence_refs ?? [])].filter(ref => !/^(ep:|ace:|goal:|https?:|vericify:)/.test(ref)).map(p => p.replace(/\\/g, '/').replace(/^\.\//, '').split('/').slice(0, 2).join('/')))];
|
|
94
|
+
const tags = ['test', 'build', 'store', 'todo', 'handoff', 'scheduler', 'migration', 'docs', 'release', 'mcp', 'hook', 'schema'].filter(tag => learningTaskText(step).toLowerCase().includes(tag));
|
|
95
|
+
const ep = (attempt) => `ep:${goal.goal_id}:${step.step_id}:${attempt}`;
|
|
96
|
+
const contrast = current.status === 'done' && previous?.failure_signature && previous.status !== 'done' ? [{ signature: previous.failure_signature, excerpt: previous.failure_excerpt ?? previous.summary, refs: [ep(previous.attempt), ep(current.attempt), ...previous.evidence_refs, ...current.evidence_refs], paths }] : [];
|
|
97
|
+
for (const [failed, passed] of exactRedGreen(current.observed_runs ?? []))
|
|
98
|
+
contrast.push({ signature: failureSignature(failed.output_tail ?? '') ?? 'command-failed', excerpt: failed.output_tail ?? `Command failed: ${failed.command}`, refs: [ep(current.attempt), failed.record_id, passed.record_id, ...current.evidence_refs], paths: [...new Set([...(failed.paths ?? []), ...(passed.paths ?? [])])] });
|
|
99
|
+
return contrast.map(pair => ({ type: 'ADD', section: 'failure_modes', status: 'quarantined', scope: { role: step.role, paths: pair.paths, task_tags: tags, failure_signature: pair.signature }, content: `When ${pair.excerpt.split('\n')[0]} occurred at ${step.role}/${pair.paths.join(', ')}, the passing attempt did: ${current.summary.slice(0, 300)}`, evidence_refs: pair.refs, provenance: { source: 'harvest', run_id: ep(current.attempt) } }));
|
|
100
|
+
}
|
|
62
101
|
//# sourceMappingURL=experience-reflector.js.map
|
package/dist/goal-engine.d.ts
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* ACE Goal Engine (WS-F).
|
|
2
|
+
* ACE Goal Engine (WS-F), with attached MCP execution for host-authored plans.
|
|
3
|
+
* Host goals use the same filesystem records and plan primitives through
|
|
4
|
+
* next_step/complete_step. They enforce their declared contract and explicitly
|
|
5
|
+
* label completion without verification commands as not machine-verified.
|
|
3
6
|
*
|
|
4
7
|
* `startGoal("<objective>")` compiles a plan with ACE's own planner, then a
|
|
5
8
|
* self-paced driver loop (`runGoal`) executes it step-by-step under evidence-
|
|
@@ -9,7 +12,7 @@
|
|
|
9
12
|
* structurally impossible (there is no code path from a model message to
|
|
10
13
|
* `status: "done"`).
|
|
11
14
|
*
|
|
12
|
-
*
|
|
15
|
+
* In the engine-executed path, that guarantee rests on the success contract carrying at least one
|
|
13
16
|
* machine-checkable obligation. A contract with none is refused at `startGoal`
|
|
14
17
|
* and again at verify time with `contract_uncheckable`, never satisfied
|
|
15
18
|
* vacuously — see {@link enforceableObligationCount}.
|
|
@@ -30,6 +33,7 @@ import type { BridgeResult } from "./model-bridge.js";
|
|
|
30
33
|
import { type TaskPlan, type TaskStep } from "./orchestrator-supervisor.js";
|
|
31
34
|
import type { ProposePlanResult } from "./plan-proposal.js";
|
|
32
35
|
import { GoalRepository, type GoalEscalationKind, type GoalRecord, type SuccessContract } from "./store/repositories/goal-repository.js";
|
|
36
|
+
import { type CommandOptions, type CommandPolicy } from './progress-command.js';
|
|
33
37
|
export type { GoalRecord, GoalStatus, GoalBudgets, SuccessContract, } from "./store/repositories/goal-repository.js";
|
|
34
38
|
export interface CompiledPlan {
|
|
35
39
|
proposal: ProposePlanResult;
|
|
@@ -40,6 +44,20 @@ export interface CompiledPlan {
|
|
|
40
44
|
};
|
|
41
45
|
}
|
|
42
46
|
export interface GoalEngineDeps {
|
|
47
|
+
observations?: {
|
|
48
|
+
supported_requirements?: readonly ("action" | "command_pass")[];
|
|
49
|
+
late_evidence?: {
|
|
50
|
+
wait_ms: number;
|
|
51
|
+
poll_ms?: number;
|
|
52
|
+
};
|
|
53
|
+
readWindow: (window: NonNullable<TaskStep["observation_window"]>) => Promise<{
|
|
54
|
+
status: "available" | "pending" | "unavailable";
|
|
55
|
+
records: NonNullable<TaskStep["observation_refs"]>;
|
|
56
|
+
reason_code?: string;
|
|
57
|
+
query?: Record<string, unknown>;
|
|
58
|
+
coverage?: Record<string, unknown>;
|
|
59
|
+
}>;
|
|
60
|
+
};
|
|
43
61
|
workspaceRoot?: string;
|
|
44
62
|
/** Millisecond clock (injectable so budgets/heartbeats are deterministic). */
|
|
45
63
|
now?: () => number;
|
|
@@ -48,7 +66,9 @@ export interface GoalEngineDeps {
|
|
|
48
66
|
/** Compiles an objective into a validated proposal. Default: proposePlan+validatePlan. */
|
|
49
67
|
compilePlan?: (objective: string) => Promise<CompiledPlan>;
|
|
50
68
|
/** Runs a verification command; ok === (exit 0). Default: exec in workspace. */
|
|
51
|
-
runVerification?: (command: string, workspaceRoot: string
|
|
69
|
+
runVerification?: (command: string, workspaceRoot: string, options?: CommandOptions & {
|
|
70
|
+
timeout_ms?: number;
|
|
71
|
+
}) => Promise<{
|
|
52
72
|
ok: boolean;
|
|
53
73
|
output: string;
|
|
54
74
|
}>;
|
|
@@ -62,7 +82,7 @@ export interface GoalEngineDeps {
|
|
|
62
82
|
summary: string;
|
|
63
83
|
payload: Record<string, unknown>;
|
|
64
84
|
}) => Promise<void>;
|
|
65
|
-
/** Vericify process-post sink. Default:
|
|
85
|
+
/** Vericify process-post sink. Default: appendAutomaticVericifyProcessPostSafe. */
|
|
66
86
|
appendProcessPost?: (input: {
|
|
67
87
|
kind: GoalEscalationKind | "progress" | "completion";
|
|
68
88
|
summary: string;
|
|
@@ -71,13 +91,39 @@ export interface GoalEngineDeps {
|
|
|
71
91
|
}) => Promise<void>;
|
|
72
92
|
}
|
|
73
93
|
export interface StartGoalOptions {
|
|
94
|
+
executor?: "engine" | "host";
|
|
95
|
+
agent?: string;
|
|
96
|
+
session_id?: string;
|
|
97
|
+
steps?: Array<{
|
|
98
|
+
id?: string;
|
|
99
|
+
task: string;
|
|
100
|
+
role?: string;
|
|
101
|
+
depends_on?: string[];
|
|
102
|
+
expected_artifacts?: Array<string | {
|
|
103
|
+
path: string;
|
|
104
|
+
required?: boolean;
|
|
105
|
+
transient?: boolean;
|
|
106
|
+
}>;
|
|
107
|
+
required_evidence_refs?: string[];
|
|
108
|
+
required_observation?: "action" | "command_pass";
|
|
109
|
+
}>;
|
|
110
|
+
todo_ids?: Record<string, string>;
|
|
74
111
|
budget_hours?: number;
|
|
75
112
|
max_ticks?: number;
|
|
76
113
|
max_replans?: number;
|
|
77
114
|
plan_only?: boolean;
|
|
78
115
|
goal_id?: string;
|
|
79
116
|
/** Shell commands that must exit 0 before the goal can reach `done`. */
|
|
80
|
-
verify_commands?:
|
|
117
|
+
verify_commands?: VerificationCommand[];
|
|
118
|
+
}
|
|
119
|
+
export type VerificationCommand = string | ({
|
|
120
|
+
cmd: string;
|
|
121
|
+
} & CommandPolicy);
|
|
122
|
+
export declare const verificationCommandText: (command: VerificationCommand) => string;
|
|
123
|
+
export interface ResumeGoalOptions {
|
|
124
|
+
/** New total allowance from the original start, not a restart of the clock. */
|
|
125
|
+
budget_hours?: number;
|
|
126
|
+
max_replans?: number;
|
|
81
127
|
}
|
|
82
128
|
interface ResolvedDeps {
|
|
83
129
|
workspaceRoot: string;
|
|
@@ -91,6 +137,7 @@ interface ResolvedDeps {
|
|
|
91
137
|
emitStatusEvent: NonNullable<GoalEngineDeps["emitStatusEvent"]>;
|
|
92
138
|
appendProcessPost: NonNullable<GoalEngineDeps["appendProcessPost"]>;
|
|
93
139
|
}
|
|
140
|
+
export declare function resolveGoalDeps(deps?: GoalEngineDeps): ResolvedDeps;
|
|
94
141
|
/**
|
|
95
142
|
* The number of machine-checkable obligations in a contract. Zero means the
|
|
96
143
|
* only thing standing between the model and `status: "done"` is the model's own
|
|
@@ -104,6 +151,10 @@ export interface StartGoalResult {
|
|
|
104
151
|
goal: GoalRecord;
|
|
105
152
|
reason_code?: string;
|
|
106
153
|
blocking_findings?: string[];
|
|
154
|
+
assignment?: import('./host-goal-engine.js').Assignment;
|
|
155
|
+
now?: string;
|
|
156
|
+
message?: string;
|
|
157
|
+
waiting_on?: string[];
|
|
107
158
|
}
|
|
108
159
|
export declare function startGoal(objective: string, options?: StartGoalOptions, deps?: GoalEngineDeps): Promise<StartGoalResult>;
|
|
109
160
|
export interface TickGoalResult {
|
|
@@ -119,6 +170,7 @@ export interface ContractCheckResult {
|
|
|
119
170
|
missing_artifacts: string[];
|
|
120
171
|
missing_evidence_refs: string[];
|
|
121
172
|
failed_commands: string[];
|
|
173
|
+
failure_signatures?: string[];
|
|
122
174
|
/** True when the contract carries zero enforceable obligations. Never `ok`. */
|
|
123
175
|
uncheckable: boolean;
|
|
124
176
|
}
|
|
@@ -128,8 +180,11 @@ export interface RunGoalResult {
|
|
|
128
180
|
plan?: TaskPlan;
|
|
129
181
|
}
|
|
130
182
|
export declare function runGoal(goalId: string, deps?: GoalEngineDeps): Promise<RunGoalResult>;
|
|
131
|
-
export declare function resumeGoal(goalId: string, deps?: GoalEngineDeps): Promise<RunGoalResult>;
|
|
132
|
-
|
|
183
|
+
export declare function resumeGoal(goalId: string, deps?: GoalEngineDeps, options?: ResumeGoalOptions): Promise<RunGoalResult>;
|
|
184
|
+
/** Operator-approved increases retain the original clock and all accepted work. */
|
|
185
|
+
export declare function recoverEngineGoalBudgets(goalId: string, options: ResumeGoalOptions, deps?: GoalEngineDeps): Promise<GoalRecord>;
|
|
186
|
+
export { beginStep, completeStep, applyHostResultToStep } from './host-goal-engine.js';
|
|
187
|
+
export declare function stopGoal(goalId: string, deps?: GoalEngineDeps): Promise<GoalRecord>;
|
|
133
188
|
export interface GoalStatusView {
|
|
134
189
|
goal: GoalRecord;
|
|
135
190
|
plan?: TaskPlan;
|
|
@@ -152,4 +207,6 @@ export declare class GoalNotResumableError extends Error {
|
|
|
152
207
|
readonly name = "GoalNotResumableError";
|
|
153
208
|
constructor(goal_id: string, message: string);
|
|
154
209
|
}
|
|
210
|
+
/** Learning groups related failures; loop detection must also retain exact test identities. */
|
|
211
|
+
export declare function failureProgressSignature(text: string): string;
|
|
155
212
|
//# sourceMappingURL=goal-engine.d.ts.map
|