@moretea-labs/forge 1.7.2 → 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 +121 -62
- package/CHANGELOG.md +40 -0
- package/CLAUDE.md +57 -62
- package/CONTRIBUTING.md +3 -2
- package/README.md +2 -2
- package/SKILL.md +0 -1
- package/THIRD_PARTY_NOTICES.md +5 -2
- package/adapters/browser/index.ts +2 -0
- package/adapters/chatgpt/browser-delivery-host.ts +77 -0
- package/adapters/chatgpt/browser-delivery-runtime.ts +1256 -0
- package/adapters/chatgpt/controller-binding-store.ts +134 -0
- package/adapters/chatgpt/controller-round-host.ts +68 -0
- package/adapters/chatgpt/controller-round-settlement-store.ts +99 -0
- package/adapters/chatgpt/provider-delivery.ts +340 -0
- package/adapters/chatgpt/work-conversation-binding-store.ts +218 -0
- package/adapters/chatgpt/wsl-bridge-delivery-host.ts +63 -0
- 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-contract.ts +7 -0
- package/adapters/computer/desktop-operator-discovery.ts +181 -0
- package/adapters/computer/desktop-operator-negotiation.ts +174 -0
- package/adapters/computer/desktop-operator-provider.ts +312 -0
- package/adapters/computer/index.ts +1 -0
- package/adapters/computer/interaction-target-authority.ts +1068 -0
- package/adapters/controller-process/binding-store.ts +34 -0
- package/adapters/controller-process/controller-host.ts +26 -0
- package/adapters/mcp/access-mode.ts +132 -0
- package/adapters/mcp/audit.ts +32 -0
- package/adapters/mcp/auth.ts +406 -0
- package/adapters/mcp/instructions.ts +37 -0
- package/adapters/mcp/legacy-context.ts +18 -0
- package/adapters/mcp/multi-repository.ts +421 -0
- package/adapters/mcp/oauth.ts +464 -0
- package/adapters/mcp/paths.ts +143 -0
- package/adapters/mcp/policy.ts +232 -0
- package/adapters/mcp/proxy-env.ts +62 -0
- package/adapters/mcp/readiness-projection.ts +24 -0
- package/adapters/mcp/redaction.ts +21 -0
- package/adapters/mcp/repo.ts +24 -0
- package/adapters/mcp/runtime-gateway/artifact-adapter.ts +52 -0
- 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 +1167 -0
- package/adapters/mcp/runtime-gateway/context-pack-sidecar.ts +91 -0
- package/adapters/mcp/runtime-gateway/controller-authority-adapter.ts +206 -0
- package/adapters/mcp/runtime-gateway/core-capability-adapter.ts +258 -0
- package/adapters/mcp/runtime-gateway/engineering-preconditions.ts +130 -0
- package/adapters/mcp/runtime-gateway/engineering-tool-contract.ts +15 -0
- package/adapters/mcp/runtime-gateway/execution-control-adapter.ts +28 -0
- package/adapters/mcp/runtime-gateway/execution-tools.ts +173 -0
- package/adapters/mcp/runtime-gateway/filesystem-adapter.ts +38 -0
- package/adapters/mcp/runtime-gateway/gateway-execution-adapter.ts +412 -0
- package/adapters/mcp/runtime-gateway/legacy-ios-tool-adapter.ts +105 -0
- package/adapters/mcp/runtime-gateway/maintenance-adapter.ts +44 -0
- package/adapters/mcp/runtime-gateway/model-adapter.ts +63 -0
- package/adapters/mcp/runtime-gateway/persisted-check-process.ts +3 -0
- package/adapters/mcp/runtime-gateway/plugin-adapter.ts +380 -0
- package/adapters/mcp/runtime-gateway/process-tools.ts +457 -0
- package/adapters/mcp/runtime-gateway/protected-computer-adapter.ts +88 -0
- package/adapters/mcp/runtime-gateway/recovery-adapter.ts +285 -0
- package/adapters/mcp/runtime-gateway/recovery-client-adapter.ts +70 -0
- package/adapters/mcp/runtime-gateway/recovery-tool-contract.ts +99 -0
- package/adapters/mcp/runtime-gateway/repository-compat-adapter.ts +79 -0
- package/adapters/mcp/runtime-gateway/result-adapter.ts +114 -0
- package/adapters/mcp/runtime-gateway/router.ts +242 -0
- package/adapters/mcp/runtime-gateway/routing-policy.ts +499 -0
- package/adapters/mcp/runtime-gateway/runtime-observation-adapter.ts +1200 -0
- package/adapters/mcp/runtime-gateway/runtime-readiness-observation.ts +218 -0
- package/adapters/mcp/runtime-gateway/runtime-tool-definitions.ts +574 -0
- package/adapters/mcp/runtime-gateway/runtime-tool-shared.ts +27 -0
- package/adapters/mcp/runtime-gateway/runtime-tools.ts +78 -0
- package/adapters/mcp/runtime-gateway/scheduler-adapter.ts +187 -0
- package/adapters/mcp/runtime-gateway/shared-adapter.ts +45 -0
- package/adapters/mcp/runtime-gateway/status-inbox-adapter.ts +962 -0
- package/adapters/mcp/runtime-gateway/typescript-navigation-sidecar.ts +136 -0
- package/adapters/mcp/runtime-gateway/work-adapter.ts +325 -0
- 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-validation-reconciler.ts +1 -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 +1092 -0
- package/adapters/mcp/setup.ts +789 -0
- package/adapters/mcp/tool-capability-cache.ts +87 -0
- package/adapters/mcp/tool-mapping/access-tools.ts +387 -0
- package/adapters/mcp/tool-mapping/legacy-tool-service.ts +5139 -0
- package/adapters/mcp/tool-mapping/post-finalize-work-attribution.ts +145 -0
- package/adapters/mcp/tool-mapping/repository-tools.ts +1682 -0
- package/adapters/mcp/tool-mapping/tools.ts +9 -0
- package/adapters/mcp/tool-mapping/umbrella-tools.ts +117 -0
- package/adapters/mcp/toolset-names.ts +79 -0
- package/adapters/mcp/toolset-selection.ts +41 -0
- package/adapters/mcp/toolset.ts +337 -0
- package/adapters/mcp/transports/http-observation.ts +365 -0
- package/adapters/mcp/transports/http.ts +933 -0
- package/adapters/mcp/transports/oauth-http.ts +322 -0
- package/adapters/mcp/transports/session-registry.ts +519 -0
- package/adapters/mcp/transports/stdio.ts +8 -0
- package/adapters/mcp/tunnels/openai-secure-tunnel.ts +223 -0
- package/adapters/mcp/types.ts +41 -0
- package/assets/AGENTS.md +2 -16
- package/assets/CLAUDE.md +2 -16
- package/assets/hooks/AGENTS.md +3 -14
- package/assets/hooks/CLAUDE.md +3 -14
- package/assets/hooks/hook-input.sh +9 -2
- package/assets/hooks/lib/workflow-state.sh +28 -10
- package/assets/hooks/prompt-guard.sh +63 -37
- package/assets/hooks/security-sentinel.sh +2 -1
- package/assets/hooks/session-start-context.sh +7 -5
- package/assets/hooks/stop-orchestrator.sh +13 -3
- package/assets/initializer-question-pack.v4.json +11 -7
- package/assets/partials/05-workflow.partial.md +18 -73
- package/assets/partials/07-footer.partial.md +1 -1
- package/assets/partials-agents/02-operating-mode.partial.md +1 -2
- package/assets/partials-agents/04-task-protocol.partial.md +14 -59
- package/assets/partials-agents/06-quality-safety.partial.md +11 -16
- package/assets/partials-agents/08-deep-docs.partial.md +1 -2
- package/assets/plan-map.json +11 -11
- package/assets/plugin-registry.v1.json +11 -3
- package/assets/plugin-trust-policy.v1.json +6 -0
- package/assets/recovery/ForgeRecovery.ps1 +100 -0
- package/assets/recovery/forge-wsl-rescue +271 -0
- package/assets/reference-configs/agentic-development-flow.md +25 -0
- package/assets/reference-configs/development-protocol.md +11 -15
- package/assets/reference-configs/document-generation.md +1 -1
- package/assets/reference-configs/global-working-rules.md +28 -1
- package/assets/reference-configs/harness-overview.md +22 -112
- package/assets/reference-configs/hook-operations.md +1 -1
- package/assets/reference-configs/sprint-contracts.md +2 -2
- package/assets/skill-version.json +2 -2
- package/assets/templates/helpers/architecture-event.ts +3 -34
- package/assets/templates/helpers/architecture-queue.sh +61 -10
- package/assets/templates/helpers/archive-workflow.sh +90 -180
- package/assets/templates/helpers/capability-config.ts +8 -11
- package/assets/templates/helpers/capability-resolver.ts +37 -19
- package/assets/templates/helpers/capture-plan.sh +2 -2
- package/assets/templates/helpers/check-architecture-sync.sh +1 -9
- package/assets/templates/helpers/check-task-sync.sh +82 -11
- package/assets/templates/helpers/check-task-workflow.sh +1 -3
- package/assets/templates/helpers/context-contract-sync.sh +1 -12
- package/assets/templates/helpers/contract-worktree.sh +26 -24
- package/assets/templates/helpers/ensure-task-workflow.sh +6 -8
- package/assets/templates/helpers/inspect-project-state.ts +1 -1
- package/assets/templates/helpers/migrate-project-template.sh +1 -1
- package/assets/templates/helpers/migrate-workflow-docs.ts +53 -239
- package/assets/templates/helpers/new-plan.sh +2 -2
- package/assets/templates/helpers/plan-to-todo.sh +3 -31
- package/assets/templates/helpers/sprint-backlog.sh +1 -1
- package/assets/templates/helpers/switch-plan.sh +1 -1
- package/assets/templates/helpers/workflow-contract.ts +1 -0
- package/assets/workflow-contract.v1.json +63 -171
- package/assets/workflows/xiaohongshu/xiaohongshu.collect-metrics.v1.draft.json +118 -0
- package/assets/workflows/xiaohongshu/xiaohongshu.publish-image-note.v1.draft.json +316 -0
- package/assets/workflows/xiaohongshu/xiaohongshu.publish-long-text.v1.draft.json +324 -0
- package/docs/architecture/CURRENT.md +233 -28
- package/docs/architecture/EVOLUTION.md +13 -0
- package/docs/architecture/decisions/20260801-controller-home-sqlite-state.md +2 -1
- 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/20260831-independent-windows-wsl-host-rescue.md +59 -0
- package/docs/architecture/decisions/20260904-ios-device-migration-baseline.md +120 -0
- package/docs/architecture/decisions/20260904-repository-runtime-data-boundary.md +42 -0
- package/docs/architecture/decisions/20260907-assistant-learning-loop.md +37 -0
- package/docs/architecture/decisions/20260907-controller-round-transition-policy.md +311 -0
- package/docs/architecture/decisions/20260907-maintenance-diagnosis-bounded-read.md +39 -0
- 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 +8 -0
- package/docs/architecture/domains/workflow-engine.md +7 -1
- package/docs/architecture/index.md +3 -3
- package/docs/architecture/modules/controller-runtime/transport-lifecycle.md +19 -8
- package/docs/architecture/requests/2026-09-04-computer-plugin-workflow-taxonomy.md +124 -0
- package/docs/forge-chatgpt-mcp-setup.md +5 -3
- package/docs/forge-plugin-management.md +20 -4
- package/docs/forge-runtime-self-healing-loop.md +2 -0
- package/docs/operations/benchmark-cross-version-freeze.md +38 -0
- package/docs/operations/controller-browser-plugin.md +3 -1
- 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/platform-support.md +16 -8
- package/docs/operations/platform-support.zh-CN.md +2 -2
- package/docs/operations/releasing.md +2 -0
- package/docs/operations/standalone-disaster-recovery.md +38 -5
- package/docs/operations/uu-remote-rescue.md +41 -0
- package/docs/operations/windows-wsl-host-rescue.md +133 -0
- package/docs/public-usage-guide.md +1 -1
- package/docs/public-usage-guide.zh-CN.md +1 -1
- package/docs/tutorials/01-install-and-start.md +1 -1
- package/docs/tutorials/01-install-and-start.zh-CN.md +1 -1
- package/docs/tutorials/02-connect-chatgpt.md +4 -4
- package/docs/tutorials/02-connect-chatgpt.zh-CN.md +4 -4
- package/docs/wiki/Implementation.md +1 -1
- package/package.json +46 -26
- 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 +3 -0
- package/packages/kernel/controller/application/continuation-service.ts +281 -0
- package/packages/kernel/controller/application/controller-round-service.ts +41 -0
- package/packages/kernel/controller/application/controller-service.ts +30 -0
- package/packages/kernel/controller/domain/controller-round-transition-policy.ts +529 -0
- package/packages/kernel/controller/domain/controller-round.ts +110 -0
- package/packages/kernel/controller/domain/execution-quality.ts +135 -0
- package/packages/kernel/controller/domain/types.ts +56 -0
- package/packages/kernel/controller/index.ts +1 -0
- package/packages/kernel/controller/infrastructure/controller-binding-store.ts +84 -0
- package/packages/kernel/controller/infrastructure/controller-round-store.ts +1970 -0
- package/packages/kernel/controller/infrastructure/controller-session-store.ts +804 -0
- package/packages/kernel/controller/ports/controller-host.ts +18 -0
- package/packages/kernel/goal/api/index.ts +1 -0
- package/packages/kernel/goal/domain/types.ts +40 -0
- package/packages/kernel/goal/index.ts +1 -0
- package/packages/kernel/identity/api/index.ts +15 -0
- package/packages/kernel/identity/application/identity-service.ts +67 -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/scope.ts +63 -0
- package/packages/kernel/identity/domain/semantic-sync.ts +81 -0
- package/packages/kernel/identity/domain/types.ts +44 -0
- package/packages/kernel/identity/domain/user-request.ts +93 -0
- package/packages/kernel/identity/domain/workspace.ts +56 -0
- package/packages/kernel/identity/index.ts +1 -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/identity-store.ts +75 -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/memory/api/index.ts +5 -0
- package/packages/kernel/memory/application/experience-service.ts +118 -0
- package/packages/kernel/memory/application/outcome-service.ts +77 -0
- package/packages/kernel/memory/domain/experience.ts +103 -0
- package/packages/kernel/memory/domain/operational-prior.ts +92 -0
- package/packages/kernel/memory/index.ts +1 -0
- package/packages/kernel/scheduler/api/index.ts +4 -0
- package/packages/kernel/scheduler/application/eligibility.ts +252 -0
- package/packages/kernel/scheduler/application/schedule-service.ts +27 -0
- package/packages/kernel/scheduler/application/settlement.ts +182 -0
- package/packages/kernel/scheduler/domain/schedule.ts +236 -0
- package/packages/kernel/scheduler/index.ts +1 -0
- package/packages/kernel/scheduler/infrastructure/schedule-store.ts +805 -0
- package/packages/kernel/work/api/index.ts +16 -0
- package/packages/kernel/work/application/work-service.ts +123 -0
- package/packages/kernel/work/domain/check-receipt.ts +43 -0
- package/packages/kernel/work/domain/context-closure-receipt.ts +32 -0
- package/packages/kernel/work/domain/current-task-lineage.ts +104 -0
- package/packages/kernel/work/domain/engineering-contracts.ts +157 -0
- package/packages/kernel/work/domain/engineering-design.ts +286 -0
- package/packages/kernel/work/domain/engineering-profile.ts +238 -0
- package/packages/kernel/work/domain/evaluation-promotion-receipt.ts +186 -0
- package/packages/kernel/work/domain/execution-concurrency.ts +247 -0
- package/packages/kernel/work/domain/execution-snapshot.ts +2 -0
- package/packages/kernel/work/domain/implementation-review.ts +193 -0
- package/packages/kernel/work/domain/objective-graph.ts +119 -0
- package/packages/kernel/work/domain/project-engineering-contract.ts +224 -0
- package/packages/kernel/work/domain/repository-completion-receipt.ts +73 -0
- package/{src/runtime/control-plane/facade/work-state-machine.ts → packages/kernel/work/domain/state-machine.ts} +37 -66
- package/packages/kernel/work/domain/types.ts +534 -0
- package/packages/kernel/work/index.ts +1 -0
- package/packages/kernel/work/infrastructure/work-contract-store.ts +1967 -0
- package/packages/kernel/work/ports/work-contract-store.ts +21 -0
- package/packages/plugin-runtime/browser/index.ts +3 -0
- package/packages/plugin-runtime/browser/provider-registry.ts +110 -0
- package/packages/plugin-runtime/browser/runtime-contract.ts +150 -0
- package/packages/plugin-runtime/browser/session-authority.ts +62 -0
- 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 +8 -0
- package/packages/plugin-runtime/computer/provider-error.ts +26 -0
- package/packages/plugin-runtime/computer/provider-registration.ts +52 -0
- package/packages/plugin-runtime/computer/provider-registry.ts +63 -0
- package/packages/plugin-runtime/computer/provider.ts +19 -0
- package/packages/plugin-runtime/computer/target-authority.ts +215 -0
- package/packages/plugin-runtime/computer/target-persistence.ts +54 -0
- package/packages/plugin-runtime/external/index.ts +1 -0
- package/packages/plugin-runtime/external/unix-jsonl-transport.ts +581 -0
- package/packages/plugin-runtime/index.ts +3 -0
- package/packages/protocols/browser/index.ts +1 -0
- package/packages/protocols/browser/session.ts +98 -0
- package/packages/protocols/computer/contract.ts +225 -0
- package/packages/protocols/computer/index.ts +1 -0
- package/packages/protocols/failure/contract.ts +158 -0
- package/packages/protocols/failure/index.ts +1 -0
- package/packages/protocols/handoff/index.ts +1 -0
- package/packages/protocols/handoff/status.ts +22 -0
- package/packages/protocols/mcp/execution-context.ts +11 -0
- package/packages/protocols/mcp/index.ts +2 -0
- package/packages/protocols/mcp/tool-contract.ts +42 -0
- package/packages/workflow-runtime/api/index.ts +2 -0
- package/packages/workflow-runtime/application/interpreter.ts +342 -0
- package/packages/workflow-runtime/domain/workflow-asset.ts +223 -0
- package/packages/workflow-runtime/index.ts +1 -0
- package/scripts/activate-source-baseline.ts +7 -9
- package/scripts/assemble-template.ts +1 -1
- package/scripts/bootstrap-runtime-maintenance-recovery.sh +4 -1
- package/scripts/canary-chatgpt-provider-delivery.ts +97 -0
- package/scripts/canary-controller-semantic-wait.ts +183 -0
- package/scripts/canary-global-hook.sh +2 -2
- package/scripts/check-mcp-compatibility.ts +85 -7
- package/scripts/check-platform-support.mjs +28 -2
- package/scripts/check-public-docs.sh +1 -1
- package/scripts/check-repository-hygiene.mjs +92 -0
- package/scripts/check-runtime-architecture.mjs +1643 -127
- package/scripts/check-source-duplication.mjs +9 -1
- package/scripts/controller-ngrok-rotation.sh +5 -4
- package/scripts/create-project-dirs.sh +10 -74
- package/scripts/forge-local-recovery-helper.mjs +282 -0
- package/scripts/forge-uu-remote-rescue-helper.d.mts +31 -0
- package/scripts/forge-uu-remote-rescue-helper.mjs +409 -0
- package/scripts/forge-windows-host-recovery-helper.mjs +136 -0
- package/scripts/hook-shim.sh +2 -2
- package/scripts/init-project.sh +12 -70
- package/scripts/install-desktop-operator-registration.ts +4 -2
- package/scripts/install-independent-windows-wsl-recovery.ts +125 -0
- package/scripts/install-standalone-recovery.ts +122 -10
- package/scripts/install-uu-remote-rescue-registration.ts +74 -0
- package/scripts/install-windows-host-recovery-registration.ts +22 -0
- package/scripts/lib/controller-home-env.sh +6 -3
- package/scripts/lib/project-init-lib.sh +42 -582
- package/scripts/migrate-chatgpt-automation-schedules.ts +2 -2
- package/scripts/migrate-windows-wsl-controller-home.ts +306 -0
- package/scripts/open-source-audit-allowlist.txt +11 -1
- package/scripts/portability-bindings.mjs +70 -0
- package/scripts/run-bounded-command.mjs +60 -0
- package/scripts/run-bun-test-file.ts +22 -6
- package/scripts/run-governed-gate.ts +4 -2
- 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 +6 -1
- package/scripts/smoke-runtime-recovery.ts +13 -11
- package/scripts/smoke-schedule-engine.ts +24 -16
- 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/test-governance.ts +51 -2
- 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 +17 -4
- package/src/cli/chatgpt-browser/bind-server.ts +2 -1
- package/src/cli/chatgpt-browser/binding.ts +20 -10
- package/src/cli/chatgpt-browser/bridge-extension.ts +75 -0
- package/src/cli/chatgpt-browser/bridge-provider.ts +376 -11
- package/src/cli/chatgpt-browser/engine.ts +10 -11
- package/src/cli/chatgpt-browser/native-provider.ts +24 -83
- package/src/cli/chatgpt-browser/oracle-provider.ts +5 -3
- package/src/cli/chatgpt-browser/types.ts +1 -0
- package/src/cli/commands/bootstrap-control.ts +334 -0
- package/src/cli/commands/brain-assistant.ts +52 -0
- package/src/cli/commands/brain.ts +191 -40
- package/src/cli/commands/chatgpt.ts +32 -67
- package/src/cli/commands/computer.ts +437 -0
- package/src/cli/commands/doctor.ts +18 -1
- package/src/cli/commands/init-hook.ts +71 -61
- package/src/cli/commands/init.ts +3 -1
- package/src/cli/commands/mcp.ts +16 -10
- package/src/cli/commands/plugin.ts +38 -12
- package/src/cli/commands/recovery.ts +507 -80
- package/src/cli/commands/runtime.ts +12 -7
- package/src/cli/commands/setup-profile.ts +97 -39
- package/src/cli/commands/status.ts +2 -1
- package/src/cli/controller/check-runner.ts +500 -100
- 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/types.ts +7 -1
- package/src/cli/controller/context-pack.ts +28 -6
- 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 +148 -0
- package/src/cli/controller/types.ts +10 -70
- package/src/cli/controller/worklog.ts +67 -13
- package/src/cli/editing/edit-operation-contract.ts +92 -0
- package/src/cli/editing/edit-session.ts +290 -20
- package/src/cli/github/plugin.ts +17 -12
- package/src/cli/hook/route-registry.ts +3 -5
- package/src/cli/hook/runtime.ts +49 -3
- package/src/cli/index.ts +3 -0
- package/src/cli/local-bridge/connector-freshness.ts +2 -2
- package/src/cli/local-bridge/console-automations.ts +20 -15
- package/src/cli/local-bridge/console-view-models.ts +3 -12
- package/src/cli/local-bridge/facade-api.ts +105 -205
- package/src/cli/local-bridge/job-store.ts +1 -1
- package/src/cli/local-bridge/server.ts +48 -174
- package/src/cli/local-bridge/types.ts +0 -1
- package/src/cli/mcp/access-mode.ts +2 -132
- package/src/cli/mcp/access-tools.ts +2 -387
- package/src/cli/mcp/audit.ts +2 -32
- package/src/cli/mcp/auth.ts +2 -404
- package/src/cli/mcp/instructions.ts +2 -34
- package/src/cli/mcp/legacy-context.ts +2 -16
- package/src/cli/mcp/legacy-tool-service.ts +2 -5308
- package/src/cli/mcp/multi-repository.ts +2 -436
- package/src/cli/mcp/oauth-client-retirement.ts +74 -0
- package/src/cli/mcp/oauth.ts +2 -375
- package/src/cli/mcp/openai-secure-tunnel.ts +2 -0
- package/src/cli/mcp/paths.ts +2 -140
- package/src/cli/mcp/policy.ts +2 -232
- package/src/cli/mcp/post-finalize-work-attribution.ts +2 -150
- package/src/cli/mcp/proxy-env.ts +2 -62
- package/src/cli/mcp/readiness-projection.ts +2 -24
- package/src/cli/mcp/redaction.ts +2 -21
- package/src/cli/mcp/repo.ts +2 -24
- package/src/cli/mcp/repository-tools.ts +2 -1613
- package/src/cli/mcp/server.ts +2 -951
- package/src/cli/mcp/setup.ts +2 -737
- package/src/cli/mcp/tool-capability-cache.ts +2 -87
- package/src/cli/mcp/tool-contract.ts +2 -14
- package/src/cli/mcp/tools.ts +2 -9
- package/src/cli/mcp/toolset-names.ts +2 -70
- package/src/cli/mcp/toolset-selection.ts +2 -41
- package/src/cli/mcp/toolset.ts +2 -336
- package/src/cli/mcp/transports/AGENTS.md +1 -10
- package/src/cli/mcp/transports/CLAUDE.md +1 -10
- package/src/cli/mcp/transports/http.ts +2 -1414
- package/src/cli/mcp/transports/session-registry.ts +2 -490
- package/src/cli/mcp/transports/stdio.ts +2 -8
- package/src/cli/mcp/types.ts +2 -41
- package/src/cli/mcp/umbrella-tools.ts +2 -117
- package/src/cli/repositories/command-executor.ts +91 -39
- package/src/cli/repositories/command-scope.ts +139 -4
- package/src/cli/repositories/controller-home.ts +167 -1
- package/src/cli/repositories/ephemeral-workspace.ts +20 -30
- package/src/cli/repositories/git-command-executor.ts +2 -2
- package/src/cli/repositories/identity.ts +13 -0
- package/src/cli/repositories/registry.ts +145 -60
- package/src/cli/repositories/repository-snapshot.ts +53 -7
- package/src/cli/repositories/runtime-storage.ts +27 -2
- package/src/cli/repositories/safe-patch.ts +34 -38
- package/src/cli/repositories/selected-path-actions.ts +22 -2
- package/src/cli/repositories/structured-git.ts +167 -27
- package/src/cli/repository/session-cache.ts +92 -6
- package/src/cli/runtime/helper-runner.ts +7 -0
- package/src/cli/runtime-invocation.ts +8 -1
- package/src/cli/tools/codegraph.ts +44 -25
- package/src/core/adoption/manifest-templates.ts +1 -1
- package/src/core/adoption/plan.ts +3 -26
- package/src/core/adoption/workflow-contract-plan.ts +17 -9
- package/src/effects/process-runner.ts +8 -14
- package/src/runtime/context/assistant-context.ts +167 -0
- package/src/runtime/context/assistant-work-context.ts +209 -0
- package/src/runtime/context/automatic-learning.ts +565 -0
- package/src/runtime/context/codegraph-cache-boundary.ts +255 -0
- package/src/runtime/context/codegraph-read-provider.ts +55 -22
- package/src/runtime/context/codegraph-sidecar.cjs +8 -1
- 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 +305 -0
- package/src/runtime/context/context-pack-process.ts +103 -0
- package/src/runtime/context/context-plane.ts +203 -0
- package/src/runtime/context/direct-controller-learning.ts +298 -0
- package/src/runtime/context/project-engineering-contract.ts +60 -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/bootstrap/capability-provider.ts +74 -0
- package/src/runtime/control-plane/bootstrap/control-api.ts +57 -0
- package/src/runtime/control-plane/bootstrap/index.ts +5 -0
- package/src/runtime/control-plane/bootstrap/state-machine.ts +141 -0
- package/src/runtime/control-plane/bootstrap/store.ts +21 -0
- package/src/runtime/control-plane/bootstrap/types.ts +87 -0
- package/src/runtime/control-plane/cleanup-artifact-retention.ts +531 -0
- package/src/runtime/control-plane/codegraph-cache-retention.ts +164 -0
- package/src/runtime/control-plane/concurrency/work-execution-concurrency.ts +282 -0
- package/src/runtime/control-plane/execution/controller-authority-recovery.ts +380 -0
- package/src/runtime/control-plane/execution/edit-validation-coordinator.ts +113 -16
- package/src/runtime/control-plane/execution/execution-identity.ts +23 -3
- package/src/runtime/control-plane/execution/implementation-review-content.ts +95 -0
- package/src/runtime/control-plane/execution/repository-work-attribution.ts +7 -30
- package/src/runtime/control-plane/execution/retained-work-resume.ts +439 -102
- package/src/runtime/control-plane/execution/session-store.ts +31 -1
- package/src/runtime/control-plane/execution/validation.ts +34 -11
- package/src/runtime/control-plane/execution/work-authority-reconciler.ts +87 -0
- package/src/runtime/control-plane/execution/work-check-evidence.ts +137 -0
- package/src/runtime/control-plane/execution/work-completion-authority.ts +31 -44
- package/src/runtime/control-plane/execution/work-delivery-service.ts +497 -0
- package/src/runtime/control-plane/execution/work-evidence-policy.ts +46 -53
- package/src/runtime/control-plane/execution/work-execution-support.ts +85 -164
- package/src/runtime/control-plane/execution/work-handle-authority.ts +349 -73
- package/src/runtime/control-plane/execution/work-handle-store.ts +55 -2
- package/src/runtime/control-plane/execution/work-head-settlement.ts +108 -0
- package/src/runtime/control-plane/execution/work-lifecycle-audit.ts +173 -28
- package/src/runtime/control-plane/execution/work-operation-service.ts +92 -40
- package/src/runtime/control-plane/execution/work-preparation-service.ts +145 -269
- 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 +543 -225
- package/src/runtime/control-plane/execution/work-validation-reconciler.ts +59 -45
- package/src/runtime/control-plane/execution/work-verification-context.ts +1 -1
- package/src/runtime/control-plane/execution/work-verification-service.ts +662 -52
- package/src/runtime/control-plane/execution/work-verification-snapshot.ts +205 -16
- package/src/runtime/control-plane/facade/capability-registry.ts +380 -44
- 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/controller-session-store.ts +2 -488
- package/src/runtime/control-plane/facade/goal-workloop-access.ts +6 -22
- package/src/runtime/control-plane/facade/goal-workloop.ts +565 -1202
- package/src/runtime/control-plane/facade/handoff-inbox-application.ts +145 -0
- package/src/runtime/control-plane/facade/handoff-inbox-store.ts +266 -52
- package/src/runtime/control-plane/facade/index.ts +4 -3
- package/src/runtime/control-plane/facade/operation-digest.ts +34 -73
- package/src/runtime/control-plane/facade/plan-contract-store.ts +671 -245
- package/src/runtime/control-plane/facade/policy-gate.ts +0 -23
- package/src/runtime/control-plane/facade/repository-work-admission.ts +31 -23
- package/src/runtime/control-plane/facade/requirement-authority.ts +121 -0
- package/src/runtime/control-plane/facade/requirement-board.ts +9 -4
- package/src/runtime/control-plane/facade/rh-work-operation-contract.ts +85 -0
- package/src/runtime/control-plane/facade/self-healing-loop.ts +18 -53
- package/src/runtime/control-plane/facade/semantic-admission.ts +8 -16
- package/src/runtime/control-plane/facade/suggested-actions.ts +15 -15
- package/src/runtime/control-plane/facade/types.ts +218 -620
- package/src/runtime/control-plane/facade/work-continuation.ts +8 -8
- package/src/runtime/control-plane/facade/work-contract-store.ts +2 -1043
- package/src/runtime/control-plane/generated-cache-retention.ts +336 -19
- package/src/runtime/control-plane/global-scheduler/autonomous-continuation.ts +248 -0
- package/src/runtime/control-plane/global-scheduler/durable-admission.ts +13 -2
- package/src/runtime/control-plane/global-scheduler/maintenance.ts +274 -84
- package/src/runtime/control-plane/global-scheduler/periodic-cleanup-entry.ts +55 -0
- package/src/runtime/control-plane/global-scheduler/periodic-cleanup-process.ts +98 -0
- package/src/runtime/control-plane/global-scheduler/reconciliation.ts +3 -2
- package/src/runtime/control-plane/global-scheduler/scheduler-worker-entry.ts +10 -0
- package/src/runtime/control-plane/global-scheduler/scheduler.ts +227 -109
- package/src/runtime/control-plane/global-scheduler/wake-signal.ts +42 -2
- package/src/runtime/control-plane/global-scheduler/worker-launch.ts +18 -6
- 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 +160 -0
- package/src/runtime/control-plane/launcher/chatgpt-work-binding-store.ts +2 -177
- package/src/runtime/control-plane/launcher/chatgpt-work-continuation.ts +139 -670
- package/src/runtime/control-plane/launcher/local-conversation-controller.ts +238 -0
- package/src/runtime/control-plane/launcher/provider-mcp-bootstrap.ts +25 -6
- package/src/runtime/control-plane/launcher/thin-launcher.ts +96 -194
- package/src/runtime/control-plane/lifecycle-retention-metrics.ts +60 -0
- package/src/runtime/control-plane/persistence/cognition-store.ts +820 -0
- package/src/runtime/control-plane/persistence/experience-store.ts +302 -0
- package/src/runtime/control-plane/persistence/operational-prior-store.ts +348 -0
- package/src/runtime/control-plane/persistence/requirement-store.ts +230 -80
- package/src/runtime/control-plane/persistence/sqlite-store.ts +654 -78
- package/src/runtime/control-plane/persistence/workflow-content-store.ts +98 -0
- package/src/runtime/control-plane/persistence/workflow-registry-store.ts +186 -0
- package/src/runtime/control-plane/persistence/workflow-run-store.ts +123 -0
- package/src/runtime/control-plane/release-retention.ts +154 -26
- package/src/runtime/control-plane/repository-namespace-retention.ts +208 -0
- package/src/runtime/control-plane/runtime-cleanup.ts +844 -38
- package/src/runtime/control-plane/runtime-generation.ts +6 -0
- package/src/runtime/control-plane/workspace/project-onboarding.ts +80 -0
- package/src/runtime/control-plane/workspace/semantic-sync-service.ts +479 -0
- package/src/runtime/control-plane/workspace/workspace-store.ts +249 -0
- package/src/runtime/diagnostics/incident-repair.ts +573 -0
- package/src/runtime/diagnostics/mcp-timing.ts +239 -6
- package/src/runtime/diagnostics/performance.ts +6 -14
- package/src/runtime/diagnostics/read-only-tool.ts +1 -1
- package/src/runtime/evidence/artifact-store.ts +216 -35
- package/src/runtime/evidence/evidence-store.ts +112 -8
- package/src/runtime/evidence/operational-shadow.ts +38 -0
- package/src/runtime/evidence/output-handle-index.ts +225 -0
- package/src/runtime/evidence/process-check-receipt.ts +5 -43
- package/src/runtime/evidence/result-store.ts +158 -44
- package/src/runtime/evidence/sensitive-output.ts +4 -4
- package/src/runtime/execution/jobs/receipt-recovery.ts +1 -1
- package/src/runtime/execution/jobs/store.ts +124 -6
- package/src/runtime/execution/managed-workspace.ts +112 -5
- package/src/runtime/execution/process-runtime/canary.ts +19 -5
- package/src/runtime/execution/process-runtime/check-classification.ts +48 -0
- package/src/runtime/execution/process-runtime/check-facade.ts +24 -10
- package/src/runtime/execution/process-runtime/check-receipt.ts +1 -1
- package/src/runtime/execution/process-runtime/check-result-retention.ts +132 -0
- package/src/runtime/execution/process-runtime/check-result.ts +177 -2
- package/src/runtime/execution/process-runtime/check-runner-sidecar.ts +58 -9
- package/src/runtime/execution/process-runtime/check-storage.ts +187 -0
- package/src/runtime/execution/process-runtime/command-facade.ts +117 -114
- 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 +4 -0
- package/src/runtime/execution/process-runtime/interactive-admission.ts +2 -1
- package/src/runtime/execution/process-runtime/lightweight-managed.ts +283 -73
- package/src/runtime/execution/process-runtime/persisted-check.ts +130 -23
- 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 +125 -64
- package/src/runtime/execution/process-runtime/runtime.ts +167 -17
- package/src/runtime/execution/process-runtime/store.ts +30 -2
- package/src/runtime/execution/process-runtime/types.ts +27 -0
- package/src/runtime/execution/workers/executor.ts +18 -19
- package/src/runtime/execution/workers/worker-entry.ts +1 -1
- package/src/runtime/gateway/mcp/execution-tools.ts +2 -207
- package/src/runtime/gateway/mcp/legacy-ios-tool-adapter.ts +2 -61
- package/src/runtime/gateway/mcp/persisted-check-process.ts +2 -3
- package/src/runtime/gateway/mcp/process-tools.ts +2 -289
- package/src/runtime/gateway/mcp/router.ts +2 -1125
- package/src/runtime/gateway/mcp/runtime-tool-definitions.ts +2 -565
- package/src/runtime/gateway/mcp/runtime-tools.ts +2 -6655
- package/src/runtime/gateway/mcp/work-validation-reconciler.ts +2 -1
- package/src/runtime/maintenance/cleanup.ts +38 -24
- package/src/runtime/platform/browser-product-discovery.ts +174 -0
- package/src/runtime/platform/computer-platform.ts +14 -0
- package/src/runtime/platform/executable-discovery.ts +54 -0
- package/src/runtime/platform/fetch-http-server.ts +90 -0
- package/src/runtime/platform/service-inventory.ts +130 -0
- package/src/runtime/platform/service-manager.ts +146 -0
- package/src/runtime/platform/windows-host-discovery.ts +118 -0
- package/src/runtime/platform/windows-recovery-deployment.ts +67 -0
- package/src/runtime/plugins/action-application.ts +192 -0
- package/src/runtime/plugins/app-store-connect-adapter.ts +47 -35
- package/src/runtime/plugins/browser-adapter.ts +898 -135
- package/src/runtime/plugins/browser-automation-service.ts +33 -34
- package/src/runtime/plugins/browser-macos-bridge.ts +386 -46
- package/src/runtime/plugins/browser-manifest-surface.ts +75 -17
- package/src/runtime/plugins/browser-native-session-service.ts +64 -14
- package/src/runtime/plugins/browser-provider-registry.ts +2 -109
- package/src/runtime/plugins/browser-registration.ts +32 -0
- package/src/runtime/plugins/browser-runtime-contract.ts +2 -154
- package/src/runtime/plugins/browser-runtime.ts +55 -10
- package/src/runtime/plugins/browser-session-authority.ts +101 -291
- package/src/runtime/plugins/browser-session-legacy-migration.ts +203 -0
- package/src/runtime/plugins/browser-session-store.ts +243 -80
- package/src/runtime/plugins/browser-session-types.ts +2 -98
- package/src/runtime/plugins/capability-authorization-grants.ts +272 -59
- package/src/runtime/plugins/catalog-trust.ts +82 -0
- 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 +1050 -0
- package/src/runtime/plugins/config-store.ts +119 -0
- package/src/runtime/plugins/desktop-operator-external-policy.ts +964 -0
- package/src/runtime/plugins/desktop-operator-registration.ts +123 -12
- package/src/runtime/plugins/errors.ts +8 -1
- package/src/runtime/plugins/external-adapter.ts +82 -323
- package/src/runtime/plugins/external-provider-policy.ts +48 -0
- package/src/runtime/plugins/external-registration.ts +30 -2
- package/src/runtime/plugins/external-unix-socket-probe.cjs +9 -3
- package/src/runtime/plugins/external-unix-socket.ts +64 -193
- package/src/runtime/plugins/first-party-external-registration.ts +163 -0
- package/src/runtime/plugins/first-party-registry.ts +3 -1
- package/src/runtime/plugins/github-adapter.ts +1 -2
- package/src/runtime/plugins/gmail-adapter.ts +29 -8
- package/src/runtime/plugins/google-calendar-adapter.ts +8 -8
- package/src/runtime/plugins/google-shared.ts +45 -53
- package/src/runtime/plugins/google-tasks-adapter.ts +8 -8
- package/src/runtime/plugins/ios-adapter.ts +2 -3
- package/src/runtime/plugins/lightweight-action.ts +208 -2
- package/src/runtime/plugins/local-system-adapter.ts +192 -2
- package/src/runtime/plugins/macos-capability-broker.ts +15 -105
- 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/resend-adapter.ts +15 -24
- package/src/runtime/plugins/store.ts +1003 -387
- package/src/runtime/plugins/types.ts +28 -1
- package/src/runtime/plugins/uu-remote-rescue-registration.ts +155 -0
- package/src/runtime/plugins/windows-host-recovery-install.ts +68 -0
- package/src/runtime/plugins/windows-host-recovery-registration.ts +85 -0
- package/src/runtime/plugins/xiaohongshu-publish.ts +102 -430
- package/src/runtime/projections/controller-context.ts +12 -6
- package/src/runtime/projections/git-status-sampler.ts +73 -22
- package/src/runtime/projections/invalidation.ts +7 -3
- package/src/runtime/projections/materialized-view.ts +93 -43
- package/src/runtime/recovery/actions.ts +3 -3
- package/src/runtime/recovery/capability-action-application.ts +229 -0
- package/src/runtime/recovery/index.ts +3 -0
- package/src/runtime/recovery/lifecycle-inventory.ts +338 -0
- package/src/runtime/recovery/local-jobs-repair.ts +14 -14
- package/src/runtime/recovery/maintenance-executor.ts +701 -168
- package/src/runtime/recovery/quarantine-retention.ts +256 -0
- package/src/runtime/recovery/store.ts +29 -11
- package/src/runtime/release/identity.ts +6 -0
- 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/active-execution-power-assertion.ts +139 -0
- package/src/runtime/root/assistant-learning-loop.ts +45 -0
- package/src/runtime/root/browser-session-composition.ts +59 -0
- package/src/runtime/root/computer-composition.ts +376 -0
- package/src/runtime/root/computer-target-composition.ts +16 -0
- package/src/runtime/root/computer-target-persistence.ts +39 -0
- package/src/runtime/root/controller-progression-composition.ts +192 -0
- package/src/runtime/root/controller-round-composition.ts +126 -0
- package/src/runtime/root/controller-services.ts +2 -0
- package/src/runtime/root/deployment-topology.ts +106 -0
- package/src/runtime/root/entry.ts +8 -6
- package/src/runtime/root/gateway-adapter.ts +3 -3
- package/src/runtime/root/known-good-recovery.ts +184 -0
- package/src/runtime/root/local-bridge.ts +5 -3
- package/src/runtime/root/mcp-transport.ts +116 -23
- package/src/runtime/root/ownership.ts +261 -9
- package/src/runtime/root/package-connector-service.ts +212 -74
- package/src/runtime/root/package-runtime-release.ts +199 -33
- package/src/runtime/root/package-runtime-service.ts +77 -108
- package/src/runtime/root/release-execution-canary.ts +103 -0
- package/src/runtime/root/release-loader.ts +150 -0
- package/src/runtime/root/release-manifest.ts +185 -7
- package/src/runtime/root/release-materialize.ts +474 -31
- package/src/runtime/root/release-store.ts +425 -37
- package/src/runtime/root/runtime-lane.ts +191 -0
- package/src/runtime/root/runtime.ts +379 -32
- package/src/runtime/root/scheduled-controller-composition.ts +76 -0
- package/src/runtime/root/scheduler.ts +12 -4
- package/src/runtime/root/service-runner.ts +3 -3
- package/src/runtime/root/service.ts +73 -45
- package/src/runtime/root/status.ts +49 -0
- package/src/runtime/root/types.ts +55 -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/local-bridge-surface.ts +1 -1
- package/src/runtime/shared/process-environment.ts +36 -10
- package/src/runtime/shared/response-budget.ts +1 -3
- package/src/runtime/shared/storage-capacity.ts +68 -0
- package/src/runtime/standalone-recovery/controller-home-migration.ts +1108 -0
- package/src/runtime/standalone-recovery/core.ts +4609 -495
- package/src/runtime/standalone-recovery/entry.ts +642 -81
- package/src/runtime/standalone-recovery/independent-host-rescue.ts +172 -0
- package/src/runtime/standalone-recovery/installer.ts +399 -177
- package/src/runtime/standalone-recovery/mcp-server.ts +79 -0
- package/src/runtime/standalone-recovery/mutation-identity-contract.ts +21 -0
- package/src/runtime/standalone-recovery/operation-lock.ts +160 -0
- package/src/runtime/standalone-recovery/performance.ts +173 -0
- package/src/runtime/standalone-recovery/release.ts +58 -5
- package/src/runtime/standalone-recovery/service-labels.ts +5 -2
- package/src/runtime/standalone-recovery/watchdog-heartbeat.ts +5 -2
- package/src/runtime/watchdog/workflow-watchdog.ts +1 -1
- package/src/runtime/workflow/schedules/browser-probe.ts +17 -6
- package/src/runtime/workflow/schedules/chatgpt-automation-migration.ts +11 -4
- package/src/runtime/workflow/schedules/engine.ts +298 -484
- package/src/runtime/workflow/schedules/pending-activation.ts +1 -1
- package/src/runtime/workflow/schedules/settlement.ts +2 -191
- package/src/runtime/workflow/schedules/store.ts +2 -607
- package/src/runtime/workflow/schedules/types.ts +2 -127
- package/src/runtime/workflow/schedules/work-continuation.ts +220 -16
- package/src/runtime/workflows/first-party/xiaohongshu.ts +122 -0
- package/src/runtime/workflows/runtime.ts +482 -0
- package/src/testing/test-governance.ts +95 -30
- 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/assets/templates/helpers/archive-architecture-request.sh +0 -244
- package/docs/architecture/history/README.md +0 -7
- package/docs/architecture/history/chatgpt-handoff-facade.md +0 -397
- package/docs/architecture/history/global-hook-runtime.md +0 -166
- package/docs/architecture/history/ios-semantic-automation-provider-v2.md +0 -170
- package/docs/architecture/requests/archive/2026/20260528-154740-ai-hooks-ai-hooks-hook-input-sh.md +0 -59
- package/docs/architecture/requests/archive/2026/20260528-154816-assets-hooks-assets-hooks-hook-input-sh.md +0 -59
- package/docs/architecture/requests/archive/2026/20260528-161851-ai-harness-workflow-contract-json-ai-harness-workflow-contract-json.md +0 -59
- package/docs/architecture/requests/archive/2026/20260528-161853-scripts-check-task-workflow-sh-scripts-check-task-workflow-sh.md +0 -59
- package/docs/architecture/requests/archive/2026/20260528-161911-assets-workflow-contract-v1-json-assets-workflow-contract-v1-json.md +0 -59
- package/docs/architecture/requests/archive/2026/20260528-222416-ai-hooks-ai-hooks-hook-input-sh.md +0 -59
- package/docs/architecture/requests/archive/2026/20260528-222444-ai-hooks-ai-hooks-pre-edit-guard-sh.md +0 -59
- package/docs/architecture/requests/archive/2026/20260528-222457-ai-hooks-ai-hooks-pre-edit-guard-sh.md +0 -59
- package/docs/architecture/requests/archive/2026/20260528-222648-ai-hooks-ai-hooks-pre-edit-guard-sh.md +0 -59
- package/docs/architecture/requests/archive/2026/20260528-222705-ai-hooks-ai-hooks-worktree-guard-sh.md +0 -59
- package/docs/architecture/requests/archive/2026/20260528-222726-ai-hooks-ai-hooks-prompt-guard-sh.md +0 -59
- package/docs/architecture/requests/archive/2026/20260528-222727-ai-hooks-ai-hooks-prompt-guard-sh.md +0 -59
- package/docs/architecture/requests/archive/2026/20260528-224736-ai-hooks-ai-hooks-hook-input-sh.md +0 -59
- package/docs/architecture/requests/archive/2026/20260528-233259-ai-hooks-ai-hooks-prompt-guard-sh.md +0 -59
- package/docs/architecture/requests/archive/2026/20260528-233335-assets-hooks-assets-hooks-prompt-guard-sh.md +0 -59
- package/docs/architecture/requests/archive/2026/20260528-233456-ai-hooks-ai-hooks-prompt-guard-sh.md +0 -59
- package/docs/architecture/requests/archive/2026/20260528-233457-assets-hooks-assets-hooks-prompt-guard-sh.md +0 -59
- package/docs/architecture/requests/archive/2026/20260528-233637-ai-hooks-ai-hooks-prompt-guard-sh.md +0 -59
- package/docs/architecture/requests/archive/2026/20260528-233638-assets-hooks-assets-hooks-prompt-guard-sh.md +0 -59
- package/docs/architecture/requests/archive/2026/20260529-000322-root-package-json.md +0 -59
- package/docs/architecture/requests/archive/2026/20260529-004238-ai-hooks-ai-hooks-lib-workflow-state-sh.md +0 -59
- package/docs/architecture/requests/archive/2026/20260529-020654-ai-harness-policy-json-ai-harness-policy-json.md +0 -63
- package/docs/architecture/requests/archive/2026/20260529-094236-ai-hooks-ai-hooks-prompt-guard-sh.md +0 -60
- package/docs/architecture/requests/archive/2026/20260529-094323-assets-hooks-assets-hooks-prompt-guard-sh.md +0 -60
- package/docs/architecture/requests/archive/2026/20260529-094331-ai-hooks-ai-hooks-prompt-guard-sh.md +0 -60
- package/docs/architecture/requests/archive/2026/20260529-094339-assets-hooks-assets-hooks-prompt-guard-sh.md +0 -60
- package/docs/architecture/requests/archive/2026/20260529-094430-assets-hooks-assets-hooks-session-start-context-sh.md +0 -60
- package/docs/architecture/requests/archive/2026/20260529-094446-ai-hooks-ai-hooks-session-start-context-sh.md +0 -60
- package/docs/architecture/requests/archive/2026/20260613-002040-runtime-harness-hook-adapters.md +0 -68
- package/docs/architecture/requests/archive/2026/root.md +0 -68
- package/docs/architecture/requests/archive/2026/runtime-harness-hook-adapters.md +0 -76
- package/docs/architecture/requests/archive/2026/verification-evals-checks.md +0 -68
- package/docs/architecture/requests/archive/2026/workflow-engine-contract-assets.md +0 -69
- package/scripts/archive-architecture-request.sh +0 -4
- package/scripts/benchmark-background-check-overlap.ts +0 -228
- package/scripts/benchmark-controller-hotpath.ts +0 -212
- package/scripts/benchmark-controller-round2.ts +0 -139
- package/scripts/benchmark-ios-agent-device.ts +0 -514
- package/scripts/benchmark-mcp-host.sh +0 -117
- package/scripts/benchmark-mcp-transport.ts +0 -170
- 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 -67
- 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-evals.ts +0 -1022
- package/scripts/stage-runtime-release.ts +0 -39
- 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/direct-edit-work-completion.ts +0 -385
- package/src/runtime/control-plane/execution/work-finalization-service.ts +0 -1913
- package/src/runtime/control-plane/execution/work-path-scope.ts +0 -37
- package/src/runtime/control-plane/execution/work-task-receipt.ts +0 -449
- package/src/runtime/control-plane/facade/controller-round-relay.ts +0 -1118
- package/src/runtime/control-plane/facade/work-admission-policy.ts +0 -93
- 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 -382
- package/src/runtime/control-plane/routing/workspace-admission.ts +0 -70
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import type { IncomingMessage, ServerResponse } from 'http';
|
|
2
|
+
import { createMcpHandler, Server, type Tool } from '@modelcontextprotocol/server';
|
|
3
|
+
import { toNodeHandler } from '@modelcontextprotocol/node';
|
|
4
|
+
import { FORGE_VERSION } from '../../version';
|
|
5
|
+
|
|
6
|
+
export interface RecoveryMcpRequestContext {
|
|
7
|
+
remoteAddress: string;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export interface RecoveryMcpServerOptions {
|
|
11
|
+
tools: readonly Tool[];
|
|
12
|
+
dispatchTool(name: string, args: Record<string, unknown>, context: RecoveryMcpRequestContext): Promise<unknown>;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Standalone Recovery owns durable recovery/release authority, never MCP
|
|
17
|
+
* transport-session authority. Both MCP 2026-07-28 and the bounded 2025-era
|
|
18
|
+
* compatibility protocol are served statelessly so a Gateway process
|
|
19
|
+
* replacement cannot invalidate the Recovery control path.
|
|
20
|
+
*/
|
|
21
|
+
export class RecoveryMcpServer {
|
|
22
|
+
constructor(private readonly options: RecoveryMcpServerOptions) {}
|
|
23
|
+
|
|
24
|
+
async close(): Promise<void> {
|
|
25
|
+
// Stateless handlers retain no cross-request transport resources.
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
async handle(request: IncomingMessage, response: ServerResponse, body?: unknown): Promise<void> {
|
|
29
|
+
if (request.method !== 'POST') {
|
|
30
|
+
response.statusCode = 405;
|
|
31
|
+
response.setHeader('allow', 'POST');
|
|
32
|
+
response.end();
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const context: RecoveryMcpRequestContext = {
|
|
37
|
+
remoteAddress: request.socket.remoteAddress ?? 'unknown',
|
|
38
|
+
};
|
|
39
|
+
const handler = createMcpHandler(async () => this.createServer(context), {
|
|
40
|
+
legacy: 'stateless',
|
|
41
|
+
responseMode: 'auto',
|
|
42
|
+
});
|
|
43
|
+
try {
|
|
44
|
+
await toNodeHandler(handler)(request, response, body);
|
|
45
|
+
} finally {
|
|
46
|
+
await handler.close();
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
private createServer(context: RecoveryMcpRequestContext): Server {
|
|
51
|
+
const server = new Server(
|
|
52
|
+
{ name: 'forge-standalone-recovery', version: FORGE_VERSION },
|
|
53
|
+
{ capabilities: { tools: {} } },
|
|
54
|
+
);
|
|
55
|
+
server.setRequestHandler('tools/list', async () => ({ tools: [...this.options.tools] }));
|
|
56
|
+
server.setRequestHandler('tools/call', async (request) => {
|
|
57
|
+
const name = request.params.name;
|
|
58
|
+
const args = request.params.arguments && typeof request.params.arguments === 'object' && !Array.isArray(request.params.arguments)
|
|
59
|
+
? request.params.arguments as Record<string, unknown>
|
|
60
|
+
: {};
|
|
61
|
+
try {
|
|
62
|
+
const payload = await this.options.dispatchTool(name, args, context);
|
|
63
|
+
const structuredContent = payload && typeof payload === 'object' && !Array.isArray(payload)
|
|
64
|
+
? payload as Record<string, unknown>
|
|
65
|
+
: { value: payload };
|
|
66
|
+
return {
|
|
67
|
+
content: [{ type: 'text' as const, text: JSON.stringify(payload) }],
|
|
68
|
+
structuredContent,
|
|
69
|
+
};
|
|
70
|
+
} catch (error) {
|
|
71
|
+
return {
|
|
72
|
+
isError: true,
|
|
73
|
+
content: [{ type: 'text' as const, text: error instanceof Error ? error.message : 'Recovery request rejected' }],
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
});
|
|
77
|
+
return server;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/** Canonical external mutation identity contract for Standalone Recovery.
|
|
2
|
+
*
|
|
3
|
+
* Both the runtime fencing implementation and the MCP tool schema derive from
|
|
4
|
+
* this single authority. Keep target-identity field names and validation shape
|
|
5
|
+
* here so an upgraded Recovery cannot require fields that its own connector
|
|
6
|
+
* schema forgot to expose.
|
|
7
|
+
*/
|
|
8
|
+
export const RECOVERY_MUTATION_IDENTITY_CONTRACT = {
|
|
9
|
+
expected_host: { type: 'string', minLength: 1, maxLength: 255 },
|
|
10
|
+
expected_platform: { type: 'string', minLength: 1, maxLength: 64 },
|
|
11
|
+
expected_controller_home: { type: 'string', minLength: 1, maxLength: 2048 },
|
|
12
|
+
expected_recovery_release: { type: 'string', minLength: 1, maxLength: 256 },
|
|
13
|
+
expected_target_runtime: { type: 'string', minLength: 1, maxLength: 1024 },
|
|
14
|
+
} as const;
|
|
15
|
+
|
|
16
|
+
export const RECOVERY_MUTATION_IDENTITY_FIELDS = Object.freeze(
|
|
17
|
+
Object.keys(RECOVERY_MUTATION_IDENTITY_CONTRACT),
|
|
18
|
+
) as readonly (keyof typeof RECOVERY_MUTATION_IDENTITY_CONTRACT)[];
|
|
19
|
+
|
|
20
|
+
export type RecoveryMutationIdentityField = (typeof RECOVERY_MUTATION_IDENTITY_FIELDS)[number];
|
|
21
|
+
export type RecoveryMutationIdentityArguments = Record<RecoveryMutationIdentityField, string>;
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
import { randomUUID } from 'crypto';
|
|
2
|
+
import { spawnSync } from 'child_process';
|
|
3
|
+
import { closeSync, mkdirSync, openSync, readFileSync, realpathSync, rmSync, writeFileSync } from 'fs';
|
|
4
|
+
import { dirname, join, resolve } from 'path';
|
|
5
|
+
import { isProcessAlive } from '../shared/process-tree';
|
|
6
|
+
|
|
7
|
+
export interface RecoveryOperationLockRecord {
|
|
8
|
+
schemaVersion?: 1;
|
|
9
|
+
pid: number;
|
|
10
|
+
instanceId: string;
|
|
11
|
+
processStartTime?: string;
|
|
12
|
+
acquiredAt: string;
|
|
13
|
+
action?: string;
|
|
14
|
+
requestId?: string;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export interface RecoveryOperationLockHandle {
|
|
18
|
+
path: string;
|
|
19
|
+
record: RecoveryOperationLockRecord;
|
|
20
|
+
close: () => void;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export type RecoveryOperationLockAttempt =
|
|
24
|
+
| { acquired: true; handle: RecoveryOperationLockHandle }
|
|
25
|
+
| { acquired: false; owner: RecoveryOperationLockRecord };
|
|
26
|
+
|
|
27
|
+
function processStartTime(pid: number): string | undefined {
|
|
28
|
+
const result = spawnSync('/bin/ps', ['-o', 'lstart=', '-p', String(pid)], {
|
|
29
|
+
encoding: 'utf8',
|
|
30
|
+
timeout: 2_000,
|
|
31
|
+
maxBuffer: 4_096,
|
|
32
|
+
});
|
|
33
|
+
if (result.status !== 0 || typeof result.stdout !== 'string') return undefined;
|
|
34
|
+
return result.stdout.trim() || undefined;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function readRecoveryOperationLockPath(path: string): RecoveryOperationLockRecord | undefined {
|
|
38
|
+
let raw: string;
|
|
39
|
+
try {
|
|
40
|
+
raw = readFileSync(path, 'utf8');
|
|
41
|
+
} catch (error) {
|
|
42
|
+
if ((error as NodeJS.ErrnoException).code === 'ENOENT') return undefined;
|
|
43
|
+
throw error;
|
|
44
|
+
}
|
|
45
|
+
try {
|
|
46
|
+
const parsed = JSON.parse(raw) as RecoveryOperationLockRecord;
|
|
47
|
+
if (!Number.isInteger(parsed.pid) || parsed.pid <= 0) return undefined;
|
|
48
|
+
if (typeof parsed.instanceId !== 'string' || !parsed.instanceId.trim()) return undefined;
|
|
49
|
+
if (typeof parsed.acquiredAt !== 'string' || !parsed.acquiredAt.trim()) return undefined;
|
|
50
|
+
return parsed;
|
|
51
|
+
} catch {
|
|
52
|
+
return undefined;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export function recoveryOperationLockPath(controllerHome: string): string {
|
|
57
|
+
const resolved = resolve(controllerHome);
|
|
58
|
+
let canonical = resolved;
|
|
59
|
+
try {
|
|
60
|
+
canonical = realpathSync(resolved);
|
|
61
|
+
} catch (error) {
|
|
62
|
+
if ((error as NodeJS.ErrnoException).code !== 'ENOENT') throw error;
|
|
63
|
+
}
|
|
64
|
+
return join(canonical, 'recovery', 'locks', 'operation.lock');
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export function readRecoveryOperationLock(controllerHome: string): RecoveryOperationLockRecord | undefined {
|
|
68
|
+
return readRecoveryOperationLockPath(recoveryOperationLockPath(controllerHome));
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export function recoveryOperationLockOwnerAlive(lock: RecoveryOperationLockRecord): boolean {
|
|
72
|
+
if (!isProcessAlive(lock.pid)) return false;
|
|
73
|
+
if (!lock.processStartTime) return true;
|
|
74
|
+
const observed = processStartTime(lock.pid);
|
|
75
|
+
return observed === lock.processStartTime;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export function acquireRecoveryOperationLock(input: {
|
|
79
|
+
controllerHome: string;
|
|
80
|
+
action: string;
|
|
81
|
+
requestId?: string;
|
|
82
|
+
instanceIdPrefix?: string;
|
|
83
|
+
}, dependencies: {
|
|
84
|
+
writeRecord?: (fd: number, content: string) => void;
|
|
85
|
+
} = {}): RecoveryOperationLockAttempt {
|
|
86
|
+
const path = recoveryOperationLockPath(input.controllerHome);
|
|
87
|
+
mkdirSync(dirname(path), { recursive: true, mode: 0o700 });
|
|
88
|
+
const instanceId = `${input.instanceIdPrefix ?? 'recovery-operation-'}${randomUUID()}`;
|
|
89
|
+
const requestId = input.requestId?.trim() || `internal:${input.action}:${instanceId}`;
|
|
90
|
+
const record: RecoveryOperationLockRecord = {
|
|
91
|
+
schemaVersion: 1,
|
|
92
|
+
pid: process.pid,
|
|
93
|
+
instanceId,
|
|
94
|
+
processStartTime: processStartTime(process.pid),
|
|
95
|
+
acquiredAt: new Date().toISOString(),
|
|
96
|
+
action: input.action,
|
|
97
|
+
requestId,
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
for (let attempt = 0; attempt < 2; attempt += 1) {
|
|
101
|
+
let fd: number | undefined;
|
|
102
|
+
try {
|
|
103
|
+
try {
|
|
104
|
+
fd = openSync(path, 'wx', 0o600);
|
|
105
|
+
try {
|
|
106
|
+
(dependencies.writeRecord ?? ((targetFd: number, content: string) => writeFileSync(targetFd, content)))(fd, JSON.stringify(record));
|
|
107
|
+
} catch (error) {
|
|
108
|
+
// O_EXCL proved this process created this exact path. A partial or failed
|
|
109
|
+
// owner-record write must never leave an unreadable lock that poisons
|
|
110
|
+
// every later Recovery/certification attempt.
|
|
111
|
+
try { rmSync(path, { force: true }); } finally {
|
|
112
|
+
try { closeSync(fd); } catch { /* best effort */ }
|
|
113
|
+
fd = undefined;
|
|
114
|
+
}
|
|
115
|
+
throw error;
|
|
116
|
+
}
|
|
117
|
+
} catch (error) {
|
|
118
|
+
if ((error as NodeJS.ErrnoException).code !== 'EEXIST') throw error;
|
|
119
|
+
const existing = readRecoveryOperationLockPath(path);
|
|
120
|
+
if (!existing) throw new Error('RECOVERY_OPERATION_LOCK_UNCERTAIN');
|
|
121
|
+
if (recoveryOperationLockOwnerAlive(existing)) return { acquired: false, owner: existing };
|
|
122
|
+
const latest = readRecoveryOperationLockPath(path);
|
|
123
|
+
if (!latest || latest.instanceId !== existing.instanceId) {
|
|
124
|
+
if (attempt === 1) {
|
|
125
|
+
if (latest && recoveryOperationLockOwnerAlive(latest)) return { acquired: false, owner: latest };
|
|
126
|
+
throw new Error('RECOVERY_OPERATION_LOCK_RACE');
|
|
127
|
+
}
|
|
128
|
+
continue;
|
|
129
|
+
}
|
|
130
|
+
if (recoveryOperationLockOwnerAlive(latest)) return { acquired: false, owner: latest };
|
|
131
|
+
try { writeFileSync(`${path}.stale-${Date.now()}-${existing.instanceId}`, readFileSync(path)); } catch { /* evidence best effort */ }
|
|
132
|
+
rmSync(path, { force: true });
|
|
133
|
+
continue;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
if (fd === undefined) throw new Error('RECOVERY_OPERATION_LOCK_BUSY');
|
|
137
|
+
let closed = false;
|
|
138
|
+
return {
|
|
139
|
+
acquired: true,
|
|
140
|
+
handle: {
|
|
141
|
+
path,
|
|
142
|
+
record,
|
|
143
|
+
close: () => {
|
|
144
|
+
if (closed) return;
|
|
145
|
+
closed = true;
|
|
146
|
+
closeSync(fd!);
|
|
147
|
+
const current = readRecoveryOperationLockPath(path);
|
|
148
|
+
if (current?.instanceId === instanceId) rmSync(path, { force: true });
|
|
149
|
+
},
|
|
150
|
+
},
|
|
151
|
+
};
|
|
152
|
+
} catch (error) {
|
|
153
|
+
if (fd !== undefined) {
|
|
154
|
+
try { closeSync(fd); } catch { /* best effort */ }
|
|
155
|
+
}
|
|
156
|
+
throw error;
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
throw new Error('RECOVERY_OPERATION_LOCK_BUSY');
|
|
160
|
+
}
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
import { spawnSync } from 'node:child_process';
|
|
2
|
+
|
|
3
|
+
/** Release acceptance evidence, never a readiness/liveness or watchdog input. */
|
|
4
|
+
export interface RuntimePerformanceIdentity {
|
|
5
|
+
releaseId: string;
|
|
6
|
+
authorityRevision: number;
|
|
7
|
+
runtimeInstanceId: string;
|
|
8
|
+
pid: number;
|
|
9
|
+
startedAt: string;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export interface RuntimePerformanceEvidence extends RuntimePerformanceIdentity {
|
|
13
|
+
policy: 'runaway-cpu-v4';
|
|
14
|
+
measuredFrom: string;
|
|
15
|
+
measuredUntil: string;
|
|
16
|
+
warmupMs: number;
|
|
17
|
+
durationMs: number;
|
|
18
|
+
sampleCount: number;
|
|
19
|
+
meanCpuPercent: number;
|
|
20
|
+
p95CpuPercent: number;
|
|
21
|
+
/** Windows whose CPU consumption reached the per-window runaway ceiling. */
|
|
22
|
+
sustainedHighWindowCount: number;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export interface RuntimeCpuReading { cpuMs: number; processStartTime: string }
|
|
26
|
+
|
|
27
|
+
const PERFORMANCE_WINDOW_MS = 2_500;
|
|
28
|
+
const PERFORMANCE_MAX_WINDOW_MS = 3_750;
|
|
29
|
+
const PERFORMANCE_WARMUP_WINDOWS = 4;
|
|
30
|
+
const PERFORMANCE_SAMPLE_WINDOWS = 20;
|
|
31
|
+
const PERFORMANCE_WARMUP_MS = PERFORMANCE_WINDOW_MS * PERFORMANCE_WARMUP_WINDOWS;
|
|
32
|
+
const PERFORMANCE_DURATION_MS = PERFORMANCE_WINDOW_MS * PERFORMANCE_SAMPLE_WINDOWS;
|
|
33
|
+
|
|
34
|
+
// Recovery known-good is a runaway safety gate, not the comparative release benchmark.
|
|
35
|
+
// The v4 sampler keeps the same 60-second budget, the same twenty 2.5-second windows
|
|
36
|
+
// and the same 25%/50% ceilings as v2/v3, but decides runaway from *sustained*
|
|
37
|
+
// consumption instead of from nearest-rank p95.
|
|
38
|
+
//
|
|
39
|
+
// Why p95 cannot be the decision rule: the Canonical Runtime performs bounded,
|
|
40
|
+
// scheduled maintenance (the release-fenced periodic cleanup child and the in-process
|
|
41
|
+
// scheduler/recovery passes). Such a pass lasts several seconds and recurs about once
|
|
42
|
+
// per minute, so in any 50-second observation at least two windows necessarily land
|
|
43
|
+
// inside it. nearest-rank p95 is exactly the second-highest window, so a healthy
|
|
44
|
+
// Runtime with an ~11% mean was deterministically rejected (live evidence:
|
|
45
|
+
// mean=12.60% p95=65.05% and mean=11.41% p95=65.13%, both rolled back within minutes
|
|
46
|
+
// of cutover) and every automatic release progression converged on rollback.
|
|
47
|
+
//
|
|
48
|
+
// A watchdog duty must distinguish "unbounded spin" from "bounded periodic work", so
|
|
49
|
+
// v4 rejects a sample only when the process is high for at least half of the observed
|
|
50
|
+
// windows (sustainedHighWindowCount * 2 >= sampleCount) or when the mean exceeds the
|
|
51
|
+
// ceiling. The historical runaway population (mean >= 90.64%, p95 >= 104.72%) fails
|
|
52
|
+
// both tests by a wide margin, while a once-per-minute bounded pass (<= 4 of 20
|
|
53
|
+
// windows) can no longer be mistaken for runaway. p95 stays in the evidence for audit.
|
|
54
|
+
// Relative <=10% regression remains Benchmark/Release Evaluation authority.
|
|
55
|
+
export const RECOVERY_RUNAWAY_MEAN_CPU_PERCENT = 25;
|
|
56
|
+
export const RECOVERY_RUNAWAY_P95_CPU_PERCENT = 50;
|
|
57
|
+
|
|
58
|
+
/** Dependencies are in-process test seams; no transport accepts evidence or threshold overrides. */
|
|
59
|
+
export interface RuntimePerformanceDependencies {
|
|
60
|
+
readCpu?: (pid: number) => RuntimeCpuReading;
|
|
61
|
+
monotonicNow?: () => number;
|
|
62
|
+
wallNow?: () => number;
|
|
63
|
+
sleep?: (ms: number) => Promise<void>;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export function readRuntimeCpu(pid: number): RuntimeCpuReading {
|
|
67
|
+
const result = spawnSync('/bin/ps', ['-p', String(pid), '-o', 'time=', '-o', 'lstart='], {
|
|
68
|
+
encoding: 'utf8', timeout: 2_000, maxBuffer: 4_096, env: { ...process.env, LC_ALL: 'C' },
|
|
69
|
+
});
|
|
70
|
+
const match = result.status === 0
|
|
71
|
+
? result.stdout.trim().match(/^(?:(\d+)-)?(?:(\d+):)?(\d+):(\d+(?:\.\d+)?)\s+(.+)$/)
|
|
72
|
+
: undefined;
|
|
73
|
+
if (!match) throw new Error('RECOVERY_PERFORMANCE_UNKNOWN: process CPU measurement unavailable');
|
|
74
|
+
const cpuMs = (Number(match[1] ?? 0) * 86400 + Number(match[2] ?? 0) * 3600
|
|
75
|
+
+ Number(match[3]) * 60 + Number(match[4])) * 1000;
|
|
76
|
+
return { cpuMs, processStartTime: match[5]! };
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
export function samePerformanceIdentity(a: RuntimePerformanceIdentity, b: RuntimePerformanceIdentity): boolean {
|
|
80
|
+
return a.releaseId === b.releaseId && a.authorityRevision === b.authorityRevision
|
|
81
|
+
&& a.runtimeInstanceId === b.runtimeInstanceId && a.pid === b.pid && a.startedAt === b.startedAt;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
export function assertRuntimePerformanceEvidence(
|
|
85
|
+
evidence: RuntimePerformanceEvidence,
|
|
86
|
+
identity: RuntimePerformanceIdentity,
|
|
87
|
+
now = Date.now(),
|
|
88
|
+
): void {
|
|
89
|
+
const age = now - Date.parse(evidence.measuredUntil);
|
|
90
|
+
if (evidence.policy !== 'runaway-cpu-v4' || !samePerformanceIdentity(evidence, identity)
|
|
91
|
+
|| !Number.isFinite(age) || age < 0 || age > 60_000
|
|
92
|
+
|| evidence.warmupMs < PERFORMANCE_WARMUP_MS || evidence.warmupMs > PERFORMANCE_MAX_WINDOW_MS * PERFORMANCE_WARMUP_WINDOWS
|
|
93
|
+
|| evidence.durationMs < PERFORMANCE_DURATION_MS || evidence.durationMs > PERFORMANCE_MAX_WINDOW_MS * PERFORMANCE_SAMPLE_WINDOWS || evidence.sampleCount !== PERFORMANCE_SAMPLE_WINDOWS
|
|
94
|
+
|| !Number.isFinite(evidence.meanCpuPercent) || evidence.meanCpuPercent < 0
|
|
95
|
+
|| !Number.isFinite(evidence.p95CpuPercent) || evidence.p95CpuPercent < 0
|
|
96
|
+
|| !Number.isInteger(evidence.sustainedHighWindowCount)
|
|
97
|
+
|| evidence.sustainedHighWindowCount < 0
|
|
98
|
+
|| evidence.sustainedHighWindowCount > evidence.sampleCount) {
|
|
99
|
+
throw new Error('RECOVERY_PERFORMANCE_UNKNOWN: incomplete, stale or mismatched performance evidence');
|
|
100
|
+
}
|
|
101
|
+
const sustained = evidence.sustainedHighWindowCount * 2 >= evidence.sampleCount;
|
|
102
|
+
if (evidence.meanCpuPercent > RECOVERY_RUNAWAY_MEAN_CPU_PERCENT || sustained) {
|
|
103
|
+
throw new Error(`RECOVERY_PERFORMANCE_REJECTED: mean=${evidence.meanCpuPercent.toFixed(2)}% p95=${evidence.p95CpuPercent.toFixed(2)}% sustained=${evidence.sustainedHighWindowCount}/${evidence.sampleCount}`);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/** Observe 10 seconds of warmup followed by twenty 2.5-second CPU-time delta windows. */
|
|
108
|
+
export async function measureRuntimePerformance(
|
|
109
|
+
observeIdentity: () => RuntimePerformanceIdentity,
|
|
110
|
+
dependencies: RuntimePerformanceDependencies = {},
|
|
111
|
+
): Promise<RuntimePerformanceEvidence> {
|
|
112
|
+
const readCpu = dependencies.readCpu ?? readRuntimeCpu;
|
|
113
|
+
const monotonicNow = dependencies.monotonicNow ?? (() => performance.now());
|
|
114
|
+
const wallNow = dependencies.wallNow ?? Date.now;
|
|
115
|
+
const sleep = dependencies.sleep ?? ((ms) => new Promise((resolve) => setTimeout(resolve, ms)));
|
|
116
|
+
const identity = observeIdentity();
|
|
117
|
+
const initial = readCpu(identity.pid);
|
|
118
|
+
const observe = () => {
|
|
119
|
+
if (!samePerformanceIdentity(identity, observeIdentity())) {
|
|
120
|
+
throw new Error('RECOVERY_PERFORMANCE_UNKNOWN: Runtime or release authority changed');
|
|
121
|
+
}
|
|
122
|
+
const cpu = readCpu(identity.pid);
|
|
123
|
+
if (cpu.processStartTime !== initial.processStartTime || !Number.isFinite(cpu.cpuMs)) {
|
|
124
|
+
throw new Error('RECOVERY_PERFORMANCE_UNKNOWN: process identity changed');
|
|
125
|
+
}
|
|
126
|
+
return cpu;
|
|
127
|
+
};
|
|
128
|
+
const warmingAt = monotonicNow();
|
|
129
|
+
let previousWarmupAt = warmingAt;
|
|
130
|
+
for (let i = 0; i < PERFORMANCE_WARMUP_WINDOWS; i++) {
|
|
131
|
+
await sleep(PERFORMANCE_WINDOW_MS);
|
|
132
|
+
observe();
|
|
133
|
+
const nextWarmupAt = monotonicNow();
|
|
134
|
+
const elapsed = nextWarmupAt - previousWarmupAt;
|
|
135
|
+
if (elapsed < PERFORMANCE_WINDOW_MS || elapsed > PERFORMANCE_MAX_WINDOW_MS) {
|
|
136
|
+
throw new Error('RECOVERY_PERFORMANCE_UNKNOWN: interrupted CPU warmup window');
|
|
137
|
+
}
|
|
138
|
+
previousWarmupAt = nextWarmupAt;
|
|
139
|
+
}
|
|
140
|
+
const warmupMs = monotonicNow() - warmingAt;
|
|
141
|
+
const measuredFrom = new Date(wallNow()).toISOString();
|
|
142
|
+
let previousCpu = observe().cpuMs;
|
|
143
|
+
let previousAt = monotonicNow();
|
|
144
|
+
const startedAt = previousAt;
|
|
145
|
+
let totalCpuMs = 0;
|
|
146
|
+
const windows: number[] = [];
|
|
147
|
+
for (let i = 0; i < PERFORMANCE_SAMPLE_WINDOWS; i++) {
|
|
148
|
+
await sleep(PERFORMANCE_WINDOW_MS);
|
|
149
|
+
const nextCpu = observe().cpuMs;
|
|
150
|
+
const nextAt = monotonicNow();
|
|
151
|
+
const elapsed = nextAt - previousAt;
|
|
152
|
+
const cpuDelta = nextCpu - previousCpu;
|
|
153
|
+
// Suspended/overloaded collectors cannot pass as ordinary sample windows.
|
|
154
|
+
if (elapsed < PERFORMANCE_WINDOW_MS || elapsed > PERFORMANCE_MAX_WINDOW_MS || cpuDelta < 0) {
|
|
155
|
+
throw new Error('RECOVERY_PERFORMANCE_UNKNOWN: interrupted CPU observation window');
|
|
156
|
+
}
|
|
157
|
+
windows.push(cpuDelta / elapsed * 100);
|
|
158
|
+
totalCpuMs += cpuDelta;
|
|
159
|
+
previousCpu = nextCpu;
|
|
160
|
+
previousAt = nextAt;
|
|
161
|
+
}
|
|
162
|
+
const durationMs = previousAt - startedAt;
|
|
163
|
+
windows.sort((a, b) => a - b);
|
|
164
|
+
const evidence: RuntimePerformanceEvidence = {
|
|
165
|
+
...identity, policy: 'runaway-cpu-v4', measuredFrom, measuredUntil: new Date(wallNow()).toISOString(),
|
|
166
|
+
warmupMs, durationMs, sampleCount: windows.length,
|
|
167
|
+
meanCpuPercent: totalCpuMs / durationMs * 100,
|
|
168
|
+
p95CpuPercent: windows[Math.ceil(windows.length * 0.95) - 1]!,
|
|
169
|
+
sustainedHighWindowCount: windows.filter((cpuPercent) => cpuPercent >= RECOVERY_RUNAWAY_P95_CPU_PERCENT).length,
|
|
170
|
+
};
|
|
171
|
+
assertRuntimePerformanceEvidence(evidence, observeIdentity(), wallNow());
|
|
172
|
+
return evidence;
|
|
173
|
+
}
|
|
@@ -15,8 +15,8 @@ import {
|
|
|
15
15
|
import { dirname, join, relative, resolve, sep } from 'path';
|
|
16
16
|
import { writeJsonAtomic } from '../shared/json-files';
|
|
17
17
|
|
|
18
|
-
export const RECOVERY_RELEASE_BINARIES = [
|
|
19
|
-
|
|
18
|
+
export const RECOVERY_RELEASE_BINARIES = ['forge-recovery'] as const;
|
|
19
|
+
export const RECOVERY_RELEASE_COMPATIBILITY_BINARIES = [
|
|
20
20
|
'forge-recovery-gateway',
|
|
21
21
|
'forge-recovery-watchdog',
|
|
22
22
|
] as const;
|
|
@@ -24,7 +24,8 @@ export const RECOVERY_RELEASE_BINARIES = [
|
|
|
24
24
|
export const RECOVERY_RELEASE_ROLE_CANARY_ARG = '--forge-release-role-canary';
|
|
25
25
|
|
|
26
26
|
export type RecoveryReleaseBinary = (typeof RECOVERY_RELEASE_BINARIES)[number];
|
|
27
|
-
|
|
27
|
+
/** daemon is the only current persistent owner; gateway/watchdog remain legacy CLI compatibility roles. */
|
|
28
|
+
export type RecoveryRuntimeRole = 'daemon' | 'gateway' | 'watchdog';
|
|
28
29
|
export interface RecoveryReleaseManifest {
|
|
29
30
|
schemaVersion: 1;
|
|
30
31
|
releaseRevision: string;
|
|
@@ -32,6 +33,8 @@ export interface RecoveryReleaseManifest {
|
|
|
32
33
|
sourceRoot: string;
|
|
33
34
|
cleanWorkspace: boolean;
|
|
34
35
|
builtAt: string;
|
|
36
|
+
/** Product version derived from the source package and bound by the manifest hash. */
|
|
37
|
+
productVersion?: string;
|
|
35
38
|
legacy?: boolean;
|
|
36
39
|
artifacts: Record<RecoveryReleaseBinary, { sha256: string }>;
|
|
37
40
|
}
|
|
@@ -42,6 +45,7 @@ export interface RecoveryReleaseDescriptor {
|
|
|
42
45
|
sourceCommit: string;
|
|
43
46
|
sourceRoot: string;
|
|
44
47
|
cleanWorkspace: boolean;
|
|
48
|
+
productVersion?: string;
|
|
45
49
|
manifestSha256: string;
|
|
46
50
|
artifacts: RecoveryReleaseManifest['artifacts'];
|
|
47
51
|
legacy: boolean;
|
|
@@ -81,6 +85,49 @@ export function recoveryRuntimeStatePath(controllerHome: string, role: RecoveryR
|
|
|
81
85
|
return join(recoveryRoot(controllerHome), 'state', `${role}-runtime.json`);
|
|
82
86
|
}
|
|
83
87
|
|
|
88
|
+
export function recoveryGatewayDrainMarkerPath(controllerHome: string): string {
|
|
89
|
+
return join(recoveryRoot(controllerHome), 'state', 'gateway-draining.json');
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
const RECOVERY_GATEWAY_DRAIN_MARKER_TTL_MS = 5 * 60_000;
|
|
93
|
+
|
|
94
|
+
export function recoveryGatewayIsDraining(controllerHome: string, now = Date.now()): boolean {
|
|
95
|
+
const path = recoveryGatewayDrainMarkerPath(controllerHome);
|
|
96
|
+
if (!existsSync(path)) return false;
|
|
97
|
+
try {
|
|
98
|
+
const marker = JSON.parse(readFileSync(path, 'utf8')) as { pid?: unknown; at?: unknown };
|
|
99
|
+
const pid = Number(marker.pid);
|
|
100
|
+
const at = typeof marker.at === 'string' ? Date.parse(marker.at) : Number.NaN;
|
|
101
|
+
if (!Number.isInteger(pid) || pid <= 0 || !Number.isFinite(at) || now - at > RECOVERY_GATEWAY_DRAIN_MARKER_TTL_MS) {
|
|
102
|
+
rmSync(path, { force: true });
|
|
103
|
+
return false;
|
|
104
|
+
}
|
|
105
|
+
try {
|
|
106
|
+
process.kill(pid, 0);
|
|
107
|
+
return true;
|
|
108
|
+
} catch (error) {
|
|
109
|
+
const code = (error as NodeJS.ErrnoException).code;
|
|
110
|
+
if (code === 'EPERM') return true;
|
|
111
|
+
rmSync(path, { force: true });
|
|
112
|
+
return false;
|
|
113
|
+
}
|
|
114
|
+
} catch {
|
|
115
|
+
rmSync(path, { force: true });
|
|
116
|
+
return false;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
export function setRecoveryGatewayDraining(controllerHome: string, draining: boolean): void {
|
|
121
|
+
const path = recoveryGatewayDrainMarkerPath(controllerHome);
|
|
122
|
+
if (!draining) {
|
|
123
|
+
rmSync(path, { force: true });
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
126
|
+
mkdirSync(dirname(path), { recursive: true, mode: 0o700 });
|
|
127
|
+
writeJsonAtomic(path, { schemaVersion: 1, draining: true, pid: process.pid, at: new Date().toISOString() });
|
|
128
|
+
chmodSync(path, 0o600);
|
|
129
|
+
}
|
|
130
|
+
|
|
84
131
|
function fileSha256(path: string): string {
|
|
85
132
|
return createHash('sha256').update(readFileSync(path)).digest('hex');
|
|
86
133
|
}
|
|
@@ -109,6 +156,7 @@ export function readRecoveryRelease(path: string | undefined): RecoveryReleaseDe
|
|
|
109
156
|
if (typeof parsed.sourceCommit !== 'string' || !parsed.sourceCommit.trim()) return undefined;
|
|
110
157
|
if (typeof parsed.sourceRoot !== 'string' || !parsed.sourceRoot.trim()) return undefined;
|
|
111
158
|
if (typeof parsed.cleanWorkspace !== 'boolean') return undefined;
|
|
159
|
+
if (parsed.productVersion !== undefined && (typeof parsed.productVersion !== 'string' || !parsed.productVersion.trim())) return undefined;
|
|
112
160
|
if (!parsed.artifacts || typeof parsed.artifacts !== 'object') return undefined;
|
|
113
161
|
const artifacts = {} as RecoveryReleaseManifest['artifacts'];
|
|
114
162
|
for (const binary of RECOVERY_RELEASE_BINARIES) {
|
|
@@ -123,6 +171,7 @@ export function readRecoveryRelease(path: string | undefined): RecoveryReleaseDe
|
|
|
123
171
|
sourceCommit: parsed.sourceCommit,
|
|
124
172
|
sourceRoot: resolve(parsed.sourceRoot),
|
|
125
173
|
cleanWorkspace: parsed.cleanWorkspace,
|
|
174
|
+
productVersion: typeof parsed.productVersion === 'string' ? parsed.productVersion.trim() : undefined,
|
|
126
175
|
manifestSha256: createHash('sha256').update(bytes).digest('hex'),
|
|
127
176
|
artifacts,
|
|
128
177
|
legacy: parsed.legacy === true,
|
|
@@ -179,11 +228,15 @@ export function publishRecoveryCompatibilityLinks(controllerHome: string): void
|
|
|
179
228
|
assertRecoveryReleaseContained(controllerHome, current);
|
|
180
229
|
const binRoot = join(recoveryRoot(controllerHome), 'bin');
|
|
181
230
|
mkdirSync(binRoot, { recursive: true, mode: 0o700 });
|
|
182
|
-
|
|
231
|
+
const compatibilityTargets = [
|
|
232
|
+
...RECOVERY_RELEASE_BINARIES.map((binary) => ({ binary, target: binary })),
|
|
233
|
+
...RECOVERY_RELEASE_COMPATIBILITY_BINARIES.map((binary) => ({ binary, target: 'forge-recovery' as const })),
|
|
234
|
+
];
|
|
235
|
+
for (const { binary, target } of compatibilityTargets) {
|
|
183
236
|
const destination = join(binRoot, binary);
|
|
184
237
|
const temporary = `${destination}.${process.pid}.tmp`;
|
|
185
238
|
rmSync(temporary, { force: true });
|
|
186
|
-
symlinkSync(join('..', 'current',
|
|
239
|
+
symlinkSync(join('..', 'current', target), temporary);
|
|
187
240
|
renameSync(temporary, destination);
|
|
188
241
|
}
|
|
189
242
|
}
|
|
@@ -1,2 +1,5 @@
|
|
|
1
|
-
export
|
|
2
|
-
|
|
1
|
+
export {
|
|
2
|
+
FORGE_RECOVERY_DAEMON_LABEL as RECOVERY_DAEMON_LABEL,
|
|
3
|
+
FORGE_RECOVERY_GATEWAY_LABEL as RECOVERY_GATEWAY_LABEL,
|
|
4
|
+
FORGE_RECOVERY_WATCHDOG_LABEL as RECOVERY_WATCHDOG_LABEL,
|
|
5
|
+
} from '../platform/service-inventory';
|
|
@@ -151,10 +151,13 @@ export function evaluateRecoveryWatchdogHealth(input: {
|
|
|
151
151
|
return { ok: true, detail: 'Recovery Watchdog heartbeat, PID, and immutable release identity are current', pulseAgeMs, heartbeat, runtimeIdentity, currentReleaseRevision: current.releaseRevision };
|
|
152
152
|
}
|
|
153
153
|
|
|
154
|
-
export function observeRecoveryWatchdogHealth(controllerHome: string): RecoveryWatchdogHealth {
|
|
154
|
+
export function observeRecoveryWatchdogHealth(controllerHome: string, enabled = true): RecoveryWatchdogHealth {
|
|
155
|
+
if (!enabled) {
|
|
156
|
+
return { ok: true, detail: 'Recovery Watchdog is disabled by the configured install profile' };
|
|
157
|
+
}
|
|
155
158
|
return evaluateRecoveryWatchdogHealth({
|
|
156
159
|
heartbeat: readRecoveryWatchdogHeartbeat(controllerHome),
|
|
157
|
-
runtimeIdentity: readRecoveryRuntimeIdentity(controllerHome, '
|
|
160
|
+
runtimeIdentity: readRecoveryRuntimeIdentity(controllerHome, 'daemon'),
|
|
158
161
|
currentRelease: readCurrentRecoveryRelease(controllerHome),
|
|
159
162
|
});
|
|
160
163
|
}
|
|
@@ -3,7 +3,7 @@ import { getLocalBridgeJobEventsSnapshot, listLocalBridgeJobSnapshots } from '..
|
|
|
3
3
|
import type { RepositoryRecord } from '../../cli/repositories/types';
|
|
4
4
|
import { listExecutionJobs } from '../execution/jobs/store';
|
|
5
5
|
import { collectRuntimePerformanceDiagnostics, type RuntimePerformanceDiagnostics } from '../diagnostics/performance';
|
|
6
|
-
import { listSchedules } from '
|
|
6
|
+
import { listSchedules } from '../../../packages/kernel/scheduler/api/index';
|
|
7
7
|
|
|
8
8
|
const ACTIVE_AGENT_STATUSES = new Set(['queued', 'starting', 'running']);
|
|
9
9
|
|
|
@@ -82,6 +82,7 @@ async function browserAction(
|
|
|
82
82
|
occurrenceId: string,
|
|
83
83
|
actionId: string,
|
|
84
84
|
args: Record<string, unknown>,
|
|
85
|
+
authorizationGrantRefs: readonly string[],
|
|
85
86
|
): Promise<Record<string, unknown>> {
|
|
86
87
|
return executeBrowserPluginAction({
|
|
87
88
|
controllerHome,
|
|
@@ -92,9 +93,16 @@ async function browserAction(
|
|
|
92
93
|
requestId: `schedule-browser-probe:${occurrenceId}:${actionId}`,
|
|
93
94
|
args,
|
|
94
95
|
origin: { surface: 'schedule', actor: 'browser-probe', correlationId: occurrenceId },
|
|
96
|
+
authorizationGrantRefs,
|
|
95
97
|
});
|
|
96
98
|
}
|
|
97
99
|
|
|
100
|
+
/** Exact interactive grants attached to this Schedule; contents remain Controller-owned. */
|
|
101
|
+
export function scheduledBrowserProbeAuthorizationGrantRefs(args: Record<string, unknown>): string[] {
|
|
102
|
+
if (!Array.isArray(args.authorization_grant_refs)) return [];
|
|
103
|
+
return [...new Set(args.authorization_grant_refs.map(String).map((value) => value.trim()).filter(Boolean))];
|
|
104
|
+
}
|
|
105
|
+
|
|
98
106
|
interface ScheduledBrowserSessionMetadata {
|
|
99
107
|
url?: string;
|
|
100
108
|
ownership?: string;
|
|
@@ -137,8 +145,9 @@ async function scheduledBrowserSessionMetadata(
|
|
|
137
145
|
repository: RepositoryRecord,
|
|
138
146
|
occurrenceId: string,
|
|
139
147
|
sessionId: string,
|
|
148
|
+
authorizationGrantRefs: readonly string[],
|
|
140
149
|
): Promise<ScheduledBrowserSessionMetadata | undefined> {
|
|
141
|
-
const inventory = await browserAction(controllerHome, repository, occurrenceId, 'list_sessions', {});
|
|
150
|
+
const inventory = await browserAction(controllerHome, repository, occurrenceId, 'list_sessions', {}, authorizationGrantRefs);
|
|
142
151
|
const sessions = Array.isArray(inventory.sessions) ? inventory.sessions : [];
|
|
143
152
|
const saved = sessions
|
|
144
153
|
.map((entry) => recordValue(entry))
|
|
@@ -170,10 +179,12 @@ export async function executeScheduledBrowserProbe(input: {
|
|
|
170
179
|
const url = stringValue(input.args.probe_url) ?? stringValue(input.args.url);
|
|
171
180
|
if (!requestedSessionId && !url) throw new Error('SCHEDULE_BROWSER_PROBE_TARGET_REQUIRED');
|
|
172
181
|
|
|
182
|
+
const authorizationGrantRefs = scheduledBrowserProbeAuthorizationGrantRefs(input.args);
|
|
183
|
+
|
|
173
184
|
const waitUntil = stringValue(input.args.wait_until) ?? 'domcontentloaded';
|
|
174
185
|
const timeoutMs = boundedNumber(input.args.timeout_ms, 60_000, 1_000, 120_000);
|
|
175
186
|
const savedSession = requestedSessionId
|
|
176
|
-
? await scheduledBrowserSessionMetadata(input.controllerHome, input.repository, input.occurrenceId, requestedSessionId)
|
|
187
|
+
? await scheduledBrowserSessionMetadata(input.controllerHome, input.repository, input.occurrenceId, requestedSessionId, authorizationGrantRefs)
|
|
177
188
|
: undefined;
|
|
178
189
|
const navigationAction = scheduledBrowserProbeNavigationAction(savedSession?.ownership, Boolean(url));
|
|
179
190
|
const managedRehydrateIntent = scheduledBrowserProbeManagedRehydrateIntent(savedSession);
|
|
@@ -188,7 +199,7 @@ export async function executeScheduledBrowserProbe(input: {
|
|
|
188
199
|
state: waitUntil,
|
|
189
200
|
timeout_ms: timeoutMs,
|
|
190
201
|
...managedRehydrateIntent,
|
|
191
|
-
});
|
|
202
|
+
}, authorizationGrantRefs);
|
|
192
203
|
} else if (navigationAction === 'navigate') {
|
|
193
204
|
navigation = await browserAction(input.controllerHome, input.repository, input.occurrenceId, 'navigate', {
|
|
194
205
|
...(requestedSessionId ? { session_id: requestedSessionId } : {}),
|
|
@@ -197,14 +208,14 @@ export async function executeScheduledBrowserProbe(input: {
|
|
|
197
208
|
timeout_ms: timeoutMs,
|
|
198
209
|
retries: 1,
|
|
199
210
|
...managedRehydrateIntent,
|
|
200
|
-
});
|
|
211
|
+
}, authorizationGrantRefs);
|
|
201
212
|
} else {
|
|
202
213
|
navigation = await browserAction(input.controllerHome, input.repository, input.occurrenceId, 'reload', {
|
|
203
214
|
session_id: requestedSessionId!,
|
|
204
215
|
wait_until: waitUntil,
|
|
205
216
|
timeout_ms: timeoutMs,
|
|
206
217
|
...managedRehydrateIntent,
|
|
207
|
-
});
|
|
218
|
+
}, authorizationGrantRefs);
|
|
208
219
|
}
|
|
209
220
|
|
|
210
221
|
const session = recordValue(navigation.session);
|
|
@@ -224,7 +235,7 @@ export async function executeScheduledBrowserProbe(input: {
|
|
|
224
235
|
session_id: sessionId,
|
|
225
236
|
...(stringValue(input.args.selector) ? { selector: stringValue(input.args.selector) } : {}),
|
|
226
237
|
max_chars: boundedNumber(input.args.max_chars, 20_000, 256, 100_000),
|
|
227
|
-
});
|
|
238
|
+
}, authorizationGrantRefs);
|
|
228
239
|
rawText = stringValue(textResult.text) ?? '';
|
|
229
240
|
truncated = textResult.truncated === true;
|
|
230
241
|
}
|