@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,11 +1,13 @@
|
|
|
1
1
|
import { createHash, randomUUID } from 'crypto';
|
|
2
2
|
import { createRequire } from 'module';
|
|
3
|
-
import { chmodSync, copyFileSync, cpSync, existsSync, lstatSync, mkdirSync, readFileSync, readdirSync, realpathSync, renameSync, rmSync, statSync, writeFileSync } from 'fs';
|
|
3
|
+
import { chmodSync, copyFileSync, cpSync, existsSync, lstatSync, mkdirSync, mkdtempSync, readFileSync, readdirSync, realpathSync, renameSync, rmSync, statSync, symlinkSync, writeFileSync } from 'fs';
|
|
4
|
+
import { tmpdir } from 'os';
|
|
4
5
|
import { dirname, join, relative, resolve } from 'path';
|
|
5
6
|
import { runProcess } from '../../effects/process-runner';
|
|
6
7
|
import { resolveBunExecutable } from '../shared/process-environment';
|
|
8
|
+
import { assertStorageHeadroom } from '../shared/storage-capacity';
|
|
7
9
|
import { CONTROL_PLANE_SCHEMA_VERSION } from '../control-plane/persistence/sqlite-store';
|
|
8
|
-
import { loadRuntimeReleaseManifest, requireCompleteCompiledRuntimeReleaseManifest } from './release-manifest';
|
|
10
|
+
import { assertRuntimeReleaseExecutionSurface, loadRuntimeReleaseManifest, requireCompleteCompiledRuntimeReleaseManifest } from './release-manifest';
|
|
9
11
|
import { assertRuntimeReleaseExecutionCanaries, type RuntimeReleaseExecutionCanaryCommand } from './release-execution-canary';
|
|
10
12
|
export { assertRuntimeReleaseExecutionCanaries, type RuntimeReleaseExecutionCanaryDependencies } from './release-execution-canary';
|
|
11
13
|
import { packageRuntimeFileIndex, stagePackageRuntimeSnapshot } from './package-runtime-release';
|
|
@@ -34,11 +36,16 @@ export interface StagedRuntimeRelease {
|
|
|
34
36
|
releaseId: string;
|
|
35
37
|
artifactIdentity: string;
|
|
36
38
|
runtimeBundleArtifactIdentity?: string;
|
|
39
|
+
runtimeInterpreterArtifactIdentity?: string;
|
|
37
40
|
diagnosticArtifactIdentity?: string;
|
|
41
|
+
connectorArtifactIdentity?: string;
|
|
38
42
|
browserNodeBridgeArtifactIdentity?: string;
|
|
39
43
|
browserHandoffArtifactIdentity?: string;
|
|
44
|
+
workflowSupervisorNativeHostArtifactIdentity?: string;
|
|
40
45
|
processRunnerArtifactIdentity?: string;
|
|
41
46
|
checkRunnerArtifactIdentity?: string;
|
|
47
|
+
typescriptNavigationArtifactIdentity?: string;
|
|
48
|
+
contextPackArtifactIdentity?: string;
|
|
42
49
|
schedulerWorkerArtifactIdentity?: string;
|
|
43
50
|
periodicCleanupArtifactIdentity?: string;
|
|
44
51
|
pluginActionSidecarArtifactIdentity?: string;
|
|
@@ -61,6 +68,7 @@ export interface RuntimeReleaseMaterializerDependencies {
|
|
|
61
68
|
uuid?: () => string;
|
|
62
69
|
compileBinary?: (input: { sourceRoot: string; outputPath: string; entryPath?: string }) => { ok: boolean; stderr?: string; stdout?: string; error?: string };
|
|
63
70
|
bundleRuntime?: (input: { sourceRoot: string; outputPath: string; entryPath: string }) => { ok: boolean; stderr?: string; stdout?: string; error?: string };
|
|
71
|
+
materializeRuntimeInterpreter?: (input: { sourceRoot: string; outputPath: string }) => { ok: boolean; stderr?: string; stdout?: string; error?: string };
|
|
64
72
|
bundleNodeHost?: (input: { sourceRoot: string; outputPath: string; entryPath: string }) => { ok: boolean; stderr?: string; stdout?: string; error?: string };
|
|
65
73
|
bundleProcessRunner?: (input: { sourceRoot: string; outputPath: string; entryPath: string }) => { ok: boolean; stderr?: string; stdout?: string; error?: string };
|
|
66
74
|
materializeCodeGraphRuntime?: (input: {
|
|
@@ -89,6 +97,7 @@ export interface CandidateRuntimeReleaseStagerDependencies {
|
|
|
89
97
|
bunExecutable: string;
|
|
90
98
|
scriptPath: string;
|
|
91
99
|
sourceRoot: string;
|
|
100
|
+
dependencyRoot: string;
|
|
92
101
|
controllerHome: string;
|
|
93
102
|
expectedHead: string;
|
|
94
103
|
sourceRepositoryId: string;
|
|
@@ -102,6 +111,61 @@ function gitText(root: string, args: string[]): string {
|
|
|
102
111
|
return result.stdout.trim();
|
|
103
112
|
}
|
|
104
113
|
|
|
114
|
+
/**
|
|
115
|
+
* Materialize one exact tracked Git revision into a detached temporary worktree.
|
|
116
|
+
* The mutable source checkout remains only the object/dependency provider and may
|
|
117
|
+
* advance while the callback runs. Lifecycle/Runtime authority is untouched.
|
|
118
|
+
*/
|
|
119
|
+
export function withRuntimeReleaseSourceSnapshot<T>(input: {
|
|
120
|
+
sourceRoot: string;
|
|
121
|
+
sourceRevision: string;
|
|
122
|
+
}, operation: (snapshotRoot: string) => T): T {
|
|
123
|
+
const sourceRoot = resolve(input.sourceRoot);
|
|
124
|
+
const requestedRevision = input.sourceRevision.trim();
|
|
125
|
+
if (!/^[a-f0-9]{40}$/i.test(requestedRevision)) throw new Error('RUNTIME_RELEASE_SOURCE_REVISION_INVALID');
|
|
126
|
+
const resolvedRevision = gitText(sourceRoot, ['rev-parse', '--verify', `${requestedRevision}^{commit}`]);
|
|
127
|
+
if (resolvedRevision !== requestedRevision) throw new Error('RUNTIME_RELEASE_SOURCE_REVISION_MISMATCH');
|
|
128
|
+
// Release materialization is Runtime-owned temporary state, not repository
|
|
129
|
+
// workspace state. Keeping the detached worktree outside sourceRoot prevents
|
|
130
|
+
// Forge's own immutable-source snapshot from perturbing repository status or
|
|
131
|
+
// workspace fingerprints while release validation is running.
|
|
132
|
+
const snapshotContainer = mkdtempSync(join(tmpdir(), `forge-runtime-release-source-${process.pid}-`));
|
|
133
|
+
const snapshotRoot = join(snapshotContainer, `${requestedRevision}-${randomUUID().slice(0, 8)}`);
|
|
134
|
+
const materialized = runProcess('git', ['-C', sourceRoot, 'worktree', 'add', '--detach', '--force', snapshotRoot, requestedRevision], {
|
|
135
|
+
timeoutMs: 60_000,
|
|
136
|
+
maxOutputBytes: 128 * 1024,
|
|
137
|
+
});
|
|
138
|
+
if (!materialized.ok) {
|
|
139
|
+
rmSync(snapshotContainer, { recursive: true, force: true });
|
|
140
|
+
runProcess('git', ['-C', sourceRoot, 'worktree', 'prune'], { timeoutMs: 30_000, maxOutputBytes: 64 * 1024 });
|
|
141
|
+
throw new Error(`RUNTIME_RELEASE_SOURCE_SNAPSHOT_FAILED: ${materialized.stderr || materialized.stdout || materialized.error}`.slice(0, 2_000));
|
|
142
|
+
}
|
|
143
|
+
try {
|
|
144
|
+
const sourceDependencies = join(sourceRoot, 'node_modules');
|
|
145
|
+
if (existsSync(sourceDependencies)) {
|
|
146
|
+
const snapshotDependencies = join(snapshotRoot, 'node_modules');
|
|
147
|
+
symlinkSync(realpathSync(sourceDependencies), snapshotDependencies, process.platform === 'win32' ? 'junction' : 'dir');
|
|
148
|
+
}
|
|
149
|
+
if (gitText(snapshotRoot, ['rev-parse', '--verify', 'HEAD']) !== requestedRevision) {
|
|
150
|
+
throw new Error('RUNTIME_RELEASE_SOURCE_SNAPSHOT_REVISION_MISMATCH');
|
|
151
|
+
}
|
|
152
|
+
if (gitText(snapshotRoot, ['status', '--porcelain=v1', '--untracked-files=no'])) {
|
|
153
|
+
throw new Error('RUNTIME_RELEASE_SOURCE_SNAPSHOT_DIRTY');
|
|
154
|
+
}
|
|
155
|
+
return operation(snapshotRoot);
|
|
156
|
+
} finally {
|
|
157
|
+
const removed = runProcess('git', ['-C', sourceRoot, 'worktree', 'remove', '--force', snapshotRoot], {
|
|
158
|
+
timeoutMs: 60_000,
|
|
159
|
+
maxOutputBytes: 128 * 1024,
|
|
160
|
+
});
|
|
161
|
+
if (!removed.ok) {
|
|
162
|
+
rmSync(snapshotRoot, { recursive: true, force: true });
|
|
163
|
+
}
|
|
164
|
+
runProcess('git', ['-C', sourceRoot, 'worktree', 'prune'], { timeoutMs: 30_000, maxOutputBytes: 64 * 1024 });
|
|
165
|
+
rmSync(snapshotContainer, { recursive: true, force: true });
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
|
|
105
169
|
function sha256(path: string): string {
|
|
106
170
|
return createHash('sha256').update(readFileSync(path)).digest('hex');
|
|
107
171
|
}
|
|
@@ -164,6 +228,10 @@ function inspectMacOSRuntimeCodeSigning(executable: string): MacOSRuntimeCodeSig
|
|
|
164
228
|
return parseMacOSRuntimeCodeSigning({ identifier, teamIdentifier, authority, designatedRequirement }, 'RUNTIME_RELEASE_MACOS_SIGNATURE_INVALID')!;
|
|
165
229
|
}
|
|
166
230
|
|
|
231
|
+
export function macOSRuntimeSigningMayRetryWithoutTimestamp(detail: string): boolean {
|
|
232
|
+
return /(?:^|\n).*timestamp service is not available\.?\s*$/im.test(detail);
|
|
233
|
+
}
|
|
234
|
+
|
|
167
235
|
function defaultSignMacOSRuntime(input: { executable: string; controllerHome: string }): MacOSRuntimeCodeSigning {
|
|
168
236
|
const identities = runProcess('security', ['find-identity', '-v', '-p', 'codesigning'], { timeoutMs: 30_000, maxOutputBytes: 128 * 1024 });
|
|
169
237
|
if (!identities.ok) throw new Error(`RUNTIME_RELEASE_MACOS_SIGNING_IDENTITY_LOOKUP_FAILED: ${identities.stderr || identities.stdout || identities.error}`.slice(0, 2_000));
|
|
@@ -186,9 +254,16 @@ function defaultSignMacOSRuntime(input: { executable: string; controllerHome: st
|
|
|
186
254
|
selected = eligible[0];
|
|
187
255
|
}
|
|
188
256
|
if (expectedTeam && selected.teamIdentifier !== expectedTeam) throw new Error('RUNTIME_RELEASE_MACOS_SIGNING_TEAM_CHANGED');
|
|
189
|
-
const
|
|
190
|
-
'--force', '--sign', selected.hash, '--identifier', FORGE_MACOS_RUNTIME_SIGNING_IDENTIFIER, '--options', 'runtime',
|
|
191
|
-
]
|
|
257
|
+
const signingArgs = [
|
|
258
|
+
'--force', '--sign', selected.hash, '--identifier', FORGE_MACOS_RUNTIME_SIGNING_IDENTIFIER, '--options', 'runtime',
|
|
259
|
+
];
|
|
260
|
+
let signed = runProcess('codesign', [...signingArgs, input.executable], { timeoutMs: 120_000, maxOutputBytes: 128 * 1024 });
|
|
261
|
+
if (!signed.ok) {
|
|
262
|
+
const detail = `${signed.stderr ?? ''}\n${signed.stdout ?? ''}\n${signed.error ?? ''}`;
|
|
263
|
+
if (macOSRuntimeSigningMayRetryWithoutTimestamp(detail)) {
|
|
264
|
+
signed = runProcess('codesign', [...signingArgs, '--timestamp=none', input.executable], { timeoutMs: 120_000, maxOutputBytes: 128 * 1024 });
|
|
265
|
+
}
|
|
266
|
+
}
|
|
192
267
|
if (!signed.ok) throw new Error(`RUNTIME_RELEASE_MACOS_SIGNING_FAILED: ${signed.stderr || signed.stdout || signed.error}`.slice(0, 2_000));
|
|
193
268
|
const inspected = inspectMacOSRuntimeCodeSigning(input.executable);
|
|
194
269
|
if (inspected.teamIdentifier !== selected.teamIdentifier) throw new Error('RUNTIME_RELEASE_MACOS_SIGNING_TEAM_MISMATCH');
|
|
@@ -258,10 +333,12 @@ function parseCandidateStageReceipt(stdout: string): CandidateRuntimeStageReceip
|
|
|
258
333
|
export function stageRuntimeReleaseFromCandidateSource(input: {
|
|
259
334
|
controllerHome: string;
|
|
260
335
|
sourceRoot: string;
|
|
336
|
+
dependencyRoot?: string;
|
|
261
337
|
sourceRepositoryId: string;
|
|
262
338
|
}, dependencies: CandidateRuntimeReleaseStagerDependencies = {}): StagedRuntimeRelease {
|
|
263
339
|
const controllerHome = resolve(input.controllerHome);
|
|
264
340
|
const sourceRoot = resolve(input.sourceRoot);
|
|
341
|
+
const dependencyRoot = resolve(input.dependencyRoot ?? input.sourceRoot);
|
|
265
342
|
const sourceRepositoryId = input.sourceRepositoryId.trim();
|
|
266
343
|
if (!sourceRepositoryId) throw new Error('RUNTIME_RELEASE_SOURCE_REPOSITORY_ID_REQUIRED');
|
|
267
344
|
const expectedHead = gitText(sourceRoot, ['rev-parse', '--verify', 'HEAD']);
|
|
@@ -279,10 +356,11 @@ export function stageRuntimeReleaseFromCandidateSource(input: {
|
|
|
279
356
|
request.scriptPath,
|
|
280
357
|
'--controller-home', request.controllerHome,
|
|
281
358
|
'--source-root', request.sourceRoot,
|
|
359
|
+
'--dependency-root', request.dependencyRoot,
|
|
282
360
|
'--expected-head', request.expectedHead,
|
|
283
361
|
'--source-repository-id', request.sourceRepositoryId,
|
|
284
362
|
], { cwd: request.sourceRoot, timeoutMs: 600_000, maxOutputBytes: 512 * 1024 }));
|
|
285
|
-
const executed = runCandidateStager({ bunExecutable, scriptPath, sourceRoot, controllerHome, expectedHead, sourceRepositoryId });
|
|
363
|
+
const executed = runCandidateStager({ bunExecutable, scriptPath, sourceRoot, dependencyRoot, controllerHome, expectedHead, sourceRepositoryId });
|
|
286
364
|
if (!executed.ok) {
|
|
287
365
|
throw new Error(`RUNTIME_RELEASE_CANDIDATE_STAGE_FAILED: ${executed.stderr || executed.stdout || executed.error}`.slice(0, 2_000));
|
|
288
366
|
}
|
|
@@ -360,9 +438,12 @@ export function stageRuntimeReleaseFromCandidateSource(input: {
|
|
|
360
438
|
releaseId: receipt.releaseId,
|
|
361
439
|
artifactIdentity: receipt.artifactIdentity,
|
|
362
440
|
runtimeBundleArtifactIdentity: manifest.runtimeBundleArtifactIdentity,
|
|
441
|
+
runtimeInterpreterArtifactIdentity: manifest.runtimeInterpreterArtifactIdentity,
|
|
363
442
|
diagnosticArtifactIdentity: manifest.diagnosticArtifactIdentity,
|
|
443
|
+
connectorArtifactIdentity: manifest.connectorArtifactIdentity,
|
|
364
444
|
browserNodeBridgeArtifactIdentity: manifest.browserNodeBridgeArtifactIdentity,
|
|
365
445
|
browserHandoffArtifactIdentity: manifest.browserHandoffArtifactIdentity,
|
|
446
|
+
workflowSupervisorNativeHostArtifactIdentity: manifest.workflowSupervisorNativeHostArtifactIdentity,
|
|
366
447
|
processRunnerArtifactIdentity: manifest.processRunnerArtifactIdentity,
|
|
367
448
|
checkRunnerArtifactIdentity: manifest.checkRunnerArtifactIdentity,
|
|
368
449
|
schedulerWorkerArtifactIdentity: manifest.schedulerWorkerArtifactIdentity,
|
|
@@ -396,6 +477,31 @@ function defaultCompileBinary(input: { sourceRoot: string; outputPath: string; e
|
|
|
396
477
|
], { cwd: input.sourceRoot, timeoutMs: 300_000, maxOutputBytes: 512 * 1024 });
|
|
397
478
|
}
|
|
398
479
|
|
|
480
|
+
function defaultMaterializeRuntimeInterpreter(input: { sourceRoot: string; outputPath: string }): { ok: boolean; stderr?: string; stdout?: string; error?: string } {
|
|
481
|
+
const configured = process.env.FORGE_BUN_BIN?.trim();
|
|
482
|
+
const bun = configured || resolveBunExecutable(process.execPath, process.env);
|
|
483
|
+
const probe = runProcess(bun, ['-e', 'process.stdout.write(process.execPath)'], {
|
|
484
|
+
cwd: input.sourceRoot,
|
|
485
|
+
timeoutMs: 15_000,
|
|
486
|
+
maxOutputBytes: 16 * 1024,
|
|
487
|
+
});
|
|
488
|
+
if (!probe.ok) return probe;
|
|
489
|
+
try {
|
|
490
|
+
const reported = probe.stdout.trim();
|
|
491
|
+
if (!reported) return { ok: false, error: 'Bun did not report process.execPath' };
|
|
492
|
+
const source = realpathSync(resolve(reported));
|
|
493
|
+
const status = lstatSync(source);
|
|
494
|
+
if (status.isSymbolicLink() || !status.isFile() || (status.mode & 0o111) === 0) {
|
|
495
|
+
return { ok: false, error: `resolved Bun interpreter is not a regular executable: ${source}` };
|
|
496
|
+
}
|
|
497
|
+
copyFileSync(source, input.outputPath);
|
|
498
|
+
chmodSync(input.outputPath, 0o700);
|
|
499
|
+
return { ok: true };
|
|
500
|
+
} catch (error) {
|
|
501
|
+
return { ok: false, error: error instanceof Error ? error.message : String(error) };
|
|
502
|
+
}
|
|
503
|
+
}
|
|
504
|
+
|
|
399
505
|
function defaultBundleRuntimeScript(input: { sourceRoot: string; outputPath: string; entryPath: string }): { ok: boolean; stderr?: string; stdout?: string; error?: string } {
|
|
400
506
|
const configured = process.env.FORGE_BUN_BIN?.trim();
|
|
401
507
|
const bun = configured || resolveBunExecutable(process.execPath, process.env);
|
|
@@ -449,9 +555,11 @@ function defaultMaterializeCodeGraphRuntime(input: {
|
|
|
449
555
|
export function stageRuntimeRelease(input: {
|
|
450
556
|
controllerHome: string;
|
|
451
557
|
sourceRoot: string;
|
|
558
|
+
dependencyRoot?: string;
|
|
452
559
|
sourceRepositoryId?: string;
|
|
453
560
|
}, dependencies: RuntimeReleaseMaterializerDependencies = {}): StagedRuntimeRelease {
|
|
454
561
|
const sourceRoot = resolve(input.sourceRoot);
|
|
562
|
+
const dependencyRoot = resolve(input.dependencyRoot ?? input.sourceRoot);
|
|
455
563
|
const sourceRepositoryId = input.sourceRepositoryId?.trim();
|
|
456
564
|
if (input.sourceRepositoryId !== undefined && !sourceRepositoryId) throw new Error('RUNTIME_RELEASE_SOURCE_REPOSITORY_ID_INVALID');
|
|
457
565
|
const sourceCommit = gitText(sourceRoot, ['rev-parse', '--verify', 'HEAD']);
|
|
@@ -472,6 +580,7 @@ export function stageRuntimeRelease(input: {
|
|
|
472
580
|
mkdirSync(staging, { recursive: true, mode: 0o700 });
|
|
473
581
|
try {
|
|
474
582
|
const compileBinary = dependencies.compileBinary ?? defaultCompileBinary;
|
|
583
|
+
const platform = dependencies.platform ?? process.platform;
|
|
475
584
|
const runtimeBundleEntrypoint = 'forge-runtime-bundle.js' as const;
|
|
476
585
|
const runtimeBundlePath = join(staging, runtimeBundleEntrypoint);
|
|
477
586
|
const runtimeBundle = (dependencies.bundleRuntime ?? defaultBundleRuntimeScript)({
|
|
@@ -485,6 +594,20 @@ export function stageRuntimeRelease(input: {
|
|
|
485
594
|
chmodSync(runtimeBundlePath, 0o600);
|
|
486
595
|
const runtimeBundleArtifactIdentity = `sha256:${sha256(runtimeBundlePath)}`;
|
|
487
596
|
|
|
597
|
+
const runtimeInterpreterEntrypoint = platform === 'win32'
|
|
598
|
+
? 'forge-runtime-bun.exe' as const
|
|
599
|
+
: 'forge-runtime-bun' as const;
|
|
600
|
+
const runtimeInterpreterPath = join(staging, runtimeInterpreterEntrypoint);
|
|
601
|
+
const runtimeInterpreter = (dependencies.materializeRuntimeInterpreter ?? defaultMaterializeRuntimeInterpreter)({
|
|
602
|
+
sourceRoot,
|
|
603
|
+
outputPath: runtimeInterpreterPath,
|
|
604
|
+
});
|
|
605
|
+
if (!runtimeInterpreter.ok) {
|
|
606
|
+
throw new Error(`RUNTIME_RELEASE_INTERPRETER_BUILD_FAILED: ${runtimeInterpreter.stderr || runtimeInterpreter.stdout || runtimeInterpreter.error}`.slice(0, 2_000));
|
|
607
|
+
}
|
|
608
|
+
chmodSync(runtimeInterpreterPath, 0o700);
|
|
609
|
+
const runtimeInterpreterArtifactIdentity = `sha256:${sha256(runtimeInterpreterPath)}`;
|
|
610
|
+
|
|
488
611
|
const executable = join(staging, 'forge-runtime');
|
|
489
612
|
const compile = compileBinary({
|
|
490
613
|
sourceRoot,
|
|
@@ -495,7 +618,6 @@ export function stageRuntimeRelease(input: {
|
|
|
495
618
|
throw new Error(`RUNTIME_RELEASE_BUILD_FAILED: ${compile.stderr || compile.stdout || compile.error}`.slice(0, 2_000));
|
|
496
619
|
}
|
|
497
620
|
chmodSync(executable, 0o700);
|
|
498
|
-
const platform = dependencies.platform ?? process.platform;
|
|
499
621
|
const macosCodeSigning = platform === 'darwin'
|
|
500
622
|
? (dependencies.signMacOSRuntime ?? defaultSignMacOSRuntime)({ executable, controllerHome: resolve(input.controllerHome) })
|
|
501
623
|
: undefined;
|
|
@@ -517,6 +639,19 @@ export function stageRuntimeRelease(input: {
|
|
|
517
639
|
chmodSync(diagnosticExecutable, 0o700);
|
|
518
640
|
const diagnosticArtifactIdentity = `sha256:${sha256(diagnosticExecutable)}`;
|
|
519
641
|
|
|
642
|
+
const connectorEntrypoint = 'forge-mcp-gateway' as const;
|
|
643
|
+
const connectorPath = join(staging, connectorEntrypoint);
|
|
644
|
+
const connectorCompile = compileBinary({
|
|
645
|
+
sourceRoot,
|
|
646
|
+
outputPath: connectorPath,
|
|
647
|
+
entryPath: join(sourceRoot, 'src/cli/index.ts'),
|
|
648
|
+
});
|
|
649
|
+
if (!connectorCompile.ok) {
|
|
650
|
+
throw new Error(`RUNTIME_RELEASE_CONNECTOR_BUILD_FAILED: ${connectorCompile.stderr || connectorCompile.stdout || connectorCompile.error}`.slice(0, 2_000));
|
|
651
|
+
}
|
|
652
|
+
chmodSync(connectorPath, 0o700);
|
|
653
|
+
const connectorArtifactIdentity = `sha256:${sha256(connectorPath)}`;
|
|
654
|
+
|
|
520
655
|
const browserNodeBridgeEntrypoint = 'browser-node-bridge-host.js' as const;
|
|
521
656
|
const browserNodeBridgePath = join(staging, browserNodeBridgeEntrypoint);
|
|
522
657
|
const bundleNodeHost = dependencies.bundleNodeHost ?? defaultBundleNodeScript;
|
|
@@ -544,6 +679,19 @@ export function stageRuntimeRelease(input: {
|
|
|
544
679
|
chmodSync(browserHandoffPath, 0o700);
|
|
545
680
|
const browserHandoffArtifactIdentity = `sha256:${sha256(browserHandoffPath)}`;
|
|
546
681
|
|
|
682
|
+
const workflowSupervisorNativeHostEntrypoint = 'forge-workflow-supervisor-native-host' as const;
|
|
683
|
+
const workflowSupervisorNativeHostPath = join(staging, workflowSupervisorNativeHostEntrypoint);
|
|
684
|
+
const workflowSupervisorNativeHostCompile = compileBinary({
|
|
685
|
+
sourceRoot,
|
|
686
|
+
outputPath: workflowSupervisorNativeHostPath,
|
|
687
|
+
entryPath: join(sourceRoot, 'supervisor', 'native-messaging', 'host.ts'),
|
|
688
|
+
});
|
|
689
|
+
if (!workflowSupervisorNativeHostCompile.ok) {
|
|
690
|
+
throw new Error(`RUNTIME_RELEASE_WORKFLOW_SUPERVISOR_NATIVE_HOST_BUILD_FAILED: ${workflowSupervisorNativeHostCompile.stderr || workflowSupervisorNativeHostCompile.stdout || workflowSupervisorNativeHostCompile.error}`.slice(0, 2_000));
|
|
691
|
+
}
|
|
692
|
+
chmodSync(workflowSupervisorNativeHostPath, 0o700);
|
|
693
|
+
const workflowSupervisorNativeHostArtifactIdentity = `sha256:${sha256(workflowSupervisorNativeHostPath)}`;
|
|
694
|
+
|
|
547
695
|
const processRunnerEntrypoint = 'process-runner.js' as const;
|
|
548
696
|
const processRunnerPath = join(staging, processRunnerEntrypoint);
|
|
549
697
|
// Process Runner is part of the immutable execution surface and must not
|
|
@@ -576,6 +724,32 @@ export function stageRuntimeRelease(input: {
|
|
|
576
724
|
chmodSync(checkRunnerPath, 0o700);
|
|
577
725
|
const checkRunnerArtifactIdentity = `sha256:${sha256(checkRunnerPath)}`;
|
|
578
726
|
|
|
727
|
+
const typescriptNavigationEntrypoint = 'forge-typescript-navigation' as const;
|
|
728
|
+
const typescriptNavigationPath = join(staging, typescriptNavigationEntrypoint);
|
|
729
|
+
const typescriptNavigationCompile = compileBinary({
|
|
730
|
+
sourceRoot,
|
|
731
|
+
outputPath: typescriptNavigationPath,
|
|
732
|
+
entryPath: join(sourceRoot, 'adapters/mcp/runtime-gateway/typescript-navigation-sidecar.ts'),
|
|
733
|
+
});
|
|
734
|
+
if (!typescriptNavigationCompile.ok) {
|
|
735
|
+
throw new Error(`RUNTIME_RELEASE_TYPESCRIPT_NAVIGATION_BUILD_FAILED: ${typescriptNavigationCompile.stderr || typescriptNavigationCompile.stdout || typescriptNavigationCompile.error}`.slice(0, 2_000));
|
|
736
|
+
}
|
|
737
|
+
chmodSync(typescriptNavigationPath, 0o700);
|
|
738
|
+
const typescriptNavigationArtifactIdentity = `sha256:${sha256(typescriptNavigationPath)}`;
|
|
739
|
+
|
|
740
|
+
const contextPackEntrypoint = 'forge-context-pack' as const;
|
|
741
|
+
const contextPackPath = join(staging, contextPackEntrypoint);
|
|
742
|
+
const contextPackCompile = compileBinary({
|
|
743
|
+
sourceRoot,
|
|
744
|
+
outputPath: contextPackPath,
|
|
745
|
+
entryPath: join(sourceRoot, 'adapters/mcp/runtime-gateway/context-pack-sidecar.ts'),
|
|
746
|
+
});
|
|
747
|
+
if (!contextPackCompile.ok) {
|
|
748
|
+
throw new Error(`RUNTIME_RELEASE_CONTEXT_PACK_BUILD_FAILED: ${contextPackCompile.stderr || contextPackCompile.stdout || contextPackCompile.error}`.slice(0, 2_000));
|
|
749
|
+
}
|
|
750
|
+
chmodSync(contextPackPath, 0o700);
|
|
751
|
+
const contextPackArtifactIdentity = `sha256:${sha256(contextPackPath)}`;
|
|
752
|
+
|
|
579
753
|
const schedulerWorkerEntrypoint = 'forge-scheduler-worker' as const;
|
|
580
754
|
const schedulerWorkerPath = join(staging, schedulerWorkerEntrypoint);
|
|
581
755
|
const schedulerWorkerCompile = compileBinary({
|
|
@@ -646,25 +820,17 @@ export function stageRuntimeRelease(input: {
|
|
|
646
820
|
const codeGraphSidecarArtifactIdentity = `sha256:${sha256(codeGraphSidecarPath)}`;
|
|
647
821
|
const codeGraphLibraryArtifactIdentity = `sha256:${sha256Directory(codeGraphLibraryPath)}`;
|
|
648
822
|
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
const controllerUiPath = join(staging, controllerUiRoot);
|
|
657
|
-
cpSync(sourceControllerUiPath, controllerUiPath, { recursive: true, force: false });
|
|
658
|
-
const controllerUiArtifactIdentity = `sha256:${sha256Directory(controllerUiPath)}`;
|
|
659
|
-
|
|
660
|
-
// The persistent OAuth/Connector is source-backed even when the primary
|
|
661
|
-
// Runtime itself is compiled. Co-locate one immutable package snapshot in
|
|
662
|
-
// the same release so standalone Recovery can bind the Connector to the
|
|
663
|
-
// exact active release instead of retaining an older package release.
|
|
823
|
+
// Keep the source-backed package projection during the Recovery migration.
|
|
824
|
+
// The active standalone Recovery release can predate the compiled Connector
|
|
825
|
+
// sidecar and still rebind the primary Connector through package/src/cli.
|
|
826
|
+
// Removing that surface here makes a candidate pass isolated Runtime
|
|
827
|
+
// canaries but fail the real cutover with missing CLI command modules. Once
|
|
828
|
+
// every supported Recovery release launches forge-mcp-gateway, this
|
|
829
|
+
// compatibility projection can be removed together with the fallback.
|
|
664
830
|
const packageRoot = 'package' as const;
|
|
665
831
|
const packagePath = join(staging, packageRoot);
|
|
666
|
-
const packageRecords = packageRuntimeFileIndex(sourceRoot);
|
|
667
|
-
stagePackageRuntimeSnapshot(sourceRoot, packagePath, packageRecords);
|
|
832
|
+
const packageRecords = packageRuntimeFileIndex(sourceRoot, dependencyRoot);
|
|
833
|
+
stagePackageRuntimeSnapshot(sourceRoot, packagePath, packageRecords, dependencyRoot);
|
|
668
834
|
const packageArtifactIdentity = `sha256:${sha256Directory(packagePath)}`;
|
|
669
835
|
|
|
670
836
|
const manifest = {
|
|
@@ -675,17 +841,27 @@ export function stageRuntimeRelease(input: {
|
|
|
675
841
|
executionMode: 'standalone-binary',
|
|
676
842
|
runtimeBundleEntrypoint,
|
|
677
843
|
runtimeBundleArtifactIdentity,
|
|
844
|
+
runtimeInterpreterEntrypoint,
|
|
845
|
+
runtimeInterpreterArtifactIdentity,
|
|
678
846
|
...(normalizedMacOSCodeSigning ? { macosCodeSigning: normalizedMacOSCodeSigning } : {}),
|
|
679
847
|
diagnosticEntrypoint: 'forge-cli',
|
|
680
848
|
diagnosticArtifactIdentity,
|
|
849
|
+
connectorEntrypoint,
|
|
850
|
+
connectorArtifactIdentity,
|
|
681
851
|
browserNodeBridgeEntrypoint,
|
|
682
852
|
browserNodeBridgeArtifactIdentity,
|
|
683
853
|
browserHandoffEntrypoint,
|
|
684
854
|
browserHandoffArtifactIdentity,
|
|
855
|
+
workflowSupervisorNativeHostEntrypoint,
|
|
856
|
+
workflowSupervisorNativeHostArtifactIdentity,
|
|
685
857
|
processRunnerEntrypoint,
|
|
686
858
|
processRunnerArtifactIdentity,
|
|
687
859
|
checkRunnerEntrypoint,
|
|
688
860
|
checkRunnerArtifactIdentity,
|
|
861
|
+
typescriptNavigationEntrypoint,
|
|
862
|
+
typescriptNavigationArtifactIdentity,
|
|
863
|
+
contextPackEntrypoint,
|
|
864
|
+
contextPackArtifactIdentity,
|
|
689
865
|
schedulerWorkerEntrypoint,
|
|
690
866
|
schedulerWorkerArtifactIdentity,
|
|
691
867
|
periodicCleanupEntrypoint,
|
|
@@ -702,11 +878,9 @@ export function stageRuntimeRelease(input: {
|
|
|
702
878
|
codeGraphLibraryArtifactIdentity,
|
|
703
879
|
packageRoot,
|
|
704
880
|
packageArtifactIdentity,
|
|
705
|
-
controllerUiRoot,
|
|
706
|
-
controllerUiArtifactIdentity,
|
|
707
881
|
arguments: [],
|
|
708
882
|
configurationSchemaVersion: 1,
|
|
709
|
-
|
|
883
|
+
deploymentScope: 'portable',
|
|
710
884
|
databaseSchemaCompatibility: {
|
|
711
885
|
minimum: CONTROL_PLANE_SCHEMA_VERSION,
|
|
712
886
|
maximum: CONTROL_PLANE_SCHEMA_VERSION,
|
|
@@ -728,12 +902,17 @@ export function stageRuntimeRelease(input: {
|
|
|
728
902
|
releaseId,
|
|
729
903
|
artifactIdentity,
|
|
730
904
|
runtimeBundleArtifactIdentity,
|
|
905
|
+
runtimeInterpreterArtifactIdentity,
|
|
731
906
|
...(normalizedMacOSCodeSigning ? { macosCodeSigning: normalizedMacOSCodeSigning } : {}),
|
|
732
907
|
diagnosticArtifactIdentity,
|
|
908
|
+
connectorArtifactIdentity,
|
|
733
909
|
browserNodeBridgeArtifactIdentity,
|
|
734
910
|
browserHandoffArtifactIdentity,
|
|
911
|
+
workflowSupervisorNativeHostArtifactIdentity,
|
|
735
912
|
processRunnerArtifactIdentity,
|
|
736
913
|
checkRunnerArtifactIdentity,
|
|
914
|
+
typescriptNavigationArtifactIdentity,
|
|
915
|
+
contextPackArtifactIdentity,
|
|
737
916
|
schedulerWorkerArtifactIdentity,
|
|
738
917
|
periodicCleanupArtifactIdentity,
|
|
739
918
|
pluginActionSidecarArtifactIdentity,
|
|
@@ -742,7 +921,6 @@ export function stageRuntimeRelease(input: {
|
|
|
742
921
|
codeGraphSidecarArtifactIdentity,
|
|
743
922
|
codeGraphLibraryArtifactIdentity,
|
|
744
923
|
packageArtifactIdentity,
|
|
745
|
-
controllerUiArtifactIdentity,
|
|
746
924
|
manifestSha256: createHash('sha256').update(`${JSON.stringify(manifest, null, 2)}\n`).digest('hex'),
|
|
747
925
|
sourceCommit,
|
|
748
926
|
...(sourceRepositoryId ? { sourceRepositoryId } : {}),
|
|
@@ -753,6 +931,161 @@ export function stageRuntimeRelease(input: {
|
|
|
753
931
|
}
|
|
754
932
|
}
|
|
755
933
|
|
|
934
|
+
|
|
935
|
+
interface RuntimeReleaseTreeInspection {
|
|
936
|
+
sha256: string;
|
|
937
|
+
bytes: number;
|
|
938
|
+
files: number;
|
|
939
|
+
}
|
|
940
|
+
|
|
941
|
+
function inspectRuntimeReleaseTree(releaseRootInput: string): RuntimeReleaseTreeInspection {
|
|
942
|
+
const requestedRoot = resolve(releaseRootInput);
|
|
943
|
+
if (!existsSync(requestedRoot)) throw new Error('RUNTIME_RELEASE_TREE_MISSING');
|
|
944
|
+
const rootStat = lstatSync(requestedRoot);
|
|
945
|
+
if (!rootStat.isDirectory() || rootStat.isSymbolicLink()) throw new Error('RUNTIME_RELEASE_TREE_ROOT_INVALID');
|
|
946
|
+
const root = realpathSync(requestedRoot);
|
|
947
|
+
const records: Array<{ path: string; mode: number; bytes: number; sha256: string }> = [];
|
|
948
|
+
const visit = (directory: string): void => {
|
|
949
|
+
for (const entry of readdirSync(directory, { withFileTypes: true }).sort((a, b) => a.name.localeCompare(b.name))) {
|
|
950
|
+
const path = join(directory, entry.name);
|
|
951
|
+
const stat = lstatSync(path);
|
|
952
|
+
if (stat.isSymbolicLink()) throw new Error(`RUNTIME_RELEASE_TREE_SYMLINK_FORBIDDEN: ${relative(root, path)}`);
|
|
953
|
+
if (stat.isDirectory()) {
|
|
954
|
+
visit(path);
|
|
955
|
+
continue;
|
|
956
|
+
}
|
|
957
|
+
if (!stat.isFile()) throw new Error(`RUNTIME_RELEASE_TREE_SPECIAL_FILE_FORBIDDEN: ${relative(root, path)}`);
|
|
958
|
+
const bytes = readFileSync(path);
|
|
959
|
+
records.push({
|
|
960
|
+
path: relative(root, path).replaceAll('\\', '/'),
|
|
961
|
+
mode: stat.mode & 0o777,
|
|
962
|
+
bytes: bytes.length,
|
|
963
|
+
sha256: createHash('sha256').update(bytes).digest('hex'),
|
|
964
|
+
});
|
|
965
|
+
}
|
|
966
|
+
};
|
|
967
|
+
visit(root);
|
|
968
|
+
const digest = createHash('sha256').update(JSON.stringify(records)).digest('hex');
|
|
969
|
+
return {
|
|
970
|
+
sha256: digest,
|
|
971
|
+
bytes: records.reduce((sum, record) => sum + record.bytes, 0),
|
|
972
|
+
files: records.length,
|
|
973
|
+
};
|
|
974
|
+
}
|
|
975
|
+
|
|
976
|
+
function preserveRuntimeReleaseTreeModes(sourceRootInput: string, targetRootInput: string): void {
|
|
977
|
+
const sourceRoot = resolve(sourceRootInput);
|
|
978
|
+
const targetRoot = resolve(targetRootInput);
|
|
979
|
+
const visit = (sourceDirectory: string, targetDirectory: string): void => {
|
|
980
|
+
for (const entry of readdirSync(sourceDirectory, { withFileTypes: true })) {
|
|
981
|
+
const sourcePath = join(sourceDirectory, entry.name);
|
|
982
|
+
const targetPath = join(targetDirectory, entry.name);
|
|
983
|
+
const sourceStat = lstatSync(sourcePath);
|
|
984
|
+
if (sourceStat.isDirectory()) {
|
|
985
|
+
chmodSync(targetPath, sourceStat.mode & 0o777);
|
|
986
|
+
visit(sourcePath, targetPath);
|
|
987
|
+
} else if (sourceStat.isFile()) {
|
|
988
|
+
// fs.cpSync applies the process umask to copied files. The release
|
|
989
|
+
// tree digest includes permission bits, so restore the source mode
|
|
990
|
+
// before comparing the staged tree with its immutable source.
|
|
991
|
+
chmodSync(targetPath, sourceStat.mode & 0o777);
|
|
992
|
+
}
|
|
993
|
+
}
|
|
994
|
+
};
|
|
995
|
+
chmodSync(targetRoot, lstatSync(sourceRoot).mode & 0o777);
|
|
996
|
+
visit(sourceRoot, targetRoot);
|
|
997
|
+
}
|
|
998
|
+
|
|
999
|
+
export function runtimeReleaseTreeSha256(releaseRoot: string): string {
|
|
1000
|
+
return inspectRuntimeReleaseTree(releaseRoot).sha256;
|
|
1001
|
+
}
|
|
1002
|
+
|
|
1003
|
+
export interface PromotedPortableRuntimeRelease {
|
|
1004
|
+
releaseId: string;
|
|
1005
|
+
artifactIdentity: string;
|
|
1006
|
+
manifestPath: string;
|
|
1007
|
+
manifestSha256: string;
|
|
1008
|
+
treeSha256: string;
|
|
1009
|
+
sourceReleaseRoot: string;
|
|
1010
|
+
targetReleaseRoot: string;
|
|
1011
|
+
reusedExisting: boolean;
|
|
1012
|
+
}
|
|
1013
|
+
|
|
1014
|
+
export function promotePortableRuntimeRelease(input: {
|
|
1015
|
+
sourceManifestPath: string;
|
|
1016
|
+
targetControllerHome: string;
|
|
1017
|
+
expectedTreeSha256: string;
|
|
1018
|
+
}): PromotedPortableRuntimeRelease {
|
|
1019
|
+
const sourceManifestPath = resolve(input.sourceManifestPath);
|
|
1020
|
+
const sourceReleaseRoot = dirname(sourceManifestPath);
|
|
1021
|
+
const targetControllerHome = resolve(input.targetControllerHome);
|
|
1022
|
+
const manifest = loadRuntimeReleaseManifest(sourceManifestPath, targetControllerHome);
|
|
1023
|
+
if (manifest.deploymentScope !== 'portable') throw new Error('RUNTIME_RELEASE_PROMOTION_REQUIRES_PORTABLE_ARTIFACT');
|
|
1024
|
+
requireCompleteCompiledRuntimeReleaseManifest(manifest);
|
|
1025
|
+
assertRuntimeReleaseExecutionSurface(sourceManifestPath, targetControllerHome);
|
|
1026
|
+
|
|
1027
|
+
const sourceTree = inspectRuntimeReleaseTree(sourceReleaseRoot);
|
|
1028
|
+
if (sourceTree.sha256 !== input.expectedTreeSha256) throw new Error('RUNTIME_RELEASE_PROMOTION_SOURCE_TREE_MISMATCH');
|
|
1029
|
+
const sourceManifestSha256 = createHash('sha256').update(readFileSync(sourceManifestPath)).digest('hex');
|
|
1030
|
+
|
|
1031
|
+
const releasesRoot = join(targetControllerHome, 'runtime', 'releases');
|
|
1032
|
+
mkdirSync(releasesRoot, { recursive: true, mode: 0o700 });
|
|
1033
|
+
const targetReleaseRoot = join(releasesRoot, manifest.releaseId);
|
|
1034
|
+
const targetManifestPath = join(targetReleaseRoot, 'manifest.json');
|
|
1035
|
+
|
|
1036
|
+
const verifyTarget = (reusedExisting: boolean): PromotedPortableRuntimeRelease => {
|
|
1037
|
+
const targetManifest = loadRuntimeReleaseManifest(targetManifestPath, targetControllerHome);
|
|
1038
|
+
if (
|
|
1039
|
+
targetManifest.deploymentScope !== 'portable'
|
|
1040
|
+
|| targetManifest.releaseId !== manifest.releaseId
|
|
1041
|
+
|| targetManifest.artifactIdentity !== manifest.artifactIdentity
|
|
1042
|
+
) throw new Error('RUNTIME_RELEASE_PROMOTION_TARGET_IDENTITY_MISMATCH');
|
|
1043
|
+
requireCompleteCompiledRuntimeReleaseManifest(targetManifest);
|
|
1044
|
+
assertRuntimeReleaseExecutionSurface(targetManifestPath, targetControllerHome);
|
|
1045
|
+
const targetManifestSha256 = createHash('sha256').update(readFileSync(targetManifestPath)).digest('hex');
|
|
1046
|
+
const targetTreeSha256 = runtimeReleaseTreeSha256(targetReleaseRoot);
|
|
1047
|
+
if (targetManifestSha256 !== sourceManifestSha256 || targetTreeSha256 !== sourceTree.sha256) {
|
|
1048
|
+
throw new Error('RUNTIME_RELEASE_PROMOTION_NOT_BYTE_IDENTICAL');
|
|
1049
|
+
}
|
|
1050
|
+
return {
|
|
1051
|
+
releaseId: manifest.releaseId,
|
|
1052
|
+
artifactIdentity: manifest.artifactIdentity,
|
|
1053
|
+
manifestPath: targetManifestPath,
|
|
1054
|
+
manifestSha256: targetManifestSha256,
|
|
1055
|
+
treeSha256: targetTreeSha256,
|
|
1056
|
+
sourceReleaseRoot,
|
|
1057
|
+
targetReleaseRoot,
|
|
1058
|
+
reusedExisting,
|
|
1059
|
+
};
|
|
1060
|
+
};
|
|
1061
|
+
|
|
1062
|
+
if (existsSync(targetReleaseRoot)) return verifyTarget(true);
|
|
1063
|
+
|
|
1064
|
+
assertStorageHeadroom(releasesRoot, {
|
|
1065
|
+
operation: 'runtime_release_promotion',
|
|
1066
|
+
requiredBytes: sourceTree.bytes,
|
|
1067
|
+
reserveBytes: 64 * 1024 * 1024,
|
|
1068
|
+
});
|
|
1069
|
+
const staging = join(releasesRoot, `.${manifest.releaseId}.promote-${process.pid}-${randomUUID().slice(0, 8)}`);
|
|
1070
|
+
try {
|
|
1071
|
+
cpSync(sourceReleaseRoot, staging, {
|
|
1072
|
+
recursive: true,
|
|
1073
|
+
force: false,
|
|
1074
|
+
errorOnExist: true,
|
|
1075
|
+
preserveTimestamps: false,
|
|
1076
|
+
dereference: false,
|
|
1077
|
+
});
|
|
1078
|
+
preserveRuntimeReleaseTreeModes(sourceReleaseRoot, staging);
|
|
1079
|
+
const stagedTree = inspectRuntimeReleaseTree(staging);
|
|
1080
|
+
if (stagedTree.sha256 !== sourceTree.sha256) throw new Error('RUNTIME_RELEASE_PROMOTION_STAGING_TREE_MISMATCH');
|
|
1081
|
+
renameSync(staging, targetReleaseRoot);
|
|
1082
|
+
return verifyTarget(false);
|
|
1083
|
+
} catch (error) {
|
|
1084
|
+
rmSync(staging, { recursive: true, force: true });
|
|
1085
|
+
throw error;
|
|
1086
|
+
}
|
|
1087
|
+
}
|
|
1088
|
+
|
|
756
1089
|
export function assertRuntimeReleaseFiles(release: StagedRuntimeRelease, dependencies: { platform?: NodeJS.Platform; inspectMacOSRuntime?: (executable: string) => MacOSRuntimeCodeSigning } = {}): void {
|
|
757
1090
|
const assertRegularFile = (path: string, missingCode: string): void => {
|
|
758
1091
|
if (!existsSync(path)) throw new Error(`${missingCode}: ${path}`);
|
|
@@ -803,6 +1136,13 @@ export function assertRuntimeReleaseFiles(release: StagedRuntimeRelease, depende
|
|
|
803
1136
|
assertFileIdentity(runtimePath, release.artifactIdentity);
|
|
804
1137
|
assertComponentFile({ path: join(release.releasePath, 'forge-runtime-bundle.js'), identity: release.runtimeBundleArtifactIdentity, missingCode: 'RUNTIME_RELEASE_BUNDLE_MISSING' });
|
|
805
1138
|
const platform = dependencies.platform ?? process.platform;
|
|
1139
|
+
const runtimeInterpreterEntrypoint = platform === 'win32' ? 'forge-runtime-bun.exe' : 'forge-runtime-bun';
|
|
1140
|
+
assertComponentFile({
|
|
1141
|
+
path: join(release.releasePath, runtimeInterpreterEntrypoint),
|
|
1142
|
+
identity: release.runtimeInterpreterArtifactIdentity,
|
|
1143
|
+
missingCode: 'RUNTIME_RELEASE_INTERPRETER_MISSING',
|
|
1144
|
+
executable: true,
|
|
1145
|
+
});
|
|
806
1146
|
if (platform === 'darwin' && release.macosCodeSigning) {
|
|
807
1147
|
const actual = (dependencies.inspectMacOSRuntime ?? inspectMacOSRuntimeCodeSigning)(runtimePath);
|
|
808
1148
|
if (actual.identifier !== release.macosCodeSigning.identifier
|
|
@@ -813,10 +1153,14 @@ export function assertRuntimeReleaseFiles(release: StagedRuntimeRelease, depende
|
|
|
813
1153
|
}
|
|
814
1154
|
}
|
|
815
1155
|
assertComponentFile({ path: join(release.releasePath, 'forge-cli'), identity: release.diagnosticArtifactIdentity, missingCode: 'RUNTIME_RELEASE_DIAGNOSTIC_ENTRYPOINT_MISSING', executable: true });
|
|
1156
|
+
assertComponentFile({ path: join(release.releasePath, 'forge-mcp-gateway'), identity: release.connectorArtifactIdentity, missingCode: 'RUNTIME_RELEASE_CONNECTOR_ENTRYPOINT_MISSING', executable: true });
|
|
816
1157
|
assertComponentFile({ path: join(release.releasePath, 'browser-node-bridge-host.js'), identity: release.browserNodeBridgeArtifactIdentity, missingCode: 'RUNTIME_RELEASE_BROWSER_NODE_HOST_MISSING', executable: true });
|
|
817
1158
|
assertComponentFile({ path: join(release.releasePath, 'browser-handoff-host.js'), identity: release.browserHandoffArtifactIdentity, missingCode: 'RUNTIME_RELEASE_BROWSER_HANDOFF_HOST_MISSING', executable: true });
|
|
1159
|
+
assertComponentFile({ path: join(release.releasePath, 'forge-workflow-supervisor-native-host'), identity: release.workflowSupervisorNativeHostArtifactIdentity, missingCode: 'RUNTIME_RELEASE_WORKFLOW_SUPERVISOR_NATIVE_HOST_MISSING', executable: true });
|
|
818
1160
|
assertComponentFile({ path: join(release.releasePath, 'process-runner.js'), identity: release.processRunnerArtifactIdentity, missingCode: 'RUNTIME_RELEASE_PROCESS_RUNNER_MISSING', executable: true });
|
|
819
1161
|
assertComponentFile({ path: join(release.releasePath, 'forge-check-runner'), identity: release.checkRunnerArtifactIdentity, missingCode: 'RUNTIME_RELEASE_CHECK_RUNNER_MISSING', executable: true });
|
|
1162
|
+
assertComponentFile({ path: join(release.releasePath, 'forge-typescript-navigation'), identity: release.typescriptNavigationArtifactIdentity, missingCode: 'RUNTIME_RELEASE_TYPESCRIPT_NAVIGATION_MISSING', executable: true });
|
|
1163
|
+
assertComponentFile({ path: join(release.releasePath, 'forge-context-pack'), identity: release.contextPackArtifactIdentity, missingCode: 'RUNTIME_RELEASE_CONTEXT_PACK_MISSING', executable: true });
|
|
820
1164
|
assertComponentFile({ path: join(release.releasePath, 'forge-scheduler-worker'), identity: release.schedulerWorkerArtifactIdentity, missingCode: 'RUNTIME_RELEASE_SCHEDULER_WORKER_MISSING', executable: true });
|
|
821
1165
|
assertComponentFile({ path: join(release.releasePath, 'forge-periodic-cleanup'), identity: release.periodicCleanupArtifactIdentity, missingCode: 'RUNTIME_RELEASE_PERIODIC_CLEANUP_MISSING', executable: true });
|
|
822
1166
|
assertComponentFile({ path: join(release.releasePath, 'forge-plugin-action-sidecar'), identity: release.pluginActionSidecarArtifactIdentity, missingCode: 'RUNTIME_RELEASE_PLUGIN_ACTION_SIDECAR_MISSING', executable: true });
|