@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,6 +1,6 @@
|
|
|
1
1
|
import { existsSync, lstatSync, opendirSync, statSync, unlinkSync } from 'fs';
|
|
2
2
|
import { join, relative } from 'path';
|
|
3
|
-
import {
|
|
3
|
+
import { isTerminalSemanticWorkState, type WorkContract } from '../../../../packages/kernel/work/api/index';
|
|
4
4
|
import { listControlPlaneRecords } from '../../control-plane/persistence/sqlite-store';
|
|
5
5
|
import { processLogDir } from './store';
|
|
6
6
|
import { readPersistedCheckResultReceipt } from './check-result';
|
|
@@ -50,7 +50,7 @@ export function cleanupPersistedCheckResults(
|
|
|
50
50
|
}
|
|
51
51
|
for (const record of workRecords) {
|
|
52
52
|
const work = record.value;
|
|
53
|
-
if (
|
|
53
|
+
if (isTerminalSemanticWorkState(work.semanticState)) continue;
|
|
54
54
|
for (const verification of work.checkRefs ?? []) {
|
|
55
55
|
const key = verification.receipt?.checkCacheKey?.trim();
|
|
56
56
|
if (key) protectedCacheKeys.add(key);
|
|
@@ -3,6 +3,7 @@ import { existsSync, mkdirSync, readFileSync, renameSync, writeFileSync } from '
|
|
|
3
3
|
import { dirname, join } from 'path';
|
|
4
4
|
import { processLogDir } from './store';
|
|
5
5
|
import type { ManagedProcessRecord } from './types';
|
|
6
|
+
import type { ProcessCheckCompletionReceipt } from './check-receipt';
|
|
6
7
|
|
|
7
8
|
export const STRUCTURED_CHECK_RESULT_PATH_ENV = 'FORGE_CHECK_STRUCTURED_RESULT_PATH';
|
|
8
9
|
export const MAX_STRUCTURED_CHECK_FAILURE_DETAILS = 32;
|
|
@@ -110,7 +111,17 @@ export function readPersistedCheckResultReceipt(path: string | undefined): Persi
|
|
|
110
111
|
if (!path || !existsSync(path)) return undefined;
|
|
111
112
|
try {
|
|
112
113
|
const value = JSON.parse(readFileSync(path, 'utf8')) as PersistedCheckResultReceipt;
|
|
113
|
-
if (
|
|
114
|
+
if (
|
|
115
|
+
value?.schemaVersion !== 1
|
|
116
|
+
|| typeof value.receiptId !== 'string'
|
|
117
|
+
|| typeof value.checkId !== 'string'
|
|
118
|
+
|| typeof value.cacheKey !== 'string'
|
|
119
|
+
|| typeof value.ok !== 'boolean'
|
|
120
|
+
|| typeof value.status !== 'number'
|
|
121
|
+
|| typeof value.timedOut !== 'boolean'
|
|
122
|
+
|| typeof value.executedAt !== 'string'
|
|
123
|
+
|| (value.failureClass !== undefined && value.failureClass !== 'acceptance_failure' && value.failureClass !== 'infrastructure_failure')
|
|
124
|
+
) return undefined;
|
|
114
125
|
if (value.failureEvidence !== undefined && !isStructuredCheckFailureEvidence(value.failureEvidence)) return undefined;
|
|
115
126
|
return value;
|
|
116
127
|
} catch {
|
|
@@ -128,6 +139,9 @@ export interface PersistedCheckTerminalEvidence {
|
|
|
128
139
|
state: PersistedCheckTerminalEvidenceState;
|
|
129
140
|
failureClass?: PersistedCheckResultReceipt['failureClass'];
|
|
130
141
|
failureEvidence?: StructuredCheckFailureEvidence;
|
|
142
|
+
semanticOk?: boolean;
|
|
143
|
+
semanticStatus?: number;
|
|
144
|
+
semanticTimedOut?: boolean;
|
|
131
145
|
warning?: string;
|
|
132
146
|
infrastructureReason?: string;
|
|
133
147
|
}
|
|
@@ -173,6 +187,9 @@ export function classifyTerminalCheckEvidence(
|
|
|
173
187
|
*/
|
|
174
188
|
export interface LegacyCheckEvidenceLike {
|
|
175
189
|
cacheKey?: string;
|
|
190
|
+
ok?: boolean;
|
|
191
|
+
status?: number;
|
|
192
|
+
timedOut?: boolean;
|
|
176
193
|
failureClass?: PersistedCheckResultReceipt['failureClass'];
|
|
177
194
|
failureEvidence?: StructuredCheckFailureEvidence;
|
|
178
195
|
}
|
|
@@ -207,6 +224,93 @@ export function classifyPersistedCheckTerminalEvidence(
|
|
|
207
224
|
...classified,
|
|
208
225
|
failureClass: structuredMatches ? structured?.failureClass : legacy?.failureClass,
|
|
209
226
|
failureEvidence: structuredMatches ? structured?.failureEvidence : legacy?.failureEvidence,
|
|
227
|
+
semanticOk: structuredMatches ? structured?.ok : legacy?.ok,
|
|
228
|
+
semanticStatus: structuredMatches ? structured?.status : legacy?.status,
|
|
229
|
+
semanticTimedOut: structuredMatches ? structured?.timedOut : legacy?.timedOut,
|
|
210
230
|
}
|
|
211
231
|
: classified;
|
|
212
232
|
}
|
|
233
|
+
|
|
234
|
+
export type TerminalCheckVerificationOutcome = 'valid_pass' | 'valid_fail' | 'infrastructure_failure';
|
|
235
|
+
|
|
236
|
+
export interface TerminalCheckVerificationProjection {
|
|
237
|
+
outcome: TerminalCheckVerificationOutcome;
|
|
238
|
+
failureClass?: 'acceptance_failure' | 'infrastructure_failure';
|
|
239
|
+
isAcceptanceFailure: boolean;
|
|
240
|
+
isInfrastructureIssue: boolean;
|
|
241
|
+
boundedStatus: 'pass' | 'fail' | 'infrastructure_failure';
|
|
242
|
+
evidence: PersistedCheckTerminalEvidence;
|
|
243
|
+
infrastructureReason?: string;
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
/**
|
|
247
|
+
* Canonical Failure Contract projection from one exact terminal Check Process
|
|
248
|
+
* plus its semantic Check-result evidence into Work verification truth.
|
|
249
|
+
* Process exit state is necessary evidence, but never acceptance authority by
|
|
250
|
+
* itself. Missing, mismatched, interrupted, infrastructure, or contradictory
|
|
251
|
+
* evidence fails closed as infrastructure_failure.
|
|
252
|
+
*/
|
|
253
|
+
export function projectTerminalCheckVerification(
|
|
254
|
+
record: ManagedProcessRecord,
|
|
255
|
+
expectedCheckId: string,
|
|
256
|
+
receipt: ProcessCheckCompletionReceipt,
|
|
257
|
+
options: { legacyEvidence?: LegacyCheckEvidenceLike } = {},
|
|
258
|
+
): TerminalCheckVerificationProjection {
|
|
259
|
+
const evidence = classifyPersistedCheckTerminalEvidence(record, expectedCheckId, options);
|
|
260
|
+
const semanticContradiction = evidence.state === 'matched' && Boolean(
|
|
261
|
+
(evidence.semanticOk !== undefined && evidence.semanticOk !== receipt.ok)
|
|
262
|
+
|| (evidence.semanticTimedOut !== undefined && evidence.semanticTimedOut !== receipt.timedOut)
|
|
263
|
+
|| (evidence.semanticOk === true && evidence.semanticStatus !== undefined && evidence.semanticStatus !== 0)
|
|
264
|
+
|| (evidence.semanticOk === false && evidence.semanticStatus === 0)
|
|
265
|
+
|| (receipt.ok && evidence.failureClass !== undefined)
|
|
266
|
+
|| (evidence.semanticOk === true && evidence.failureClass !== undefined)
|
|
267
|
+
|| (!receipt.ok && evidence.failureClass === undefined)
|
|
268
|
+
|| (evidence.semanticOk === false && evidence.failureClass === undefined)
|
|
269
|
+
);
|
|
270
|
+
const infrastructureReason = evidence.infrastructureReason
|
|
271
|
+
?? (semanticContradiction ? 'terminal Check Process and semantic result evidence contradict each other' : undefined);
|
|
272
|
+
const infrastructure = receipt.timedOut
|
|
273
|
+
|| receipt.cancelled
|
|
274
|
+
|| evidence.state !== 'matched'
|
|
275
|
+
|| semanticContradiction
|
|
276
|
+
|| evidence.failureClass === 'infrastructure_failure';
|
|
277
|
+
if (infrastructure) {
|
|
278
|
+
return {
|
|
279
|
+
outcome: 'infrastructure_failure',
|
|
280
|
+
failureClass: 'infrastructure_failure',
|
|
281
|
+
isAcceptanceFailure: false,
|
|
282
|
+
isInfrastructureIssue: true,
|
|
283
|
+
boundedStatus: 'infrastructure_failure',
|
|
284
|
+
evidence,
|
|
285
|
+
...(infrastructureReason ? { infrastructureReason } : {}),
|
|
286
|
+
};
|
|
287
|
+
}
|
|
288
|
+
if (receipt.ok) {
|
|
289
|
+
return {
|
|
290
|
+
outcome: 'valid_pass',
|
|
291
|
+
isAcceptanceFailure: false,
|
|
292
|
+
isInfrastructureIssue: false,
|
|
293
|
+
boundedStatus: 'pass',
|
|
294
|
+
evidence,
|
|
295
|
+
};
|
|
296
|
+
}
|
|
297
|
+
if (evidence.failureClass === 'acceptance_failure') {
|
|
298
|
+
return {
|
|
299
|
+
outcome: 'valid_fail',
|
|
300
|
+
failureClass: 'acceptance_failure',
|
|
301
|
+
isAcceptanceFailure: true,
|
|
302
|
+
isInfrastructureIssue: false,
|
|
303
|
+
boundedStatus: 'fail',
|
|
304
|
+
evidence,
|
|
305
|
+
};
|
|
306
|
+
}
|
|
307
|
+
return {
|
|
308
|
+
outcome: 'infrastructure_failure',
|
|
309
|
+
failureClass: 'infrastructure_failure',
|
|
310
|
+
isAcceptanceFailure: false,
|
|
311
|
+
isInfrastructureIssue: true,
|
|
312
|
+
boundedStatus: 'infrastructure_failure',
|
|
313
|
+
evidence,
|
|
314
|
+
infrastructureReason: 'terminal Check failure lacks explicit acceptance-failure evidence',
|
|
315
|
+
};
|
|
316
|
+
}
|
|
@@ -2,13 +2,8 @@
|
|
|
2
2
|
import { createHash } from 'crypto';
|
|
3
3
|
import { rmSync } from 'fs';
|
|
4
4
|
import { resolve } from 'path';
|
|
5
|
-
import {
|
|
6
|
-
|
|
7
|
-
runControllerCheckAsync,
|
|
8
|
-
snapshotControllerCheck,
|
|
9
|
-
type ControllerCheckSnapshot,
|
|
10
|
-
} from '../../../cli/controller/check-runner';
|
|
11
|
-
import { writePersistedCheckResultReceipt } from './check-result';
|
|
5
|
+
import type { ControllerCheckSnapshot } from '../../../cli/controller/check-runner';
|
|
6
|
+
import { materializeManagedWorkspaceDependencies } from '../managed-workspace';
|
|
12
7
|
import { PROCESS_RUNTIME_RELEASE_CANARY_ARG } from './canary';
|
|
13
8
|
|
|
14
9
|
interface ParsedArgs {
|
|
@@ -33,7 +28,6 @@ function requiredValue(argv: string[], flag: string): string {
|
|
|
33
28
|
return value;
|
|
34
29
|
}
|
|
35
30
|
|
|
36
|
-
|
|
37
31
|
function decodeCheckSnapshot(value: string): ControllerCheckSnapshot {
|
|
38
32
|
let decoded: unknown;
|
|
39
33
|
try {
|
|
@@ -77,6 +71,22 @@ export async function runPersistedCheckSidecar(argv = process.argv.slice(2)): Pr
|
|
|
77
71
|
const args = parseArgs(argv);
|
|
78
72
|
const root = resolve(args.repo);
|
|
79
73
|
try {
|
|
74
|
+
// A Work verification snapshot is disposable execution state. When exact
|
|
75
|
+
// canonical dependency reuse was unavailable during snapshot construction,
|
|
76
|
+
// establish the candidate's frozen dependency closure inside this Check
|
|
77
|
+
// Process before loading the candidate Check Runner module graph.
|
|
78
|
+
if (args.cleanupRoot && (!args.checkSnapshot || args.checkSnapshot.source === 'package-script')) {
|
|
79
|
+
materializeManagedWorkspaceDependencies(root);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
const [
|
|
83
|
+
{ controllerCheckExecutionIdentity, runControllerCheckAsync, snapshotControllerCheck },
|
|
84
|
+
{ writePersistedCheckResultReceipt },
|
|
85
|
+
] = await Promise.all([
|
|
86
|
+
import('../../../cli/controller/check-runner'),
|
|
87
|
+
import('./check-result'),
|
|
88
|
+
]);
|
|
89
|
+
|
|
80
90
|
// New callers carry the exact definition resolved from canonical repository
|
|
81
91
|
// authority. The fallback keeps older package releases compatible.
|
|
82
92
|
const snapshot = args.checkSnapshot ?? snapshotControllerCheck(root, args.checkId);
|
|
@@ -8,7 +8,10 @@
|
|
|
8
8
|
* - Durable: explicit Work/external/release boundaries only.
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
|
-
import
|
|
11
|
+
import {
|
|
12
|
+
commandExecutionScopeKey,
|
|
13
|
+
type RepositoryCommandScopeTarget,
|
|
14
|
+
} from '../../../cli/repositories/command-scope';
|
|
12
15
|
import { classifyRepositoryCommand, fixedShellWrapperCommand, shellSegments, shellWordsPreservingQuotes } from '../../../cli/repositories/command-classifier';
|
|
13
16
|
import {
|
|
14
17
|
executeRepositoryCommandAsync,
|
|
@@ -38,10 +41,12 @@ import {
|
|
|
38
41
|
cancelLightweightProcess,
|
|
39
42
|
getLightweightProcessHandle,
|
|
40
43
|
isLightweightProcessId,
|
|
44
|
+
lightweightProcessScopeKey,
|
|
41
45
|
readLightweightProcessLogs,
|
|
42
46
|
startLightweightRepositoryCommand,
|
|
43
47
|
waitForLightweightProcess,
|
|
44
48
|
} from './lightweight-managed';
|
|
49
|
+
import { isForgeInstanceProcessScopeKey, processScopeKeyForHandle } from './process-scope';
|
|
45
50
|
|
|
46
51
|
export type RepositoryCommandRoute =
|
|
47
52
|
| 'process_direct'
|
|
@@ -51,7 +56,8 @@ export type RepositoryCommandRoute =
|
|
|
51
56
|
|
|
52
57
|
export interface RepositoryCommandProcessInput {
|
|
53
58
|
controllerHome: string;
|
|
54
|
-
|
|
59
|
+
/** Repository identity is optional: an arbitrary workspace target carries a workspace scope key. */
|
|
60
|
+
repository: RepositoryCommandScopeTarget;
|
|
55
61
|
command: string | readonly string[];
|
|
56
62
|
cwd?: string;
|
|
57
63
|
timeoutMs?: number;
|
|
@@ -64,6 +70,8 @@ export interface RepositoryCommandProcessInput {
|
|
|
64
70
|
requestId?: string;
|
|
65
71
|
workId?: string;
|
|
66
72
|
commandId?: string;
|
|
73
|
+
/** Authenticated principal recorded with the process handle for principal-bound attachment. */
|
|
74
|
+
principalId?: string;
|
|
67
75
|
signal?: AbortSignal;
|
|
68
76
|
/** Explicit unregistered local workspace authority; never inferred from cwd. */
|
|
69
77
|
allowNonGitWorkspace?: boolean;
|
|
@@ -353,9 +361,9 @@ export async function executeRepositoryCommandViaProcessRuntime(
|
|
|
353
361
|
throw new Error('EXECUTION_IDENTITY_REQUIRED: repository command process path requires an immutable executionIdentity');
|
|
354
362
|
}
|
|
355
363
|
const executionIdentity = input.executionIdentity;
|
|
356
|
-
if (executionIdentity.repositoryId !== input.repository
|
|
364
|
+
if (executionIdentity.repositoryId !== commandExecutionScopeKey(input.repository)) {
|
|
357
365
|
throw new Error(
|
|
358
|
-
`EXECUTION_IDENTITY_MISMATCH: repository ${input.repository
|
|
366
|
+
`EXECUTION_IDENTITY_MISMATCH: repository ${commandExecutionScopeKey(input.repository)} differs from identity ${executionIdentity.repositoryId}`,
|
|
359
367
|
);
|
|
360
368
|
}
|
|
361
369
|
if (executionIdentity.checkoutId !== input.repository.activeCheckoutId) {
|
|
@@ -376,13 +384,12 @@ export async function executeRepositoryCommandViaProcessRuntime(
|
|
|
376
384
|
// immutable repository identity first, then execute through the authorized
|
|
377
385
|
// non-persistent repository executor. Runtime/release durability is not a
|
|
378
386
|
// command-execution tax.
|
|
379
|
-
const canonicalCommand = normalizeRepositoryCommand(input.command);
|
|
380
387
|
if (decision.route === 'process_direct') {
|
|
381
388
|
assertExecutionIdentity({
|
|
382
389
|
controllerHome: input.controllerHome,
|
|
383
390
|
identity: executionIdentity,
|
|
384
391
|
cwd,
|
|
385
|
-
requestedRepoId: input.repository
|
|
392
|
+
requestedRepoId: commandExecutionScopeKey(input.repository),
|
|
386
393
|
requestedCheckoutId: input.repository.activeCheckoutId,
|
|
387
394
|
});
|
|
388
395
|
const directInput = {
|
|
@@ -395,8 +402,7 @@ export async function executeRepositoryCommandViaProcessRuntime(
|
|
|
395
402
|
allowOpaqueLocalScript: decision.reason === 'lightweight_local_shell_wrapper'
|
|
396
403
|
|| decision.reason === 'lightweight_local_inline_interpreter',
|
|
397
404
|
};
|
|
398
|
-
const readonly =
|
|
399
|
-
&& classifyRepositoryCommand(input.command, input.repository.defaultBranch).risk === 'readonly';
|
|
405
|
+
const readonly = classifyRepositoryCommand(input.command, input.repository.defaultBranch).risk === 'readonly';
|
|
400
406
|
if (!readonly) {
|
|
401
407
|
const deferLongPreparation = decision.reason === 'ephemeral_local_build_or_test';
|
|
402
408
|
const interactiveWaitMs = deferLongPreparation
|
|
@@ -419,6 +425,7 @@ export async function executeRepositoryCommandViaProcessRuntime(
|
|
|
419
425
|
maxOutputBytes: input.maxOutputBytes,
|
|
420
426
|
workId: input.workId,
|
|
421
427
|
commandId: input.commandId ?? input.requestId,
|
|
428
|
+
...(input.principalId ? { principalId: input.principalId } : {}),
|
|
422
429
|
deferStart: deferLongPreparation,
|
|
423
430
|
reuseActiveEquivalent: deferLongPreparation,
|
|
424
431
|
onCompleted: (result) => {
|
|
@@ -427,7 +434,7 @@ export async function executeRepositoryCommandViaProcessRuntime(
|
|
|
427
434
|
// evidence is unavailable. Finalization must keep failing closed until
|
|
428
435
|
// a later authoritative repository inspection proves the new HEAD.
|
|
429
436
|
if (result.evidenceError) return;
|
|
430
|
-
settleWorkHandleExpectedHeadAfterRepositoryCommand({
|
|
437
|
+
const settlement = settleWorkHandleExpectedHeadAfterRepositoryCommand({
|
|
431
438
|
controllerHome: input.controllerHome,
|
|
432
439
|
repository: input.repository,
|
|
433
440
|
executionIdentity,
|
|
@@ -436,6 +443,12 @@ export async function executeRepositoryCommandViaProcessRuntime(
|
|
|
436
443
|
cancelled: result.cancelled,
|
|
437
444
|
timedOut: result.timedOut,
|
|
438
445
|
});
|
|
446
|
+
if (!settlement.settled && settlement.reason === 'concurrent_lifecycle_write') {
|
|
447
|
+
result.evidenceError = {
|
|
448
|
+
code: 'WORK_HEAD_SETTLEMENT_UNRESOLVED',
|
|
449
|
+
message: `Work ${input.workId ?? 'unknown'} repository command succeeded, but expectedHead settlement remained contested after bounded retry (${settlement.previousHead ?? 'unknown'} -> ${settlement.currentHead ?? 'unknown'}).`,
|
|
450
|
+
};
|
|
451
|
+
}
|
|
439
452
|
},
|
|
440
453
|
});
|
|
441
454
|
const handle = lightweight.handle;
|
|
@@ -526,6 +539,7 @@ export async function executeRepositoryCommandViaProcessRuntime(
|
|
|
526
539
|
repoId: executionIdentity.repositoryId,
|
|
527
540
|
checkoutId: executionIdentity.checkoutId,
|
|
528
541
|
executionIdentity,
|
|
542
|
+
...(input.principalId ? { principalId: input.principalId } : {}),
|
|
529
543
|
workId: input.workId,
|
|
530
544
|
commandId: input.commandId,
|
|
531
545
|
command: toProcessCommand(input.command, cwd),
|
|
@@ -563,40 +577,78 @@ export async function executeRepositoryCommandViaProcessRuntime(
|
|
|
563
577
|
};
|
|
564
578
|
}
|
|
565
579
|
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
580
|
+
/**
|
|
581
|
+
* Resolve the canonical Process scope of one process handle.
|
|
582
|
+
*
|
|
583
|
+
* Explicit placement stays authoritative and is validated by the lane itself.
|
|
584
|
+
* When the caller omits it, this Runtime's own lightweight memory or the
|
|
585
|
+
* instance-level handle index supplies the recorded scope, so attachment never
|
|
586
|
+
* requires replaying the original placement inputs or scanning repositories.
|
|
587
|
+
*/
|
|
588
|
+
function resolveCommandProcessScopeKey(
|
|
589
|
+
controllerHome: string,
|
|
590
|
+
repoId: string | undefined,
|
|
591
|
+
processId: string,
|
|
592
|
+
): string | undefined {
|
|
593
|
+
const explicit = repoId?.trim();
|
|
594
|
+
if (explicit) return explicit;
|
|
595
|
+
if (isLightweightProcessId(processId)) {
|
|
596
|
+
const inMemory = lightweightProcessScopeKey(processId);
|
|
597
|
+
if (inMemory) return inMemory;
|
|
598
|
+
}
|
|
599
|
+
return processScopeKeyForHandle(controllerHome, processId);
|
|
570
600
|
}
|
|
571
601
|
|
|
572
|
-
export function
|
|
602
|
+
export function getRepositoryCommandProcess(
|
|
573
603
|
controllerHome: string,
|
|
574
|
-
repoId: string,
|
|
604
|
+
repoId: string | undefined,
|
|
605
|
+
processId: string,
|
|
606
|
+
): ProcessHandle | undefined {
|
|
607
|
+
const scopeKey = resolveCommandProcessScopeKey(controllerHome, repoId, processId);
|
|
608
|
+
if (!scopeKey) return undefined;
|
|
609
|
+
if (!isLightweightProcessId(processId)) {
|
|
610
|
+
return getProcessHandle(controllerHome, scopeKey, processId);
|
|
611
|
+
}
|
|
612
|
+
return getLightweightProcessHandle(controllerHome, scopeKey, processId);
|
|
613
|
+
}
|
|
614
|
+
|
|
615
|
+
export async function waitRepositoryCommandProcess(
|
|
616
|
+
controllerHome: string,
|
|
617
|
+
repoId: string | undefined,
|
|
575
618
|
processId: string,
|
|
576
619
|
options?: Parameters<typeof waitForProcess>[3],
|
|
577
620
|
): Promise<ProcessHandle> {
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
621
|
+
const scopeKey = resolveCommandProcessScopeKey(controllerHome, repoId, processId);
|
|
622
|
+
if (!scopeKey) throw new Error(`PROCESS_NOT_FOUND: ${processId}`);
|
|
623
|
+
if (!isLightweightProcessId(processId)) {
|
|
624
|
+
return waitForProcess(controllerHome, scopeKey, processId, options);
|
|
625
|
+
}
|
|
626
|
+
return waitForLightweightProcess(controllerHome, scopeKey, processId, options);
|
|
581
627
|
}
|
|
582
628
|
|
|
583
|
-
export function cancelRepositoryCommandProcess(
|
|
629
|
+
export async function cancelRepositoryCommandProcess(
|
|
584
630
|
controllerHome: string,
|
|
585
|
-
repoId: string,
|
|
631
|
+
repoId: string | undefined,
|
|
586
632
|
processId: string,
|
|
587
633
|
): Promise<ProcessHandle> {
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
634
|
+
const scopeKey = resolveCommandProcessScopeKey(controllerHome, repoId, processId);
|
|
635
|
+
if (!scopeKey) throw new Error(`PROCESS_NOT_FOUND: ${processId}`);
|
|
636
|
+
if (!isLightweightProcessId(processId)) {
|
|
637
|
+
return cancelProcess(controllerHome, scopeKey, processId);
|
|
638
|
+
}
|
|
639
|
+
return cancelLightweightProcess(controllerHome, scopeKey, processId);
|
|
591
640
|
}
|
|
592
641
|
|
|
593
642
|
export function readRepositoryCommandProcessLogs(
|
|
594
643
|
controllerHome: string,
|
|
595
|
-
repoId: string,
|
|
644
|
+
repoId: string | undefined,
|
|
596
645
|
processId: string,
|
|
597
646
|
maxBytes?: number,
|
|
598
647
|
) {
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
648
|
+
const scopeKey = resolveCommandProcessScopeKey(controllerHome, repoId, processId);
|
|
649
|
+
if (!scopeKey) return undefined;
|
|
650
|
+
if (!isLightweightProcessId(processId)) {
|
|
651
|
+
return readProcessLogs(controllerHome, scopeKey, processId, maxBytes);
|
|
652
|
+
}
|
|
653
|
+
return readLightweightProcessLogs(controllerHome, scopeKey, processId, maxBytes);
|
|
602
654
|
}
|
|
@@ -9,8 +9,9 @@
|
|
|
9
9
|
import { existsSync, readFileSync, readdirSync, unlinkSync, statSync } from 'fs';
|
|
10
10
|
import { join } from 'path';
|
|
11
11
|
import { ensureRepositoryControllerLayout, repositoryControllerRoot } from '../../../cli/repositories/controller-home';
|
|
12
|
+
import { isRepositoryProcessScopeKey, processScopeRoot } from './process-scope';
|
|
12
13
|
import { getProcessRecord, listActiveProcessIds } from './store';
|
|
13
|
-
import { reconcileStaleManagedProcessForMaintenance } from './runtime';
|
|
14
|
+
import { reconcileStaleManagedProcessForMaintenance, releaseProcessLeasesOnce } from './runtime';
|
|
14
15
|
import { isManagedProcessActive, type ProcessRuntimeStatus } from './types';
|
|
15
16
|
import { assertRuntimeMayWrite } from '../../root/write-fence';
|
|
16
17
|
import { isProcessAlive } from '../../shared/process-tree';
|
|
@@ -52,7 +53,12 @@ export interface ProcessGcResult {
|
|
|
52
53
|
}
|
|
53
54
|
|
|
54
55
|
function processesDir(controllerHome: string, repoId: string): string {
|
|
55
|
-
|
|
56
|
+
// Repository scopes keep their per-repository layout; instance and workspace
|
|
57
|
+
// scopes own sibling partitions so their process records are still collected.
|
|
58
|
+
const root = isRepositoryProcessScopeKey(repoId)
|
|
59
|
+
? ensureRepositoryControllerLayout(controllerHome, repoId)
|
|
60
|
+
: processScopeRoot(controllerHome, repoId);
|
|
61
|
+
return join(root, 'processes');
|
|
56
62
|
}
|
|
57
63
|
|
|
58
64
|
function logDir(controllerHome: string, repoId: string): string {
|
|
@@ -196,6 +202,13 @@ export function gcTerminalProcesses(options: ProcessGcOptions): ProcessGcResult
|
|
|
196
202
|
}
|
|
197
203
|
}
|
|
198
204
|
if (!TERMINAL.has(metadata.status)) continue;
|
|
205
|
+
// Terminal evidence and lease cleanup are separate durable phases. A
|
|
206
|
+
// crash/fence between them must not leave a workspace lease immortal just
|
|
207
|
+
// because the terminal record is still inside the retention window.
|
|
208
|
+
const terminalRecord = getProcessRecord(options.controllerHome, options.repoId, processId);
|
|
209
|
+
if (terminalRecord?.terminalWritten === true && terminalRecord.leasesReleased !== true) {
|
|
210
|
+
releaseProcessLeasesOnce(options.controllerHome, options.repoId, processId);
|
|
211
|
+
}
|
|
199
212
|
// Do not delete terminal evidence that has never been read when maxAge is not exceeded
|
|
200
213
|
// unless we are strictly over maxTerminalRecords budget (handled by sort below).
|
|
201
214
|
const finished = Date.parse(metadata.finishedAt ?? metadata.updatedAt ?? '');
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Instance-level Process handle index.
|
|
3
|
+
*
|
|
4
|
+
* Process attachment (get/wait/logs/cancel) resolves the concrete execution
|
|
5
|
+
* target from the returned handle identity instead of replaying the original
|
|
6
|
+
* placement inputs or scanning every repository partition. The index lives in
|
|
7
|
+
* Controller Home, so it is a ForgeInstance-level locator: repository/checkout
|
|
8
|
+
* placement is target metadata, never the address space of the process itself.
|
|
9
|
+
*
|
|
10
|
+
* This is a rebuildable locator projection. The Process Runtime record and its
|
|
11
|
+
* exit receipt remain the only outcome evidence; a missing or stale index entry
|
|
12
|
+
* degrades attachment convenience and never becomes a capability gate.
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
import { readForgeInstanceIdentity } from '../../../../packages/kernel/identity/api/index';
|
|
16
|
+
import { mutateControlPlaneRecord, readControlPlaneRecord } from '../../control-plane/persistence/sqlite-store';
|
|
17
|
+
|
|
18
|
+
export const PROCESS_HANDLE_INDEX_NAMESPACE = 'process_handle_index';
|
|
19
|
+
const PROCESS_HANDLE_INDEX_SCOPE = 'instance';
|
|
20
|
+
const PROCESS_HANDLE_INDEX_SCHEMA_VERSION = 1;
|
|
21
|
+
|
|
22
|
+
export type ProcessExecutionTargetScope = 'forge_instance' | 'repository' | 'workspace';
|
|
23
|
+
|
|
24
|
+
/** Typed execution target for one process handle. Repository placement is optional context. */
|
|
25
|
+
export interface ProcessExecutionTarget {
|
|
26
|
+
schemaVersion: 1;
|
|
27
|
+
scope: ProcessExecutionTargetScope;
|
|
28
|
+
forgeInstanceId?: string;
|
|
29
|
+
repositoryId?: string;
|
|
30
|
+
/** Workspace scope id when the target is an arbitrary workspace without repository semantics. */
|
|
31
|
+
workspaceId?: string;
|
|
32
|
+
checkoutId?: string;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export interface ProcessHandleIndexEntry {
|
|
36
|
+
schemaVersion: 1;
|
|
37
|
+
processId: string;
|
|
38
|
+
lane: 'lightweight' | 'managed';
|
|
39
|
+
target: ProcessExecutionTarget;
|
|
40
|
+
/** Authenticated principal that owns the handle; opaque ids never authorize by themselves. */
|
|
41
|
+
principalId?: string;
|
|
42
|
+
workId?: string;
|
|
43
|
+
commandId?: string;
|
|
44
|
+
recordedAt: string;
|
|
45
|
+
updatedAt: string;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function boundedId(value: string | undefined): string | undefined {
|
|
49
|
+
const normalized = value?.trim();
|
|
50
|
+
return normalized ? normalized.slice(0, 512) : undefined;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export function forgeInstanceIdFor(controllerHome: string): string | undefined {
|
|
54
|
+
return readForgeInstanceIdentity(controllerHome)?.instanceId;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export function forgeInstanceExecutionTarget(controllerHome: string): ProcessExecutionTarget {
|
|
58
|
+
const forgeInstanceId = forgeInstanceIdFor(controllerHome);
|
|
59
|
+
return { schemaVersion: 1, scope: 'forge_instance', ...(forgeInstanceId ? { forgeInstanceId } : {}) };
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export function repositoryExecutionTarget(
|
|
63
|
+
controllerHome: string,
|
|
64
|
+
repositoryId: string,
|
|
65
|
+
checkoutId?: string,
|
|
66
|
+
): ProcessExecutionTarget {
|
|
67
|
+
const forgeInstanceId = forgeInstanceIdFor(controllerHome);
|
|
68
|
+
const repository = boundedId(repositoryId);
|
|
69
|
+
if (!repository) throw new Error('PROCESS_EXECUTION_TARGET_REPOSITORY_REQUIRED');
|
|
70
|
+
const checkout = boundedId(checkoutId);
|
|
71
|
+
return {
|
|
72
|
+
schemaVersion: 1,
|
|
73
|
+
scope: 'repository',
|
|
74
|
+
...(forgeInstanceId ? { forgeInstanceId } : {}),
|
|
75
|
+
repositoryId: repository,
|
|
76
|
+
...(checkout ? { checkoutId: checkout } : {}),
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/** Target for an arbitrary workspace: no repository identity is created or implied. */
|
|
81
|
+
export function workspaceExecutionTarget(controllerHome: string, workspaceId: string): ProcessExecutionTarget {
|
|
82
|
+
const workspace = boundedId(workspaceId);
|
|
83
|
+
if (!workspace) throw new Error('PROCESS_EXECUTION_TARGET_WORKSPACE_REQUIRED');
|
|
84
|
+
const forgeInstanceId = forgeInstanceIdFor(controllerHome);
|
|
85
|
+
return {
|
|
86
|
+
schemaVersion: 1,
|
|
87
|
+
scope: 'workspace',
|
|
88
|
+
...(forgeInstanceId ? { forgeInstanceId } : {}),
|
|
89
|
+
workspaceId: workspace,
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
export function recordProcessHandleIndexEntry(
|
|
94
|
+
controllerHome: string,
|
|
95
|
+
input: Omit<ProcessHandleIndexEntry, 'schemaVersion' | 'recordedAt' | 'updatedAt'> & { now?: string },
|
|
96
|
+
): ProcessHandleIndexEntry | undefined {
|
|
97
|
+
const processId = boundedId(input.processId);
|
|
98
|
+
if (!processId) return undefined;
|
|
99
|
+
const now = input.now ?? new Date().toISOString();
|
|
100
|
+
const principalId = boundedId(input.principalId);
|
|
101
|
+
const workId = boundedId(input.workId);
|
|
102
|
+
const commandId = boundedId(input.commandId);
|
|
103
|
+
try {
|
|
104
|
+
const record = mutateControlPlaneRecord<ProcessHandleIndexEntry>(controllerHome, {
|
|
105
|
+
namespace: PROCESS_HANDLE_INDEX_NAMESPACE,
|
|
106
|
+
scope: PROCESS_HANDLE_INDEX_SCOPE,
|
|
107
|
+
key: processId,
|
|
108
|
+
schemaVersion: PROCESS_HANDLE_INDEX_SCHEMA_VERSION,
|
|
109
|
+
action: 'process_handle_index_record',
|
|
110
|
+
mutate: (current) => ({
|
|
111
|
+
schemaVersion: PROCESS_HANDLE_INDEX_SCHEMA_VERSION,
|
|
112
|
+
processId,
|
|
113
|
+
lane: input.lane,
|
|
114
|
+
target: input.target,
|
|
115
|
+
...(principalId ? { principalId } : {}),
|
|
116
|
+
...(current?.value.principalId && !principalId ? { principalId: current.value.principalId } : {}),
|
|
117
|
+
...(workId ? { workId } : {}),
|
|
118
|
+
...(commandId ? { commandId } : {}),
|
|
119
|
+
recordedAt: current?.value.recordedAt ?? now,
|
|
120
|
+
updatedAt: now,
|
|
121
|
+
}),
|
|
122
|
+
});
|
|
123
|
+
return record.value;
|
|
124
|
+
} catch {
|
|
125
|
+
// A locator projection must never block an already-authorized process.
|
|
126
|
+
return undefined;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
export function readProcessHandleIndexEntry(
|
|
131
|
+
controllerHome: string,
|
|
132
|
+
processId: string,
|
|
133
|
+
): ProcessHandleIndexEntry | undefined {
|
|
134
|
+
const key = boundedId(processId);
|
|
135
|
+
if (!key) return undefined;
|
|
136
|
+
try {
|
|
137
|
+
const record = readControlPlaneRecord<ProcessHandleIndexEntry>(
|
|
138
|
+
controllerHome,
|
|
139
|
+
PROCESS_HANDLE_INDEX_NAMESPACE,
|
|
140
|
+
PROCESS_HANDLE_INDEX_SCOPE,
|
|
141
|
+
key,
|
|
142
|
+
);
|
|
143
|
+
const value = record?.value;
|
|
144
|
+
if (!value || value.schemaVersion !== PROCESS_HANDLE_INDEX_SCHEMA_VERSION || value.processId !== key) return undefined;
|
|
145
|
+
if (!value.target || value.target.schemaVersion !== 1) return undefined;
|
|
146
|
+
return value;
|
|
147
|
+
} catch {
|
|
148
|
+
return undefined;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/** Resolve the concrete execution target recorded for one process handle. */
|
|
153
|
+
export function resolveProcessExecutionTarget(
|
|
154
|
+
controllerHome: string,
|
|
155
|
+
processId: string,
|
|
156
|
+
): ProcessExecutionTarget | undefined {
|
|
157
|
+
return readProcessHandleIndexEntry(controllerHome, processId)?.target;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* Principal that owns one process handle, when recorded. Opaque handle ids
|
|
162
|
+
* locate a record; they never authorize attachment on their own.
|
|
163
|
+
*/
|
|
164
|
+
export function processHandlePrincipalId(controllerHome: string, processId: string): string | undefined {
|
|
165
|
+
return readProcessHandleIndexEntry(controllerHome, processId)?.principalId;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
/** Compatibility narrowing: the repository placement recorded for a process, when it has one. */
|
|
169
|
+
export function resolveProcessRepositoryTarget(
|
|
170
|
+
controllerHome: string,
|
|
171
|
+
processId: string,
|
|
172
|
+
): { repositoryId: string; checkoutId?: string } | undefined {
|
|
173
|
+
const target = resolveProcessExecutionTarget(controllerHome, processId);
|
|
174
|
+
if (!target?.repositoryId) return undefined;
|
|
175
|
+
return { repositoryId: target.repositoryId, ...(target.checkoutId ? { checkoutId: target.checkoutId } : {}) };
|
|
176
|
+
}
|