@caupulican/pi-adaptative 0.94.0 → 0.94.1
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 +16 -0
- package/dist/core/agent-paths.d.ts +2 -0
- package/dist/core/agent-paths.d.ts.map +1 -1
- package/dist/core/agent-paths.js +7 -0
- package/dist/core/agent-paths.js.map +1 -1
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +5 -1
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/background-lane-controller.d.ts +8 -0
- package/dist/core/background-lane-controller.d.ts.map +1 -1
- package/dist/core/background-lane-controller.js +75 -5
- package/dist/core/background-lane-controller.js.map +1 -1
- package/dist/core/background-tool-task-controller.d.ts +15 -0
- package/dist/core/background-tool-task-controller.d.ts.map +1 -1
- package/dist/core/background-tool-task-controller.js +122 -15
- package/dist/core/background-tool-task-controller.js.map +1 -1
- package/dist/core/context/long-term-memory-trigger.d.ts +3 -1
- package/dist/core/context/long-term-memory-trigger.d.ts.map +1 -1
- package/dist/core/context/long-term-memory-trigger.js +1 -1
- package/dist/core/context/long-term-memory-trigger.js.map +1 -1
- package/dist/core/context/okf-memory-provider.d.ts +3 -0
- package/dist/core/context/okf-memory-provider.d.ts.map +1 -1
- package/dist/core/context/okf-memory-provider.js +66 -31
- package/dist/core/context/okf-memory-provider.js.map +1 -1
- package/dist/core/context/okf-memory.d.ts +18 -1
- package/dist/core/context/okf-memory.d.ts.map +1 -1
- package/dist/core/context/okf-memory.js +48 -0
- package/dist/core/context/okf-memory.js.map +1 -1
- package/dist/core/delegation/worker-agent-control.d.ts +4 -0
- package/dist/core/delegation/worker-agent-control.d.ts.map +1 -1
- package/dist/core/delegation/worker-agent-control.js.map +1 -1
- package/dist/core/delegation/worker-execution-policy.d.ts.map +1 -1
- package/dist/core/delegation/worker-execution-policy.js +1 -1
- package/dist/core/delegation/worker-execution-policy.js.map +1 -1
- package/dist/core/delegation/worker-notification-coordinator.d.ts +10 -0
- package/dist/core/delegation/worker-notification-coordinator.d.ts.map +1 -1
- package/dist/core/delegation/worker-notification-coordinator.js +69 -3
- package/dist/core/delegation/worker-notification-coordinator.js.map +1 -1
- package/dist/core/foreground-terminal-handoff-controller.d.ts +17 -0
- package/dist/core/foreground-terminal-handoff-controller.d.ts.map +1 -1
- package/dist/core/foreground-terminal-handoff-controller.js +78 -10
- package/dist/core/foreground-terminal-handoff-controller.js.map +1 -1
- package/dist/core/learning/learning-audit.d.ts +5 -1
- package/dist/core/learning/learning-audit.d.ts.map +1 -1
- package/dist/core/learning/learning-audit.js +32 -1
- package/dist/core/learning/learning-audit.js.map +1 -1
- package/dist/core/learning/reflection-engine.d.ts +20 -0
- package/dist/core/learning/reflection-engine.d.ts.map +1 -1
- package/dist/core/learning/reflection-engine.js +58 -0
- package/dist/core/learning/reflection-engine.js.map +1 -1
- package/dist/core/memory/okf-project-memory-store.d.ts +28 -0
- package/dist/core/memory/okf-project-memory-store.d.ts.map +1 -0
- package/dist/core/memory/okf-project-memory-store.js +111 -0
- package/dist/core/memory/okf-project-memory-store.js.map +1 -0
- package/dist/core/memory/providers/file-store.d.ts +42 -1
- package/dist/core/memory/providers/file-store.d.ts.map +1 -1
- package/dist/core/memory/providers/file-store.js +274 -13
- package/dist/core/memory/providers/file-store.js.map +1 -1
- package/dist/core/memory-controller.d.ts +10 -1
- package/dist/core/memory-controller.d.ts.map +1 -1
- package/dist/core/memory-controller.js +72 -8
- package/dist/core/memory-controller.js.map +1 -1
- package/dist/core/provider-prompt-contracts.d.ts.map +1 -1
- package/dist/core/provider-prompt-contracts.js +9 -19
- package/dist/core/provider-prompt-contracts.js.map +1 -1
- package/dist/core/reflection-controller.d.ts +7 -0
- package/dist/core/reflection-controller.d.ts.map +1 -1
- package/dist/core/reflection-controller.js +94 -15
- package/dist/core/reflection-controller.js.map +1 -1
- package/dist/core/tools/delegate-status.d.ts +2 -0
- package/dist/core/tools/delegate-status.d.ts.map +1 -1
- package/dist/core/tools/delegate-status.js +4 -0
- package/dist/core/tools/delegate-status.js.map +1 -1
- package/dist/core/tools/delegate.d.ts +2 -0
- package/dist/core/tools/delegate.d.ts.map +1 -1
- package/dist/core/tools/delegate.js +83 -21
- package/dist/core/tools/delegate.js.map +1 -1
- package/dist/core/tools/tool-task.d.ts +1 -0
- package/dist/core/tools/tool-task.d.ts.map +1 -1
- package/dist/core/tools/tool-task.js +13 -8
- package/dist/core/tools/tool-task.js.map +1 -1
- package/dist/core/util/atomic-file.d.ts +2 -0
- package/dist/core/util/atomic-file.d.ts.map +1 -1
- package/dist/core/util/atomic-file.js +4 -0
- package/dist/core/util/atomic-file.js.map +1 -1
- package/dist/modes/interactive/auto-learn-controller.d.ts.map +1 -1
- package/dist/modes/interactive/auto-learn-controller.js +2 -0
- package/dist/modes/interactive/auto-learn-controller.js.map +1 -1
- package/dist/modes/interactive/components/activity-lane.d.ts.map +1 -1
- package/dist/modes/interactive/components/activity-lane.js +12 -23
- package/dist/modes/interactive/components/activity-lane.js.map +1 -1
- package/dist/modes/interactive/components/custom-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/custom-message.js +125 -1
- package/dist/modes/interactive/components/custom-message.js.map +1 -1
- package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
- package/examples/extensions/custom-provider-anthropic/package.json +1 -1
- package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
- package/examples/extensions/sandbox/package-lock.json +2 -2
- package/examples/extensions/sandbox/package.json +1 -1
- package/examples/extensions/with-deps/package-lock.json +2 -2
- package/examples/extensions/with-deps/package.json +1 -1
- package/npm-shrinkwrap.json +12 -12
- package/package.json +4 -4
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"worker-execution-policy.js","sourceRoot":"","sources":["../../../src/core/delegation/worker-execution-policy.ts"],"names":[],"mappings":"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","sourcesContent":["import path from \"node:path\";\nimport { isPathWithinScope } from \"../autonomy/path-scope.ts\";\nimport { mapToolNamesForPlatform, STABLE_SHELL_TOOL_NAME } from \"../default-tool-surface.ts\";\nimport type {\n\tExecutionGrant,\n\tHarnessCapability,\n\tOrchestrationProfile,\n\tResourcePointer,\n\tRiskBudget,\n\tToolCapabilityManifest,\n\tWorkerExecutionAuthorityContract,\n\tWorkerRole,\n} from \"../orchestration/contracts.ts\";\nimport { buildLaneToolManifests } from \"../orchestration/lane-tool-manifests.ts\";\nimport { ExecutionPolicyCompiler } from \"../orchestration/policy-compiler.ts\";\nimport { intersectRiskBudgets } from \"../orchestration/risk-budget.ts\";\nimport type { ResolvedWorkerDelegationSettings } from \"../settings-manager.ts\";\nimport { getToolCapabilityPolicy, requiredEnvelopeCapabilities } from \"../tool-capability-policy.ts\";\n\nconst READ_TOOL_NAMES = [\"read\", \"grep\", \"find\", \"ls\"] as const;\nconst WRITE_TOOL_NAMES = [\"write\", \"edit\"] as const;\n\nfunction delegatedToolCapabilities(toolName: string): readonly HarnessCapability[] {\n\treturn toolName === \"memory\" ? [\"memory.query\"] : requiredEnvelopeCapabilities(toolName);\n}\n\nexport interface WorkerExecutionPlan {\n\ttoolManifests: readonly ToolCapabilityManifest[];\n\trequiredCapabilities: readonly HarnessCapability[];\n\treadPaths: readonly string[];\n\twritePaths: readonly string[];\n\tdeniedPaths: readonly string[];\n\treadMemory: boolean;\n\twriteEnabled: boolean;\n\tprocessEnabled: boolean;\n\tbudget: RiskBudget;\n}\n\nfunction intersectPathScopes(admittedPaths: readonly string[], currentPaths: readonly string[]): string[] {\n\tconst intersections = admittedPaths.flatMap((admitted) =>\n\t\tcurrentPaths.flatMap((current) => {\n\t\t\tif (isPathWithinScope(current, admitted)) return [current];\n\t\t\tif (isPathWithinScope(admitted, current)) return [admitted];\n\t\t\treturn [];\n\t\t}),\n\t);\n\treturn [...new Set(intersections.map((entry) => path.resolve(entry)))];\n}\n\nexport function workerExecutionAuthorityFromPlan(plan: WorkerExecutionPlan): WorkerExecutionAuthorityContract {\n\treturn {\n\t\tcapabilities: [...plan.requiredCapabilities],\n\t\ttoolNames: plan.toolManifests.map((manifest) => manifest.toolName),\n\t\treadPaths: [...plan.readPaths],\n\t\twritePaths: [...plan.writePaths],\n\t\tdeniedPaths: [...plan.deniedPaths],\n\t\tbudget: { ...plan.budget },\n\t};\n}\n\n/** Apply live revocations to admitted authority without allowing later settings to widen it. */\nexport function narrowWorkerExecutionPlan(\n\tadmitted: WorkerExecutionAuthorityContract,\n\tcurrent: WorkerExecutionPlan,\n): WorkerExecutionPlan {\n\tconst admittedTools = new Set(mapToolNamesForPlatform(admitted.toolNames));\n\tconst admittedCapabilities = new Set(admitted.capabilities);\n\tconst toolManifests = current.toolManifests.filter(\n\t\t(manifest) =>\n\t\t\tadmittedTools.has(manifest.toolName) &&\n\t\t\tmanifest.capabilities.every((capability) => admittedCapabilities.has(capability)),\n\t);\n\tconst requiredCapabilities = [...new Set(toolManifests.flatMap((manifest) => manifest.capabilities))];\n\tconst grantedTools = new Set(toolManifests.map((manifest) => manifest.toolName));\n\tconst readEnabled = requiredCapabilities.some(\n\t\t(capability) => capability === \"filesystem.read\" || capability === \"worktree.read\",\n\t);\n\tconst writeEnabled = grantedTools.has(\"write\") || grantedTools.has(\"edit\");\n\treturn {\n\t\ttoolManifests,\n\t\trequiredCapabilities,\n\t\treadPaths: readEnabled ? intersectPathScopes(admitted.readPaths, current.readPaths) : [],\n\t\twritePaths: writeEnabled ? intersectPathScopes(admitted.writePaths, current.writePaths) : [],\n\t\tdeniedPaths: [...new Set([...admitted.deniedPaths, ...current.deniedPaths].map((entry) => path.resolve(entry)))],\n\t\treadMemory: grantedTools.has(\"memory\"),\n\t\twriteEnabled,\n\t\tprocessEnabled: grantedTools.has(\"run_process\") || grantedTools.has(STABLE_SHELL_TOOL_NAME),\n\t\tbudget: intersectRiskBudgets(admitted.budget, current.budget),\n\t};\n}\n\nexport function buildWorkerExecutionPlan(args: {\n\tprofile: OrchestrationProfile;\n\tsettings: ResolvedWorkerDelegationSettings;\n\tcwd: string;\n\tdeniedPaths: readonly string[];\n\tforegroundMaxCostUsd?: number;\n\tmemoryEnabled: boolean;\n\trequestedReadPaths?: readonly string[];\n\trequestedWritePaths?: readonly string[];\n}): WorkerExecutionPlan {\n\tconst profileToolNames = new Set(mapToolNamesForPlatform(args.profile.toolNames));\n\tconst grantsRead =\n\t\targs.profile.capabilityCeiling.includes(\"filesystem.read\") ||\n\t\targs.profile.capabilityCeiling.includes(\"worktree.read\");\n\tconst writeEligible =\n\t\targs.settings.writeEnabled &&\n\t\targs.settings.writePaths.length > 0 &&\n\t\t(args.profile.capabilityCeiling.includes(\"filesystem.write\") ||\n\t\t\targs.profile.capabilityCeiling.includes(\"worktree.mutate\"));\n\tconst memoryEligible = args.memoryEnabled;\n\tconst processEligible =\n\t\targs.profile.capabilityCeiling.includes(\"process.exec\") ||\n\t\targs.profile.capabilityCeiling.includes(\"tests.execute\");\n\tconst enabledProcessToolNames = processEligible\n\t\t? [\n\t\t\t\t...(args.profile.executionPolicy && profileToolNames.has(\"run_process\") ? ([\"run_process\"] as const) : []),\n\t\t\t\t...(profileToolNames.has(STABLE_SHELL_TOOL_NAME) ? [STABLE_SHELL_TOOL_NAME] : []),\n\t\t\t]\n\t\t: [];\n\tconst enabledToolNames = [\n\t\t...(grantsRead ? READ_TOOL_NAMES : []),\n\t\t...(writeEligible ? WRITE_TOOL_NAMES : []),\n\t\t...enabledProcessToolNames,\n\t\t...(profileToolNames.has(\"delegate\") && args.profile.capabilityCeiling.includes(\"workflow.delegate\")\n\t\t\t? ([\"delegate\"] as const)\n\t\t\t: []),\n\t];\n\tconst toolManifests = buildLaneToolManifests(args.profile, enabledToolNames);\n\tif (memoryEligible) {\n\t\ttoolManifests.push({\n\t\t\ttoolName: \"memory\",\n\t\t\tmoduleSpecifier: \"../tools/memory.ts\",\n\t\t\tcapabilities: delegatedToolCapabilities(\"memory\"),\n\t\t\troles: [args.profile.role],\n\t\t\tenforcements: [\"memory-broker\"],\n\t\t});\n\t}\n\tconst grantedTools = new Set(toolManifests.map((manifest) => manifest.toolName));\n\tconst readEnabled = toolManifests.some((manifest) =>\n\t\tmanifest.capabilities.some((capability) => capability === \"filesystem.read\" || capability === \"worktree.read\"),\n\t);\n\tconst writeEnabled = grantedTools.has(\"write\") || grantedTools.has(\"edit\");\n\tconst readMemory = grantedTools.has(\"memory\");\n\tconst processEnabled = grantedTools.has(\"run_process\") || grantedTools.has(STABLE_SHELL_TOOL_NAME);\n\tconst budget = intersectRiskBudgets(\n\t\targs.profile.budget,\n\t\t...(args.settings.maxUsd > 0 ? [{ maxCostUsd: args.settings.maxUsd }] : []),\n\t\t...(args.foregroundMaxCostUsd !== undefined ? [{ maxCostUsd: args.foregroundMaxCostUsd }] : []),\n\t\t...(args.settings.maxWallClockMs > 0 ? [{ maxWallClockMs: args.settings.maxWallClockMs }] : []),\n\t);\n\treturn {\n\t\ttoolManifests,\n\t\trequiredCapabilities: [...new Set(toolManifests.flatMap((manifest) => manifest.capabilities))],\n\t\treadPaths: readEnabled\n\t\t\t? (args.requestedReadPaths ?? [args.cwd]).map((entry) =>\n\t\t\t\t\tpath.isAbsolute(entry) ? path.resolve(entry) : path.resolve(args.cwd, entry),\n\t\t\t\t)\n\t\t\t: [],\n\t\twritePaths: writeEnabled\n\t\t\t? intersectPathScopes(\n\t\t\t\t\targs.settings.writePaths.map((entry) =>\n\t\t\t\t\t\tpath.isAbsolute(entry) ? path.resolve(entry) : path.resolve(args.cwd, entry),\n\t\t\t\t\t),\n\t\t\t\t\t(args.requestedWritePaths ?? args.settings.writePaths).map((entry) =>\n\t\t\t\t\t\tpath.isAbsolute(entry) ? path.resolve(entry) : path.resolve(args.cwd, entry),\n\t\t\t\t\t),\n\t\t\t\t)\n\t\t\t: [],\n\t\tdeniedPaths: args.deniedPaths.map((entry) => path.resolve(entry)),\n\t\treadMemory,\n\t\twriteEnabled,\n\t\tprocessEnabled,\n\t\tbudget,\n\t};\n}\n\nexport function compileWorkerExecutionGrant(args: {\n\ttarget: { objectiveId: string; taskId: string; attemptId: string };\n\tprofile: OrchestrationProfile;\n\tplan: WorkerExecutionPlan;\n\tresources: readonly ResourcePointer[];\n}): { ok: true; grant: ExecutionGrant } | { ok: false; reasonCodes: readonly string[] } {\n\tconst authorityCapabilities =\n\t\targs.plan.readMemory && !args.profile.capabilityCeiling.includes(\"memory.query\")\n\t\t\t? [...args.profile.capabilityCeiling, \"memory.query\" as const]\n\t\t\t: args.profile.capabilityCeiling;\n\tconst compiled = new ExecutionPolicyCompiler().compile({\n\t\tobjectiveId: args.target.objectiveId,\n\t\ttaskId: args.target.taskId,\n\t\tattemptId: args.target.attemptId,\n\t\tsubjectId: `in-process:${args.target.attemptId}`,\n\t\trole: args.profile.role,\n\t\trequiredCapabilities: args.plan.requiredCapabilities,\n\t\trequestedCapabilities: args.plan.requiredCapabilities,\n\t\tauthorityCapabilities,\n\t\trequestedTools: args.plan.toolManifests.map((manifest) => manifest.toolName),\n\t\ttoolManifests: args.plan.toolManifests,\n\t\tresources: args.resources,\n\t\treadPaths: args.plan.readPaths,\n\t\twritePaths: args.plan.writePaths,\n\t\tdeniedPaths: args.plan.deniedPaths,\n\t\trequestedBudget: args.plan.budget,\n\t\tauthorityBudget: args.plan.budget,\n\t\tpolicyVersion: \"worker-profile-v1\",\n\t});\n\tif (compiled.outcome !== \"allow\") return { ok: false, reasonCodes: compiled.reasonCodes };\n\treturn { ok: true, grant: compiled.grant };\n}\n\n/** Compile the host's durable authority record before an externally managed process is launched. */\nexport function compileManagedProcessExecutionGrant(args: {\n\ttarget: { objectiveId: string; taskId: string; attemptId: string };\n\tlaneId: string;\n\tauthorizationId: string;\n\trole: WorkerRole;\n\tallowedTools: readonly string[];\n\twritePaths: readonly string[];\n\tcwd: string;\n\tdeniedPaths: readonly string[];\n\tbudget: RiskBudget;\n}): { ok: true; grant: ExecutionGrant } | { ok: false; reasonCodes: readonly string[] } {\n\tconst manifests: ToolCapabilityManifest[] = [];\n\tconst unknownTools: string[] = [];\n\tfor (const toolName of [...new Set(args.allowedTools)]) {\n\t\tconst policy = getToolCapabilityPolicy(toolName);\n\t\tconst capabilities = delegatedToolCapabilities(toolName);\n\t\tif (!policy || capabilities.length === 0) {\n\t\t\tunknownTools.push(toolName);\n\t\t\tcontinue;\n\t\t}\n\t\tmanifests.push({\n\t\t\ttoolName,\n\t\t\tmoduleSpecifier: `managed-process:${toolName}`,\n\t\t\tcapabilities,\n\t\t\troles: [args.role],\n\t\t\tenforcements: policy.enforcements,\n\t\t});\n\t}\n\tif (unknownTools.length > 0) return { ok: false, reasonCodes: unknownTools.map((name) => `unknown_tool:${name}`) };\n\tconst capabilities = [...new Set(manifests.flatMap((manifest) => manifest.capabilities))];\n\tconst readEnabled = capabilities.some(\n\t\t(capability) => capability === \"filesystem.read\" || capability === \"worktree.read\",\n\t);\n\tconst compiled = new ExecutionPolicyCompiler().compile({\n\t\t...args.target,\n\t\tsubjectId: `managed:${args.laneId}:${args.authorizationId}`,\n\t\trole: args.role,\n\t\trequiredCapabilities: capabilities,\n\t\trequestedCapabilities: capabilities,\n\t\tauthorityCapabilities: capabilities,\n\t\trequestedTools: manifests.map((manifest) => manifest.toolName),\n\t\ttoolManifests: manifests,\n\t\treadPaths: readEnabled ? [path.resolve(args.cwd)] : [],\n\t\twritePaths: args.writePaths.map((entry) =>\n\t\t\tpath.isAbsolute(entry) ? path.resolve(entry) : path.resolve(args.cwd, entry),\n\t\t),\n\t\tdeniedPaths: args.deniedPaths.map((entry) => path.resolve(entry)),\n\t\trequestedBudget: args.budget,\n\t\tauthorityBudget: args.budget,\n\t\tpolicyVersion: \"managed-process-v1\",\n\t});\n\tif (compiled.outcome !== \"allow\") return { ok: false, reasonCodes: compiled.reasonCodes };\n\treturn { ok: true, grant: compiled.grant };\n}\n"]}
|
|
1
|
+
{"version":3,"file":"worker-execution-policy.js","sourceRoot":"","sources":["../../../src/core/delegation/worker-execution-policy.ts"],"names":[],"mappings":"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","sourcesContent":["import path from \"node:path\";\nimport { isPathWithinScope } from \"../autonomy/path-scope.ts\";\nimport { mapToolNamesForPlatform, STABLE_SHELL_TOOL_NAME } from \"../default-tool-surface.ts\";\nimport type {\n\tExecutionGrant,\n\tHarnessCapability,\n\tOrchestrationProfile,\n\tResourcePointer,\n\tRiskBudget,\n\tToolCapabilityManifest,\n\tWorkerExecutionAuthorityContract,\n\tWorkerRole,\n} from \"../orchestration/contracts.ts\";\nimport { buildLaneToolManifests } from \"../orchestration/lane-tool-manifests.ts\";\nimport { ExecutionPolicyCompiler } from \"../orchestration/policy-compiler.ts\";\nimport { intersectRiskBudgets } from \"../orchestration/risk-budget.ts\";\nimport type { ResolvedWorkerDelegationSettings } from \"../settings-manager.ts\";\nimport { getToolCapabilityPolicy, requiredEnvelopeCapabilities } from \"../tool-capability-policy.ts\";\n\nconst READ_TOOL_NAMES = [\"read\", \"grep\", \"find\", \"ls\"] as const;\nconst WRITE_TOOL_NAMES = [\"write\", \"edit\"] as const;\n\nfunction delegatedToolCapabilities(toolName: string): readonly HarnessCapability[] {\n\treturn toolName === \"memory\" ? [\"memory.query\"] : requiredEnvelopeCapabilities(toolName);\n}\n\nexport interface WorkerExecutionPlan {\n\ttoolManifests: readonly ToolCapabilityManifest[];\n\trequiredCapabilities: readonly HarnessCapability[];\n\treadPaths: readonly string[];\n\twritePaths: readonly string[];\n\tdeniedPaths: readonly string[];\n\treadMemory: boolean;\n\twriteEnabled: boolean;\n\tprocessEnabled: boolean;\n\tbudget: RiskBudget;\n}\n\nfunction intersectPathScopes(admittedPaths: readonly string[], currentPaths: readonly string[]): string[] {\n\tconst intersections = admittedPaths.flatMap((admitted) =>\n\t\tcurrentPaths.flatMap((current) => {\n\t\t\tif (isPathWithinScope(current, admitted)) return [current];\n\t\t\tif (isPathWithinScope(admitted, current)) return [admitted];\n\t\t\treturn [];\n\t\t}),\n\t);\n\treturn [...new Set(intersections.map((entry) => path.resolve(entry)))];\n}\n\nexport function workerExecutionAuthorityFromPlan(plan: WorkerExecutionPlan): WorkerExecutionAuthorityContract {\n\treturn {\n\t\tcapabilities: [...plan.requiredCapabilities],\n\t\ttoolNames: plan.toolManifests.map((manifest) => manifest.toolName),\n\t\treadPaths: [...plan.readPaths],\n\t\twritePaths: [...plan.writePaths],\n\t\tdeniedPaths: [...plan.deniedPaths],\n\t\tbudget: { ...plan.budget },\n\t};\n}\n\n/** Apply live revocations to admitted authority without allowing later settings to widen it. */\nexport function narrowWorkerExecutionPlan(\n\tadmitted: WorkerExecutionAuthorityContract,\n\tcurrent: WorkerExecutionPlan,\n): WorkerExecutionPlan {\n\tconst admittedTools = new Set(mapToolNamesForPlatform(admitted.toolNames));\n\tconst admittedCapabilities = new Set(admitted.capabilities);\n\tconst toolManifests = current.toolManifests.filter(\n\t\t(manifest) =>\n\t\t\tadmittedTools.has(manifest.toolName) &&\n\t\t\tmanifest.capabilities.every((capability) => admittedCapabilities.has(capability)),\n\t);\n\tconst requiredCapabilities = [...new Set(toolManifests.flatMap((manifest) => manifest.capabilities))];\n\tconst grantedTools = new Set(toolManifests.map((manifest) => manifest.toolName));\n\tconst readEnabled = requiredCapabilities.some(\n\t\t(capability) => capability === \"filesystem.read\" || capability === \"worktree.read\",\n\t);\n\tconst writeEnabled = grantedTools.has(\"write\") || grantedTools.has(\"edit\");\n\treturn {\n\t\ttoolManifests,\n\t\trequiredCapabilities,\n\t\treadPaths: readEnabled ? intersectPathScopes(admitted.readPaths, current.readPaths) : [],\n\t\twritePaths: writeEnabled ? intersectPathScopes(admitted.writePaths, current.writePaths) : [],\n\t\tdeniedPaths: [...new Set([...admitted.deniedPaths, ...current.deniedPaths].map((entry) => path.resolve(entry)))],\n\t\treadMemory: grantedTools.has(\"memory\"),\n\t\twriteEnabled,\n\t\tprocessEnabled: grantedTools.has(\"run_process\") || grantedTools.has(STABLE_SHELL_TOOL_NAME),\n\t\tbudget: intersectRiskBudgets(admitted.budget, current.budget),\n\t};\n}\n\nexport function buildWorkerExecutionPlan(args: {\n\tprofile: OrchestrationProfile;\n\tsettings: ResolvedWorkerDelegationSettings;\n\tcwd: string;\n\tdeniedPaths: readonly string[];\n\tforegroundMaxCostUsd?: number;\n\tmemoryEnabled: boolean;\n\trequestedReadPaths?: readonly string[];\n\trequestedWritePaths?: readonly string[];\n}): WorkerExecutionPlan {\n\tconst profileToolNames = new Set(mapToolNamesForPlatform(args.profile.toolNames));\n\tconst grantsRead =\n\t\targs.profile.capabilityCeiling.includes(\"filesystem.read\") ||\n\t\targs.profile.capabilityCeiling.includes(\"worktree.read\");\n\tconst writeEligible =\n\t\targs.settings.writeEnabled &&\n\t\targs.settings.writePaths.length > 0 &&\n\t\t(args.profile.capabilityCeiling.includes(\"filesystem.write\") ||\n\t\t\targs.profile.capabilityCeiling.includes(\"worktree.mutate\"));\n\tconst memoryEligible = args.memoryEnabled;\n\tconst processEligible =\n\t\targs.profile.capabilityCeiling.includes(\"process.exec\") ||\n\t\targs.profile.capabilityCeiling.includes(\"tests.execute\");\n\tconst enabledProcessToolNames = processEligible\n\t\t? [\n\t\t\t\t...(args.profile.executionPolicy && profileToolNames.has(\"run_process\") ? ([\"run_process\"] as const) : []),\n\t\t\t\t...(profileToolNames.has(STABLE_SHELL_TOOL_NAME) ? [STABLE_SHELL_TOOL_NAME] : []),\n\t\t\t]\n\t\t: [];\n\tconst enabledToolNames = [\n\t\t...(grantsRead ? READ_TOOL_NAMES : []),\n\t\t...(writeEligible ? WRITE_TOOL_NAMES : []),\n\t\t...enabledProcessToolNames,\n\t\t...(profileToolNames.has(\"delegate\") && args.profile.capabilityCeiling.includes(\"workflow.delegate\")\n\t\t\t? ([\"delegate\"] as const)\n\t\t\t: []),\n\t];\n\tconst toolManifests = buildLaneToolManifests(args.profile, enabledToolNames);\n\tif (memoryEligible) {\n\t\ttoolManifests.push({\n\t\t\ttoolName: \"memory\",\n\t\t\tmoduleSpecifier: \"../tools/memory.ts\",\n\t\t\tcapabilities: delegatedToolCapabilities(\"memory\"),\n\t\t\troles: [args.profile.role],\n\t\t\tenforcements: [\"memory-broker\"],\n\t\t});\n\t}\n\tconst grantedTools = new Set(toolManifests.map((manifest) => manifest.toolName));\n\tconst readEnabled = toolManifests.some((manifest) =>\n\t\tmanifest.capabilities.some((capability) => capability === \"filesystem.read\" || capability === \"worktree.read\"),\n\t);\n\tconst writeEnabled = grantedTools.has(\"write\") || grantedTools.has(\"edit\");\n\tconst readMemory = grantedTools.has(\"memory\");\n\tconst processEnabled = grantedTools.has(\"run_process\") || grantedTools.has(STABLE_SHELL_TOOL_NAME);\n\tconst budget = intersectRiskBudgets(\n\t\targs.profile.budget,\n\t\t...(args.settings.maxUsd > 0 ? [{ maxCostUsd: args.settings.maxUsd }] : []),\n\t\t...(args.foregroundMaxCostUsd !== undefined ? [{ maxCostUsd: args.foregroundMaxCostUsd }] : []),\n\t\t...(args.settings.maxWallClockMs > 0 ? [{ maxWallClockMs: args.settings.maxWallClockMs }] : []),\n\t);\n\treturn {\n\t\ttoolManifests,\n\t\trequiredCapabilities: [...new Set(toolManifests.flatMap((manifest) => manifest.capabilities))],\n\t\treadPaths: readEnabled\n\t\t\t? intersectPathScopes(\n\t\t\t\t\t[path.resolve(args.cwd)],\n\t\t\t\t\t(args.requestedReadPaths ?? [args.cwd]).map((entry) =>\n\t\t\t\t\t\tpath.isAbsolute(entry) ? path.resolve(entry) : path.resolve(args.cwd, entry),\n\t\t\t\t\t),\n\t\t\t\t)\n\t\t\t: [],\n\t\twritePaths: writeEnabled\n\t\t\t? intersectPathScopes(\n\t\t\t\t\targs.settings.writePaths.map((entry) =>\n\t\t\t\t\t\tpath.isAbsolute(entry) ? path.resolve(entry) : path.resolve(args.cwd, entry),\n\t\t\t\t\t),\n\t\t\t\t\t(args.requestedWritePaths ?? args.settings.writePaths).map((entry) =>\n\t\t\t\t\t\tpath.isAbsolute(entry) ? path.resolve(entry) : path.resolve(args.cwd, entry),\n\t\t\t\t\t),\n\t\t\t\t)\n\t\t\t: [],\n\t\tdeniedPaths: args.deniedPaths.map((entry) => path.resolve(entry)),\n\t\treadMemory,\n\t\twriteEnabled,\n\t\tprocessEnabled,\n\t\tbudget,\n\t};\n}\n\nexport function compileWorkerExecutionGrant(args: {\n\ttarget: { objectiveId: string; taskId: string; attemptId: string };\n\tprofile: OrchestrationProfile;\n\tplan: WorkerExecutionPlan;\n\tresources: readonly ResourcePointer[];\n}): { ok: true; grant: ExecutionGrant } | { ok: false; reasonCodes: readonly string[] } {\n\tconst authorityCapabilities =\n\t\targs.plan.readMemory && !args.profile.capabilityCeiling.includes(\"memory.query\")\n\t\t\t? [...args.profile.capabilityCeiling, \"memory.query\" as const]\n\t\t\t: args.profile.capabilityCeiling;\n\tconst compiled = new ExecutionPolicyCompiler().compile({\n\t\tobjectiveId: args.target.objectiveId,\n\t\ttaskId: args.target.taskId,\n\t\tattemptId: args.target.attemptId,\n\t\tsubjectId: `in-process:${args.target.attemptId}`,\n\t\trole: args.profile.role,\n\t\trequiredCapabilities: args.plan.requiredCapabilities,\n\t\trequestedCapabilities: args.plan.requiredCapabilities,\n\t\tauthorityCapabilities,\n\t\trequestedTools: args.plan.toolManifests.map((manifest) => manifest.toolName),\n\t\ttoolManifests: args.plan.toolManifests,\n\t\tresources: args.resources,\n\t\treadPaths: args.plan.readPaths,\n\t\twritePaths: args.plan.writePaths,\n\t\tdeniedPaths: args.plan.deniedPaths,\n\t\trequestedBudget: args.plan.budget,\n\t\tauthorityBudget: args.plan.budget,\n\t\tpolicyVersion: \"worker-profile-v1\",\n\t});\n\tif (compiled.outcome !== \"allow\") return { ok: false, reasonCodes: compiled.reasonCodes };\n\treturn { ok: true, grant: compiled.grant };\n}\n\n/** Compile the host's durable authority record before an externally managed process is launched. */\nexport function compileManagedProcessExecutionGrant(args: {\n\ttarget: { objectiveId: string; taskId: string; attemptId: string };\n\tlaneId: string;\n\tauthorizationId: string;\n\trole: WorkerRole;\n\tallowedTools: readonly string[];\n\twritePaths: readonly string[];\n\tcwd: string;\n\tdeniedPaths: readonly string[];\n\tbudget: RiskBudget;\n}): { ok: true; grant: ExecutionGrant } | { ok: false; reasonCodes: readonly string[] } {\n\tconst manifests: ToolCapabilityManifest[] = [];\n\tconst unknownTools: string[] = [];\n\tfor (const toolName of [...new Set(args.allowedTools)]) {\n\t\tconst policy = getToolCapabilityPolicy(toolName);\n\t\tconst capabilities = delegatedToolCapabilities(toolName);\n\t\tif (!policy || capabilities.length === 0) {\n\t\t\tunknownTools.push(toolName);\n\t\t\tcontinue;\n\t\t}\n\t\tmanifests.push({\n\t\t\ttoolName,\n\t\t\tmoduleSpecifier: `managed-process:${toolName}`,\n\t\t\tcapabilities,\n\t\t\troles: [args.role],\n\t\t\tenforcements: policy.enforcements,\n\t\t});\n\t}\n\tif (unknownTools.length > 0) return { ok: false, reasonCodes: unknownTools.map((name) => `unknown_tool:${name}`) };\n\tconst capabilities = [...new Set(manifests.flatMap((manifest) => manifest.capabilities))];\n\tconst readEnabled = capabilities.some(\n\t\t(capability) => capability === \"filesystem.read\" || capability === \"worktree.read\",\n\t);\n\tconst compiled = new ExecutionPolicyCompiler().compile({\n\t\t...args.target,\n\t\tsubjectId: `managed:${args.laneId}:${args.authorizationId}`,\n\t\trole: args.role,\n\t\trequiredCapabilities: capabilities,\n\t\trequestedCapabilities: capabilities,\n\t\tauthorityCapabilities: capabilities,\n\t\trequestedTools: manifests.map((manifest) => manifest.toolName),\n\t\ttoolManifests: manifests,\n\t\treadPaths: readEnabled ? [path.resolve(args.cwd)] : [],\n\t\twritePaths: args.writePaths.map((entry) =>\n\t\t\tpath.isAbsolute(entry) ? path.resolve(entry) : path.resolve(args.cwd, entry),\n\t\t),\n\t\tdeniedPaths: args.deniedPaths.map((entry) => path.resolve(entry)),\n\t\trequestedBudget: args.budget,\n\t\tauthorityBudget: args.budget,\n\t\tpolicyVersion: \"managed-process-v1\",\n\t});\n\tif (compiled.outcome !== \"allow\") return { ok: false, reasonCodes: compiled.reasonCodes };\n\treturn { ok: true, grant: compiled.grant };\n}\n"]}
|
|
@@ -2,9 +2,12 @@ import type { LaneRecord, LaneTerminalStatus } from "../autonomy/lane-tracker.ts
|
|
|
2
2
|
export interface WorkerTerminalHandoffRecord {
|
|
3
3
|
laneId: string;
|
|
4
4
|
status: LaneTerminalStatus;
|
|
5
|
+
completedAt?: string;
|
|
5
6
|
reasonCode?: string;
|
|
6
7
|
/** Goal ownership retained until delivery so a stopped goal cannot be resurrected by a late terminal. */
|
|
7
8
|
goalId?: string;
|
|
9
|
+
/** Runtime-only receipt. Observation consumes delivery, never mutation review. */
|
|
10
|
+
observedAt?: string;
|
|
8
11
|
}
|
|
9
12
|
export interface WorkerNotificationStatus {
|
|
10
13
|
active: number;
|
|
@@ -22,6 +25,8 @@ export interface WorkerNotificationCoordinatorOptions {
|
|
|
22
25
|
notify(records: readonly WorkerTerminalHandoffRecord[]): Promise<void>;
|
|
23
26
|
warn(message: string): void;
|
|
24
27
|
markDurableDelivered(notificationIds: readonly string[]): void;
|
|
28
|
+
/** Active event-driven waits consume matching terminals before a second foreground wake is admitted. */
|
|
29
|
+
isObserved?(record: LaneRecord): boolean;
|
|
25
30
|
}
|
|
26
31
|
/** Event-driven, bounded terminal outbox. Durable worker events can be replayed into it on resume. */
|
|
27
32
|
export declare class WorkerNotificationCoordinator {
|
|
@@ -37,15 +42,20 @@ export declare class WorkerNotificationCoordinator {
|
|
|
37
42
|
* an owning caller can durably persist and replay them across a process restart.
|
|
38
43
|
*/
|
|
39
44
|
private readonly inFlight;
|
|
45
|
+
private readonly observedTerminals;
|
|
40
46
|
private scheduled;
|
|
41
47
|
private disposed;
|
|
42
48
|
private deliveryTail;
|
|
43
49
|
private retryTimer;
|
|
50
|
+
private readonly handoffWatchdogs;
|
|
44
51
|
private retryCount;
|
|
45
52
|
constructor(options: WorkerNotificationCoordinatorOptions);
|
|
46
53
|
/** Every notification recorded but not yet confirmed delivered, for durable cross-restart replay. */
|
|
47
54
|
getOutstandingRecords(): readonly WorkerTerminalHandoffRecord[];
|
|
48
55
|
recordTerminal(record: LaneRecord, durableNotificationId?: string): void;
|
|
56
|
+
/** Mark exact terminal generations as already exposed to the parent model. */
|
|
57
|
+
observeTerminals(records: readonly Pick<LaneRecord, "laneId" | "status" | "completedAt" | "reasonCode">[], observedAt?: string): void;
|
|
58
|
+
private rememberObserved;
|
|
49
59
|
statusChanged(): void;
|
|
50
60
|
/** Callers that want to durably persist outstanding work must read getOutstandingRecords() first. */
|
|
51
61
|
dispose(): void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"worker-notification-coordinator.d.ts","sourceRoot":"","sources":["../../../src/core/delegation/worker-notification-coordinator.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,kBAAkB,EAAE,MAAM,6BAA6B,CAAC;
|
|
1
|
+
{"version":3,"file":"worker-notification-coordinator.d.ts","sourceRoot":"","sources":["../../../src/core/delegation/worker-notification-coordinator.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,kBAAkB,EAAE,MAAM,6BAA6B,CAAC;AAsBlF,MAAM,WAAW,2BAA2B;IAC3C,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,kBAAkB,CAAC;IAC3B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,yGAAyG;IACzG,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,kFAAkF;IAClF,UAAU,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,wBAAwB;IACxC,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,mBAAmB,EAAE,MAAM,CAAC;IAC5B,gBAAgB,EAAE,MAAM,CAAC;IACzB,6FAA6F;IAC7F,mBAAmB,EAAE,MAAM,CAAC;IAC5B,kBAAkB,EAAE,SAAS,2BAA2B,EAAE,CAAC;CAC3D;AAQD,MAAM,WAAW,oCAAoC;IACpD,gBAAgB,IAAI,SAAS,UAAU,EAAE,CAAC;IAC1C,UAAU,CAAC,MAAM,EAAE,wBAAwB,GAAG,IAAI,CAAC;IACnD,MAAM,CAAC,OAAO,EAAE,SAAS,2BAA2B,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACvE,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,oBAAoB,CAAC,eAAe,EAAE,SAAS,MAAM,EAAE,GAAG,IAAI,CAAC;IAC/D,wGAAwG;IACxG,UAAU,CAAC,CAAC,MAAM,EAAE,UAAU,GAAG,OAAO,CAAC;CACzC;AAMD,sGAAsG;AACtG,qBAAa,6BAA6B;IACzC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAuC;IAC/D,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAgD;IACxE;;;;;;;;OAQG;IACH,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAgD;IACzE,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAA6B;IAC/D,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,YAAY,CAAqB;IACzC,OAAO,CAAC,UAAU,CAA4C;IAC9D,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAA4C;IAC7E,OAAO,CAAC,UAAU,CAAK;IAEvB,YAAY,OAAO,EAAE,oCAAoC,EAExD;IAED,qGAAqG;IACrG,qBAAqB,IAAI,SAAS,2BAA2B,EAAE,CAE9D;IAED,cAAc,CAAC,MAAM,EAAE,UAAU,EAAE,qBAAqB,CAAC,EAAE,MAAM,GAAG,IAAI,CAiCvE;IAED,8EAA8E;IAC9E,gBAAgB,CACf,OAAO,EAAE,SAAS,IAAI,CAAC,UAAU,EAAE,QAAQ,GAAG,QAAQ,GAAG,aAAa,GAAG,YAAY,CAAC,EAAE,EACxF,UAAU,SAA2B,GACnC,IAAI,CAMN;IAED,OAAO,CAAC,gBAAgB;IAUxB,aAAa,IAAI,IAAI,CAEpB;IAED,qGAAqG;IACrG,OAAO,IAAI,IAAI,CAUd;IAED,OAAO,CAAC,QAAQ;IAQhB,OAAO,CAAC,aAAa;IAWrB,OAAO,CAAC,cAAc;IAQtB;;;;OAIG;IACH,OAAO,CAAC,oBAAoB;IAiB5B,OAAO,CAAC,KAAK;CAiFb"}
|
|
@@ -15,6 +15,10 @@ const ATTENTION_TERMINAL_STATUSES = new Set(["partial", "blocked", "canceled"]);
|
|
|
15
15
|
* subsequent worker terminal) forever with zero visibility. This watchdog only ever warns.
|
|
16
16
|
*/
|
|
17
17
|
const HANDOFF_WATCHDOG_MS = 1_800_000;
|
|
18
|
+
const MAX_OBSERVED_TERMINALS = 512;
|
|
19
|
+
function terminalIdentity(record) {
|
|
20
|
+
return [record.laneId, record.completedAt ?? "", record.status, record.reasonCode ?? ""].join("\0");
|
|
21
|
+
}
|
|
18
22
|
/** Event-driven, bounded terminal outbox. Durable worker events can be replayed into it on resume. */
|
|
19
23
|
export class WorkerNotificationCoordinator {
|
|
20
24
|
constructor(options) {
|
|
@@ -29,9 +33,11 @@ export class WorkerNotificationCoordinator {
|
|
|
29
33
|
* an owning caller can durably persist and replay them across a process restart.
|
|
30
34
|
*/
|
|
31
35
|
this.inFlight = new Map();
|
|
36
|
+
this.observedTerminals = new Map();
|
|
32
37
|
this.scheduled = false;
|
|
33
38
|
this.disposed = false;
|
|
34
39
|
this.deliveryTail = Promise.resolve();
|
|
40
|
+
this.handoffWatchdogs = new Set();
|
|
35
41
|
this.retryCount = 0;
|
|
36
42
|
this.options = options;
|
|
37
43
|
}
|
|
@@ -43,18 +49,58 @@ export class WorkerNotificationCoordinator {
|
|
|
43
49
|
if (record.status === "queued" || record.status === "running")
|
|
44
50
|
return;
|
|
45
51
|
const key = durableNotificationId ?? `transient:${record.laneId}:${record.completedAt ?? record.status}`;
|
|
52
|
+
const inFlight = this.inFlight.get(key);
|
|
53
|
+
if (inFlight) {
|
|
54
|
+
// A terminal can be observed again while its handoff is still awaiting the parent. Keep
|
|
55
|
+
// the existing receipt and consumer: replacing it in `pending` would enqueue a second
|
|
56
|
+
// wake as soon as the first delivery settles.
|
|
57
|
+
if (this.options.isObserved?.(record)) {
|
|
58
|
+
const observedAt = new Date().toISOString();
|
|
59
|
+
this.rememberObserved(terminalIdentity(record), observedAt);
|
|
60
|
+
inFlight.record.observedAt = observedAt;
|
|
61
|
+
}
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
const identity = terminalIdentity(record);
|
|
65
|
+
const observedAt = this.options.isObserved?.(record)
|
|
66
|
+
? new Date().toISOString()
|
|
67
|
+
: this.observedTerminals.get(identity);
|
|
68
|
+
if (observedAt)
|
|
69
|
+
this.rememberObserved(identity, observedAt);
|
|
46
70
|
this.pending.set(key, {
|
|
47
71
|
key,
|
|
48
72
|
record: {
|
|
49
73
|
laneId: record.laneId,
|
|
50
74
|
status: record.status,
|
|
75
|
+
...(record.completedAt ? { completedAt: record.completedAt } : {}),
|
|
51
76
|
...(record.reasonCode ? { reasonCode: record.reasonCode } : {}),
|
|
52
77
|
...(record.goalId ? { goalId: record.goalId } : {}),
|
|
78
|
+
...(observedAt ? { observedAt } : {}),
|
|
53
79
|
},
|
|
54
80
|
...(durableNotificationId ? { durableNotificationId } : {}),
|
|
55
81
|
});
|
|
56
82
|
this.schedule();
|
|
57
83
|
}
|
|
84
|
+
/** Mark exact terminal generations as already exposed to the parent model. */
|
|
85
|
+
observeTerminals(records, observedAt = new Date().toISOString()) {
|
|
86
|
+
const identities = new Set(records.map(terminalIdentity));
|
|
87
|
+
for (const identity of identities)
|
|
88
|
+
this.rememberObserved(identity, observedAt);
|
|
89
|
+
for (const notification of [...this.pending.values(), ...this.inFlight.values()]) {
|
|
90
|
+
if (identities.has(terminalIdentity(notification.record)))
|
|
91
|
+
notification.record.observedAt = observedAt;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
rememberObserved(identity, observedAt) {
|
|
95
|
+
this.observedTerminals.delete(identity);
|
|
96
|
+
this.observedTerminals.set(identity, observedAt);
|
|
97
|
+
while (this.observedTerminals.size > MAX_OBSERVED_TERMINALS) {
|
|
98
|
+
const oldest = this.observedTerminals.keys().next().value;
|
|
99
|
+
if (oldest === undefined)
|
|
100
|
+
break;
|
|
101
|
+
this.observedTerminals.delete(oldest);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
58
104
|
statusChanged() {
|
|
59
105
|
this.schedule();
|
|
60
106
|
}
|
|
@@ -65,8 +111,12 @@ export class WorkerNotificationCoordinator {
|
|
|
65
111
|
if (this.retryTimer)
|
|
66
112
|
clearTimeout(this.retryTimer);
|
|
67
113
|
this.retryTimer = undefined;
|
|
114
|
+
for (const watchdog of this.handoffWatchdogs)
|
|
115
|
+
clearTimeout(watchdog);
|
|
116
|
+
this.handoffWatchdogs.clear();
|
|
68
117
|
this.pending.clear();
|
|
69
118
|
this.inFlight.clear();
|
|
119
|
+
this.observedTerminals.clear();
|
|
70
120
|
}
|
|
71
121
|
schedule() {
|
|
72
122
|
if (this.disposed || this.scheduled)
|
|
@@ -104,11 +154,18 @@ export class WorkerNotificationCoordinator {
|
|
|
104
154
|
*/
|
|
105
155
|
startHandoffWatchdog(laneIds) {
|
|
106
156
|
const timer = setTimeout(() => {
|
|
157
|
+
this.handoffWatchdogs.delete(timer);
|
|
107
158
|
this.warnBestEffort(`Background worker handoff has not settled after ${HANDOFF_WATCHDOG_MS}ms for lane(s): ${laneIds.join(", ")}. Observation only; no redispatch will occur.`);
|
|
108
159
|
}, HANDOFF_WATCHDOG_MS);
|
|
160
|
+
this.handoffWatchdogs.add(timer);
|
|
109
161
|
if (typeof timer === "object" && "unref" in timer)
|
|
110
162
|
timer.unref();
|
|
111
|
-
return {
|
|
163
|
+
return {
|
|
164
|
+
clear: () => {
|
|
165
|
+
clearTimeout(timer);
|
|
166
|
+
this.handoffWatchdogs.delete(timer);
|
|
167
|
+
},
|
|
168
|
+
};
|
|
112
169
|
}
|
|
113
170
|
flush() {
|
|
114
171
|
this.scheduled = false;
|
|
@@ -167,8 +224,17 @@ export class WorkerNotificationCoordinator {
|
|
|
167
224
|
this.inFlight.delete(notification.key);
|
|
168
225
|
this.retryCount = 0;
|
|
169
226
|
const durableIds = batch.flatMap((notification) => notification.durableNotificationId ? [notification.durableNotificationId] : []);
|
|
170
|
-
if (durableIds.length > 0)
|
|
171
|
-
|
|
227
|
+
if (durableIds.length > 0) {
|
|
228
|
+
try {
|
|
229
|
+
this.options.markDurableDelivered(durableIds);
|
|
230
|
+
}
|
|
231
|
+
catch (error) {
|
|
232
|
+
// Delivery is already confirmed. Retrying notify() would wake the parent twice just
|
|
233
|
+
// to repair a separate durable acknowledgment; keep the ledger pending for a future
|
|
234
|
+
// replay and make the acknowledgment failure observable instead.
|
|
235
|
+
this.warnBestEffort(`Background worker durable handoff acknowledgment failed after delivery: ${error instanceof Error ? error.message : String(error)}`);
|
|
236
|
+
}
|
|
237
|
+
}
|
|
172
238
|
});
|
|
173
239
|
this.deliveryTail = delivery.catch((error) => {
|
|
174
240
|
for (const notification of batch) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"worker-notification-coordinator.js","sourceRoot":"","sources":["../../../src/core/delegation/worker-notification-coordinator.ts"],"names":[],"mappings":"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","sourcesContent":["import type { LaneRecord, LaneTerminalStatus } from \"../autonomy/lane-tracker.ts\";\n\nconst FAILED_TERMINAL_STATUSES: ReadonlySet<LaneTerminalStatus> = new Set([\"failed\", \"timeout\", \"budget_exhausted\"]);\n/**\n * \"partial\", \"blocked\", and \"canceled\" are neither an outright infra failure nor a clean success —\n * each needs the parent's attention (review a partial/blocked claim, or simply note an explicit\n * stop), but folding them into `failedSinceFlush` would misclassify them as harness failures (the\n * exact bug 78a2158dd fixed in the other direction). Leaving them out of every tally instead made\n * them invisible: a blocked worker previously reported completedSinceFlush:0, failedSinceFlush:0 —\n * counted nowhere. Every LaneTerminalStatus must land in exactly one of the three tallies below.\n */\nconst ATTENTION_TERMINAL_STATUSES: ReadonlySet<LaneTerminalStatus> = new Set([\"partial\", \"blocked\", \"canceled\"]);\n\n/**\n * Reuses the former handoff-timeout boundary, now purely as an observation threshold: a re-dispatch\n * on this timer used to create a duplicate consumer of the same handoff, so it was removed. Without\n * any signal in its place, a notify() call that never settles would block deliveryTail (and every\n * subsequent worker terminal) forever with zero visibility. This watchdog only ever warns.\n */\nconst HANDOFF_WATCHDOG_MS = 1_800_000;\n\nexport interface WorkerTerminalHandoffRecord {\n\tlaneId: string;\n\tstatus: LaneTerminalStatus;\n\treasonCode?: string;\n\t/** Goal ownership retained until delivery so a stopped goal cannot be resurrected by a late terminal. */\n\tgoalId?: string;\n}\n\nexport interface WorkerNotificationStatus {\n\tactive: number;\n\tqueued: number;\n\trunning: number;\n\tcompletedSinceFlush: number;\n\tfailedSinceFlush: number;\n\t/** partial, blocked, and canceled terminals — needs parent review, not a harness failure. */\n\tattentionSinceFlush: number;\n\tterminalSinceFlush: readonly WorkerTerminalHandoffRecord[];\n}\n\ninterface PendingWorkerNotification {\n\tkey: string;\n\trecord: WorkerTerminalHandoffRecord;\n\tdurableNotificationId?: string;\n}\n\nexport interface WorkerNotificationCoordinatorOptions {\n\tgetWorkerRecords(): readonly LaneRecord[];\n\temitStatus(status: WorkerNotificationStatus): void;\n\tnotify(records: readonly WorkerTerminalHandoffRecord[]): Promise<void>;\n\twarn(message: string): void;\n\tmarkDurableDelivered(notificationIds: readonly string[]): void;\n}\n\n/** Event-driven, bounded terminal outbox. Durable worker events can be replayed into it on resume. */\nexport class WorkerNotificationCoordinator {\n\tprivate readonly options: WorkerNotificationCoordinatorOptions;\n\tprivate readonly pending = new Map<string, PendingWorkerNotification>();\n\t/**\n\t * Notifications currently being attempted by notify() — moved here from `pending` the instant\n\t * delivery starts, never cleared until notify() is CONFIRMED to have settled (success or\n\t * failure). If notify() never settles, this remains the durable, externally-visible record of\n\t * what's stuck: a batch must never be reachable ONLY through the one promise closure that may\n\t * never resolve (that closure is what previously starved every worker queued behind it, with\n\t * no trace of the lost batch anywhere). getOutstandingRecords() exposes `pending ∪ inFlight` so\n\t * an owning caller can durably persist and replay them across a process restart.\n\t */\n\tprivate readonly inFlight = new Map<string, PendingWorkerNotification>();\n\tprivate scheduled = false;\n\tprivate disposed = false;\n\tprivate deliveryTail = Promise.resolve();\n\tprivate retryTimer: ReturnType<typeof setTimeout> | undefined;\n\tprivate retryCount = 0;\n\n\tconstructor(options: WorkerNotificationCoordinatorOptions) {\n\t\tthis.options = options;\n\t}\n\n\t/** Every notification recorded but not yet confirmed delivered, for durable cross-restart replay. */\n\tgetOutstandingRecords(): readonly WorkerTerminalHandoffRecord[] {\n\t\treturn [...this.pending.values(), ...this.inFlight.values()].map((notification) => notification.record);\n\t}\n\n\trecordTerminal(record: LaneRecord, durableNotificationId?: string): void {\n\t\tif (record.status === \"queued\" || record.status === \"running\") return;\n\t\tconst key = durableNotificationId ?? `transient:${record.laneId}:${record.completedAt ?? record.status}`;\n\t\tthis.pending.set(key, {\n\t\t\tkey,\n\t\t\trecord: {\n\t\t\t\tlaneId: record.laneId,\n\t\t\t\tstatus: record.status,\n\t\t\t\t...(record.reasonCode ? { reasonCode: record.reasonCode } : {}),\n\t\t\t\t...(record.goalId ? { goalId: record.goalId } : {}),\n\t\t\t},\n\t\t\t...(durableNotificationId ? { durableNotificationId } : {}),\n\t\t});\n\t\tthis.schedule();\n\t}\n\n\tstatusChanged(): void {\n\t\tthis.schedule();\n\t}\n\n\t/** Callers that want to durably persist outstanding work must read getOutstandingRecords() first. */\n\tdispose(): void {\n\t\tthis.disposed = true;\n\t\tthis.scheduled = false;\n\t\tif (this.retryTimer) clearTimeout(this.retryTimer);\n\t\tthis.retryTimer = undefined;\n\t\tthis.pending.clear();\n\t\tthis.inFlight.clear();\n\t}\n\n\tprivate schedule(): void {\n\t\tif (this.disposed || this.scheduled) return;\n\t\tif (this.retryTimer) clearTimeout(this.retryTimer);\n\t\tthis.retryTimer = undefined;\n\t\tthis.scheduled = true;\n\t\tqueueMicrotask(() => this.flush());\n\t}\n\n\tprivate scheduleRetry(): void {\n\t\tif (this.disposed || this.scheduled || this.retryTimer) return;\n\t\tconst delayMs = Math.min(100 * 2 ** Math.min(this.retryCount, 5), 5_000);\n\t\tthis.retryCount++;\n\t\tthis.retryTimer = setTimeout(() => {\n\t\t\tthis.retryTimer = undefined;\n\t\t\tthis.schedule();\n\t\t}, delayMs);\n\t\tif (typeof this.retryTimer === \"object\" && \"unref\" in this.retryTimer) this.retryTimer.unref();\n\t}\n\n\tprivate warnBestEffort(message: string): void {\n\t\ttry {\n\t\t\tthis.options.warn(message);\n\t\t} catch {\n\t\t\t// Diagnostics cannot consume or stop durable notification delivery.\n\t\t}\n\t}\n\n\t/**\n\t * Observe-only: warns once if the in-flight notify() call has not settled after\n\t * HANDOFF_WATCHDOG_MS. Never re-dispatches and never creates a second notify() consumer —\n\t * callers must clear() it once the awaited notify() settles, success or failure.\n\t */\n\tprivate startHandoffWatchdog(laneIds: readonly string[]): { clear(): void } {\n\t\tconst timer = setTimeout(() => {\n\t\t\tthis.warnBestEffort(\n\t\t\t\t`Background worker handoff has not settled after ${HANDOFF_WATCHDOG_MS}ms for lane(s): ${laneIds.join(\", \")}. Observation only; no redispatch will occur.`,\n\t\t\t);\n\t\t}, HANDOFF_WATCHDOG_MS);\n\t\tif (typeof timer === \"object\" && \"unref\" in timer) timer.unref();\n\t\treturn { clear: () => clearTimeout(timer) };\n\t}\n\n\tprivate flush(): void {\n\t\tthis.scheduled = false;\n\t\tif (this.disposed) return;\n\t\tconst batch = [...this.pending.values()];\n\t\tthis.pending.clear();\n\t\tlet workerRecords: readonly LaneRecord[] = [];\n\t\ttry {\n\t\t\tworkerRecords = this.options.getWorkerRecords();\n\t\t} catch (error) {\n\t\t\tthis.warnBestEffort(\n\t\t\t\t`Background worker status projection failed: ${error instanceof Error ? error.message : String(error)}`,\n\t\t\t);\n\t\t}\n\t\tconst queued = workerRecords.filter((record) => record.status === \"queued\").length;\n\t\tconst running = workerRecords.filter((record) => record.status === \"running\").length;\n\t\tconst terminalSinceFlush = batch.map((notification) => notification.record);\n\t\tconst status = {\n\t\t\tactive: queued + running,\n\t\t\tqueued,\n\t\t\trunning,\n\t\t\tcompletedSinceFlush: terminalSinceFlush.filter((record) => record.status === \"succeeded\").length,\n\t\t\tfailedSinceFlush: terminalSinceFlush.filter((record) => FAILED_TERMINAL_STATUSES.has(record.status)).length,\n\t\t\tattentionSinceFlush: terminalSinceFlush.filter((record) => ATTENTION_TERMINAL_STATUSES.has(record.status))\n\t\t\t\t.length,\n\t\t\tterminalSinceFlush,\n\t\t};\n\t\ttry {\n\t\t\tthis.options.emitStatus(status);\n\t\t} catch (error) {\n\t\t\tthis.warnBestEffort(\n\t\t\t\t`Background worker status observer failed: ${error instanceof Error ? error.message : String(error)}`,\n\t\t\t);\n\t\t}\n\t\tif (batch.length === 0) return;\n\t\t// Moved into `inFlight`, not merely captured by the closure below: if notify() never\n\t\t// settles, this batch stays durably visible via getOutstandingRecords() instead of being\n\t\t// reachable ONLY through this one promise, which is exactly what previously starved every\n\t\t// worker queued behind it with no trace of the lost batch anywhere.\n\t\tfor (const notification of batch) this.inFlight.set(notification.key, notification);\n\t\tconst delivery = this.deliveryTail.then(async () => {\n\t\t\tif (this.disposed) return;\n\t\t\t// A foreground lease wait is an in-flight side effect, not a failed attempt. Re-dispatching it\n\t\t\t// on a wall-clock timer creates concurrent consumers that later persist the same handoff.\n\t\t\t// Explicit rejection remains retryable; process restart replays the durable pending record.\n\t\t\tconst watchdog = this.startHandoffWatchdog(terminalSinceFlush.map((record) => record.laneId));\n\t\t\ttry {\n\t\t\t\tawait this.options.notify(terminalSinceFlush);\n\t\t\t} finally {\n\t\t\t\twatchdog.clear();\n\t\t\t}\n\t\t\tfor (const notification of batch) this.inFlight.delete(notification.key);\n\t\t\tthis.retryCount = 0;\n\t\t\tconst durableIds = batch.flatMap((notification) =>\n\t\t\t\tnotification.durableNotificationId ? [notification.durableNotificationId] : [],\n\t\t\t);\n\t\t\tif (durableIds.length > 0) this.options.markDurableDelivered(durableIds);\n\t\t});\n\t\tthis.deliveryTail = delivery.catch((error: unknown) => {\n\t\t\tfor (const notification of batch) {\n\t\t\t\tthis.inFlight.delete(notification.key);\n\t\t\t\tthis.pending.set(notification.key, notification);\n\t\t\t}\n\t\t\tthis.warnBestEffort(\n\t\t\t\t`Background worker handoff failed: ${error instanceof Error ? error.message : String(error)}`,\n\t\t\t);\n\t\t\tthis.scheduleRetry();\n\t\t});\n\t}\n}\n"]}
|
|
1
|
+
{"version":3,"file":"worker-notification-coordinator.js","sourceRoot":"","sources":["../../../src/core/delegation/worker-notification-coordinator.ts"],"names":[],"mappings":"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","sourcesContent":["import type { LaneRecord, LaneTerminalStatus } from \"../autonomy/lane-tracker.ts\";\n\nconst FAILED_TERMINAL_STATUSES: ReadonlySet<LaneTerminalStatus> = new Set([\"failed\", \"timeout\", \"budget_exhausted\"]);\n/**\n * \"partial\", \"blocked\", and \"canceled\" are neither an outright infra failure nor a clean success —\n * each needs the parent's attention (review a partial/blocked claim, or simply note an explicit\n * stop), but folding them into `failedSinceFlush` would misclassify them as harness failures (the\n * exact bug 78a2158dd fixed in the other direction). Leaving them out of every tally instead made\n * them invisible: a blocked worker previously reported completedSinceFlush:0, failedSinceFlush:0 —\n * counted nowhere. Every LaneTerminalStatus must land in exactly one of the three tallies below.\n */\nconst ATTENTION_TERMINAL_STATUSES: ReadonlySet<LaneTerminalStatus> = new Set([\"partial\", \"blocked\", \"canceled\"]);\n\n/**\n * Reuses the former handoff-timeout boundary, now purely as an observation threshold: a re-dispatch\n * on this timer used to create a duplicate consumer of the same handoff, so it was removed. Without\n * any signal in its place, a notify() call that never settles would block deliveryTail (and every\n * subsequent worker terminal) forever with zero visibility. This watchdog only ever warns.\n */\nconst HANDOFF_WATCHDOG_MS = 1_800_000;\nconst MAX_OBSERVED_TERMINALS = 512;\n\nexport interface WorkerTerminalHandoffRecord {\n\tlaneId: string;\n\tstatus: LaneTerminalStatus;\n\tcompletedAt?: string;\n\treasonCode?: string;\n\t/** Goal ownership retained until delivery so a stopped goal cannot be resurrected by a late terminal. */\n\tgoalId?: string;\n\t/** Runtime-only receipt. Observation consumes delivery, never mutation review. */\n\tobservedAt?: string;\n}\n\nexport interface WorkerNotificationStatus {\n\tactive: number;\n\tqueued: number;\n\trunning: number;\n\tcompletedSinceFlush: number;\n\tfailedSinceFlush: number;\n\t/** partial, blocked, and canceled terminals — needs parent review, not a harness failure. */\n\tattentionSinceFlush: number;\n\tterminalSinceFlush: readonly WorkerTerminalHandoffRecord[];\n}\n\ninterface PendingWorkerNotification {\n\tkey: string;\n\trecord: WorkerTerminalHandoffRecord;\n\tdurableNotificationId?: string;\n}\n\nexport interface WorkerNotificationCoordinatorOptions {\n\tgetWorkerRecords(): readonly LaneRecord[];\n\temitStatus(status: WorkerNotificationStatus): void;\n\tnotify(records: readonly WorkerTerminalHandoffRecord[]): Promise<void>;\n\twarn(message: string): void;\n\tmarkDurableDelivered(notificationIds: readonly string[]): void;\n\t/** Active event-driven waits consume matching terminals before a second foreground wake is admitted. */\n\tisObserved?(record: LaneRecord): boolean;\n}\n\nfunction terminalIdentity(record: Pick<LaneRecord, \"laneId\" | \"status\" | \"completedAt\" | \"reasonCode\">): string {\n\treturn [record.laneId, record.completedAt ?? \"\", record.status, record.reasonCode ?? \"\"].join(\"\\0\");\n}\n\n/** Event-driven, bounded terminal outbox. Durable worker events can be replayed into it on resume. */\nexport class WorkerNotificationCoordinator {\n\tprivate readonly options: WorkerNotificationCoordinatorOptions;\n\tprivate readonly pending = new Map<string, PendingWorkerNotification>();\n\t/**\n\t * Notifications currently being attempted by notify() — moved here from `pending` the instant\n\t * delivery starts, never cleared until notify() is CONFIRMED to have settled (success or\n\t * failure). If notify() never settles, this remains the durable, externally-visible record of\n\t * what's stuck: a batch must never be reachable ONLY through the one promise closure that may\n\t * never resolve (that closure is what previously starved every worker queued behind it, with\n\t * no trace of the lost batch anywhere). getOutstandingRecords() exposes `pending ∪ inFlight` so\n\t * an owning caller can durably persist and replay them across a process restart.\n\t */\n\tprivate readonly inFlight = new Map<string, PendingWorkerNotification>();\n\tprivate readonly observedTerminals = new Map<string, string>();\n\tprivate scheduled = false;\n\tprivate disposed = false;\n\tprivate deliveryTail = Promise.resolve();\n\tprivate retryTimer: ReturnType<typeof setTimeout> | undefined;\n\tprivate readonly handoffWatchdogs = new Set<ReturnType<typeof setTimeout>>();\n\tprivate retryCount = 0;\n\n\tconstructor(options: WorkerNotificationCoordinatorOptions) {\n\t\tthis.options = options;\n\t}\n\n\t/** Every notification recorded but not yet confirmed delivered, for durable cross-restart replay. */\n\tgetOutstandingRecords(): readonly WorkerTerminalHandoffRecord[] {\n\t\treturn [...this.pending.values(), ...this.inFlight.values()].map((notification) => notification.record);\n\t}\n\n\trecordTerminal(record: LaneRecord, durableNotificationId?: string): void {\n\t\tif (record.status === \"queued\" || record.status === \"running\") return;\n\t\tconst key = durableNotificationId ?? `transient:${record.laneId}:${record.completedAt ?? record.status}`;\n\t\tconst inFlight = this.inFlight.get(key);\n\t\tif (inFlight) {\n\t\t\t// A terminal can be observed again while its handoff is still awaiting the parent. Keep\n\t\t\t// the existing receipt and consumer: replacing it in `pending` would enqueue a second\n\t\t\t// wake as soon as the first delivery settles.\n\t\t\tif (this.options.isObserved?.(record)) {\n\t\t\t\tconst observedAt = new Date().toISOString();\n\t\t\t\tthis.rememberObserved(terminalIdentity(record), observedAt);\n\t\t\t\tinFlight.record.observedAt = observedAt;\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\t\tconst identity = terminalIdentity(record);\n\t\tconst observedAt = this.options.isObserved?.(record)\n\t\t\t? new Date().toISOString()\n\t\t\t: this.observedTerminals.get(identity);\n\t\tif (observedAt) this.rememberObserved(identity, observedAt);\n\t\tthis.pending.set(key, {\n\t\t\tkey,\n\t\t\trecord: {\n\t\t\t\tlaneId: record.laneId,\n\t\t\t\tstatus: record.status,\n\t\t\t\t...(record.completedAt ? { completedAt: record.completedAt } : {}),\n\t\t\t\t...(record.reasonCode ? { reasonCode: record.reasonCode } : {}),\n\t\t\t\t...(record.goalId ? { goalId: record.goalId } : {}),\n\t\t\t\t...(observedAt ? { observedAt } : {}),\n\t\t\t},\n\t\t\t...(durableNotificationId ? { durableNotificationId } : {}),\n\t\t});\n\t\tthis.schedule();\n\t}\n\n\t/** Mark exact terminal generations as already exposed to the parent model. */\n\tobserveTerminals(\n\t\trecords: readonly Pick<LaneRecord, \"laneId\" | \"status\" | \"completedAt\" | \"reasonCode\">[],\n\t\tobservedAt = new Date().toISOString(),\n\t): void {\n\t\tconst identities = new Set(records.map(terminalIdentity));\n\t\tfor (const identity of identities) this.rememberObserved(identity, observedAt);\n\t\tfor (const notification of [...this.pending.values(), ...this.inFlight.values()]) {\n\t\t\tif (identities.has(terminalIdentity(notification.record))) notification.record.observedAt = observedAt;\n\t\t}\n\t}\n\n\tprivate rememberObserved(identity: string, observedAt: string): void {\n\t\tthis.observedTerminals.delete(identity);\n\t\tthis.observedTerminals.set(identity, observedAt);\n\t\twhile (this.observedTerminals.size > MAX_OBSERVED_TERMINALS) {\n\t\t\tconst oldest = this.observedTerminals.keys().next().value;\n\t\t\tif (oldest === undefined) break;\n\t\t\tthis.observedTerminals.delete(oldest);\n\t\t}\n\t}\n\n\tstatusChanged(): void {\n\t\tthis.schedule();\n\t}\n\n\t/** Callers that want to durably persist outstanding work must read getOutstandingRecords() first. */\n\tdispose(): void {\n\t\tthis.disposed = true;\n\t\tthis.scheduled = false;\n\t\tif (this.retryTimer) clearTimeout(this.retryTimer);\n\t\tthis.retryTimer = undefined;\n\t\tfor (const watchdog of this.handoffWatchdogs) clearTimeout(watchdog);\n\t\tthis.handoffWatchdogs.clear();\n\t\tthis.pending.clear();\n\t\tthis.inFlight.clear();\n\t\tthis.observedTerminals.clear();\n\t}\n\n\tprivate schedule(): void {\n\t\tif (this.disposed || this.scheduled) return;\n\t\tif (this.retryTimer) clearTimeout(this.retryTimer);\n\t\tthis.retryTimer = undefined;\n\t\tthis.scheduled = true;\n\t\tqueueMicrotask(() => this.flush());\n\t}\n\n\tprivate scheduleRetry(): void {\n\t\tif (this.disposed || this.scheduled || this.retryTimer) return;\n\t\tconst delayMs = Math.min(100 * 2 ** Math.min(this.retryCount, 5), 5_000);\n\t\tthis.retryCount++;\n\t\tthis.retryTimer = setTimeout(() => {\n\t\t\tthis.retryTimer = undefined;\n\t\t\tthis.schedule();\n\t\t}, delayMs);\n\t\tif (typeof this.retryTimer === \"object\" && \"unref\" in this.retryTimer) this.retryTimer.unref();\n\t}\n\n\tprivate warnBestEffort(message: string): void {\n\t\ttry {\n\t\t\tthis.options.warn(message);\n\t\t} catch {\n\t\t\t// Diagnostics cannot consume or stop durable notification delivery.\n\t\t}\n\t}\n\n\t/**\n\t * Observe-only: warns once if the in-flight notify() call has not settled after\n\t * HANDOFF_WATCHDOG_MS. Never re-dispatches and never creates a second notify() consumer —\n\t * callers must clear() it once the awaited notify() settles, success or failure.\n\t */\n\tprivate startHandoffWatchdog(laneIds: readonly string[]): { clear(): void } {\n\t\tconst timer = setTimeout(() => {\n\t\t\tthis.handoffWatchdogs.delete(timer);\n\t\t\tthis.warnBestEffort(\n\t\t\t\t`Background worker handoff has not settled after ${HANDOFF_WATCHDOG_MS}ms for lane(s): ${laneIds.join(\", \")}. Observation only; no redispatch will occur.`,\n\t\t\t);\n\t\t}, HANDOFF_WATCHDOG_MS);\n\t\tthis.handoffWatchdogs.add(timer);\n\t\tif (typeof timer === \"object\" && \"unref\" in timer) timer.unref();\n\t\treturn {\n\t\t\tclear: () => {\n\t\t\t\tclearTimeout(timer);\n\t\t\t\tthis.handoffWatchdogs.delete(timer);\n\t\t\t},\n\t\t};\n\t}\n\n\tprivate flush(): void {\n\t\tthis.scheduled = false;\n\t\tif (this.disposed) return;\n\t\tconst batch = [...this.pending.values()];\n\t\tthis.pending.clear();\n\t\tlet workerRecords: readonly LaneRecord[] = [];\n\t\ttry {\n\t\t\tworkerRecords = this.options.getWorkerRecords();\n\t\t} catch (error) {\n\t\t\tthis.warnBestEffort(\n\t\t\t\t`Background worker status projection failed: ${error instanceof Error ? error.message : String(error)}`,\n\t\t\t);\n\t\t}\n\t\tconst queued = workerRecords.filter((record) => record.status === \"queued\").length;\n\t\tconst running = workerRecords.filter((record) => record.status === \"running\").length;\n\t\tconst terminalSinceFlush = batch.map((notification) => notification.record);\n\t\tconst status = {\n\t\t\tactive: queued + running,\n\t\t\tqueued,\n\t\t\trunning,\n\t\t\tcompletedSinceFlush: terminalSinceFlush.filter((record) => record.status === \"succeeded\").length,\n\t\t\tfailedSinceFlush: terminalSinceFlush.filter((record) => FAILED_TERMINAL_STATUSES.has(record.status)).length,\n\t\t\tattentionSinceFlush: terminalSinceFlush.filter((record) => ATTENTION_TERMINAL_STATUSES.has(record.status))\n\t\t\t\t.length,\n\t\t\tterminalSinceFlush,\n\t\t};\n\t\ttry {\n\t\t\tthis.options.emitStatus(status);\n\t\t} catch (error) {\n\t\t\tthis.warnBestEffort(\n\t\t\t\t`Background worker status observer failed: ${error instanceof Error ? error.message : String(error)}`,\n\t\t\t);\n\t\t}\n\t\tif (batch.length === 0) return;\n\t\t// Moved into `inFlight`, not merely captured by the closure below: if notify() never\n\t\t// settles, this batch stays durably visible via getOutstandingRecords() instead of being\n\t\t// reachable ONLY through this one promise, which is exactly what previously starved every\n\t\t// worker queued behind it with no trace of the lost batch anywhere.\n\t\tfor (const notification of batch) this.inFlight.set(notification.key, notification);\n\t\tconst delivery = this.deliveryTail.then(async () => {\n\t\t\tif (this.disposed) return;\n\t\t\t// A foreground lease wait is an in-flight side effect, not a failed attempt. Re-dispatching it\n\t\t\t// on a wall-clock timer creates concurrent consumers that later persist the same handoff.\n\t\t\t// Explicit rejection remains retryable; process restart replays the durable pending record.\n\t\t\tconst watchdog = this.startHandoffWatchdog(terminalSinceFlush.map((record) => record.laneId));\n\t\t\ttry {\n\t\t\t\tawait this.options.notify(terminalSinceFlush);\n\t\t\t} finally {\n\t\t\t\twatchdog.clear();\n\t\t\t}\n\t\t\tfor (const notification of batch) this.inFlight.delete(notification.key);\n\t\t\tthis.retryCount = 0;\n\t\t\tconst durableIds = batch.flatMap((notification) =>\n\t\t\t\tnotification.durableNotificationId ? [notification.durableNotificationId] : [],\n\t\t\t);\n\t\t\tif (durableIds.length > 0) {\n\t\t\t\ttry {\n\t\t\t\t\tthis.options.markDurableDelivered(durableIds);\n\t\t\t\t} catch (error) {\n\t\t\t\t\t// Delivery is already confirmed. Retrying notify() would wake the parent twice just\n\t\t\t\t\t// to repair a separate durable acknowledgment; keep the ledger pending for a future\n\t\t\t\t\t// replay and make the acknowledgment failure observable instead.\n\t\t\t\t\tthis.warnBestEffort(\n\t\t\t\t\t\t`Background worker durable handoff acknowledgment failed after delivery: ${\n\t\t\t\t\t\t\terror instanceof Error ? error.message : String(error)\n\t\t\t\t\t\t}`,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t\tthis.deliveryTail = delivery.catch((error: unknown) => {\n\t\t\tfor (const notification of batch) {\n\t\t\t\tthis.inFlight.delete(notification.key);\n\t\t\t\tthis.pending.set(notification.key, notification);\n\t\t\t}\n\t\t\tthis.warnBestEffort(\n\t\t\t\t`Background worker handoff failed: ${error instanceof Error ? error.message : String(error)}`,\n\t\t\t);\n\t\t\tthis.scheduleRetry();\n\t\t});\n\t}\n}\n"]}
|
|
@@ -6,6 +6,22 @@ import type { WorkerTerminalHandoffRecord } from "./delegation/worker-notificati
|
|
|
6
6
|
import type { ForegroundRecoveryController, ForegroundSubmissionLease } from "./foreground-recovery-controller.ts";
|
|
7
7
|
import { type GoalState } from "./goals/goal-state.ts";
|
|
8
8
|
import type { ArtifactContract, WorkerResultContract } from "./orchestration/contracts.ts";
|
|
9
|
+
export type BackgroundActivitySummaryKind = "agent" | "task";
|
|
10
|
+
export type BackgroundActivitySummaryStatus = "success" | "attention" | "failed" | "canceled";
|
|
11
|
+
export interface BackgroundActivitySummaryItem {
|
|
12
|
+
id: string;
|
|
13
|
+
status: BackgroundActivitySummaryStatus;
|
|
14
|
+
}
|
|
15
|
+
/** Provider-neutral counts retained when the detailed handoff is bounded. */
|
|
16
|
+
export interface BackgroundActivitySummaryContract {
|
|
17
|
+
kind: BackgroundActivitySummaryKind;
|
|
18
|
+
totalCount: number;
|
|
19
|
+
attentionCount: number;
|
|
20
|
+
failedCount: number;
|
|
21
|
+
canceledCount: number;
|
|
22
|
+
}
|
|
23
|
+
export declare function createBackgroundActivitySummaryContract(kind: BackgroundActivitySummaryKind, items: readonly BackgroundActivitySummaryItem[]): BackgroundActivitySummaryContract;
|
|
24
|
+
export declare function isBackgroundActivitySummaryContract(value: unknown): value is BackgroundActivitySummaryContract;
|
|
9
25
|
interface ForegroundTerminalHandoffControllerDeps {
|
|
10
26
|
foreground: ForegroundRecoveryController;
|
|
11
27
|
isDisposed(): boolean;
|
|
@@ -35,6 +51,7 @@ export declare function buildForegroundWorkerTerminalHandoffContent(records: rea
|
|
|
35
51
|
};
|
|
36
52
|
}[], options?: {
|
|
37
53
|
wakeParent?: boolean;
|
|
54
|
+
totalCount?: number;
|
|
38
55
|
}): string;
|
|
39
56
|
/** Serializes durable background terminal delivery through the foreground submission owner. */
|
|
40
57
|
export declare class ForegroundTerminalHandoffController {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"foreground-terminal-handoff-controller.d.ts","sourceRoot":"","sources":["../../src/core/foreground-terminal-handoff-controller.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAC/D,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AACrE,OAAO,EACN,KAAK,wBAAwB,EAE7B,MAAM,sCAAsC,CAAC;AAC9C,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,sCAAsC,CAAC;AACvF,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,iDAAiD,CAAC;AAGnG,OAAO,KAAK,EAAE,4BAA4B,EAAE,yBAAyB,EAAE,MAAM,qCAAqC,CAAC;AACnH,OAAO,EAAE,KAAK,SAAS,EAAyB,MAAM,uBAAuB,CAAC;AAC9E,OAAO,KAAK,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,MAAM,8BAA8B,CAAC;AAE3F,UAAU,uCAAuC;IAChD,UAAU,EAAE,4BAA4B,CAAC;IACzC,UAAU,IAAI,OAAO,CAAC;IACtB,oBAAoB,IAAI,IAAI,CAAC,SAAS,EAAE,QAAQ,GAAG,QAAQ,CAAC,GAAG,SAAS,CAAC;IACzE,sBAAsB,CAAC,CAAC,MAAM,EAAE,MAAM,GAAG,0BAA0B,GAAG,SAAS,CAAC;IAChF,eAAe,CAAC,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC,oBAAoB,EAAE,WAAW,CAAC,GAAG,SAAS,CAAC;IACtF,sBAAsB,CACrB,OAAO,EAAE,IAAI,CAAC,aAAa,CAAC,OAAO,CAAC,EAAE,YAAY,GAAG,SAAS,GAAG,SAAS,GAAG,SAAS,CAAC,EACvF,KAAK,EAAE,yBAAyB,EAChC,MAAM,CAAC,EAAE,MAAM,GACb,OAAO,CAAC;QAAE,UAAU,EAAE,OAAO,CAAC,IAAI,CAAC,CAAA;KAAE,CAAC,CAAC;IAC1C,iBAAiB,CAChB,OAAO,EAAE,IAAI,CAAC,aAAa,CAAC,OAAO,CAAC,EAAE,YAAY,GAAG,SAAS,GAAG,SAAS,GAAG,SAAS,CAAC,EACvF,OAAO,EAAE;QAAE,WAAW,EAAE,KAAK,CAAC;QAAC,SAAS,EAAE,UAAU,CAAA;KAAE,EACtD,KAAK,EAAE,yBAAyB,GAC9B,OAAO,CAAC,IAAI,CAAC,CAAC;IACjB,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;CAC5B;AAED,wBAAgB,2CAA2C,CAC1D,OAAO,EAAE,SAAS;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,kBAAkB,CAAC;IAC3B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,cAAc,CAAC,EAAE,gBAAgB,CAAC;IAClC,KAAK,CAAC,EAAE;QACP,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,YAAY,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;QACjC,QAAQ,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;QAC7B,oBAAoB,CAAC,EAAE,OAAO,CAAC;KAC/B,CAAC;CACF,EAAE,EACH,OAAO,CAAC,EAAE;IAAE,UAAU,CAAC,EAAE,OAAO,CAAA;CAAE,
|
|
1
|
+
{"version":3,"file":"foreground-terminal-handoff-controller.d.ts","sourceRoot":"","sources":["../../src/core/foreground-terminal-handoff-controller.ts"],"names":[],"mappings":"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"}
|
|
@@ -2,9 +2,45 @@ import { createBackgroundToolTerminalMessage, } from "./background-tool-task-con
|
|
|
2
2
|
import { WORKER_COMPLETION_ERROR_CAVEMAN_GUIDANCE } from "./delegation/worker-terminal-handoff-coordinator.js";
|
|
3
3
|
import { workerTerminalOutputArtifact } from "./delegation/worker-terminal-output-artifact.js";
|
|
4
4
|
import { isGoalExecutionActive } from "./goals/goal-state.js";
|
|
5
|
+
export function createBackgroundActivitySummaryContract(kind, items) {
|
|
6
|
+
return {
|
|
7
|
+
kind,
|
|
8
|
+
totalCount: items.length,
|
|
9
|
+
attentionCount: items.filter((item) => item.status === "attention").length,
|
|
10
|
+
failedCount: items.filter((item) => item.status === "failed").length,
|
|
11
|
+
canceledCount: items.filter((item) => item.status === "canceled").length,
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
export function isBackgroundActivitySummaryContract(value) {
|
|
15
|
+
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
16
|
+
return false;
|
|
17
|
+
const summary = value;
|
|
18
|
+
const counts = ["totalCount", "attentionCount", "failedCount", "canceledCount"];
|
|
19
|
+
if (summary.kind !== "agent" && summary.kind !== "task")
|
|
20
|
+
return false;
|
|
21
|
+
if (counts.some((field) => typeof summary[field] !== "number" ||
|
|
22
|
+
!Number.isSafeInteger(summary[field]) ||
|
|
23
|
+
summary[field] < 0)) {
|
|
24
|
+
return false;
|
|
25
|
+
}
|
|
26
|
+
const totalCount = summary.totalCount;
|
|
27
|
+
return (totalCount > 0 &&
|
|
28
|
+
summary.attentionCount + summary.failedCount + summary.canceledCount <=
|
|
29
|
+
totalCount);
|
|
30
|
+
}
|
|
31
|
+
function workerSummaryStatus(record, claimNeedsReview) {
|
|
32
|
+
if (record.status === "failed" || record.status === "timeout" || record.status === "budget_exhausted") {
|
|
33
|
+
return "failed";
|
|
34
|
+
}
|
|
35
|
+
if (record.status === "canceled")
|
|
36
|
+
return "canceled";
|
|
37
|
+
if (claimNeedsReview || record.status === "partial" || record.status === "blocked")
|
|
38
|
+
return "attention";
|
|
39
|
+
return "success";
|
|
40
|
+
}
|
|
5
41
|
export function buildForegroundWorkerTerminalHandoffContent(records, options) {
|
|
6
42
|
const included = records.slice(0, 8);
|
|
7
|
-
const omitted = records.length - included.length;
|
|
43
|
+
const omitted = Math.max(0, (options?.totalCount ?? records.length) - included.length);
|
|
8
44
|
const wakeParent = options?.wakeParent ?? true;
|
|
9
45
|
const sanitize = (value) => value.replace(/[\r\n]+/g, " ").slice(0, 120);
|
|
10
46
|
return [
|
|
@@ -58,18 +94,25 @@ export class ForegroundTerminalHandoffController {
|
|
|
58
94
|
this.deps = deps;
|
|
59
95
|
}
|
|
60
96
|
async notifyWorkers(records) {
|
|
61
|
-
if (records.
|
|
97
|
+
if (records.every((record) => record.observedAt !== undefined))
|
|
62
98
|
return;
|
|
63
99
|
this.assertLive("worker terminal handoff was persisted");
|
|
64
100
|
const lease = await this.deps.foreground.acquireSubmission();
|
|
65
101
|
let releaseLease = true;
|
|
66
102
|
try {
|
|
67
103
|
this.assertLive("worker terminal handoff was persisted");
|
|
68
|
-
const
|
|
104
|
+
const unread = records.filter((record) => record.observedAt === undefined);
|
|
105
|
+
if (unread.length === 0)
|
|
106
|
+
return;
|
|
107
|
+
const prepared = unread.map((record, index) => {
|
|
69
108
|
const snapshot = this.deps.getWorkerClaimSnapshot?.(record.laneId);
|
|
70
109
|
const claim = snapshot?.claim;
|
|
71
|
-
const outputArtifact = workerTerminalOutputArtifact(this.deps.getWorkerResult?.(record.laneId));
|
|
110
|
+
const outputArtifact = index < 8 ? workerTerminalOutputArtifact(this.deps.getWorkerResult?.(record.laneId)) : undefined;
|
|
72
111
|
return {
|
|
112
|
+
summaryItem: {
|
|
113
|
+
id: record.laneId,
|
|
114
|
+
status: workerSummaryStatus(record, claim?.parentReviewRequired === true),
|
|
115
|
+
},
|
|
73
116
|
laneId: record.laneId,
|
|
74
117
|
status: record.status,
|
|
75
118
|
...(record.reasonCode ? { reasonCode: record.reasonCode } : {}),
|
|
@@ -87,16 +130,23 @@ export class ForegroundTerminalHandoffController {
|
|
|
87
130
|
: {}),
|
|
88
131
|
};
|
|
89
132
|
});
|
|
133
|
+
const included = prepared.slice(0, 8).map(({ summaryItem: _summaryItem, ...record }) => record);
|
|
90
134
|
const goal = this.deps.getGoalStateSnapshot();
|
|
91
|
-
const wakeParent =
|
|
135
|
+
const wakeParent = unread.some((record) => !record.goalId || (goal?.goalId === record.goalId && isGoalExecutionActive(goal.status)));
|
|
92
136
|
const message = {
|
|
93
137
|
customType: "background-worker-completion",
|
|
94
|
-
content: buildForegroundWorkerTerminalHandoffContent(included, {
|
|
138
|
+
content: buildForegroundWorkerTerminalHandoffContent(included, {
|
|
139
|
+
wakeParent,
|
|
140
|
+
totalCount: unread.length,
|
|
141
|
+
}),
|
|
95
142
|
display: true,
|
|
96
|
-
details: {
|
|
143
|
+
details: {
|
|
144
|
+
records: included,
|
|
145
|
+
summary: createBackgroundActivitySummaryContract("agent", prepared.map((entry) => entry.summaryItem)),
|
|
146
|
+
},
|
|
97
147
|
};
|
|
98
148
|
if (wakeParent) {
|
|
99
|
-
const goalId =
|
|
149
|
+
const goalId = unread.find((record) => record.goalId === goal?.goalId)?.goalId;
|
|
100
150
|
const started = await this.deps.startCustomMessageTurn(message, lease, goalId);
|
|
101
151
|
this.releaseAfterTurn(started.completion, lease, "worker terminal handoff turn");
|
|
102
152
|
releaseLease = false;
|
|
@@ -111,14 +161,32 @@ export class ForegroundTerminalHandoffController {
|
|
|
111
161
|
}
|
|
112
162
|
}
|
|
113
163
|
async notifyTools(records, wakeParent) {
|
|
114
|
-
if (!wakeParent)
|
|
164
|
+
if (!wakeParent || records.every((record) => record.observedAt !== undefined))
|
|
115
165
|
return;
|
|
116
166
|
this.assertLive("background tool terminal handoff was delivered");
|
|
117
167
|
const lease = await this.deps.foreground.acquireSubmission();
|
|
118
168
|
let releaseLease = true;
|
|
119
169
|
try {
|
|
120
170
|
this.assertLive("background tool terminal handoff was delivered");
|
|
121
|
-
const
|
|
171
|
+
const unread = records.filter((record) => record.observedAt === undefined);
|
|
172
|
+
if (unread.length === 0)
|
|
173
|
+
return;
|
|
174
|
+
const toolMessage = createBackgroundToolTerminalMessage(unread);
|
|
175
|
+
const message = {
|
|
176
|
+
...toolMessage,
|
|
177
|
+
details: {
|
|
178
|
+
...toolMessage.details,
|
|
179
|
+
summary: createBackgroundActivitySummaryContract("task", unread.map((record) => ({
|
|
180
|
+
id: record.taskId,
|
|
181
|
+
status: record.status === "failed"
|
|
182
|
+
? "failed"
|
|
183
|
+
: record.status === "canceled"
|
|
184
|
+
? "canceled"
|
|
185
|
+
: "success",
|
|
186
|
+
}))),
|
|
187
|
+
},
|
|
188
|
+
};
|
|
189
|
+
const started = await this.deps.startCustomMessageTurn(message, lease);
|
|
122
190
|
this.releaseAfterTurn(started.completion, lease, "background tool terminal handoff turn");
|
|
123
191
|
releaseLease = false;
|
|
124
192
|
}
|