@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
|
@@ -2,12 +2,10 @@ import { resolve } from 'path';
|
|
|
2
2
|
import type { RepositoryRecord } from '../../../cli/repositories/types';
|
|
3
3
|
import { getRepository, resolveRepositorySelection, selectRepositoryCheckout } from '../../../cli/repositories/registry';
|
|
4
4
|
import { repositoryGitStatus } from '../../../cli/repositories/structured-git';
|
|
5
|
-
import { appendWorkEvidence, getWorkContract,
|
|
6
|
-
import { controllerSessionPrincipalId, getControllerSession } from '../../../../packages/kernel/controller/api/index';
|
|
7
|
-
import { isTerminalWorkContractStatus } from '../facade/types';
|
|
5
|
+
import { appendWorkEvidence, getWorkContract, recordWorkEvidenceState, semanticWorkState } from '../../../../packages/kernel/work/api/index';
|
|
8
6
|
import { currentPermissionSnapshotVersion } from './validation';
|
|
9
7
|
import { listWorkHandles, readWorkHandle, transitionWorkHandle, writeWorkHandle, type WorkHandleState } from './work-handle-store';
|
|
10
|
-
import {
|
|
8
|
+
import { gitIsAncestor } from './work-execution-support';
|
|
11
9
|
|
|
12
10
|
export interface RepositoryWorkHandleControllerIdentity {
|
|
13
11
|
sessionId: string;
|
|
@@ -46,10 +44,11 @@ export function assertCanonicalRepositoryMutationWorkHandleAvailable(input: {
|
|
|
46
44
|
handle.workId,
|
|
47
45
|
);
|
|
48
46
|
// A stale physical handle cannot outlive canonical Work lifecycle authority.
|
|
49
|
-
//
|
|
50
|
-
//
|
|
51
|
-
//
|
|
52
|
-
|
|
47
|
+
// Delivery receipts are mechanical evidence only; an explicitly open Work
|
|
48
|
+
// continues to own its concrete mutation surface until semantic completion
|
|
49
|
+
// or cancellation releases that authority.
|
|
50
|
+
if (!contract) return false;
|
|
51
|
+
return semanticWorkState(contract) === 'open';
|
|
53
52
|
})
|
|
54
53
|
.sort((left, right) => left.workId.localeCompare(right.workId));
|
|
55
54
|
if (owners.length === 0) return;
|
|
@@ -86,8 +85,9 @@ function resolveRepositoryWorkHandlePlacement(input: {
|
|
|
86
85
|
}
|
|
87
86
|
|
|
88
87
|
/**
|
|
89
|
-
*
|
|
90
|
-
*
|
|
88
|
+
* Materialize concrete repository-mutation ownership for an optional semantic
|
|
89
|
+
* Work attribution. Thin Work does not classify execution kind; checkout/CAS
|
|
90
|
+
* placement and the WorkHandle resource fence own mutation safety.
|
|
91
91
|
* Transport layers provide only the authenticated Controller identity.
|
|
92
92
|
*/
|
|
93
93
|
export function ensureRepositoryWorkHandle(input: {
|
|
@@ -95,28 +95,35 @@ export function ensureRepositoryWorkHandle(input: {
|
|
|
95
95
|
repository: RepositoryRecord;
|
|
96
96
|
workId: string;
|
|
97
97
|
identity: RepositoryWorkHandleControllerIdentity;
|
|
98
|
+
checkoutId?: string;
|
|
98
99
|
allowEffectWork?: boolean;
|
|
99
100
|
}): WorkHandleState | undefined {
|
|
100
101
|
const existing = readWorkHandle(input.controllerHome, input.repository.repoId, input.workId);
|
|
101
|
-
if (existing)
|
|
102
|
+
if (existing) {
|
|
103
|
+
if (input.checkoutId?.trim() && existing.checkoutId !== input.checkoutId.trim()) {
|
|
104
|
+
throw new Error(`WORK_HANDLE_PLACEMENT_CHECKOUT_MISMATCH: ${input.workId}`);
|
|
105
|
+
}
|
|
106
|
+
return existing;
|
|
107
|
+
}
|
|
102
108
|
const contract = getWorkContract(
|
|
103
109
|
{ controllerHome: input.controllerHome, repoId: input.repository.repoId },
|
|
104
110
|
input.workId,
|
|
105
111
|
);
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
}
|
|
112
|
+
// allowEffectWork is retained only for source compatibility while old
|
|
113
|
+
// repository callers cut over. workKind is no longer an execution authority.
|
|
114
|
+
void input.allowEffectWork;
|
|
115
|
+
const checkoutId = input.checkoutId?.trim() || contract?.checkoutId?.trim();
|
|
116
|
+
if (!contract || !checkoutId) return undefined;
|
|
112
117
|
// Callers may already be scoped to the Work checkout. Re-read the unselected
|
|
113
118
|
// registry record so WorkHandle source/delivery authority never mistakes an
|
|
114
|
-
// isolated execution worktree for the canonical source checkout.
|
|
119
|
+
// isolated execution worktree for the canonical source checkout. Legacy
|
|
120
|
+
// WorkContract checkout/worktree fields remain migration-era placement hints;
|
|
121
|
+
// new Thin Work receives its concrete checkout from the repository target.
|
|
115
122
|
const placement = resolveRepositoryWorkHandlePlacement({
|
|
116
123
|
controllerHome: input.controllerHome,
|
|
117
124
|
repositoryId: input.repository.repoId,
|
|
118
|
-
checkoutId
|
|
119
|
-
worktreeRef: contract.worktreeRef,
|
|
125
|
+
checkoutId,
|
|
126
|
+
worktreeRef: contract.checkoutId === checkoutId ? contract.worktreeRef : undefined,
|
|
120
127
|
});
|
|
121
128
|
const { registeredRepository, checkout, status, branch, managedWorktree } = placement;
|
|
122
129
|
const sourceCheckoutId = registeredRepository.activeCheckoutId;
|
|
@@ -130,7 +137,7 @@ export function ensureRepositoryWorkHandle(input: {
|
|
|
130
137
|
sessionId: input.identity.sessionId,
|
|
131
138
|
principalId: input.identity.principalId,
|
|
132
139
|
repositoryId: input.repository.repoId,
|
|
133
|
-
checkoutId
|
|
140
|
+
checkoutId,
|
|
134
141
|
worktreePath: checkout.canonicalRoot,
|
|
135
142
|
branch,
|
|
136
143
|
sourceCheckoutId,
|
|
@@ -164,7 +171,7 @@ export function reconcileRepositoryWorkHandlePlacement(input: {
|
|
|
164
171
|
const existing = readWorkHandle(input.controllerHome, input.repositoryId, input.workId);
|
|
165
172
|
if (!existing || existing.managedWorktree) return existing;
|
|
166
173
|
const contract = getWorkContract({ controllerHome: input.controllerHome, repoId: input.repositoryId }, input.workId);
|
|
167
|
-
if (!contract ||
|
|
174
|
+
if (!contract || !contract.checkoutId) return existing;
|
|
168
175
|
if (contract.checkoutId !== existing.checkoutId) throw new Error(`WORK_HANDLE_PLACEMENT_CHECKOUT_MISMATCH: ${input.workId}`);
|
|
169
176
|
const placement = resolveRepositoryWorkHandlePlacement({ controllerHome: input.controllerHome, repositoryId: input.repositoryId, checkoutId: contract.checkoutId, worktreeRef: contract.worktreeRef });
|
|
170
177
|
if (!placement.managedWorktree) return existing;
|
|
@@ -174,58 +181,160 @@ export function reconcileRepositoryWorkHandlePlacement(input: {
|
|
|
174
181
|
return writeWorkHandle(input.controllerHome, { ...existing, sourceCheckoutId: placement.registeredRepository.activeCheckoutId, managedWorktree: true });
|
|
175
182
|
}
|
|
176
183
|
|
|
177
|
-
function
|
|
184
|
+
export function assertManagedRepositoryMutationAuthority(input: {
|
|
185
|
+
repository: RepositoryRecord;
|
|
186
|
+
handle: WorkHandleState;
|
|
187
|
+
}): void {
|
|
188
|
+
if (!input.handle.managedWorktree) return;
|
|
189
|
+
if (input.handle.state !== 'prepared' && input.handle.state !== 'editing') {
|
|
190
|
+
throw new Error(`WORK_REPOSITORY_MUTATION_LIFECYCLE_INVALID: ${input.handle.workId}:${input.handle.state}`);
|
|
191
|
+
}
|
|
192
|
+
if (input.repository.activeCheckoutId !== input.handle.checkoutId) {
|
|
193
|
+
throw new Error(`WORK_REPOSITORY_MUTATION_CHECKOUT_MISMATCH: expected ${input.handle.checkoutId}, found ${input.repository.activeCheckoutId}`);
|
|
194
|
+
}
|
|
195
|
+
const status = repositoryGitStatus(input.repository);
|
|
196
|
+
if (status.branch !== input.handle.branch) {
|
|
197
|
+
throw new Error(`WORK_REPOSITORY_MUTATION_BRANCH_CHANGED: expected ${input.handle.branch}, found ${status.branch ?? 'detached'}`);
|
|
198
|
+
}
|
|
199
|
+
if (!input.handle.expectedHead || status.head !== input.handle.expectedHead) {
|
|
200
|
+
throw new Error(`WORK_REPOSITORY_MUTATION_HEAD_CHANGED: expected ${input.handle.expectedHead ?? 'missing'}, found ${status.head ?? 'missing'}`);
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
export function rearmFailedPreservedWorkHandle(input: {
|
|
178
205
|
controllerHome: string;
|
|
179
206
|
repository: RepositoryRecord;
|
|
180
207
|
workId: string;
|
|
181
208
|
contract: NonNullable<ReturnType<typeof getWorkContract>>;
|
|
182
209
|
handle: WorkHandleState;
|
|
183
|
-
|
|
210
|
+
principalId: string;
|
|
211
|
+
sessionId: string;
|
|
184
212
|
}): WorkHandleState {
|
|
185
|
-
|
|
186
|
-
if (
|
|
187
|
-
|
|
213
|
+
const { handle } = input;
|
|
214
|
+
if (!handle.managedWorktree || handle.state !== 'failed') return handle;
|
|
215
|
+
const validationRecoverable = handle.finalization.validation === 'pending'
|
|
216
|
+
|| handle.finalization.validation === 'failed';
|
|
217
|
+
if (!validationRecoverable
|
|
218
|
+
|| handle.finalization.commit !== 'pending'
|
|
219
|
+
|| handle.finalization.merge !== 'pending'
|
|
220
|
+
|| handle.finalization.branchCleanup !== 'pending'
|
|
221
|
+
|| handle.finalization.worktreeCleanup !== 'pending'
|
|
222
|
+
|| handle.cleanupReceipt
|
|
223
|
+
|| input.contract.completionReceipt
|
|
224
|
+
|| input.contract.completionOutcome) {
|
|
225
|
+
return handle;
|
|
226
|
+
}
|
|
227
|
+
if (handle.principalId !== input.principalId) {
|
|
228
|
+
throw new Error(`WORK_REPOSITORY_MUTATION_PRINCIPAL_MISMATCH: ${input.workId}`);
|
|
188
229
|
}
|
|
189
|
-
if (!input.contract.checkoutId) throw new Error(`WORK_REPOSITORY_MUTATION_CHECKOUT_REQUIRED: ${input.workId}`);
|
|
190
|
-
|
|
191
230
|
const placement = resolveRepositoryWorkHandlePlacement({
|
|
192
231
|
controllerHome: input.controllerHome,
|
|
193
232
|
repositoryId: input.repository.repoId,
|
|
194
|
-
checkoutId:
|
|
195
|
-
worktreeRef:
|
|
233
|
+
checkoutId: handle.checkoutId,
|
|
234
|
+
worktreeRef: handle.worktreePath,
|
|
235
|
+
});
|
|
236
|
+
if (!placement.managedWorktree || placement.registeredCheckout.lifecycle !== 'active') {
|
|
237
|
+
throw new Error(`WORK_REPOSITORY_MUTATION_FAILED_CHECKOUT_NOT_ACTIVE: ${input.workId}`);
|
|
238
|
+
}
|
|
239
|
+
if (resolve(placement.checkout.canonicalRoot) !== resolve(handle.worktreePath)
|
|
240
|
+
|| placement.branch !== handle.branch
|
|
241
|
+
|| (handle.expectedHead && placement.status.head !== handle.expectedHead)) {
|
|
242
|
+
throw new Error(`WORK_REPOSITORY_MUTATION_FAILED_CHECKOUT_OWNERSHIP_MISMATCH: ${input.workId}`);
|
|
243
|
+
}
|
|
244
|
+
if (input.contract.evidenceState === 'valid') {
|
|
245
|
+
recordWorkEvidenceState(
|
|
246
|
+
{ controllerHome: input.controllerHome, repoId: input.repository.repoId },
|
|
247
|
+
input.workId,
|
|
248
|
+
'stale',
|
|
249
|
+
);
|
|
250
|
+
}
|
|
251
|
+
const next = writeWorkHandle(input.controllerHome, {
|
|
252
|
+
...handle,
|
|
253
|
+
principalId: input.principalId,
|
|
254
|
+
sessionId: input.sessionId,
|
|
255
|
+
state: 'editing',
|
|
256
|
+
validationRun: undefined,
|
|
257
|
+
validatedInputFingerprint: undefined,
|
|
258
|
+
failureReason: undefined,
|
|
259
|
+
finalization: { ...handle.finalization, validation: 'pending' },
|
|
260
|
+
updatedAt: new Date().toISOString(),
|
|
196
261
|
});
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
262
|
+
appendWorkEvidence(
|
|
263
|
+
{ controllerHome: input.controllerHome, repoId: input.repository.repoId },
|
|
264
|
+
input.workId,
|
|
265
|
+
{
|
|
266
|
+
title: 'failed retained Work re-armed for same-Work mutation',
|
|
267
|
+
summary: `Re-armed preserved managed checkout ${handle.checkoutId} after proving the Work remained open, commit/merge/cleanup had not started, and exact checkout/path/branch/HEAD ownership still matched.`,
|
|
268
|
+
detailLevel: 'summary',
|
|
269
|
+
},
|
|
270
|
+
);
|
|
271
|
+
return next;
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
function rearmRetainedMergedWorkForMutation(input: {
|
|
275
|
+
controllerHome: string;
|
|
276
|
+
repository: RepositoryRecord;
|
|
277
|
+
workId: string;
|
|
278
|
+
contract: NonNullable<ReturnType<typeof getWorkContract>>;
|
|
279
|
+
handle: WorkHandleState;
|
|
280
|
+
}): WorkHandleState {
|
|
281
|
+
const { handle } = input;
|
|
282
|
+
if (!handle.managedWorktree || handle.state !== 'merged') return handle;
|
|
283
|
+
const retained = handle.terminalResourceDisposition;
|
|
284
|
+
if (retained?.mode !== 'retained_by_request' || retained.retainWorktree !== true || retained.retainBranch !== true) return handle;
|
|
285
|
+
if (semanticWorkState(input.contract) !== 'open') throw new Error(`WORK_RETAINED_REARM_SEMANTIC_STATE_INVALID: ${input.workId}`);
|
|
286
|
+
if (!handle.expectedHead?.trim()) throw new Error(`WORK_RETAINED_REARM_EXPECTED_HEAD_REQUIRED: ${input.workId}`);
|
|
200
287
|
|
|
201
|
-
const
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
status: placement.status,
|
|
207
|
-
freshlyMaterialized: input.freshlyMaterialized,
|
|
288
|
+
const placement = resolveRepositoryWorkHandlePlacement({
|
|
289
|
+
controllerHome: input.controllerHome,
|
|
290
|
+
repositoryId: input.repository.repoId,
|
|
291
|
+
checkoutId: handle.checkoutId,
|
|
292
|
+
worktreeRef: input.contract.worktreeRef,
|
|
208
293
|
});
|
|
209
|
-
if (
|
|
210
|
-
|
|
211
|
-
|
|
294
|
+
if (!placement.managedWorktree || placement.registeredCheckout.lifecycle !== 'active') {
|
|
295
|
+
throw new Error(`WORK_RETAINED_REARM_CHECKOUT_NOT_ACTIVE: ${input.workId}`);
|
|
296
|
+
}
|
|
297
|
+
if (resolve(placement.checkout.canonicalRoot) !== resolve(handle.worktreePath) || placement.branch !== handle.branch) {
|
|
298
|
+
throw new Error(`WORK_RETAINED_REARM_OWNERSHIP_MISMATCH: ${input.workId}`);
|
|
299
|
+
}
|
|
300
|
+
if (!placement.status.clean) throw new Error(`WORK_RETAINED_REARM_WORKTREE_DIRTY: ${input.workId}`);
|
|
301
|
+
if (placement.status.head !== handle.expectedHead) {
|
|
302
|
+
throw new Error(`WORK_RETAINED_REARM_HEAD_CHANGED: expected ${handle.expectedHead}, found ${placement.status.head ?? 'missing'}`);
|
|
303
|
+
}
|
|
304
|
+
const sourceCheckout = selectRepositoryCheckout(
|
|
305
|
+
placement.registeredRepository,
|
|
306
|
+
handle.sourceCheckoutId ?? placement.registeredRepository.activeCheckoutId,
|
|
307
|
+
{ allowArchived: true },
|
|
308
|
+
);
|
|
309
|
+
const targetBranch = handle.deliveryTargetBranch?.trim();
|
|
310
|
+
if (!targetBranch || !gitIsAncestor(sourceCheckout.canonicalRoot, handle.expectedHead, targetBranch)) {
|
|
311
|
+
throw new Error(`WORK_RETAINED_REARM_TARGET_CONTAINMENT_REQUIRED: ${input.workId}`);
|
|
212
312
|
}
|
|
213
313
|
|
|
214
|
-
const
|
|
215
|
-
|
|
216
|
-
|
|
314
|
+
const evidenceState = input.contract.evidenceState === 'valid' || input.contract.evidenceState === 'stale' ? 'stale' : 'partial';
|
|
315
|
+
if (input.contract.evidenceState !== evidenceState) recordWorkEvidenceState(
|
|
316
|
+
{ controllerHome: input.controllerHome, repoId: input.repository.repoId }, input.workId, evidenceState,
|
|
317
|
+
);
|
|
318
|
+
const next = writeWorkHandle(input.controllerHome, {
|
|
319
|
+
...handle,
|
|
320
|
+
state: 'editing',
|
|
321
|
+
terminalResourceDisposition: undefined,
|
|
322
|
+
validatedInputFingerprint: undefined,
|
|
323
|
+
validationRun: undefined,
|
|
324
|
+
cleanupReceipt: undefined,
|
|
217
325
|
failureReason: undefined,
|
|
326
|
+
finalization: { validation: 'pending', commit: 'pending', merge: 'pending', branchCleanup: 'pending', worktreeCleanup: 'pending' },
|
|
218
327
|
});
|
|
219
328
|
appendWorkEvidence(
|
|
220
329
|
{ controllerHome: input.controllerHome, repoId: input.repository.repoId },
|
|
221
330
|
input.workId,
|
|
222
331
|
{
|
|
223
|
-
title: '
|
|
224
|
-
summary: `
|
|
332
|
+
title: 'retained merged Work re-armed for same-Work mutation',
|
|
333
|
+
summary: `Re-armed retained merged Work at ${handle.expectedHead} only after proving semantic Work remains open, retained branch/worktree ownership, clean exact checkout identity, and target containment on ${targetBranch}. Prior validation/delivery authority is stale; no new Work was created.`,
|
|
225
334
|
detailLevel: 'summary',
|
|
226
335
|
},
|
|
227
336
|
);
|
|
228
|
-
return
|
|
337
|
+
return next;
|
|
229
338
|
}
|
|
230
339
|
|
|
231
340
|
export function markRepositoryMutationStarted(input: {
|
|
@@ -236,9 +345,7 @@ export function markRepositoryMutationStarted(input: {
|
|
|
236
345
|
}): WorkHandleState | undefined {
|
|
237
346
|
const store = { controllerHome: input.controllerHome, repoId: input.repository.repoId };
|
|
238
347
|
const contract = getWorkContract(store, input.workId);
|
|
239
|
-
if (contract
|
|
240
|
-
promoteWorkToRepositoryChange(store, input.workId);
|
|
241
|
-
}
|
|
348
|
+
if (!contract) return undefined;
|
|
242
349
|
const handle = readWorkHandle(input.controllerHome, input.repository.repoId, input.workId);
|
|
243
350
|
if (!handle || handle.managedWorktree || handle.state !== 'prepared') return handle;
|
|
244
351
|
const boundWorkId = handle.workContractId ?? handle.workId;
|
|
@@ -253,40 +360,30 @@ export function markRepositoryMutationStarted(input: {
|
|
|
253
360
|
}
|
|
254
361
|
|
|
255
362
|
/**
|
|
256
|
-
*
|
|
257
|
-
*
|
|
258
|
-
*
|
|
259
|
-
* allowed to become a second mutation authority.
|
|
363
|
+
* Materializes repository delivery authority for an optional semantic Work.
|
|
364
|
+
* Work is not a controller mutex or an execution-kind gate: authenticated caller
|
|
365
|
+
* identity is provenance while checkout/head/CAS/resource fences own mutation safety.
|
|
260
366
|
*/
|
|
261
367
|
export function ensureRepositoryMutationWorkHandle(input: {
|
|
262
368
|
controllerHome: string;
|
|
263
369
|
repository: RepositoryRecord;
|
|
264
370
|
workId: string;
|
|
265
371
|
principalId: string;
|
|
372
|
+
sessionId?: string;
|
|
266
373
|
deferEffectPromotion?: boolean;
|
|
267
374
|
}): { handle: WorkHandleState; promotedFrom?: 'local_effect' | 'remote_effect' } {
|
|
268
375
|
const store = { controllerHome: input.controllerHome, repoId: input.repository.repoId };
|
|
269
|
-
|
|
376
|
+
const contract = getWorkContract(store, input.workId);
|
|
270
377
|
if (!contract) throw new Error(`WORK_NOT_FOUND: ${input.workId}`);
|
|
271
|
-
if (
|
|
378
|
+
if (semanticWorkState(contract) !== 'open') {
|
|
272
379
|
throw new Error(`WORK_REPOSITORY_MUTATION_TERMINAL: ${input.workId}`);
|
|
273
380
|
}
|
|
274
381
|
const principalId = input.principalId.trim();
|
|
275
|
-
if (!principalId) throw new Error(`
|
|
276
|
-
const
|
|
277
|
-
if (!owner) throw new Error(`WORK_CONTROLLER_CLAIM_REQUIRED: ${input.workId}`);
|
|
278
|
-
if (controllerSessionPrincipalId(owner) !== principalId) {
|
|
279
|
-
throw new Error(`WORK_CONTROLLER_OWNERSHIP_MISMATCH: ${input.workId}`);
|
|
280
|
-
}
|
|
382
|
+
if (!principalId) throw new Error(`WORK_AUTHENTICATED_PRINCIPAL_REQUIRED: ${input.workId}`);
|
|
383
|
+
const provenanceSessionId = input.sessionId?.trim() || `sessionless:${principalId}`;
|
|
281
384
|
|
|
282
|
-
|
|
283
|
-
if (!mutationCheckoutId) {
|
|
284
|
-
if (contract.worktreeRef?.trim()) {
|
|
285
|
-
throw new Error(`WORK_REPOSITORY_MUTATION_CHECKOUT_REQUIRED: ${input.workId}`);
|
|
286
|
-
}
|
|
287
|
-
mutationCheckoutId = input.repository.activeCheckoutId;
|
|
288
|
-
contract = updateWorkContract(store, input.workId, { checkoutId: mutationCheckoutId });
|
|
289
|
-
}
|
|
385
|
+
const mutationCheckoutId = contract.checkoutId?.trim() || input.repository.activeCheckoutId;
|
|
386
|
+
if (!mutationCheckoutId) throw new Error(`WORK_REPOSITORY_MUTATION_CHECKOUT_REQUIRED: ${input.workId}`);
|
|
290
387
|
assertCanonicalRepositoryMutationWorkHandleAvailable({
|
|
291
388
|
controllerHome: input.controllerHome,
|
|
292
389
|
repositoryId: input.repository.repoId,
|
|
@@ -294,54 +391,36 @@ export function ensureRepositoryMutationWorkHandle(input: {
|
|
|
294
391
|
workId: input.workId,
|
|
295
392
|
});
|
|
296
393
|
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
if (input.deferEffectPromotion !== true) {
|
|
301
|
-
contract = promoteWorkToRepositoryChange(store, input.workId);
|
|
302
|
-
}
|
|
303
|
-
}
|
|
304
|
-
if (contract.workKind !== 'repository_change' && input.deferEffectPromotion !== true) {
|
|
305
|
-
throw new Error(`WORK_REPOSITORY_MUTATION_KIND_INVALID: ${input.workId}:${contract.workKind}`);
|
|
306
|
-
}
|
|
394
|
+
// deferEffectPromotion is a compatibility input from the retired Work-kind
|
|
395
|
+
// lifecycle. Repository mutation is now admitted by the concrete target fence.
|
|
396
|
+
void input.deferEffectPromotion;
|
|
307
397
|
|
|
308
|
-
const existingHandle = readWorkHandle(input.controllerHome, input.repository.repoId, input.workId);
|
|
309
398
|
let handle = ensureRepositoryWorkHandle({
|
|
310
399
|
controllerHome: input.controllerHome,
|
|
311
400
|
repository: input.repository,
|
|
312
401
|
workId: input.workId,
|
|
313
|
-
identity: { sessionId:
|
|
314
|
-
|
|
402
|
+
identity: { sessionId: provenanceSessionId, principalId },
|
|
403
|
+
checkoutId: mutationCheckoutId,
|
|
404
|
+
allowEffectWork: true,
|
|
315
405
|
});
|
|
316
406
|
if (!handle) throw new Error(`WORK_REPOSITORY_MUTATION_HANDLE_REQUIRED: ${input.workId}`);
|
|
317
|
-
handle =
|
|
407
|
+
handle = rearmFailedPreservedWorkHandle({
|
|
318
408
|
controllerHome: input.controllerHome,
|
|
319
409
|
repository: input.repository,
|
|
320
410
|
workId: input.workId,
|
|
321
411
|
contract,
|
|
322
412
|
handle,
|
|
323
|
-
|
|
413
|
+
principalId,
|
|
414
|
+
sessionId: provenanceSessionId,
|
|
324
415
|
});
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
* revision on the read handle preserves fail-closed concurrent ownership.
|
|
332
|
-
*/
|
|
333
|
-
export function rebindRepositoryWorkHandleControllerIdentity(input: {
|
|
334
|
-
controllerHome: string;
|
|
335
|
-
repositoryId: string;
|
|
336
|
-
workId: string;
|
|
337
|
-
identity: RepositoryWorkHandleControllerIdentity;
|
|
338
|
-
}): WorkHandleState | undefined {
|
|
339
|
-
const existing = readWorkHandle(input.controllerHome, input.repositoryId, input.workId);
|
|
340
|
-
if (!existing) return undefined;
|
|
341
|
-
if (existing.principalId === input.identity.principalId && existing.sessionId === input.identity.sessionId) return existing;
|
|
342
|
-
return writeWorkHandle(input.controllerHome, {
|
|
343
|
-
...existing,
|
|
344
|
-
principalId: input.identity.principalId,
|
|
345
|
-
sessionId: input.identity.sessionId,
|
|
416
|
+
handle = rearmRetainedMergedWorkForMutation({
|
|
417
|
+
controllerHome: input.controllerHome,
|
|
418
|
+
repository: input.repository,
|
|
419
|
+
workId: input.workId,
|
|
420
|
+
contract,
|
|
421
|
+
handle,
|
|
346
422
|
});
|
|
423
|
+
assertManagedRepositoryMutationAuthority({ repository: input.repository, handle });
|
|
424
|
+
return { handle };
|
|
347
425
|
}
|
|
426
|
+
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { randomUUID } from 'crypto';
|
|
2
2
|
import { existsSync } from 'fs';
|
|
3
3
|
import { join } from 'path';
|
|
4
|
-
import {
|
|
4
|
+
import { scopedOperationRoot } from '../../../cli/repositories/controller-home';
|
|
5
5
|
import { readJsonFile, sanitizeFileComponent } from '../../shared/json-files';
|
|
6
6
|
import type { ProcessCheckExecutionIdentity } from '../../evidence/process-check-execution';
|
|
7
7
|
import { listControlPlaneRecords, mutateControlPlaneRecord, readOrImportControlPlaneRecord, writeControlPlaneRecord } from '../persistence/sqlite-store';
|
|
@@ -227,7 +227,7 @@ export function resolveWorkDeliveryTargetBranch(
|
|
|
227
227
|
}
|
|
228
228
|
|
|
229
229
|
function workHandlePath(controllerHome: string, handle: Pick<WorkHandleState, 'repositoryId' | 'workId'>): string {
|
|
230
|
-
return join(
|
|
230
|
+
return join(scopedOperationRoot(controllerHome, handle.repositoryId), 'work-handles', `${sanitizeFileComponent(handle.workId)}.json`);
|
|
231
231
|
}
|
|
232
232
|
|
|
233
233
|
function now(): string {
|
|
@@ -376,6 +376,23 @@ export function writeWorkHandle(controllerHome: string, handle: WorkHandleState)
|
|
|
376
376
|
return { ...record.value, recordRevision: record.revision };
|
|
377
377
|
}
|
|
378
378
|
|
|
379
|
+
/**
|
|
380
|
+
* Refresh legacy controller identity fields as provenance only. Repository
|
|
381
|
+
* mutation authority remains WorkHandle CAS plus concrete checkout/resource fences.
|
|
382
|
+
*/
|
|
383
|
+
export function rebindWorkHandleControllerIdentity(
|
|
384
|
+
controllerHome: string,
|
|
385
|
+
handle: WorkHandleState,
|
|
386
|
+
identity: { principalId: string; sessionId: string },
|
|
387
|
+
): WorkHandleState {
|
|
388
|
+
if (handle.principalId === identity.principalId && handle.sessionId === identity.sessionId) return handle;
|
|
389
|
+
return writeWorkHandle(controllerHome, {
|
|
390
|
+
...handle,
|
|
391
|
+
principalId: identity.principalId,
|
|
392
|
+
sessionId: identity.sessionId,
|
|
393
|
+
});
|
|
394
|
+
}
|
|
395
|
+
|
|
379
396
|
const TRANSITIONS: Record<WorkHandleStateName, readonly WorkHandleStateName[]> = {
|
|
380
397
|
prepared: ['editing', 'validating', 'committed', 'failed', 'failed_terminal_cleanup'],
|
|
381
398
|
editing: ['validating', 'committed', 'merged', 'failed', 'failed_terminal_cleanup'],
|
|
@@ -404,47 +421,6 @@ export function transitionWorkHandle(
|
|
|
404
421
|
});
|
|
405
422
|
}
|
|
406
423
|
|
|
407
|
-
export interface WorkHandleSuccessorAdoption {
|
|
408
|
-
candidateHead: string;
|
|
409
|
-
targetHead: string;
|
|
410
|
-
}
|
|
411
|
-
|
|
412
|
-
/**
|
|
413
|
-
* Explicit WorkHandle authority transition for a conflict-repaired managed
|
|
414
|
-
* candidate. Git lineage/scope/cleanliness must be proven by the finalizer
|
|
415
|
-
* before this transition is called. Adopting a rewritten candidate never
|
|
416
|
-
* transfers validation implicitly: the new source identity must obtain exact
|
|
417
|
-
* verification/review authority before delivery can resume.
|
|
418
|
-
*/
|
|
419
|
-
export function adoptWorkHandleSuccessorCandidate(
|
|
420
|
-
controllerHome: string,
|
|
421
|
-
handle: WorkHandleState,
|
|
422
|
-
adoption: WorkHandleSuccessorAdoption,
|
|
423
|
-
): WorkHandleState {
|
|
424
|
-
const candidateHead = adoption.candidateHead.trim();
|
|
425
|
-
const targetHead = adoption.targetHead.trim();
|
|
426
|
-
if (!handle.managedWorktree) throw new Error('WORK_SUCCESSOR_ADOPTION_MANAGED_CHECKOUT_REQUIRED');
|
|
427
|
-
if (!candidateHead || !targetHead) throw new Error('WORK_SUCCESSOR_ADOPTION_REVISION_REQUIRED');
|
|
428
|
-
if (candidateHead === handle.expectedHead) throw new Error('WORK_SUCCESSOR_ADOPTION_NO_CHANGE');
|
|
429
|
-
return transitionWorkHandle(controllerHome, handle, 'validating', {
|
|
430
|
-
deliveryBaseCommit: targetHead,
|
|
431
|
-
expectedHead: candidateHead,
|
|
432
|
-
failureReason: undefined,
|
|
433
|
-
finalization: {
|
|
434
|
-
...handle.finalization,
|
|
435
|
-
validation: 'pending',
|
|
436
|
-
commit: 'done',
|
|
437
|
-
merge: 'pending',
|
|
438
|
-
branchCleanup: 'pending',
|
|
439
|
-
worktreeCleanup: 'pending',
|
|
440
|
-
failureCode: undefined, lastError: undefined,
|
|
441
|
-
},
|
|
442
|
-
validationRun: undefined,
|
|
443
|
-
validatedInputFingerprint: undefined,
|
|
444
|
-
cleanupReceipt: undefined,
|
|
445
|
-
});
|
|
446
|
-
}
|
|
447
|
-
|
|
448
424
|
export function markWorkHandleFailed(controllerHome: string, handle: WorkHandleState, reason: string): WorkHandleState {
|
|
449
425
|
return writeWorkHandle(controllerHome, {
|
|
450
426
|
...handle,
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { commandExecutionScopeKey, type RepositoryCommandScopeTarget } from '../../../cli/repositories/command-scope';
|
|
1
2
|
import type { RepositoryRecord } from '../../../cli/repositories/types';
|
|
2
3
|
import { repositoryGitStatus } from '../../../cli/repositories/structured-git';
|
|
3
4
|
import type { ResolvedExecutionIdentity } from './execution-identity';
|
|
@@ -30,7 +31,7 @@ export interface WorkHeadSettlementResult {
|
|
|
30
31
|
*/
|
|
31
32
|
export function settleWorkHandleExpectedHeadAfterRepositoryCommand(input: {
|
|
32
33
|
controllerHome: string;
|
|
33
|
-
repository:
|
|
34
|
+
repository: RepositoryCommandScopeTarget;
|
|
34
35
|
executionIdentity: ResolvedExecutionIdentity;
|
|
35
36
|
workId?: string;
|
|
36
37
|
ok?: boolean;
|
|
@@ -42,33 +43,65 @@ export function settleWorkHandleExpectedHeadAfterRepositoryCommand(input: {
|
|
|
42
43
|
if (input.ok !== true || input.cancelled === true || input.timedOut === true) {
|
|
43
44
|
return { settled: false, reason: 'command_not_successful' };
|
|
44
45
|
}
|
|
45
|
-
const
|
|
46
|
-
if (!
|
|
47
|
-
|
|
48
|
-
handle.repositoryId
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
) return { settled: false, reason: 'identity_mismatch' };
|
|
54
|
-
if (
|
|
46
|
+
const originalHandle = readWorkHandle(input.controllerHome, commandExecutionScopeKey(input.repository), workId);
|
|
47
|
+
if (!originalHandle) return { settled: false, reason: 'work_handle_missing' };
|
|
48
|
+
const sameStaticExecutionIdentity = (handle: typeof originalHandle): boolean => (
|
|
49
|
+
handle.repositoryId === input.executionIdentity.repositoryId
|
|
50
|
+
&& handle.checkoutId === input.executionIdentity.checkoutId
|
|
51
|
+
&& handle.workId === input.executionIdentity.workId
|
|
52
|
+
&& handle.branch === input.executionIdentity.branch
|
|
53
|
+
);
|
|
54
|
+
if (!sameStaticExecutionIdentity(originalHandle)) return { settled: false, reason: 'identity_mismatch' };
|
|
55
|
+
if (originalHandle.state === 'merged' || originalHandle.state === 'cleaned' || originalHandle.state === 'failed_terminal_cleanup') {
|
|
55
56
|
return { settled: false, reason: 'terminal_handle' };
|
|
56
57
|
}
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
58
|
+
// A Work head settlement only runs for a Work-bound (repository) command, so
|
|
59
|
+
// the scope target is a registered repository record at this point.
|
|
60
|
+
const status = repositoryGitStatus(input.repository as RepositoryRecord);
|
|
61
|
+
if (!status.branch || status.branch !== originalHandle.branch) {
|
|
62
|
+
return { settled: false, reason: 'branch_changed', previousHead: originalHandle.expectedHead, currentHead: status.head ?? undefined };
|
|
60
63
|
}
|
|
61
64
|
const currentHead = status.head?.trim();
|
|
62
|
-
if (!currentHead) return { settled: false, reason: 'head_unavailable', previousHead:
|
|
63
|
-
|
|
64
|
-
|
|
65
|
+
if (!currentHead) return { settled: false, reason: 'head_unavailable', previousHead: originalHandle.expectedHead };
|
|
66
|
+
const originalAuthorityHead = input.executionIdentity.expectedHead;
|
|
67
|
+
if (originalHandle.expectedHead === currentHead) {
|
|
68
|
+
if (originalAuthorityHead !== undefined && originalAuthorityHead !== currentHead) {
|
|
69
|
+
return { settled: true, reason: 'settled', previousHead: originalAuthorityHead, currentHead };
|
|
70
|
+
}
|
|
71
|
+
return { settled: false, reason: 'head_unchanged', previousHead: originalHandle.expectedHead, currentHead };
|
|
72
|
+
}
|
|
73
|
+
if (originalAuthorityHead !== undefined && originalHandle.expectedHead !== originalAuthorityHead) {
|
|
74
|
+
return { settled: false, reason: 'identity_mismatch', previousHead: originalHandle.expectedHead, currentHead };
|
|
75
|
+
}
|
|
76
|
+
try {
|
|
77
|
+
transitionWorkHandle(input.controllerHome, originalHandle, originalHandle.state, { expectedHead: currentHead });
|
|
78
|
+
return { settled: true, reason: 'settled', previousHead: originalHandle.expectedHead, currentHead };
|
|
79
|
+
} catch (error) {
|
|
80
|
+
if (!(error instanceof Error) || !error.message.includes('CONTROL_PLANE_REVISION_CONFLICT')) throw error;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// One concurrent lifecycle write is allowed to win the first CAS. Re-read the
|
|
84
|
+
// exact Work authority and converge only when identity/branch are unchanged.
|
|
85
|
+
const refreshedHandle = readWorkHandle(input.controllerHome, commandExecutionScopeKey(input.repository), workId);
|
|
86
|
+
if (!refreshedHandle) return { settled: false, reason: 'work_handle_missing', previousHead: originalHandle.expectedHead, currentHead };
|
|
87
|
+
if (!sameStaticExecutionIdentity(refreshedHandle)) {
|
|
88
|
+
return { settled: false, reason: 'identity_mismatch', previousHead: refreshedHandle.expectedHead, currentHead };
|
|
89
|
+
}
|
|
90
|
+
if (refreshedHandle.expectedHead !== currentHead && originalAuthorityHead !== undefined && refreshedHandle.expectedHead !== originalAuthorityHead) {
|
|
91
|
+
return { settled: false, reason: 'identity_mismatch', previousHead: refreshedHandle.expectedHead, currentHead };
|
|
92
|
+
}
|
|
93
|
+
if (refreshedHandle.state === 'merged' || refreshedHandle.state === 'cleaned' || refreshedHandle.state === 'failed_terminal_cleanup') {
|
|
94
|
+
return { settled: false, reason: 'terminal_handle', previousHead: refreshedHandle.expectedHead, currentHead };
|
|
95
|
+
}
|
|
96
|
+
if (refreshedHandle.expectedHead === currentHead) {
|
|
97
|
+
return { settled: true, reason: 'settled', previousHead: originalHandle.expectedHead, currentHead };
|
|
65
98
|
}
|
|
66
99
|
try {
|
|
67
|
-
transitionWorkHandle(input.controllerHome,
|
|
68
|
-
return { settled: true, reason: 'settled', previousHead:
|
|
100
|
+
transitionWorkHandle(input.controllerHome, refreshedHandle, refreshedHandle.state, { expectedHead: currentHead });
|
|
101
|
+
return { settled: true, reason: 'settled', previousHead: refreshedHandle.expectedHead, currentHead };
|
|
69
102
|
} catch (error) {
|
|
70
103
|
if (error instanceof Error && error.message.includes('CONTROL_PLANE_REVISION_CONFLICT')) {
|
|
71
|
-
return { settled: false, reason: 'concurrent_lifecycle_write', previousHead:
|
|
104
|
+
return { settled: false, reason: 'concurrent_lifecycle_write', previousHead: refreshedHandle.expectedHead, currentHead };
|
|
72
105
|
}
|
|
73
106
|
throw error;
|
|
74
107
|
}
|