@moretea-labs/forge 1.8.0 → 1.8.2
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 +73 -7
- package/CHANGELOG.md +34 -0
- package/CLAUDE.md +17 -2
- package/CONTRIBUTING.md +3 -2
- package/README.en.md +24 -3
- package/README.md +10 -6
- package/README.zh-CN.md +5 -3
- package/THIRD_PARTY_NOTICES.md +1 -2
- package/adapters/chatgpt/browser-delivery-host.ts +7 -1
- package/adapters/chatgpt/browser-delivery-runtime.ts +531 -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 +229 -2
- package/adapters/chatgpt/work-conversation-binding-store.ts +99 -54
- package/adapters/computer/chatgpt-extension-target.ts +708 -0
- package/adapters/computer/chrome-extension/background.js +541 -0
- package/adapters/computer/chrome-extension/content.js +402 -0
- package/adapters/computer/chrome-extension/core.js +24 -0
- package/adapters/computer/chrome-extension/manifest.json +32 -0
- package/adapters/computer/desktop-operator-discovery.ts +11 -31
- package/adapters/computer/desktop-operator-provider.ts +18 -6
- package/adapters/computer/interaction-target-authority.ts +178 -24
- package/adapters/mcp/access-mode.ts +18 -39
- package/adapters/mcp/auth.ts +2 -7
- package/adapters/mcp/instructions.ts +6 -5
- package/adapters/mcp/multi-repository.ts +10 -47
- package/adapters/mcp/oauth.ts +73 -0
- package/adapters/mcp/paths.ts +4 -1
- 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 +490 -113
- package/adapters/mcp/runtime-gateway/context-pack-sidecar.ts +83 -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 +14 -54
- package/adapters/mcp/runtime-gateway/gateway-execution-adapter.ts +2 -1
- package/adapters/mcp/runtime-gateway/plugin-adapter.ts +132 -47
- package/adapters/mcp/runtime-gateway/process-tools.ts +173 -23
- 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 +19 -507
- package/adapters/mcp/runtime-gateway/routing-policy.ts +506 -0
- package/adapters/mcp/runtime-gateway/runtime-observation-adapter.ts +15 -66
- package/adapters/mcp/runtime-gateway/runtime-readiness-observation.ts +218 -0
- package/adapters/mcp/runtime-gateway/runtime-tool-definitions.ts +123 -178
- package/adapters/mcp/runtime-gateway/runtime-tools.ts +11 -5
- package/adapters/mcp/runtime-gateway/scheduler-adapter.ts +37 -1
- package/adapters/mcp/runtime-gateway/shared-adapter.ts +20 -0
- package/adapters/mcp/runtime-gateway/status-inbox-adapter.ts +416 -270
- package/adapters/mcp/runtime-gateway/typescript-navigation-sidecar.ts +140 -0
- package/adapters/mcp/runtime-gateway/work-adapter.ts +262 -3123
- 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 +229 -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 +320 -0
- package/adapters/mcp/runtime-gateway/work-workflow-operations.ts +113 -0
- package/adapters/mcp/runtime-gateway/workflow-supervisor-adapter.ts +180 -0
- package/adapters/mcp/server.ts +91 -26
- package/adapters/mcp/setup.ts +5 -13
- package/adapters/mcp/tool-mapping/access-tools.ts +0 -6
- package/adapters/mcp/tool-mapping/legacy-tool-service.ts +703 -3092
- package/adapters/mcp/tool-mapping/post-finalize-work-attribution.ts +5 -10
- package/adapters/mcp/tool-mapping/repository-tools.ts +170 -213
- package/adapters/mcp/toolset-names.ts +11 -37
- package/adapters/mcp/toolset.ts +19 -92
- package/{src/cli → adapters}/mcp/transports/AGENTS.md +5 -5
- package/{src/cli → adapters}/mcp/transports/CLAUDE.md +5 -5
- package/adapters/mcp/transports/http-observation.ts +377 -0
- package/adapters/mcp/transports/http-post-lifecycle.ts +19 -0
- package/adapters/mcp/transports/http.ts +200 -683
- 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/adapters/mcp/types.ts +0 -6
- package/assets/hooks/lib/session-state.sh +0 -38
- package/assets/hooks/post-bash.sh +1 -1
- package/assets/hooks/post-tool-observer.sh +0 -5
- package/assets/hooks/prompt-guard.sh +0 -55
- package/assets/partials/04-project-structure.partial.md +1 -1
- package/assets/partials/07-footer.partial.md +1 -1
- package/assets/partials-agents/02-operating-mode.partial.md +1 -1
- package/assets/partials-agents/08-deep-docs.partial.md +1 -1
- package/assets/plugin-registry.v1.json +6 -4
- package/assets/reference-configs/agentic-development-flow.md +26 -1
- package/assets/reference-configs/external-tooling.md +0 -76
- package/assets/reference-configs/global-working-rules.md +19 -0
- package/assets/reference-configs/release-deploy.md +1 -1
- package/assets/templates/helpers/architecture-queue.sh +1 -1
- package/assets/templates/helpers/check-agent-tooling.sh +1 -327
- package/assets/templates/helpers/check-task-workflow.sh +1 -1
- package/assets/templates/helpers/ensure-task-workflow.sh +0 -14
- package/assets/templates/helpers/migrate-project-template.sh +2 -2
- package/assets/workflow-contract.v1.json +0 -2
- package/docs/README.md +5 -2
- package/docs/architecture/CURRENT.md +205 -51
- 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/20260904-ios-device-migration-baseline.md +42 -0
- 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 +234 -0
- package/docs/architecture/decisions/20260919-autonomous-work-liveness.md +62 -0
- package/docs/architecture/decisions/20260924-thin-semantic-working-context.md +74 -0
- package/docs/architecture/decisions/20261001-supervisor-turn-authority.md +342 -0
- package/docs/architecture/decisions/20261005-forge-v3-desktop-client-boundary.md +77 -0
- package/docs/architecture/decisions/20261009-exact-code-context-discovery.md +19 -0
- package/docs/architecture/decisions/20261009-generated-xcode-cache-retention.md +37 -0
- package/docs/architecture/decisions/20261011-autonomous-continuation-convergence.md +597 -0
- package/docs/architecture/decisions/20261017-edit-session-finalization-reconciliation.md +17 -0
- package/docs/architecture/decisions/20261019-retire-host-skills.md +16 -0
- package/docs/architecture/diagrams/agentic-dev-plugin-architecture.html +1 -1
- package/docs/architecture/domains/public-surface.md +3 -5
- package/docs/architecture/domains/verification.md +6 -5
- package/docs/architecture/domains/workflow-engine.md +6 -0
- package/docs/architecture/modules/controller-runtime/transport-lifecycle.md +3 -3
- package/docs/architecture/requests/2026-09-04-computer-plugin-workflow-taxonomy.md +4 -4
- package/docs/architecture/reviews/20261015-code-search-runtime-acceptance.md +75 -0
- package/docs/forge-plugin-management.md +16 -4
- package/docs/operations/controller-browser-plugin.md +23 -0
- package/docs/operations/controller-performance-and-502.md +17 -0
- package/docs/operations/controller-reliability-runbook.md +2 -2
- package/docs/operations/features.md +6 -7
- package/docs/operations/features.zh-CN.md +1 -1
- package/docs/operations/github-repository.md +4 -4
- package/docs/operations/github-semantic-release-projection.md +20 -0
- package/docs/operations/homebrew.md +2 -2
- package/docs/operations/mcp-tool-exposure.md +13 -52
- package/docs/operations/releasing.md +2 -0
- package/docs/operations/runtime-performance-diagnostics.md +8 -0
- package/docs/operations/standalone-disaster-recovery.md +15 -7
- package/docs/tutorials/01-install-and-start.zh-CN.md +1 -1
- package/docs/tutorials/03-first-repository-task.md +2 -0
- package/docs/wiki/Computer-and-Plugins.md +78 -0
- package/docs/wiki/Computer-and-Plugins.zh-CN.md +88 -0
- package/docs/wiki/Home.md +16 -2
- package/docs/wiki/Implementation.md +25 -13
- package/docs/wiki/Installation.md +28 -32
- package/docs/wiki/Integrations.md +4 -0
- package/docs/wiki/Quick-Start.md +35 -22
- package/docs/wiki/Releases-and-Upgrades.md +15 -25
- package/docs/wiki/_Sidebar.md +5 -1
- package/package.json +25 -25
- 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 +348 -97
- 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 +87 -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/eligibility.ts +4 -1
- 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 +166 -143
- package/packages/kernel/work/api/index.ts +3 -2
- package/packages/kernel/work/application/work-service.ts +18 -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 +34 -65
- package/packages/kernel/work/domain/types.ts +57 -51
- package/packages/kernel/work/infrastructure/work-contract-store.ts +847 -729
- package/packages/kernel/work/ports/work-contract-store.ts +5 -2
- package/packages/plugin-runtime/browser/provider-registry.ts +12 -36
- 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 +153 -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/assemble-template.ts +11 -72
- package/scripts/canary-controller-semantic-wait.ts +12 -24
- package/scripts/check-mcp-compatibility.ts +94 -201
- package/scripts/check-package-identity.mjs +0 -5
- package/scripts/check-runtime-architecture.mjs +921 -239
- package/scripts/forge-local-recovery-helper.mjs +93 -15
- package/scripts/init-project.sh +0 -46
- package/scripts/install-ios-hid-toolchain.sh +60 -0
- package/scripts/install-standalone-recovery.ts +1 -1
- package/scripts/lib/project-init-lib.sh +6 -3
- package/scripts/migrate-windows-wsl-controller-home.ts +2 -0
- package/scripts/open-source-audit-allowlist.txt +1 -3
- package/scripts/run-bounded-command.mjs +5 -0
- package/scripts/run-governed-gate.ts +2 -1
- package/scripts/run-mobile-monitor-bridge.ts +0 -1
- package/scripts/smoke-control-plane-failure-domain.ts +94 -0
- package/scripts/smoke-ios-physical-device.ts +38 -10
- package/scripts/smoke-mcp-http-runtime.ts +12 -8
- package/scripts/smoke-mcp-tool-surface.ts +27 -41
- 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 +95 -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/sync-generated-authority.mjs +0 -1
- package/scripts/verify-forge-runtime.sh +2 -1
- package/src/cli/agent-jobs/executor-health.ts +12 -35
- package/src/cli/agent-jobs/integration.ts +20 -51
- package/src/cli/agent-jobs/job-manager.ts +7 -3
- package/src/cli/chatgpt-browser/file-policy.ts +2 -2
- 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/doctor.ts +1 -143
- package/src/cli/commands/global-runtime.ts +3 -196
- package/src/cli/commands/init-hook.ts +6 -23
- package/src/cli/commands/init.ts +3 -252
- package/src/cli/commands/mcp.ts +0 -5
- package/src/cli/commands/prompt-guard-decision.ts +0 -2
- package/src/cli/commands/recovery.ts +137 -135
- package/src/cli/commands/repository.ts +17 -1
- package/src/cli/commands/runtime.ts +3 -3
- package/src/cli/commands/setup-execution.ts +41 -0
- 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 +5 -44
- package/src/cli/controller/completion-target.ts +3 -72
- package/src/cli/controller/composite-operations.ts +1 -1
- package/src/cli/controller/context/instruction-context.ts +1 -1
- package/src/cli/controller/context/known-paths.ts +2 -2
- package/src/cli/controller/context/query-planning.ts +11 -4
- package/src/cli/controller/context/rule-resolution.ts +2 -2
- package/src/cli/controller/context/source-materializer.ts +83 -102
- package/src/cli/controller/context/structural-provider.ts +84 -0
- package/src/cli/controller/context/structural.ts +6 -6
- package/src/cli/controller/context/types.ts +8 -9
- package/src/cli/controller/context-pack.ts +107 -84
- 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 +25 -52
- 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 +42 -10
- package/src/cli/editing/edit-session.ts +18 -12
- package/src/cli/github/github.ts +4 -4
- package/src/cli/github/semantic-projection.ts +174 -0
- package/src/cli/hook/prompt-intents.ts +0 -9
- package/src/cli/index.ts +1 -43
- package/src/cli/local-bridge/connector-freshness.ts +1 -12
- package/src/cli/local-bridge/console-automations.ts +19 -14
- package/src/cli/local-bridge/console-view-models.ts +4 -13
- package/src/cli/local-bridge/facade-api.ts +64 -193
- 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-classifier.ts +0 -9
- package/src/cli/repositories/command-executor.ts +29 -23
- package/src/cli/repositories/command-scope.ts +37 -18
- 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/locks.ts +20 -0
- package/src/cli/repositories/registry.ts +79 -12
- package/src/cli/repositories/safe-patch.ts +2 -12
- package/src/cli/repositories/structured-git.ts +101 -5
- package/src/cli/repository/inspector.ts +185 -343
- package/src/cli/repository/session-cache.ts +92 -6
- package/src/effects/process-runner.ts +17 -1
- 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/generic-lsp-provider.ts +1 -1
- package/src/runtime/context/semantic-navigation-contract.ts +16 -0
- package/src/runtime/context/semantic-navigation.ts +7 -35
- 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 +215 -12
- 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 +616 -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 +197 -110
- package/src/runtime/control-plane/execution/work-handle-store.ts +72 -44
- 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 +60 -34
- package/src/runtime/control-plane/execution/work-preparation-service.ts +231 -267
- package/src/runtime/control-plane/execution/work-process-evidence.ts +2 -2
- 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 +201 -199
- package/src/runtime/control-plane/execution/work-validation-reconciler.ts +33 -85
- package/src/runtime/control-plane/execution/work-verification-service.ts +406 -50
- package/src/runtime/control-plane/execution/work-verification-snapshot.ts +6 -2
- package/src/runtime/control-plane/facade/capability-registry.ts +364 -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 +9 -9
- package/src/runtime/control-plane/generated-cache-retention.ts +206 -59
- 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 +256 -117
- package/src/runtime/control-plane/global-scheduler/reconciliation.ts +3 -12
- 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/governance/external-effects.ts +1 -1
- package/src/runtime/control-plane/launcher/chatgpt-round-continuation.ts +63 -300
- package/src/runtime/control-plane/launcher/chatgpt-work-continuation.ts +29 -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 +295 -107
- 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/evidence/sensitive-output.ts +22 -2
- package/src/runtime/execution/jobs/child-reference.ts +11 -0
- package/src/runtime/execution/jobs/receipt-recovery.ts +1 -11
- 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 +82 -30
- 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 +55 -18
- package/src/runtime/execution/process-runtime/store.ts +30 -2
- package/src/runtime/execution/process-runtime/types.ts +6 -1
- package/src/runtime/execution/thin-harness/execution-router.ts +16 -16
- package/src/runtime/execution/thin-harness/fast-executor.ts +2 -2
- package/src/runtime/execution/thin-harness/search-worker.ts +2 -2
- package/src/runtime/execution/workers/executor.ts +3 -8
- package/src/runtime/maintenance/cleanup.ts +41 -5
- 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 +97 -29
- package/src/runtime/plugins/app-store-connect-adapter.ts +290 -18
- package/src/runtime/plugins/browser-adapter.ts +1124 -333
- package/src/runtime/plugins/browser-automation-service.ts +23 -3
- package/src/runtime/plugins/browser-macos-bridge.ts +431 -137
- package/src/runtime/plugins/browser-manifest-surface.ts +47 -12
- package/src/runtime/plugins/browser-native-session-service.ts +63 -13
- package/src/runtime/plugins/browser-registration.ts +18 -0
- package/src/runtime/plugins/browser-runtime.ts +40 -36
- 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 +228 -0
- package/src/runtime/plugins/computer-registration.ts +298 -20
- 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/github-adapter.ts +30 -3
- package/src/runtime/plugins/gmail-adapter.ts +189 -3
- package/src/runtime/plugins/google-calendar-adapter.ts +2 -2
- package/src/runtime/plugins/google-shared.ts +24 -12
- package/src/runtime/plugins/google-tasks-adapter.ts +2 -2
- package/src/runtime/plugins/ios/remote-xpc-hid.ts +70 -30
- package/src/runtime/plugins/ios-adapter.ts +46 -41
- package/src/runtime/plugins/ios-agent-device.ts +54 -4
- package/src/runtime/plugins/ios-device-ownership.ts +103 -0
- package/src/runtime/plugins/ios-physical-device.ts +497 -79
- package/src/runtime/plugins/lightweight-action.ts +208 -2
- package/src/runtime/plugins/local-system-adapter.ts +12 -100
- 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 +682 -435
- package/src/runtime/plugins/types.ts +24 -0
- package/src/runtime/plugins/xiaohongshu-publish.ts +16 -0
- package/src/runtime/projections/git-status-sampler.ts +2 -19
- package/src/runtime/projections/invalidation.ts +7 -3
- package/src/runtime/projections/materialized-view.ts +80 -36
- package/src/runtime/recovery/actions.ts +4 -4
- package/src/runtime/recovery/capability-action-application.ts +46 -45
- package/src/runtime/recovery/lifecycle-inventory.ts +30 -40
- package/src/runtime/recovery/maintenance-executor.ts +374 -123
- package/src/runtime/recovery/probe.ts +2 -2
- package/src/runtime/recovery/store.ts +29 -11
- package/src/runtime/release/release-coordinator.ts +312 -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 +254 -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 +227 -29
- package/src/runtime/root/package-runtime-release.ts +117 -30
- package/src/runtime/root/package-runtime-service.ts +24 -24
- package/src/runtime/root/release-execution-canary.ts +57 -12
- package/src/runtime/root/release-loader.ts +90 -8
- package/src/runtime/root/release-manifest.ts +80 -40
- package/src/runtime/root/release-materialize.ts +372 -106
- package/src/runtime/root/release-store.ts +395 -36
- package/src/runtime/root/runtime-lane.ts +191 -0
- package/src/runtime/root/runtime.ts +160 -29
- package/src/runtime/root/scheduled-controller-composition.ts +29 -3
- package/src/runtime/root/service-runner.ts +2 -2
- package/src/runtime/root/service.ts +126 -44
- package/src/runtime/root/status.ts +48 -0
- package/src/runtime/root/types.ts +32 -9
- package/src/runtime/root/workflow-supervisor-composition.ts +681 -0
- package/src/runtime/root/workflow-supervisor-runtime.ts +564 -0
- package/src/runtime/root/write-fence.ts +50 -2
- package/src/runtime/safe-tooling/google-credential-store.ts +67 -22
- package/src/runtime/safe-tooling/google-oauth-broker.ts +25 -7
- package/src/runtime/safe-tooling/ios-development.ts +22 -8
- package/src/runtime/safe-tooling/job-summary.ts +1 -1
- package/src/runtime/safe-tooling/workspace-auth.ts +5 -2
- package/src/runtime/shared/atomic-text-file.ts +21 -0
- package/src/runtime/shared/bounded-child-supervisor.ts +9 -1
- package/src/runtime/shared/json-files.ts +8 -3
- 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 +3792 -417
- package/src/runtime/standalone-recovery/entry.ts +507 -45
- 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 +12 -2
- 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 +11 -3
- package/src/runtime/workflow/schedules/engine.ts +166 -178
- package/src/runtime/workflow/schedules/pending-activation.ts +11 -4
- package/src/runtime/workflow/schedules/work-continuation.ts +95 -11
- 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 +218 -0
- package/supervisor/control-plane.ts +963 -0
- package/supervisor/entry.ts +15 -0
- package/supervisor/forge-validators.ts +147 -0
- package/supervisor/index.ts +5 -0
- package/supervisor/native-browser-adapter.ts +1151 -0
- package/supervisor/native-messaging/host.ts +58 -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 +250 -0
- package/supervisor/server.ts +412 -0
- package/supervisor/store.ts +1870 -0
- package/supervisor/tsconfig.json +8 -0
- package/supervisor/types.ts +261 -0
- package/SKILL.md +0 -427
- 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/adapters/mcp/runtime-gateway/work-validation-reconciler.ts +0 -1
- package/adapters/mcp/toolset-selection.ts +0 -41
- package/agents/openai.yaml +0 -4
- package/assets/skill-hooks.json +0 -41
- package/assets/skill-version.json +0 -189
- package/assets/skills/claude-review/SKILL.md +0 -231
- package/assets/skills/codex-review/SKILL.md +0 -103
- package/assets/templates/helpers/check-skill-version.ts +0 -193
- 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-skill-version.ts +0 -5
- package/scripts/check-tarball-install-smoke.sh +0 -150
- package/scripts/ensure-codegraph.sh +0 -16
- 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/run-skill-hook.ts +0 -244
- package/scripts/stage-runtime-release.ts +0 -44
- package/scripts/sync-codex-installed-copies.sh +0 -182
- package/src/cli/commands/tools.ts +0 -167
- 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/cli/mcp/access-mode.ts +0 -2
- package/src/cli/mcp/access-tools.ts +0 -2
- package/src/cli/mcp/audit.ts +0 -2
- package/src/cli/mcp/auth.ts +0 -2
- package/src/cli/mcp/instructions.ts +0 -2
- package/src/cli/mcp/legacy-context.ts +0 -2
- package/src/cli/mcp/legacy-tool-service.ts +0 -2
- package/src/cli/mcp/multi-repository.ts +0 -2
- package/src/cli/mcp/oauth.ts +0 -2
- package/src/cli/mcp/openai-secure-tunnel.ts +0 -2
- package/src/cli/mcp/paths.ts +0 -2
- package/src/cli/mcp/policy.ts +0 -2
- package/src/cli/mcp/post-finalize-work-attribution.ts +0 -2
- package/src/cli/mcp/proxy-env.ts +0 -2
- package/src/cli/mcp/readiness-projection.ts +0 -2
- package/src/cli/mcp/redaction.ts +0 -2
- package/src/cli/mcp/repo.ts +0 -2
- package/src/cli/mcp/repository-tools.ts +0 -2
- package/src/cli/mcp/server.ts +0 -2
- package/src/cli/mcp/setup.ts +0 -2
- package/src/cli/mcp/tool-capability-cache.ts +0 -2
- package/src/cli/mcp/tool-contract.ts +0 -2
- package/src/cli/mcp/tools.ts +0 -2
- package/src/cli/mcp/toolset-names.ts +0 -2
- package/src/cli/mcp/toolset-selection.ts +0 -2
- package/src/cli/mcp/toolset.ts +0 -2
- package/src/cli/mcp/transports/http.ts +0 -2
- package/src/cli/mcp/transports/session-registry.ts +0 -2
- package/src/cli/mcp/transports/stdio.ts +0 -2
- package/src/cli/mcp/types.ts +0 -2
- package/src/cli/mcp/umbrella-tools.ts +0 -2
- package/src/cli/tools/codegraph.ts +0 -695
- package/src/core/adoption/helper-wrapper-plan.ts +0 -159
- package/src/runtime/context/codegraph-cache-boundary.ts +0 -255
- package/src/runtime/context/codegraph-read-provider.ts +0 -611
- package/src/runtime/context/codegraph-sidecar.cjs +0 -248
- package/src/runtime/control-plane/codegraph-cache-retention.ts +0 -164
- 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
- package/src/runtime/gateway/mcp/execution-tools.ts +0 -2
- package/src/runtime/gateway/mcp/legacy-ios-tool-adapter.ts +0 -2
- package/src/runtime/gateway/mcp/persisted-check-process.ts +0 -2
- package/src/runtime/gateway/mcp/process-tools.ts +0 -2
- package/src/runtime/gateway/mcp/router.ts +0 -2
- package/src/runtime/gateway/mcp/runtime-tool-definitions.ts +0 -2
- package/src/runtime/gateway/mcp/runtime-tools.ts +0 -2
- package/src/runtime/gateway/mcp/work-validation-reconciler.ts +0 -2
- package/src/runtime/plugins/browser-provider-registry.ts +0 -2
|
@@ -13,11 +13,19 @@ interface ManagedSession {
|
|
|
13
13
|
activeStreams: number;
|
|
14
14
|
}
|
|
15
15
|
|
|
16
|
+
type RuntimeMcpRequestId = string | number;
|
|
17
|
+
interface ActiveRuntimeMcpPost {
|
|
18
|
+
response: Response;
|
|
19
|
+
requestIds: RuntimeMcpRequestId[];
|
|
20
|
+
transport?: NodeStreamableHTTPServerTransport;
|
|
21
|
+
}
|
|
22
|
+
|
|
16
23
|
export interface RuntimeMcpSessionSnapshot {
|
|
17
24
|
active: number;
|
|
18
25
|
maximum: number;
|
|
19
26
|
initializing: number;
|
|
20
27
|
protected: number;
|
|
28
|
+
activeRequests: number;
|
|
21
29
|
capacityAvailable: number;
|
|
22
30
|
capacityEvictions: number;
|
|
23
31
|
}
|
|
@@ -47,6 +55,8 @@ export interface StartRuntimeMcpTransportOptions {
|
|
|
47
55
|
onFatal?: (error: Error) => void;
|
|
48
56
|
/** Internal Runtime sessions are bounded even if a Gateway dies without DELETE. */
|
|
49
57
|
maximumSessions?: number;
|
|
58
|
+
/** Test/embedded override; production defaults to the bounded cutover grace. */
|
|
59
|
+
requestDrainTimeoutMs?: number;
|
|
50
60
|
}
|
|
51
61
|
|
|
52
62
|
function authorized(request: Request, configuredToken: string): boolean {
|
|
@@ -76,6 +86,15 @@ function observesToolSurface(body: unknown): boolean {
|
|
|
76
86
|
});
|
|
77
87
|
}
|
|
78
88
|
|
|
89
|
+
function runtimeMcpRequestIds(body: unknown): RuntimeMcpRequestId[] {
|
|
90
|
+
const values = Array.isArray(body) ? body : [body];
|
|
91
|
+
return values.flatMap((value) => {
|
|
92
|
+
if (!value || typeof value !== 'object') return [];
|
|
93
|
+
const id = (value as Record<string, unknown>).id;
|
|
94
|
+
return typeof id === 'string' || typeof id === 'number' ? [id] : [];
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
|
|
79
98
|
function parseBody(body: unknown): unknown {
|
|
80
99
|
if (!Buffer.isBuffer(body)) return body;
|
|
81
100
|
try { return JSON.parse(body.toString('utf8')); } catch {
|
|
@@ -95,7 +114,16 @@ function authMiddleware(token: string) {
|
|
|
95
114
|
}
|
|
96
115
|
|
|
97
116
|
const SESSION_CLOSE_TIMEOUT_MS = 1_000;
|
|
98
|
-
|
|
117
|
+
/**
|
|
118
|
+
* Cutover first withdraws admission, then gives already-admitted requests a
|
|
119
|
+
* bounded grace period that still fits inside the primary service stop budget.
|
|
120
|
+
* Requests that outlive it are explicitly settled as outcome-unknown before
|
|
121
|
+
* session/socket teardown, so an outer controller turn is never left waiting on
|
|
122
|
+
* a connection the Runtime is intentionally destroying.
|
|
123
|
+
*/
|
|
124
|
+
export const RUNTIME_MCP_REQUEST_DRAIN_TIMEOUT_MS = 5_000;
|
|
125
|
+
const CUTOVER_SETTLEMENT_DRAIN_TIMEOUT_MS = 250;
|
|
126
|
+
export const RUNTIME_MCP_CUTOVER_OUTCOME_UNKNOWN = 'MCP_RUNTIME_CUTOVER_OUTCOME_UNKNOWN';
|
|
99
127
|
export const DEFAULT_RUNTIME_MCP_MAX_SESSIONS = 64;
|
|
100
128
|
|
|
101
129
|
function boundedRuntimeMcpMaximumSessions(value: number | undefined): number {
|
|
@@ -112,31 +140,41 @@ function closeServer(server: NodeHttpServer): Promise<void> {
|
|
|
112
140
|
});
|
|
113
141
|
}
|
|
114
142
|
|
|
115
|
-
function boundedDrain(wait: Promise<void>, timeoutMs: number): Promise<
|
|
116
|
-
if (timeoutMs <= 0) return
|
|
117
|
-
|
|
118
|
-
|
|
143
|
+
async function boundedDrain(wait: Promise<void>, timeoutMs: number): Promise<boolean> {
|
|
144
|
+
if (timeoutMs <= 0) return false;
|
|
145
|
+
let drained = false;
|
|
146
|
+
await Promise.race([
|
|
147
|
+
wait.then(() => { drained = true; }).catch(() => undefined),
|
|
119
148
|
new Promise<void>((resolve) => setTimeout(resolve, timeoutMs)),
|
|
120
149
|
]);
|
|
150
|
+
return drained;
|
|
121
151
|
}
|
|
122
152
|
|
|
123
153
|
export async function closeRuntimeMcpTransportResources(input: {
|
|
124
154
|
closeListener: () => Promise<void>;
|
|
125
155
|
closeSessions: Array<() => Promise<void>>;
|
|
126
156
|
waitForRequestDrain?: () => Promise<void>;
|
|
157
|
+
settleActiveRequests?: () => void | Promise<void>;
|
|
127
158
|
forceCloseConnections?: () => void;
|
|
128
159
|
requestDrainTimeoutMs?: number;
|
|
129
160
|
sessionCloseTimeoutMs?: number;
|
|
130
161
|
}): Promise<void> {
|
|
131
|
-
// Withdraw the
|
|
132
|
-
//
|
|
133
|
-
//
|
|
162
|
+
// Withdraw the listener first so no new request can enter. Existing calls get
|
|
163
|
+
// one bounded grace window. If that expires, settle still-open POST responses
|
|
164
|
+
// as explicit cutover/outcome-unknown before closing session transports. This
|
|
165
|
+
// preserves the no-blind-replay contract while preventing a controller turn
|
|
166
|
+
// from being stranded on a socket the Runtime is about to destroy.
|
|
134
167
|
const listenerClose = input.closeListener();
|
|
135
168
|
void listenerClose.catch(() => undefined);
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
169
|
+
const requestDrain = input.waitForRequestDrain?.() ?? Promise.resolve();
|
|
170
|
+
const drained = await boundedDrain(
|
|
171
|
+
requestDrain,
|
|
172
|
+
Math.max(0, input.requestDrainTimeoutMs ?? RUNTIME_MCP_REQUEST_DRAIN_TIMEOUT_MS),
|
|
139
173
|
);
|
|
174
|
+
if (!drained) {
|
|
175
|
+
await input.settleActiveRequests?.();
|
|
176
|
+
await boundedDrain(requestDrain, CUTOVER_SETTLEMENT_DRAIN_TIMEOUT_MS);
|
|
177
|
+
}
|
|
140
178
|
const sessionDrain = Promise.allSettled(input.closeSessions.map(async (close) => await close()));
|
|
141
179
|
await boundedDrain(sessionDrain.then(() => undefined), Math.max(0, input.sessionCloseTimeoutMs ?? SESSION_CLOSE_TIMEOUT_MS));
|
|
142
180
|
input.forceCloseConnections?.();
|
|
@@ -152,12 +190,14 @@ export async function startRuntimeMcpTransport(
|
|
|
152
190
|
let initializingSessions = 0;
|
|
153
191
|
let capacityEvictions = 0;
|
|
154
192
|
let activeRequests = 0;
|
|
193
|
+
const activePosts = new Map<Response, ActiveRuntimeMcpPost>();
|
|
155
194
|
|
|
156
195
|
const sessionSnapshot = (): RuntimeMcpSessionSnapshot => ({
|
|
157
196
|
active: sessions.size,
|
|
158
197
|
maximum: maximumSessions,
|
|
159
198
|
initializing: initializingSessions,
|
|
160
199
|
protected: [...sessions.values()].filter((session) => session.activePosts > 0).length,
|
|
200
|
+
activeRequests,
|
|
161
201
|
capacityAvailable: Math.max(0, maximumSessions - sessions.size - initializingSessions),
|
|
162
202
|
capacityEvictions,
|
|
163
203
|
});
|
|
@@ -192,7 +232,7 @@ export async function startRuntimeMcpTransport(
|
|
|
192
232
|
managed.lastActivityAt = Date.now();
|
|
193
233
|
}
|
|
194
234
|
};
|
|
195
|
-
const
|
|
235
|
+
const postDrainWaiters = new Set<() => void>();
|
|
196
236
|
const app = express();
|
|
197
237
|
app.disable('x-powered-by');
|
|
198
238
|
app.use((_req, res, next) => {
|
|
@@ -202,18 +242,17 @@ export async function startRuntimeMcpTransport(
|
|
|
202
242
|
if (settled) return;
|
|
203
243
|
settled = true;
|
|
204
244
|
activeRequests = Math.max(0, activeRequests - 1);
|
|
205
|
-
if (activeRequests === 0) {
|
|
206
|
-
for (const resolve of requestDrainWaiters) resolve();
|
|
207
|
-
requestDrainWaiters.clear();
|
|
208
|
-
}
|
|
209
245
|
};
|
|
210
246
|
res.once('finish', settle);
|
|
211
247
|
res.once('close', settle);
|
|
212
248
|
next();
|
|
213
249
|
});
|
|
214
|
-
|
|
250
|
+
// Only POST requests can represent an in-flight tool mutation/read result that
|
|
251
|
+
// must settle before cutover. Long-lived GET/SSE streams are transport-only and
|
|
252
|
+
// must not consume the cutover grace window.
|
|
253
|
+
const waitForRequestDrain = (): Promise<void> => activePosts.size === 0
|
|
215
254
|
? Promise.resolve()
|
|
216
|
-
: new Promise<void>((resolve) =>
|
|
255
|
+
: new Promise<void>((resolve) => postDrainWaiters.add(resolve));
|
|
217
256
|
app.get('/ready', (_req, res) => {
|
|
218
257
|
const readiness = options.readiness();
|
|
219
258
|
res.status(readiness.ready ? 200 : 503).json(readiness);
|
|
@@ -221,12 +260,24 @@ export async function startRuntimeMcpTransport(
|
|
|
221
260
|
|
|
222
261
|
const requireAuth = authMiddleware(options.authToken);
|
|
223
262
|
app.post('/mcp', requireAuth, express.raw({ type: '*/*', limit: '1mb' }), (req, res) => {
|
|
263
|
+
const activePost: ActiveRuntimeMcpPost = { response: res, requestIds: [] };
|
|
264
|
+
activePosts.set(res, activePost);
|
|
265
|
+
const releasePostResponse = (): void => {
|
|
266
|
+
activePosts.delete(res);
|
|
267
|
+
if (activePosts.size === 0) {
|
|
268
|
+
for (const resolve of postDrainWaiters) resolve();
|
|
269
|
+
postDrainWaiters.clear();
|
|
270
|
+
}
|
|
271
|
+
};
|
|
272
|
+
res.once('finish', releasePostResponse);
|
|
273
|
+
res.once('close', releasePostResponse);
|
|
224
274
|
void (async () => {
|
|
225
275
|
let body: unknown;
|
|
226
276
|
try { body = parseBody(req.body); } catch (error) {
|
|
227
277
|
res.status(400).json({ error: error instanceof Error ? error.message : String(error) });
|
|
228
278
|
return;
|
|
229
279
|
}
|
|
280
|
+
activePost.requestIds = runtimeMcpRequestIds(body);
|
|
230
281
|
if (observesToolSurface(body)) options.onToolSurfaceObservation?.();
|
|
231
282
|
const requestedSessionId = req.headers['mcp-session-id'];
|
|
232
283
|
const sessionId = typeof requestedSessionId === 'string' ? requestedSessionId : undefined;
|
|
@@ -265,6 +316,7 @@ export async function startRuntimeMcpTransport(
|
|
|
265
316
|
});
|
|
266
317
|
},
|
|
267
318
|
});
|
|
319
|
+
activePost.transport = transport;
|
|
268
320
|
transport.onclose = () => {
|
|
269
321
|
if (transport.sessionId) sessions.delete(transport.sessionId);
|
|
270
322
|
};
|
|
@@ -293,10 +345,15 @@ export async function startRuntimeMcpTransport(
|
|
|
293
345
|
res.status(404).json({ error: 'mcp_session_not_found' });
|
|
294
346
|
return;
|
|
295
347
|
}
|
|
348
|
+
activePost.transport = managed.transport;
|
|
296
349
|
await withManagedSessionRequest(managed, 'post', async () => await managed.transport.handleRequest(req, res, body));
|
|
297
350
|
})().catch((error: unknown) => {
|
|
298
351
|
if (!res.headersSent) res.status(500).json({ error: 'mcp_request_failed' });
|
|
299
352
|
console.error('[forge-runtime mcp] request failed:', error);
|
|
353
|
+
}).finally(() => {
|
|
354
|
+
releasePostResponse();
|
|
355
|
+
res.off('finish', releasePostResponse);
|
|
356
|
+
res.off('close', releasePostResponse);
|
|
300
357
|
});
|
|
301
358
|
});
|
|
302
359
|
app.get('/mcp', requireAuth, (req, res) => {
|
|
@@ -362,6 +419,7 @@ export async function startRuntimeMcpTransport(
|
|
|
362
419
|
await closeRuntimeMcpTransportResources({
|
|
363
420
|
closeListener: async () => await closeServer(httpServer),
|
|
364
421
|
waitForRequestDrain,
|
|
422
|
+
requestDrainTimeoutMs: options.requestDrainTimeoutMs,
|
|
365
423
|
// Snapshot sessions only after the request drain: an initialize request
|
|
366
424
|
// already in flight may register its session while shutdown is starting.
|
|
367
425
|
closeSessions: [async () => {
|
|
@@ -369,6 +427,41 @@ export async function startRuntimeMcpTransport(
|
|
|
369
427
|
await Promise.allSettled(activeSessions.map(async ({ transport }) => await transport.close().catch(() => undefined)));
|
|
370
428
|
sessions.clear();
|
|
371
429
|
}],
|
|
430
|
+
settleActiveRequests: async () => {
|
|
431
|
+
for (const active of activePosts.values()) {
|
|
432
|
+
let protocolSettled = false;
|
|
433
|
+
if (active.transport && active.requestIds.length > 0) {
|
|
434
|
+
const outcomes = await Promise.allSettled(active.requestIds.map(async (id) => {
|
|
435
|
+
await active.transport!.send({
|
|
436
|
+
jsonrpc: '2.0',
|
|
437
|
+
id,
|
|
438
|
+
error: {
|
|
439
|
+
code: -32000,
|
|
440
|
+
message: RUNTIME_MCP_CUTOVER_OUTCOME_UNKNOWN,
|
|
441
|
+
data: {
|
|
442
|
+
outcome: 'unknown',
|
|
443
|
+
recoverable: true,
|
|
444
|
+
retryable: false,
|
|
445
|
+
action: 'reconcile',
|
|
446
|
+
},
|
|
447
|
+
},
|
|
448
|
+
});
|
|
449
|
+
}));
|
|
450
|
+
protocolSettled = outcomes.some((outcome) => outcome.status === 'fulfilled');
|
|
451
|
+
}
|
|
452
|
+
if (protocolSettled) continue;
|
|
453
|
+
const response = active.response;
|
|
454
|
+
if (response.destroyed || response.writableEnded || response.headersSent) continue;
|
|
455
|
+
response.status(409).json({
|
|
456
|
+
error: 'runtime_cutover_outcome_unknown',
|
|
457
|
+
code: RUNTIME_MCP_CUTOVER_OUTCOME_UNKNOWN,
|
|
458
|
+
message: 'Canonical Runtime entered cutover after this request was admitted. The request outcome is unknown; reconcile by request/effect identity before any retry.',
|
|
459
|
+
recoverable: true,
|
|
460
|
+
retryable: false,
|
|
461
|
+
action: 'reconcile',
|
|
462
|
+
});
|
|
463
|
+
}
|
|
464
|
+
},
|
|
372
465
|
forceCloseConnections: () => httpServer.closeAllConnections?.(),
|
|
373
466
|
});
|
|
374
467
|
},
|
|
@@ -10,13 +10,28 @@ import {
|
|
|
10
10
|
} from 'fs';
|
|
11
11
|
import { dirname, join } from 'path';
|
|
12
12
|
import { resolveControllerHome } from '../../cli/repositories/controller-home';
|
|
13
|
-
import { isProcessAlive } from '../shared/process-tree';
|
|
13
|
+
import { isProcessAlive, terminateProcessTree, type ProcessTreeTerminationResult } from '../shared/process-tree';
|
|
14
|
+
import { defaultProcessIdentityProbe, executableFingerprint, processIdentityMatches } from '../shared/process-identity';
|
|
14
15
|
|
|
15
16
|
export interface RuntimeOwnerRecord {
|
|
16
|
-
schemaVersion: 1;
|
|
17
|
+
schemaVersion: 1 | 2;
|
|
17
18
|
runtimeInstanceId: string;
|
|
18
19
|
pid: number;
|
|
19
20
|
acquiredAt: string;
|
|
21
|
+
/** Monotonic Controller-Home writer epoch. Schema v1 owners predate it. */
|
|
22
|
+
fencingGeneration?: number;
|
|
23
|
+
/** Optional OS-process identity evidence used only for bounded crash recovery. */
|
|
24
|
+
processStartTime?: string;
|
|
25
|
+
executableFingerprint?: string;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export interface RuntimeIncarnationRecord {
|
|
29
|
+
schemaVersion: 1;
|
|
30
|
+
controllerHome: string;
|
|
31
|
+
runtimeInstanceId: string;
|
|
32
|
+
pid: number;
|
|
33
|
+
fencingGeneration: number;
|
|
34
|
+
activatedAt: string;
|
|
20
35
|
}
|
|
21
36
|
|
|
22
37
|
export interface RuntimeOwnershipHandle {
|
|
@@ -28,11 +43,18 @@ export function runtimeOwnerPath(controllerHome: string): string {
|
|
|
28
43
|
return join(resolveControllerHome(controllerHome), 'runtime', 'active-runtime-owner.json');
|
|
29
44
|
}
|
|
30
45
|
|
|
46
|
+
export function runtimeIncarnationPath(controllerHome: string): string {
|
|
47
|
+
return join(resolveControllerHome(controllerHome), 'runtime', 'runtime-incarnation.json');
|
|
48
|
+
}
|
|
49
|
+
|
|
31
50
|
function readOwnerPath(path: string): RuntimeOwnerRecord | undefined {
|
|
32
51
|
if (!existsSync(path)) return undefined;
|
|
33
52
|
try {
|
|
34
53
|
const value = JSON.parse(readFileSync(path, 'utf8')) as RuntimeOwnerRecord;
|
|
35
|
-
if (value.schemaVersion !== 1 || !value.runtimeInstanceId || !Number.isInteger(value.pid)) return undefined;
|
|
54
|
+
if ((value.schemaVersion !== 1 && value.schemaVersion !== 2) || !value.runtimeInstanceId || !Number.isInteger(value.pid)) return undefined;
|
|
55
|
+
if (value.schemaVersion === 2 && (!Number.isInteger(value.fencingGeneration) || value.fencingGeneration! < 1)) return undefined;
|
|
56
|
+
if ((value.processStartTime === undefined) !== (value.executableFingerprint === undefined)) return undefined;
|
|
57
|
+
if (value.processStartTime !== undefined && (!value.processStartTime.trim() || !value.executableFingerprint?.trim())) return undefined;
|
|
36
58
|
return value;
|
|
37
59
|
} catch {
|
|
38
60
|
return undefined;
|
|
@@ -43,6 +65,208 @@ export function readRuntimeOwner(controllerHome: string): RuntimeOwnerRecord | u
|
|
|
43
65
|
return readOwnerPath(runtimeOwnerPath(controllerHome));
|
|
44
66
|
}
|
|
45
67
|
|
|
68
|
+
export function readRuntimeIncarnation(controllerHome: string): RuntimeIncarnationRecord | undefined {
|
|
69
|
+
const path = runtimeIncarnationPath(controllerHome);
|
|
70
|
+
if (!existsSync(path)) return undefined;
|
|
71
|
+
try {
|
|
72
|
+
const value = JSON.parse(readFileSync(path, 'utf8')) as RuntimeIncarnationRecord;
|
|
73
|
+
if (
|
|
74
|
+
value.schemaVersion !== 1
|
|
75
|
+
|| resolveControllerHome(value.controllerHome) !== resolveControllerHome(controllerHome)
|
|
76
|
+
|| !value.runtimeInstanceId
|
|
77
|
+
|| !Number.isInteger(value.pid)
|
|
78
|
+
|| !Number.isInteger(value.fencingGeneration)
|
|
79
|
+
|| value.fencingGeneration < 1
|
|
80
|
+
|| !Number.isFinite(Date.parse(value.activatedAt))
|
|
81
|
+
) return undefined;
|
|
82
|
+
return value;
|
|
83
|
+
} catch {
|
|
84
|
+
return undefined;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
function nextFencingGeneration(controllerHome: string, minimum = 1): number {
|
|
89
|
+
const incarnationGeneration = readRuntimeIncarnation(controllerHome)?.fencingGeneration ?? 0;
|
|
90
|
+
const ownerGeneration = readRuntimeOwner(controllerHome)?.fencingGeneration ?? 0;
|
|
91
|
+
return Math.max(minimum - 1, incarnationGeneration, ownerGeneration) + 1;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
function writeRuntimeIncarnation(record: RuntimeIncarnationRecord): void {
|
|
95
|
+
const path = runtimeIncarnationPath(record.controllerHome);
|
|
96
|
+
const temporary = `${path}.${process.pid}.${Date.now()}.tmp`;
|
|
97
|
+
writeFileSync(temporary, `${JSON.stringify(record, null, 2)}\n`, { encoding: 'utf8', mode: 0o600 });
|
|
98
|
+
renameSync(temporary, path);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
export interface RuntimeOwnershipInspection {
|
|
103
|
+
owner?: RuntimeOwnerRecord;
|
|
104
|
+
incarnation?: RuntimeIncarnationRecord;
|
|
105
|
+
ownerAlive: boolean;
|
|
106
|
+
incarnationAlive: boolean;
|
|
107
|
+
coherent: boolean;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
export function inspectRuntimeOwnership(controllerHome: string): RuntimeOwnershipInspection {
|
|
111
|
+
const owner = readRuntimeOwner(controllerHome);
|
|
112
|
+
const incarnation = readRuntimeIncarnation(controllerHome);
|
|
113
|
+
const coherent = Boolean(
|
|
114
|
+
owner
|
|
115
|
+
&& incarnation
|
|
116
|
+
&& owner.runtimeInstanceId === incarnation.runtimeInstanceId
|
|
117
|
+
&& owner.pid === incarnation.pid
|
|
118
|
+
&& (owner.fencingGeneration ?? incarnation.fencingGeneration) === incarnation.fencingGeneration,
|
|
119
|
+
);
|
|
120
|
+
// Schema-v2 owners carry OS-process identity. Once present, raw PID liveness
|
|
121
|
+
// is insufficient because a stopped Runtime PID may be reused by another
|
|
122
|
+
// process before Recovery reconciles durable ownership.
|
|
123
|
+
const ownerAlive = Boolean(owner && (
|
|
124
|
+
owner.processStartTime && owner.executableFingerprint
|
|
125
|
+
? runtimeOwnerProcessIdentityMatches(owner)
|
|
126
|
+
: isProcessAlive(owner.pid)
|
|
127
|
+
));
|
|
128
|
+
// A coherent incarnation is the same Runtime owner epoch, so inherit the
|
|
129
|
+
// stronger owner identity result instead of re-introducing PID-only liveness.
|
|
130
|
+
// Incarnation-only legacy evidence remains conservative because it has no
|
|
131
|
+
// independent process identity fields.
|
|
132
|
+
const incarnationAlive = Boolean(incarnation && (
|
|
133
|
+
coherent
|
|
134
|
+
? ownerAlive
|
|
135
|
+
: isProcessAlive(incarnation.pid)
|
|
136
|
+
));
|
|
137
|
+
return { owner, incarnation, ownerAlive, incarnationAlive, coherent };
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
export function runtimeOwnerProcessIdentityMatches(record: RuntimeOwnerRecord | undefined): boolean {
|
|
141
|
+
if (!record?.processStartTime || !record.executableFingerprint) return false;
|
|
142
|
+
return processIdentityMatches({
|
|
143
|
+
pid: record.pid,
|
|
144
|
+
processStartTime: record.processStartTime,
|
|
145
|
+
executableFingerprint: record.executableFingerprint,
|
|
146
|
+
}, record.pid).matches;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* Recovery calls this only after the service manager and Runtime listener have
|
|
151
|
+
* been proven stopped. It never kills a live process. Dead owner evidence is
|
|
152
|
+
* renamed, not discarded, so fencing generations and forensic evidence survive.
|
|
153
|
+
*/
|
|
154
|
+
export function reconcileStoppedRuntimeOwnership(controllerHome: string): {
|
|
155
|
+
ok: boolean;
|
|
156
|
+
changed: boolean;
|
|
157
|
+
detail: string;
|
|
158
|
+
inspection: RuntimeOwnershipInspection;
|
|
159
|
+
staleOwnerPath?: string;
|
|
160
|
+
} {
|
|
161
|
+
const inspection = inspectRuntimeOwnership(controllerHome);
|
|
162
|
+
if (inspection.ownerAlive || inspection.incarnationAlive) {
|
|
163
|
+
return {
|
|
164
|
+
ok: false,
|
|
165
|
+
changed: false,
|
|
166
|
+
detail: 'RUNTIME_OWNERSHIP_STILL_LIVE',
|
|
167
|
+
inspection,
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
const ownerPath = runtimeOwnerPath(controllerHome);
|
|
171
|
+
if (!inspection.owner || !existsSync(ownerPath)) {
|
|
172
|
+
return {
|
|
173
|
+
ok: true,
|
|
174
|
+
changed: false,
|
|
175
|
+
detail: 'Runtime ownership is already quiescent',
|
|
176
|
+
inspection,
|
|
177
|
+
};
|
|
178
|
+
}
|
|
179
|
+
const staleOwnerPath = `${ownerPath}.stale-${Date.now()}`;
|
|
180
|
+
renameSync(ownerPath, staleOwnerPath);
|
|
181
|
+
return {
|
|
182
|
+
ok: true,
|
|
183
|
+
changed: true,
|
|
184
|
+
detail: 'dead Runtime owner evidence was fenced out after service shutdown',
|
|
185
|
+
inspection,
|
|
186
|
+
staleOwnerPath,
|
|
187
|
+
};
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
|
|
191
|
+
export async function terminateVerifiedRuntimeOwner(
|
|
192
|
+
controllerHome: string,
|
|
193
|
+
expectedOwner?: RuntimeOwnerRecord | null,
|
|
194
|
+
): Promise<{
|
|
195
|
+
ok: boolean;
|
|
196
|
+
attempted: boolean;
|
|
197
|
+
detail: string;
|
|
198
|
+
owner?: RuntimeOwnerRecord;
|
|
199
|
+
termination?: ProcessTreeTerminationResult;
|
|
200
|
+
}> {
|
|
201
|
+
const owner = readRuntimeOwner(controllerHome);
|
|
202
|
+
if (expectedOwner) {
|
|
203
|
+
if (!owner) {
|
|
204
|
+
return {
|
|
205
|
+
ok: true,
|
|
206
|
+
attempted: false,
|
|
207
|
+
detail: 'Runtime owner disappeared during stop',
|
|
208
|
+
owner: expectedOwner,
|
|
209
|
+
};
|
|
210
|
+
}
|
|
211
|
+
if (
|
|
212
|
+
owner.pid !== expectedOwner.pid
|
|
213
|
+
|| owner.runtimeInstanceId !== expectedOwner.runtimeInstanceId
|
|
214
|
+
|| owner.fencingGeneration !== expectedOwner.fencingGeneration
|
|
215
|
+
|| owner.processStartTime !== expectedOwner.processStartTime
|
|
216
|
+
|| owner.executableFingerprint !== expectedOwner.executableFingerprint
|
|
217
|
+
) {
|
|
218
|
+
return {
|
|
219
|
+
ok: false,
|
|
220
|
+
attempted: false,
|
|
221
|
+
detail: 'RUNTIME_OWNER_CHANGED_DURING_STOP',
|
|
222
|
+
owner,
|
|
223
|
+
};
|
|
224
|
+
}
|
|
225
|
+
} else if (owner) {
|
|
226
|
+
return {
|
|
227
|
+
ok: false,
|
|
228
|
+
attempted: false,
|
|
229
|
+
detail: 'RUNTIME_OWNER_APPEARED_DURING_STOP',
|
|
230
|
+
owner,
|
|
231
|
+
};
|
|
232
|
+
}
|
|
233
|
+
if (!owner) return { ok: true, attempted: false, detail: 'Runtime owner is already absent' };
|
|
234
|
+
if (!isProcessAlive(owner.pid)) {
|
|
235
|
+
return { ok: true, attempted: false, detail: 'Runtime owner process is already dead', owner };
|
|
236
|
+
}
|
|
237
|
+
if (!owner.processStartTime || !owner.executableFingerprint) {
|
|
238
|
+
return {
|
|
239
|
+
ok: false,
|
|
240
|
+
attempted: false,
|
|
241
|
+
detail: 'RUNTIME_OWNER_IDENTITY_EVIDENCE_MISSING',
|
|
242
|
+
owner,
|
|
243
|
+
};
|
|
244
|
+
}
|
|
245
|
+
if (!runtimeOwnerProcessIdentityMatches(owner)) {
|
|
246
|
+
return {
|
|
247
|
+
ok: false,
|
|
248
|
+
attempted: false,
|
|
249
|
+
detail: 'RUNTIME_OWNER_IDENTITY_CHANGED',
|
|
250
|
+
owner,
|
|
251
|
+
};
|
|
252
|
+
}
|
|
253
|
+
const termination = await terminateProcessTree(owner.pid, {
|
|
254
|
+
gracePeriodMs: 1_500,
|
|
255
|
+
killAfterMs: 5_000,
|
|
256
|
+
pollIntervalMs: 50,
|
|
257
|
+
});
|
|
258
|
+
const exited = termination.exited && !isProcessAlive(owner.pid);
|
|
259
|
+
return {
|
|
260
|
+
ok: exited,
|
|
261
|
+
attempted: true,
|
|
262
|
+
detail: exited
|
|
263
|
+
? 'verified orphan Runtime owner process tree terminated after service shutdown'
|
|
264
|
+
: `verified orphan Runtime owner did not fully exit; remaining pids=${termination.remainingPids.join(',')}`,
|
|
265
|
+
owner,
|
|
266
|
+
termination,
|
|
267
|
+
};
|
|
268
|
+
}
|
|
269
|
+
|
|
46
270
|
export function acquireRuntimeOwnership(
|
|
47
271
|
controllerHome: string,
|
|
48
272
|
runtimeInstanceId: string,
|
|
@@ -51,14 +275,23 @@ export function acquireRuntimeOwnership(
|
|
|
51
275
|
if (!runtimeInstanceId.trim()) throw new Error('RUNTIME_INSTANCE_ID_REQUIRED');
|
|
52
276
|
const path = runtimeOwnerPath(controllerHome);
|
|
53
277
|
mkdirSync(dirname(path), { recursive: true, mode: 0o700 });
|
|
54
|
-
|
|
55
|
-
schemaVersion: 1,
|
|
56
|
-
runtimeInstanceId,
|
|
57
|
-
pid: process.pid,
|
|
58
|
-
acquiredAt: now(),
|
|
59
|
-
};
|
|
278
|
+
let minimumGeneration = nextFencingGeneration(controllerHome);
|
|
60
279
|
|
|
61
280
|
for (let attempt = 0; attempt < 3; attempt += 1) {
|
|
281
|
+
const generation = nextFencingGeneration(controllerHome, minimumGeneration);
|
|
282
|
+
const processStartTime = defaultProcessIdentityProbe.startTime(process.pid);
|
|
283
|
+
const processCommand = defaultProcessIdentityProbe.command(process.pid);
|
|
284
|
+
const record: RuntimeOwnerRecord = {
|
|
285
|
+
schemaVersion: 2,
|
|
286
|
+
runtimeInstanceId,
|
|
287
|
+
pid: process.pid,
|
|
288
|
+
acquiredAt: now(),
|
|
289
|
+
fencingGeneration: generation,
|
|
290
|
+
...(processStartTime && processCommand ? {
|
|
291
|
+
processStartTime,
|
|
292
|
+
executableFingerprint: executableFingerprint(processCommand),
|
|
293
|
+
} : {}),
|
|
294
|
+
};
|
|
62
295
|
try {
|
|
63
296
|
const fd = openSync(path, 'wx', 0o600);
|
|
64
297
|
try {
|
|
@@ -66,6 +299,19 @@ export function acquireRuntimeOwnership(
|
|
|
66
299
|
} finally {
|
|
67
300
|
closeSync(fd);
|
|
68
301
|
}
|
|
302
|
+
try {
|
|
303
|
+
writeRuntimeIncarnation({
|
|
304
|
+
schemaVersion: 1,
|
|
305
|
+
controllerHome: resolveControllerHome(controllerHome),
|
|
306
|
+
runtimeInstanceId,
|
|
307
|
+
pid: process.pid,
|
|
308
|
+
fencingGeneration: generation,
|
|
309
|
+
activatedAt: record.acquiredAt,
|
|
310
|
+
});
|
|
311
|
+
} catch (writeError) {
|
|
312
|
+
try { unlinkSync(path); } catch { /* ownership did not become usable */ }
|
|
313
|
+
throw writeError;
|
|
314
|
+
}
|
|
69
315
|
return {
|
|
70
316
|
record,
|
|
71
317
|
release: () => {
|
|
@@ -84,6 +330,12 @@ export function acquireRuntimeOwnership(
|
|
|
84
330
|
`RUNTIME_OWNERSHIP_CONFLICT: controller home is owned by ${current.runtimeInstanceId} pid=${current.pid}`,
|
|
85
331
|
);
|
|
86
332
|
}
|
|
333
|
+
minimumGeneration = Math.max(
|
|
334
|
+
minimumGeneration,
|
|
335
|
+
generation + 1,
|
|
336
|
+
(current?.fencingGeneration ?? 0) + 1,
|
|
337
|
+
(readRuntimeIncarnation(controllerHome)?.fencingGeneration ?? 0) + 1,
|
|
338
|
+
);
|
|
87
339
|
const stalePath = `${path}.stale-${Date.now()}-${attempt}`;
|
|
88
340
|
try { renameSync(path, stalePath); } catch (renameError) {
|
|
89
341
|
if ((renameError as NodeJS.ErrnoException).code !== 'ENOENT') throw renameError;
|