@moretea-labs/forge 1.8.0 → 1.8.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +70 -7
- package/CHANGELOG.md +14 -0
- package/CLAUDE.md +17 -2
- package/CONTRIBUTING.md +3 -2
- package/THIRD_PARTY_NOTICES.md +1 -1
- package/adapters/chatgpt/browser-delivery-host.ts +7 -1
- package/adapters/chatgpt/browser-delivery-runtime.ts +529 -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 +228 -1
- package/adapters/chatgpt/work-conversation-binding-store.ts +79 -53
- package/adapters/computer/chatgpt-extension-target.ts +463 -0
- package/adapters/computer/chatgpt-target-router.ts +103 -0
- package/adapters/computer/chrome-extension/background.js +385 -0
- package/adapters/computer/chrome-extension/content.js +378 -0
- package/adapters/computer/chrome-extension/core.js +24 -0
- package/adapters/computer/chrome-extension/manifest.json +30 -0
- package/adapters/computer/desktop-operator-discovery.ts +11 -31
- package/adapters/computer/interaction-target-authority.ts +142 -18
- package/adapters/mcp/auth.ts +0 -1
- package/adapters/mcp/instructions.ts +5 -4
- package/adapters/mcp/multi-repository.ts +3 -19
- package/adapters/mcp/oauth.ts +73 -0
- package/adapters/mcp/paths.ts +4 -1
- package/adapters/mcp/runtime-gateway/automation-receipt-adapter.ts +87 -0
- 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 +411 -73
- package/adapters/mcp/runtime-gateway/context-pack-sidecar.ts +91 -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 +8 -42
- package/adapters/mcp/runtime-gateway/gateway-execution-adapter.ts +2 -1
- package/adapters/mcp/runtime-gateway/plugin-adapter.ts +117 -45
- package/adapters/mcp/runtime-gateway/process-tools.ts +190 -22
- 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 +18 -504
- package/adapters/mcp/runtime-gateway/routing-policy.ts +499 -0
- package/adapters/mcp/runtime-gateway/runtime-observation-adapter.ts +14 -65
- package/adapters/mcp/runtime-gateway/runtime-readiness-observation.ts +218 -0
- package/adapters/mcp/runtime-gateway/runtime-tool-definitions.ts +113 -173
- package/adapters/mcp/runtime-gateway/runtime-tools.ts +15 -5
- package/adapters/mcp/runtime-gateway/scheduler-adapter.ts +1 -0
- package/adapters/mcp/runtime-gateway/shared-adapter.ts +20 -0
- package/adapters/mcp/runtime-gateway/status-inbox-adapter.ts +358 -266
- package/adapters/mcp/runtime-gateway/typescript-navigation-sidecar.ts +136 -0
- package/adapters/mcp/runtime-gateway/work-adapter.ts +261 -3122
- 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 +246 -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 +263 -0
- package/adapters/mcp/runtime-gateway/work-workflow-operations.ts +113 -0
- package/adapters/mcp/runtime-gateway/workflow-supervisor-adapter.ts +156 -0
- package/adapters/mcp/server.ts +67 -23
- package/adapters/mcp/setup.ts +1 -3
- package/adapters/mcp/tool-mapping/legacy-tool-service.ts +44 -170
- package/adapters/mcp/tool-mapping/post-finalize-work-attribution.ts +4 -9
- package/adapters/mcp/tool-mapping/repository-tools.ts +133 -142
- package/adapters/mcp/toolset-names.ts +5 -0
- package/adapters/mcp/toolset.ts +6 -5
- package/adapters/mcp/transports/http-observation.ts +365 -0
- package/adapters/mcp/transports/http.ts +154 -677
- 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/assets/plugin-registry.v1.json +6 -4
- package/assets/reference-configs/agentic-development-flow.md +25 -0
- package/assets/reference-configs/global-working-rules.md +19 -0
- package/assets/skill-version.json +2 -2
- package/docs/architecture/CURRENT.md +111 -41
- 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/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 +221 -0
- package/docs/architecture/decisions/20260919-autonomous-work-liveness.md +62 -0
- package/docs/architecture/decisions/20260924-thin-semantic-working-context.md +72 -0
- package/docs/architecture/decisions/20261001-supervisor-turn-authority.md +237 -0
- package/docs/architecture/decisions/20261005-forge-v3-desktop-client-boundary.md +77 -0
- package/docs/architecture/domains/verification.md +1 -0
- package/docs/architecture/domains/workflow-engine.md +6 -0
- package/docs/architecture/modules/controller-runtime/transport-lifecycle.md +1 -1
- package/docs/forge-plugin-management.md +2 -2
- package/docs/operations/controller-performance-and-502.md +17 -0
- package/docs/operations/controller-reliability-runbook.md +2 -2
- package/docs/operations/features.md +1 -1
- package/docs/operations/features.zh-CN.md +1 -1
- package/docs/operations/homebrew.md +2 -2
- package/docs/operations/mcp-tool-exposure.md +2 -0
- package/docs/operations/releasing.md +2 -0
- package/docs/operations/standalone-disaster-recovery.md +14 -6
- package/docs/wiki/Implementation.md +1 -1
- package/package.json +25 -14
- 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 +297 -71
- 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 +77 -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/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 +153 -133
- package/packages/kernel/work/api/index.ts +3 -2
- package/packages/kernel/work/application/work-service.ts +17 -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 +25 -63
- package/packages/kernel/work/domain/types.ts +57 -51
- package/packages/kernel/work/infrastructure/work-contract-store.ts +819 -728
- package/packages/kernel/work/ports/work-contract-store.ts +5 -2
- 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 +143 -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/canary-controller-semantic-wait.ts +12 -24
- package/scripts/check-mcp-compatibility.ts +48 -136
- package/scripts/check-runtime-architecture.mjs +622 -217
- package/scripts/forge-local-recovery-helper.mjs +93 -15
- package/scripts/lib/project-init-lib.sh +3 -0
- package/scripts/open-source-audit-allowlist.txt +1 -2
- package/scripts/run-bounded-command.mjs +5 -0
- package/scripts/run-governed-gate.ts +0 -1
- package/scripts/run-mobile-monitor-bridge.ts +0 -1
- package/scripts/smoke-control-plane-failure-domain.ts +94 -0
- package/scripts/smoke-mcp-http-runtime.ts +5 -0
- 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 +92 -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/verify-forge-runtime.sh +2 -1
- package/src/cli/agent-jobs/executor-health.ts +11 -34
- package/src/cli/agent-jobs/integration.ts +18 -49
- package/src/cli/agent-jobs/job-manager.ts +7 -3
- 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/recovery.ts +135 -121
- package/src/cli/commands/runtime.ts +3 -3
- 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 +4 -43
- package/src/cli/controller/completion-target.ts +3 -72
- package/src/cli/controller/context/source-materializer.ts +81 -100
- package/src/cli/controller/context-pack.ts +10 -8
- 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 +24 -51
- 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 +39 -1
- package/src/cli/editing/edit-session.ts +1 -7
- package/src/cli/local-bridge/console-automations.ts +18 -13
- package/src/cli/local-bridge/console-view-models.ts +3 -12
- package/src/cli/local-bridge/facade-api.ts +64 -191
- 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-executor.ts +29 -23
- package/src/cli/repositories/command-scope.ts +35 -16
- 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/registry.ts +77 -11
- package/src/cli/repositories/structured-git.ts +62 -2
- package/src/cli/repository/session-cache.ts +92 -6
- 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/semantic-navigation-contract.ts +9 -0
- package/src/runtime/context/semantic-navigation.ts +6 -34
- 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 +212 -9
- 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 +497 -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 +188 -109
- package/src/runtime/control-plane/execution/work-handle-store.ts +19 -43
- 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 +43 -27
- package/src/runtime/control-plane/execution/work-preparation-service.ts +126 -266
- 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 +173 -186
- package/src/runtime/control-plane/execution/work-validation-reconciler.ts +28 -84
- package/src/runtime/control-plane/execution/work-verification-service.ts +406 -50
- package/src/runtime/control-plane/execution/work-verification-snapshot.ts +5 -1
- package/src/runtime/control-plane/facade/capability-registry.ts +362 -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 +8 -8
- package/src/runtime/control-plane/generated-cache-retention.ts +97 -1
- 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 +239 -112
- package/src/runtime/control-plane/global-scheduler/reconciliation.ts +2 -1
- 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/launcher/chatgpt-round-continuation.ts +63 -300
- package/src/runtime/control-plane/launcher/chatgpt-work-continuation.ts +28 -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 +290 -21
- 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/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 +79 -27
- 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 +35 -2
- package/src/runtime/execution/process-runtime/store.ts +30 -2
- package/src/runtime/execution/process-runtime/types.ts +6 -1
- package/src/runtime/execution/workers/executor.ts +2 -6
- 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 +85 -28
- package/src/runtime/plugins/app-store-connect-adapter.ts +38 -14
- package/src/runtime/plugins/browser-adapter.ts +757 -34
- package/src/runtime/plugins/browser-automation-service.ts +23 -3
- package/src/runtime/plugins/browser-macos-bridge.ts +321 -29
- package/src/runtime/plugins/browser-manifest-surface.ts +45 -11
- package/src/runtime/plugins/browser-native-session-service.ts +63 -13
- package/src/runtime/plugins/browser-registration.ts +16 -0
- package/src/runtime/plugins/browser-runtime.ts +14 -1
- 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 +219 -0
- package/src/runtime/plugins/computer-chatgpt-macos-target.ts +891 -0
- package/src/runtime/plugins/computer-registration.ts +222 -11
- 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/gmail-adapter.ts +23 -2
- package/src/runtime/plugins/google-calendar-adapter.ts +2 -2
- package/src/runtime/plugins/google-shared.ts +14 -7
- package/src/runtime/plugins/google-tasks-adapter.ts +2 -2
- package/src/runtime/plugins/ios-adapter.ts +1 -1
- package/src/runtime/plugins/lightweight-action.ts +208 -2
- package/src/runtime/plugins/local-system-adapter.ts +12 -2
- 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 +602 -428
- package/src/runtime/plugins/types.ts +20 -0
- package/src/runtime/plugins/xiaohongshu-publish.ts +16 -0
- package/src/runtime/projections/invalidation.ts +7 -3
- package/src/runtime/projections/materialized-view.ts +80 -36
- package/src/runtime/recovery/actions.ts +3 -3
- package/src/runtime/recovery/capability-action-application.ts +46 -45
- package/src/runtime/recovery/lifecycle-inventory.ts +29 -29
- package/src/runtime/recovery/maintenance-executor.ts +374 -123
- package/src/runtime/recovery/store.ts +29 -11
- package/src/runtime/release/release-coordinator.ts +296 -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 +192 -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 +105 -19
- package/src/runtime/root/package-runtime-release.ts +117 -18
- package/src/runtime/root/package-runtime-service.ts +17 -11
- package/src/runtime/root/release-execution-canary.ts +44 -12
- package/src/runtime/root/release-loader.ts +90 -8
- package/src/runtime/root/release-manifest.ts +80 -6
- package/src/runtime/root/release-materialize.ts +372 -28
- package/src/runtime/root/release-store.ts +395 -36
- package/src/runtime/root/runtime-lane.ts +191 -0
- package/src/runtime/root/runtime.ts +159 -27
- package/src/runtime/root/scheduled-controller-composition.ts +28 -3
- package/src/runtime/root/service-runner.ts +2 -2
- package/src/runtime/root/service.ts +36 -33
- package/src/runtime/root/status.ts +48 -0
- package/src/runtime/root/types.ts +32 -3
- package/src/runtime/root/workflow-supervisor-composition.ts +493 -0
- package/src/runtime/root/workflow-supervisor-runtime.ts +209 -0
- package/src/runtime/root/write-fence.ts +50 -2
- package/src/runtime/safe-tooling/google-credential-store.ts +76 -21
- package/src/runtime/safe-tooling/google-oauth-broker.ts +25 -7
- package/src/runtime/safe-tooling/workspace-auth.ts +1 -1
- package/src/runtime/shared/bounded-child-supervisor.ts +9 -1
- 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 +3702 -342
- package/src/runtime/standalone-recovery/entry.ts +469 -39
- 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 +1 -1
- 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 +10 -3
- package/src/runtime/workflow/schedules/engine.ts +138 -172
- package/src/runtime/workflow/schedules/work-continuation.ts +44 -5
- 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 +201 -0
- package/supervisor/control-plane.ts +868 -0
- package/supervisor/entry.ts +15 -0
- package/supervisor/forge-validators.ts +80 -0
- package/supervisor/index.ts +5 -0
- package/supervisor/native-browser-adapter.ts +786 -0
- package/supervisor/native-messaging/host.ts +39 -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 +202 -0
- package/supervisor/server.ts +404 -0
- package/supervisor/store.ts +1451 -0
- package/supervisor/tsconfig.json +8 -0
- package/supervisor/types.ts +255 -0
- 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/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-tarball-install-smoke.sh +0 -150
- 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/stage-runtime-release.ts +0 -44
- 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/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
|
@@ -0,0 +1,493 @@
|
|
|
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
|
+
rebindChatgptWorkConversation,
|
|
16
|
+
type ChatgptWorkConversationBinding,
|
|
17
|
+
} from '../../../adapters/chatgpt/work-conversation-binding-store';
|
|
18
|
+
import { readRequirement } from '../control-plane/persistence/requirement-store';
|
|
19
|
+
import { getWorkflowSupervisorCurrentConversation, getWorkflowSupervisorTaskByConversationId, registerWorkflowSupervisorTask, reserveWorkflowSupervisorEnrollment } from '../../../supervisor/client';
|
|
20
|
+
import { resolveWorkflowSupervisorForgeHome, workflowSupervisorSocketPath } from '../../../supervisor/paths';
|
|
21
|
+
import type { WorkflowSupervisorLifecycleHooks, WorkflowSupervisorTask } from '../../../supervisor/types';
|
|
22
|
+
import { getRuntimeWriteClaim } from './write-fence';
|
|
23
|
+
import { renderCognitiveAttentionForWork } from '../context/cognitive-attention';
|
|
24
|
+
|
|
25
|
+
export type WorkflowSupervisorBoundary =
|
|
26
|
+
| { status: 'not_eligible' }
|
|
27
|
+
| { status: 'conversation_pending'; reason: 'EXACT_WORK_CONVERSATION_BINDING_REQUIRED' }
|
|
28
|
+
| { status: 'outer_turn'; workId?: string; requirementId?: string; conversationId: string; conversationUrl: string };
|
|
29
|
+
|
|
30
|
+
export type WorkflowSupervisorEnrollmentStatus =
|
|
31
|
+
| 'not_eligible'
|
|
32
|
+
| 'conversation_pending'
|
|
33
|
+
| 'current_conversation_unbound'
|
|
34
|
+
| 'daemon_unavailable'
|
|
35
|
+
| 'enrolled'
|
|
36
|
+
| 'lower_layer_not_ready';
|
|
37
|
+
|
|
38
|
+
export function workflowSupervisorLowerLayerReadyForWork(
|
|
39
|
+
options: { controllerHome: string; repoId: string },
|
|
40
|
+
workId: string,
|
|
41
|
+
): { ready: true; workId: string; providerEffectId: string } | { ready: false; reason: string } {
|
|
42
|
+
const directRelay = getControllerRoundRelay(options, workId);
|
|
43
|
+
const work = getWorkContract(options, workId);
|
|
44
|
+
const relay = directRelay ?? (work?.requirementId ? getRequirementControllerRoundRelay(options, work.requirementId) : undefined);
|
|
45
|
+
if (!relay) return { ready: false, reason: 'CONTROLLER_ROUND_NOT_PREPARED' };
|
|
46
|
+
if (!relay.authorityId?.trim()) return { ready: false, reason: `CONTROLLER_ROUND_AUTHORITY_REQUIRED:${relay.originWorkId}` };
|
|
47
|
+
const outcomeUnknownEffectAwaitingObservation = relay.status === 'blocked'
|
|
48
|
+
&& controllerRoundBlockerClass(relay) === 'provider_dispatch_outcome_unknown'
|
|
49
|
+
&& (relay.providerDispatchAttempt ?? 0) > 0
|
|
50
|
+
&& Boolean(relay.providerDispatchEffectId?.trim());
|
|
51
|
+
if (!['dispatching', 'dispatched', 'claimed'].includes(relay.status) && !outcomeUnknownEffectAwaitingObservation) {
|
|
52
|
+
return { ready: false, reason: `CONTROLLER_ROUND_NOT_DISPATCHABLE:${relay.status}:${relay.blockedReason ?? relay.originWorkId}` };
|
|
53
|
+
}
|
|
54
|
+
return {
|
|
55
|
+
ready: true,
|
|
56
|
+
workId: relay.originWorkId,
|
|
57
|
+
providerEffectId: relay.providerDispatchEffectId ?? controllerRoundProviderEffectId(relay),
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function taskIdForWork(repoId: string, workId: string): string {
|
|
62
|
+
return `forge:${repoId}:work:${workId}`;
|
|
63
|
+
}
|
|
64
|
+
export function getWorkflowSupervisorConversationBindingForWork(
|
|
65
|
+
options: { controllerHome: string; repoId: string },
|
|
66
|
+
workId: string,
|
|
67
|
+
): ChatgptWorkConversationBinding | undefined {
|
|
68
|
+
return getChatgptWorkConversationBinding(options, workId);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export function bindWorkflowSupervisorConversationForWork(
|
|
72
|
+
options: { controllerHome: string; repoId: string },
|
|
73
|
+
input: { workId: string; conversationUrl: string; localAlias?: string },
|
|
74
|
+
): ChatgptWorkConversationBinding {
|
|
75
|
+
return bindChatgptWorkConversation(options, input);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* The boundary is derived from canonical lower-layer facts, never copied into
|
|
80
|
+
* Scheduler or ControllerRound state. Once one Requirement-backed Work has an
|
|
81
|
+
* exact ChatGPT conversation, lower layers may prepare/claim ControllerRounds
|
|
82
|
+
* but may no longer submit the next outer assistant turn.
|
|
83
|
+
*/
|
|
84
|
+
export function workflowSupervisorBoundaryForWork(
|
|
85
|
+
options: { controllerHome: string; repoId: string },
|
|
86
|
+
workId: string,
|
|
87
|
+
): WorkflowSupervisorBoundary {
|
|
88
|
+
const work = getWorkContract(options, workId);
|
|
89
|
+
if (!work || semanticWorkState(work) !== 'open') return { status: 'not_eligible' };
|
|
90
|
+
const binding = getChatgptWorkConversationBinding(options, workId);
|
|
91
|
+
if (!binding) return { status: 'conversation_pending', reason: 'EXACT_WORK_CONVERSATION_BINDING_REQUIRED' };
|
|
92
|
+
return {
|
|
93
|
+
status: 'outer_turn',
|
|
94
|
+
workId: work.workId,
|
|
95
|
+
...(work.requirementId ? { requirementId: work.requirementId } : {}),
|
|
96
|
+
conversationId: binding.conversationId,
|
|
97
|
+
conversationUrl: binding.conversationUrl,
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
export function inheritWorkflowSupervisorConversationBinding(
|
|
102
|
+
options: { controllerHome: string; repoId: string },
|
|
103
|
+
fromWorkId: string,
|
|
104
|
+
toWorkId: string,
|
|
105
|
+
): ChatgptWorkConversationBinding | undefined {
|
|
106
|
+
if (fromWorkId === toWorkId) return getChatgptWorkConversationBinding(options, toWorkId);
|
|
107
|
+
const sourceWork = getWorkContract(options, fromWorkId);
|
|
108
|
+
const targetWork = getWorkContract(options, toWorkId);
|
|
109
|
+
if (!sourceWork?.requirementId || sourceWork.requirementId !== targetWork?.requirementId) return undefined;
|
|
110
|
+
// Requirement membership is goal identity, not conversation lineage. Only an
|
|
111
|
+
// explicit Work predecessor edge proves that the successor belongs to the
|
|
112
|
+
// same logical controller conversation. Sibling Works must bind their own
|
|
113
|
+
// current conversation instead of silently reusing historical delivery.
|
|
114
|
+
if (targetWork?.predecessorWorkId?.trim() !== fromWorkId) return undefined;
|
|
115
|
+
const source = getChatgptWorkConversationBinding(options, fromWorkId);
|
|
116
|
+
if (!source) return undefined;
|
|
117
|
+
const existing = getChatgptWorkConversationBinding(options, toWorkId);
|
|
118
|
+
if (existing) {
|
|
119
|
+
if (existing.conversationId !== source.conversationId) {
|
|
120
|
+
throw new Error(`WORKFLOW_SUPERVISOR_CONVERSATION_CONFLICT:${sourceWork.requirementId}`);
|
|
121
|
+
}
|
|
122
|
+
return existing;
|
|
123
|
+
}
|
|
124
|
+
return bindChatgptWorkConversation(options, {
|
|
125
|
+
workId: toWorkId,
|
|
126
|
+
conversationUrl: source.conversationUrl,
|
|
127
|
+
latestBrowserSessionId: source.latestBrowserSessionId,
|
|
128
|
+
authorizationGrantRefs: source.authorizationGrantRefs,
|
|
129
|
+
localAlias: source.localAlias,
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
function workflowSupervisorContractText(task: WorkflowSupervisorTask, key: string): string | undefined {
|
|
134
|
+
const value = task.completionContract[key] ?? task.userBlockerPolicy[key];
|
|
135
|
+
return typeof value === 'string' && value.trim() ? value.trim() : undefined;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
function workflowSupervisorOriginWorkId(task: WorkflowSupervisorTask, repoId: string): string | undefined {
|
|
139
|
+
const legacyWorkPrefix = `forge:${repoId}:work:`;
|
|
140
|
+
return workflowSupervisorContractText(task, 'work_id')
|
|
141
|
+
?? (task.taskId.startsWith(legacyWorkPrefix) ? task.taskId.slice(legacyWorkPrefix.length) || undefined : undefined);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* Mechanical Work projection used to decide whether a provider turn advanced
|
|
146
|
+
* anything. `updatedAt` is deliberately excluded: mechanical Supervisor and
|
|
147
|
+
* Controller bookkeeping touches the record every turn, while only a real Work
|
|
148
|
+
* mutation (authored revision/state, phase evidence, execution evidence,
|
|
149
|
+
* observable changed paths, or a delivery receipt) means the turn did work.
|
|
150
|
+
*/
|
|
151
|
+
function workflowSupervisorWorkProgressFingerprint(controllerHome: string, task: WorkflowSupervisorTask): string | undefined {
|
|
152
|
+
const repoId = workflowSupervisorContractText(task, 'repo_id');
|
|
153
|
+
const taskControllerHome = workflowSupervisorContractText(task, 'controller_home');
|
|
154
|
+
if (!repoId || (taskControllerHome && taskControllerHome !== controllerHome)) return undefined;
|
|
155
|
+
const workId = workflowSupervisorOriginWorkId(task, repoId);
|
|
156
|
+
if (!workId) return undefined;
|
|
157
|
+
const work = getWorkContract({ controllerHome, repoId }, workId);
|
|
158
|
+
if (!work) return undefined;
|
|
159
|
+
return createHash('sha256').update(JSON.stringify({
|
|
160
|
+
semanticRevision: work.semanticRevision ?? null,
|
|
161
|
+
semanticState: work.semanticState,
|
|
162
|
+
phase: work.phase,
|
|
163
|
+
phaseEvidence: work.phaseEvidence,
|
|
164
|
+
dispatchState: work.dispatchState,
|
|
165
|
+
evidenceState: work.evidenceState,
|
|
166
|
+
completionOutcome: work.completionOutcome ?? null,
|
|
167
|
+
completionReceipt: work.completionReceipt ?? null,
|
|
168
|
+
evidenceRefs: work.evidenceRefs,
|
|
169
|
+
changedPaths: work.scopeEvidence?.actualChangedPaths ?? [],
|
|
170
|
+
})).digest('hex');
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
function workflowSupervisorProjectAliases(task: WorkflowSupervisorTask): string[] {
|
|
174
|
+
const requirementId = workflowSupervisorContractText(task, 'requirement_id');
|
|
175
|
+
if (!requirementId) return [];
|
|
176
|
+
// Requirement ids intentionally carry the product key before the structural
|
|
177
|
+
// suffix. ChatGPT Project slugs may insert word separators (for example
|
|
178
|
+
// shenbaobao -> shen-bao-bao), so the browser adapter compares compact ids.
|
|
179
|
+
const productKey = /^REQ-([a-z0-9]{4,})-/i.exec(requirementId.trim())?.[1];
|
|
180
|
+
return productKey ? [productKey] : [];
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
/**
|
|
184
|
+
* Enrollment gives Supervisor authority over this exact conversation. Work and
|
|
185
|
+
* ControllerRound are execution context, not another cross-turn lifecycle.
|
|
186
|
+
* Goal cancellation and explicit conversation rebind revoke new-send authority.
|
|
187
|
+
* Provider observation remains governed separately by the effect ledger.
|
|
188
|
+
*/
|
|
189
|
+
function createForgeWorkflowSupervisorBrowserTaskActive(controllerHome: string): (task: WorkflowSupervisorTask) => boolean {
|
|
190
|
+
return (task) => {
|
|
191
|
+
if (task.continuationPolicy.kind === 'standalone_supervisor') return true;
|
|
192
|
+
if (task.continuationPolicy.kind !== 'forge_goal_outer_turn') return false;
|
|
193
|
+
const repoId = workflowSupervisorContractText(task, 'repo_id');
|
|
194
|
+
const requirementId = workflowSupervisorContractText(task, 'requirement_id');
|
|
195
|
+
const taskControllerHome = workflowSupervisorContractText(task, 'controller_home');
|
|
196
|
+
if (!repoId || taskControllerHome !== controllerHome) return false;
|
|
197
|
+
if (requirementId && readRequirement({ controllerHome }, requirementId)?.value.state === 'cancelled') return false;
|
|
198
|
+
const workId = workflowSupervisorOriginWorkId(task, repoId);
|
|
199
|
+
if (!requirementId && !workId) return false;
|
|
200
|
+
// An existing task may outlive the Work that originally enrolled it. Its
|
|
201
|
+
// durable task/effect chain still owns the original Goal; absence cannot
|
|
202
|
+
// mean DONE, NEEDS_USER, nor permit a replacement provider send.
|
|
203
|
+
const binding = workId ? getChatgptWorkConversationBinding({ controllerHome, repoId }, workId) : undefined;
|
|
204
|
+
return !binding || binding.conversationId === task.conversationId;
|
|
205
|
+
};
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
export function forgeWorkflowSupervisorLifecycleHooks(controllerHome: string): WorkflowSupervisorLifecycleHooks {
|
|
209
|
+
const browserTaskActive = createForgeWorkflowSupervisorBrowserTaskActive(controllerHome);
|
|
210
|
+
return {
|
|
211
|
+
canonicalObjectiveForTask: (task) => {
|
|
212
|
+
const repoId = workflowSupervisorContractText(task, 'repo_id');
|
|
213
|
+
const requirementId = workflowSupervisorContractText(task, 'requirement_id');
|
|
214
|
+
const taskControllerHome = workflowSupervisorContractText(task, 'controller_home');
|
|
215
|
+
if (!repoId || (taskControllerHome && taskControllerHome !== controllerHome)) return undefined;
|
|
216
|
+
// Requirement is the durable Goal root. Its outcome is therefore the
|
|
217
|
+
// canonical Supervisor goal; a Work objective is lower-layer execution
|
|
218
|
+
// context and must not become a permanent outer-turn instruction surface.
|
|
219
|
+
if (requirementId) {
|
|
220
|
+
const outcome = readRequirement({ controllerHome }, requirementId)?.value.outcomeStatement?.trim();
|
|
221
|
+
if (outcome) return outcome;
|
|
222
|
+
}
|
|
223
|
+
const workId = workflowSupervisorOriginWorkId(task, repoId);
|
|
224
|
+
if (!workId) return undefined;
|
|
225
|
+
const work = getWorkContract({ controllerHome, repoId }, workId);
|
|
226
|
+
// Legacy / independent Work without Requirement authority keeps the
|
|
227
|
+
// existing fallback. Absence never manufactures a replacement Work.
|
|
228
|
+
return work?.objective;
|
|
229
|
+
},
|
|
230
|
+
advisoryCognitionForTask: (task) => {
|
|
231
|
+
const repoId = workflowSupervisorContractText(task, 'repo_id');
|
|
232
|
+
const taskControllerHome = workflowSupervisorContractText(task, 'controller_home');
|
|
233
|
+
if (!repoId || (taskControllerHome && taskControllerHome !== controllerHome)) return undefined;
|
|
234
|
+
const workId = workflowSupervisorOriginWorkId(task, repoId);
|
|
235
|
+
if (!workId) return undefined;
|
|
236
|
+
return renderCognitiveAttentionForWork({ controllerHome, repoId, workId, query: task.objective, maxItems: 6, maxBytes: 8 * 1024 });
|
|
237
|
+
},
|
|
238
|
+
effectDispatchEvidence: ({ task }) => {
|
|
239
|
+
const claim = getRuntimeWriteClaim();
|
|
240
|
+
const progress = workflowSupervisorWorkProgressFingerprint(controllerHome, task);
|
|
241
|
+
return {
|
|
242
|
+
...(claim && !claim.unmanaged
|
|
243
|
+
? {
|
|
244
|
+
runtime_instance_id: claim.runtimeInstanceId,
|
|
245
|
+
runtime_fencing_generation: claim.fencingGeneration,
|
|
246
|
+
active_release_id: claim.releaseId,
|
|
247
|
+
active_release_authority_revision: claim.releaseAuthorityRevision,
|
|
248
|
+
}
|
|
249
|
+
: {}),
|
|
250
|
+
...(progress ? { work_progress_fingerprint: progress } : {}),
|
|
251
|
+
};
|
|
252
|
+
},
|
|
253
|
+
workProgressFingerprint: (task) => workflowSupervisorWorkProgressFingerprint(controllerHome, task),
|
|
254
|
+
inheritedEffectDispatch: (task, effect) => {
|
|
255
|
+
if (effect.kind !== 'enrollment') return undefined;
|
|
256
|
+
const repoId = workflowSupervisorContractText(task, 'repo_id');
|
|
257
|
+
const requirementId = workflowSupervisorContractText(task, 'requirement_id');
|
|
258
|
+
const workId = repoId ? workflowSupervisorOriginWorkId(task, repoId) : undefined;
|
|
259
|
+
const taskControllerHome = workflowSupervisorContractText(task, 'controller_home');
|
|
260
|
+
if (!repoId || (!requirementId && !workId) || taskControllerHome !== controllerHome) return undefined;
|
|
261
|
+
const store = { controllerHome, repoId };
|
|
262
|
+
const relay = workId
|
|
263
|
+
? getControllerRoundRelay(store, workId)
|
|
264
|
+
: getRequirementControllerRoundRelay(store, requirementId!);
|
|
265
|
+
const legacyStartedDispatch = Boolean(
|
|
266
|
+
relay
|
|
267
|
+
&& (relay.providerDispatchAttempt ?? 0) >= 1
|
|
268
|
+
&& relay.providerDispatchEffectId === effect.effectId
|
|
269
|
+
&& (
|
|
270
|
+
(relay.status === 'blocked' && controllerRoundBlockerClass(relay) === 'provider_dispatch_outcome_unknown')
|
|
271
|
+
|| (relay.status === 'dispatched' && Boolean(relay.providerDispatchReceiptId))
|
|
272
|
+
)
|
|
273
|
+
);
|
|
274
|
+
if (!relay || !legacyStartedDispatch) return undefined;
|
|
275
|
+
const boundary = workflowSupervisorBoundaryForWork(store, relay.originWorkId);
|
|
276
|
+
if (boundary.status !== 'outer_turn'
|
|
277
|
+
|| boundary.conversationId !== task.conversationId
|
|
278
|
+
|| boundary.conversationUrl !== task.conversationUrl) return undefined;
|
|
279
|
+
return {
|
|
280
|
+
generation: 1,
|
|
281
|
+
dispatchId: `controller-round:${relay.relayScopeId}:${relay.providerDispatchAttempt}`,
|
|
282
|
+
evidence: {
|
|
283
|
+
surface: 'controller_round_reconciliation',
|
|
284
|
+
inherited_provider_dispatch: true,
|
|
285
|
+
relay_scope_id: relay.relayScopeId,
|
|
286
|
+
provider_dispatch_attempt: relay.providerDispatchAttempt,
|
|
287
|
+
...(relay.providerDispatchStartedAt ? { provider_dispatch_started_at: relay.providerDispatchStartedAt } : {}),
|
|
288
|
+
},
|
|
289
|
+
};
|
|
290
|
+
},
|
|
291
|
+
projectScopeForTask: (task) => {
|
|
292
|
+
const repoId = workflowSupervisorContractText(task, 'repo_id');
|
|
293
|
+
const taskControllerHome = workflowSupervisorContractText(task, 'controller_home');
|
|
294
|
+
if (!repoId) return undefined;
|
|
295
|
+
if (taskControllerHome && taskControllerHome !== controllerHome) return undefined;
|
|
296
|
+
if (!taskControllerHome && task.continuationPolicy.kind !== 'standalone_supervisor') return undefined;
|
|
297
|
+
try {
|
|
298
|
+
const repository = getRepository(repoId, controllerHome);
|
|
299
|
+
const aliases = workflowSupervisorProjectAliases(task);
|
|
300
|
+
return {
|
|
301
|
+
title: repository.displayName,
|
|
302
|
+
...(aliases.length > 0 ? { aliases } : {}),
|
|
303
|
+
repoId,
|
|
304
|
+
controllerHome,
|
|
305
|
+
};
|
|
306
|
+
} catch { return undefined; }
|
|
307
|
+
},
|
|
308
|
+
browserTaskActive,
|
|
309
|
+
bootstrapConversationBound: (task, context) => {
|
|
310
|
+
const repoId = workflowSupervisorContractText(task, 'repo_id');
|
|
311
|
+
const workId = workflowSupervisorContractText(task, 'work_id');
|
|
312
|
+
const taskControllerHome = workflowSupervisorContractText(task, 'controller_home');
|
|
313
|
+
if (!repoId || !workId || taskControllerHome !== controllerHome) return;
|
|
314
|
+
const existing = getChatgptWorkConversationBinding({ controllerHome, repoId }, workId);
|
|
315
|
+
if (existing && existing.conversationId !== task.conversationId) {
|
|
316
|
+
if (!context?.migratedFromConversationId || context.migratedFromConversationId !== existing.conversationId) {
|
|
317
|
+
throw new Error('WORKFLOW_SUPERVISOR_BOOTSTRAP_WORK_CONVERSATION_CONFLICT');
|
|
318
|
+
}
|
|
319
|
+
rebindChatgptWorkConversation({ controllerHome, repoId }, {
|
|
320
|
+
workId,
|
|
321
|
+
previousConversationId: existing.conversationId,
|
|
322
|
+
conversationUrl: task.conversationUrl,
|
|
323
|
+
localAlias: existing.localAlias,
|
|
324
|
+
});
|
|
325
|
+
return;
|
|
326
|
+
}
|
|
327
|
+
if (!existing) {
|
|
328
|
+
bindChatgptWorkConversation({ controllerHome, repoId }, {
|
|
329
|
+
workId,
|
|
330
|
+
conversationUrl: task.conversationUrl,
|
|
331
|
+
localAlias: 'Forge autonomous execution',
|
|
332
|
+
});
|
|
333
|
+
}
|
|
334
|
+
},
|
|
335
|
+
effectApplied: (task, effect, observation) => {
|
|
336
|
+
if (effect.kind !== 'enrollment') return;
|
|
337
|
+
const repoId = workflowSupervisorContractText(task, 'repo_id');
|
|
338
|
+
const requirementId = workflowSupervisorContractText(task, 'requirement_id');
|
|
339
|
+
const workId = repoId ? workflowSupervisorOriginWorkId(task, repoId) : undefined;
|
|
340
|
+
const taskControllerHome = workflowSupervisorContractText(task, 'controller_home');
|
|
341
|
+
if (!repoId || (!requirementId && !workId) || taskControllerHome !== controllerHome) return;
|
|
342
|
+
const store = { controllerHome, repoId };
|
|
343
|
+
const relay = workId
|
|
344
|
+
? getControllerRoundRelay(store, workId)
|
|
345
|
+
: getRequirementControllerRoundRelay(store, requirementId!);
|
|
346
|
+
if (!relay || !['dispatching', 'blocked'].includes(relay.status)) return;
|
|
347
|
+
// Receipt projection can settle only the enrolled lower effect. A newer
|
|
348
|
+
// occurrence or sibling Work must never inherit an old conversation send.
|
|
349
|
+
if ((relay.providerDispatchEffectId ?? controllerRoundProviderEffectId(relay)) !== effect.effectId) return;
|
|
350
|
+
const boundary = workflowSupervisorBoundaryForWork(store, relay.originWorkId);
|
|
351
|
+
if (boundary.status !== 'outer_turn' || boundary.conversationId !== task.conversationId) return;
|
|
352
|
+
finishControllerRoundRelayDispatch(store, {
|
|
353
|
+
workId: relay.originWorkId,
|
|
354
|
+
ok: true,
|
|
355
|
+
providerDispatchEffectId: effect.effectId,
|
|
356
|
+
providerDispatchReceiptId: `workflow-supervisor:${effect.effectId}:${observation.observationId}`,
|
|
357
|
+
});
|
|
358
|
+
},
|
|
359
|
+
};
|
|
360
|
+
}
|
|
361
|
+
export async function workflowSupervisorCurrentConversationMatchesWork(
|
|
362
|
+
options: { controllerHome: string; repoId: string },
|
|
363
|
+
workId: string,
|
|
364
|
+
): Promise<boolean> {
|
|
365
|
+
const boundary = workflowSupervisorBoundaryForWork(options, workId);
|
|
366
|
+
if (boundary.status !== 'outer_turn') return false;
|
|
367
|
+
const forgeHome = resolveWorkflowSupervisorForgeHome(options.controllerHome);
|
|
368
|
+
if (!existsSync(workflowSupervisorSocketPath(forgeHome))) return false;
|
|
369
|
+
try {
|
|
370
|
+
const current = await getWorkflowSupervisorCurrentConversation(forgeHome);
|
|
371
|
+
// The same ChatGPT conversation may be rendered with or without its Project
|
|
372
|
+
// route. Its durable conversation id, not that route, proves continuity.
|
|
373
|
+
return Boolean(current
|
|
374
|
+
&& current.conversationId === boundary.conversationId);
|
|
375
|
+
} catch {
|
|
376
|
+
return false;
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
export async function bindCurrentWorkflowSupervisorConversationForWork(
|
|
381
|
+
options: { controllerHome: string; repoId: string },
|
|
382
|
+
workId: string,
|
|
383
|
+
): Promise<
|
|
384
|
+
| { status: 'bound'; binding: ChatgptWorkConversationBinding }
|
|
385
|
+
| { status: 'not_eligible' | 'current_conversation_unbound' | 'daemon_unavailable'; reason?: string }
|
|
386
|
+
> {
|
|
387
|
+
const work = getWorkContract(options, workId);
|
|
388
|
+
if (!work || semanticWorkState(work) !== 'open') return { status: 'not_eligible' };
|
|
389
|
+
const forgeHome = resolveWorkflowSupervisorForgeHome(options.controllerHome);
|
|
390
|
+
if (!existsSync(workflowSupervisorSocketPath(forgeHome))) return { status: 'daemon_unavailable', reason: 'WORKFLOW_SUPERVISOR_DAEMON_UNAVAILABLE' };
|
|
391
|
+
const existing = getChatgptWorkConversationBinding(options, workId);
|
|
392
|
+
const current = await getWorkflowSupervisorCurrentConversation(forgeHome);
|
|
393
|
+
// Browser focus is ephemeral observation, not a second authority over an
|
|
394
|
+
// already-bound Work. When a durable exact binding exists, a missing current
|
|
395
|
+
// marker cannot revoke it; a fresh conflicting marker still fails closed.
|
|
396
|
+
if (existing) {
|
|
397
|
+
if (current && existing.conversationId !== current.conversationId) {
|
|
398
|
+
throw new Error(`WORKFLOW_SUPERVISOR_CURRENT_CONVERSATION_CONFLICT:${workId}:${existing.conversationId}:${current.conversationId}`);
|
|
399
|
+
}
|
|
400
|
+
return { status: 'bound', binding: existing };
|
|
401
|
+
}
|
|
402
|
+
if (!current) return { status: 'current_conversation_unbound', reason: 'WORKFLOW_SUPERVISOR_CURRENT_CONVERSATION_UNBOUND' };
|
|
403
|
+
const binding = bindChatgptWorkConversation(options, {
|
|
404
|
+
workId,
|
|
405
|
+
conversationUrl: current.canonicalUrl,
|
|
406
|
+
localAlias: current.title,
|
|
407
|
+
});
|
|
408
|
+
return { status: 'bound', binding };
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
export async function ensureWorkflowSupervisorEnrollmentForWork(
|
|
412
|
+
options: { controllerHome: string; repoId: string },
|
|
413
|
+
workId: string,
|
|
414
|
+
): Promise<{ status: WorkflowSupervisorEnrollmentStatus; taskId?: string; effectId?: string; reason?: string }> {
|
|
415
|
+
const boundary = workflowSupervisorBoundaryForWork(options, workId);
|
|
416
|
+
if (boundary.status === 'not_eligible') return { status: boundary.status };
|
|
417
|
+
const forgeHome = resolveWorkflowSupervisorForgeHome(options.controllerHome);
|
|
418
|
+
// Work-derived task ids are only bootstrap reservation identities. Once an
|
|
419
|
+
// exact conversation exists, the task-registration RPC returns the canonical
|
|
420
|
+
// Supervisor task already owning that conversation, including across successor Work.
|
|
421
|
+
const taskId = taskIdForWork(options.repoId, workId);
|
|
422
|
+
if (!existsSync(workflowSupervisorSocketPath(forgeHome))) return { status: 'daemon_unavailable', taskId };
|
|
423
|
+
|
|
424
|
+
// Once an exact conversation is already owned by a Supervisor task, that
|
|
425
|
+
// task is the outer-turn authority. ControllerRound is only first-admission
|
|
426
|
+
// execution context and must not regain veto power over later continuation.
|
|
427
|
+
// Read before any lower-layer admission check so a blocked/exhausted old
|
|
428
|
+
// Round cannot strand an already-enrolled exact conversation.
|
|
429
|
+
if (boundary.status === 'outer_turn') {
|
|
430
|
+
const existingAuthority = await getWorkflowSupervisorTaskByConversationId(forgeHome, boundary.conversationId);
|
|
431
|
+
if (existingAuthority) {
|
|
432
|
+
const existingRepoId = typeof existingAuthority.task.completionContract.repo_id === 'string'
|
|
433
|
+
? existingAuthority.task.completionContract.repo_id
|
|
434
|
+
: existingAuthority.task.continuationPolicy.repo_id;
|
|
435
|
+
if (typeof existingRepoId === 'string' && existingRepoId !== options.repoId) {
|
|
436
|
+
throw new Error(`WORKFLOW_SUPERVISOR_TASK_REPOSITORY_CONFLICT:${boundary.conversationId}`);
|
|
437
|
+
}
|
|
438
|
+
if (existingAuthority.terminal) {
|
|
439
|
+
// Terminal Supervisor authority must never be resurrected by a lower
|
|
440
|
+
// ControllerRound. Report the outer-turn boundary as already owned so
|
|
441
|
+
// Scheduler/Controller composition cannot create another provider turn.
|
|
442
|
+
return {
|
|
443
|
+
status: 'enrolled',
|
|
444
|
+
taskId: existingAuthority.task.taskId,
|
|
445
|
+
reason: `WORKFLOW_SUPERVISOR_TASK_TERMINAL:${existingAuthority.terminal}`,
|
|
446
|
+
};
|
|
447
|
+
}
|
|
448
|
+
const effect = await reserveWorkflowSupervisorEnrollment(forgeHome, existingAuthority.task.taskId);
|
|
449
|
+
return { status: 'enrolled', taskId: existingAuthority.task.taskId, effectId: effect.effectId };
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
const lowerLayer = workflowSupervisorLowerLayerReadyForWork(options, workId);
|
|
454
|
+
if (!lowerLayer.ready) return { status: 'lower_layer_not_ready', reason: lowerLayer.reason };
|
|
455
|
+
const work = getWorkContract(options, workId);
|
|
456
|
+
const requirement = work?.requirementId
|
|
457
|
+
? readRequirement({ controllerHome: options.controllerHome }, work.requirementId)?.value
|
|
458
|
+
: undefined;
|
|
459
|
+
const registeredTask = await registerWorkflowSupervisorTask(forgeHome, {
|
|
460
|
+
taskId,
|
|
461
|
+
// This is a durable pre-send reservation, not a conversation identity.
|
|
462
|
+
// The Computer adapter replaces it atomically after the first confirmed
|
|
463
|
+
// submission exposes ChatGPT's canonical conversation URL.
|
|
464
|
+
conversationId: boundary.status === 'outer_turn' ? boundary.conversationId : `bootstrap:${workId}`,
|
|
465
|
+
conversationUrl: boundary.status === 'outer_turn' ? boundary.conversationUrl : 'https://chatgpt.com/',
|
|
466
|
+
objective: requirement?.outcomeStatement ?? work?.objective ?? workId,
|
|
467
|
+
completionContract: {
|
|
468
|
+
kind: requirement ? 'forge_requirement_done' : 'forge_work_done',
|
|
469
|
+
controller_home: options.controllerHome,
|
|
470
|
+
repo_id: options.repoId,
|
|
471
|
+
work_id: workId,
|
|
472
|
+
...(requirement ? { requirement_id: requirement.requirementId } : {}),
|
|
473
|
+
},
|
|
474
|
+
continuationPolicy: {
|
|
475
|
+
kind: 'forge_goal_outer_turn',
|
|
476
|
+
...(boundary.status === 'outer_turn'
|
|
477
|
+
? { exact_conversation_id: boundary.conversationId, exact_conversation_url: boundary.conversationUrl }
|
|
478
|
+
: { bootstrap: true }),
|
|
479
|
+
outer_turn_owner: 'workflow_supervisor',
|
|
480
|
+
},
|
|
481
|
+
userBlockerPolicy: {
|
|
482
|
+
kind: requirement ? 'forge_requirement_waiting_for_user' : 'forge_work_waiting_for_user',
|
|
483
|
+
controller_home: options.controllerHome,
|
|
484
|
+
repo_id: options.repoId,
|
|
485
|
+
work_id: workId,
|
|
486
|
+
...(requirement ? { requirement_id: requirement.requirementId } : {}),
|
|
487
|
+
},
|
|
488
|
+
});
|
|
489
|
+
const effect = await reserveWorkflowSupervisorEnrollment(forgeHome, registeredTask.taskId, lowerLayer.providerEffectId);
|
|
490
|
+
// Runtime owns only enrollment. Provider send/reconcile/re-dispatch budgeting
|
|
491
|
+
// stays entirely inside the Supervisor effect ledger and Browser adapter.
|
|
492
|
+
return { status: 'enrolled', taskId: registeredTask.taskId, effectId: effect.effectId };
|
|
493
|
+
}
|