@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
|
@@ -8,10 +8,11 @@ import { listRepositories, repositoryCheckoutLifecycle, selectRepositoryCheckout
|
|
|
8
8
|
import { repositoryGitStatus } from '../../../cli/repositories/structured-git';
|
|
9
9
|
import { ensureManagedWorkspace } from '../../execution/managed-workspace';
|
|
10
10
|
import { getControllerSession } from '../../../../packages/kernel/controller/api/index';
|
|
11
|
-
import { getWorkContract, recordWorkEvidenceState,
|
|
11
|
+
import { getWorkContract, recordWorkEvidenceState, transitionWorkContractPhase, updateWorkContract } from '../../../../packages/kernel/work/api/index';
|
|
12
12
|
import { gitCommitAtRef, gitWorktreeSnapshot } from './work-lifecycle-audit';
|
|
13
|
-
import { findWorkPathScopeViolation } from './work-path-scope';
|
|
14
13
|
import { readWorkHandle, writeWorkHandle, type WorkHandleState } from './work-handle-store';
|
|
14
|
+
import { rearmFailedPreservedWorkHandle } from './work-handle-authority';
|
|
15
|
+
import { hasSettledWorkDeliveryReceipt } from './work-completion-authority';
|
|
15
16
|
|
|
16
17
|
export interface RetainedWorkResumeIdentity {
|
|
17
18
|
principalId: string;
|
|
@@ -19,16 +20,6 @@ export interface RetainedWorkResumeIdentity {
|
|
|
19
20
|
controllerInstanceId: string;
|
|
20
21
|
}
|
|
21
22
|
|
|
22
|
-
export interface ReauthorizeRetainedCancelledWorkInput {
|
|
23
|
-
controllerHome: string;
|
|
24
|
-
repository: RepositoryRecord;
|
|
25
|
-
workId: string;
|
|
26
|
-
identity: RetainedWorkResumeIdentity;
|
|
27
|
-
requestedBy?: string;
|
|
28
|
-
approvalConfirmed?: boolean;
|
|
29
|
-
prepareDependencies?: boolean;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
23
|
export interface EnsureRunningRepositoryWorkCheckoutInput {
|
|
33
24
|
controllerHome: string;
|
|
34
25
|
repository: RepositoryRecord;
|
|
@@ -72,7 +63,7 @@ function restoreArchivedBlockedDeliveryCheckout(input: {
|
|
|
72
63
|
const { controllerHome, repository, work, handle, identity } = input;
|
|
73
64
|
const receipt = handle.cleanupReceipt;
|
|
74
65
|
if (handle.state !== 'cleaned' || receipt?.terminalOutcome !== 'blocked_terminal') return undefined;
|
|
75
|
-
if (work.completionReceipt || work.completionOutcome || work.
|
|
66
|
+
if (work.completionReceipt || work.completionOutcome || work.dispatchState !== 'blocked' || work.phase !== 'delivery') {
|
|
76
67
|
throw new Error(`WORK_CONTINUE_ARCHIVED_DELIVERY_LIFECYCLE_CONFLICT: ${work.workId}`);
|
|
77
68
|
}
|
|
78
69
|
if (!['none', 'partial', 'valid', 'stale'].includes(work.evidenceState)) {
|
|
@@ -150,10 +141,6 @@ function restoreArchivedBlockedDeliveryCheckout(input: {
|
|
|
150
141
|
if (!changed.ok) throw new Error(`WORK_CONTINUE_ARCHIVED_DELIVERY_DIFF_UNAVAILABLE: ${work.workId}`);
|
|
151
142
|
const changedPaths = normalizedPaths(changed.stdout.split(/\r?\n/));
|
|
152
143
|
if (changedPaths.length === 0) throw new Error(`WORK_CONTINUE_ARCHIVED_DELIVERY_ZERO_DELTA: ${work.workId}`);
|
|
153
|
-
const scopeViolation = findWorkPathScopeViolation(work, changedPaths);
|
|
154
|
-
if (scopeViolation) {
|
|
155
|
-
throw new Error(`WORK_CONTINUE_ARCHIVED_DELIVERY_SCOPE_VIOLATION: ${scopeViolation.kind}:${scopeViolation.path}`);
|
|
156
|
-
}
|
|
157
144
|
const recordedChangedPaths = normalizedPaths(work.scopeEvidence?.actualChangedPaths ?? []);
|
|
158
145
|
if (recordedChangedPaths.length > 0 && JSON.stringify(recordedChangedPaths) !== JSON.stringify(changedPaths)) {
|
|
159
146
|
throw new Error(`WORK_CONTINUE_ARCHIVED_DELIVERY_PATH_IDENTITY_MISMATCH: ${work.workId}`);
|
|
@@ -167,6 +154,7 @@ function restoreArchivedBlockedDeliveryCheckout(input: {
|
|
|
167
154
|
const workspace = ensureManagedWorkspace(controllerHome, repository, {
|
|
168
155
|
requestId: `${work.workId}:archived-delivery-recovery:${candidateRevision}`,
|
|
169
156
|
title: `${work.objective} archived delivery recovery`,
|
|
157
|
+
associatedWorkId: work.workId,
|
|
170
158
|
branchName,
|
|
171
159
|
baseRef: candidateRevision,
|
|
172
160
|
prepareDependencies: input.prepareDependencies === true,
|
|
@@ -193,7 +181,6 @@ function restoreArchivedBlockedDeliveryCheckout(input: {
|
|
|
193
181
|
});
|
|
194
182
|
transitionWorkContractPhase(store, work.workId, {
|
|
195
183
|
phase: 'verification',
|
|
196
|
-
status: 'running',
|
|
197
184
|
state: 'active',
|
|
198
185
|
dispatchState: 'running',
|
|
199
186
|
summary: `Archived candidate ${candidateRevision} was rehydrated from verified blocked-terminal preservation; fresh verification is required before delivery.`,
|
|
@@ -225,114 +212,145 @@ function restoreArchivedBlockedDeliveryCheckout(input: {
|
|
|
225
212
|
}
|
|
226
213
|
|
|
227
214
|
/**
|
|
228
|
-
*
|
|
229
|
-
*
|
|
230
|
-
*
|
|
231
|
-
*
|
|
215
|
+
* Rehydrate a committed candidate whose validation process disappeared before
|
|
216
|
+
* delivery/cleanup. The candidate is safe to revisit only when the durable
|
|
217
|
+
* WorkHandle, Git object database, and recorded changed-path identity all agree.
|
|
218
|
+
* A missing cleanup receipt is intentional here: this is a pre-delivery
|
|
219
|
+
* recovery, not a second delivery authority.
|
|
232
220
|
*/
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
if (checkoutActive && worktreePresent) return { reconstructedCheckout: false };
|
|
253
|
-
if (checkoutActive) throw new Error(`WORK_CONTINUE_CHECKOUT_PRESERVATION_AMBIGUOUS: ${workId}`);
|
|
221
|
+
function restoreArchivedPendingCandidateCheckout(input: {
|
|
222
|
+
controllerHome: string;
|
|
223
|
+
repository: RepositoryRecord;
|
|
224
|
+
work: NonNullable<ReturnType<typeof getWorkContract>>;
|
|
225
|
+
handle: WorkHandleState;
|
|
226
|
+
identity: RetainedWorkResumeIdentity;
|
|
227
|
+
}): { reconstructedCheckout: boolean } | undefined {
|
|
228
|
+
const { controllerHome, repository, work, handle, identity } = input;
|
|
229
|
+
if (work.semanticState !== 'open') return undefined;
|
|
230
|
+
if (work.phase !== 'verification' || work.workKind !== 'repository_change') return undefined;
|
|
231
|
+
if (handle.state !== 'failed'
|
|
232
|
+
|| handle.finalization.validation !== 'failed'
|
|
233
|
+
|| handle.finalization.commit !== 'done'
|
|
234
|
+
|| handle.finalization.merge !== 'pending'
|
|
235
|
+
|| handle.finalization.branchCleanup !== 'pending'
|
|
236
|
+
|| handle.finalization.worktreeCleanup !== 'pending'
|
|
237
|
+
|| handle.cleanupReceipt
|
|
238
|
+
|| work.completionReceipt
|
|
239
|
+
|| work.completionOutcome) return undefined;
|
|
254
240
|
|
|
255
|
-
const
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
241
|
+
const candidateRevision = handle.expectedHead?.trim();
|
|
242
|
+
const baseRevisionRaw = work.baseRevision?.trim() || handle.baseCommit?.trim();
|
|
243
|
+
const recordedChangedPaths = normalizedPaths(work.scopeEvidence?.actualChangedPaths ?? []);
|
|
244
|
+
if (!candidateRevision || !baseRevisionRaw || recordedChangedPaths.length === 0) {
|
|
245
|
+
return undefined;
|
|
259
246
|
}
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
247
|
+
|
|
248
|
+
const candidateCommit = gitCommitAtRef(repository.canonicalRoot, candidateRevision);
|
|
249
|
+
if (candidateCommit !== candidateRevision) {
|
|
250
|
+
throw new Error(`WORK_CONTINUE_COMMITTED_CANDIDATE_MISSING: ${work.workId}`);
|
|
263
251
|
}
|
|
264
|
-
const
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
if (['committed', 'merged', 'cleaned', 'failed_terminal_cleanup'].includes(handle.state)
|
|
269
|
-
|| handle.finalization.commit === 'done'
|
|
270
|
-
|| handle.finalization.merge === 'done'
|
|
271
|
-
|| handle.cleanupReceipt?.complete === true) {
|
|
272
|
-
throw new Error(`WORK_CONTINUE_DELIVERY_OR_CLEANUP_CONFLICT: ${workId}`);
|
|
252
|
+
const baseRevision = gitCommitAtRef(repository.canonicalRoot, baseRevisionRaw);
|
|
253
|
+
if (!baseRevision) throw new Error(`WORK_CONTINUE_COMMITTED_CANDIDATE_BASE_MISSING: ${work.workId}`);
|
|
254
|
+
if (!git(repository.canonicalRoot, ['merge-base', '--is-ancestor', baseRevision, candidateRevision]).ok) {
|
|
255
|
+
throw new Error(`WORK_CONTINUE_COMMITTED_CANDIDATE_REVISION_AMBIGUOUS: ${work.workId}`);
|
|
273
256
|
}
|
|
274
257
|
|
|
275
|
-
const
|
|
276
|
-
if (!
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|| work.evidenceState !== 'none') {
|
|
280
|
-
throw new Error(`WORK_CONTINUE_ZERO_DELTA_PROOF_REQUIRED: ${workId}`);
|
|
281
|
-
}
|
|
282
|
-
const recordedBase = work.baseRevision?.trim();
|
|
283
|
-
if (!recordedBase) throw new Error(`WORK_CONTINUE_BASE_REVISION_REQUIRED: ${workId}`);
|
|
284
|
-
const baseRevision = gitCommitAtRef(repository.canonicalRoot, recordedBase);
|
|
285
|
-
if (!baseRevision) throw new Error(`WORK_CONTINUE_BASE_REVISION_MISSING: ${workId}`);
|
|
286
|
-
const handleBase = handle.baseCommit ? gitCommitAtRef(repository.canonicalRoot, handle.baseCommit) : undefined;
|
|
287
|
-
const handleHead = handle.expectedHead ? gitCommitAtRef(repository.canonicalRoot, handle.expectedHead) : undefined;
|
|
288
|
-
if ((handle.baseCommit && handleBase !== baseRevision) || (handle.expectedHead && handleHead !== baseRevision)) {
|
|
289
|
-
throw new Error(`WORK_CONTINUE_REVISION_AMBIGUOUS: ${workId}`);
|
|
258
|
+
const targetBranch = handle.deliveryTargetBranch?.trim() || repository.defaultBranch?.trim();
|
|
259
|
+
if (!targetBranch) throw new Error(`WORK_CONTINUE_COMMITTED_CANDIDATE_TARGET_REQUIRED: ${work.workId}`);
|
|
260
|
+
if (git(repository.canonicalRoot, ['merge-base', '--is-ancestor', candidateRevision, targetBranch]).ok) {
|
|
261
|
+
throw new Error(`WORK_CONTINUE_COMMITTED_CANDIDATE_ALREADY_INTEGRATED: ${work.workId}`);
|
|
290
262
|
}
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
263
|
+
const changed = git(repository.canonicalRoot, ['diff', '--name-only', `${baseRevision}..${candidateRevision}`]);
|
|
264
|
+
if (!changed.ok) throw new Error(`WORK_CONTINUE_COMMITTED_CANDIDATE_DIFF_UNAVAILABLE: ${work.workId}`);
|
|
265
|
+
const candidateChangedPaths = normalizedPaths(changed.stdout.split(/\r?\n/));
|
|
266
|
+
if (candidateChangedPaths.length === 0) throw new Error(`WORK_CONTINUE_COMMITTED_CANDIDATE_ZERO_DELTA: ${work.workId}`);
|
|
267
|
+
|
|
268
|
+
// A delivery candidate can contain a canonical target advancement as a
|
|
269
|
+
// merge parent. Only the unique parent already reachable from the current
|
|
270
|
+
// target branch may be treated as target history; the Work-owned delta is
|
|
271
|
+
// then measured from that parent to the candidate. This keeps unrelated
|
|
272
|
+
// target changes out of Work scope evidence while still requiring the exact
|
|
273
|
+
// candidate tree and recorded path identity to agree.
|
|
274
|
+
let workOwnedChangedPaths = candidateChangedPaths;
|
|
275
|
+
let deliveryBaseCommit = baseRevision;
|
|
276
|
+
const parents = git(repository.canonicalRoot, ['rev-list', '--parents', '-n', '1', candidateRevision]);
|
|
277
|
+
if (parents.ok) {
|
|
278
|
+
const parentRevisions = parents.stdout.split(/\s+/).slice(1).filter(Boolean);
|
|
279
|
+
const targetParents = parentRevisions.filter((parent) =>
|
|
280
|
+
git(repository.canonicalRoot, ['merge-base', '--is-ancestor', parent, targetBranch]).ok,
|
|
281
|
+
);
|
|
282
|
+
if (parentRevisions.length === 2 && targetParents.length === 1 && targetParents[0] !== baseRevision) {
|
|
283
|
+
const targetParent = targetParents[0];
|
|
284
|
+
const targetRelative = git(repository.canonicalRoot, ['diff', '--name-only', `${targetParent}..${candidateRevision}`]);
|
|
285
|
+
if (!targetRelative.ok) throw new Error(`WORK_CONTINUE_COMMITTED_CANDIDATE_TARGET_RELATIVE_DIFF_UNAVAILABLE: ${work.workId}`);
|
|
286
|
+
workOwnedChangedPaths = normalizedPaths(targetRelative.stdout.split(/\r?\n/));
|
|
287
|
+
if (workOwnedChangedPaths.length === 0) throw new Error(`WORK_CONTINUE_COMMITTED_CANDIDATE_ZERO_WORK_DELTA: ${work.workId}`);
|
|
288
|
+
deliveryBaseCommit = targetParent;
|
|
289
|
+
const expectedRecordedPaths = normalizedPaths([...workOwnedChangedPaths, ...normalizedPaths(
|
|
290
|
+
git(repository.canonicalRoot, ['diff', '--name-only', `${baseRevision}..${targetParent}`]).stdout.split(/\r?\n/),
|
|
291
|
+
)]);
|
|
292
|
+
if (JSON.stringify(recordedChangedPaths) !== JSON.stringify(candidateChangedPaths)
|
|
293
|
+
&& JSON.stringify(recordedChangedPaths) !== JSON.stringify(workOwnedChangedPaths)
|
|
294
|
+
&& JSON.stringify(recordedChangedPaths) !== JSON.stringify(expectedRecordedPaths)) {
|
|
295
|
+
throw new Error(`WORK_CONTINUE_COMMITTED_CANDIDATE_PATH_IDENTITY_MISMATCH: ${work.workId}`);
|
|
296
|
+
}
|
|
295
297
|
}
|
|
296
298
|
}
|
|
297
|
-
if (
|
|
298
|
-
|
|
299
|
-
if (!retainedSnapshot || !retainedSnapshot.clean || retainedSnapshot.head !== baseRevision || (handle.branch && retainedSnapshot.branch !== handle.branch)) {
|
|
300
|
-
throw new Error(`WORK_CONTINUE_ZERO_DELTA_PHYSICAL_CONFLICT: ${workId}`);
|
|
301
|
-
}
|
|
299
|
+
if (deliveryBaseCommit === baseRevision && JSON.stringify(recordedChangedPaths) !== JSON.stringify(candidateChangedPaths)) {
|
|
300
|
+
throw new Error(`WORK_CONTINUE_COMMITTED_CANDIDATE_PATH_IDENTITY_MISMATCH: ${work.workId}`);
|
|
302
301
|
}
|
|
303
302
|
|
|
304
|
-
const branchName = `work/resume-${workId.replace(/[^A-Za-z0-9._-]+/g, '-').slice(0,
|
|
303
|
+
const branchName = `work/resume-pending-candidate-${work.workId.replace(/[^A-Za-z0-9._-]+/g, '-').slice(0, 34)}-${candidateRevision.slice(0, 12)}`;
|
|
305
304
|
const existingResumeBranch = gitCommitAtRef(repository.canonicalRoot, `refs/heads/${branchName}`);
|
|
306
|
-
if (existingResumeBranch && existingResumeBranch !==
|
|
307
|
-
throw new Error(`
|
|
305
|
+
if (existingResumeBranch && existingResumeBranch !== candidateRevision) {
|
|
306
|
+
throw new Error(`WORK_CONTINUE_COMMITTED_CANDIDATE_BRANCH_CONFLICT: ${work.workId}`);
|
|
308
307
|
}
|
|
309
308
|
const workspace = ensureManagedWorkspace(controllerHome, repository, {
|
|
310
|
-
requestId: `${workId}:
|
|
311
|
-
title: `${work.objective}
|
|
309
|
+
requestId: `${work.workId}:pending-candidate-recovery:${candidateRevision}`,
|
|
310
|
+
title: `${work.objective} pending candidate recovery`,
|
|
311
|
+
associatedWorkId: work.workId,
|
|
312
312
|
branchName,
|
|
313
|
-
baseRef:
|
|
314
|
-
prepareDependencies: input.prepareDependencies === true,
|
|
313
|
+
baseRef: candidateRevision,
|
|
315
314
|
});
|
|
316
315
|
if (!workspace.managed || !workspace.checkoutId || !workspace.root || !workspace.branch) {
|
|
317
|
-
throw new Error(`
|
|
316
|
+
throw new Error(`WORK_CONTINUE_COMMITTED_CANDIDATE_RECONSTRUCTION_FAILED: ${work.workId}`);
|
|
318
317
|
}
|
|
319
318
|
const refreshedRepository = listRepositories(controllerHome, { includeRemoved: true })
|
|
320
319
|
.find((candidate) => candidate.repoId === repository.repoId);
|
|
321
|
-
if (!refreshedRepository) throw new Error(`WORK_CONTINUE_REPOSITORY_MISSING: ${workId}`);
|
|
320
|
+
if (!refreshedRepository) throw new Error(`WORK_CONTINUE_REPOSITORY_MISSING: ${work.workId}`);
|
|
322
321
|
const reconstructed = selectRepositoryCheckout(refreshedRepository, workspace.checkoutId);
|
|
323
322
|
const reconstructedStatus = repositoryGitStatus(reconstructed);
|
|
324
|
-
if (!reconstructedStatus.clean || reconstructedStatus.head !==
|
|
325
|
-
throw new Error(`
|
|
323
|
+
if (!reconstructedStatus.clean || reconstructedStatus.head !== candidateRevision || reconstructedStatus.branch !== workspace.branch) {
|
|
324
|
+
throw new Error(`WORK_CONTINUE_COMMITTED_CANDIDATE_RECONSTRUCTION_REVISION_MISMATCH: ${work.workId}`);
|
|
326
325
|
}
|
|
327
326
|
|
|
328
|
-
|
|
327
|
+
const at = new Date().toISOString();
|
|
328
|
+
const store = { controllerHome, repoId: repository.repoId };
|
|
329
|
+
updateWorkContract(store, work.workId, {
|
|
329
330
|
checkoutId: workspace.checkoutId,
|
|
330
331
|
worktreeRef: workspace.root,
|
|
331
|
-
baseRevision,
|
|
332
332
|
controllerInstanceId: identity.controllerInstanceId,
|
|
333
|
-
|
|
333
|
+
...(deliveryBaseCommit !== baseRevision
|
|
334
|
+
? {
|
|
335
|
+
scopeEvidence: {
|
|
336
|
+
initialLikelyPaths: work.scopeEvidence?.initialLikelyPaths ?? [],
|
|
337
|
+
inspectedPaths: work.scopeEvidence?.inspectedPaths ?? [],
|
|
338
|
+
actualChangedPaths: workOwnedChangedPaths,
|
|
339
|
+
recordedAt: at,
|
|
340
|
+
},
|
|
341
|
+
}
|
|
342
|
+
: {}),
|
|
343
|
+
continuationPrompt: `Continue work ${repository.repoId}: ${work.objective.slice(0, 500)}. Forge rehydrated exact pending candidate ${candidateRevision}; rerun verification before delivery.`,
|
|
334
344
|
});
|
|
335
|
-
|
|
345
|
+
transitionWorkContractPhase(store, work.workId, {
|
|
346
|
+
phase: 'verification',
|
|
347
|
+
state: 'active',
|
|
348
|
+
dispatchState: 'running',
|
|
349
|
+
summary: `Pending candidate ${candidateRevision} was rehydrated after validation-process loss; fresh verification is required before delivery.`,
|
|
350
|
+
});
|
|
351
|
+
if (work.evidenceState === 'partial' || work.evidenceState === 'valid') {
|
|
352
|
+
recordWorkEvidenceState(store, work.workId, 'stale');
|
|
353
|
+
}
|
|
336
354
|
writeWorkHandle(controllerHome, {
|
|
337
355
|
...handle,
|
|
338
356
|
principalId: identity.principalId,
|
|
@@ -341,169 +359,165 @@ export function ensureRunningRepositoryWorkCheckout(
|
|
|
341
359
|
worktreePath: workspace.root,
|
|
342
360
|
branch: workspace.branch,
|
|
343
361
|
sourceCheckoutId: repository.activeCheckoutId,
|
|
362
|
+
deliveryTargetBranch: targetBranch,
|
|
344
363
|
managedWorktree: true,
|
|
345
364
|
baseCommit: baseRevision,
|
|
346
|
-
deliveryBaseCommit
|
|
347
|
-
expectedHead:
|
|
348
|
-
state: '
|
|
365
|
+
deliveryBaseCommit,
|
|
366
|
+
expectedHead: candidateRevision,
|
|
367
|
+
state: 'validating',
|
|
349
368
|
validatedInputFingerprint: undefined,
|
|
350
369
|
failureReason: undefined,
|
|
351
370
|
cleanupReceipt: undefined,
|
|
352
|
-
|
|
353
|
-
|
|
371
|
+
updatedAt: at,
|
|
372
|
+
finalization: {
|
|
373
|
+
validation: 'pending',
|
|
374
|
+
commit: 'done',
|
|
375
|
+
merge: 'pending',
|
|
376
|
+
branchCleanup: 'pending',
|
|
377
|
+
worktreeCleanup: 'pending',
|
|
378
|
+
},
|
|
354
379
|
});
|
|
355
380
|
return { reconstructedCheckout: true };
|
|
356
381
|
}
|
|
357
382
|
|
|
358
383
|
/**
|
|
359
|
-
*
|
|
360
|
-
*
|
|
361
|
-
*
|
|
362
|
-
*
|
|
384
|
+
* Re-establish the checkout binding for a still-running isolated Work only
|
|
385
|
+
* when durable and Git evidence prove that the missing checkout carried no
|
|
386
|
+
* repository delta. Any dirty, divergent, committed, or cleaned evidence
|
|
387
|
+
* fails closed so recovery never becomes permission to discard source.
|
|
363
388
|
*/
|
|
364
|
-
export function
|
|
365
|
-
input:
|
|
389
|
+
export function ensureRunningRepositoryWorkCheckout(
|
|
390
|
+
input: EnsureRunningRepositoryWorkCheckoutInput,
|
|
366
391
|
): { reconstructedCheckout: boolean } {
|
|
367
392
|
const { controllerHome, repository, workId, identity } = input;
|
|
368
393
|
const store = { controllerHome, repoId: repository.repoId };
|
|
369
|
-
|
|
370
|
-
if (!work || work.
|
|
371
|
-
if (
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
}
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
if (work
|
|
382
|
-
if (work.reconciliations.length > 0) throw new Error(`WORK_CANCELLED_RESUME_DELIVERY_HISTORY_AMBIGUOUS: ${workId}`);
|
|
383
|
-
if (work.phase !== 'cleanup' || work.phaseEvidence.cleanup.state !== 'skipped' || work.phaseEvidence.cleanup.source !== 'recorded') {
|
|
384
|
-
throw new Error(`WORK_CANCELLED_RESUME_HISTORY_AMBIGUOUS: ${workId}`);
|
|
385
|
-
}
|
|
386
|
-
if (work.workKind !== 'repository_change' || work.worktreePolicy.required !== true) {
|
|
387
|
-
throw new Error(`WORK_CANCELLED_RESUME_ISOLATED_REPOSITORY_WORK_REQUIRED: ${workId}`);
|
|
388
|
-
}
|
|
394
|
+
const work = getWorkContract(store, workId);
|
|
395
|
+
if (!work || work.semanticState !== 'open') return { reconstructedCheckout: false };
|
|
396
|
+
if (work.workKind !== 'repository_change') return { reconstructedCheckout: false };
|
|
397
|
+
const handle = readWorkHandle(controllerHome, repository.repoId, workId);
|
|
398
|
+
const hasManagedPlacement = handle?.managedWorktree === true
|
|
399
|
+
&& Boolean(handle.checkoutId?.trim())
|
|
400
|
+
&& Boolean(handle.worktreePath?.trim());
|
|
401
|
+
if (work.worktreePolicy.required !== true && !hasManagedPlacement) return { reconstructedCheckout: false };
|
|
402
|
+
// A settled physical delivery may intentionally outlive its managed checkout
|
|
403
|
+
// while semantic Work remains open. Do not reconstruct or reject source that
|
|
404
|
+
// the finalizer has already integrated and cleaned; Controller semantic
|
|
405
|
+
// judgment is the only remaining authority.
|
|
406
|
+
if (hasSettledWorkDeliveryReceipt(work)) return { reconstructedCheckout: false };
|
|
389
407
|
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
throw new Error(`WORK_CANCELLED_RESUME_HANDLE_IDENTITY_MISMATCH: ${workId}`);
|
|
394
|
-
}
|
|
395
|
-
if (handle.principalId !== identity.principalId) throw new Error(`WORK_CANCELLED_RESUME_HANDLE_PRINCIPAL_MISMATCH: ${workId}`);
|
|
396
|
-
if (['committed', 'merged', 'cleaned', 'failed_terminal_cleanup'].includes(handle.state)
|
|
397
|
-
|| handle.finalization.commit === 'done'
|
|
398
|
-
|| handle.finalization.merge === 'done'
|
|
399
|
-
|| handle.cleanupReceipt?.complete === true) {
|
|
400
|
-
throw new Error(`WORK_CANCELLED_RESUME_DELIVERY_OR_CLEANUP_CONFLICT: ${workId}`);
|
|
401
|
-
}
|
|
402
|
-
}
|
|
408
|
+
const recordedCheckoutId = handle?.checkoutId?.trim() || work.checkoutId?.trim();
|
|
409
|
+
const recordedWorktree = handle?.worktreePath?.trim() || work.worktreeRef?.trim();
|
|
410
|
+
if (!recordedCheckoutId || !recordedWorktree) return { reconstructedCheckout: false };
|
|
403
411
|
|
|
404
412
|
const registryRepository = listRepositories(controllerHome, { includeRemoved: true })
|
|
405
413
|
.find((candidate) => candidate.repoId === repository.repoId);
|
|
406
|
-
if (!registryRepository) throw new Error(`
|
|
407
|
-
const
|
|
408
|
-
const
|
|
409
|
-
const
|
|
410
|
-
|
|
411
|
-
:
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
throw new Error(`WORK_CANCELLED_RESUME_CHECKOUT_REUSED: ${workId}`);
|
|
419
|
-
}
|
|
420
|
-
if (!handle) throw new Error(`WORK_CANCELLED_RESUME_HANDLE_REQUIRED: ${workId}`);
|
|
421
|
-
if (handle.checkoutId !== recordedCheckoutId || resolve(handle.worktreePath) !== resolve(recordedWorktree)) {
|
|
422
|
-
throw new Error(`WORK_CANCELLED_RESUME_CHECKOUT_OWNERSHIP_MISMATCH: ${workId}`);
|
|
423
|
-
}
|
|
424
|
-
const status = repositoryGitStatus(retained);
|
|
425
|
-
if (!status.branch || status.branch !== handle.branch) throw new Error(`WORK_CANCELLED_RESUME_BRANCH_OWNERSHIP_MISMATCH: ${workId}`);
|
|
426
|
-
writeWorkHandle(controllerHome, {
|
|
427
|
-
...handle,
|
|
414
|
+
if (!registryRepository) throw new Error(`WORK_CONTINUE_REPOSITORY_MISSING: ${workId}`);
|
|
415
|
+
const checkoutRecord = registryRepository.checkouts.find((candidate) => candidate.checkoutId === recordedCheckoutId);
|
|
416
|
+
const checkoutActive = checkoutRecord ? repositoryCheckoutLifecycle(checkoutRecord) === 'active' : false;
|
|
417
|
+
const worktreePresent = existsSync(recordedWorktree);
|
|
418
|
+
if (checkoutActive && worktreePresent) {
|
|
419
|
+
if (!handle || handle.state !== 'failed') return { reconstructedCheckout: false };
|
|
420
|
+
rearmFailedPreservedWorkHandle({
|
|
421
|
+
controllerHome,
|
|
422
|
+
repository,
|
|
423
|
+
workId,
|
|
424
|
+
contract: work,
|
|
425
|
+
handle,
|
|
428
426
|
principalId: identity.principalId,
|
|
429
427
|
sessionId: identity.sessionId,
|
|
430
|
-
updatedAt: new Date().toISOString(),
|
|
431
|
-
});
|
|
432
|
-
resumeRetainedCancelledWorkContract(store, workId, {
|
|
433
|
-
principalId: identity.principalId,
|
|
434
|
-
controllerInstanceId: identity.controllerInstanceId,
|
|
435
|
-
summary: 'Explicit current user re-authorized the same retained cancelled Work; exact managed checkout ownership was revalidated.',
|
|
436
428
|
});
|
|
437
429
|
return { reconstructedCheckout: false };
|
|
438
430
|
}
|
|
431
|
+
if (checkoutActive) throw new Error(`WORK_CONTINUE_CHECKOUT_PRESERVATION_AMBIGUOUS: ${workId}`);
|
|
439
432
|
|
|
440
|
-
if (
|
|
441
|
-
if (
|
|
433
|
+
if (!handle) throw new Error(`WORK_CONTINUE_HANDLE_REQUIRED: ${workId}`);
|
|
434
|
+
if (handle.repositoryId !== repository.repoId || (handle.workContractId && handle.workContractId !== workId)) {
|
|
435
|
+
throw new Error(`WORK_CONTINUE_HANDLE_IDENTITY_MISMATCH: ${workId}`);
|
|
436
|
+
}
|
|
437
|
+
if (handle.principalId !== identity.principalId) throw new Error(`WORK_CONTINUE_HANDLE_PRINCIPAL_MISMATCH: ${workId}`);
|
|
438
|
+
if (handle.checkoutId !== recordedCheckoutId || resolve(handle.worktreePath) !== resolve(recordedWorktree)) {
|
|
439
|
+
throw new Error(`WORK_CONTINUE_CHECKOUT_OWNERSHIP_MISMATCH: ${workId}`);
|
|
440
|
+
}
|
|
441
|
+
const archivedDelivery = restoreArchivedBlockedDeliveryCheckout({
|
|
442
|
+
controllerHome, repository, work, handle, identity, prepareDependencies: input.prepareDependencies,
|
|
443
|
+
});
|
|
444
|
+
if (archivedDelivery) return archivedDelivery;
|
|
445
|
+
const pendingCandidate = restoreArchivedPendingCandidateCheckout({
|
|
446
|
+
controllerHome, repository, work, handle, identity,
|
|
447
|
+
});
|
|
448
|
+
if (pendingCandidate) return pendingCandidate;
|
|
449
|
+
if (['committed', 'merged', 'cleaned', 'failed_terminal_cleanup'].includes(handle.state)
|
|
450
|
+
|| handle.finalization.commit === 'done'
|
|
451
|
+
|| handle.finalization.merge === 'done'
|
|
452
|
+
|| handle.cleanupReceipt?.complete === true) {
|
|
453
|
+
throw new Error(`WORK_CONTINUE_DELIVERY_OR_CLEANUP_CONFLICT: ${workId}`);
|
|
454
|
+
}
|
|
442
455
|
|
|
443
456
|
const actualChangedPaths = work.scopeEvidence?.actualChangedPaths;
|
|
457
|
+
// `work.checks` is a declaration of verification obligations, not evidence
|
|
458
|
+
// that any verification or repository mutation already occurred. Only
|
|
459
|
+
// durable checkRefs participate in the zero-delta recovery proof.
|
|
444
460
|
if (!actualChangedPaths || actualChangedPaths.length !== 0
|
|
445
|
-
|| work.checks.length !== 0
|
|
446
461
|
|| work.checkRefs.length !== 0
|
|
447
462
|
|| work.evidenceState !== 'none') {
|
|
448
|
-
throw new Error(`
|
|
463
|
+
throw new Error(`WORK_CONTINUE_ZERO_DELTA_PROOF_REQUIRED: ${workId}`);
|
|
449
464
|
}
|
|
450
465
|
const recordedBase = work.baseRevision?.trim();
|
|
451
|
-
if (!recordedBase) throw new Error(`
|
|
466
|
+
if (!recordedBase) throw new Error(`WORK_CONTINUE_BASE_REVISION_REQUIRED: ${workId}`);
|
|
452
467
|
const baseRevision = gitCommitAtRef(repository.canonicalRoot, recordedBase);
|
|
453
|
-
if (!baseRevision) throw new Error(`
|
|
468
|
+
if (!baseRevision) throw new Error(`WORK_CONTINUE_BASE_REVISION_MISSING: ${workId}`);
|
|
454
469
|
const handleBase = handle.baseCommit ? gitCommitAtRef(repository.canonicalRoot, handle.baseCommit) : undefined;
|
|
455
470
|
const handleHead = handle.expectedHead ? gitCommitAtRef(repository.canonicalRoot, handle.expectedHead) : undefined;
|
|
456
471
|
if ((handle.baseCommit && handleBase !== baseRevision) || (handle.expectedHead && handleHead !== baseRevision)) {
|
|
457
|
-
throw new Error(`
|
|
458
|
-
}
|
|
459
|
-
if (handle.checkoutId !== recordedCheckoutId || resolve(handle.worktreePath) !== resolve(recordedWorktree)) {
|
|
460
|
-
throw new Error(`WORK_CANCELLED_RESUME_CHECKOUT_OWNERSHIP_MISMATCH: ${workId}`);
|
|
472
|
+
throw new Error(`WORK_CONTINUE_REVISION_AMBIGUOUS: ${workId}`);
|
|
461
473
|
}
|
|
462
474
|
if (handle.branch) {
|
|
463
475
|
const historicalBranchHead = gitCommitAtRef(repository.canonicalRoot, `refs/heads/${handle.branch}`);
|
|
464
476
|
if (historicalBranchHead && historicalBranchHead !== baseRevision) {
|
|
465
|
-
throw new Error(`
|
|
477
|
+
throw new Error(`WORK_CONTINUE_UNIQUE_COMMIT_CONFLICT: ${workId}`);
|
|
466
478
|
}
|
|
467
479
|
}
|
|
468
480
|
if (worktreePresent) {
|
|
469
481
|
const retainedSnapshot = gitWorktreeSnapshot(recordedWorktree);
|
|
470
482
|
if (!retainedSnapshot || !retainedSnapshot.clean || retainedSnapshot.head !== baseRevision || (handle.branch && retainedSnapshot.branch !== handle.branch)) {
|
|
471
|
-
throw new Error(`
|
|
483
|
+
throw new Error(`WORK_CONTINUE_ZERO_DELTA_PHYSICAL_CONFLICT: ${workId}`);
|
|
472
484
|
}
|
|
473
485
|
}
|
|
474
486
|
|
|
475
487
|
const branchName = `work/resume-${workId.replace(/[^A-Za-z0-9._-]+/g, '-').slice(0, 42)}-${baseRevision.slice(0, 12)}`;
|
|
476
488
|
const existingResumeBranch = gitCommitAtRef(repository.canonicalRoot, `refs/heads/${branchName}`);
|
|
477
489
|
if (existingResumeBranch && existingResumeBranch !== baseRevision) {
|
|
478
|
-
throw new Error(`
|
|
490
|
+
throw new Error(`WORK_CONTINUE_RECONSTRUCTION_BRANCH_CONFLICT: ${workId}`);
|
|
479
491
|
}
|
|
480
492
|
const workspace = ensureManagedWorkspace(controllerHome, repository, {
|
|
481
|
-
requestId: `${workId}:
|
|
482
|
-
title: `${work.objective}
|
|
493
|
+
requestId: `${workId}:active-checkout-recovery:${baseRevision}`,
|
|
494
|
+
title: `${work.objective} checkout recovery`,
|
|
495
|
+
associatedWorkId: workId,
|
|
483
496
|
branchName,
|
|
484
497
|
baseRef: baseRevision,
|
|
485
498
|
prepareDependencies: input.prepareDependencies === true,
|
|
486
499
|
});
|
|
487
500
|
if (!workspace.managed || !workspace.checkoutId || !workspace.root || !workspace.branch) {
|
|
488
|
-
throw new Error(`
|
|
501
|
+
throw new Error(`WORK_CONTINUE_RECONSTRUCTION_FAILED: ${workId}`);
|
|
489
502
|
}
|
|
490
503
|
const refreshedRepository = listRepositories(controllerHome, { includeRemoved: true })
|
|
491
504
|
.find((candidate) => candidate.repoId === repository.repoId);
|
|
492
|
-
if (!refreshedRepository) throw new Error(`
|
|
505
|
+
if (!refreshedRepository) throw new Error(`WORK_CONTINUE_REPOSITORY_MISSING: ${workId}`);
|
|
493
506
|
const reconstructed = selectRepositoryCheckout(refreshedRepository, workspace.checkoutId);
|
|
494
507
|
const reconstructedStatus = repositoryGitStatus(reconstructed);
|
|
495
508
|
if (!reconstructedStatus.clean || reconstructedStatus.head !== baseRevision || reconstructedStatus.branch !== workspace.branch) {
|
|
496
|
-
throw new Error(`
|
|
509
|
+
throw new Error(`WORK_CONTINUE_RECONSTRUCTION_REVISION_MISMATCH: ${workId}`);
|
|
497
510
|
}
|
|
498
511
|
|
|
499
|
-
|
|
512
|
+
updateWorkContract(store, workId, {
|
|
500
513
|
checkoutId: workspace.checkoutId,
|
|
501
514
|
worktreeRef: workspace.root,
|
|
502
515
|
baseRevision,
|
|
503
516
|
controllerInstanceId: identity.controllerInstanceId,
|
|
517
|
+
continuationPrompt: `Continue work ${repository.repoId}: ${work.objective.slice(0, 500)}. The prior managed checkout was absent; Forge reconstructed an exact zero-delta checkout at ${baseRevision}.`,
|
|
504
518
|
});
|
|
505
|
-
const
|
|
506
|
-
|
|
519
|
+
const updatedAt = new Date().toISOString();
|
|
520
|
+
writeWorkHandle(controllerHome, {
|
|
507
521
|
...handle,
|
|
508
522
|
principalId: identity.principalId,
|
|
509
523
|
sessionId: identity.sessionId,
|
|
@@ -520,14 +534,7 @@ export function reauthorizeRetainedCancelledRepositoryWork(
|
|
|
520
534
|
failureReason: undefined,
|
|
521
535
|
cleanupReceipt: undefined,
|
|
522
536
|
finalization: { validation: 'pending', commit: 'pending', merge: 'pending', branchCleanup: 'pending', worktreeCleanup: 'pending' },
|
|
523
|
-
updatedAt
|
|
524
|
-
});
|
|
525
|
-
resumeRetainedCancelledWorkContract(store, workId, {
|
|
526
|
-
principalId: identity.principalId,
|
|
527
|
-
controllerInstanceId: identity.controllerInstanceId,
|
|
528
|
-
summary: 'Explicit current user re-authorized the same cancelled Work; prior managed checkout was absent and a fresh isolated checkout was reconstructed at the exact zero-delta base revision.',
|
|
529
|
-
checkoutId: workspace.checkoutId,
|
|
530
|
-
worktreeRef: workspace.root,
|
|
537
|
+
updatedAt,
|
|
531
538
|
});
|
|
532
539
|
return { reconstructedCheckout: true };
|
|
533
540
|
}
|
|
@@ -4,7 +4,12 @@ import { join } from 'path';
|
|
|
4
4
|
import { ensureControllerHome } from '../../../cli/repositories/controller-home';
|
|
5
5
|
import { readJsonFile, sanitizeFileComponent } from '../../shared/json-files';
|
|
6
6
|
import type { GoalDelegation } from '../governance/authorization';
|
|
7
|
-
import {
|
|
7
|
+
import {
|
|
8
|
+
readControlPlaneRecordWithinTransaction,
|
|
9
|
+
readOrImportControlPlaneRecord,
|
|
10
|
+
writeControlPlaneRecord,
|
|
11
|
+
type SqliteDatabase,
|
|
12
|
+
} from '../persistence/sqlite-store';
|
|
8
13
|
|
|
9
14
|
export interface ExecutionSessionContext {
|
|
10
15
|
schemaVersion: 1;
|
|
@@ -71,6 +76,31 @@ export function peekExecutionSession(controllerHome: string, sessionId: string):
|
|
|
71
76
|
return session.sessionId === normalizedSessionId ? session : undefined;
|
|
72
77
|
}
|
|
73
78
|
|
|
79
|
+
/**
|
|
80
|
+
* Transaction-safe execution-session projection. It never imports legacy
|
|
81
|
+
* state while another control-plane write transaction is open. A legacy JSON
|
|
82
|
+
* file may still be read as evidence and is imported later by the ordinary
|
|
83
|
+
* non-transactional session path.
|
|
84
|
+
*/
|
|
85
|
+
export function peekExecutionSessionWithinTransaction(
|
|
86
|
+
database: SqliteDatabase,
|
|
87
|
+
controllerHome: string,
|
|
88
|
+
sessionId: string,
|
|
89
|
+
): ExecutionSessionContext | undefined {
|
|
90
|
+
const normalizedSessionId = sessionId.trim();
|
|
91
|
+
if (!normalizedSessionId) return undefined;
|
|
92
|
+
const stored = readControlPlaneRecordWithinTransaction<ExecutionSessionContext>(
|
|
93
|
+
database,
|
|
94
|
+
'execution_session',
|
|
95
|
+
'controller',
|
|
96
|
+
sanitizeFileComponent(normalizedSessionId),
|
|
97
|
+
)?.value;
|
|
98
|
+
const legacyPath = sessionPath(controllerHome, normalizedSessionId);
|
|
99
|
+
const session = stored ?? (existsSync(legacyPath) ? readJsonFile<ExecutionSessionContext>(legacyPath) : undefined);
|
|
100
|
+
if (!session) return undefined;
|
|
101
|
+
return session.sessionId === normalizedSessionId ? session : undefined;
|
|
102
|
+
}
|
|
103
|
+
|
|
74
104
|
export function readExecutionSession(controllerHome: string, identity: SessionIdentity): ExecutionSessionContext | undefined {
|
|
75
105
|
const sessionId = identity.sessionId?.trim();
|
|
76
106
|
if (!sessionId) return undefined;
|