agentic-engineering-harness 0.6.8 → 0.6.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 (45) hide show
  1. package/dist/agents/permissions.d.ts +28 -1
  2. package/dist/agents/permissions.js +188 -29
  3. package/dist/agents/permissions.js.map +1 -1
  4. package/dist/operations/completion.d.ts +26 -0
  5. package/dist/operations/completion.js +152 -0
  6. package/dist/operations/completion.js.map +1 -0
  7. package/dist/operations/controller.d.ts +3 -0
  8. package/dist/operations/controller.js +38 -9
  9. package/dist/operations/controller.js.map +1 -1
  10. package/dist/operations/mcp.js +23 -9
  11. package/dist/operations/mcp.js.map +1 -1
  12. package/dist/operations/state.d.ts +14 -0
  13. package/dist/operations/state.js +26 -0
  14. package/dist/operations/state.js.map +1 -1
  15. package/dist/paseo/launchSpec.d.ts +6 -0
  16. package/dist/paseo/launchSpec.js +25 -3
  17. package/dist/paseo/launchSpec.js.map +1 -1
  18. package/dist/paseo/modePreflight.d.ts +15 -0
  19. package/dist/paseo/modePreflight.js +118 -0
  20. package/dist/paseo/modePreflight.js.map +1 -0
  21. package/dist/paseo/native.d.ts +6 -2
  22. package/dist/paseo/native.js +26 -10
  23. package/dist/paseo/native.js.map +1 -1
  24. package/dist/paseo/runtime.d.ts +7 -2
  25. package/dist/paseo/runtime.js +75 -11
  26. package/dist/paseo/runtime.js.map +1 -1
  27. package/dist/paseo/sdk.d.ts +3 -0
  28. package/dist/paseo/sdk.js +122 -43
  29. package/dist/paseo/sdk.js.map +1 -1
  30. package/dist/paseo/start.d.ts +1 -1
  31. package/dist/paseo/start.js +4 -2
  32. package/dist/paseo/start.js.map +1 -1
  33. package/dist/workers/agentPrompt.js +232 -70
  34. package/dist/workers/agentPrompt.js.map +1 -1
  35. package/dist/workers/direct.js +85 -22
  36. package/dist/workers/direct.js.map +1 -1
  37. package/dist/workers/paseo.js +31 -7
  38. package/dist/workers/paseo.js.map +1 -1
  39. package/dist/workers/podman.js +97 -19
  40. package/dist/workers/podman.js.map +1 -1
  41. package/docs/PASEO_NATIVE.md +93 -4
  42. package/package.json +1 -1
  43. package/presets/agents/orchestration.jsonc +5 -0
  44. package/skills/engineering-workflow/SKILL.md +22 -12
  45. package/skills/paseo-orchestration/SKILL.md +19 -2
@@ -1,5 +1,32 @@
1
1
  import type { HarnessProjectConfig } from "../core/types.js";
2
2
  import type { AgentExecutionSelection } from "./types.js";
3
+ export type OpenCodeAgentBindingSource = "aeh-managed" | "explicit";
4
+ export interface OpenCodeAgentBinding {
5
+ agentId: string;
6
+ source: OpenCodeAgentBindingSource;
7
+ managed: boolean;
8
+ }
9
+ export interface OpenCodeRuntimeProjection {
10
+ binding: OpenCodeAgentBinding;
11
+ config: Record<string, unknown>;
12
+ env: Record<string, string>;
13
+ }
3
14
  export declare function validateExecutionCapabilities(selection: AgentExecutionSelection, transport: string): string[];
4
15
  export declare function permissionSummary(selection: AgentExecutionSelection): string;
5
- export declare function buildOpenCodeRuntimeConfig(selection: AgentExecutionSelection, config?: HarnessProjectConfig): Record<string, unknown>;
16
+ /**
17
+ * Resolve the concrete OpenCode execution identity for an AEH logical agent.
18
+ *
19
+ * Explicit nativeAgent is an externally-authored OpenCode primary/all agent and
20
+ * is preserved exactly. Otherwise AEH owns the native identity and injects a
21
+ * primary agent with a deterministic collision-resistant name into the
22
+ * session-local OpenCode config.
23
+ */
24
+ export declare function resolveOpenCodeAgentBinding(selection: AgentExecutionSelection): OpenCodeAgentBinding;
25
+ /**
26
+ * Compile the inline OpenCode configuration used by direct, Podman and Paseo
27
+ * transports. OPENCODE_CONFIG_CONTENT is loaded after ordinary user/project
28
+ * config, so the AEH-managed identity and policy are deterministic without
29
+ * mutating the user's global OpenCode configuration.
30
+ */
31
+ export declare function buildOpenCodeRuntimeConfig(selection: AgentExecutionSelection, config?: HarnessProjectConfig, binding?: OpenCodeAgentBinding): Record<string, unknown>;
32
+ export declare function compileOpenCodeRuntimeProjection(selection: AgentExecutionSelection, config?: HarnessProjectConfig): OpenCodeRuntimeProjection;
@@ -1,30 +1,189 @@
1
- export function validateExecutionCapabilities(selection, transport) { const issues = []; if (selection.nativeAgent && selection.runtimeCapabilities.nativeAgent === false)
2
- issues.push(`Runtime ${selection.runtimeName} cannot select native agent ${selection.nativeAgent}.`); if (selection.nativeAgent && transport === "paseo" && selection.runtimeCapabilities.nativeAgentViaPaseo !== true)
3
- issues.push(`Agent ${selection.logicalAgent} requires nativeAgent=${selection.nativeAgent}, but runtime ${selection.runtimeName} does not declare nativeAgentViaPaseo. Use transport=direct/podman or configure a Paseo provider that exposes this native agent.`); if (selection.variant && selection.runtimeCapabilities.variantSelection === false)
4
- issues.push(`Runtime ${selection.runtimeName} cannot select variant ${selection.variant}.`); if (selection.role === "implementer" && selection.permissions.write === "deny")
5
- issues.push(`Implementer ${selection.logicalAgent} denies write permission.`); if ((selection.role === "reviewer" || selection.role === "validator") && selection.permissions.write === "allow")
6
- issues.push(`${selection.role} ${selection.logicalAgent} explicitly allows writes; read-only roles should use write=deny unless intentionally mutating.`); if (selection.role === "orchestrator" && selection.permissions.delegate === "deny")
7
- issues.push(`Orchestrator ${selection.logicalAgent} denies delegation.`); return issues; }
8
- export function permissionSummary(selection) { return Object.entries(selection.permissions).map(([key, value]) => `${key}=${value}`).join(", ") || "unspecified"; }
9
- export function buildOpenCodeRuntimeConfig(selection, config) { const permission = {}; const p = selection.permissions; if (p.read)
10
- permission.read = p.read; if (p.write)
11
- permission.edit = p.write; if (p.network) {
12
- permission.webfetch = p.network;
13
- permission.websearch = p.network;
14
- } if (p.delegate)
15
- permission.task = p.delegate; const bash = buildBashPermission(p.shell, p.gitWrite); if (bash)
16
- permission.bash = bash; if (selection.skills.length && !selection.skills.includes("*"))
17
- permission.skill = Object.fromEntries([["*", "deny"], ...selection.skills.map((skill) => [skill, "allow"])]); const mcp = {}; const tools = {}; const configured = config?.mcp?.servers ?? {}; for (const [name, server] of Object.entries(configured)) {
18
- const selected = selection.mcps.includes(name) && server.enabled !== false;
19
- tools[`${name}_*`] = selected;
20
- if (selected)
21
- mcp[name] = toOpenCodeMcp(server);
22
- } for (const name of selection.mcps)
23
- if (!configured[name])
24
- tools[`${name}_*`] = true; return { $schema: "https://opencode.ai/config.json", permission, ...(Object.keys(mcp).length ? { mcp } : {}), ...(Object.keys(tools).length ? { tools } : {}) }; }
25
- function toOpenCodeMcp(server) { if (server.type === "local")
26
- return { type: "local", command: server.command, enabled: true, ...(server.environment ? { environment: server.environment } : {}), ...(server.timeoutMs ? { timeout: server.timeoutMs } : {}) }; return { type: "remote", url: server.url, enabled: true, ...(server.headers ? { headers: server.headers } : {}), ...(server.oauth !== undefined ? { oauth: server.oauth } : {}), ...(server.timeoutMs ? { timeout: server.timeoutMs } : {}) }; }
27
- function buildBashPermission(shell, gitWrite) { if (!gitWrite)
28
- return shell; const result = { "*": shell ?? "ask" }; for (const pattern of ["git add *", "git commit *", "git push *", "git tag *", "git checkout *", "git switch *", "git reset *", "git clean *", "git restore *", "git merge *", "git rebase *", "git cherry-pick *"])
29
- result[pattern] = gitWrite; return result; }
1
+ import { createHash } from "node:crypto";
2
+ export function validateExecutionCapabilities(selection, transport) {
3
+ const issues = [];
4
+ if (selection.nativeAgent && selection.runtimeCapabilities.nativeAgent === false) {
5
+ issues.push(`Runtime ${selection.runtimeName} cannot select native agent ${selection.nativeAgent}.`);
6
+ }
7
+ const nativeAgentViaPaseo = selection.runtimeCapabilities.nativeAgentViaPaseo === true ||
8
+ (selection.runtimeAdapter === "opencode" && selection.paseoProvider === "opencode");
9
+ if (selection.nativeAgent && transport === "paseo" && !nativeAgentViaPaseo) {
10
+ issues.push(`Agent ${selection.logicalAgent} requires nativeAgent=${selection.nativeAgent}, but runtime ${selection.runtimeName} does not support that native agent through Paseo.`);
11
+ }
12
+ if (selection.variant && selection.runtimeCapabilities.variantSelection === false) {
13
+ issues.push(`Runtime ${selection.runtimeName} cannot select variant ${selection.variant}.`);
14
+ }
15
+ if (selection.role === "implementer" && selection.permissions.write === "deny") {
16
+ issues.push(`Implementer ${selection.logicalAgent} denies write permission.`);
17
+ }
18
+ if ((selection.role === "reviewer" || selection.role === "validator") &&
19
+ selection.permissions.write === "allow") {
20
+ issues.push(`${selection.role} ${selection.logicalAgent} explicitly allows writes; read-only roles should use write=deny unless intentionally mutating.`);
21
+ }
22
+ if (selection.role === "orchestrator" && selection.permissions.delegate === "deny") {
23
+ issues.push(`Orchestrator ${selection.logicalAgent} denies delegation.`);
24
+ }
25
+ return issues;
26
+ }
27
+ export function permissionSummary(selection) {
28
+ return (Object.entries(selection.permissions)
29
+ .map(([key, value]) => `${key}=${value}`)
30
+ .join(", ") || "unspecified");
31
+ }
32
+ /**
33
+ * Resolve the concrete OpenCode execution identity for an AEH logical agent.
34
+ *
35
+ * Explicit nativeAgent is an externally-authored OpenCode primary/all agent and
36
+ * is preserved exactly. Otherwise AEH owns the native identity and injects a
37
+ * primary agent with a deterministic collision-resistant name into the
38
+ * session-local OpenCode config.
39
+ */
40
+ export function resolveOpenCodeAgentBinding(selection) {
41
+ const explicit = selection.nativeAgent?.trim();
42
+ if (explicit) {
43
+ return { agentId: explicit, source: "explicit", managed: false };
44
+ }
45
+ return {
46
+ agentId: managedOpenCodeAgentId(selection.logicalAgent),
47
+ source: "aeh-managed",
48
+ managed: true
49
+ };
50
+ }
51
+ /**
52
+ * Compile the inline OpenCode configuration used by direct, Podman and Paseo
53
+ * transports. OPENCODE_CONFIG_CONTENT is loaded after ordinary user/project
54
+ * config, so the AEH-managed identity and policy are deterministic without
55
+ * mutating the user's global OpenCode configuration.
56
+ */
57
+ export function buildOpenCodeRuntimeConfig(selection, config, binding = resolveOpenCodeAgentBinding(selection)) {
58
+ const permission = buildOpenCodePermission(selection);
59
+ const mcp = {};
60
+ const tools = {};
61
+ const configured = config?.mcp?.servers ?? {};
62
+ for (const [name, server] of Object.entries(configured)) {
63
+ const selected = selection.mcps.includes(name) && server.enabled !== false;
64
+ tools[`${name}_*`] = selected;
65
+ if (selected)
66
+ mcp[name] = toOpenCodeMcp(server);
67
+ }
68
+ for (const name of selection.mcps) {
69
+ if (!configured[name])
70
+ tools[`${name}_*`] = true;
71
+ }
72
+ const managedAgent = binding.managed
73
+ ? {
74
+ agent: {
75
+ [binding.agentId]: {
76
+ mode: "primary",
77
+ description: selection.description ??
78
+ `AEH-managed OpenCode execution identity for ${selection.logicalAgent}.`,
79
+ model: selection.modelId,
80
+ prompt: `AEH execution identity: ${selection.logicalAgent}. Follow the task-scoped AEH charter, frozen control-plane context, permissions and acceptance criteria supplied with each turn.`,
81
+ ...(selection.variant ? { variant: selection.variant } : {}),
82
+ ...(selection.temperature !== undefined
83
+ ? { temperature: selection.temperature }
84
+ : {}),
85
+ ...(Object.keys(permission).length ? { permission } : {})
86
+ }
87
+ },
88
+ default_agent: binding.agentId
89
+ }
90
+ : {};
91
+ return {
92
+ $schema: "https://opencode.ai/config.json",
93
+ permission,
94
+ ...managedAgent,
95
+ ...(Object.keys(mcp).length ? { mcp } : {}),
96
+ ...(Object.keys(tools).length ? { tools } : {})
97
+ };
98
+ }
99
+ export function compileOpenCodeRuntimeProjection(selection, config) {
100
+ const binding = resolveOpenCodeAgentBinding(selection);
101
+ const runtimeConfig = buildOpenCodeRuntimeConfig(selection, config, binding);
102
+ return {
103
+ binding,
104
+ config: runtimeConfig,
105
+ env: {
106
+ OPENCODE_CONFIG_CONTENT: JSON.stringify(runtimeConfig)
107
+ }
108
+ };
109
+ }
110
+ function buildOpenCodePermission(selection) {
111
+ const permission = {};
112
+ const p = selection.permissions;
113
+ if (p.read)
114
+ permission.read = p.read;
115
+ if (p.write)
116
+ permission.edit = p.write;
117
+ if (p.network) {
118
+ permission.webfetch = p.network;
119
+ permission.websearch = p.network;
120
+ }
121
+ if (p.delegate)
122
+ permission.task = p.delegate;
123
+ const bash = buildBashPermission(p.shell, p.gitWrite);
124
+ if (bash)
125
+ permission.bash = bash;
126
+ if (selection.skills.length && !selection.skills.includes("*")) {
127
+ permission.skill = Object.fromEntries([
128
+ ["*", "deny"],
129
+ ...selection.skills.map((skill) => [skill, "allow"])
130
+ ]);
131
+ }
132
+ return permission;
133
+ }
134
+ function managedOpenCodeAgentId(logicalAgent) {
135
+ const original = logicalAgent.trim();
136
+ if (!original)
137
+ throw new Error("AEH logical agent name is required for OpenCode identity.");
138
+ const slug = original
139
+ .toLowerCase()
140
+ .replace(/[^a-z0-9._-]+/g, "-")
141
+ .replace(/^-+|-+$/g, "") || "agent";
142
+ const normalizedOriginal = original.toLowerCase();
143
+ if (slug === normalizedOriginal)
144
+ return `aeh-${slug}`;
145
+ const digest = createHash("sha256").update(original).digest("hex").slice(0, 8);
146
+ return `aeh-${slug}-${digest}`;
147
+ }
148
+ function toOpenCodeMcp(server) {
149
+ if (server.type === "local") {
150
+ return {
151
+ type: "local",
152
+ command: server.command,
153
+ enabled: true,
154
+ ...(server.environment ? { environment: server.environment } : {}),
155
+ ...(server.timeoutMs ? { timeout: server.timeoutMs } : {})
156
+ };
157
+ }
158
+ return {
159
+ type: "remote",
160
+ url: server.url,
161
+ enabled: true,
162
+ ...(server.headers ? { headers: server.headers } : {}),
163
+ ...(server.oauth !== undefined ? { oauth: server.oauth } : {}),
164
+ ...(server.timeoutMs ? { timeout: server.timeoutMs } : {})
165
+ };
166
+ }
167
+ function buildBashPermission(shell, gitWrite) {
168
+ if (!gitWrite)
169
+ return shell;
170
+ const result = { "*": shell ?? "ask" };
171
+ for (const pattern of [
172
+ "git add *",
173
+ "git commit *",
174
+ "git push *",
175
+ "git tag *",
176
+ "git checkout *",
177
+ "git switch *",
178
+ "git reset *",
179
+ "git clean *",
180
+ "git restore *",
181
+ "git merge *",
182
+ "git rebase *",
183
+ "git cherry-pick *"
184
+ ]) {
185
+ result[pattern] = gitWrite;
186
+ }
187
+ return result;
188
+ }
30
189
  //# sourceMappingURL=permissions.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"permissions.js","sourceRoot":"","sources":["../../src/agents/permissions.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"permissions.js","sourceRoot":"","sources":["../../src/agents/permissions.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,26 @@
1
+ import { dispatchManagedPaseoAgent } from "../paseo/runtime.js";
2
+ import { recordPaseoTrace } from "../paseo/trace.js";
3
+ import type { OperationRecord } from "./state.js";
4
+ export type OperationCompletionStatus = "PENDING" | "SENT" | "FAILED" | "DISABLED";
5
+ export interface OperationCompletionTarget {
6
+ version: 1;
7
+ operationId: string;
8
+ agentId: string;
9
+ source?: string;
10
+ status: OperationCompletionStatus;
11
+ registeredAt: string;
12
+ attemptedAt?: string;
13
+ sentAt?: string;
14
+ failedAt?: string;
15
+ error?: string;
16
+ }
17
+ export interface OperationCompletionDeps {
18
+ dispatch?: typeof dispatchManagedPaseoAgent;
19
+ trace?: typeof recordPaseoTrace;
20
+ }
21
+ export declare function operationCompletionFile(root: string, operationId: string): string;
22
+ export declare function registerOperationCompletionTarget(root: string, operationId: string, agentId: string, source?: string, trace?: typeof recordPaseoTrace): Promise<OperationCompletionTarget>;
23
+ export declare function disableOperationCompletionTarget(root: string, operationId: string, reason: string, trace?: typeof recordPaseoTrace): Promise<void>;
24
+ export declare function loadOperationCompletionTarget(root: string, operationId: string): Promise<OperationCompletionTarget | undefined>;
25
+ export declare function notifyOperationCompletion(root: string, operation: OperationRecord, deps?: OperationCompletionDeps): Promise<OperationCompletionTarget | undefined>;
26
+ export declare function completionPrompt(operation: OperationRecord): string;
@@ -0,0 +1,152 @@
1
+ import fs from "node:fs/promises";
2
+ import path from "node:path";
3
+ import { dispatchManagedPaseoAgent } from "../paseo/runtime.js";
4
+ import { recordPaseoTrace } from "../paseo/trace.js";
5
+ export function operationCompletionFile(root, operationId) {
6
+ return path.resolve(root, ".harness/operations", `${safeId(operationId)}.completion.json`);
7
+ }
8
+ export async function registerOperationCompletionTarget(root, operationId, agentId, source, trace = recordPaseoTrace) {
9
+ const target = {
10
+ version: 1,
11
+ operationId,
12
+ agentId: requiredId(agentId, "agent id"),
13
+ source,
14
+ status: "PENDING",
15
+ registeredAt: new Date().toISOString()
16
+ };
17
+ await persist(root, target);
18
+ await trace(root, "operation.callback.registered", {
19
+ operationId,
20
+ agentId: target.agentId,
21
+ source: source ?? "unknown"
22
+ });
23
+ return target;
24
+ }
25
+ export async function disableOperationCompletionTarget(root, operationId, reason, trace = recordPaseoTrace) {
26
+ const target = await loadOperationCompletionTarget(root, operationId);
27
+ if (!target || target.status === "SENT")
28
+ return;
29
+ const disabled = {
30
+ ...target,
31
+ status: "DISABLED",
32
+ attemptedAt: new Date().toISOString(),
33
+ error: reason
34
+ };
35
+ await persist(root, disabled);
36
+ await trace(root, "operation.callback.disabled", {
37
+ operationId,
38
+ agentId: target.agentId,
39
+ reason
40
+ });
41
+ }
42
+ export async function loadOperationCompletionTarget(root, operationId) {
43
+ try {
44
+ const value = JSON.parse(await fs.readFile(operationCompletionFile(root, operationId), "utf8"));
45
+ if (value.version !== 1 ||
46
+ value.operationId !== operationId ||
47
+ !value.agentId ||
48
+ !["PENDING", "SENT", "FAILED", "DISABLED"].includes(value.status)) {
49
+ throw new Error("invalid completion target record");
50
+ }
51
+ return value;
52
+ }
53
+ catch (error) {
54
+ if (isMissing(error))
55
+ return undefined;
56
+ throw error;
57
+ }
58
+ }
59
+ export async function notifyOperationCompletion(root, operation, deps = {}) {
60
+ const target = await loadOperationCompletionTarget(root, operation.id);
61
+ if (!target || target.status === "SENT" || target.status === "DISABLED")
62
+ return target;
63
+ const dispatch = deps.dispatch ?? dispatchManagedPaseoAgent;
64
+ const trace = deps.trace ?? recordPaseoTrace;
65
+ const attemptedAt = new Date().toISOString();
66
+ try {
67
+ const result = await dispatch(root, target.agentId, completionPrompt(operation), 60);
68
+ if (result.exitCode !== 0) {
69
+ throw new Error(result.stderr || result.stdout || `Paseo dispatch exited with code ${result.exitCode}`);
70
+ }
71
+ const sent = {
72
+ ...target,
73
+ status: "SENT",
74
+ attemptedAt,
75
+ sentAt: new Date().toISOString(),
76
+ error: undefined
77
+ };
78
+ await persist(root, sent);
79
+ await trace(root, "operation.callback.sent", {
80
+ operationId: operation.id,
81
+ operationStatus: operation.status,
82
+ agentId: target.agentId,
83
+ transport: result.transport,
84
+ resultPath: resultPath(operation) ?? ""
85
+ });
86
+ return sent;
87
+ }
88
+ catch (error) {
89
+ const failed = {
90
+ ...target,
91
+ status: "FAILED",
92
+ attemptedAt,
93
+ failedAt: new Date().toISOString(),
94
+ error: error instanceof Error ? error.message : String(error)
95
+ };
96
+ await persist(root, failed);
97
+ await trace(root, "operation.callback.failed", {
98
+ operationId: operation.id,
99
+ operationStatus: operation.status,
100
+ agentId: target.agentId,
101
+ error: failed.error ?? "unknown"
102
+ });
103
+ return failed;
104
+ }
105
+ }
106
+ export function completionPrompt(operation) {
107
+ const artifact = resultPath(operation);
108
+ const result = operation.result ? JSON.stringify(operation.result) : "{}";
109
+ return [
110
+ "[AEH_OPERATION_COMPLETED]",
111
+ `Detached AEH operation ${operation.id} (${operation.kind}) reached terminal state ${operation.status}.`,
112
+ "This is an internal AEH controller completion callback for the user request that launched this operation; it is not a new user task.",
113
+ "Do not start a duplicate AUDIT/RUN and do not restart the completed operation.",
114
+ `Use aeh_operation_status for ${operation.id} only if you need to refresh durable metadata.${artifact ? ` Read the authoritative artifact ${artifact}.` : ""}`,
115
+ "Continue and finish the original pending user-facing request now, using the durable operation result and artifacts as the source of truth.",
116
+ operation.error ? `Operation error: ${operation.error.split("\n", 1)[0]}` : `Operation result: ${result}`
117
+ ].join("\n");
118
+ }
119
+ function resultPath(operation) {
120
+ const report = operation.result?.report;
121
+ return typeof report === "string" && report.trim() ? report.trim() : undefined;
122
+ }
123
+ async function persist(root, target) {
124
+ const file = operationCompletionFile(root, target.operationId);
125
+ await fs.mkdir(path.dirname(file), { recursive: true });
126
+ const temp = `${file}.${process.pid}.tmp`;
127
+ await fs.writeFile(temp, `${JSON.stringify(target, null, 2)}\n`);
128
+ try {
129
+ await fs.rename(temp, file);
130
+ }
131
+ finally {
132
+ await fs.rm(temp, { force: true }).catch(() => undefined);
133
+ }
134
+ }
135
+ function requiredId(value, name) {
136
+ const trimmed = value.trim();
137
+ if (!trimmed)
138
+ throw new Error(`${name} is required.`);
139
+ return trimmed;
140
+ }
141
+ function safeId(value) {
142
+ if (!/^[A-Za-z0-9._-]+$/.test(value))
143
+ throw new Error(`Invalid operation id '${value}'.`);
144
+ return value;
145
+ }
146
+ function isMissing(error) {
147
+ return Boolean(error &&
148
+ typeof error === "object" &&
149
+ "code" in error &&
150
+ error.code === "ENOENT");
151
+ }
152
+ //# sourceMappingURL=completion.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"completion.js","sourceRoot":"","sources":["../../src/operations/completion.ts"],"names":[],"mappings":"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"}
@@ -6,10 +6,13 @@ export interface StartOperationOptions {
6
6
  nodeExecutable: string;
7
7
  entryFile: string;
8
8
  spawnProcess?: typeof spawn;
9
+ completionAgentId?: string;
10
+ completionSource?: string;
9
11
  }
10
12
  export interface OperationControllerDeps {
11
13
  run?: typeof runProcess;
12
14
  trace?: typeof recordPaseoTrace;
15
+ notifyCompletion?: (root: string, operation: OperationRecord) => Promise<unknown>;
13
16
  }
14
17
  export declare function startDetachedOperation(root: string, kind: OperationKind, payload: OperationPayload, options: StartOperationOptions): Promise<OperationRecord>;
15
18
  export declare function executeOperation(root: string, operationId: string, deps?: OperationControllerDeps): Promise<OperationRecord>;
@@ -8,7 +8,8 @@ import { runTask } from "../core/run.js";
8
8
  import { listManagedPaseoAgents } from "../paseo/runtime.js";
9
9
  import { recordPaseoTrace } from "../paseo/trace.js";
10
10
  import { runProcess } from "../utils/process.js";
11
- import { loadOperation, patchOperation, saveOperation } from "./state.js";
11
+ import { disableOperationCompletionTarget, notifyOperationCompletion, registerOperationCompletionTarget } from "./completion.js";
12
+ import { loadOperation, patchOperation, saveOperation, transitionOperationToTerminal } from "./state.js";
12
13
  export async function startDetachedOperation(root, kind, payload, options) {
13
14
  const absoluteRoot = path.resolve(root);
14
15
  const now = new Date().toISOString();
@@ -25,6 +26,10 @@ export async function startDetachedOperation(root, kind, payload, options) {
25
26
  updatedAt: now
26
27
  };
27
28
  await saveOperation(absoluteRoot, record);
29
+ const completionAgentId = options.completionAgentId?.trim() || process.env.PASEO_AGENT_ID?.trim() || undefined;
30
+ if (completionAgentId) {
31
+ await registerOperationCompletionTarget(absoluteRoot, id, completionAgentId, options.completionSource ?? (options.completionAgentId ? "explicit" : "environment"));
32
+ }
28
33
  const spawnProcess = options.spawnProcess ?? spawn;
29
34
  let child;
30
35
  try {
@@ -40,6 +45,9 @@ export async function startDetachedOperation(root, kind, payload, options) {
40
45
  });
41
46
  }
42
47
  catch (error) {
48
+ if (completionAgentId) {
49
+ await disableOperationCompletionTarget(absoluteRoot, id, `Detached controller spawn failed before the initiating tool returned: ${String(error)}`).catch(() => undefined);
50
+ }
43
51
  return patchOperation(absoluteRoot, id, {
44
52
  status: "FAILED",
45
53
  phase: "spawn-failed",
@@ -92,7 +100,7 @@ export async function executeOperation(root, operationId, deps = {}) {
92
100
  const current = await loadOperation(absoluteRoot, operationId);
93
101
  if (current.status === "CANCELLED")
94
102
  return current;
95
- return patchOperation(absoluteRoot, operationId, {
103
+ return terminalizeOperation(absoluteRoot, operationId, {
96
104
  status: "SUCCEEDED",
97
105
  phase: "finished",
98
106
  finishedAt: new Date().toISOString(),
@@ -102,7 +110,7 @@ export async function executeOperation(root, operationId, deps = {}) {
102
110
  productionSafe: report.productionSafe,
103
111
  report: `.harness/audits/${report.auditId}.json`
104
112
  }
105
- });
113
+ }, deps);
106
114
  }
107
115
  const payload = record.payload;
108
116
  const contract = await loadTaskContract(absoluteRoot, payload.taskId, config);
@@ -112,7 +120,7 @@ export async function executeOperation(root, operationId, deps = {}) {
112
120
  const current = await loadOperation(absoluteRoot, operationId);
113
121
  if (current.status === "CANCELLED")
114
122
  return current;
115
- return patchOperation(absoluteRoot, operationId, {
123
+ return terminalizeOperation(absoluteRoot, operationId, {
116
124
  status: result.status === "PASS" ? "SUCCEEDED" : "FAILED",
117
125
  phase: "finished",
118
126
  finishedAt: new Date().toISOString(),
@@ -121,18 +129,18 @@ export async function executeOperation(root, operationId, deps = {}) {
121
129
  status: result.status,
122
130
  attempts: result.attempts
123
131
  }
124
- });
132
+ }, deps);
125
133
  }
126
134
  catch (error) {
127
135
  const current = await loadOperation(absoluteRoot, operationId).catch(() => record);
128
136
  if (current.status === "CANCELLED")
129
137
  return current;
130
- return patchOperation(absoluteRoot, operationId, {
138
+ return terminalizeOperation(absoluteRoot, operationId, {
131
139
  status: "FAILED",
132
140
  phase: "failed",
133
141
  error: error instanceof Error ? error.stack ?? error.message : String(error),
134
142
  finishedAt: new Date().toISOString()
135
- });
143
+ }, deps);
136
144
  }
137
145
  }
138
146
  export async function waitForOperation(root, operationId, timeoutMs = 1_800_000, pollMs = 500) {
@@ -218,12 +226,12 @@ export async function cancelOperation(root, operationId, deps = {}) {
218
226
  cleanupWarnings.push(`agent ${agentId}: ${stopped.stderr || stopped.stdout || `exit ${stopped.exitCode}`}`);
219
227
  }
220
228
  }
221
- return patchOperation(absoluteRoot, operationId, {
229
+ return terminalizeOperation(absoluteRoot, operationId, {
222
230
  status: "CANCELLED",
223
231
  phase: "cancelled",
224
232
  finishedAt: new Date().toISOString(),
225
233
  cleanupWarnings: cleanupWarnings.length ? cleanupWarnings : undefined
226
- });
234
+ }, deps);
227
235
  }
228
236
  export function createOperationId(kind, seed) {
229
237
  const stamp = new Date()
@@ -233,6 +241,27 @@ export function createOperationId(kind, seed) {
233
241
  const hash = crypto.createHash("sha256").update(seed).digest("hex").slice(0, 8);
234
242
  return `${kind.toUpperCase()}-${stamp}-${hash}`;
235
243
  }
244
+ async function terminalizeOperation(root, operationId, patch, deps) {
245
+ const { record: terminal, transitioned } = await transitionOperationToTerminal(root, operationId, patch);
246
+ if (!transitioned)
247
+ return terminal;
248
+ const trace = deps.trace ?? recordPaseoTrace;
249
+ try {
250
+ if (deps.notifyCompletion)
251
+ await deps.notifyCompletion(root, terminal);
252
+ else
253
+ await notifyOperationCompletion(root, terminal, { trace });
254
+ }
255
+ catch (error) {
256
+ await trace(root, "operation.callback.failed", {
257
+ operationId,
258
+ operationStatus: terminal.status,
259
+ error: error instanceof Error ? error.message : String(error),
260
+ boundary: "controller"
261
+ }).catch(() => undefined);
262
+ }
263
+ return terminal;
264
+ }
236
265
  async function ensureOperationWorkspace(root, record, run, trace) {
237
266
  const title = `AEH ${record.kind.toUpperCase()} · ${record.id}`;
238
267
  const command = `paseo workspace create --isolation local --path ${quote(root)} --title ${quote(title)} --json`;