@moretea-labs/forge 1.8.0 → 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 +73 -7
- package/CHANGELOG.md +34 -0
- package/CLAUDE.md +17 -2
- package/CONTRIBUTING.md +3 -2
- 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-host.ts +7 -1
- package/adapters/chatgpt/browser-delivery-runtime.ts +531 -56
- package/adapters/chatgpt/controller-binding-store.ts +101 -22
- package/adapters/chatgpt/controller-round-host.ts +15 -25
- package/adapters/chatgpt/controller-round-settlement-store.ts +58 -4
- package/adapters/chatgpt/provider-delivery.ts +229 -2
- package/adapters/chatgpt/work-conversation-binding-store.ts +99 -54
- package/adapters/computer/chatgpt-extension-target.ts +708 -0
- package/adapters/computer/chrome-extension/background.js +541 -0
- package/adapters/computer/chrome-extension/content.js +402 -0
- package/adapters/computer/chrome-extension/core.js +24 -0
- package/adapters/computer/chrome-extension/manifest.json +32 -0
- package/adapters/computer/desktop-operator-discovery.ts +11 -31
- package/adapters/computer/desktop-operator-provider.ts +18 -6
- package/adapters/computer/interaction-target-authority.ts +178 -24
- package/adapters/mcp/access-mode.ts +18 -39
- package/adapters/mcp/auth.ts +2 -7
- package/adapters/mcp/instructions.ts +6 -5
- package/adapters/mcp/multi-repository.ts +10 -47
- package/adapters/mcp/oauth.ts +73 -0
- package/adapters/mcp/paths.ts +4 -1
- package/adapters/mcp/runtime-gateway/bounded-result-runtime.ts +62 -0
- package/adapters/mcp/runtime-gateway/cognition-settlement.ts +201 -0
- package/adapters/mcp/runtime-gateway/context-adapter.ts +490 -113
- package/adapters/mcp/runtime-gateway/context-pack-sidecar.ts +83 -0
- package/adapters/mcp/runtime-gateway/controller-authority-adapter.ts +20 -5
- package/adapters/mcp/runtime-gateway/core-capability-adapter.ts +258 -0
- package/adapters/mcp/runtime-gateway/engineering-preconditions.ts +10 -27
- package/adapters/mcp/runtime-gateway/engineering-tool-contract.ts +15 -0
- package/adapters/mcp/runtime-gateway/execution-tools.ts +14 -54
- package/adapters/mcp/runtime-gateway/gateway-execution-adapter.ts +2 -1
- package/adapters/mcp/runtime-gateway/plugin-adapter.ts +132 -47
- package/adapters/mcp/runtime-gateway/process-tools.ts +173 -23
- package/adapters/mcp/runtime-gateway/protected-computer-adapter.ts +16 -4
- package/adapters/mcp/runtime-gateway/recovery-adapter.ts +69 -52
- package/adapters/mcp/runtime-gateway/repository-compat-adapter.ts +4 -35
- package/adapters/mcp/runtime-gateway/result-adapter.ts +10 -4
- package/adapters/mcp/runtime-gateway/router.ts +19 -507
- package/adapters/mcp/runtime-gateway/routing-policy.ts +506 -0
- package/adapters/mcp/runtime-gateway/runtime-observation-adapter.ts +15 -66
- package/adapters/mcp/runtime-gateway/runtime-readiness-observation.ts +218 -0
- package/adapters/mcp/runtime-gateway/runtime-tool-definitions.ts +123 -178
- package/adapters/mcp/runtime-gateway/runtime-tools.ts +11 -5
- package/adapters/mcp/runtime-gateway/scheduler-adapter.ts +37 -1
- package/adapters/mcp/runtime-gateway/shared-adapter.ts +20 -0
- package/adapters/mcp/runtime-gateway/status-inbox-adapter.ts +416 -270
- package/adapters/mcp/runtime-gateway/typescript-navigation-sidecar.ts +140 -0
- package/adapters/mcp/runtime-gateway/work-adapter.ts +262 -3123
- package/adapters/mcp/runtime-gateway/work-controller-operations.ts +257 -0
- package/adapters/mcp/runtime-gateway/work-detail-projection.ts +60 -0
- package/adapters/mcp/runtime-gateway/work-input-wire-migration.ts +229 -0
- package/adapters/mcp/runtime-gateway/work-learning-operations.ts +145 -0
- package/adapters/mcp/runtime-gateway/work-list-projection.ts +38 -0
- package/adapters/mcp/runtime-gateway/work-plan-operations.ts +382 -0
- package/adapters/mcp/runtime-gateway/work-repair-adapter.ts +308 -0
- package/adapters/mcp/runtime-gateway/work-requirement-operations.ts +148 -0
- package/adapters/mcp/runtime-gateway/work-semantic-operations.ts +320 -0
- package/adapters/mcp/runtime-gateway/work-workflow-operations.ts +113 -0
- package/adapters/mcp/runtime-gateway/workflow-supervisor-adapter.ts +180 -0
- package/adapters/mcp/server.ts +91 -26
- package/adapters/mcp/setup.ts +5 -13
- package/adapters/mcp/tool-mapping/access-tools.ts +0 -6
- package/adapters/mcp/tool-mapping/legacy-tool-service.ts +703 -3092
- package/adapters/mcp/tool-mapping/post-finalize-work-attribution.ts +5 -10
- package/adapters/mcp/tool-mapping/repository-tools.ts +170 -213
- package/adapters/mcp/toolset-names.ts +11 -37
- package/adapters/mcp/toolset.ts +19 -92
- 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 +377 -0
- package/adapters/mcp/transports/http-post-lifecycle.ts +19 -0
- package/adapters/mcp/transports/http.ts +200 -683
- package/adapters/mcp/transports/oauth-http.ts +322 -0
- package/adapters/mcp/transports/session-registry.ts +6 -0
- package/adapters/mcp/tunnels/openai-secure-tunnel.ts +89 -5
- 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/plugin-registry.v1.json +6 -4
- package/assets/reference-configs/agentic-development-flow.md +26 -1
- package/assets/reference-configs/external-tooling.md +0 -76
- package/assets/reference-configs/global-working-rules.md +19 -0
- 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 +205 -51
- package/docs/architecture/decisions/20260803-release-identity-binding-and-exit-policy.md +14 -5
- package/docs/architecture/decisions/20260823-immediate-controller-relay.md +6 -3
- package/docs/architecture/decisions/20260904-ios-device-migration-baseline.md +42 -0
- package/docs/architecture/decisions/20260907-assistant-learning-loop.md +2 -0
- package/docs/architecture/decisions/20260907-controller-round-transition-policy.md +19 -4
- package/docs/architecture/decisions/20260916-workflow-supervisor-authority.md +249 -0
- package/docs/architecture/decisions/20260917-cognitive-memory-foundation.md +82 -0
- package/docs/architecture/decisions/20260918-stable-candidate-release-lifecycle.md +234 -0
- package/docs/architecture/decisions/20260919-autonomous-work-liveness.md +62 -0
- package/docs/architecture/decisions/20260924-thin-semantic-working-context.md +74 -0
- package/docs/architecture/decisions/20261001-supervisor-turn-authority.md +342 -0
- package/docs/architecture/decisions/20261005-forge-v3-desktop-client-boundary.md +77 -0
- 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 +6 -5
- package/docs/architecture/domains/workflow-engine.md +6 -0
- package/docs/architecture/modules/controller-runtime/transport-lifecycle.md +3 -3
- 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 +16 -4
- package/docs/operations/controller-browser-plugin.md +23 -0
- package/docs/operations/controller-performance-and-502.md +17 -0
- package/docs/operations/controller-reliability-runbook.md +2 -2
- 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 -52
- package/docs/operations/releasing.md +2 -0
- package/docs/operations/runtime-performance-diagnostics.md +8 -0
- package/docs/operations/standalone-disaster-recovery.md +15 -7
- 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 +25 -13
- 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 +25 -25
- package/packages/kernel/cognition/api/index.ts +6 -0
- package/packages/kernel/cognition/application/activation-service.ts +451 -0
- package/packages/kernel/cognition/application/consolidation-service.ts +185 -0
- package/packages/kernel/cognition/application/legacy-experience-adapter.ts +38 -0
- package/packages/kernel/cognition/application/memory-service.ts +64 -0
- package/packages/kernel/cognition/domain/learning.ts +106 -0
- package/packages/kernel/cognition/domain/memory.ts +254 -0
- package/packages/kernel/controller/api/index.ts +1 -0
- package/packages/kernel/controller/application/continuation-service.ts +281 -0
- package/packages/kernel/controller/application/controller-round-service.ts +12 -0
- package/packages/kernel/controller/domain/controller-round-transition-policy.ts +242 -21
- package/packages/kernel/controller/domain/controller-round.ts +4 -1
- package/packages/kernel/controller/domain/execution-quality.ts +3 -1
- package/packages/kernel/controller/infrastructure/controller-round-store.ts +689 -103
- package/packages/kernel/controller/infrastructure/controller-session-store.ts +348 -97
- package/packages/kernel/controller/ports/controller-host.ts +2 -0
- package/packages/kernel/identity/api/index.ts +10 -0
- package/packages/kernel/identity/domain/activity-projection.ts +43 -0
- package/packages/kernel/identity/domain/capability-broker.ts +60 -0
- package/packages/kernel/identity/domain/grant.ts +72 -0
- package/packages/kernel/identity/domain/owned-resource.ts +116 -0
- package/packages/kernel/identity/domain/user-request.ts +93 -0
- package/packages/kernel/identity/infrastructure/activity-projection-store.ts +87 -0
- package/packages/kernel/identity/infrastructure/capability-broker.ts +81 -0
- package/packages/kernel/identity/infrastructure/grant-store.ts +284 -0
- package/packages/kernel/identity/infrastructure/owned-resource-store.ts +259 -0
- package/packages/kernel/identity/infrastructure/user-request-store.ts +182 -0
- package/packages/kernel/scheduler/api/index.ts +0 -2
- package/packages/kernel/scheduler/application/eligibility.ts +4 -1
- package/packages/kernel/scheduler/application/schedule-service.ts +3 -0
- package/packages/kernel/scheduler/application/settlement.ts +0 -15
- package/packages/kernel/scheduler/domain/schedule.ts +87 -0
- package/packages/kernel/scheduler/infrastructure/schedule-store.ts +166 -143
- package/packages/kernel/work/api/index.ts +3 -2
- package/packages/kernel/work/application/work-service.ts +18 -42
- package/packages/kernel/work/domain/current-task-lineage.ts +104 -0
- package/packages/kernel/work/domain/engineering-design.ts +10 -5
- package/packages/kernel/work/domain/engineering-profile.ts +8 -12
- package/packages/kernel/work/domain/evaluation-promotion-receipt.ts +186 -0
- package/packages/kernel/work/domain/execution-concurrency.ts +19 -26
- package/packages/kernel/work/domain/execution-snapshot.ts +0 -31
- package/packages/kernel/work/domain/implementation-review.ts +14 -331
- package/packages/kernel/work/domain/objective-graph.ts +119 -0
- package/packages/kernel/work/domain/project-engineering-contract.ts +23 -1
- package/packages/kernel/work/domain/repository-completion-receipt.ts +1 -1
- package/packages/kernel/work/domain/state-machine.ts +34 -65
- package/packages/kernel/work/domain/types.ts +57 -51
- package/packages/kernel/work/infrastructure/work-contract-store.ts +847 -729
- package/packages/kernel/work/ports/work-contract-store.ts +5 -2
- package/packages/plugin-runtime/browser/provider-registry.ts +12 -36
- package/packages/plugin-runtime/browser/session-authority.ts +2 -1
- package/packages/plugin-runtime/computer/chatgpt-identity.ts +24 -0
- package/packages/plugin-runtime/computer/conversation-target.ts +153 -0
- package/packages/plugin-runtime/computer/index.ts +2 -0
- package/packages/plugin-runtime/computer/target-authority.ts +26 -1
- package/packages/plugin-runtime/external/unix-jsonl-transport.ts +142 -18
- package/packages/protocols/computer/contract.ts +27 -1
- package/scripts/activate-source-baseline.ts +7 -9
- package/scripts/assemble-template.ts +11 -72
- package/scripts/canary-controller-semantic-wait.ts +12 -24
- package/scripts/check-mcp-compatibility.ts +94 -201
- package/scripts/check-package-identity.mjs +0 -5
- package/scripts/check-runtime-architecture.mjs +921 -239
- package/scripts/forge-local-recovery-helper.mjs +93 -15
- 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 +6 -3
- package/scripts/migrate-windows-wsl-controller-home.ts +2 -0
- package/scripts/open-source-audit-allowlist.txt +1 -3
- package/scripts/run-bounded-command.mjs +5 -0
- package/scripts/run-governed-gate.ts +2 -1
- package/scripts/run-mobile-monitor-bridge.ts +0 -1
- package/scripts/smoke-control-plane-failure-domain.ts +94 -0
- package/scripts/smoke-ios-physical-device.ts +38 -10
- package/scripts/smoke-mcp-http-runtime.ts +12 -8
- package/scripts/smoke-mcp-tool-surface.ts +27 -41
- package/scripts/smoke-runtime-recovery.ts +12 -43
- package/scripts/smoke-schedule-engine.ts +23 -15
- package/scripts/smoke-unattended-transport-recovery.ts +223 -0
- package/scripts/smoke-user-request-continuation-restart.ts +232 -0
- package/scripts/smoke-workflow-supervisor-chrome-adapter.ts +95 -0
- package/scripts/smoke-workflow-supervisor-process-restart.ts +276 -0
- package/scripts/smoke-workflow-supervisor-restart-recovery.ts +150 -0
- package/scripts/smoke-workflow-supervisor.ts +103 -0
- package/scripts/sync-generated-authority.mjs +0 -1
- package/scripts/verify-forge-runtime.sh +2 -1
- package/src/cli/agent-jobs/executor-health.ts +12 -35
- package/src/cli/agent-jobs/integration.ts +20 -51
- package/src/cli/agent-jobs/job-manager.ts +7 -3
- package/src/cli/chatgpt-browser/file-policy.ts +2 -2
- package/src/cli/commands/brain-assistant.ts +27 -13
- package/src/cli/commands/brain.ts +13 -15
- package/src/cli/commands/chatgpt.ts +1 -163
- 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 +137 -135
- package/src/cli/commands/repository.ts +17 -1
- package/src/cli/commands/runtime.ts +3 -3
- package/src/cli/commands/setup-execution.ts +41 -0
- package/src/cli/commands/setup-profile.ts +8 -0
- package/src/cli/controller/check-runner.ts +13 -2
- package/src/cli/controller/completion-backlog.ts +3 -3
- package/src/cli/controller/completion-orchestrator.ts +5 -44
- package/src/cli/controller/completion-target.ts +3 -72
- 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 +83 -102
- 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 +107 -84
- package/src/cli/controller/execution-completion.ts +4 -7
- package/src/cli/controller/execution-policy.ts +36 -153
- package/src/cli/controller/governance.ts +2 -3
- package/src/cli/controller/issue-store.ts +4 -99
- package/src/cli/controller/launch-agents.ts +59 -18
- package/src/cli/controller/operational-plan.ts +25 -52
- package/src/cli/controller/runtime-config.ts +5 -1
- package/src/cli/controller/stuck-state-migration.ts +2 -3
- package/src/cli/controller/systemd-user.ts +42 -10
- package/src/cli/editing/edit-session.ts +18 -12
- 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 +19 -14
- package/src/cli/local-bridge/console-view-models.ts +4 -13
- package/src/cli/local-bridge/facade-api.ts +64 -193
- package/src/cli/local-bridge/server.ts +24 -147
- package/src/cli/local-bridge/types.ts +0 -1
- package/src/cli/mcp/oauth-client-retirement.ts +74 -0
- package/src/cli/repositories/command-classifier.ts +0 -9
- package/src/cli/repositories/command-executor.ts +29 -23
- package/src/cli/repositories/command-scope.ts +37 -18
- package/src/cli/repositories/controller-home.ts +48 -0
- package/src/cli/repositories/ephemeral-workspace.ts +20 -30
- package/src/cli/repositories/git-command-executor.ts +2 -2
- package/src/cli/repositories/locks.ts +20 -0
- package/src/cli/repositories/registry.ts +79 -12
- package/src/cli/repositories/safe-patch.ts +2 -12
- package/src/cli/repositories/structured-git.ts +101 -5
- package/src/cli/repository/inspector.ts +185 -343
- package/src/cli/repository/session-cache.ts +92 -6
- package/src/effects/process-runner.ts +17 -1
- package/src/runtime/context/assistant-context.ts +20 -7
- package/src/runtime/context/assistant-work-context.ts +89 -27
- package/src/runtime/context/automatic-learning.ts +565 -0
- package/src/runtime/context/cognitive-attention.ts +173 -0
- package/src/runtime/context/cognitive-skill-canary.ts +158 -0
- package/src/runtime/context/context-closure.ts +46 -9
- package/src/runtime/context/context-pack-process.ts +103 -0
- package/src/runtime/context/context-plane.ts +1 -9
- package/src/runtime/context/direct-controller-learning.ts +298 -0
- package/src/runtime/context/generic-lsp-provider.ts +1 -1
- package/src/runtime/context/semantic-navigation-contract.ts +16 -0
- package/src/runtime/context/semantic-navigation.ts +7 -35
- package/src/runtime/context/typescript-navigation-process.ts +145 -0
- package/src/runtime/context/typescript-navigation.ts +89 -3
- package/src/runtime/control-plane/cleanup-artifact-retention.ts +215 -12
- package/src/runtime/control-plane/concurrency/work-execution-concurrency.ts +9 -47
- package/src/runtime/control-plane/execution/controller-authority-recovery.ts +34 -4
- package/src/runtime/control-plane/execution/edit-validation-coordinator.ts +29 -20
- package/src/runtime/control-plane/execution/execution-identity.ts +23 -3
- package/src/runtime/control-plane/execution/repository-work-attribution.ts +7 -30
- package/src/runtime/control-plane/execution/retained-work-resume.ts +206 -199
- package/src/runtime/control-plane/execution/session-store.ts +31 -1
- package/src/runtime/control-plane/execution/validation.ts +6 -8
- package/src/runtime/control-plane/execution/work-authority-reconciler.ts +13 -42
- package/src/runtime/control-plane/execution/work-check-evidence.ts +137 -0
- package/src/runtime/control-plane/execution/work-completion-authority.ts +30 -85
- package/src/runtime/control-plane/execution/work-delivery-service.ts +616 -0
- package/src/runtime/control-plane/execution/work-evidence-policy.ts +12 -50
- package/src/runtime/control-plane/execution/work-execution-support.ts +50 -149
- package/src/runtime/control-plane/execution/work-handle-authority.ts +197 -110
- package/src/runtime/control-plane/execution/work-handle-store.ts +72 -44
- package/src/runtime/control-plane/execution/work-head-settlement.ts +53 -20
- package/src/runtime/control-plane/execution/work-lifecycle-audit.ts +52 -29
- package/src/runtime/control-plane/execution/work-operation-service.ts +60 -34
- package/src/runtime/control-plane/execution/work-preparation-service.ts +231 -267
- package/src/runtime/control-plane/execution/work-process-evidence.ts +2 -2
- package/src/runtime/control-plane/execution/work-remote-delivery.ts +2 -3
- package/src/runtime/control-plane/execution/work-revision-diff.ts +39 -0
- package/src/runtime/control-plane/execution/work-terminal-cleanup.ts +201 -199
- package/src/runtime/control-plane/execution/work-validation-reconciler.ts +33 -85
- package/src/runtime/control-plane/execution/work-verification-service.ts +406 -50
- package/src/runtime/control-plane/execution/work-verification-snapshot.ts +6 -2
- package/src/runtime/control-plane/facade/capability-registry.ts +364 -37
- package/src/runtime/control-plane/facade/check-normalization.ts +3 -9
- package/src/runtime/control-plane/facade/codex-delegation.ts +10 -11
- package/src/runtime/control-plane/facade/controller-connection.ts +135 -0
- package/src/runtime/control-plane/facade/goal-workloop-access.ts +1 -20
- package/src/runtime/control-plane/facade/goal-workloop.ts +281 -1753
- package/src/runtime/control-plane/facade/handoff-inbox-application.ts +12 -25
- package/src/runtime/control-plane/facade/handoff-inbox-store.ts +256 -52
- package/src/runtime/control-plane/facade/index.ts +0 -1
- package/src/runtime/control-plane/facade/operation-digest.ts +12 -15
- package/src/runtime/control-plane/facade/plan-contract-store.ts +451 -991
- package/src/runtime/control-plane/facade/policy-gate.ts +0 -23
- package/src/runtime/control-plane/facade/repository-work-admission.ts +12 -22
- package/src/runtime/control-plane/facade/requirement-authority.ts +102 -199
- package/src/runtime/control-plane/facade/requirement-board.ts +3 -3
- package/src/runtime/control-plane/facade/rh-work-operation-contract.ts +51 -14
- package/src/runtime/control-plane/facade/self-healing-loop.ts +18 -53
- package/src/runtime/control-plane/facade/suggested-actions.ts +15 -18
- package/src/runtime/control-plane/facade/types.ts +49 -108
- package/src/runtime/control-plane/facade/work-continuation.ts +9 -9
- package/src/runtime/control-plane/generated-cache-retention.ts +206 -59
- package/src/runtime/control-plane/global-scheduler/autonomous-continuation.ts +248 -0
- package/src/runtime/control-plane/global-scheduler/durable-admission.ts +1 -1
- package/src/runtime/control-plane/global-scheduler/maintenance.ts +256 -117
- package/src/runtime/control-plane/global-scheduler/reconciliation.ts +3 -12
- package/src/runtime/control-plane/global-scheduler/scheduler.ts +66 -40
- package/src/runtime/control-plane/global-scheduler/wake-signal.ts +42 -2
- package/src/runtime/control-plane/governance/access-policy.ts +19 -2
- package/src/runtime/control-plane/governance/authorization.ts +20 -3
- package/src/runtime/control-plane/governance/external-effects.ts +1 -1
- package/src/runtime/control-plane/launcher/chatgpt-round-continuation.ts +63 -300
- package/src/runtime/control-plane/launcher/chatgpt-work-continuation.ts +29 -300
- package/src/runtime/control-plane/launcher/local-conversation-controller.ts +238 -0
- package/src/runtime/control-plane/launcher/provider-mcp-bootstrap.ts +5 -2
- package/src/runtime/control-plane/launcher/thin-launcher.ts +96 -240
- package/src/runtime/control-plane/persistence/cognition-store.ts +820 -0
- package/src/runtime/control-plane/persistence/experience-store.ts +162 -29
- package/src/runtime/control-plane/persistence/requirement-store.ts +216 -74
- package/src/runtime/control-plane/persistence/sqlite-store.ts +113 -6
- package/src/runtime/control-plane/release-retention.ts +135 -47
- package/src/runtime/control-plane/repository-namespace-retention.ts +2 -2
- package/src/runtime/control-plane/runtime-cleanup.ts +295 -107
- package/src/runtime/control-plane/workspace/project-onboarding.ts +80 -0
- package/src/runtime/control-plane/workspace/semantic-sync-service.ts +19 -5
- package/src/runtime/control-plane/workspace/workspace-store.ts +169 -0
- package/src/runtime/diagnostics/incident-repair.ts +313 -146
- package/src/runtime/diagnostics/mcp-timing.ts +114 -0
- package/src/runtime/evidence/artifact-store.ts +158 -40
- package/src/runtime/evidence/evidence-store.ts +112 -8
- package/src/runtime/evidence/output-handle-index.ts +225 -0
- package/src/runtime/evidence/result-store.ts +158 -44
- 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/jobs/store.ts +3 -4
- package/src/runtime/execution/managed-workspace.ts +57 -0
- package/src/runtime/execution/process-runtime/check-facade.ts +1 -1
- package/src/runtime/execution/process-runtime/check-result-retention.ts +2 -2
- package/src/runtime/execution/process-runtime/check-result.ts +105 -1
- package/src/runtime/execution/process-runtime/check-runner-sidecar.ts +18 -8
- package/src/runtime/execution/process-runtime/command-facade.ts +82 -30
- package/src/runtime/execution/process-runtime/gc.ts +15 -2
- package/src/runtime/execution/process-runtime/handle-index.ts +176 -0
- package/src/runtime/execution/process-runtime/host-command-lane.ts +139 -0
- package/src/runtime/execution/process-runtime/index.ts +3 -0
- package/src/runtime/execution/process-runtime/lightweight-managed.ts +251 -72
- package/src/runtime/execution/process-runtime/persisted-check.ts +3 -3
- package/src/runtime/execution/process-runtime/process-runner-entry.ts +47 -5
- package/src/runtime/execution/process-runtime/process-scope.ts +160 -0
- package/src/runtime/execution/process-runtime/resource-claims.ts +65 -61
- package/src/runtime/execution/process-runtime/runtime.ts +55 -18
- package/src/runtime/execution/process-runtime/store.ts +30 -2
- package/src/runtime/execution/process-runtime/types.ts +6 -1
- 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 +3 -8
- package/src/runtime/maintenance/cleanup.ts +41 -5
- package/src/runtime/platform/service-inventory.ts +130 -0
- package/src/runtime/platform/service-manager.ts +8 -0
- package/src/runtime/plugins/action-application.ts +97 -29
- package/src/runtime/plugins/app-store-connect-adapter.ts +290 -18
- package/src/runtime/plugins/browser-adapter.ts +1124 -333
- package/src/runtime/plugins/browser-automation-service.ts +23 -3
- package/src/runtime/plugins/browser-macos-bridge.ts +431 -137
- package/src/runtime/plugins/browser-manifest-surface.ts +47 -12
- package/src/runtime/plugins/browser-native-session-service.ts +63 -13
- package/src/runtime/plugins/browser-registration.ts +18 -0
- package/src/runtime/plugins/browser-runtime.ts +40 -36
- package/src/runtime/plugins/browser-session-authority.ts +2 -2
- package/src/runtime/plugins/browser-session-store.ts +46 -76
- package/src/runtime/plugins/capability-authorization-grants.ts +258 -62
- package/src/runtime/plugins/computer-chatgpt-browser-adapter-installer.ts +228 -0
- package/src/runtime/plugins/computer-registration.ts +298 -20
- package/src/runtime/plugins/desktop-operator-external-policy.ts +36 -4
- package/src/runtime/plugins/desktop-operator-registration.ts +12 -4
- package/src/runtime/plugins/external-adapter.ts +42 -6
- package/src/runtime/plugins/external-registration.ts +21 -1
- package/src/runtime/plugins/github-adapter.ts +30 -3
- package/src/runtime/plugins/gmail-adapter.ts +189 -3
- package/src/runtime/plugins/google-calendar-adapter.ts +2 -2
- package/src/runtime/plugins/google-shared.ts +24 -12
- package/src/runtime/plugins/google-tasks-adapter.ts +2 -2
- package/src/runtime/plugins/ios/remote-xpc-hid.ts +70 -30
- package/src/runtime/plugins/ios-adapter.ts +46 -41
- 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/lightweight-action.ts +208 -2
- package/src/runtime/plugins/local-system-adapter.ts +12 -100
- package/src/runtime/plugins/managed-process-adapter.ts +12 -5
- package/src/runtime/plugins/plugin-action-sidecar.ts +17 -13
- package/src/runtime/plugins/plugin-management-adapter.ts +1 -1
- package/src/runtime/plugins/store.ts +682 -435
- package/src/runtime/plugins/types.ts +24 -0
- package/src/runtime/plugins/xiaohongshu-publish.ts +16 -0
- package/src/runtime/projections/git-status-sampler.ts +2 -19
- package/src/runtime/projections/invalidation.ts +7 -3
- package/src/runtime/projections/materialized-view.ts +80 -36
- package/src/runtime/recovery/actions.ts +4 -4
- package/src/runtime/recovery/capability-action-application.ts +46 -45
- package/src/runtime/recovery/lifecycle-inventory.ts +30 -40
- package/src/runtime/recovery/maintenance-executor.ts +374 -123
- package/src/runtime/recovery/probe.ts +2 -2
- package/src/runtime/recovery/store.ts +29 -11
- package/src/runtime/release/release-coordinator.ts +312 -0
- package/src/runtime/release/release-session.ts +716 -0
- package/src/runtime/release/release-state-migration.ts +25 -0
- package/src/runtime/resources/leases/store.ts +56 -25
- package/src/runtime/root/computer-composition.ts +191 -6
- package/src/runtime/root/controller-progression-composition.ts +254 -0
- package/src/runtime/root/controller-round-composition.ts +20 -1
- package/src/runtime/root/deployment-topology.ts +106 -0
- package/src/runtime/root/entry.ts +4 -3
- package/src/runtime/root/known-good-recovery.ts +184 -0
- package/src/runtime/root/local-bridge.ts +0 -1
- package/src/runtime/root/mcp-transport.ts +111 -18
- package/src/runtime/root/ownership.ts +261 -9
- package/src/runtime/root/package-connector-service.ts +227 -29
- package/src/runtime/root/package-runtime-release.ts +117 -30
- package/src/runtime/root/package-runtime-service.ts +24 -24
- package/src/runtime/root/release-execution-canary.ts +57 -12
- package/src/runtime/root/release-loader.ts +90 -8
- package/src/runtime/root/release-manifest.ts +80 -40
- package/src/runtime/root/release-materialize.ts +372 -106
- package/src/runtime/root/release-store.ts +395 -36
- package/src/runtime/root/runtime-lane.ts +191 -0
- package/src/runtime/root/runtime.ts +160 -29
- package/src/runtime/root/scheduled-controller-composition.ts +29 -3
- package/src/runtime/root/service-runner.ts +2 -2
- package/src/runtime/root/service.ts +126 -44
- package/src/runtime/root/status.ts +48 -0
- package/src/runtime/root/types.ts +32 -9
- package/src/runtime/root/workflow-supervisor-composition.ts +681 -0
- package/src/runtime/root/workflow-supervisor-runtime.ts +564 -0
- package/src/runtime/root/write-fence.ts +50 -2
- package/src/runtime/safe-tooling/google-credential-store.ts +67 -22
- package/src/runtime/safe-tooling/google-oauth-broker.ts +25 -7
- 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 +5 -2
- package/src/runtime/shared/atomic-text-file.ts +21 -0
- package/src/runtime/shared/bounded-child-supervisor.ts +9 -1
- package/src/runtime/shared/json-files.ts +8 -3
- package/src/runtime/shared/process-environment.ts +20 -9
- package/src/runtime/shared/response-budget.ts +1 -3
- package/src/runtime/standalone-recovery/controller-home-migration.ts +16 -24
- package/src/runtime/standalone-recovery/core.ts +3792 -417
- package/src/runtime/standalone-recovery/entry.ts +507 -45
- package/src/runtime/standalone-recovery/installer.ts +262 -148
- package/src/runtime/standalone-recovery/mcp-server.ts +29 -193
- package/src/runtime/standalone-recovery/operation-lock.ts +12 -2
- package/src/runtime/standalone-recovery/performance.ts +54 -16
- package/src/runtime/standalone-recovery/release.ts +53 -5
- package/src/runtime/standalone-recovery/service-labels.ts +5 -2
- package/src/runtime/standalone-recovery/watchdog-heartbeat.ts +5 -2
- package/src/runtime/workflow/schedules/browser-probe.ts +17 -6
- package/src/runtime/workflow/schedules/chatgpt-automation-migration.ts +11 -3
- package/src/runtime/workflow/schedules/engine.ts +166 -178
- package/src/runtime/workflow/schedules/pending-activation.ts +11 -4
- package/src/runtime/workflow/schedules/work-continuation.ts +95 -11
- package/src/runtime/workflows/runtime.ts +15 -19
- package/src/testing/test-governance.ts +5 -1
- package/supervisor/chatgpt-conversation.ts +23 -0
- package/supervisor/client.ts +218 -0
- package/supervisor/control-plane.ts +963 -0
- package/supervisor/entry.ts +15 -0
- package/supervisor/forge-validators.ts +147 -0
- package/supervisor/index.ts +5 -0
- package/supervisor/native-browser-adapter.ts +1151 -0
- package/supervisor/native-messaging/host.ts +58 -0
- package/supervisor/native-messaging/manifest.ts +26 -0
- package/supervisor/native-messaging/protocol.ts +27 -0
- package/supervisor/paths.ts +18 -0
- package/supervisor/protocol.ts +250 -0
- package/supervisor/server.ts +412 -0
- package/supervisor/store.ts +1870 -0
- package/supervisor/tsconfig.json +8 -0
- package/supervisor/types.ts +261 -0
- package/SKILL.md +0 -427
- package/adapters/chatgpt/controller-host.ts +0 -119
- package/adapters/mcp/controller-round-compatibility.ts +0 -184
- package/adapters/mcp/frozen-client-semantic-compatibility.ts +0 -292
- package/adapters/mcp/runtime-gateway/work-compat-adapter.ts +0 -502
- 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/packages/kernel/progression/api/index.ts +0 -2
- package/packages/kernel/progression/application/projector.ts +0 -211
- package/packages/kernel/progression/domain/types.ts +0 -116
- package/packages/kernel/progression/index.ts +0 -1
- package/packages/kernel/scheduler/application/continuation-service.ts +0 -212
- package/packages/kernel/scheduler/domain/continuation.ts +0 -38
- package/packages/kernel/scheduler/infrastructure/continuation-dispatch-store.ts +0 -38
- package/packages/kernel/work/domain/admission-policy.ts +0 -34
- package/scripts/benchmark-background-check-overlap.ts +0 -228
- package/scripts/benchmark-computer-hotpath.ts +0 -255
- package/scripts/benchmark-controller-hotpath.ts +0 -212
- package/scripts/benchmark-controller-round2.ts +0 -191
- package/scripts/benchmark-ios-agent-device.ts +0 -511
- package/scripts/benchmark-mcp-host.sh +0 -117
- package/scripts/benchmark-mcp-transport.ts +0 -169
- package/scripts/benchmark-operational-memory-activation.ts +0 -235
- package/scripts/benchmark-operational-shadow.ts +0 -28
- package/scripts/benchmark-quality-harness.ts +0 -146
- package/scripts/benchmark-route-session-concurrency.ts +0 -915
- package/scripts/benchmark-thin-harness-gateway-ab.ts +0 -632
- package/scripts/benchmark-thin-harness-mcp-e2e.ts +0 -498
- package/scripts/benchmark-thin-harness.ts +0 -251
- package/scripts/benchmark-typescript-navigation.ts +0 -186
- package/scripts/benchmark-work-efficiency.ts +0 -334
- package/scripts/build-controller-ui.ts +0 -28
- package/scripts/check-npm-release.sh +0 -32
- package/scripts/check-public-release-surface.sh +0 -19
- package/scripts/check-release-published.sh +0 -57
- package/scripts/check-release-readiness.sh +0 -37
- package/scripts/check-release-version.mjs +0 -74
- package/scripts/check-skill-version.ts +0 -5
- package/scripts/check-tarball-install-smoke.sh +0 -150
- package/scripts/ensure-codegraph.sh +0 -16
- package/scripts/package-source-archive.sh +0 -147
- package/scripts/public-release-files.txt +0 -39
- package/scripts/public-release.ts +0 -174
- package/scripts/publish-release-tarball.sh +0 -27
- package/scripts/route-nl-vs-ts-eval.ts +0 -679
- package/scripts/run-skill-hook.ts +0 -244
- package/scripts/stage-runtime-release.ts +0 -44
- package/scripts/sync-codex-installed-copies.sh +0 -182
- package/src/cli/commands/tools.ts +0 -167
- package/src/cli/controller/progress.ts +0 -656
- package/src/cli/controller/work-mode.ts +0 -181
- package/src/cli/local-bridge/console-assets.ts +0 -17
- package/src/cli/local-bridge/dashboard.ts +0 -17
- package/src/cli/local-bridge/frontend/src/App.tsx +0 -10
- package/src/cli/local-bridge/frontend/src/components/Button.tsx +0 -1
- package/src/cli/local-bridge/frontend/src/components/DetailPane.tsx +0 -3
- package/src/cli/local-bridge/frontend/src/components/SearchField.tsx +0 -1
- package/src/cli/local-bridge/frontend/src/components/SectionHeader.tsx +0 -1
- package/src/cli/local-bridge/frontend/src/components/Segmented.tsx +0 -1
- package/src/cli/local-bridge/frontend/src/components/StatusText.tsx +0 -3
- package/src/cli/local-bridge/frontend/src/design/icons.tsx +0 -11
- package/src/cli/local-bridge/frontend/src/design/tokens.css +0 -8
- package/src/cli/local-bridge/frontend/src/features/automations/AutomationsView.tsx +0 -153
- package/src/cli/local-bridge/frontend/src/features/capabilities/CapabilitiesView.tsx +0 -37
- package/src/cli/local-bridge/frontend/src/features/overview/OverviewView.tsx +0 -183
- package/src/cli/local-bridge/frontend/src/features/repositories/RepositoriesView.tsx +0 -2
- package/src/cli/local-bridge/frontend/src/features/system/SystemView.tsx +0 -2
- package/src/cli/local-bridge/frontend/src/features/work/WorkView.tsx +0 -4
- package/src/cli/local-bridge/frontend/src/lib/api.ts +0 -30
- package/src/cli/local-bridge/frontend/src/lib/format.ts +0 -4
- package/src/cli/local-bridge/frontend/src/lib/routes.ts +0 -7
- package/src/cli/local-bridge/frontend/src/main.tsx +0 -1
- package/src/cli/local-bridge/frontend/src/shell/AppShell.tsx +0 -1
- package/src/cli/local-bridge/frontend/src/shell/CommandBar.tsx +0 -2
- package/src/cli/local-bridge/frontend/src/shell/Sidebar.tsx +0 -4
- package/src/cli/local-bridge/frontend/src/styles.css +0 -28
- package/src/cli/local-bridge/frontend/src/types.ts +0 -15
- package/src/cli/local-bridge/frontend/src/vite-env.d.ts +0 -1
- package/src/cli/local-bridge/frontend/vite.config.ts +0 -27
- package/src/cli/local-bridge/ui-dist/app.css +0 -1
- package/src/cli/local-bridge/ui-dist/app.js +0 -11228
- 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/control-plane/execution/content-equivalent-commit-authority.ts +0 -169
- package/src/runtime/control-plane/execution/direct-canonical-work-reconciliation.ts +0 -85
- package/src/runtime/control-plane/execution/direct-edit-work-completion.ts +0 -655
- package/src/runtime/control-plane/execution/work-finalization-service.ts +0 -2850
- package/src/runtime/control-plane/execution/work-path-scope.ts +0 -37
- package/src/runtime/control-plane/execution/work-task-receipt.ts +0 -468
- package/src/runtime/control-plane/facade/controller-round-relay.ts +0 -3
- package/src/runtime/control-plane/facade/work-admission-policy.ts +0 -142
- package/src/runtime/control-plane/facade/work-implementation-review.ts +0 -2
- package/src/runtime/control-plane/facade/work-state-machine.ts +0 -2
- package/src/runtime/control-plane/facade/work-task-projection.ts +0 -66
- package/src/runtime/control-plane/routing/index.ts +0 -1
- package/src/runtime/control-plane/routing/route-policy.ts +0 -401
- package/src/runtime/control-plane/routing/workspace-admission.ts +0 -70
- 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
|
@@ -0,0 +1,681 @@
|
|
|
1
|
+
import { existsSync } from 'node:fs';
|
|
2
|
+
import { createHash } from 'node:crypto';
|
|
3
|
+
import { getRepository } from '../../cli/repositories/registry';
|
|
4
|
+
import { getWorkContract, semanticWorkState } from '../../../packages/kernel/work/api/index';
|
|
5
|
+
import {
|
|
6
|
+
controllerRoundBlockerClass,
|
|
7
|
+
controllerRoundProviderEffectId,
|
|
8
|
+
finishControllerRoundRelayDispatch,
|
|
9
|
+
getControllerRoundRelay,
|
|
10
|
+
getRequirementControllerRoundRelay,
|
|
11
|
+
} from '../../../packages/kernel/controller/api/index';
|
|
12
|
+
import {
|
|
13
|
+
bindChatgptWorkConversation,
|
|
14
|
+
getChatgptWorkConversationBinding,
|
|
15
|
+
listChatgptWorkBindingsForConversation,
|
|
16
|
+
rebindChatgptWorkConversation,
|
|
17
|
+
type ChatgptWorkConversationBinding,
|
|
18
|
+
} from '../../../adapters/chatgpt/work-conversation-binding-store';
|
|
19
|
+
import { readRequirement } from '../control-plane/persistence/requirement-store';
|
|
20
|
+
import { bindWorkflowSupervisorScheduledWake, getWorkflowSupervisorCurrentConversation, getWorkflowSupervisorTask, getWorkflowSupervisorTaskByConversationId, getWorkflowSupervisorTaskStall, registerWorkflowSupervisorTask, reserveWorkflowSupervisorEnrollment, wakeWorkflowSupervisorScheduledTask } from '../../../supervisor/client';
|
|
21
|
+
import { resolveWorkflowSupervisorForgeHome, workflowSupervisorSocketPath } from '../../../supervisor/paths';
|
|
22
|
+
import type { WorkflowSupervisorLifecycleHooks, WorkflowSupervisorTask } from '../../../supervisor/types';
|
|
23
|
+
import { getRuntimeWriteClaim } from './write-fence';
|
|
24
|
+
import { renderCognitiveAttentionForWork } from '../context/cognitive-attention';
|
|
25
|
+
|
|
26
|
+
export type WorkflowSupervisorBoundary =
|
|
27
|
+
| { status: 'not_eligible' }
|
|
28
|
+
| { status: 'conversation_pending'; reason: 'EXACT_WORK_CONVERSATION_BINDING_REQUIRED' }
|
|
29
|
+
| { status: 'outer_turn'; workId?: string; requirementId?: string; conversationId: string; conversationUrl: string };
|
|
30
|
+
|
|
31
|
+
export type WorkflowSupervisorEnrollmentStatus =
|
|
32
|
+
| 'not_eligible'
|
|
33
|
+
| 'conversation_pending'
|
|
34
|
+
| 'current_conversation_unbound'
|
|
35
|
+
| 'daemon_unavailable'
|
|
36
|
+
| 'enrolled'
|
|
37
|
+
| 'lower_layer_not_ready';
|
|
38
|
+
|
|
39
|
+
export function workflowSupervisorLowerLayerReadyForWork(
|
|
40
|
+
options: { controllerHome: string; repoId: string },
|
|
41
|
+
workId: string,
|
|
42
|
+
): { ready: true; workId: string; providerEffectId: string } | { ready: false; reason: string } {
|
|
43
|
+
const directRelay = getControllerRoundRelay(options, workId);
|
|
44
|
+
const work = getWorkContract(options, workId);
|
|
45
|
+
const relay = directRelay ?? (work?.requirementId ? getRequirementControllerRoundRelay(options, work.requirementId) : undefined);
|
|
46
|
+
if (!relay) return { ready: false, reason: 'CONTROLLER_ROUND_NOT_PREPARED' };
|
|
47
|
+
if (!relay.authorityId?.trim()) return { ready: false, reason: `CONTROLLER_ROUND_AUTHORITY_REQUIRED:${relay.originWorkId}` };
|
|
48
|
+
const outcomeUnknownEffectAwaitingObservation = relay.status === 'blocked'
|
|
49
|
+
&& controllerRoundBlockerClass(relay) === 'provider_dispatch_outcome_unknown'
|
|
50
|
+
&& (relay.providerDispatchAttempt ?? 0) > 0
|
|
51
|
+
&& Boolean(relay.providerDispatchEffectId?.trim());
|
|
52
|
+
if (!['dispatching', 'dispatched', 'claimed'].includes(relay.status) && !outcomeUnknownEffectAwaitingObservation) {
|
|
53
|
+
return { ready: false, reason: `CONTROLLER_ROUND_NOT_DISPATCHABLE:${relay.status}:${relay.blockedReason ?? relay.originWorkId}` };
|
|
54
|
+
}
|
|
55
|
+
return {
|
|
56
|
+
ready: true,
|
|
57
|
+
workId: relay.originWorkId,
|
|
58
|
+
providerEffectId: relay.providerDispatchEffectId ?? controllerRoundProviderEffectId(relay),
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function taskIdForWork(repoId: string, workId: string): string {
|
|
63
|
+
return `forge:${repoId}:work:${workId}`;
|
|
64
|
+
}
|
|
65
|
+
export function getWorkflowSupervisorConversationBindingForWork(
|
|
66
|
+
options: { controllerHome: string; repoId: string },
|
|
67
|
+
workId: string,
|
|
68
|
+
): ChatgptWorkConversationBinding | undefined {
|
|
69
|
+
return getChatgptWorkConversationBinding(options, workId);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export function bindWorkflowSupervisorConversationForWork(
|
|
73
|
+
options: { controllerHome: string; repoId: string },
|
|
74
|
+
input: { workId: string; conversationUrl: string; localAlias?: string },
|
|
75
|
+
): ChatgptWorkConversationBinding {
|
|
76
|
+
return bindChatgptWorkConversation(options, input);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* The boundary is derived from canonical lower-layer facts, never copied into
|
|
81
|
+
* Scheduler or ControllerRound state. Once one Requirement-backed Work has an
|
|
82
|
+
* exact ChatGPT conversation, lower layers may prepare/claim ControllerRounds
|
|
83
|
+
* but may no longer submit the next outer assistant turn.
|
|
84
|
+
*/
|
|
85
|
+
export function workflowSupervisorBoundaryForWork(
|
|
86
|
+
options: { controllerHome: string; repoId: string },
|
|
87
|
+
workId: string,
|
|
88
|
+
): WorkflowSupervisorBoundary {
|
|
89
|
+
const work = getWorkContract(options, workId);
|
|
90
|
+
if (!work || semanticWorkState(work) !== 'open') return { status: 'not_eligible' };
|
|
91
|
+
const binding = getChatgptWorkConversationBinding(options, workId);
|
|
92
|
+
if (!binding) return { status: 'conversation_pending', reason: 'EXACT_WORK_CONVERSATION_BINDING_REQUIRED' };
|
|
93
|
+
return {
|
|
94
|
+
status: 'outer_turn',
|
|
95
|
+
workId: work.workId,
|
|
96
|
+
...(work.requirementId ? { requirementId: work.requirementId } : {}),
|
|
97
|
+
conversationId: binding.conversationId,
|
|
98
|
+
conversationUrl: binding.conversationUrl,
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
export function inheritWorkflowSupervisorConversationBinding(
|
|
103
|
+
options: { controllerHome: string; repoId: string },
|
|
104
|
+
fromWorkId: string,
|
|
105
|
+
toWorkId: string,
|
|
106
|
+
): ChatgptWorkConversationBinding | undefined {
|
|
107
|
+
if (fromWorkId === toWorkId) return getChatgptWorkConversationBinding(options, toWorkId);
|
|
108
|
+
const sourceWork = getWorkContract(options, fromWorkId);
|
|
109
|
+
const targetWork = getWorkContract(options, toWorkId);
|
|
110
|
+
if (!sourceWork?.requirementId || sourceWork.requirementId !== targetWork?.requirementId) return undefined;
|
|
111
|
+
// Requirement membership is goal identity, not conversation lineage. Only an
|
|
112
|
+
// explicit Work predecessor edge proves that the successor belongs to the
|
|
113
|
+
// same logical controller conversation. Sibling Works must bind their own
|
|
114
|
+
// current conversation instead of silently reusing historical delivery.
|
|
115
|
+
if (targetWork?.predecessorWorkId?.trim() !== fromWorkId) return undefined;
|
|
116
|
+
const source = getChatgptWorkConversationBinding(options, fromWorkId);
|
|
117
|
+
if (!source) return undefined;
|
|
118
|
+
const existing = getChatgptWorkConversationBinding(options, toWorkId);
|
|
119
|
+
if (existing) {
|
|
120
|
+
if (existing.conversationId !== source.conversationId) {
|
|
121
|
+
throw new Error(`WORKFLOW_SUPERVISOR_CONVERSATION_CONFLICT:${sourceWork.requirementId}`);
|
|
122
|
+
}
|
|
123
|
+
return existing;
|
|
124
|
+
}
|
|
125
|
+
return bindChatgptWorkConversation(options, {
|
|
126
|
+
workId: toWorkId,
|
|
127
|
+
conversationUrl: source.conversationUrl,
|
|
128
|
+
latestBrowserSessionId: source.latestBrowserSessionId,
|
|
129
|
+
authorizationGrantRefs: source.authorizationGrantRefs,
|
|
130
|
+
localAlias: source.localAlias,
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
export function workflowSupervisorContractText(task: WorkflowSupervisorTask, key: string): string | undefined {
|
|
135
|
+
const value = task.completionContract[key] ?? task.userBlockerPolicy[key];
|
|
136
|
+
return typeof value === 'string' && value.trim() ? value.trim() : undefined;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
function workflowSupervisorOriginWorkId(
|
|
140
|
+
task: WorkflowSupervisorTask,
|
|
141
|
+
repoId: string,
|
|
142
|
+
controllerHome: string,
|
|
143
|
+
conversationId = task.conversationId,
|
|
144
|
+
): string | undefined {
|
|
145
|
+
const legacyWorkPrefix = `forge:${repoId}:work:`;
|
|
146
|
+
const explicit = workflowSupervisorContractText(task, 'work_id')
|
|
147
|
+
?? (task.taskId.startsWith(legacyWorkPrefix) ? task.taskId.slice(legacyWorkPrefix.length) || undefined : undefined);
|
|
148
|
+
const original = explicit ? getWorkContract({ controllerHome, repoId }, explicit) : undefined;
|
|
149
|
+
if (explicit && (!original || semanticWorkState(original) === 'open')) return explicit;
|
|
150
|
+
const active = listChatgptWorkBindingsForConversation({ controllerHome, repoId }, conversationId)
|
|
151
|
+
.map(({ workId }) => getWorkContract({ controllerHome, repoId }, workId))
|
|
152
|
+
.filter((work): work is NonNullable<typeof work> => Boolean(work && semanticWorkState(work) === 'open'));
|
|
153
|
+
// A terminal predecessor retains its audit and conversation binding. Only
|
|
154
|
+
// explicit successor lineage within the same Requirement can transfer the
|
|
155
|
+
// active Work projection; siblings cannot inherit the predecessor's task.
|
|
156
|
+
if (explicit) {
|
|
157
|
+
const successors = active.filter((work) => work.predecessorWorkId === explicit
|
|
158
|
+
&& original?.requirementId && work.requirementId === original.requirementId);
|
|
159
|
+
return successors.length === 1 && active.length === 1 ? successors[0]!.workId : explicit;
|
|
160
|
+
}
|
|
161
|
+
// Standalone enrollment predates Work binding. It may project into one
|
|
162
|
+
// unambiguous open Work, without creating a second conversation authority.
|
|
163
|
+
if (task.continuationPolicy.kind !== 'standalone_supervisor') return undefined;
|
|
164
|
+
return active.length === 1 ? active[0]!.workId : undefined;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* Mechanical Work projection used to decide whether a provider turn advanced
|
|
169
|
+
* anything. `updatedAt` is deliberately excluded: mechanical Supervisor and
|
|
170
|
+
* Controller bookkeeping touches the record every turn, while only a real Work
|
|
171
|
+
* mutation (authored revision/state, phase evidence, execution evidence,
|
|
172
|
+
* observable changed paths, or a delivery receipt) means the turn did work.
|
|
173
|
+
*/
|
|
174
|
+
function workflowSupervisorWorkProgressFingerprint(controllerHome: string, task: WorkflowSupervisorTask): string | undefined {
|
|
175
|
+
const repoId = workflowSupervisorContractText(task, 'repo_id');
|
|
176
|
+
const taskControllerHome = workflowSupervisorContractText(task, 'controller_home');
|
|
177
|
+
if (!repoId || (taskControllerHome && taskControllerHome !== controllerHome)) return undefined;
|
|
178
|
+
const workId = workflowSupervisorOriginWorkId(task, repoId, controllerHome);
|
|
179
|
+
if (!workId) return undefined;
|
|
180
|
+
const work = getWorkContract({ controllerHome, repoId }, workId);
|
|
181
|
+
if (!work) return undefined;
|
|
182
|
+
return createHash('sha256').update(JSON.stringify({
|
|
183
|
+
semanticRevision: work.semanticRevision ?? null,
|
|
184
|
+
semanticState: work.semanticState,
|
|
185
|
+
phase: work.phase,
|
|
186
|
+
phaseEvidence: work.phaseEvidence,
|
|
187
|
+
dispatchState: work.dispatchState,
|
|
188
|
+
evidenceState: work.evidenceState,
|
|
189
|
+
completionOutcome: work.completionOutcome ?? null,
|
|
190
|
+
completionReceipt: work.completionReceipt ?? null,
|
|
191
|
+
evidenceRefs: work.evidenceRefs,
|
|
192
|
+
changedPaths: work.scopeEvidence?.actualChangedPaths ?? [],
|
|
193
|
+
})).digest('hex');
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
function workflowSupervisorProjectAliases(task: WorkflowSupervisorTask): string[] {
|
|
197
|
+
const requirementId = workflowSupervisorContractText(task, 'requirement_id');
|
|
198
|
+
if (!requirementId) return [];
|
|
199
|
+
// Requirement ids intentionally carry the product key before the structural
|
|
200
|
+
// suffix. ChatGPT Project slugs may insert word separators (for example
|
|
201
|
+
// shenbaobao -> shen-bao-bao), so the browser adapter compares compact ids.
|
|
202
|
+
const productKey = /^REQ-([a-z0-9]{4,})-/i.exec(requirementId.trim())?.[1];
|
|
203
|
+
return productKey ? [productKey] : [];
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
/**
|
|
207
|
+
* Enrollment gives Supervisor authority over this exact conversation. Work and
|
|
208
|
+
* ControllerRound are execution context, not another cross-turn lifecycle.
|
|
209
|
+
* Goal cancellation and explicit conversation rebind revoke new-send authority.
|
|
210
|
+
* Provider observation remains governed separately by the effect ledger.
|
|
211
|
+
*/
|
|
212
|
+
function createForgeWorkflowSupervisorBrowserTaskActive(controllerHome: string): (task: WorkflowSupervisorTask) => boolean {
|
|
213
|
+
return (task) => {
|
|
214
|
+
if (task.continuationPolicy.kind === 'standalone_supervisor') return true;
|
|
215
|
+
if (task.continuationPolicy.kind !== 'forge_goal_outer_turn') return false;
|
|
216
|
+
const repoId = workflowSupervisorContractText(task, 'repo_id');
|
|
217
|
+
const requirementId = workflowSupervisorContractText(task, 'requirement_id');
|
|
218
|
+
const taskControllerHome = workflowSupervisorContractText(task, 'controller_home');
|
|
219
|
+
if (!repoId || taskControllerHome !== controllerHome) return false;
|
|
220
|
+
if (requirementId && readRequirement({ controllerHome }, requirementId)?.value.state === 'cancelled') return false;
|
|
221
|
+
const workId = workflowSupervisorOriginWorkId(task, repoId, controllerHome);
|
|
222
|
+
if (!requirementId && !workId) return false;
|
|
223
|
+
// An independent Requirement Goal can outlive an execution Work; an exact
|
|
224
|
+
// Work-owned Supervisor cannot initiate another Send after that Work closes.
|
|
225
|
+
if (terminalWorkSupervisorStopReason(controllerHome, task)) return false;
|
|
226
|
+
const binding = workId ? getChatgptWorkConversationBinding({ controllerHome, repoId }, workId) : undefined;
|
|
227
|
+
return !binding || binding.conversationId === task.conversationId;
|
|
228
|
+
};
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
/**
|
|
232
|
+
* Only an exact Work-owned Supervisor task follows that Work's terminal state.
|
|
233
|
+
* Requirement-owned autonomous Goals and standalone tasks keep their own
|
|
234
|
+
* explicit lifecycle; a completed lower-layer carrier is not goal completion.
|
|
235
|
+
*/
|
|
236
|
+
function terminalWorkSupervisorStopReason(controllerHome: string, task: WorkflowSupervisorTask): string | undefined {
|
|
237
|
+
const repoId = workflowSupervisorContractText(task, 'repo_id');
|
|
238
|
+
const workId = workflowSupervisorContractText(task, 'work_id');
|
|
239
|
+
const taskHome = workflowSupervisorContractText(task, 'controller_home');
|
|
240
|
+
if (!repoId || !workId || (taskHome && taskHome !== controllerHome)) return undefined;
|
|
241
|
+
if (task.taskId !== `forge:${repoId}:work:${workId}`
|
|
242
|
+
|| task.continuationPolicy.kind === 'standalone_supervisor') return undefined;
|
|
243
|
+
const work = getWorkContract({ controllerHome, repoId }, workId);
|
|
244
|
+
if (!work) return undefined;
|
|
245
|
+
const state = semanticWorkState(work);
|
|
246
|
+
return state !== 'open'
|
|
247
|
+
? `Exact Work ${workId} is ${state}; stop its Work-owned Supervisor continuation without changing the original Work or any successor Schedule.`
|
|
248
|
+
: undefined;
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
export function forgeWorkflowSupervisorLifecycleHooks(controllerHome: string): WorkflowSupervisorLifecycleHooks {
|
|
252
|
+
const browserTaskActive = createForgeWorkflowSupervisorBrowserTaskActive(controllerHome);
|
|
253
|
+
return {
|
|
254
|
+
terminalWorkStopReasonForTask: (task) => terminalWorkSupervisorStopReason(controllerHome, task),
|
|
255
|
+
canonicalObjectiveForTask: (task) => {
|
|
256
|
+
// Standalone Supervisor owns its full objective; Work execution context
|
|
257
|
+
// must never silently replace the original autonomous business goal.
|
|
258
|
+
if (task.continuationPolicy.kind === 'standalone_supervisor') return undefined;
|
|
259
|
+
const repoId = workflowSupervisorContractText(task, 'repo_id');
|
|
260
|
+
const requirementId = workflowSupervisorContractText(task, 'requirement_id');
|
|
261
|
+
const taskControllerHome = workflowSupervisorContractText(task, 'controller_home');
|
|
262
|
+
if (!repoId || (taskControllerHome && taskControllerHome !== controllerHome)) return undefined;
|
|
263
|
+
// Requirement is the durable Goal root. Its outcome is therefore the
|
|
264
|
+
// canonical Supervisor goal; a Work objective is lower-layer execution
|
|
265
|
+
// context and must not become a permanent outer-turn instruction surface.
|
|
266
|
+
if (requirementId) {
|
|
267
|
+
const outcome = readRequirement({ controllerHome }, requirementId)?.value.outcomeStatement?.trim();
|
|
268
|
+
if (outcome) return outcome;
|
|
269
|
+
}
|
|
270
|
+
const workId = workflowSupervisorOriginWorkId(task, repoId, controllerHome);
|
|
271
|
+
if (!workId) return undefined;
|
|
272
|
+
const work = getWorkContract({ controllerHome, repoId }, workId);
|
|
273
|
+
// Legacy / independent Work without Requirement authority keeps the
|
|
274
|
+
// existing fallback. Absence never manufactures a replacement Work.
|
|
275
|
+
return work?.objective;
|
|
276
|
+
},
|
|
277
|
+
advisoryCognitionForTask: (task) => {
|
|
278
|
+
const repoId = workflowSupervisorContractText(task, 'repo_id');
|
|
279
|
+
const taskControllerHome = workflowSupervisorContractText(task, 'controller_home');
|
|
280
|
+
if (!repoId || (taskControllerHome && taskControllerHome !== controllerHome)) return undefined;
|
|
281
|
+
const workId = workflowSupervisorOriginWorkId(task, repoId, controllerHome);
|
|
282
|
+
if (!workId) return undefined;
|
|
283
|
+
const cognitive = renderCognitiveAttentionForWork({ controllerHome, repoId, workId, query: task.objective, maxItems: 6, maxBytes: 5 * 1024 });
|
|
284
|
+
if (task.continuationPolicy.kind !== 'standalone_supervisor') return cognitive;
|
|
285
|
+
const work = getWorkContract({ controllerHome, repoId }, workId);
|
|
286
|
+
if (!work) return cognitive;
|
|
287
|
+
// Thin evidence, not a second task/goal authority. Recent semantic refs
|
|
288
|
+
// carry the concrete next step even when Cognitive recall is empty.
|
|
289
|
+
const refs = (work.semanticResultRefs ?? []).slice(-5).map((ref) => ref.slice(0, 500));
|
|
290
|
+
return [
|
|
291
|
+
`Canonical Work: ${workId} (read-only execution context; Supervisor objective remains authoritative).`,
|
|
292
|
+
`Work objective: ${work.objective.slice(0, 600)}`,
|
|
293
|
+
...refs.map((ref) => `Work evidence: ${ref}`),
|
|
294
|
+
...(cognitive ? [cognitive] : []),
|
|
295
|
+
].join('\n').slice(0, 8_000);
|
|
296
|
+
},
|
|
297
|
+
effectDispatchEvidence: ({ task }) => {
|
|
298
|
+
const claim = getRuntimeWriteClaim();
|
|
299
|
+
const progress = workflowSupervisorWorkProgressFingerprint(controllerHome, task);
|
|
300
|
+
return {
|
|
301
|
+
...(claim && !claim.unmanaged
|
|
302
|
+
? {
|
|
303
|
+
runtime_instance_id: claim.runtimeInstanceId,
|
|
304
|
+
runtime_fencing_generation: claim.fencingGeneration,
|
|
305
|
+
active_release_id: claim.releaseId,
|
|
306
|
+
active_release_authority_revision: claim.releaseAuthorityRevision,
|
|
307
|
+
}
|
|
308
|
+
: {}),
|
|
309
|
+
...(progress ? { work_progress_fingerprint: progress } : {}),
|
|
310
|
+
};
|
|
311
|
+
},
|
|
312
|
+
workProgressFingerprint: (task) => workflowSupervisorWorkProgressFingerprint(controllerHome, task),
|
|
313
|
+
inheritedEffectDispatch: (task, effect) => {
|
|
314
|
+
if (effect.kind !== 'enrollment') return undefined;
|
|
315
|
+
const repoId = workflowSupervisorContractText(task, 'repo_id');
|
|
316
|
+
const requirementId = workflowSupervisorContractText(task, 'requirement_id');
|
|
317
|
+
const workId = repoId ? workflowSupervisorOriginWorkId(task, repoId, controllerHome) : undefined;
|
|
318
|
+
const taskControllerHome = workflowSupervisorContractText(task, 'controller_home');
|
|
319
|
+
if (!repoId || (!requirementId && !workId) || taskControllerHome !== controllerHome) return undefined;
|
|
320
|
+
const store = { controllerHome, repoId };
|
|
321
|
+
const relay = workId
|
|
322
|
+
? getControllerRoundRelay(store, workId)
|
|
323
|
+
: getRequirementControllerRoundRelay(store, requirementId!);
|
|
324
|
+
const legacyStartedDispatch = Boolean(
|
|
325
|
+
relay
|
|
326
|
+
&& (relay.providerDispatchAttempt ?? 0) >= 1
|
|
327
|
+
&& relay.providerDispatchEffectId === effect.effectId
|
|
328
|
+
&& (
|
|
329
|
+
(relay.status === 'blocked' && controllerRoundBlockerClass(relay) === 'provider_dispatch_outcome_unknown')
|
|
330
|
+
|| (relay.status === 'dispatched' && Boolean(relay.providerDispatchReceiptId))
|
|
331
|
+
)
|
|
332
|
+
);
|
|
333
|
+
if (!relay || !legacyStartedDispatch) return undefined;
|
|
334
|
+
const boundary = workflowSupervisorBoundaryForWork(store, relay.originWorkId);
|
|
335
|
+
if (boundary.status !== 'outer_turn'
|
|
336
|
+
|| boundary.conversationId !== task.conversationId
|
|
337
|
+
|| boundary.conversationUrl !== task.conversationUrl) return undefined;
|
|
338
|
+
return {
|
|
339
|
+
generation: 1,
|
|
340
|
+
dispatchId: `controller-round:${relay.relayScopeId}:${relay.providerDispatchAttempt}`,
|
|
341
|
+
evidence: {
|
|
342
|
+
surface: 'controller_round_reconciliation',
|
|
343
|
+
inherited_provider_dispatch: true,
|
|
344
|
+
relay_scope_id: relay.relayScopeId,
|
|
345
|
+
provider_dispatch_attempt: relay.providerDispatchAttempt,
|
|
346
|
+
...(relay.providerDispatchStartedAt ? { provider_dispatch_started_at: relay.providerDispatchStartedAt } : {}),
|
|
347
|
+
},
|
|
348
|
+
};
|
|
349
|
+
},
|
|
350
|
+
projectScopeForTask: (task) => {
|
|
351
|
+
const repoId = workflowSupervisorContractText(task, 'repo_id');
|
|
352
|
+
const taskControllerHome = workflowSupervisorContractText(task, 'controller_home');
|
|
353
|
+
if (!repoId) return undefined;
|
|
354
|
+
if (taskControllerHome && taskControllerHome !== controllerHome) return undefined;
|
|
355
|
+
if (!taskControllerHome && task.continuationPolicy.kind !== 'standalone_supervisor') return undefined;
|
|
356
|
+
try {
|
|
357
|
+
const repository = getRepository(repoId, controllerHome);
|
|
358
|
+
const aliases = workflowSupervisorProjectAliases(task);
|
|
359
|
+
return {
|
|
360
|
+
title: repository.displayName,
|
|
361
|
+
...(aliases.length > 0 ? { aliases } : {}),
|
|
362
|
+
repoId,
|
|
363
|
+
controllerHome,
|
|
364
|
+
};
|
|
365
|
+
} catch { return undefined; }
|
|
366
|
+
},
|
|
367
|
+
browserTaskActive,
|
|
368
|
+
bootstrapConversationBound: (task, context) => {
|
|
369
|
+
const repoId = workflowSupervisorContractText(task, 'repo_id');
|
|
370
|
+
const declaredWorkId = workflowSupervisorContractText(task, 'work_id');
|
|
371
|
+
const taskControllerHome = workflowSupervisorContractText(task, 'controller_home');
|
|
372
|
+
if (!repoId || taskControllerHome !== controllerHome) return;
|
|
373
|
+
// On migration, retain the sole active Work projection even for a
|
|
374
|
+
// standalone task without work_id or a completed predecessor. Prefer
|
|
375
|
+
// a binding already moved to the new conversation on duplicate callbacks.
|
|
376
|
+
const currentWorkId = workflowSupervisorOriginWorkId(task, repoId, controllerHome);
|
|
377
|
+
const bindingWorkId = context?.migratedFromConversationId
|
|
378
|
+
? (currentWorkId && currentWorkId !== declaredWorkId
|
|
379
|
+
? currentWorkId
|
|
380
|
+
: workflowSupervisorOriginWorkId(task, repoId, controllerHome, context.migratedFromConversationId) ?? declaredWorkId)
|
|
381
|
+
: declaredWorkId;
|
|
382
|
+
if (!bindingWorkId) return;
|
|
383
|
+
const existing = getChatgptWorkConversationBinding({ controllerHome, repoId }, bindingWorkId);
|
|
384
|
+
if (existing && existing.conversationId !== task.conversationId) {
|
|
385
|
+
if (!context?.migratedFromConversationId || context.migratedFromConversationId !== existing.conversationId) {
|
|
386
|
+
throw new Error('WORKFLOW_SUPERVISOR_BOOTSTRAP_WORK_CONVERSATION_CONFLICT');
|
|
387
|
+
}
|
|
388
|
+
rebindChatgptWorkConversation({ controllerHome, repoId }, {
|
|
389
|
+
workId: bindingWorkId,
|
|
390
|
+
previousConversationId: existing.conversationId,
|
|
391
|
+
conversationUrl: task.conversationUrl,
|
|
392
|
+
localAlias: existing.localAlias,
|
|
393
|
+
});
|
|
394
|
+
return;
|
|
395
|
+
}
|
|
396
|
+
if (!existing) {
|
|
397
|
+
bindChatgptWorkConversation({ controllerHome, repoId }, {
|
|
398
|
+
workId: bindingWorkId,
|
|
399
|
+
conversationUrl: task.conversationUrl,
|
|
400
|
+
localAlias: 'Forge autonomous execution',
|
|
401
|
+
});
|
|
402
|
+
}
|
|
403
|
+
},
|
|
404
|
+
effectApplied: (task, effect, observation) => {
|
|
405
|
+
if (effect.kind !== 'enrollment') return;
|
|
406
|
+
const repoId = workflowSupervisorContractText(task, 'repo_id');
|
|
407
|
+
const requirementId = workflowSupervisorContractText(task, 'requirement_id');
|
|
408
|
+
const workId = repoId ? workflowSupervisorOriginWorkId(task, repoId, controllerHome) : undefined;
|
|
409
|
+
const taskControllerHome = workflowSupervisorContractText(task, 'controller_home');
|
|
410
|
+
if (!repoId || (!requirementId && !workId) || taskControllerHome !== controllerHome) return;
|
|
411
|
+
const store = { controllerHome, repoId };
|
|
412
|
+
const relay = workId
|
|
413
|
+
? getControllerRoundRelay(store, workId)
|
|
414
|
+
: getRequirementControllerRoundRelay(store, requirementId!);
|
|
415
|
+
if (!relay || !['dispatching', 'blocked'].includes(relay.status)) return;
|
|
416
|
+
// Receipt projection can settle only the enrolled lower effect. A newer
|
|
417
|
+
// occurrence or sibling Work must never inherit an old conversation send.
|
|
418
|
+
if ((relay.providerDispatchEffectId ?? controllerRoundProviderEffectId(relay)) !== effect.effectId) return;
|
|
419
|
+
const boundary = workflowSupervisorBoundaryForWork(store, relay.originWorkId);
|
|
420
|
+
if (boundary.status !== 'outer_turn' || boundary.conversationId !== task.conversationId) return;
|
|
421
|
+
finishControllerRoundRelayDispatch(store, {
|
|
422
|
+
workId: relay.originWorkId,
|
|
423
|
+
ok: true,
|
|
424
|
+
providerDispatchEffectId: effect.effectId,
|
|
425
|
+
providerDispatchReceiptId: `workflow-supervisor:${effect.effectId}:${observation.observationId}`,
|
|
426
|
+
});
|
|
427
|
+
},
|
|
428
|
+
};
|
|
429
|
+
}
|
|
430
|
+
export async function workflowSupervisorCurrentConversationMatchesWork(
|
|
431
|
+
options: { controllerHome: string; repoId: string },
|
|
432
|
+
workId: string,
|
|
433
|
+
): Promise<boolean> {
|
|
434
|
+
const boundary = workflowSupervisorBoundaryForWork(options, workId);
|
|
435
|
+
if (boundary.status !== 'outer_turn') return false;
|
|
436
|
+
const forgeHome = resolveWorkflowSupervisorForgeHome(options.controllerHome);
|
|
437
|
+
if (!existsSync(workflowSupervisorSocketPath(forgeHome))) return false;
|
|
438
|
+
try {
|
|
439
|
+
const current = await getWorkflowSupervisorCurrentConversation(forgeHome);
|
|
440
|
+
// The same ChatGPT conversation may be rendered with or without its Project
|
|
441
|
+
// route. Its durable conversation id, not that route, proves continuity.
|
|
442
|
+
return Boolean(current
|
|
443
|
+
&& current.conversationId === boundary.conversationId);
|
|
444
|
+
} catch {
|
|
445
|
+
return false;
|
|
446
|
+
}
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
export async function bindCurrentWorkflowSupervisorConversationForWork(
|
|
450
|
+
options: { controllerHome: string; repoId: string },
|
|
451
|
+
workId: string,
|
|
452
|
+
): Promise<
|
|
453
|
+
| { status: 'bound'; binding: ChatgptWorkConversationBinding }
|
|
454
|
+
| { status: 'not_eligible' | 'current_conversation_unbound' | 'daemon_unavailable'; reason?: string }
|
|
455
|
+
> {
|
|
456
|
+
const work = getWorkContract(options, workId);
|
|
457
|
+
if (!work || semanticWorkState(work) !== 'open') return { status: 'not_eligible' };
|
|
458
|
+
const forgeHome = resolveWorkflowSupervisorForgeHome(options.controllerHome);
|
|
459
|
+
if (!existsSync(workflowSupervisorSocketPath(forgeHome))) return { status: 'daemon_unavailable', reason: 'WORKFLOW_SUPERVISOR_DAEMON_UNAVAILABLE' };
|
|
460
|
+
const existing = getChatgptWorkConversationBinding(options, workId);
|
|
461
|
+
const current = await getWorkflowSupervisorCurrentConversation(forgeHome);
|
|
462
|
+
// Browser focus is ephemeral observation, not a second authority over an
|
|
463
|
+
// already-bound Work. When a durable exact binding exists, a missing current
|
|
464
|
+
// marker cannot revoke it; a fresh conflicting marker still fails closed.
|
|
465
|
+
if (existing) {
|
|
466
|
+
if (current && existing.conversationId !== current.conversationId) {
|
|
467
|
+
throw new Error(`WORKFLOW_SUPERVISOR_CURRENT_CONVERSATION_CONFLICT:${workId}:${existing.conversationId}:${current.conversationId}`);
|
|
468
|
+
}
|
|
469
|
+
return { status: 'bound', binding: existing };
|
|
470
|
+
}
|
|
471
|
+
if (!current) return { status: 'current_conversation_unbound', reason: 'WORKFLOW_SUPERVISOR_CURRENT_CONVERSATION_UNBOUND' };
|
|
472
|
+
const binding = bindChatgptWorkConversation(options, {
|
|
473
|
+
workId,
|
|
474
|
+
conversationUrl: current.canonicalUrl,
|
|
475
|
+
localAlias: current.title,
|
|
476
|
+
});
|
|
477
|
+
return { status: 'bound', binding };
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
export async function bindWorkflowSupervisorScheduledWakeForWork(
|
|
481
|
+
options: { controllerHome: string; repoId: string },
|
|
482
|
+
workId: string,
|
|
483
|
+
scheduleId: string,
|
|
484
|
+
): Promise<{ status: 'bound'; taskId: string } | { status: 'not_enrolled' | 'binding_deferred' }> {
|
|
485
|
+
const forgeHome = resolveWorkflowSupervisorForgeHome(options.controllerHome);
|
|
486
|
+
if (!existsSync(workflowSupervisorSocketPath(forgeHome))) return { status: 'binding_deferred' };
|
|
487
|
+
const exactTaskId = taskIdForWork(options.repoId, workId);
|
|
488
|
+
let task = await getWorkflowSupervisorTask(forgeHome, exactTaskId);
|
|
489
|
+
if (!task) {
|
|
490
|
+
const binding = getChatgptWorkConversationBinding(options, workId);
|
|
491
|
+
if (binding) {
|
|
492
|
+
const authority = await getWorkflowSupervisorTaskByConversationId(forgeHome, binding.conversationId);
|
|
493
|
+
if (authority) {
|
|
494
|
+
const ownerRepoId = typeof authority.task.completionContract.repo_id === 'string'
|
|
495
|
+
? authority.task.completionContract.repo_id : authority.task.continuationPolicy.repo_id;
|
|
496
|
+
if (ownerRepoId !== options.repoId || authority.task.completionContract.work_id !== workId) {
|
|
497
|
+
throw new Error('WORKFLOW_SUPERVISOR_SCHEDULE_WORK_IDENTITY_MISMATCH');
|
|
498
|
+
}
|
|
499
|
+
task = authority.task;
|
|
500
|
+
}
|
|
501
|
+
}
|
|
502
|
+
}
|
|
503
|
+
if (!task) return { status: 'not_enrolled' };
|
|
504
|
+
const bound = await bindWorkflowSupervisorScheduledWake(forgeHome, {
|
|
505
|
+
taskId: task.taskId,
|
|
506
|
+
repoId: options.repoId,
|
|
507
|
+
workId,
|
|
508
|
+
scheduleId,
|
|
509
|
+
});
|
|
510
|
+
return { status: 'bound', taskId: bound.task.taskId };
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
export async function wakeWorkflowSupervisorScheduledTaskForWork(
|
|
514
|
+
options: { controllerHome: string; repoId: string },
|
|
515
|
+
workId: string,
|
|
516
|
+
scheduleId: string,
|
|
517
|
+
occurrenceId: string,
|
|
518
|
+
): Promise<{ status: 'woken' | 'not_waiting' | 'not_enrolled' | 'binding_deferred'; taskId?: string; effectId?: string }> {
|
|
519
|
+
const binding = await bindWorkflowSupervisorScheduledWakeForWork(options, workId, scheduleId);
|
|
520
|
+
if (binding.status !== 'bound') return binding;
|
|
521
|
+
if (!binding.taskId) throw new Error('WORKFLOW_SUPERVISOR_SCHEDULE_BINDING_TASK_ID_MISSING');
|
|
522
|
+
const forgeHome = resolveWorkflowSupervisorForgeHome(options.controllerHome);
|
|
523
|
+
const stall = await getWorkflowSupervisorTaskStall(forgeHome, binding.taskId);
|
|
524
|
+
if (stall.state !== 'waiting') return { status: 'not_waiting', taskId: binding.taskId };
|
|
525
|
+
const wake = await wakeWorkflowSupervisorScheduledTask(forgeHome, {
|
|
526
|
+
taskId: binding.taskId, scheduleId, occurrenceId,
|
|
527
|
+
});
|
|
528
|
+
return { status: 'woken', taskId: binding.taskId, effectId: wake.effect.effectId };
|
|
529
|
+
}
|
|
530
|
+
|
|
531
|
+
export async function ensureWorkflowSupervisorEnrollmentForWork(
|
|
532
|
+
options: { controllerHome: string; repoId: string },
|
|
533
|
+
workId: string,
|
|
534
|
+
scheduledWakeScheduleId?: string,
|
|
535
|
+
scheduleOccurrenceId?: string,
|
|
536
|
+
): Promise<{ status: WorkflowSupervisorEnrollmentStatus; taskId?: string; effectId?: string; reason?: string }> {
|
|
537
|
+
const boundary = workflowSupervisorBoundaryForWork(options, workId);
|
|
538
|
+
if (boundary.status === 'not_eligible') return { status: boundary.status };
|
|
539
|
+
const forgeHome = resolveWorkflowSupervisorForgeHome(options.controllerHome);
|
|
540
|
+
// Work-derived task ids are only bootstrap reservation identities. Once an
|
|
541
|
+
// exact conversation exists, the task-registration RPC returns the canonical
|
|
542
|
+
// Supervisor task already owning that conversation, including across successor Work.
|
|
543
|
+
const taskId = taskIdForWork(options.repoId, workId);
|
|
544
|
+
if (!existsSync(workflowSupervisorSocketPath(forgeHome))) return { status: 'daemon_unavailable', taskId };
|
|
545
|
+
|
|
546
|
+
// A Work-derived Supervisor id is a durable task reservation, not a
|
|
547
|
+
// registration template to rewrite on every Scheduler wake. In particular,
|
|
548
|
+
// an explicitly stopped historical task remains terminal even if its Work is
|
|
549
|
+
// still open, and a live bootstrap retains its original immutable objective
|
|
550
|
+
// and effect when the lower Work wording changes. Do not mint a replacement
|
|
551
|
+
// send, mutate Task identity, or use lower ControllerRound state to revive it.
|
|
552
|
+
const existingWorkTask = await getWorkflowSupervisorTask(forgeHome, taskId);
|
|
553
|
+
if (existingWorkTask) {
|
|
554
|
+
const existingRepoId = typeof existingWorkTask.completionContract.repo_id === 'string'
|
|
555
|
+
? existingWorkTask.completionContract.repo_id
|
|
556
|
+
: existingWorkTask.continuationPolicy.repo_id;
|
|
557
|
+
const existingWorkId = existingWorkTask.completionContract.work_id;
|
|
558
|
+
if (existingRepoId !== options.repoId || existingWorkId !== workId) {
|
|
559
|
+
throw new Error('WORKFLOW_SUPERVISOR_TASK_ID_CONFLICT');
|
|
560
|
+
}
|
|
561
|
+
let stall = await getWorkflowSupervisorTaskStall(forgeHome, taskId);
|
|
562
|
+
if (stall.state === 'terminal') {
|
|
563
|
+
return { status: 'lower_layer_not_ready', reason: 'WORKFLOW_SUPERVISOR_TASK_TERMINAL' };
|
|
564
|
+
}
|
|
565
|
+
if (scheduledWakeScheduleId) {
|
|
566
|
+
await bindWorkflowSupervisorScheduledWake(forgeHome, {
|
|
567
|
+
taskId,
|
|
568
|
+
repoId: options.repoId,
|
|
569
|
+
workId,
|
|
570
|
+
scheduleId: scheduledWakeScheduleId,
|
|
571
|
+
});
|
|
572
|
+
stall = await getWorkflowSupervisorTaskStall(forgeHome, taskId);
|
|
573
|
+
if (stall.state === 'waiting') {
|
|
574
|
+
if (!scheduleOccurrenceId) return { status: 'lower_layer_not_ready', taskId, reason: 'SCHEDULE_OCCURRENCE_ID_REQUIRED' };
|
|
575
|
+
const wake = await wakeWorkflowSupervisorScheduledTask(forgeHome, {
|
|
576
|
+
taskId, scheduleId: scheduledWakeScheduleId, occurrenceId: scheduleOccurrenceId,
|
|
577
|
+
});
|
|
578
|
+
return { status: 'enrolled', taskId, effectId: wake.effect.effectId };
|
|
579
|
+
}
|
|
580
|
+
}
|
|
581
|
+
const ownedRequirementId = typeof existingWorkTask.completionContract.requirement_id === 'string'
|
|
582
|
+
? existingWorkTask.completionContract.requirement_id : undefined;
|
|
583
|
+
if (ownedRequirementId !== getWorkContract(options, workId)?.requirementId) {
|
|
584
|
+
throw new Error('WORKFLOW_SUPERVISOR_TASK_REQUIREMENT_CONFLICT');
|
|
585
|
+
}
|
|
586
|
+
if (boundary.status === 'conversation_pending') {
|
|
587
|
+
if (existingWorkTask.continuationPolicy.kind !== 'forge_goal_outer_turn') {
|
|
588
|
+
throw new Error('WORKFLOW_SUPERVISOR_TASK_ID_CONFLICT');
|
|
589
|
+
}
|
|
590
|
+
const effect = await reserveWorkflowSupervisorEnrollment(forgeHome, taskId);
|
|
591
|
+
return { status: 'enrolled', taskId, effectId: effect.effectId };
|
|
592
|
+
}
|
|
593
|
+
}
|
|
594
|
+
|
|
595
|
+
// Once an exact conversation is already owned by a Supervisor task, that
|
|
596
|
+
// task is the outer-turn authority. ControllerRound is only first-admission
|
|
597
|
+
// execution context and must not regain veto power over later continuation.
|
|
598
|
+
// Read before any lower-layer admission check so a blocked/exhausted old
|
|
599
|
+
// Round cannot strand an already-enrolled exact conversation.
|
|
600
|
+
if (boundary.status === 'outer_turn') {
|
|
601
|
+
const existingAuthority = await getWorkflowSupervisorTaskByConversationId(forgeHome, boundary.conversationId);
|
|
602
|
+
if (existingAuthority) {
|
|
603
|
+
const existingRepoId = typeof existingAuthority.task.completionContract.repo_id === 'string'
|
|
604
|
+
? existingAuthority.task.completionContract.repo_id
|
|
605
|
+
: existingAuthority.task.continuationPolicy.repo_id;
|
|
606
|
+
if (typeof existingRepoId === 'string' && existingRepoId !== options.repoId) {
|
|
607
|
+
throw new Error(`WORKFLOW_SUPERVISOR_TASK_REPOSITORY_CONFLICT:${boundary.conversationId}`);
|
|
608
|
+
}
|
|
609
|
+
if (existingAuthority.terminal) {
|
|
610
|
+
// Terminal Supervisor authority must never be resurrected by a lower
|
|
611
|
+
// ControllerRound. Report the outer-turn boundary as already owned so
|
|
612
|
+
// Scheduler/Controller composition cannot create another provider turn.
|
|
613
|
+
return {
|
|
614
|
+
status: 'enrolled',
|
|
615
|
+
taskId: existingAuthority.task.taskId,
|
|
616
|
+
reason: `WORKFLOW_SUPERVISOR_TASK_TERMINAL:${existingAuthority.terminal}`,
|
|
617
|
+
};
|
|
618
|
+
}
|
|
619
|
+
if (scheduledWakeScheduleId) {
|
|
620
|
+
await bindWorkflowSupervisorScheduledWake(forgeHome, {
|
|
621
|
+
taskId: existingAuthority.task.taskId,
|
|
622
|
+
repoId: options.repoId,
|
|
623
|
+
workId,
|
|
624
|
+
scheduleId: scheduledWakeScheduleId,
|
|
625
|
+
});
|
|
626
|
+
const stall = await getWorkflowSupervisorTaskStall(forgeHome, existingAuthority.task.taskId);
|
|
627
|
+
if (stall.state === 'waiting') {
|
|
628
|
+
if (!scheduleOccurrenceId) return { status: 'lower_layer_not_ready', taskId: existingAuthority.task.taskId, reason: 'SCHEDULE_OCCURRENCE_ID_REQUIRED' };
|
|
629
|
+
const wake = await wakeWorkflowSupervisorScheduledTask(forgeHome, {
|
|
630
|
+
taskId: existingAuthority.task.taskId, scheduleId: scheduledWakeScheduleId, occurrenceId: scheduleOccurrenceId,
|
|
631
|
+
});
|
|
632
|
+
return { status: 'enrolled', taskId: existingAuthority.task.taskId, effectId: wake.effect.effectId };
|
|
633
|
+
}
|
|
634
|
+
}
|
|
635
|
+
const effect = await reserveWorkflowSupervisorEnrollment(forgeHome, existingAuthority.task.taskId);
|
|
636
|
+
return { status: 'enrolled', taskId: existingAuthority.task.taskId, effectId: effect.effectId };
|
|
637
|
+
}
|
|
638
|
+
}
|
|
639
|
+
|
|
640
|
+
const lowerLayer = workflowSupervisorLowerLayerReadyForWork(options, workId);
|
|
641
|
+
if (!lowerLayer.ready) return { status: 'lower_layer_not_ready', reason: lowerLayer.reason };
|
|
642
|
+
const work = getWorkContract(options, workId);
|
|
643
|
+
const requirement = work?.requirementId
|
|
644
|
+
? readRequirement({ controllerHome: options.controllerHome }, work.requirementId)?.value
|
|
645
|
+
: undefined;
|
|
646
|
+
const registeredTask = await registerWorkflowSupervisorTask(forgeHome, {
|
|
647
|
+
taskId,
|
|
648
|
+
// This is a durable pre-send reservation, not a conversation identity.
|
|
649
|
+
// The Computer adapter replaces it atomically after the first confirmed
|
|
650
|
+
// submission exposes ChatGPT's canonical conversation URL.
|
|
651
|
+
conversationId: boundary.status === 'outer_turn' ? boundary.conversationId : `bootstrap:${workId}`,
|
|
652
|
+
conversationUrl: boundary.status === 'outer_turn' ? boundary.conversationUrl : 'https://chatgpt.com/',
|
|
653
|
+
objective: requirement?.outcomeStatement ?? work?.objective ?? workId,
|
|
654
|
+
completionContract: {
|
|
655
|
+
kind: requirement ? 'forge_requirement_done' : 'forge_work_done',
|
|
656
|
+
controller_home: options.controllerHome,
|
|
657
|
+
repo_id: options.repoId,
|
|
658
|
+
work_id: workId,
|
|
659
|
+
...(requirement ? { requirement_id: requirement.requirementId } : {}),
|
|
660
|
+
},
|
|
661
|
+
continuationPolicy: {
|
|
662
|
+
kind: 'forge_goal_outer_turn',
|
|
663
|
+
...(boundary.status === 'outer_turn'
|
|
664
|
+
? { exact_conversation_id: boundary.conversationId, exact_conversation_url: boundary.conversationUrl }
|
|
665
|
+
: { bootstrap: true }),
|
|
666
|
+
...(scheduledWakeScheduleId ? { scheduled_wake_schedule_id: scheduledWakeScheduleId } : {}),
|
|
667
|
+
outer_turn_owner: 'workflow_supervisor',
|
|
668
|
+
},
|
|
669
|
+
userBlockerPolicy: {
|
|
670
|
+
kind: requirement ? 'forge_requirement_waiting_for_user' : 'forge_work_waiting_for_user',
|
|
671
|
+
controller_home: options.controllerHome,
|
|
672
|
+
repo_id: options.repoId,
|
|
673
|
+
work_id: workId,
|
|
674
|
+
...(requirement ? { requirement_id: requirement.requirementId } : {}),
|
|
675
|
+
},
|
|
676
|
+
});
|
|
677
|
+
const effect = await reserveWorkflowSupervisorEnrollment(forgeHome, registeredTask.taskId, lowerLayer.providerEffectId);
|
|
678
|
+
// Runtime owns only enrollment. Provider send/reconcile/re-dispatch budgeting
|
|
679
|
+
// stays entirely inside the Supervisor effect ledger and Browser adapter.
|
|
680
|
+
return { status: 'enrolled', taskId: registeredTask.taskId, effectId: effect.effectId };
|
|
681
|
+
}
|