@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
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { existsSync, readdirSync, rmSync, statSync } from 'fs';
|
|
1
|
+
import { existsSync, lstatSync, readdirSync, rmdirSync, rmSync, statSync } from 'fs';
|
|
2
2
|
import { spawnSync } from 'child_process';
|
|
3
3
|
import { join, relative, resolve } from 'path';
|
|
4
4
|
import { repositoryControllerRoot } from '../../cli/repositories/controller-home';
|
|
@@ -37,6 +37,8 @@ export interface CleanupArtifactRetentionOptions {
|
|
|
37
37
|
graceMs?: number;
|
|
38
38
|
maxEntries?: number;
|
|
39
39
|
maxRemovals?: number;
|
|
40
|
+
scanSequence?: number;
|
|
41
|
+
repositoryIds?: readonly string[];
|
|
40
42
|
}
|
|
41
43
|
|
|
42
44
|
export interface CleanupArtifactRetentionReport {
|
|
@@ -190,6 +192,48 @@ function retentionTimestamp(receipt: WorkCleanupReceipt, bundlePath: string): nu
|
|
|
190
192
|
}
|
|
191
193
|
}
|
|
192
194
|
|
|
195
|
+
function bundleProtectedRevision(repositoryRoot: string, bundlePath: string): string | undefined {
|
|
196
|
+
if (!git(repositoryRoot, ['bundle', 'verify', bundlePath]).ok) return undefined;
|
|
197
|
+
const heads = git(repositoryRoot, ['bundle', 'list-heads', bundlePath]);
|
|
198
|
+
if (!heads.ok) return undefined;
|
|
199
|
+
const revisions = [...new Set(heads.stdout.split('\n').map((line) => line.trim().split(/\s+/, 1)[0]).filter((value) => /^[a-f0-9]{40,64}$/i.test(value ?? '')))];
|
|
200
|
+
return revisions.length === 1 ? revisions[0] : undefined;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
function proveOrphanBundleContained(
|
|
204
|
+
repositoryRoot: string,
|
|
205
|
+
bundlePath: string,
|
|
206
|
+
targetBranch: string,
|
|
207
|
+
): { contained: boolean; reason: string } {
|
|
208
|
+
const protectedRevision = bundleProtectedRevision(repositoryRoot, bundlePath);
|
|
209
|
+
if (!protectedRevision) return { contained: false, reason: 'orphan_bundle_invalid_or_ambiguous' };
|
|
210
|
+
if (!revision(repositoryRoot, protectedRevision)) {
|
|
211
|
+
return { contained: false, reason: 'orphan_protected_revision_unavailable' };
|
|
212
|
+
}
|
|
213
|
+
const targetRevision = revision(repositoryRoot, `refs/heads/${targetBranch}`);
|
|
214
|
+
if (!targetRevision) return { contained: false, reason: 'orphan_target_revision_unavailable' };
|
|
215
|
+
const remoteRevision = revision(repositoryRoot, `refs/remotes/origin/${targetBranch}`);
|
|
216
|
+
if (!remoteRevision) return { contained: false, reason: 'orphan_remote_revision_unavailable' };
|
|
217
|
+
// Anchor the inferred delta against the durable remote target. Using the
|
|
218
|
+
// local target here could collapse the delta to empty when only the local
|
|
219
|
+
// branch contains the preserved tip, falsely treating an undelivered bundle
|
|
220
|
+
// as redundant.
|
|
221
|
+
const base = git(repositoryRoot, ['merge-base', protectedRevision, remoteRevision]);
|
|
222
|
+
if (!base.ok || !base.stdout) return { contained: false, reason: 'orphan_merge_base_unavailable' };
|
|
223
|
+
const paths = changedPaths(repositoryRoot, base.stdout, protectedRevision);
|
|
224
|
+
if (!paths) return { contained: false, reason: 'orphan_diff_unavailable' };
|
|
225
|
+
for (const path of paths) {
|
|
226
|
+
const protectedEntry = treeEntry(repositoryRoot, protectedRevision, path);
|
|
227
|
+
const targetEntry = treeEntry(repositoryRoot, targetRevision, path);
|
|
228
|
+
const remoteEntry = treeEntry(repositoryRoot, remoteRevision, path);
|
|
229
|
+
if (protectedEntry === undefined || targetEntry === undefined || remoteEntry === undefined
|
|
230
|
+
|| protectedEntry !== targetEntry || protectedEntry !== remoteEntry) {
|
|
231
|
+
return { contained: false, reason: 'orphan_content_mismatch' };
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
return { contained: true, reason: paths.length === 0 ? 'orphan_no_source_delta' : 'orphan_target_and_remote_content_contained' };
|
|
235
|
+
}
|
|
236
|
+
|
|
193
237
|
function retirementFromProof(
|
|
194
238
|
proof: WorkPreservationContainmentProof,
|
|
195
239
|
status: 'eligible' | 'removed' | 'not_needed',
|
|
@@ -232,27 +276,36 @@ export function cleanupWorkPreservationArtifacts(
|
|
|
232
276
|
const repositoriesRoot = join(controllerHome, 'repositories');
|
|
233
277
|
let repositoryIds: string[] = [];
|
|
234
278
|
try {
|
|
279
|
+
const repositoryFilter = options.repositoryIds ? new Set(options.repositoryIds.map((id) => id.trim()).filter(Boolean)) : undefined;
|
|
235
280
|
repositoryIds = readdirSync(repositoriesRoot, { withFileTypes: true })
|
|
236
|
-
.filter((entry) => entry.isDirectory())
|
|
281
|
+
.filter((entry) => entry.isDirectory() && (!repositoryFilter || repositoryFilter.has(entry.name)))
|
|
237
282
|
.map((entry) => entry.name)
|
|
238
283
|
.sort();
|
|
239
284
|
} catch {
|
|
240
285
|
return report;
|
|
241
286
|
}
|
|
287
|
+
const scanSequence = Math.trunc(options.scanSequence ?? Math.floor(nowMs / 60_000));
|
|
288
|
+
if (repositoryIds.length > 1) {
|
|
289
|
+
const offset = ((scanSequence % repositoryIds.length) + repositoryIds.length) % repositoryIds.length;
|
|
290
|
+
repositoryIds.push(...repositoryIds.splice(0, offset));
|
|
291
|
+
}
|
|
292
|
+
let handleInspected = 0;
|
|
293
|
+
let physicalInspected = 0;
|
|
242
294
|
|
|
243
|
-
|
|
295
|
+
for (const repositoryId of repositoryIds) {
|
|
244
296
|
let repository;
|
|
245
297
|
try {
|
|
246
298
|
repository = getRepository(repositoryId, controllerHome, { includeRemoved: true });
|
|
247
299
|
} catch {
|
|
248
300
|
continue;
|
|
249
301
|
}
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
302
|
+
const repositoryHandles = listWorkHandles(controllerHome, repositoryId)
|
|
303
|
+
.sort((left, right) => left.workId.localeCompare(right.workId));
|
|
304
|
+
if (repositoryHandles.length > 1) {
|
|
305
|
+
const offset = ((scanSequence % repositoryHandles.length) + repositoryHandles.length) % repositoryHandles.length;
|
|
306
|
+
repositoryHandles.push(...repositoryHandles.splice(0, offset));
|
|
307
|
+
}
|
|
308
|
+
for (let handle of repositoryHandles) {
|
|
256
309
|
const receipt = handle.cleanupReceipt;
|
|
257
310
|
const bundlePath = receipt?.preservation.bundlePath;
|
|
258
311
|
const retirement = receipt?.preservation.bundleRetirement;
|
|
@@ -265,6 +318,12 @@ export function cleanupWorkPreservationArtifacts(
|
|
|
265
318
|
}
|
|
266
319
|
}
|
|
267
320
|
if (!receipt || !bundlePath) continue;
|
|
321
|
+
if (handleInspected >= maxEntries) {
|
|
322
|
+
report.budgetExhausted = true;
|
|
323
|
+
break;
|
|
324
|
+
}
|
|
325
|
+
handleInspected += 1;
|
|
326
|
+
report.inspected += 1;
|
|
268
327
|
const expectedPath = resolve(expectedBundlePath(controllerHome, handle));
|
|
269
328
|
if (resolve(bundlePath) !== expectedPath) {
|
|
270
329
|
report.retained += 1;
|
|
@@ -303,6 +362,7 @@ export function cleanupWorkPreservationArtifacts(
|
|
|
303
362
|
handle = writeWorkHandle(controllerHome, { ...handle, cleanupReceipt: eligibleReceipt, updatedAt: nowIso });
|
|
304
363
|
const measurement = existsSync(bundlePath) ? measureReclaimablePath(bundlePath) : { bytes: 0, entries: 0, complete: true };
|
|
305
364
|
if (existsSync(bundlePath)) rmSync(bundlePath, { force: true });
|
|
365
|
+
try { rmdirSync(join(bundlePath, '..')); } catch { /* Preserve non-empty or concurrently changed directories. */ }
|
|
306
366
|
if (measurement.complete) report.reclaimedBytes += measurement.bytes;
|
|
307
367
|
else report.unknownReclaimedByteCount += 1;
|
|
308
368
|
const currentReceipt = handle.cleanupReceipt!;
|
|
@@ -323,6 +383,149 @@ export function cleanupWorkPreservationArtifacts(
|
|
|
323
383
|
report.errors.push(`${handle.workId}: ${error instanceof Error ? error.message : String(error)}`);
|
|
324
384
|
}
|
|
325
385
|
}
|
|
386
|
+
|
|
387
|
+
// WorkHandle metadata is not physical-retention authority. Discover direct
|
|
388
|
+
// preservation directories as well so a missing or drifted handle cannot
|
|
389
|
+
// make an owned bundle immortal. This pass remains fail-closed: only the
|
|
390
|
+
// canonical direct child containing exactly branch.bundle is considered;
|
|
391
|
+
// symlinks and extra content are retained, and source containment still
|
|
392
|
+
// requires proof.
|
|
393
|
+
const artifactRoot = join(repositoryControllerRoot(controllerHome, repositoryId), 'cleanup-artifacts');
|
|
394
|
+
let artifactEntries;
|
|
395
|
+
try {
|
|
396
|
+
if (!lstatSync(artifactRoot).isDirectory()) continue;
|
|
397
|
+
artifactEntries = readdirSync(artifactRoot, { withFileTypes: true })
|
|
398
|
+
.sort((left, right) => left.name.localeCompare(right.name));
|
|
399
|
+
if (artifactEntries.length > 1) {
|
|
400
|
+
const offset = ((scanSequence % artifactEntries.length) + artifactEntries.length) % artifactEntries.length;
|
|
401
|
+
artifactEntries.push(...artifactEntries.splice(0, offset));
|
|
402
|
+
}
|
|
403
|
+
} catch {
|
|
404
|
+
continue;
|
|
405
|
+
}
|
|
406
|
+
const physicalHandles = repositoryHandles;
|
|
407
|
+
const handles = new Map(physicalHandles.map((handle) => [handle.workId, handle]));
|
|
408
|
+
const referencedBundlePaths = new Set(physicalHandles.flatMap((handle) => {
|
|
409
|
+
const path = handle.cleanupReceipt?.preservation.bundlePath;
|
|
410
|
+
return path ? [resolve(path)] : [];
|
|
411
|
+
}));
|
|
412
|
+
for (const entry of artifactEntries) {
|
|
413
|
+
if (!entry.isDirectory()) continue;
|
|
414
|
+
const directoryPath = join(artifactRoot, entry.name);
|
|
415
|
+
const handle = handles.get(entry.name);
|
|
416
|
+
const canonicalBundlePath = resolve(join(directoryPath, 'branch.bundle'));
|
|
417
|
+
if (referencedBundlePaths.has(canonicalBundlePath)) continue;
|
|
418
|
+
if (physicalInspected >= maxEntries) {
|
|
419
|
+
report.budgetExhausted = true;
|
|
420
|
+
break;
|
|
421
|
+
}
|
|
422
|
+
physicalInspected += 1;
|
|
423
|
+
report.inspected += 1;
|
|
424
|
+
let contents: string[];
|
|
425
|
+
let bundlePath: string;
|
|
426
|
+
try {
|
|
427
|
+
contents = readdirSync(directoryPath).sort();
|
|
428
|
+
if (contents.length !== 1 || contents[0] !== 'branch.bundle') {
|
|
429
|
+
report.retained += 1;
|
|
430
|
+
skip(report, 'physical_bundle_unrecognized_content');
|
|
431
|
+
continue;
|
|
432
|
+
}
|
|
433
|
+
bundlePath = join(directoryPath, 'branch.bundle');
|
|
434
|
+
const bundleStat = lstatSync(bundlePath);
|
|
435
|
+
if (!bundleStat.isFile() || bundleStat.isSymbolicLink()) {
|
|
436
|
+
report.retained += 1;
|
|
437
|
+
skip(report, 'physical_bundle_unrecognized_content');
|
|
438
|
+
continue;
|
|
439
|
+
}
|
|
440
|
+
} catch (error) {
|
|
441
|
+
report.retained += 1;
|
|
442
|
+
skip(report, 'physical_bundle_unreadable');
|
|
443
|
+
report.errors.push(`${repositoryId}:${entry.name}: ${error instanceof Error ? error.message : String(error)}`);
|
|
444
|
+
continue;
|
|
445
|
+
}
|
|
446
|
+
if (handle?.cleanupReceipt?.preservation.bundlePath
|
|
447
|
+
&& resolve(handle.cleanupReceipt.preservation.bundlePath) !== resolve(bundlePath)) {
|
|
448
|
+
report.retained += 1;
|
|
449
|
+
skip(report, 'bundle_metadata_conflict');
|
|
450
|
+
continue;
|
|
451
|
+
}
|
|
452
|
+
let timestamp: number | undefined;
|
|
453
|
+
try {
|
|
454
|
+
timestamp = handle?.cleanupReceipt
|
|
455
|
+
? retentionTimestamp(handle.cleanupReceipt, bundlePath)
|
|
456
|
+
: statSync(bundlePath).mtimeMs;
|
|
457
|
+
} catch (error) {
|
|
458
|
+
report.retained += 1;
|
|
459
|
+
skip(report, 'physical_bundle_unreadable');
|
|
460
|
+
report.errors.push(`${repositoryId}:${entry.name}: ${error instanceof Error ? error.message : String(error)}`);
|
|
461
|
+
continue;
|
|
462
|
+
}
|
|
463
|
+
if (timestamp === undefined || nowMs - timestamp < graceMs) {
|
|
464
|
+
report.retained += 1;
|
|
465
|
+
skip(report, 'retention_grace');
|
|
466
|
+
continue;
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
const receipt = handle?.cleanupReceipt;
|
|
470
|
+
const handleProof = handle && receipt?.complete
|
|
471
|
+
? proveWorkPreservationContained(repository.canonicalRoot, handle, receipt.targetBranch)
|
|
472
|
+
: undefined;
|
|
473
|
+
const orphanProof = !handle && repository.defaultBranch
|
|
474
|
+
? proveOrphanBundleContained(repository.canonicalRoot, bundlePath, repository.defaultBranch)
|
|
475
|
+
: undefined;
|
|
476
|
+
if (handle && (!receipt?.complete || !handleProof?.contained)) {
|
|
477
|
+
report.retained += 1;
|
|
478
|
+
skip(report, !receipt?.complete ? 'physical_bundle_incomplete_handle' : `containment_${handleProof!.reason}`);
|
|
479
|
+
continue;
|
|
480
|
+
}
|
|
481
|
+
if (!handle && !orphanProof?.contained) {
|
|
482
|
+
report.retained += 1;
|
|
483
|
+
skip(report, orphanProof?.reason ?? (repository.defaultBranch
|
|
484
|
+
? 'orphan_source_containment_unproven'
|
|
485
|
+
: 'orphan_target_branch_unavailable'));
|
|
486
|
+
continue;
|
|
487
|
+
}
|
|
488
|
+
report.eligible += 1;
|
|
489
|
+
if (remaining <= 0) {
|
|
490
|
+
report.budgetExhausted = true;
|
|
491
|
+
skip(report, 'cleanup_budget_exhausted');
|
|
492
|
+
continue;
|
|
493
|
+
}
|
|
494
|
+
report.attempted += 1;
|
|
495
|
+
remaining -= 1;
|
|
496
|
+
try {
|
|
497
|
+
const measurement = measureReclaimablePath(bundlePath);
|
|
498
|
+
if (handle && receipt && handleProof) {
|
|
499
|
+
const eligibleReceipt: WorkCleanupReceipt = {
|
|
500
|
+
...receipt,
|
|
501
|
+
preservation: { ...receipt.preservation, bundlePath, bundleRetirement: retirementFromProof(handleProof, 'eligible', nowIso) },
|
|
502
|
+
updatedAt: nowIso,
|
|
503
|
+
};
|
|
504
|
+
const updated = writeWorkHandle(controllerHome, { ...handle, cleanupReceipt: eligibleReceipt, updatedAt: nowIso });
|
|
505
|
+
rmSync(bundlePath, { force: true });
|
|
506
|
+
const removedReceipt: WorkCleanupReceipt = {
|
|
507
|
+
...updated.cleanupReceipt!,
|
|
508
|
+
preservation: {
|
|
509
|
+
...updated.cleanupReceipt!.preservation,
|
|
510
|
+
bundlePath: undefined,
|
|
511
|
+
bundleSha256: undefined,
|
|
512
|
+
bundleRetirement: retirementFromProof(handleProof, 'removed', nowIso),
|
|
513
|
+
recoveryInstructions: `Preservation bundle retired after ${handleProof.reason}; exact proof is stored in cleanupReceipt.preservation.bundleRetirement.`,
|
|
514
|
+
},
|
|
515
|
+
updatedAt: nowIso,
|
|
516
|
+
};
|
|
517
|
+
writeWorkHandle(controllerHome, { ...updated, cleanupReceipt: removedReceipt, updatedAt: nowIso });
|
|
518
|
+
} else {
|
|
519
|
+
rmSync(bundlePath, { force: true });
|
|
520
|
+
}
|
|
521
|
+
try { rmdirSync(directoryPath); } catch { /* Preserve concurrently populated directories. */ }
|
|
522
|
+
if (measurement.complete) report.reclaimedBytes += measurement.bytes;
|
|
523
|
+
else report.unknownReclaimedByteCount += 1;
|
|
524
|
+
report.removedPaths.push(relative(controllerHome, bundlePath).replace(/\\/g, '/'));
|
|
525
|
+
} catch (error) {
|
|
526
|
+
report.errors.push(`${repositoryId}:${entry.name}: ${error instanceof Error ? error.message : String(error)}`);
|
|
527
|
+
}
|
|
528
|
+
}
|
|
326
529
|
}
|
|
327
530
|
return report;
|
|
328
531
|
}
|
|
@@ -2,7 +2,7 @@ import {
|
|
|
2
2
|
buildWorkExecutionConcurrencyContract,
|
|
3
3
|
evaluateWorkExecutionCompatibility,
|
|
4
4
|
getWorkContract,
|
|
5
|
-
|
|
5
|
+
semanticWorkState,
|
|
6
6
|
readActiveWorkCandidates,
|
|
7
7
|
workExecutionLaneMutates,
|
|
8
8
|
updateWorkContract,
|
|
@@ -16,7 +16,6 @@ import type { ResourceClaimSpec } from '../../execution/jobs/types';
|
|
|
16
16
|
import { listProcessRecords } from '../../execution/process-runtime/store';
|
|
17
17
|
import { listActiveLeases } from '../../resources/leases/store';
|
|
18
18
|
import { claimsConflict } from '../../resources/claims/conflicts';
|
|
19
|
-
import { getControllerSession } from '../../../../packages/kernel/controller/api/index';
|
|
20
19
|
import {
|
|
21
20
|
isManagedProcessActive,
|
|
22
21
|
type ExecutionConcurrencyWaitProjection,
|
|
@@ -101,34 +100,6 @@ export interface RuntimeWorkCompatibilityDecision {
|
|
|
101
100
|
wait?: ExecutionConcurrencyWaitProjection;
|
|
102
101
|
}
|
|
103
102
|
|
|
104
|
-
function invalidActiveWorkCompatibility(
|
|
105
|
-
candidate: WorkExecutionConcurrencyContract,
|
|
106
|
-
invalid: ReturnType<typeof readActiveWorkCandidates>['invalid'],
|
|
107
|
-
): ExecutionConcurrencyWaitProjection | undefined {
|
|
108
|
-
if (!workExecutionLaneMutates(candidate.lane)) return undefined;
|
|
109
|
-
for (const current of invalid) {
|
|
110
|
-
if (current.workId === candidate.workId) continue;
|
|
111
|
-
const currentScope = new Set(current.semanticScopeKeys);
|
|
112
|
-
const overlap = candidate.semanticScopeKeys.filter((key) => currentScope.has(key));
|
|
113
|
-
if (overlap.length === 0
|
|
114
|
-
&& candidate.lane === 'isolated_write'
|
|
115
|
-
&& candidate.isolation === 'isolated'
|
|
116
|
-
&& current.isolation === 'isolated') continue;
|
|
117
|
-
return executionConcurrencyWaitProjection({
|
|
118
|
-
source: 'work_compatibility',
|
|
119
|
-
blockerCode: 'work_contract_invalid',
|
|
120
|
-
disposition: 'invalid',
|
|
121
|
-
blockingWorkId: current.workId,
|
|
122
|
-
semanticScopeKeys: overlap.length > 0 ? overlap : current.semanticScopeKeys,
|
|
123
|
-
resourceKeys: candidate.resourceIntents
|
|
124
|
-
.filter((intent) => intent.mode !== 'read')
|
|
125
|
-
.map((intent) => intent.resourceKey),
|
|
126
|
-
wakeTrigger: { kind: 'work_contract_change', workId: current.workId },
|
|
127
|
-
});
|
|
128
|
-
}
|
|
129
|
-
return undefined;
|
|
130
|
-
}
|
|
131
|
-
|
|
132
103
|
function contractForProcess(
|
|
133
104
|
controllerHome: string,
|
|
134
105
|
repoId: string,
|
|
@@ -181,18 +152,12 @@ export function evaluateManagedProcessWorkCompatibility(input: {
|
|
|
181
152
|
.filter((record) => record.processId !== input.processId && record.workId && isManagedProcessActive(record))
|
|
182
153
|
.map((record) => contractForProcess(input.controllerHome, input.repoId, record))
|
|
183
154
|
.filter((value): value is WorkExecutionConcurrencyContract => Boolean(value));
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
const invalidWait = invalidActiveWorkCompatibility(candidate, activeSnapshot.invalid);
|
|
191
|
-
if (invalidWait) return { compatible: false, hardBlocked: true, wait: invalidWait };
|
|
192
|
-
const activeWorkContracts = activeSnapshot.contracts
|
|
193
|
-
.filter((activeWork) => activeWork.workId !== input.workId && !worksWithActiveProcesses.has(activeWork.workId))
|
|
194
|
-
.map((activeWork) => buildWorkExecutionConcurrencyContract(activeWork));
|
|
195
|
-
const decision = evaluateWorkExecutionCompatibility(candidate, [...activeProcessContracts, ...activeWorkContracts]);
|
|
155
|
+
// Thin Work is semantic context, not a physical execution lease. An open Work
|
|
156
|
+
// with no running Process must not reserve the shared checkout or make another
|
|
157
|
+
// Process wait for semantic terminalization. Concrete Process contracts own
|
|
158
|
+
// in-flight compatibility here; durable WorkHandle and resource-lease fences
|
|
159
|
+
// separately protect repository mutation across Process lifetimes.
|
|
160
|
+
const decision = evaluateWorkExecutionCompatibility(candidate, activeProcessContracts);
|
|
196
161
|
const blocker = decision.blockers[0];
|
|
197
162
|
return blocker
|
|
198
163
|
? { compatible: false, hardBlocked: blocker.disposition === 'invalid', wait: blockerProjection(blocker) }
|
|
@@ -225,7 +190,7 @@ export function recordWorkExecutionConcurrencyWait(input: {
|
|
|
225
190
|
const workId = input.workId?.trim();
|
|
226
191
|
if (!workId) return undefined;
|
|
227
192
|
const work = getWorkContract({ controllerHome: input.controllerHome, repoId: input.repoId }, workId);
|
|
228
|
-
if (!work ||
|
|
193
|
+
if (!work || semanticWorkState(work) !== 'open') return undefined;
|
|
229
194
|
const projection: WorkExecutionConcurrencyProjection = {
|
|
230
195
|
schemaVersion: 1,
|
|
231
196
|
status: input.wait.disposition === 'invalid' ? 'invalid' : 'waiting',
|
|
@@ -275,10 +240,7 @@ function workConcurrencyWakeResolved(input: {
|
|
|
275
240
|
if (input.projection.status === 'invalid' || wake.kind === 'work_contract_change' || wake.kind === 'scheduler_capacity') return false;
|
|
276
241
|
if (wake.kind === 'work_terminal') {
|
|
277
242
|
const blocking = getWorkContract({ controllerHome: input.controllerHome, repoId: input.repoId }, wake.workId);
|
|
278
|
-
return Boolean(blocking &&
|
|
279
|
-
}
|
|
280
|
-
if (wake.kind === 'controller_release') {
|
|
281
|
-
return !getControllerSession({ controllerHome: input.controllerHome, repoId: input.repoId }, wake.workId);
|
|
243
|
+
return Boolean(blocking && semanticWorkState(blocking) !== 'open');
|
|
282
244
|
}
|
|
283
245
|
const activeLeases = listActiveLeases(input.controllerHome, input.projection.leaseRepoId?.trim() || input.repoId);
|
|
284
246
|
return !input.projection.resourceIntents.some((claim) => activeLeases.some((lease) => claimsConflict(claim, lease)));
|
|
@@ -12,7 +12,7 @@ import {
|
|
|
12
12
|
type ControllerTerminalizationAuthority,
|
|
13
13
|
type ControllerType,
|
|
14
14
|
} from '../../../../packages/kernel/controller/api/index';
|
|
15
|
-
import { getWorkContract } from '../../../../packages/kernel/work/api/index';
|
|
15
|
+
import { getWorkContract, semanticWorkState } from '../../../../packages/kernel/work/api/index';
|
|
16
16
|
import { currentPermissionSnapshotVersion } from './validation';
|
|
17
17
|
import { startExecutionSession, updateExecutionSession } from './session-store';
|
|
18
18
|
|
|
@@ -55,8 +55,8 @@ export function recoverDirectControllerAuthority(input: {
|
|
|
55
55
|
const store = { controllerHome: input.controllerHome, repoId: input.repoId };
|
|
56
56
|
const work = getWorkContract(store, workId);
|
|
57
57
|
if (!work) throw new Error(`WORK_NOT_FOUND: ${workId}`);
|
|
58
|
-
if (
|
|
59
|
-
throw new Error(`WORK_CONTROLLER_AUTHORITY_RECOVERY_TERMINAL: ${workId}:${work
|
|
58
|
+
if (semanticWorkState(work) !== 'open') {
|
|
59
|
+
throw new Error(`WORK_CONTROLLER_AUTHORITY_RECOVERY_TERMINAL: ${workId}:${semanticWorkState(work)}`);
|
|
60
60
|
}
|
|
61
61
|
if (getControllerRoundRelay(store, workId)) {
|
|
62
62
|
throw new Error(`WORK_CONTROLLER_AUTHORITY_RECOVERY_RELAY_CONFLICT: ${workId}; relay-bound Work must recover through its exact per-round authority.`);
|
|
@@ -130,6 +130,7 @@ export function recoverControllerAuthority(input: {
|
|
|
130
130
|
repositoryActiveCheckoutId?: string;
|
|
131
131
|
workId: string;
|
|
132
132
|
requestedBy?: string;
|
|
133
|
+
recoveryReason?: string;
|
|
133
134
|
identity: DirectControllerAuthorityRecoveryIdentity;
|
|
134
135
|
runtime: { running?: boolean; runtimeInstanceId?: string };
|
|
135
136
|
leaseMs?: number;
|
|
@@ -142,6 +143,8 @@ export function recoverControllerAuthority(input: {
|
|
|
142
143
|
const relay = recoverControllerRoundRelayAuthority(store, {
|
|
143
144
|
workId: input.workId,
|
|
144
145
|
requestedBy: input.requestedBy,
|
|
146
|
+
recoveryReason: input.recoveryReason,
|
|
147
|
+
allowCanonicalRuntimeMigration: true,
|
|
145
148
|
identity: {
|
|
146
149
|
controllerId: input.identity.controllerId,
|
|
147
150
|
controllerType: input.identity.controllerType,
|
|
@@ -258,6 +261,31 @@ function assertControllerLifecycleInvocationAuthority(
|
|
|
258
261
|
return undefined;
|
|
259
262
|
}
|
|
260
263
|
|
|
264
|
+
/**
|
|
265
|
+
* Modern sessionless MCP replaces its request binding on every call. For a
|
|
266
|
+
* direct Work, omission of an opaque capability is not a semantic ownership
|
|
267
|
+
* change when the exact Work, authenticated controller/principal/type and live
|
|
268
|
+
* canonical Runtime still agree. Relay-bound rounds remain capability-scoped,
|
|
269
|
+
* and an explicitly supplied wrong capability never uses this path.
|
|
270
|
+
*/
|
|
271
|
+
export function controllerInvocationCanMechanicallyRebindDirectOwnership(
|
|
272
|
+
input: ControllerInvocationAuthorityContext & { runtime: { running?: boolean; runtimeInstanceId?: string } },
|
|
273
|
+
owner: ControllerSession | undefined = getControllerSession(
|
|
274
|
+
{ controllerHome: input.controllerHome, repoId: input.repoId },
|
|
275
|
+
input.workId.trim(),
|
|
276
|
+
),
|
|
277
|
+
): boolean {
|
|
278
|
+
const workId = input.workId.trim();
|
|
279
|
+
const store = { controllerHome: input.controllerHome, repoId: input.repoId };
|
|
280
|
+
if (!owner || getControllerRoundRelay(store, workId)) return false;
|
|
281
|
+
if (input.identity.transportSessionId || input.identity.controllerAuthorityId) return false;
|
|
282
|
+
if (owner.controllerId !== input.identity.controllerId || owner.controllerType !== input.identity.controllerType) return false;
|
|
283
|
+
if (controllerSessionPrincipalId(owner) !== input.identity.principalId) return false;
|
|
284
|
+
const requestedInstanceId = input.identity.controllerInstanceId.trim();
|
|
285
|
+
const canonicalRuntimeInstanceId = input.runtime.running ? input.runtime.runtimeInstanceId?.trim() || '' : '';
|
|
286
|
+
return Boolean(requestedInstanceId && canonicalRuntimeInstanceId === requestedInstanceId);
|
|
287
|
+
}
|
|
288
|
+
|
|
261
289
|
/** Bind one exact Work owner to the current transport/runtime without changing semantic ownership. */
|
|
262
290
|
export function bindControllerOwnershipForInvocation(input: ControllerInvocationAuthorityContext & {
|
|
263
291
|
runtime: { running?: boolean; runtimeInstanceId?: string };
|
|
@@ -267,7 +295,9 @@ export function bindControllerOwnershipForInvocation(input: ControllerInvocation
|
|
|
267
295
|
const store = { controllerHome: input.controllerHome, repoId: input.repoId };
|
|
268
296
|
const workId = input.workId.trim();
|
|
269
297
|
const existingOwner = getControllerSession(store, workId);
|
|
270
|
-
|
|
298
|
+
if (!controllerInvocationCanMechanicallyRebindDirectOwnership(input, existingOwner)) {
|
|
299
|
+
assertControllerLifecycleInvocationAuthority(input, existingOwner);
|
|
300
|
+
}
|
|
271
301
|
return bindControllerSessionToCurrentRuntime(store, {
|
|
272
302
|
workId,
|
|
273
303
|
controllerId: input.identity.controllerId,
|
|
@@ -4,13 +4,13 @@ import {
|
|
|
4
4
|
recordEditSessionProcessCheckReceipts,
|
|
5
5
|
type EditSession,
|
|
6
6
|
} from '../../../cli/editing/edit-session';
|
|
7
|
-
import { listControllerChecks } from '../../../cli/controller/check-runner';
|
|
7
|
+
import { listControllerChecks, readLatestControllerCheckEvidence } from '../../../cli/controller/check-runner';
|
|
8
8
|
import type { RepositoryRecord } from '../../../cli/repositories/types';
|
|
9
9
|
import { repositoryGitStatus } from '../../../cli/repositories/structured-git';
|
|
10
10
|
import { selectRepositoryCheckout } from '../../../cli/repositories/registry';
|
|
11
11
|
import { executionIdentityForRepository } from './execution-identity';
|
|
12
12
|
import { getWorkContract } from '../../../../packages/kernel/work/api/index';
|
|
13
|
-
import {
|
|
13
|
+
import { recordWorkCheckEvidence } from './work-check-evidence';
|
|
14
14
|
import { commandFingerprint, verificationInputFingerprint, workspaceValidationFingerprint } from './verification-evidence';
|
|
15
15
|
import {
|
|
16
16
|
claimsForCheck,
|
|
@@ -20,6 +20,7 @@ import {
|
|
|
20
20
|
runPersistedCheckViaProcessRuntime,
|
|
21
21
|
type ProcessCheckCompletionReceipt,
|
|
22
22
|
} from '../../execution/process-runtime';
|
|
23
|
+
import { projectTerminalCheckVerification } from '../../execution/process-runtime/check-result';
|
|
23
24
|
import { resourceClaimsConflict } from '../../resources/claims/conflicts';
|
|
24
25
|
import {
|
|
25
26
|
mutateControlPlaneRecord,
|
|
@@ -451,10 +452,10 @@ export async function reconcileEditValidationRun(
|
|
|
451
452
|
issueId: session.issueId,
|
|
452
453
|
taskId: session.taskId,
|
|
453
454
|
},
|
|
454
|
-
verificationSnapshot:
|
|
455
|
-
workId:
|
|
456
|
-
allowedPaths:
|
|
457
|
-
forbiddenPaths:
|
|
455
|
+
verificationSnapshot: session.workId ? {
|
|
456
|
+
workId: session.workId,
|
|
457
|
+
allowedPaths: session.allowedPaths,
|
|
458
|
+
forbiddenPaths: [],
|
|
458
459
|
} : undefined,
|
|
459
460
|
leaseWaitMs: run.leaseWaitMs,
|
|
460
461
|
});
|
|
@@ -492,36 +493,44 @@ export async function reconcileEditValidationRun(
|
|
|
492
493
|
|
|
493
494
|
try {
|
|
494
495
|
const receipts = run.checkIds.map((checkId) => receiptFor(controllerHome, validationRepository, run, checkId));
|
|
496
|
+
const projections = receipts.map((receipt, index) => {
|
|
497
|
+
const record = records[index]!;
|
|
498
|
+
const legacyEvidence = record.origin?.checkResultReceiptPath
|
|
499
|
+
? undefined
|
|
500
|
+
: readLatestControllerCheckEvidence(validationRepository.canonicalRoot, receipt.checkId);
|
|
501
|
+
return projectTerminalCheckVerification(record, receipt.checkId, receipt, { legacyEvidence });
|
|
502
|
+
});
|
|
503
|
+
const infrastructureProjectionIndex = projections.findIndex((projection) => projection.outcome === 'infrastructure_failure');
|
|
504
|
+
if (infrastructureProjectionIndex >= 0) {
|
|
505
|
+
const receipt = receipts[infrastructureProjectionIndex]!;
|
|
506
|
+
const projection = projections[infrastructureProjectionIndex]!;
|
|
507
|
+
throw new Error(`EDIT_VALIDATION_CHECK_INFRASTRUCTURE_FAILURE: ${receipt.checkId}: ${projection.infrastructureReason ?? projection.evidence.warning ?? receipt.summary}`);
|
|
508
|
+
}
|
|
495
509
|
if (session.workId && work) {
|
|
496
510
|
if (!run.sourceRevision || !run.workspaceFingerprint) throw new Error('EDIT_VALIDATION_WORK_IDENTITY_REQUIRED');
|
|
497
511
|
const availableChecks = listControllerChecks(validationRepository.canonicalRoot);
|
|
498
|
-
const
|
|
499
|
-
|
|
500
|
-
handoffStore: { controllerHome, repoId: validationRepository.repoId },
|
|
501
|
-
repoId: validationRepository.repoId,
|
|
502
|
-
availableChecks,
|
|
503
|
-
sourceRevision: run.sourceRevision,
|
|
504
|
-
workspaceFingerprint: run.workspaceFingerprint,
|
|
505
|
-
};
|
|
506
|
-
for (const receipt of receipts) {
|
|
512
|
+
const workStore = { controllerHome, repoId: validationRepository.repoId };
|
|
513
|
+
for (const [index, receipt] of receipts.entries()) {
|
|
507
514
|
const checkId = receipt.checkId;
|
|
515
|
+
const projection = projections[index]!;
|
|
508
516
|
const inputFingerprint = verificationInputFingerprint({
|
|
509
517
|
sourceRevision: run.sourceRevision,
|
|
510
518
|
workspaceFingerprint: run.workspaceFingerprint,
|
|
511
519
|
checkId,
|
|
512
520
|
requestedChecks: work.checks.length ? work.checks : run.checkIds,
|
|
513
521
|
});
|
|
514
|
-
|
|
515
|
-
|
|
522
|
+
recordWorkCheckEvidence({
|
|
523
|
+
store: workStore,
|
|
516
524
|
workId: session.workId,
|
|
517
525
|
checkId,
|
|
526
|
+
availableChecks,
|
|
518
527
|
sourceRevision: run.sourceRevision,
|
|
519
528
|
workspaceFingerprint: run.workspaceFingerprint,
|
|
520
529
|
verificationInputFingerprint: inputFingerprint,
|
|
521
530
|
commandFingerprint: commandFingerprint(checkId, receipt.commandId),
|
|
522
531
|
receipt,
|
|
523
|
-
infrastructureFailed,
|
|
524
|
-
checkFailed:
|
|
532
|
+
infrastructureFailed: projection.isInfrastructureIssue,
|
|
533
|
+
checkFailed: projection.isAcceptanceFailure,
|
|
525
534
|
});
|
|
526
535
|
}
|
|
527
536
|
}
|
|
@@ -535,7 +544,7 @@ export async function reconcileEditValidationRun(
|
|
|
535
544
|
run = saveRun(controllerHome, {
|
|
536
545
|
...run,
|
|
537
546
|
status: 'completed',
|
|
538
|
-
ok:
|
|
547
|
+
ok: projections.every((projection) => projection.outcome === 'valid_pass'),
|
|
539
548
|
receipts,
|
|
540
549
|
error: undefined,
|
|
541
550
|
});
|
|
@@ -25,12 +25,15 @@ export type ExecutionIdentityErrorCode =
|
|
|
25
25
|
| 'REPOSITORY_NOT_EXECUTABLE'
|
|
26
26
|
| 'LEGACY_WORK_IDENTITY_AMBIGUOUS'
|
|
27
27
|
| 'LEGACY_WORK_IDENTITY_REJECTED'
|
|
28
|
-
| 'WORKSPACE_SCOPE_MISMATCH'
|
|
28
|
+
| 'WORKSPACE_SCOPE_MISMATCH'
|
|
29
|
+
| 'FORGE_INSTANCE_SCOPE_MISMATCH';
|
|
29
30
|
|
|
30
31
|
export interface ResolvedExecutionIdentity {
|
|
31
32
|
readonly schemaVersion: 1;
|
|
32
|
-
readonly authority?: 'repository' | 'ephemeral_workspace';
|
|
33
|
+
readonly authority?: 'repository' | 'ephemeral_workspace' | 'forge_instance';
|
|
34
|
+
/** Legacy storage coordinate. For forge_instance authority this is the reserved Process scope key `instance`, not a Repository id. */
|
|
33
35
|
readonly repositoryId: string;
|
|
36
|
+
/** Legacy storage coordinate. For forge_instance authority this is `instance`, not a checkout. */
|
|
34
37
|
readonly checkoutId: string;
|
|
35
38
|
readonly canonicalRoot: string;
|
|
36
39
|
readonly workId?: string;
|
|
@@ -253,7 +256,7 @@ export function executionIdentityFromCoordinates(input: {
|
|
|
253
256
|
branch?: string;
|
|
254
257
|
expectedHead?: string;
|
|
255
258
|
allowArchived?: boolean;
|
|
256
|
-
authority?: 'repository' | 'ephemeral_workspace';
|
|
259
|
+
authority?: 'repository' | 'ephemeral_workspace' | 'forge_instance';
|
|
257
260
|
}): ResolvedExecutionIdentity {
|
|
258
261
|
if (!input.repositoryId.trim() || !input.checkoutId.trim() || !input.canonicalRoot.trim()) {
|
|
259
262
|
fail('EXECUTION_IDENTITY_REQUIRED', 'repositoryId, checkoutId, and canonicalRoot are required');
|
|
@@ -331,6 +334,23 @@ export function assertExecutionIdentity(input: {
|
|
|
331
334
|
});
|
|
332
335
|
}
|
|
333
336
|
|
|
337
|
+
if (identity.authority === 'forge_instance') {
|
|
338
|
+
const instanceRoot = realpathOrFail(identity.canonicalRoot, 'WORKTREE_MISSING', 'ForgeInstance execution root');
|
|
339
|
+
const requestedCwd = isAbsolute(input.cwd) ? input.cwd : resolve(instanceRoot, input.cwd);
|
|
340
|
+
const resolvedCwd = realpathOrFail(requestedCwd, 'WORKTREE_MISSING', 'process cwd');
|
|
341
|
+
if (!statSync(resolvedCwd).isDirectory()) {
|
|
342
|
+
fail('FORGE_INSTANCE_SCOPE_MISMATCH', 'process cwd is not a directory', { actual: resolvedCwd });
|
|
343
|
+
}
|
|
344
|
+
const cwdRelative = relative(instanceRoot, resolvedCwd);
|
|
345
|
+
if (cwdRelative === '..' || cwdRelative.startsWith('../') || cwdRelative.startsWith('..\\')) {
|
|
346
|
+
fail('FORGE_INSTANCE_SCOPE_MISMATCH', 'process cwd escapes ForgeInstance execution root', {
|
|
347
|
+
expected: instanceRoot,
|
|
348
|
+
actual: resolvedCwd,
|
|
349
|
+
});
|
|
350
|
+
}
|
|
351
|
+
return Object.freeze({ ...identity, canonicalRoot: instanceRoot, resolvedCwd });
|
|
352
|
+
}
|
|
353
|
+
|
|
334
354
|
if (identity.authority === 'ephemeral_workspace') {
|
|
335
355
|
const workspaceRoot = realpathOrFail(identity.canonicalRoot, 'WORKTREE_MISSING', 'ephemeral workspace root');
|
|
336
356
|
const requestedCwd = isAbsolute(input.cwd) ? input.cwd : resolve(workspaceRoot, input.cwd);
|