@moretea-labs/forge 1.8.1 → 1.8.2
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/AGENTS.md +5 -2
- package/CHANGELOG.md +20 -0
- package/README.en.md +24 -3
- package/README.md +10 -6
- package/README.zh-CN.md +5 -3
- package/THIRD_PARTY_NOTICES.md +1 -2
- package/adapters/chatgpt/browser-delivery-runtime.ts +5 -3
- package/adapters/chatgpt/provider-delivery.ts +1 -1
- package/adapters/chatgpt/work-conversation-binding-store.ts +20 -1
- package/adapters/computer/chatgpt-extension-target.ts +295 -50
- package/adapters/computer/chrome-extension/background.js +227 -71
- package/adapters/computer/chrome-extension/content.js +181 -157
- package/adapters/computer/chrome-extension/manifest.json +3 -1
- package/adapters/computer/desktop-operator-provider.ts +18 -6
- package/adapters/computer/interaction-target-authority.ts +39 -9
- package/adapters/mcp/access-mode.ts +18 -39
- package/adapters/mcp/auth.ts +2 -6
- package/adapters/mcp/instructions.ts +2 -2
- package/adapters/mcp/multi-repository.ts +7 -28
- package/adapters/mcp/runtime-gateway/context-adapter.ts +79 -40
- package/adapters/mcp/runtime-gateway/context-pack-sidecar.ts +7 -15
- package/adapters/mcp/runtime-gateway/execution-tools.ts +7 -13
- package/adapters/mcp/runtime-gateway/plugin-adapter.ts +16 -3
- package/adapters/mcp/runtime-gateway/process-tools.ts +3 -21
- package/adapters/mcp/runtime-gateway/router.ts +3 -5
- package/adapters/mcp/runtime-gateway/routing-policy.ts +17 -10
- package/adapters/mcp/runtime-gateway/runtime-observation-adapter.ts +1 -1
- package/adapters/mcp/runtime-gateway/runtime-tool-definitions.ts +14 -9
- package/adapters/mcp/runtime-gateway/runtime-tools.ts +1 -5
- package/adapters/mcp/runtime-gateway/scheduler-adapter.ts +36 -1
- package/adapters/mcp/runtime-gateway/status-inbox-adapter.ts +58 -4
- package/adapters/mcp/runtime-gateway/typescript-navigation-sidecar.ts +7 -3
- package/adapters/mcp/runtime-gateway/work-adapter.ts +16 -16
- package/adapters/mcp/runtime-gateway/work-input-wire-migration.ts +0 -17
- package/adapters/mcp/runtime-gateway/work-semantic-operations.ts +69 -12
- package/adapters/mcp/runtime-gateway/workflow-supervisor-adapter.ts +26 -2
- package/adapters/mcp/server.ts +24 -3
- package/adapters/mcp/setup.ts +4 -10
- package/adapters/mcp/tool-mapping/access-tools.ts +0 -6
- package/adapters/mcp/tool-mapping/legacy-tool-service.ts +672 -2935
- package/adapters/mcp/tool-mapping/post-finalize-work-attribution.ts +1 -1
- package/adapters/mcp/tool-mapping/repository-tools.ts +52 -86
- package/adapters/mcp/toolset-names.ts +11 -42
- package/adapters/mcp/toolset.ts +16 -90
- package/{src/cli → adapters}/mcp/transports/AGENTS.md +5 -5
- package/{src/cli → adapters}/mcp/transports/CLAUDE.md +5 -5
- package/adapters/mcp/transports/http-observation.ts +18 -6
- package/adapters/mcp/transports/http-post-lifecycle.ts +19 -0
- package/adapters/mcp/transports/http.ts +54 -14
- package/adapters/mcp/types.ts +0 -6
- package/assets/hooks/lib/session-state.sh +0 -38
- package/assets/hooks/post-bash.sh +1 -1
- package/assets/hooks/post-tool-observer.sh +0 -5
- package/assets/hooks/prompt-guard.sh +0 -55
- package/assets/partials/04-project-structure.partial.md +1 -1
- package/assets/partials/07-footer.partial.md +1 -1
- package/assets/partials-agents/02-operating-mode.partial.md +1 -1
- package/assets/partials-agents/08-deep-docs.partial.md +1 -1
- package/assets/reference-configs/agentic-development-flow.md +1 -1
- package/assets/reference-configs/external-tooling.md +0 -76
- package/assets/reference-configs/release-deploy.md +1 -1
- package/assets/templates/helpers/architecture-queue.sh +1 -1
- package/assets/templates/helpers/check-agent-tooling.sh +1 -327
- package/assets/templates/helpers/check-task-workflow.sh +1 -1
- package/assets/templates/helpers/ensure-task-workflow.sh +0 -14
- package/assets/templates/helpers/migrate-project-template.sh +2 -2
- package/assets/workflow-contract.v1.json +0 -2
- package/docs/README.md +5 -2
- package/docs/architecture/CURRENT.md +114 -30
- package/docs/architecture/decisions/20260904-ios-device-migration-baseline.md +42 -0
- package/docs/architecture/decisions/20260918-stable-candidate-release-lifecycle.md +15 -2
- package/docs/architecture/decisions/20260924-thin-semantic-working-context.md +4 -2
- package/docs/architecture/decisions/20261001-supervisor-turn-authority.md +109 -4
- package/docs/architecture/decisions/20261009-exact-code-context-discovery.md +19 -0
- package/docs/architecture/decisions/20261009-generated-xcode-cache-retention.md +37 -0
- package/docs/architecture/decisions/20261011-autonomous-continuation-convergence.md +597 -0
- package/docs/architecture/decisions/20261017-edit-session-finalization-reconciliation.md +17 -0
- package/docs/architecture/decisions/20261019-retire-host-skills.md +16 -0
- package/docs/architecture/diagrams/agentic-dev-plugin-architecture.html +1 -1
- package/docs/architecture/domains/public-surface.md +3 -5
- package/docs/architecture/domains/verification.md +5 -5
- package/docs/architecture/modules/controller-runtime/transport-lifecycle.md +2 -2
- package/docs/architecture/requests/2026-09-04-computer-plugin-workflow-taxonomy.md +4 -4
- package/docs/architecture/reviews/20261015-code-search-runtime-acceptance.md +75 -0
- package/docs/forge-plugin-management.md +14 -2
- package/docs/operations/controller-browser-plugin.md +23 -0
- package/docs/operations/features.md +6 -7
- package/docs/operations/features.zh-CN.md +1 -1
- package/docs/operations/github-repository.md +4 -4
- package/docs/operations/github-semantic-release-projection.md +20 -0
- package/docs/operations/homebrew.md +2 -2
- package/docs/operations/mcp-tool-exposure.md +13 -54
- package/docs/operations/runtime-performance-diagnostics.md +8 -0
- package/docs/operations/standalone-disaster-recovery.md +1 -1
- package/docs/tutorials/01-install-and-start.zh-CN.md +1 -1
- package/docs/tutorials/03-first-repository-task.md +2 -0
- package/docs/wiki/Computer-and-Plugins.md +78 -0
- package/docs/wiki/Computer-and-Plugins.zh-CN.md +88 -0
- package/docs/wiki/Home.md +16 -2
- package/docs/wiki/Implementation.md +24 -12
- package/docs/wiki/Installation.md +28 -32
- package/docs/wiki/Integrations.md +4 -0
- package/docs/wiki/Quick-Start.md +35 -22
- package/docs/wiki/Releases-and-Upgrades.md +15 -25
- package/docs/wiki/_Sidebar.md +5 -1
- package/package.json +1 -12
- package/packages/kernel/controller/infrastructure/controller-session-store.ts +63 -38
- package/packages/kernel/identity/infrastructure/activity-projection-store.ts +10 -0
- package/packages/kernel/scheduler/application/eligibility.ts +4 -1
- package/packages/kernel/scheduler/infrastructure/schedule-store.ts +13 -10
- package/packages/kernel/work/application/work-service.ts +1 -0
- package/packages/kernel/work/domain/repository-completion-receipt.ts +1 -1
- package/packages/kernel/work/domain/state-machine.ts +9 -2
- package/packages/kernel/work/infrastructure/work-contract-store.ts +28 -1
- package/packages/plugin-runtime/browser/provider-registry.ts +12 -36
- package/packages/plugin-runtime/computer/conversation-target.ts +17 -7
- package/scripts/assemble-template.ts +11 -72
- package/scripts/check-mcp-compatibility.ts +55 -74
- package/scripts/check-package-identity.mjs +0 -5
- package/scripts/check-runtime-architecture.mjs +305 -28
- package/scripts/init-project.sh +0 -46
- package/scripts/install-ios-hid-toolchain.sh +60 -0
- package/scripts/install-standalone-recovery.ts +1 -1
- package/scripts/lib/project-init-lib.sh +3 -3
- package/scripts/migrate-windows-wsl-controller-home.ts +2 -0
- package/scripts/open-source-audit-allowlist.txt +0 -1
- package/scripts/run-governed-gate.ts +2 -0
- package/scripts/smoke-ios-physical-device.ts +38 -10
- package/scripts/smoke-mcp-http-runtime.ts +7 -8
- package/scripts/smoke-mcp-tool-surface.ts +27 -41
- package/scripts/smoke-workflow-supervisor-chrome-adapter.ts +6 -3
- package/scripts/sync-generated-authority.mjs +0 -1
- package/src/cli/agent-jobs/executor-health.ts +1 -1
- package/src/cli/agent-jobs/integration.ts +2 -2
- package/src/cli/chatgpt-browser/file-policy.ts +2 -2
- package/src/cli/commands/doctor.ts +1 -143
- package/src/cli/commands/global-runtime.ts +3 -196
- package/src/cli/commands/init-hook.ts +6 -23
- package/src/cli/commands/init.ts +3 -252
- package/src/cli/commands/mcp.ts +0 -5
- package/src/cli/commands/prompt-guard-decision.ts +0 -2
- package/src/cli/commands/recovery.ts +2 -14
- package/src/cli/commands/repository.ts +17 -1
- package/src/cli/commands/setup-execution.ts +41 -0
- package/src/cli/controller/completion-orchestrator.ts +1 -1
- package/src/cli/controller/composite-operations.ts +1 -1
- package/src/cli/controller/context/instruction-context.ts +1 -1
- package/src/cli/controller/context/known-paths.ts +2 -2
- package/src/cli/controller/context/query-planning.ts +11 -4
- package/src/cli/controller/context/rule-resolution.ts +2 -2
- package/src/cli/controller/context/source-materializer.ts +2 -2
- package/src/cli/controller/context/structural-provider.ts +84 -0
- package/src/cli/controller/context/structural.ts +6 -6
- package/src/cli/controller/context/types.ts +8 -9
- package/src/cli/controller/context-pack.ts +97 -76
- package/src/cli/controller/operational-plan.ts +1 -1
- package/src/cli/controller/systemd-user.ts +4 -10
- package/src/cli/editing/edit-session.ts +17 -5
- package/src/cli/github/github.ts +4 -4
- package/src/cli/github/semantic-projection.ts +174 -0
- package/src/cli/hook/prompt-intents.ts +0 -9
- package/src/cli/index.ts +1 -43
- package/src/cli/local-bridge/connector-freshness.ts +1 -12
- package/src/cli/local-bridge/console-automations.ts +1 -1
- package/src/cli/local-bridge/console-view-models.ts +1 -1
- package/src/cli/local-bridge/facade-api.ts +0 -2
- package/src/cli/repositories/command-classifier.ts +0 -9
- package/src/cli/repositories/command-scope.ts +2 -2
- package/src/cli/repositories/locks.ts +20 -0
- package/src/cli/repositories/registry.ts +2 -1
- package/src/cli/repositories/safe-patch.ts +2 -12
- package/src/cli/repositories/structured-git.ts +39 -3
- package/src/cli/repository/inspector.ts +185 -343
- package/src/effects/process-runner.ts +17 -1
- package/src/runtime/context/generic-lsp-provider.ts +1 -1
- package/src/runtime/context/semantic-navigation-contract.ts +7 -0
- package/src/runtime/context/semantic-navigation.ts +1 -1
- package/src/runtime/control-plane/cleanup-artifact-retention.ts +4 -4
- package/src/runtime/control-plane/execution/work-delivery-service.ts +150 -31
- package/src/runtime/control-plane/execution/work-handle-authority.ts +12 -4
- package/src/runtime/control-plane/execution/work-handle-store.ts +53 -1
- package/src/runtime/control-plane/execution/work-operation-service.ts +20 -10
- package/src/runtime/control-plane/execution/work-preparation-service.ts +108 -4
- package/src/runtime/control-plane/execution/work-process-evidence.ts +2 -2
- package/src/runtime/control-plane/execution/work-terminal-cleanup.ts +28 -13
- package/src/runtime/control-plane/execution/work-validation-reconciler.ts +5 -1
- package/src/runtime/control-plane/execution/work-verification-snapshot.ts +1 -1
- package/src/runtime/control-plane/facade/capability-registry.ts +2 -0
- package/src/runtime/control-plane/facade/work-continuation.ts +1 -1
- package/src/runtime/control-plane/generated-cache-retention.ts +114 -63
- package/src/runtime/control-plane/global-scheduler/maintenance.ts +20 -8
- package/src/runtime/control-plane/global-scheduler/reconciliation.ts +1 -11
- package/src/runtime/control-plane/governance/external-effects.ts +1 -1
- package/src/runtime/control-plane/launcher/chatgpt-work-continuation.ts +1 -0
- package/src/runtime/control-plane/runtime-cleanup.ts +12 -93
- package/src/runtime/evidence/sensitive-output.ts +22 -2
- package/src/runtime/execution/jobs/child-reference.ts +11 -0
- package/src/runtime/execution/jobs/receipt-recovery.ts +1 -11
- package/src/runtime/execution/process-runtime/command-facade.ts +3 -3
- package/src/runtime/execution/process-runtime/runtime.ts +20 -16
- package/src/runtime/execution/thin-harness/execution-router.ts +16 -16
- package/src/runtime/execution/thin-harness/fast-executor.ts +2 -2
- package/src/runtime/execution/thin-harness/search-worker.ts +2 -2
- package/src/runtime/execution/workers/executor.ts +1 -2
- package/src/runtime/maintenance/cleanup.ts +41 -5
- package/src/runtime/plugins/action-application.ts +12 -1
- package/src/runtime/plugins/app-store-connect-adapter.ts +252 -4
- package/src/runtime/plugins/browser-adapter.ts +381 -313
- package/src/runtime/plugins/browser-macos-bridge.ts +114 -112
- package/src/runtime/plugins/browser-manifest-surface.ts +2 -1
- package/src/runtime/plugins/browser-registration.ts +2 -0
- package/src/runtime/plugins/browser-runtime.ts +26 -35
- package/src/runtime/plugins/computer-chatgpt-browser-adapter-installer.ts +11 -2
- package/src/runtime/plugins/computer-registration.ts +76 -9
- package/src/runtime/plugins/github-adapter.ts +30 -3
- package/src/runtime/plugins/gmail-adapter.ts +166 -1
- package/src/runtime/plugins/google-shared.ts +10 -5
- package/src/runtime/plugins/ios/remote-xpc-hid.ts +70 -30
- package/src/runtime/plugins/ios-adapter.ts +45 -40
- package/src/runtime/plugins/ios-agent-device.ts +54 -4
- package/src/runtime/plugins/ios-device-ownership.ts +103 -0
- package/src/runtime/plugins/ios-physical-device.ts +497 -79
- package/src/runtime/plugins/local-system-adapter.ts +1 -99
- package/src/runtime/plugins/store.ts +80 -7
- package/src/runtime/plugins/types.ts +4 -0
- package/src/runtime/projections/git-status-sampler.ts +2 -19
- package/src/runtime/recovery/actions.ts +1 -1
- package/src/runtime/recovery/lifecycle-inventory.ts +1 -11
- package/src/runtime/recovery/probe.ts +2 -2
- package/src/runtime/release/release-coordinator.ts +20 -4
- package/src/runtime/root/controller-progression-composition.ts +67 -5
- package/src/runtime/root/package-connector-service.ts +123 -11
- package/src/runtime/root/package-runtime-release.ts +6 -18
- package/src/runtime/root/package-runtime-service.ts +7 -13
- package/src/runtime/root/release-execution-canary.ts +18 -5
- package/src/runtime/root/release-manifest.ts +0 -34
- package/src/runtime/root/release-materialize.ts +0 -78
- package/src/runtime/root/runtime.ts +1 -2
- package/src/runtime/root/scheduled-controller-composition.ts +2 -1
- package/src/runtime/root/service.ts +90 -11
- package/src/runtime/root/types.ts +0 -6
- package/src/runtime/root/workflow-supervisor-composition.ts +207 -19
- package/src/runtime/root/workflow-supervisor-runtime.ts +365 -10
- package/src/runtime/safe-tooling/google-credential-store.ts +1 -11
- package/src/runtime/safe-tooling/ios-development.ts +22 -8
- package/src/runtime/safe-tooling/job-summary.ts +1 -1
- package/src/runtime/safe-tooling/workspace-auth.ts +4 -1
- package/src/runtime/shared/atomic-text-file.ts +21 -0
- package/src/runtime/shared/json-files.ts +8 -3
- package/src/runtime/standalone-recovery/core.ts +189 -174
- package/src/runtime/standalone-recovery/entry.ts +62 -30
- package/src/runtime/standalone-recovery/operation-lock.ts +11 -1
- package/src/runtime/workflow/schedules/chatgpt-automation-migration.ts +1 -0
- package/src/runtime/workflow/schedules/engine.ts +36 -14
- package/src/runtime/workflow/schedules/pending-activation.ts +11 -4
- package/src/runtime/workflow/schedules/work-continuation.ts +51 -6
- package/supervisor/client.ts +31 -14
- package/supervisor/control-plane.ts +210 -115
- package/supervisor/forge-validators.ts +88 -21
- package/supervisor/native-browser-adapter.ts +393 -28
- package/supervisor/native-messaging/host.ts +21 -2
- package/supervisor/protocol.ts +74 -26
- package/supervisor/server.ts +16 -8
- package/supervisor/store.ts +476 -57
- package/supervisor/types.ts +19 -13
- package/SKILL.md +0 -427
- package/adapters/computer/chatgpt-target-router.ts +0 -103
- package/adapters/mcp/runtime-gateway/automation-receipt-adapter.ts +0 -87
- package/adapters/mcp/runtime-gateway/work-validation-reconciler.ts +0 -1
- package/adapters/mcp/toolset-selection.ts +0 -41
- package/agents/openai.yaml +0 -4
- package/assets/skill-hooks.json +0 -41
- package/assets/skill-version.json +0 -189
- package/assets/skills/claude-review/SKILL.md +0 -231
- package/assets/skills/codex-review/SKILL.md +0 -103
- package/assets/templates/helpers/check-skill-version.ts +0 -193
- package/scripts/check-skill-version.ts +0 -5
- package/scripts/ensure-codegraph.sh +0 -16
- package/scripts/run-skill-hook.ts +0 -244
- package/scripts/sync-codex-installed-copies.sh +0 -182
- package/src/cli/commands/tools.ts +0 -167
- package/src/cli/mcp/access-mode.ts +0 -2
- package/src/cli/mcp/access-tools.ts +0 -2
- package/src/cli/mcp/audit.ts +0 -2
- package/src/cli/mcp/auth.ts +0 -2
- package/src/cli/mcp/instructions.ts +0 -2
- package/src/cli/mcp/legacy-context.ts +0 -2
- package/src/cli/mcp/legacy-tool-service.ts +0 -2
- package/src/cli/mcp/multi-repository.ts +0 -2
- package/src/cli/mcp/oauth.ts +0 -2
- package/src/cli/mcp/openai-secure-tunnel.ts +0 -2
- package/src/cli/mcp/paths.ts +0 -2
- package/src/cli/mcp/policy.ts +0 -2
- package/src/cli/mcp/post-finalize-work-attribution.ts +0 -2
- package/src/cli/mcp/proxy-env.ts +0 -2
- package/src/cli/mcp/readiness-projection.ts +0 -2
- package/src/cli/mcp/redaction.ts +0 -2
- package/src/cli/mcp/repo.ts +0 -2
- package/src/cli/mcp/repository-tools.ts +0 -2
- package/src/cli/mcp/server.ts +0 -2
- package/src/cli/mcp/setup.ts +0 -2
- package/src/cli/mcp/tool-capability-cache.ts +0 -2
- package/src/cli/mcp/tool-contract.ts +0 -2
- package/src/cli/mcp/tools.ts +0 -2
- package/src/cli/mcp/toolset-names.ts +0 -2
- package/src/cli/mcp/toolset-selection.ts +0 -2
- package/src/cli/mcp/toolset.ts +0 -2
- package/src/cli/mcp/transports/http.ts +0 -2
- package/src/cli/mcp/transports/session-registry.ts +0 -2
- package/src/cli/mcp/transports/stdio.ts +0 -2
- package/src/cli/mcp/types.ts +0 -2
- package/src/cli/mcp/umbrella-tools.ts +0 -2
- package/src/cli/tools/codegraph.ts +0 -695
- package/src/core/adoption/helper-wrapper-plan.ts +0 -159
- package/src/runtime/context/codegraph-cache-boundary.ts +0 -255
- package/src/runtime/context/codegraph-read-provider.ts +0 -611
- package/src/runtime/context/codegraph-sidecar.cjs +0 -248
- package/src/runtime/control-plane/codegraph-cache-retention.ts +0 -164
- package/src/runtime/gateway/mcp/execution-tools.ts +0 -2
- package/src/runtime/gateway/mcp/legacy-ios-tool-adapter.ts +0 -2
- package/src/runtime/gateway/mcp/persisted-check-process.ts +0 -2
- package/src/runtime/gateway/mcp/process-tools.ts +0 -2
- package/src/runtime/gateway/mcp/router.ts +0 -2
- package/src/runtime/gateway/mcp/runtime-tool-definitions.ts +0 -2
- package/src/runtime/gateway/mcp/runtime-tools.ts +0 -2
- package/src/runtime/gateway/mcp/work-validation-reconciler.ts +0 -2
- package/src/runtime/plugins/browser-provider-registry.ts +0 -2
- package/src/runtime/plugins/computer-chatgpt-macos-target.ts +0 -891
|
@@ -28,11 +28,30 @@ export async function forwardNativeRequest(value: unknown, forgeHome?: string):
|
|
|
28
28
|
}
|
|
29
29
|
export function runNativeMessagingHost(forgeHome?: string): void {
|
|
30
30
|
const decoder = new NativeMessageDecoder();
|
|
31
|
-
let chain = Promise.resolve();
|
|
32
31
|
process.stdin.on('data', (chunk: Buffer) => {
|
|
33
32
|
let messages: unknown[];
|
|
34
33
|
try { messages = decoder.push(chunk); } catch (error) { process.stdout.write(encodeNativeMessage({ id: 'invalid', ok: false, error: { code: 'WORKFLOW_SUPERVISOR_NATIVE_FRAME_INVALID', message: String(error) } })); return; }
|
|
35
|
-
|
|
34
|
+
// Chrome matches replies by request id, not FIFO position. A slow page
|
|
35
|
+
// discovery/command must never queue heartbeats behind its 30s RPC budget:
|
|
36
|
+
// the Computer broker expires a provider heartbeat after 15s. Requests
|
|
37
|
+
// use independent Supervisor socket calls; the broker still exclusively
|
|
38
|
+
// owns effect claims, dispatch outcomes and exactly-once Send safety.
|
|
39
|
+
for (const message of messages) {
|
|
40
|
+
void forwardNativeRequest(message, forgeHome).then(
|
|
41
|
+
(response) => { process.stdout.write(encodeNativeMessage(response)); },
|
|
42
|
+
(error) => {
|
|
43
|
+
// Bad individual requests must not poison subsequent heartbeats.
|
|
44
|
+
const id = message && typeof message === 'object' && !Array.isArray(message)
|
|
45
|
+
&& typeof (message as { id?: unknown }).id === 'string'
|
|
46
|
+
? (message as { id: string }).id : 'invalid';
|
|
47
|
+
const detail = error instanceof Error ? error.message : String(error);
|
|
48
|
+
process.stdout.write(encodeNativeMessage({ id, ok: false, error: {
|
|
49
|
+
code: detail.split(':', 1)[0] || 'WORKFLOW_SUPERVISOR_NATIVE_REQUEST_INVALID',
|
|
50
|
+
message: detail,
|
|
51
|
+
} }));
|
|
52
|
+
},
|
|
53
|
+
);
|
|
54
|
+
}
|
|
36
55
|
});
|
|
37
56
|
process.stdin.resume();
|
|
38
57
|
}
|
package/supervisor/protocol.ts
CHANGED
|
@@ -6,7 +6,16 @@ import type { WorkflowEffectKind, WorkflowSupervisorProposal, WorkflowSupervisor
|
|
|
6
6
|
// block formats remain read-only compatibility for already-durable conversations.
|
|
7
7
|
export const SUPERVISOR_BLOCK_START = 'FORGE_WORKFLOW_SUPERVISOR_V1_BEGIN';
|
|
8
8
|
export const SUPERVISOR_BLOCK_END = 'FORGE_WORKFLOW_SUPERVISOR_V1_END';
|
|
9
|
-
const COMPACT_RECEIPT =
|
|
9
|
+
const COMPACT_RECEIPT = /(?:^|\n)([CWDU]) ([0-9a-f]{7})\s*$/;
|
|
10
|
+
// Older installed Chrome content scripts flattened an entire completed reply
|
|
11
|
+
// into one line. The immutable Effect challenge remains the sole authority;
|
|
12
|
+
// recover only its terminal token, never an inline token in multiline text.
|
|
13
|
+
const FLATTENED_COMPACT_RECEIPT = /(?:^| )([CWDU]) ([0-9a-f]{7})$/;
|
|
14
|
+
function terminalCompactReceipt(responseText: string): RegExpExecArray | null {
|
|
15
|
+
const text = responseText.trim();
|
|
16
|
+
return COMPACT_RECEIPT.exec(text)
|
|
17
|
+
?? (!/[\r\n]/.test(text) ? FLATTENED_COMPACT_RECEIPT.exec(text) : null);
|
|
18
|
+
}
|
|
10
19
|
export const LEGACY_BRACKET_SUPERVISOR_BLOCK_START = '[[[FORGE_WORKFLOW_SUPERVISOR_V1]]]';
|
|
11
20
|
export const LEGACY_BRACKET_SUPERVISOR_BLOCK_END = '[[[END_FORGE_WORKFLOW_SUPERVISOR_V1]]]';
|
|
12
21
|
export const LEGACY_SUPERVISOR_BLOCK_START = '<<<FORGE_WORKFLOW_SUPERVISOR_V1>>>';
|
|
@@ -16,6 +25,14 @@ export const SUPERVISOR_TURN_BLOCK_START = 'FORGE_WORKFLOW_TURN_V2_BEGIN';
|
|
|
16
25
|
export const SUPERVISOR_TURN_BLOCK_END = 'FORGE_WORKFLOW_TURN_V2_END';
|
|
17
26
|
const EFFECT_ID = /^(?:fx|crpe)_[a-zA-Z0-9_-]{8,120}$/;
|
|
18
27
|
const MAX_RESPONSE = 512 * 1024;
|
|
28
|
+
export const MAX_SUPERVISOR_OBJECTIVE_CHARS = 8_000;
|
|
29
|
+
|
|
30
|
+
/** A goal cannot be silently shortened between durable Task and sent effect. */
|
|
31
|
+
export function validateSupervisorObjective(value: string): string {
|
|
32
|
+
if (typeof value !== 'string' || !value.trim()) throw new Error('WORKFLOW_SUPERVISOR_OBJECTIVE_REQUIRED');
|
|
33
|
+
if (value.length > MAX_SUPERVISOR_OBJECTIVE_CHARS) throw new Error('WORKFLOW_SUPERVISOR_OBJECTIVE_TOO_LARGE');
|
|
34
|
+
return value;
|
|
35
|
+
}
|
|
19
36
|
const SUPERVISOR_BLOCK_MARKERS = [
|
|
20
37
|
{ start: SUPERVISOR_BLOCK_START, end: SUPERVISOR_BLOCK_END },
|
|
21
38
|
{ start: LEGACY_BRACKET_SUPERVISOR_BLOCK_START, end: LEGACY_BRACKET_SUPERVISOR_BLOCK_END },
|
|
@@ -50,7 +67,7 @@ export function renderSupervisorReceipt(
|
|
|
50
67
|
effectId: string,
|
|
51
68
|
action: WorkflowSupervisorProposal['action'],
|
|
52
69
|
): string {
|
|
53
|
-
const code = action === 'CONTINUE' ? 'C' : action === 'DONE' ? 'D' : 'U';
|
|
70
|
+
const code = action === 'CONTINUE' ? 'C' : action === 'WAIT' ? 'W' : action === 'DONE' ? 'D' : 'U';
|
|
54
71
|
return `${code} ${supervisorReceiptChallenge(task, effectId)}`;
|
|
55
72
|
}
|
|
56
73
|
|
|
@@ -73,34 +90,58 @@ function supervisorBlockEnvelope(responseText: string): { start: number; end: nu
|
|
|
73
90
|
|
|
74
91
|
export function hasCommittedSupervisorEnvelope(responseText: string): boolean {
|
|
75
92
|
if (Buffer.byteLength(responseText, 'utf8') > MAX_RESPONSE) return false;
|
|
76
|
-
if (
|
|
93
|
+
if (terminalCompactReceipt(responseText)) return true;
|
|
77
94
|
try { supervisorBlockEnvelope(responseText); return true; } catch { return false; }
|
|
78
95
|
}
|
|
79
96
|
|
|
80
97
|
export function parseSupervisorCompletion(
|
|
81
98
|
responseText: string,
|
|
82
|
-
expected?: { task: Pick<WorkflowSupervisorTask, 'taskId' | 'conversationId'>; effectId: string },
|
|
99
|
+
expected?: { task: Pick<WorkflowSupervisorTask, 'taskId' | 'conversationId' | 'continuationPolicy'>; effectId: string; prompt?: string },
|
|
83
100
|
): { proposal: WorkflowSupervisorProposal; controlBlock: string } {
|
|
84
101
|
if (Buffer.byteLength(responseText, 'utf8') > MAX_RESPONSE) throw new Error('WORKFLOW_SUPERVISOR_RESPONSE_TOO_LARGE');
|
|
85
|
-
const compact =
|
|
102
|
+
const compact = terminalCompactReceipt(responseText);
|
|
86
103
|
if (compact) {
|
|
87
104
|
if (!expected) throw new Error('WORKFLOW_SUPERVISOR_COMPACT_RECEIPT_CONTEXT_REQUIRED');
|
|
88
|
-
|
|
105
|
+
let challenge = supervisorReceiptChallenge(expected.task, expected.effectId);
|
|
106
|
+
// Bootstrap binding changes the Task's conversation identity after Send.
|
|
107
|
+
// Validate the challenge actually sent in the immutable effect, never a
|
|
108
|
+
// recomputation from that subsequently changed Task projection.
|
|
109
|
+
if (expected.prompt?.includes(SUPERVISOR_TURN_BLOCK_START)) {
|
|
110
|
+
const start = expected.prompt.indexOf(SUPERVISOR_TURN_BLOCK_START + '\n') + SUPERVISOR_TURN_BLOCK_START.length + 1;
|
|
111
|
+
const end = expected.prompt.indexOf('\n' + SUPERVISOR_TURN_BLOCK_END, start);
|
|
112
|
+
let envelope: WorkflowSupervisorTurnEnvelope;
|
|
113
|
+
try { envelope = JSON.parse(expected.prompt.slice(start, end)); }
|
|
114
|
+
catch { throw new Error('WORKFLOW_SUPERVISOR_EFFECT_RECEIPT_INVALID'); }
|
|
115
|
+
if (end < start || envelope?.schema_version !== 2
|
|
116
|
+
|| envelope.identity?.task_id !== expected.task.taskId
|
|
117
|
+
|| envelope.identity?.effect_id !== expected.effectId
|
|
118
|
+
|| !/^[0-9a-f]{7}$/.test(envelope.receipt?.challenge ?? '')) {
|
|
119
|
+
throw new Error('WORKFLOW_SUPERVISOR_EFFECT_RECEIPT_INVALID');
|
|
120
|
+
}
|
|
121
|
+
challenge = envelope.receipt.challenge;
|
|
122
|
+
}
|
|
89
123
|
if (compact[2] !== challenge) throw new Error('WORKFLOW_SUPERVISOR_COMPACT_RECEIPT_CHALLENGE_MISMATCH');
|
|
90
|
-
const action = compact[1] === 'C' ? 'CONTINUE' : compact[1] === 'D' ? 'DONE' : 'NEEDS_USER';
|
|
91
|
-
|
|
124
|
+
const action = compact[1] === 'C' ? 'CONTINUE' : compact[1] === 'W' ? 'WAIT' : compact[1] === 'D' ? 'DONE' : 'NEEDS_USER';
|
|
125
|
+
if (action === 'WAIT' && typeof expected.task.continuationPolicy.scheduled_wake_schedule_id !== 'string') {
|
|
126
|
+
throw new Error('WORKFLOW_SUPERVISOR_WAIT_NOT_SCHEDULED');
|
|
127
|
+
}
|
|
128
|
+
const supervisorState: WorkflowSupervisorState = action === 'CONTINUE' ? 'running' : action === 'WAIT' ? 'waiting' : action === 'DONE' ? 'done' : 'needs_user';
|
|
92
129
|
return {
|
|
93
130
|
proposal: {
|
|
94
131
|
action,
|
|
95
132
|
sourceEffectId: validateEffectId(expected.effectId),
|
|
96
133
|
checkpoint: `receipt:${challenge}`,
|
|
97
134
|
reason: 'compact_receipt',
|
|
98
|
-
evidence
|
|
135
|
+
// A transient missing tool is mechanical evidence, never user-only
|
|
136
|
+
// authorization. Persist the explicit model diagnostic on this same
|
|
137
|
+
// completion so crash reconciliation uses identical validation.
|
|
138
|
+
evidence: action === 'NEEDS_USER' && /(?:^|\r?\n)\s*NO_TOOL_RECEIPT(?=\s|[::]|$)/.test(responseText)
|
|
139
|
+
? ['NO_TOOL_RECEIPT'] : [],
|
|
99
140
|
conversationId: expected.task.conversationId,
|
|
100
141
|
taskId: expected.task.taskId,
|
|
101
142
|
supervisorState,
|
|
102
143
|
},
|
|
103
|
-
controlBlock:
|
|
144
|
+
controlBlock: compact[0].trim(),
|
|
104
145
|
};
|
|
105
146
|
}
|
|
106
147
|
const { start, end, startMarker, endMarker } = supervisorBlockEnvelope(responseText);
|
|
@@ -112,7 +153,10 @@ export function parseSupervisorCompletion(
|
|
|
112
153
|
const allowed = new Set(['action', 'source_effect_id', 'checkpoint', 'reason', 'evidence', 'conversation_id', 'task_id', 'supervisor_state', 'active_scope']);
|
|
113
154
|
if (Object.keys(record).some((key) => !allowed.has(key))) throw new Error('WORKFLOW_SUPERVISOR_CONTROL_BLOCK_FIELD_INVALID');
|
|
114
155
|
const action = boundedString(record.action, 'ACTION', 32);
|
|
115
|
-
if (!['CONTINUE', 'DONE', 'NEEDS_USER'].includes(action)) throw new Error('WORKFLOW_SUPERVISOR_ACTION_INVALID');
|
|
156
|
+
if (!['CONTINUE', 'WAIT', 'DONE', 'NEEDS_USER'].includes(action)) throw new Error('WORKFLOW_SUPERVISOR_ACTION_INVALID');
|
|
157
|
+
if (action === 'WAIT' && (!expected || typeof expected.task.continuationPolicy.scheduled_wake_schedule_id !== 'string')) {
|
|
158
|
+
throw new Error('WORKFLOW_SUPERVISOR_WAIT_NOT_SCHEDULED');
|
|
159
|
+
}
|
|
116
160
|
const sourceEffectId = validateEffectId(boundedString(record.source_effect_id, 'SOURCE_EFFECT_ID', 128));
|
|
117
161
|
const checkpoint = boundedString(record.checkpoint, 'CHECKPOINT', 2_000);
|
|
118
162
|
const reason = boundedString(record.reason, 'REASON', 2_000);
|
|
@@ -122,8 +166,8 @@ export function parseSupervisorCompletion(
|
|
|
122
166
|
const taskId = record.task_id === undefined ? undefined : boundedString(record.task_id, 'TASK_ID', 512);
|
|
123
167
|
const supervisorState = record.supervisor_state === undefined ? undefined : boundedString(record.supervisor_state, 'SUPERVISOR_STATE', 32) as WorkflowSupervisorState;
|
|
124
168
|
const activeScope = record.active_scope === undefined ? undefined : boundedString(record.active_scope, 'ACTIVE_SCOPE', 512);
|
|
125
|
-
if (supervisorState && !['running', 'done', 'needs_user'].includes(supervisorState)) throw new Error('WORKFLOW_SUPERVISOR_STATE_INVALID');
|
|
126
|
-
const expectedState: WorkflowSupervisorState = action === 'CONTINUE' ? 'running' : action === 'DONE' ? 'done' : 'needs_user';
|
|
169
|
+
if (supervisorState && !['running', 'waiting', 'done', 'needs_user'].includes(supervisorState)) throw new Error('WORKFLOW_SUPERVISOR_STATE_INVALID');
|
|
170
|
+
const expectedState: WorkflowSupervisorState = action === 'CONTINUE' ? 'running' : action === 'WAIT' ? 'waiting' : action === 'DONE' ? 'done' : 'needs_user';
|
|
127
171
|
if (supervisorState && supervisorState !== expectedState) throw new Error('WORKFLOW_SUPERVISOR_STATE_ACTION_MISMATCH');
|
|
128
172
|
if (activeScope && !/^(?:requirement|goal):[^\s]{1,480}$/.test(activeScope)) throw new Error('WORKFLOW_SUPERVISOR_ACTIVE_SCOPE_INVALID');
|
|
129
173
|
const controlBlock = responseText.slice(start, end + endMarker.length);
|
|
@@ -154,7 +198,10 @@ export function renderSupervisorPrompt(
|
|
|
154
198
|
const checkoutId = typeof task.completionContract.checkout_id === 'string'
|
|
155
199
|
? task.completionContract.checkout_id.trim()
|
|
156
200
|
: typeof task.continuationPolicy.checkout_id === 'string' ? task.continuationPolicy.checkout_id.trim() : '';
|
|
157
|
-
|
|
201
|
+
// An automation receipt is a causal key, not an engineering handoff.
|
|
202
|
+
// Conversation context and live project evidence guide the next action.
|
|
203
|
+
const rawCheckpoint = typeof _checkpoint === 'string' ? _checkpoint.trim() : '';
|
|
204
|
+
const checkpoint = /^(?:automation:|receipt:)/.test(rawCheckpoint) ? '' : rawCheckpoint.slice(0, 2_000);
|
|
158
205
|
// Recovery/correction context is model-facing advisory evidence, not another
|
|
159
206
|
// authority. Discarding it made a recovery look like the original request
|
|
160
207
|
// and allowed the model to repeat previously completed work.
|
|
@@ -174,28 +221,29 @@ export function renderSupervisorPrompt(
|
|
|
174
221
|
},
|
|
175
222
|
goal: {
|
|
176
223
|
role: 'outcome',
|
|
177
|
-
objective: task.objective
|
|
224
|
+
objective: validateSupervisorObjective(task.objective),
|
|
178
225
|
},
|
|
179
226
|
...(continuity ? { continuity: { role: 'advisory' as const, summary: continuity } } : {}),
|
|
180
227
|
...(repoId ? { repository: { repo_id: repoId, ...(checkoutId ? { checkout_id: checkoutId } : {}) } } : {}),
|
|
181
228
|
...(cognition ? { cognition: { role: 'advisory' as const, projection: cognition } } : {}),
|
|
182
|
-
|
|
183
|
-
automation_task_id: task.taskId,
|
|
184
|
-
automation_type: 'autonomous_continuation',
|
|
185
|
-
intermediate_status: 'working',
|
|
186
|
-
final_statuses: ['continue', 'done', 'needs_user'],
|
|
187
|
-
},
|
|
229
|
+
receipt: { challenge: supervisorReceiptChallenge(task, effectId) },
|
|
188
230
|
};
|
|
189
231
|
return [
|
|
190
|
-
'@forge',
|
|
191
232
|
renderEffectMarker(effectId),
|
|
233
|
+
// Keep the exact Effect marker first for existing target matching, but
|
|
234
|
+
// surface tool intent before the potentially long JSON goal envelope.
|
|
235
|
+
'forge 继续。使用真实可用的 Forge 工具接续未完成的工作;不必每轮先做工具或全局状态自检。',
|
|
192
236
|
SUPERVISOR_TURN_BLOCK_START,
|
|
193
237
|
JSON.stringify(envelope),
|
|
194
238
|
SUPERVISOR_TURN_BLOCK_END,
|
|
195
|
-
//
|
|
196
|
-
//
|
|
197
|
-
|
|
198
|
-
'
|
|
239
|
+
// Textual intent only: Project instructions and literal @forge are not proof
|
|
240
|
+
// of an App binding. No browser/plugin UI mutation belongs in this renderer.
|
|
241
|
+
'USE FORGE: 使用 forge。已有真实工具时直接执行相关源码、验证或交付动作,不要强制以 rh_status 开始。JSON、项目指令或文字 @forge 不会授予工具权限;如果工具完全不可见,仅检查一次实际提供的发现入口(如有 functions.exec 可经 ALL_TOOLS 查询 mcp__forge__),不要反复自检或要求用户选择 App,也不能伪造调用。无工具时正文写 NO_TOOL_RECEIPT 和真实缺口,不宣称工程产出。',
|
|
242
|
+
'DELIVER WORK: 把 objective 当作持续目标,像用户直接发送“继续”一样从本会话最近的未完成工作处继续;同一交付仍有安全、相关且必要的步骤时,本轮持续实现、验证、审阅并合法交付,不要因完成一次查询或一个微步而收尾。只补充当前真正缺失的证据,复用已有检查;不重复全局盘点,不机械新增 Work/Plan/测试。守住单一 writer、exact target、未知发送不重放和不可逆发布授权边界。不要在只有状态检查、计划或解释时结束本轮。',
|
|
243
|
+
...(typeof task.continuationPolicy.scheduled_wake_schedule_id === 'string' ? [
|
|
244
|
+
'SCHEDULED WORK: 本轮仍有同一日的必要步骤时继续实现并以 C ' + supervisorReceiptChallenge(task, effectId) + ' 结束;当日目标已完成且没有剩余安全必要步骤时,使用 WAIT 并以 W ' + supervisorReceiptChallenge(task, effectId) + ' 结束。若存在真实人工阻塞,先记录精确且持久的 UserRequest、停止不安全动作,并在授权可用时通知用户,然后使用 WAIT 保持同一任务开放;不要用 DONE 或 NEEDS_USER 终结每日循环,也不要自行创建新日程。WAIT 让同一任务保持非终结状态,直到绑定的 Scheduler 下次触发。',
|
|
245
|
+
] : []),
|
|
246
|
+
'END OF TURN: 本轮工作实际结束时才简述可核验产出和剩余事项,不要为尽快输出 C 提前终止仍可继续的安全开发。NO_TOOL_RECEIPT 只能写在正文中;工具不可用不等于用户必须介入,临时无工具且仍需下一轮探测时同样以 C ' + supervisorReceiptChallenge(task, effectId) + ' 结束,并写明零工程产出;不能将 C 视为成功或进展。D ' + supervisorReceiptChallenge(task, effectId) + ' 仅用于原目标真实交付;U ' + supervisorReceiptChallenge(task, effectId) + ' 仅用于确需用户决定/授权的阻塞。C/D/U' + (typeof task.continuationPolicy.scheduled_wake_schedule_id === 'string' ? '/W' : '') + ' 校验码必须独占最终助手回复最后一行,不得在中间消息提前输出,不要向 MCP 传 automation_status;Supervisor 只结算已完成的最终助手回复(only the completed final assistant reply)。',
|
|
199
247
|
].join('\n');
|
|
200
248
|
}
|
|
201
249
|
|
package/supervisor/server.ts
CHANGED
|
@@ -347,10 +347,12 @@ async function dispatch(control: WorkflowSupervisorControlPlane, discovery: Work
|
|
|
347
347
|
if (req.method === 'bootstrap_poll') return control.bootstrapPoll(text(p, 'task_id'));
|
|
348
348
|
if (req.method === 'bootstrap_project_url') return { project_url: control.bootstrapProjectUrl(text(p, 'task_id')) };
|
|
349
349
|
if (req.method === 'bootstrap_begin_effect') return { started: control.bootstrapBeginEffect({ taskId: text(p, 'task_id'), effectId: text(p, 'effect_id'), dispatchId: text(p, 'dispatch_id'), dispatchGeneration: positiveInteger(p, 'dispatch_generation') }) };
|
|
350
|
-
if (req.method === 'bootstrap_observe_effect') { const outcome = text(p, 'outcome'); if (!['applied','
|
|
350
|
+
if (req.method === 'bootstrap_observe_effect') { const outcome = text(p, 'outcome'); if (!['applied','unknown'].includes(outcome)) throw new Error('WORKFLOW_SUPERVISOR_RPC_OUTCOME_INVALID'); control.bootstrapObserveEffect({ taskId: text(p, 'task_id'), effectId: text(p, 'effect_id'), observationId: text(p, 'observation_id'), outcome: outcome as 'applied'|'unknown', evidence: object(p.evidence) }); return { recorded: true }; }
|
|
351
351
|
if (req.method === 'browser_begin_effect') return control.browserBeginEffect({ conversationId: text(p, 'conversation_id'), conversationUrl: text(p, 'conversation_url'), effectId: text(p, 'effect_id'), dispatchId: text(p, 'dispatch_id'), dispatchGeneration: positiveInteger(p, 'dispatch_generation'), evidence: object(p.evidence) });
|
|
352
352
|
if (req.method === 'browser_observe_effect') { const outcome = text(p, 'outcome'); if (!['applied','not_applied','unknown'].includes(outcome)) throw new Error('WORKFLOW_SUPERVISOR_RPC_OUTCOME_INVALID'); return control.browserObserveEffect({ conversationId: text(p, 'conversation_id'), conversationUrl: text(p, 'conversation_url'), effectId: text(p, 'effect_id'), observationId: text(p, 'observation_id'), outcome: outcome as 'applied'|'not_applied'|'unknown', evidence: object(p.evidence) }); }
|
|
353
|
-
|
|
353
|
+
// A generic observer cannot attest that a provider dispatch returned before Send.
|
|
354
|
+
// Only the in-process Computer dispatch owner may write a negative proof.
|
|
355
|
+
if (req.method === 'browser_observe_dispatch_failure') throw new Error('WORKFLOW_SUPERVISOR_RPC_DISPATCH_OWNER_ONLY');
|
|
354
356
|
if (req.method === 'browser_observe_provider_turn') return control.browserObserveProviderTurn({ conversationId: text(p, 'conversation_id'), conversationUrl: text(p, 'conversation_url'), generating: p.generating === true, latestAssistantResponse: stringValue(p.latest_assistant_response), providerActivityText: stringValue(p.provider_activity_text), providerFailureCode: chatgptProviderPageFailure(stringValue(p.provider_failure_text)), observedAtMs: safeInteger(p, 'observed_at_ms'), graceMs: positiveInteger(p, 'grace_ms') });
|
|
355
357
|
if (req.method === 'browser_observe_assistant') return control.browserObserveAssistant({ conversationId: text(p, 'conversation_id'), conversationUrl: text(p, 'conversation_url'), responseText: text(p, 'response_text') });
|
|
356
358
|
if (req.method === 'task_register') return control.registerTask({ taskId: text(p, 'task_id'), conversationId: text(p, 'conversation_id'), conversationUrl: text(p, 'conversation_url'), objective: text(p, 'objective'), completionContract: object(p.completion_contract), continuationPolicy: object(p.continuation_policy), userBlockerPolicy: object(p.user_blocker_policy) });
|
|
@@ -359,9 +361,14 @@ async function dispatch(control: WorkflowSupervisorControlPlane, discovery: Work
|
|
|
359
361
|
objective: text(p, 'objective'),
|
|
360
362
|
expectedObjectiveSha256: text(p, 'expected_objective_sha256'),
|
|
361
363
|
requestId: text(p, 'request_id'),
|
|
364
|
+
...(typeof p.work_id === 'string' && p.work_id.trim() ? { workId: p.work_id.trim() } : {}),
|
|
365
|
+
...(typeof p.requirement_id === 'string' && p.requirement_id.trim() ? { requirementId: p.requirement_id.trim() } : {}),
|
|
366
|
+
...(typeof p.expected_completion_contract_sha256 === 'string' && p.expected_completion_contract_sha256.trim() ? { expectedCompletionContractSha256: p.expected_completion_contract_sha256.trim() } : {}),
|
|
362
367
|
...(typeof p.authorized_by === 'string' && p.authorized_by.trim() ? { authorizedBy: p.authorized_by.trim() } : {}),
|
|
363
368
|
});
|
|
364
|
-
if (req.method === 'task_list') return
|
|
369
|
+
if (req.method === 'task_list') return p.terminal_only === true
|
|
370
|
+
? { tasks: [], terminalTasks: control.listTerminalTasks() }
|
|
371
|
+
: { tasks: control.listTasks(p.active_only === true) };
|
|
365
372
|
if (req.method === 'task_stop') return control.stopTask(text(p, 'task_id'), typeof p.reason === 'string' && p.reason.trim() ? p.reason.trim() : 'Stopped by operator request.');
|
|
366
373
|
if (req.method === 'task_recover') return control.recoverTask({
|
|
367
374
|
taskId: text(p, 'task_id'),
|
|
@@ -372,6 +379,12 @@ async function dispatch(control: WorkflowSupervisorControlPlane, discovery: Work
|
|
|
372
379
|
...(typeof p.authorized_by === 'string' && p.authorized_by.trim() ? { authorizedBy: p.authorized_by.trim() } : {}),
|
|
373
380
|
});
|
|
374
381
|
if (req.method === 'task_stall') return control.taskStall(text(p, 'task_id'));
|
|
382
|
+
if (req.method === 'task_bind_scheduled_wake') return control.bindScheduledWake({
|
|
383
|
+
taskId: text(p, 'task_id'), repoId: text(p, 'repo_id'), workId: text(p, 'work_id'), scheduleId: text(p, 'schedule_id'),
|
|
384
|
+
});
|
|
385
|
+
if (req.method === 'task_wake_scheduled') return control.wakeScheduledTask({
|
|
386
|
+
taskId: text(p, 'task_id'), scheduleId: text(p, 'schedule_id'), occurrenceId: text(p, 'occurrence_id'),
|
|
387
|
+
});
|
|
375
388
|
if (req.method === 'task_migrate_conversation') return control.migrateConversation({
|
|
376
389
|
taskId: text(p, 'task_id'),
|
|
377
390
|
expectedConversationId: text(p, 'expected_conversation_id'),
|
|
@@ -386,11 +399,6 @@ async function dispatch(control: WorkflowSupervisorControlPlane, discovery: Work
|
|
|
386
399
|
if (req.method === 'reserve_enrollment') return control.reserveEnrollment(text(p, 'task_id'), typeof p.effect_id === 'string' ? p.effect_id : undefined);
|
|
387
400
|
if (req.method === 'observe_effect') { const outcome = text(p, 'outcome'); if (!['applied','unknown'].includes(outcome)) throw new Error('WORKFLOW_SUPERVISOR_RPC_OUTCOME_INVALID'); control.observeEffect({ effectId: text(p, 'effect_id'), observationId: text(p, 'observation_id'), outcome: outcome as 'applied'|'unknown', evidence: object(p.evidence) }); return { recorded: true }; }
|
|
388
401
|
if (req.method === 'observe_assistant') return control.observeAssistantTurn({ taskId: text(p, 'task_id'), conversationId: text(p, 'conversation_id'), responseText: text(p, 'response_text') });
|
|
389
|
-
if (req.method === 'automation_receipt') {
|
|
390
|
-
const status = text(p, 'automation_status');
|
|
391
|
-
if (!['working', 'continue', 'done', 'needs_user'].includes(status)) throw new Error('WORKFLOW_SUPERVISOR_RPC_AUTOMATION_STATUS_INVALID');
|
|
392
|
-
return control.observeAutomationReceipt({ taskId: text(p, 'task_id'), conversationId: text(p, 'conversation_id'), status: status as import('./types').WorkflowSupervisorAutomationStatus, receiptId: text(p, 'receipt_id') });
|
|
393
|
-
}
|
|
394
402
|
if (req.method === 'task_get') return control.getTask(text(p, 'task_id')) ?? null;
|
|
395
403
|
if (req.method === 'task_get_by_conversation') return control.getTaskByConversationId(text(p, 'conversation_id')) ?? null;
|
|
396
404
|
if (req.method === 'effect_get') return control.getEffect(text(p, 'effect_id')) ?? null;
|