@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
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { createHash } from 'crypto';
|
|
1
|
+
import { createHash, randomUUID } from 'crypto';
|
|
2
2
|
import { closeSync, existsSync, mkdirSync, openSync, readFileSync, rmSync, writeFileSync } from 'fs';
|
|
3
|
+
import { tmpdir } from 'os';
|
|
3
4
|
import { basename, dirname, join, normalize, relative, resolve } from 'path';
|
|
4
5
|
import {
|
|
5
6
|
capProcessOutput,
|
|
@@ -12,6 +13,21 @@ import { runBoundedChild } from '../../runtime/shared/bounded-child-supervisor';
|
|
|
12
13
|
import { signalProcessTree } from '../../runtime/shared/process-tree';
|
|
13
14
|
import { repositoryChildProcessEnvironment, resolveBunExecutable } from '../../runtime/shared/process-environment';
|
|
14
15
|
import { materializeManagedWorkspaceCheckDependencies } from '../../runtime/execution/managed-workspace';
|
|
16
|
+
import {
|
|
17
|
+
isStructuredCheckFailureEvidence,
|
|
18
|
+
STRUCTURED_CHECK_RESULT_PATH_ENV,
|
|
19
|
+
type StructuredCheckFailureEvidence,
|
|
20
|
+
} from '../../runtime/execution/process-runtime/check-result';
|
|
21
|
+
import { readRuntimeReleaseAuthority } from '../../runtime/root/release-store';
|
|
22
|
+
import { observeRuntimeStatus } from '../../runtime/root/status';
|
|
23
|
+
import { readCurrentRecoveryRelease } from '../../runtime/standalone-recovery/release';
|
|
24
|
+
import { acquireRecoveryOperationLock, recoveryOperationLockPath } from '../../runtime/standalone-recovery/operation-lock';
|
|
25
|
+
import {
|
|
26
|
+
ensureRepositoryCheckStorage,
|
|
27
|
+
resolveRepositoryCheckStorage,
|
|
28
|
+
type RepositoryCheckStorageAuthority,
|
|
29
|
+
type ResolvedRepositoryCheckStorage,
|
|
30
|
+
} from '../../runtime/execution/process-runtime/check-storage';
|
|
15
31
|
|
|
16
32
|
export interface ControllerCheckEffects {
|
|
17
33
|
/** Repository-relative read scopes. Use [\".\"] for the whole checkout. */
|
|
@@ -29,6 +45,7 @@ export interface ControllerCheckEffects {
|
|
|
29
45
|
export type ControllerCheckCostClass = 'L0' | 'L1' | 'L2' | 'L3' | 'L4';
|
|
30
46
|
export type ControllerCheckRiskFloor = 'readonly' | 'low' | 'medium' | 'high' | 'destructive';
|
|
31
47
|
export type ControllerCheckPhase = 'pre_edit' | 'post_edit' | 'pre_finalize' | 'release';
|
|
48
|
+
export type ControllerCheckExecutionAuthority = 'isolated_controller_home' | 'live_controller_home';
|
|
32
49
|
|
|
33
50
|
export interface ControllerCheckSelection {
|
|
34
51
|
/** Execution cost only; it does not lower severity or automatically run the check. */
|
|
@@ -45,6 +62,8 @@ export interface ControllerCheck {
|
|
|
45
62
|
cwd: string;
|
|
46
63
|
timeoutMs: number;
|
|
47
64
|
source: 'repo-config' | 'package-script';
|
|
65
|
+
/** Where authority-sensitive child state is resolved. Ordinary checks stay isolated. */
|
|
66
|
+
executionAuthority?: ControllerCheckExecutionAuthority;
|
|
48
67
|
effects?: ControllerCheckEffects;
|
|
49
68
|
/** Selection/preflight metadata; intentionally excluded from physical execution identity. */
|
|
50
69
|
selection?: ControllerCheckSelection;
|
|
@@ -89,8 +108,8 @@ interface CheckConfig {
|
|
|
89
108
|
|
|
90
109
|
const CHECK_CONFIG = '.forge/checks.json';
|
|
91
110
|
const LEGACY_TRACKED_CHECK_CONFIG = '.repo-harness/checks.json';
|
|
92
|
-
const
|
|
93
|
-
const HEAVY_CHECK_LOCK = '
|
|
111
|
+
const CHECK_EVIDENCE_SUBDIR = 'controller';
|
|
112
|
+
const HEAVY_CHECK_LOCK = 'heavy-check.lock';
|
|
94
113
|
const DEFAULT_TIMEOUT_MS = 10 * 60 * 1000;
|
|
95
114
|
const MAX_TIMEOUT_MS = 30 * 60 * 1000;
|
|
96
115
|
const SAFE_PACKAGE_SCRIPT = /^(test(?::|$)|check(?::|$)|lint(?::|$)|typecheck(?::|$)|format:check$)/;
|
|
@@ -253,8 +272,27 @@ export function controllerCheckSelection(check: Pick<ControllerCheck, 'id' | 'se
|
|
|
253
272
|
|
|
254
273
|
function inferredPackageCheckEffects(name: string): ControllerCheckEffects | undefined {
|
|
255
274
|
const normalized = name.trim().toLowerCase();
|
|
256
|
-
|
|
257
|
-
|
|
275
|
+
if (normalized === 'check:stable-baseline') {
|
|
276
|
+
return { reads: ['.'], hostServices: ['canonical-runtime', 'forge-recovery'] };
|
|
277
|
+
}
|
|
278
|
+
if (normalized === 'check:task' || normalized === 'check:main') {
|
|
279
|
+
// Governed gates reject any candidate workspace mutation after every step
|
|
280
|
+
// and persist only content-bound receipts/caches outside repository source.
|
|
281
|
+
return { reads: ['.'], cache: 'write', temp: 'isolated', git: 'read' };
|
|
282
|
+
}
|
|
283
|
+
if (normalized === 'check:type' || normalized === 'check:runtime-architecture') {
|
|
284
|
+
// These canonical gates are source readers: TypeScript runs with --noEmit,
|
|
285
|
+
// while runtime-architecture only inspects source/AST structure. Neither
|
|
286
|
+
// owns the shared repository build cache.
|
|
287
|
+
return { reads: ['.'] };
|
|
288
|
+
}
|
|
289
|
+
if (normalized === 'check:architecture-sync') {
|
|
290
|
+
// Architecture sync runs the queue in --check mode and inspects Git state.
|
|
291
|
+
// Its scratch space is check-local; it never mutates repository source.
|
|
292
|
+
return { reads: ['.'], temp: 'isolated', git: 'read' };
|
|
293
|
+
}
|
|
294
|
+
const cachedStaticAnalysis = /(?:^|:)(?:typecheck|lint|format:check|mcp-compatibility|forge-runtime)$/.test(normalized);
|
|
295
|
+
if (cachedStaticAnalysis) return { reads: ['.'], cache: 'write' };
|
|
258
296
|
const isolatedReadOnlyCheck = /(?:^|:)(?:quality-harness|evaluation-framework|background-check-overlap|typescript-navigation|check-scheduling|bootstrap-files)$/.test(normalized);
|
|
259
297
|
if (isolatedReadOnlyCheck) return { reads: ['.'], temp: 'isolated', git: 'read' };
|
|
260
298
|
const browserLive = /(?:^|:)browser-live$/.test(normalized);
|
|
@@ -312,6 +350,9 @@ function packageChecks(repoRoot: string): ControllerCheck[] {
|
|
|
312
350
|
cwd: '.',
|
|
313
351
|
timeoutMs: packageScriptTimeoutMs(name),
|
|
314
352
|
source: 'package-script' as const,
|
|
353
|
+
executionAuthority: name.trim().toLowerCase() === 'check:stable-baseline'
|
|
354
|
+
? 'live_controller_home' as const
|
|
355
|
+
: 'isolated_controller_home' as const,
|
|
315
356
|
effects: inferredPackageCheckEffects(name),
|
|
316
357
|
selection: inferredCheckSelection(name),
|
|
317
358
|
}];
|
|
@@ -340,8 +381,9 @@ export interface ControllerCheckResult {
|
|
|
340
381
|
validatedRevision?: string;
|
|
341
382
|
/** Original process execution timestamp; retained when a result is served from cache. */
|
|
342
383
|
originalExecutedAt?: string;
|
|
343
|
-
/**
|
|
384
|
+
/** Non-zero repository failures are acceptance failures unless bounded infrastructure evidence proves otherwise. */
|
|
344
385
|
failureClass?: 'acceptance_failure' | 'infrastructure_failure';
|
|
386
|
+
failureEvidence?: StructuredCheckFailureEvidence;
|
|
345
387
|
}
|
|
346
388
|
|
|
347
389
|
export interface ControllerCheckEvidence {
|
|
@@ -365,54 +407,190 @@ export interface ControllerCheckEvidence {
|
|
|
365
407
|
validatedRevision?: string;
|
|
366
408
|
originalExecutedAt?: string;
|
|
367
409
|
failureClass?: 'acceptance_failure' | 'infrastructure_failure';
|
|
410
|
+
failureEvidence?: StructuredCheckFailureEvidence;
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
const STRONG_TRANSPORT_FAILURE_PATTERNS = [
|
|
414
|
+
/\bjava\.net\.(?:SocketTimeoutException|UnknownHostException|ConnectException|NoRouteToHostException)\b/i,
|
|
415
|
+
/\b(?:EAI_AGAIN|ENOTFOUND|ECONNREFUSED|ECONNRESET|ETIMEDOUT|ENETUNREACH|EHOSTUNREACH)\b/i,
|
|
416
|
+
/\bCould not resolve host\b/i,
|
|
417
|
+
/\b(?:connection|connect|read) timed out\b/i,
|
|
418
|
+
/\bNetwork is unreachable\b/i,
|
|
419
|
+
/\b(?:SSLHandshakeException|TLS handshake (?:failed|timeout|timed out)|CERTIFICATE_VERIFY_FAILED)\b/i,
|
|
420
|
+
] as const;
|
|
421
|
+
|
|
422
|
+
function classifyControllerCheckFailure(input: {
|
|
423
|
+
ok: boolean;
|
|
424
|
+
stale?: boolean;
|
|
425
|
+
timedOut: boolean;
|
|
426
|
+
runtimeFailure: boolean;
|
|
427
|
+
stdout: string;
|
|
428
|
+
stderr: string;
|
|
429
|
+
}): 'acceptance_failure' | 'infrastructure_failure' | undefined {
|
|
430
|
+
if (input.ok && !input.stale) return undefined;
|
|
431
|
+
if (input.stale || input.timedOut || input.runtimeFailure) return 'infrastructure_failure';
|
|
432
|
+
const output = `${input.stdout}\n${input.stderr}`;
|
|
433
|
+
if (STRONG_TRANSPORT_FAILURE_PATTERNS.some((pattern) => pattern.test(output))) return 'infrastructure_failure';
|
|
434
|
+
return 'acceptance_failure';
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
const GOVERNED_TEST_GATES = new Map<string, string>([
|
|
438
|
+
['package:test', 'affected'],
|
|
439
|
+
['package:test:core', 'core'],
|
|
440
|
+
['package:test:integration', 'integration'],
|
|
441
|
+
['package:test:infrastructure', 'infrastructure'],
|
|
442
|
+
['package:test:fault', 'fault'],
|
|
443
|
+
['package:test:full', 'full'],
|
|
444
|
+
['package:test:bun', 'full'],
|
|
445
|
+
]);
|
|
446
|
+
const MAX_STRUCTURED_CHECK_RESULT_BYTES = 64 * 1024;
|
|
447
|
+
|
|
448
|
+
interface StructuredCheckObservation {
|
|
449
|
+
evidence?: StructuredCheckFailureEvidence;
|
|
450
|
+
error?: string;
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
function structuredCheckResultPath(check: ControllerCheck): string | undefined {
|
|
454
|
+
if (!GOVERNED_TEST_GATES.has(check.id)) return undefined;
|
|
455
|
+
return join(tmpdir(), `forge-check-result-${process.pid}-${randomUUID()}.json`);
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
function readStructuredCheckObservation(check: ControllerCheck, path: string | undefined): StructuredCheckObservation {
|
|
459
|
+
const expectedGate = GOVERNED_TEST_GATES.get(check.id);
|
|
460
|
+
if (!expectedGate) return {};
|
|
461
|
+
if (!path || !existsSync(path)) return { error: 'CHECK_STRUCTURED_RESULT_MISSING' };
|
|
462
|
+
try {
|
|
463
|
+
const bytes = readFileSync(path);
|
|
464
|
+
if (bytes.byteLength > MAX_STRUCTURED_CHECK_RESULT_BYTES) return { error: 'CHECK_STRUCTURED_RESULT_TOO_LARGE' };
|
|
465
|
+
const value = JSON.parse(bytes.toString('utf8')) as unknown;
|
|
466
|
+
if (!isStructuredCheckFailureEvidence(value) || value.gate !== expectedGate) return { error: 'CHECK_STRUCTURED_RESULT_INVALID' };
|
|
467
|
+
return { evidence: value };
|
|
468
|
+
} catch {
|
|
469
|
+
return { error: 'CHECK_STRUCTURED_RESULT_INVALID' };
|
|
470
|
+
}
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
function consumeStructuredCheckObservation(check: ControllerCheck, path: string | undefined): StructuredCheckObservation {
|
|
474
|
+
try {
|
|
475
|
+
return readStructuredCheckObservation(check, path);
|
|
476
|
+
} finally {
|
|
477
|
+
if (path) rmSync(path, { force: true });
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
function applyStructuredCheckObservation(processOk: boolean, observation: StructuredCheckObservation): {
|
|
482
|
+
ok: boolean;
|
|
483
|
+
failureClass?: 'acceptance_failure' | 'infrastructure_failure';
|
|
484
|
+
failureEvidence?: StructuredCheckFailureEvidence;
|
|
485
|
+
error?: string;
|
|
486
|
+
} {
|
|
487
|
+
if (!observation.error && !observation.evidence) return { ok: processOk };
|
|
488
|
+
if (observation.error) return { ok: false, failureClass: 'infrastructure_failure', error: observation.error };
|
|
489
|
+
const evidence = observation.evidence!;
|
|
490
|
+
const reportOk = evidence.status === 'passed';
|
|
491
|
+
if (reportOk !== processOk) {
|
|
492
|
+
return { ok: false, failureClass: 'infrastructure_failure', failureEvidence: evidence, error: 'CHECK_STRUCTURED_RESULT_STATUS_MISMATCH' };
|
|
493
|
+
}
|
|
494
|
+
if (reportOk) return { ok: true, failureEvidence: evidence };
|
|
495
|
+
const sourceOnly = evidence.failureClasses.length > 0 && evidence.failureClasses.every((entry) => entry === 'source');
|
|
496
|
+
return {
|
|
497
|
+
ok: false,
|
|
498
|
+
failureClass: sourceOnly ? 'acceptance_failure' : 'infrastructure_failure',
|
|
499
|
+
failureEvidence: evidence,
|
|
500
|
+
};
|
|
368
501
|
}
|
|
369
502
|
|
|
370
503
|
function artifactSlug(id: string): string {
|
|
371
504
|
return id.toLowerCase().replace(/[^a-z0-9._-]+/g, '-').replace(/^-+|-+$/g, '') || 'check';
|
|
372
505
|
}
|
|
373
506
|
|
|
374
|
-
function evidencePath(
|
|
375
|
-
return join(
|
|
507
|
+
function evidencePath(storage: ResolvedRepositoryCheckStorage, id: string): string {
|
|
508
|
+
return join(storage.physicalRoot, CHECK_EVIDENCE_SUBDIR, `latest-${artifactSlug(id)}.json`);
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
function historicalEvidencePath(storage: ResolvedRepositoryCheckStorage, id: string, cacheKey: string): string {
|
|
512
|
+
return join(storage.physicalRoot, CHECK_EVIDENCE_SUBDIR, artifactSlug(id), `${cacheKey}.json`);
|
|
376
513
|
}
|
|
377
514
|
|
|
378
|
-
function
|
|
379
|
-
return
|
|
515
|
+
function logicalEvidenceArtifactPath(id: string): string {
|
|
516
|
+
return `controller-home://checks/controller/latest-${artifactSlug(id)}.json`;
|
|
380
517
|
}
|
|
381
518
|
|
|
382
519
|
const CHECK_REVISION_EXCLUDES = [
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
'.ai/harness
|
|
387
|
-
'.ai/harness/worktrees/**',
|
|
388
|
-
'.ai/harness/controller/**',
|
|
389
|
-
'.ai/harness/artifacts/**',
|
|
390
|
-
'.ai/harness/local-bridge/**',
|
|
391
|
-
'.ai/harness/ephemeral-issues/**',
|
|
520
|
+
// `.ai/harness` is Forge runtime/check state, not repository source. Checks
|
|
521
|
+
// are allowed to materialize artifacts such as design-system audit reports
|
|
522
|
+
// there; hashing those outputs would make a stable check invalidate itself.
|
|
523
|
+
'.ai/harness/**',
|
|
392
524
|
];
|
|
393
525
|
|
|
394
526
|
function checkRevisionPathspecs(): string[] {
|
|
395
527
|
return ['.', ...CHECK_REVISION_EXCLUDES.map((path) => `:(exclude)${path}`)];
|
|
396
528
|
}
|
|
397
529
|
|
|
398
|
-
|
|
530
|
+
interface ControllerCheckContentObservation {
|
|
531
|
+
revision: string;
|
|
532
|
+
fileDigests?: Map<string, string>;
|
|
533
|
+
listingAvailable: boolean;
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
function observeControllerCheckContent(
|
|
537
|
+
repoRoot: string,
|
|
538
|
+
options: { captureFileDigests?: boolean } = {},
|
|
539
|
+
): ControllerCheckContentObservation {
|
|
399
540
|
const files = runProcess('git', ['ls-files', '--cached', '--others', '--exclude-standard', '-z', '--', ...checkRevisionPathspecs()], {
|
|
400
541
|
cwd: repoRoot,
|
|
401
542
|
timeoutMs: 10_000,
|
|
402
543
|
maxOutputBytes: 8 * 1024 * 1024,
|
|
403
544
|
});
|
|
404
545
|
const revision = createHash('sha256').update('controller-check-content-v2\n');
|
|
405
|
-
|
|
546
|
+
const fileDigests = options.captureFileDigests ? new Map<string, string>() : undefined;
|
|
547
|
+
if (!files.ok) {
|
|
548
|
+
return {
|
|
549
|
+
revision: revision.update(`git-error:${files.error || files.stderr}`).digest('hex').slice(0, 24),
|
|
550
|
+
...(fileDigests ? { fileDigests } : {}),
|
|
551
|
+
listingAvailable: false,
|
|
552
|
+
};
|
|
553
|
+
}
|
|
406
554
|
for (const relativePath of files.stdout.split('\0').filter(Boolean).sort()) {
|
|
407
555
|
if (relativePath.startsWith('tasks/') || relativePath.startsWith('plans/')) continue;
|
|
408
556
|
revision.update(`${relativePath}\0`);
|
|
409
557
|
try {
|
|
410
|
-
|
|
558
|
+
const content = readFileSync(resolve(repoRoot, relativePath));
|
|
559
|
+
revision.update(content);
|
|
560
|
+
fileDigests?.set(relativePath, createHash('sha256').update(content).digest('hex'));
|
|
411
561
|
} catch (_error) {
|
|
412
562
|
revision.update('missing');
|
|
563
|
+
fileDigests?.set(relativePath, 'missing');
|
|
413
564
|
}
|
|
414
565
|
}
|
|
415
|
-
return
|
|
566
|
+
return {
|
|
567
|
+
revision: revision.digest('hex').slice(0, 24),
|
|
568
|
+
...(fileDigests ? { fileDigests } : {}),
|
|
569
|
+
listingAvailable: true,
|
|
570
|
+
};
|
|
571
|
+
}
|
|
572
|
+
|
|
573
|
+
export function currentControllerCheckRevision(repoRoot: string): string {
|
|
574
|
+
return observeControllerCheckContent(repoRoot).revision;
|
|
575
|
+
}
|
|
576
|
+
|
|
577
|
+
function controllerCheckWriteScopeContainsPath(scope: string, relativePath: string): boolean {
|
|
578
|
+
return scope === '.' || relativePath === scope || relativePath.startsWith(`${scope}/`);
|
|
579
|
+
}
|
|
580
|
+
|
|
581
|
+
function controllerCheckInputIntegrityChanged(
|
|
582
|
+
check: ControllerCheck,
|
|
583
|
+
input: ControllerCheckContentObservation,
|
|
584
|
+
completed: ControllerCheckContentObservation,
|
|
585
|
+
): boolean {
|
|
586
|
+
if (!input.listingAvailable || !completed.listingAvailable || !input.fileDigests || !completed.fileDigests) return true;
|
|
587
|
+
const writeScopes = check.effects?.writes ?? [];
|
|
588
|
+
const observedPaths = new Set([...input.fileDigests.keys(), ...completed.fileDigests.keys()]);
|
|
589
|
+
for (const relativePath of observedPaths) {
|
|
590
|
+
if (writeScopes.some((scope) => controllerCheckWriteScopeContainsPath(scope, relativePath))) continue;
|
|
591
|
+
if (input.fileDigests.get(relativePath) !== completed.fileDigests.get(relativePath)) return true;
|
|
592
|
+
}
|
|
593
|
+
return false;
|
|
416
594
|
}
|
|
417
595
|
|
|
418
596
|
function checkDefinitionDigest(check: ControllerCheck): string {
|
|
@@ -423,6 +601,7 @@ function checkDefinitionDigest(check: ControllerCheck): string {
|
|
|
423
601
|
cwd: check.cwd,
|
|
424
602
|
timeoutMs: check.timeoutMs,
|
|
425
603
|
source: check.source,
|
|
604
|
+
executionAuthority: check.executionAuthority ?? 'isolated_controller_home',
|
|
426
605
|
effects: check.effects,
|
|
427
606
|
})).digest('hex');
|
|
428
607
|
}
|
|
@@ -450,6 +629,7 @@ function validateControllerCheckSnapshot(repoRoot: string, snapshot: ControllerC
|
|
|
450
629
|
cwd: normalizeCwd(repoRoot, snapshot.cwd),
|
|
451
630
|
timeoutMs: boundedTimeout(snapshot.timeoutMs),
|
|
452
631
|
source: snapshot.source,
|
|
632
|
+
executionAuthority: snapshot.executionAuthority ?? 'isolated_controller_home',
|
|
453
633
|
effects: normalizeCheckEffects(repoRoot, snapshot.effects),
|
|
454
634
|
selection: normalizeCheckSelection(snapshot.selection, snapshot.id),
|
|
455
635
|
};
|
|
@@ -457,7 +637,72 @@ function validateControllerCheckSnapshot(repoRoot: string, snapshot: ControllerC
|
|
|
457
637
|
|
|
458
638
|
const CONTROLLER_CHECK_EXECUTION_IDENTITY_VERSION = 'controller-check-execution-v2';
|
|
459
639
|
|
|
460
|
-
|
|
640
|
+
/**
|
|
641
|
+
* Bounded live-state identity for certification checks. This is read-only
|
|
642
|
+
* evidence, not lifecycle authority. It includes current release authority and
|
|
643
|
+
* observed Runtime liveness so a dead/replaced Runtime cannot reuse a prior
|
|
644
|
+
* green Stable Baseline receipt merely because its status file remained.
|
|
645
|
+
*/
|
|
646
|
+
export function controllerCheckLiveExecutionStateFingerprint(controllerHome: string, recoveryFenceInstanceId?: string): string {
|
|
647
|
+
const mutationLockPath = recoveryOperationLockPath(controllerHome);
|
|
648
|
+
try {
|
|
649
|
+
const raw = readFileSync(mutationLockPath, 'utf8');
|
|
650
|
+
if (recoveryFenceInstanceId?.trim()) {
|
|
651
|
+
try {
|
|
652
|
+
const owner = JSON.parse(raw) as { instanceId?: unknown };
|
|
653
|
+
if (owner?.instanceId === recoveryFenceInstanceId.trim()) {
|
|
654
|
+
// This check owns the real Recovery mutation fence; its own lock is not drift.
|
|
655
|
+
} else {
|
|
656
|
+
throw new Error('LIVE_CHECK_RECOVERY_MUTATION_IN_PROGRESS');
|
|
657
|
+
}
|
|
658
|
+
} catch (error) {
|
|
659
|
+
if (error instanceof Error && error.message === 'LIVE_CHECK_RECOVERY_MUTATION_IN_PROGRESS') throw error;
|
|
660
|
+
throw new Error('LIVE_CHECK_RECOVERY_MUTATION_STATE_UNREADABLE');
|
|
661
|
+
}
|
|
662
|
+
} else {
|
|
663
|
+
throw new Error('LIVE_CHECK_RECOVERY_MUTATION_IN_PROGRESS');
|
|
664
|
+
}
|
|
665
|
+
} catch (error) {
|
|
666
|
+
if (error instanceof Error && (
|
|
667
|
+
error.message === 'LIVE_CHECK_RECOVERY_MUTATION_IN_PROGRESS'
|
|
668
|
+
|| error.message === 'LIVE_CHECK_RECOVERY_MUTATION_STATE_UNREADABLE'
|
|
669
|
+
)) throw error;
|
|
670
|
+
if ((error as NodeJS.ErrnoException)?.code !== 'ENOENT') {
|
|
671
|
+
throw new Error('LIVE_CHECK_RECOVERY_MUTATION_STATE_UNREADABLE');
|
|
672
|
+
}
|
|
673
|
+
}
|
|
674
|
+
const release = readRuntimeReleaseAuthority(controllerHome);
|
|
675
|
+
const recoveryRelease = readCurrentRecoveryRelease(controllerHome);
|
|
676
|
+
const runtime = observeRuntimeStatus(controllerHome);
|
|
677
|
+
return createHash('sha256')
|
|
678
|
+
.update(JSON.stringify({
|
|
679
|
+
release: release ? {
|
|
680
|
+
revision: release.revision,
|
|
681
|
+
releaseId: release.active.releaseId,
|
|
682
|
+
artifactIdentity: release.active.artifactIdentity,
|
|
683
|
+
manifestSha256: release.active.manifestSha256,
|
|
684
|
+
} : null,
|
|
685
|
+
recoveryRelease: recoveryRelease ? {
|
|
686
|
+
releaseRevision: recoveryRelease.releaseRevision,
|
|
687
|
+
sourceCommit: recoveryRelease.sourceCommit,
|
|
688
|
+
manifestSha256: recoveryRelease.manifestSha256,
|
|
689
|
+
} : null,
|
|
690
|
+
runtime: {
|
|
691
|
+
running: runtime.running,
|
|
692
|
+
ready: runtime.ready,
|
|
693
|
+
stale: runtime.stale,
|
|
694
|
+
reasonCodes: [...runtime.reasonCodes].sort(),
|
|
695
|
+
runtimeInstanceId: runtime.snapshot?.runtimeInstanceId ?? null,
|
|
696
|
+
pid: runtime.snapshot?.pid ?? null,
|
|
697
|
+
releaseId: runtime.snapshot?.releaseId ?? null,
|
|
698
|
+
artifactIdentity: runtime.snapshot?.artifactIdentity ?? null,
|
|
699
|
+
},
|
|
700
|
+
}))
|
|
701
|
+
.digest('hex')
|
|
702
|
+
.slice(0, 24);
|
|
703
|
+
}
|
|
704
|
+
|
|
705
|
+
export function controllerCheckEnvironmentFingerprint(check: ControllerCheck, executionStateFingerprint?: string): string {
|
|
461
706
|
const env = repositoryChildProcessEnvironment(process.env);
|
|
462
707
|
return createHash('sha256')
|
|
463
708
|
.update(JSON.stringify({
|
|
@@ -470,6 +715,8 @@ function checkEnvironmentFingerprint(check: ControllerCheck): string {
|
|
|
470
715
|
// for the parent and forge-check-runner for the sidecar; process.execPath
|
|
471
716
|
// therefore differs even though both execute the exact same check/toolchain.
|
|
472
717
|
commandExecutable: check.command[0],
|
|
718
|
+
executionAuthority: check.executionAuthority ?? 'isolated_controller_home',
|
|
719
|
+
executionStateFingerprint: executionStateFingerprint?.trim() || '',
|
|
473
720
|
path: env.PATH ?? '',
|
|
474
721
|
home: env.HOME ?? env.USERPROFILE ?? '',
|
|
475
722
|
bunInstall: env.BUN_INSTALL ?? '',
|
|
@@ -514,7 +761,7 @@ function buildCheckCacheKey(
|
|
|
514
761
|
timeoutMs: number,
|
|
515
762
|
revision: string,
|
|
516
763
|
definitionDigest = checkDefinitionDigest(check),
|
|
517
|
-
environmentFingerprint =
|
|
764
|
+
environmentFingerprint = controllerCheckEnvironmentFingerprint(check),
|
|
518
765
|
): string {
|
|
519
766
|
return createHash('sha256')
|
|
520
767
|
.update(JSON.stringify({
|
|
@@ -531,11 +778,13 @@ function buildCheckCacheKey(
|
|
|
531
778
|
.slice(0, 24);
|
|
532
779
|
}
|
|
533
780
|
|
|
534
|
-
|
|
781
|
+
function controllerCheckExecutionIdentityForRevision(
|
|
535
782
|
repoRoot: string,
|
|
536
783
|
id: string,
|
|
784
|
+
revision: string,
|
|
537
785
|
requestedTimeoutMs?: number,
|
|
538
786
|
snapshot?: ControllerCheckSnapshot,
|
|
787
|
+
executionStateFingerprint?: string,
|
|
539
788
|
): ControllerCheckExecutionIdentity {
|
|
540
789
|
const check = snapshot
|
|
541
790
|
? validateControllerCheckSnapshot(repoRoot, snapshot)
|
|
@@ -544,9 +793,8 @@ export function controllerCheckExecutionIdentity(
|
|
|
544
793
|
const timeoutMs = requestedTimeoutMs === undefined
|
|
545
794
|
? check.timeoutMs
|
|
546
795
|
: Math.min(check.timeoutMs, boundedTimeout(requestedTimeoutMs));
|
|
547
|
-
const revision = currentControllerCheckRevision(repoRoot);
|
|
548
796
|
const definitionDigest = checkDefinitionDigest(check);
|
|
549
|
-
const environmentFingerprint =
|
|
797
|
+
const environmentFingerprint = controllerCheckEnvironmentFingerprint(check, executionStateFingerprint);
|
|
550
798
|
const checkoutClean = checkWorkspaceClean(repoRoot);
|
|
551
799
|
const crossCheckoutReusable = checkoutClean
|
|
552
800
|
&& checkEffectsAllowCrossCheckoutReuse(check)
|
|
@@ -565,8 +813,25 @@ export function controllerCheckExecutionIdentity(
|
|
|
565
813
|
};
|
|
566
814
|
}
|
|
567
815
|
|
|
568
|
-
function
|
|
816
|
+
export function controllerCheckExecutionIdentity(
|
|
569
817
|
repoRoot: string,
|
|
818
|
+
id: string,
|
|
819
|
+
requestedTimeoutMs?: number,
|
|
820
|
+
snapshot?: ControllerCheckSnapshot,
|
|
821
|
+
executionStateFingerprint?: string,
|
|
822
|
+
): ControllerCheckExecutionIdentity {
|
|
823
|
+
return controllerCheckExecutionIdentityForRevision(
|
|
824
|
+
repoRoot,
|
|
825
|
+
id,
|
|
826
|
+
currentControllerCheckRevision(repoRoot),
|
|
827
|
+
requestedTimeoutMs,
|
|
828
|
+
snapshot,
|
|
829
|
+
executionStateFingerprint,
|
|
830
|
+
);
|
|
831
|
+
}
|
|
832
|
+
|
|
833
|
+
function persistCheckEvidence(
|
|
834
|
+
storage: ResolvedRepositoryCheckStorage,
|
|
570
835
|
result: Omit<ControllerCheckResult, 'artifactPath'>,
|
|
571
836
|
meta: {
|
|
572
837
|
revision?: string;
|
|
@@ -577,7 +842,7 @@ function persistCheckEvidence(
|
|
|
577
842
|
validatedRevision?: string;
|
|
578
843
|
} = {},
|
|
579
844
|
): string {
|
|
580
|
-
const path = evidencePath(
|
|
845
|
+
const path = evidencePath(storage, result.check.id);
|
|
581
846
|
mkdirSync(dirname(path), { recursive: true });
|
|
582
847
|
const evidence: ControllerCheckEvidence = {
|
|
583
848
|
schemaVersion: 2,
|
|
@@ -600,30 +865,40 @@ function persistCheckEvidence(
|
|
|
600
865
|
validatedRevision: meta.validatedRevision,
|
|
601
866
|
originalExecutedAt: result.originalExecutedAt ?? result.executedAt,
|
|
602
867
|
failureClass: result.failureClass,
|
|
868
|
+
failureEvidence: result.failureEvidence,
|
|
603
869
|
};
|
|
604
870
|
const serialized = `${JSON.stringify(evidence, null, 2)}\n`;
|
|
605
871
|
atomicWriteFileSync(path, serialized);
|
|
606
872
|
if (meta.cacheKey) {
|
|
607
|
-
const historicalPath = historicalEvidencePath(
|
|
873
|
+
const historicalPath = historicalEvidencePath(storage, result.check.id, meta.cacheKey);
|
|
608
874
|
mkdirSync(dirname(historicalPath), { recursive: true });
|
|
609
875
|
atomicWriteFileSync(historicalPath, serialized);
|
|
610
876
|
}
|
|
611
|
-
return
|
|
877
|
+
return logicalEvidenceArtifactPath(result.check.id);
|
|
612
878
|
}
|
|
613
879
|
|
|
614
|
-
export function readLatestControllerCheckEvidence(
|
|
615
|
-
|
|
880
|
+
export function readLatestControllerCheckEvidence(
|
|
881
|
+
repoRoot: string,
|
|
882
|
+
id: string,
|
|
883
|
+
storageAuthority?: RepositoryCheckStorageAuthority | ResolvedRepositoryCheckStorage,
|
|
884
|
+
): ControllerCheckEvidence | undefined {
|
|
885
|
+
const storage = storageAuthority && 'physicalRoot' in storageAuthority
|
|
886
|
+
? storageAuthority as ResolvedRepositoryCheckStorage
|
|
887
|
+
: resolveRepositoryCheckStorage(repoRoot, storageAuthority as RepositoryCheckStorageAuthority | undefined);
|
|
888
|
+
const path = evidencePath(storage, id);
|
|
616
889
|
if (!existsSync(path)) return undefined;
|
|
617
890
|
try {
|
|
618
891
|
const value = JSON.parse(readFileSync(path, 'utf-8')) as ControllerCheckEvidence;
|
|
619
|
-
|
|
892
|
+
if (value.schemaVersion !== 2 || value.checkId !== id) return undefined;
|
|
893
|
+
if (value.failureEvidence !== undefined && !isStructuredCheckFailureEvidence(value.failureEvidence)) return undefined;
|
|
894
|
+
return value;
|
|
620
895
|
} catch (_error) {
|
|
621
896
|
return undefined;
|
|
622
897
|
}
|
|
623
898
|
}
|
|
624
899
|
|
|
625
|
-
function readControllerCheckEvidenceByKey(
|
|
626
|
-
const path = historicalEvidencePath(
|
|
900
|
+
function readControllerCheckEvidenceByKey(storage: ResolvedRepositoryCheckStorage, id: string, cacheKey: string): ControllerCheckEvidence | undefined {
|
|
901
|
+
const path = historicalEvidencePath(storage, id, cacheKey);
|
|
627
902
|
if (!existsSync(path)) return undefined;
|
|
628
903
|
try {
|
|
629
904
|
const value = JSON.parse(readFileSync(path, 'utf-8')) as ControllerCheckEvidence;
|
|
@@ -638,16 +913,27 @@ function prepareControllerCheckDependencies(repoRoot: string, check: ControllerC
|
|
|
638
913
|
materializeManagedWorkspaceCheckDependencies(repoRoot);
|
|
639
914
|
}
|
|
640
915
|
|
|
641
|
-
export function runControllerCheck(
|
|
916
|
+
export function runControllerCheck(
|
|
917
|
+
repoRoot: string,
|
|
918
|
+
id: string,
|
|
919
|
+
requestedTimeoutMs?: number,
|
|
920
|
+
snapshot?: ControllerCheckSnapshot,
|
|
921
|
+
storageAuthority?: RepositoryCheckStorageAuthority,
|
|
922
|
+
): ControllerCheckResult {
|
|
642
923
|
const check = snapshot ? validateControllerCheckSnapshot(repoRoot, snapshot) : listControllerChecks(repoRoot).find((entry) => entry.id === id);
|
|
643
924
|
if (!check || check.id !== id) throw new Error(`check not found: ${id}`);
|
|
925
|
+
if (check.executionAuthority === 'live_controller_home') {
|
|
926
|
+
throw new Error('LIVE_CHECK_DURABLE_EXECUTION_REQUIRED');
|
|
927
|
+
}
|
|
928
|
+
const storage = ensureRepositoryCheckStorage(repoRoot, storageAuthority);
|
|
644
929
|
prepareControllerCheckDependencies(repoRoot, check);
|
|
645
|
-
const
|
|
930
|
+
const inputIntegrity = observeControllerCheckContent(repoRoot, { captureFileDigests: true });
|
|
931
|
+
const identity = controllerCheckExecutionIdentityForRevision(repoRoot, id, inputIntegrity.revision, requestedTimeoutMs, snapshot);
|
|
646
932
|
const timeoutMs = identity.timeoutMs;
|
|
647
933
|
const revision = identity.revision;
|
|
648
934
|
const cacheKey = identity.cacheKey;
|
|
649
|
-
const cached = readControllerCheckEvidenceByKey(
|
|
650
|
-
?? readLatestControllerCheckEvidence(repoRoot, id);
|
|
935
|
+
const cached = readControllerCheckEvidenceByKey(storage, id, cacheKey)
|
|
936
|
+
?? readLatestControllerCheckEvidence(repoRoot, id, storage);
|
|
651
937
|
if (cached?.cacheKey === cacheKey && cached.ok) {
|
|
652
938
|
return {
|
|
653
939
|
check,
|
|
@@ -658,20 +944,23 @@ export function runControllerCheck(repoRoot: string, id: string, requestedTimeou
|
|
|
658
944
|
stderr: cached.stderr,
|
|
659
945
|
command: cached.command,
|
|
660
946
|
executedAt: cached.executedAt,
|
|
661
|
-
artifactPath:
|
|
947
|
+
artifactPath: logicalEvidenceArtifactPath(id),
|
|
662
948
|
cacheHit: true,
|
|
663
949
|
validatedRevision: cached.validatedRevision ?? cached.completedRevision ?? cached.revision ?? revision,
|
|
664
950
|
originalExecutedAt: cached.originalExecutedAt ?? cached.executedAt,
|
|
665
951
|
failureClass: cached.failureClass,
|
|
952
|
+
failureEvidence: cached.failureEvidence,
|
|
666
953
|
};
|
|
667
954
|
}
|
|
668
955
|
const heavy = controllerCheckConcurrencyClass(id) === 'heavy';
|
|
669
|
-
const lease = heavy ? tryAcquireHeavyCheckLock(
|
|
956
|
+
const lease = heavy ? tryAcquireHeavyCheckLock(storage, id) : undefined;
|
|
670
957
|
if (heavy && !lease) throw new Error(`heavy check already running for repository: ${id}`);
|
|
958
|
+
const structuredResultPath = structuredCheckResultPath(check);
|
|
671
959
|
let result: ProcessRunResult;
|
|
672
960
|
try {
|
|
673
961
|
const bridgeRuntime = resolveSyncSupervisorBridgeRuntime();
|
|
674
962
|
const childEnvironment = repositoryChildProcessEnvironment();
|
|
963
|
+
if (structuredResultPath) childEnvironment[STRUCTURED_CHECK_RESULT_PATH_ENV] = structuredResultPath;
|
|
675
964
|
delete childEnvironment[CHECK_BRIDGE_RUNTIME_ENV];
|
|
676
965
|
childEnvironment.FORGE_SUPERVISED_REQUEST = Buffer.from(JSON.stringify({
|
|
677
966
|
command: check.command[0],
|
|
@@ -736,17 +1025,23 @@ export function runControllerCheck(repoRoot: string, id: string, requestedTimeou
|
|
|
736
1025
|
} finally {
|
|
737
1026
|
lease?.release();
|
|
738
1027
|
}
|
|
739
|
-
const
|
|
740
|
-
const
|
|
1028
|
+
const structuredObservation = consumeStructuredCheckObservation(check, structuredResultPath);
|
|
1029
|
+
const structuredDecision = applyStructuredCheckObservation(result.ok, structuredObservation);
|
|
1030
|
+
const completedContent = observeControllerCheckContent(repoRoot, { captureFileDigests: true });
|
|
1031
|
+
const completedRevision = completedContent.revision;
|
|
1032
|
+
const stale = controllerCheckInputIntegrityChanged(check, inputIntegrity, completedContent);
|
|
741
1033
|
const executedAt = new Date().toISOString();
|
|
1034
|
+
const effectiveOk = structuredDecision.ok && !stale;
|
|
1035
|
+
const hardInfrastructureFailure = stale || result.timedOut || Boolean(result.error) || Boolean(result.signal);
|
|
742
1036
|
const withoutPath = {
|
|
743
1037
|
check,
|
|
744
|
-
ok:
|
|
745
|
-
status: stale ? 1 : result.status,
|
|
1038
|
+
ok: effectiveOk,
|
|
1039
|
+
status: stale || (!structuredDecision.ok && result.status === 0) ? 1 : result.status,
|
|
746
1040
|
timedOut: result.timedOut,
|
|
747
1041
|
stdout: result.stdout,
|
|
748
1042
|
stderr: [
|
|
749
1043
|
result.stderr || result.error,
|
|
1044
|
+
structuredDecision.error,
|
|
750
1045
|
stale ? 'repository revision changed while the check was running; evidence is stale and the check must be rerun' : '',
|
|
751
1046
|
].filter(Boolean).join('\n'),
|
|
752
1047
|
command: result.command,
|
|
@@ -754,13 +1049,21 @@ export function runControllerCheck(repoRoot: string, id: string, requestedTimeou
|
|
|
754
1049
|
cacheHit: false,
|
|
755
1050
|
validatedRevision: stale ? completedRevision : revision,
|
|
756
1051
|
originalExecutedAt: executedAt,
|
|
757
|
-
failureClass:
|
|
1052
|
+
failureClass: hardInfrastructureFailure
|
|
758
1053
|
? 'infrastructure_failure' as const
|
|
759
|
-
:
|
|
1054
|
+
: structuredDecision.failureClass ?? classifyControllerCheckFailure({
|
|
1055
|
+
ok: effectiveOk,
|
|
1056
|
+
stale,
|
|
1057
|
+
timedOut: result.timedOut,
|
|
1058
|
+
runtimeFailure: Boolean(result.error) || Boolean(result.signal),
|
|
1059
|
+
stdout: result.stdout,
|
|
1060
|
+
stderr: [result.stderr, result.error, structuredDecision.error].filter(Boolean).join('\n'),
|
|
1061
|
+
}),
|
|
1062
|
+
failureEvidence: structuredDecision.failureEvidence,
|
|
760
1063
|
};
|
|
761
1064
|
return {
|
|
762
1065
|
...withoutPath,
|
|
763
|
-
artifactPath: persistCheckEvidence(
|
|
1066
|
+
artifactPath: persistCheckEvidence(storage, withoutPath, {
|
|
764
1067
|
revision,
|
|
765
1068
|
completedRevision,
|
|
766
1069
|
stale,
|
|
@@ -773,6 +1076,11 @@ export function runControllerCheck(repoRoot: string, id: string, requestedTimeou
|
|
|
773
1076
|
|
|
774
1077
|
export interface AsyncControllerCheckOptions {
|
|
775
1078
|
snapshot?: ControllerCheckSnapshot;
|
|
1079
|
+
/** Exact live-state identity supplied by the persisted Work verifier for live certification checks. */
|
|
1080
|
+
executionStateFingerprint?: string;
|
|
1081
|
+
/** Explicit installed Controller Home; never inferred from ambient child environment. */
|
|
1082
|
+
liveControllerHome?: string;
|
|
1083
|
+
storageAuthority?: RepositoryCheckStorageAuthority;
|
|
776
1084
|
/** Explicit isolated authority for Candidate verification child processes. */
|
|
777
1085
|
isolatedControllerHome?: string;
|
|
778
1086
|
requestedTimeoutMs?: number;
|
|
@@ -823,8 +1131,8 @@ interface HeavyCheckLease {
|
|
|
823
1131
|
release(): void;
|
|
824
1132
|
}
|
|
825
1133
|
|
|
826
|
-
function tryAcquireHeavyCheckLock(
|
|
827
|
-
const path = join(
|
|
1134
|
+
function tryAcquireHeavyCheckLock(storage: ResolvedRepositoryCheckStorage, checkId: string): HeavyCheckLease | undefined {
|
|
1135
|
+
const path = join(storage.lockRoot, HEAVY_CHECK_LOCK);
|
|
828
1136
|
mkdirSync(dirname(path), { recursive: true });
|
|
829
1137
|
const lockId = `${process.pid}:${Date.now()}:${checkId}`;
|
|
830
1138
|
const record: HeavyCheckLockRecord = {
|
|
@@ -851,7 +1159,7 @@ function tryAcquireHeavyCheckLock(repoRoot: string, checkId: string): HeavyCheck
|
|
|
851
1159
|
const orphaned = !isProcessAlive(existing?.controllerPid ?? existing?.pid) && !isProcessAlive(existing?.childPid);
|
|
852
1160
|
if (!existing || orphaned) {
|
|
853
1161
|
rmSync(path, { force: true });
|
|
854
|
-
return tryAcquireHeavyCheckLock(
|
|
1162
|
+
return tryAcquireHeavyCheckLock(storage, checkId);
|
|
855
1163
|
}
|
|
856
1164
|
return undefined;
|
|
857
1165
|
}
|
|
@@ -873,10 +1181,10 @@ function tryAcquireHeavyCheckLock(repoRoot: string, checkId: string): HeavyCheck
|
|
|
873
1181
|
};
|
|
874
1182
|
}
|
|
875
1183
|
|
|
876
|
-
async function acquireHeavyCheckLock(
|
|
1184
|
+
async function acquireHeavyCheckLock(storage: ResolvedRepositoryCheckStorage, checkId: string): Promise<HeavyCheckLease> {
|
|
877
1185
|
const deadline = Date.now() + MAX_TIMEOUT_MS * 2;
|
|
878
1186
|
while (true) {
|
|
879
|
-
const lease = tryAcquireHeavyCheckLock(
|
|
1187
|
+
const lease = tryAcquireHeavyCheckLock(storage, checkId);
|
|
880
1188
|
if (lease) return lease;
|
|
881
1189
|
if (Date.now() >= deadline) throw new Error(`timed out waiting for repository heavy-check lock before ${checkId}`);
|
|
882
1190
|
await new Promise((resolvePromise) => setTimeout(resolvePromise, 50));
|
|
@@ -913,13 +1221,19 @@ async function executeControllerCheckAsync(
|
|
|
913
1221
|
repoRoot: string,
|
|
914
1222
|
check: ControllerCheck,
|
|
915
1223
|
timeoutMs: number,
|
|
1224
|
+
storage: ResolvedRepositoryCheckStorage,
|
|
916
1225
|
onSpawn?: (pid: number) => void,
|
|
917
1226
|
isolatedControllerHome?: string,
|
|
1227
|
+
liveControllerHome?: string,
|
|
918
1228
|
): Promise<ControllerCheckResult> {
|
|
919
1229
|
const maxOutputBytes = 256 * 1024;
|
|
920
1230
|
const command = [check.command[0], ...check.command.slice(1)];
|
|
921
1231
|
const childEnvironment = repositoryChildProcessEnvironment();
|
|
922
|
-
|
|
1232
|
+
const structuredResultPath = structuredCheckResultPath(check);
|
|
1233
|
+
if (structuredResultPath) childEnvironment[STRUCTURED_CHECK_RESULT_PATH_ENV] = structuredResultPath;
|
|
1234
|
+
if (isolatedControllerHome?.trim() && liveControllerHome?.trim()) throw new Error('CHECK_CONTROLLER_HOME_AUTHORITY_CONFLICT');
|
|
1235
|
+
if (liveControllerHome?.trim()) childEnvironment.FORGE_CONTROLLER_HOME = resolve(liveControllerHome);
|
|
1236
|
+
else if (isolatedControllerHome?.trim()) childEnvironment.FORGE_CONTROLLER_HOME = resolve(isolatedControllerHome);
|
|
923
1237
|
const supervised = await runBoundedChild(check.command[0], check.command.slice(1), {
|
|
924
1238
|
cwd: resolve(repoRoot, check.cwd),
|
|
925
1239
|
env: childEnvironment,
|
|
@@ -935,19 +1249,34 @@ async function executeControllerCheckAsync(
|
|
|
935
1249
|
const timeoutMessage = supervised.timedOut
|
|
936
1250
|
? `process timed out after ${timeoutMs}ms: ${command.join(' ')}`
|
|
937
1251
|
: '';
|
|
1252
|
+
const processOk = supervised.status === 0 && !supervised.failureCode;
|
|
1253
|
+
const structuredObservation = consumeStructuredCheckObservation(check, structuredResultPath);
|
|
1254
|
+
const structuredDecision = applyStructuredCheckObservation(processOk, structuredObservation);
|
|
1255
|
+
const hardInfrastructureFailure = supervised.timedOut
|
|
1256
|
+
|| Boolean(supervised.failureCode)
|
|
1257
|
+
|| Boolean(supervised.error)
|
|
1258
|
+
|| Boolean(supervised.signal);
|
|
938
1259
|
const result = {
|
|
939
|
-
ok:
|
|
940
|
-
status: supervised.status,
|
|
1260
|
+
ok: structuredDecision.ok,
|
|
1261
|
+
status: !structuredDecision.ok && supervised.status === 0 ? 1 : supervised.status,
|
|
941
1262
|
timedOut: supervised.timedOut,
|
|
942
1263
|
stdout: capProcessOutput(redactProcessOutput(supervised.stdout), maxOutputBytes),
|
|
943
1264
|
stderr: capProcessOutput(redactProcessOutput([
|
|
944
1265
|
supervised.stderr,
|
|
945
1266
|
timeoutMessage || supervised.error || '',
|
|
946
1267
|
processTreeError,
|
|
1268
|
+
structuredDecision.error,
|
|
947
1269
|
].filter(Boolean).join('\n')), maxOutputBytes),
|
|
948
|
-
failureClass:
|
|
1270
|
+
failureClass: hardInfrastructureFailure
|
|
949
1271
|
? 'infrastructure_failure' as const
|
|
950
|
-
:
|
|
1272
|
+
: structuredDecision.failureClass ?? classifyControllerCheckFailure({
|
|
1273
|
+
ok: structuredDecision.ok,
|
|
1274
|
+
timedOut: supervised.timedOut,
|
|
1275
|
+
runtimeFailure: Boolean(supervised.failureCode) || Boolean(supervised.error) || Boolean(supervised.signal),
|
|
1276
|
+
stdout: supervised.stdout,
|
|
1277
|
+
stderr: [supervised.stderr, timeoutMessage, supervised.error, processTreeError, structuredDecision.error].filter(Boolean).join('\n'),
|
|
1278
|
+
}),
|
|
1279
|
+
failureEvidence: structuredDecision.failureEvidence,
|
|
951
1280
|
};
|
|
952
1281
|
|
|
953
1282
|
const executedAt = new Date().toISOString();
|
|
@@ -964,8 +1293,9 @@ async function executeControllerCheckAsync(
|
|
|
964
1293
|
validatedRevision: undefined,
|
|
965
1294
|
originalExecutedAt: executedAt,
|
|
966
1295
|
failureClass: result.failureClass,
|
|
1296
|
+
failureEvidence: result.failureEvidence,
|
|
967
1297
|
};
|
|
968
|
-
return { ...withoutPath, artifactPath:
|
|
1298
|
+
return { ...withoutPath, artifactPath: logicalEvidenceArtifactPath(check.id) };
|
|
969
1299
|
}
|
|
970
1300
|
|
|
971
1301
|
export function runControllerCheckAsync(
|
|
@@ -980,19 +1310,68 @@ export function runControllerCheckAsync(
|
|
|
980
1310
|
return Promise.reject(error);
|
|
981
1311
|
}
|
|
982
1312
|
if (!check || check.id !== id) return Promise.reject(new Error(`check not found: ${id}`));
|
|
1313
|
+
const liveCertification = check.executionAuthority === 'live_controller_home';
|
|
1314
|
+
const liveControllerHome = options.liveControllerHome?.trim();
|
|
1315
|
+
const expectedLiveState = options.executionStateFingerprint?.trim();
|
|
1316
|
+
if (liveCertification) {
|
|
1317
|
+
if (!liveControllerHome || !expectedLiveState) {
|
|
1318
|
+
return Promise.reject(new Error('LIVE_CHECK_EXPLICIT_AUTHORITY_REQUIRED'));
|
|
1319
|
+
}
|
|
1320
|
+
} else if (liveControllerHome) {
|
|
1321
|
+
return Promise.reject(new Error('LIVE_CHECK_AUTHORITY_NOT_DECLARED'));
|
|
1322
|
+
}
|
|
1323
|
+
let storage: ResolvedRepositoryCheckStorage;
|
|
983
1324
|
try {
|
|
1325
|
+
storage = ensureRepositoryCheckStorage(repoRoot, options.storageAuthority);
|
|
984
1326
|
prepareControllerCheckDependencies(repoRoot, check);
|
|
985
1327
|
} catch (error) {
|
|
986
1328
|
return Promise.reject(error);
|
|
987
1329
|
}
|
|
988
|
-
const
|
|
1330
|
+
const inputIntegrity = observeControllerCheckContent(repoRoot, { captureFileDigests: true });
|
|
1331
|
+
const identity = controllerCheckExecutionIdentityForRevision(
|
|
1332
|
+
repoRoot,
|
|
1333
|
+
id,
|
|
1334
|
+
inputIntegrity.revision,
|
|
1335
|
+
options.requestedTimeoutMs,
|
|
1336
|
+
options.snapshot,
|
|
1337
|
+
options.executionStateFingerprint,
|
|
1338
|
+
);
|
|
989
1339
|
const timeoutMs = identity.timeoutMs;
|
|
990
1340
|
const revision = identity.revision;
|
|
991
1341
|
const cacheKey = identity.cacheKey;
|
|
992
|
-
const cached = readControllerCheckEvidenceByKey(
|
|
993
|
-
?? readLatestControllerCheckEvidence(repoRoot, id);
|
|
1342
|
+
const cached = readControllerCheckEvidenceByKey(storage, id, cacheKey)
|
|
1343
|
+
?? readLatestControllerCheckEvidence(repoRoot, id, storage);
|
|
1344
|
+
const withLiveRecoveryFence = async <T>(action: (recoveryFenceInstanceId?: string) => Promise<T> | T): Promise<T> => {
|
|
1345
|
+
if (!liveCertification) return await action(undefined);
|
|
1346
|
+
let attempt;
|
|
1347
|
+
try {
|
|
1348
|
+
attempt = acquireRecoveryOperationLock({
|
|
1349
|
+
controllerHome: liveControllerHome!,
|
|
1350
|
+
action: 'certify_stable_baseline',
|
|
1351
|
+
requestId: `check:${id}:${cacheKey}`,
|
|
1352
|
+
instanceIdPrefix: 'live-certification-',
|
|
1353
|
+
});
|
|
1354
|
+
} catch (error) {
|
|
1355
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
1356
|
+
if (message === 'RECOVERY_OPERATION_LOCK_BUSY') throw new Error('LIVE_CHECK_RECOVERY_MUTATION_IN_PROGRESS');
|
|
1357
|
+
throw new Error(`LIVE_CHECK_RECOVERY_MUTATION_STATE_UNREADABLE: ${message}`);
|
|
1358
|
+
}
|
|
1359
|
+
if (!attempt.acquired) throw new Error('LIVE_CHECK_RECOVERY_MUTATION_IN_PROGRESS');
|
|
1360
|
+
try {
|
|
1361
|
+
const observedLiveState = controllerCheckLiveExecutionStateFingerprint(
|
|
1362
|
+
liveControllerHome!,
|
|
1363
|
+
attempt.handle.record.instanceId,
|
|
1364
|
+
);
|
|
1365
|
+
if (observedLiveState !== expectedLiveState) {
|
|
1366
|
+
throw new Error('LIVE_CHECK_STATE_CHANGED_BEFORE_EXECUTION');
|
|
1367
|
+
}
|
|
1368
|
+
return await action(attempt.handle.record.instanceId);
|
|
1369
|
+
} finally {
|
|
1370
|
+
attempt.handle.close();
|
|
1371
|
+
}
|
|
1372
|
+
};
|
|
994
1373
|
if (cached?.cacheKey === cacheKey && cached.ok) {
|
|
995
|
-
return
|
|
1374
|
+
return withLiveRecoveryFence(() => ({
|
|
996
1375
|
check,
|
|
997
1376
|
ok: cached.ok,
|
|
998
1377
|
status: cached.status,
|
|
@@ -1001,12 +1380,12 @@ export function runControllerCheckAsync(
|
|
|
1001
1380
|
stderr: cached.stderr,
|
|
1002
1381
|
command: cached.command,
|
|
1003
1382
|
executedAt: cached.executedAt,
|
|
1004
|
-
artifactPath:
|
|
1383
|
+
artifactPath: logicalEvidenceArtifactPath(id),
|
|
1005
1384
|
cacheHit: true,
|
|
1006
1385
|
validatedRevision: cached.validatedRevision ?? cached.completedRevision ?? cached.revision ?? revision,
|
|
1007
1386
|
originalExecutedAt: cached.originalExecutedAt ?? cached.executedAt,
|
|
1008
1387
|
failureClass: cached.failureClass,
|
|
1009
|
-
});
|
|
1388
|
+
}));
|
|
1010
1389
|
}
|
|
1011
1390
|
const key = `${resolve(repoRoot)}\u0000${id}\u0000${cacheKey}`;
|
|
1012
1391
|
const existing = activeAsyncChecks.get(key);
|
|
@@ -1052,48 +1431,69 @@ export function runControllerCheckAsync(
|
|
|
1052
1431
|
};
|
|
1053
1432
|
const execute = async (lease?: HeavyCheckLease) => {
|
|
1054
1433
|
assertExecutionStillRequested();
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1434
|
+
return withLiveRecoveryFence(async (recoveryFenceInstanceId) => {
|
|
1435
|
+
assertExecutionStillRequested();
|
|
1436
|
+
const result = await executeControllerCheckAsync(repoRoot, check, timeoutMs, storage, (pid) => {
|
|
1437
|
+
lease?.setChildPid(pid);
|
|
1438
|
+
notifySpawn(pid);
|
|
1439
|
+
}, options.isolatedControllerHome, options.liveControllerHome);
|
|
1440
|
+
const completedContent = observeControllerCheckContent(repoRoot, { captureFileDigests: true });
|
|
1441
|
+
const completedRevision = completedContent.revision;
|
|
1442
|
+
let liveStateStale = false;
|
|
1443
|
+
if (liveCertification) {
|
|
1444
|
+
try {
|
|
1445
|
+
liveStateStale = controllerCheckLiveExecutionStateFingerprint(
|
|
1446
|
+
liveControllerHome!,
|
|
1447
|
+
recoveryFenceInstanceId,
|
|
1448
|
+
) !== expectedLiveState;
|
|
1449
|
+
} catch {
|
|
1450
|
+
liveStateStale = true;
|
|
1451
|
+
}
|
|
1452
|
+
}
|
|
1453
|
+
const repositoryStale = controllerCheckInputIntegrityChanged(check, inputIntegrity, completedContent);
|
|
1454
|
+
const stale = repositoryStale || liveStateStale;
|
|
1455
|
+
const finalized = {
|
|
1456
|
+
...result,
|
|
1457
|
+
...(stale ? {
|
|
1458
|
+
ok: false,
|
|
1459
|
+
status: 1,
|
|
1460
|
+
stderr: [
|
|
1461
|
+
result.stderr,
|
|
1462
|
+
repositoryStale
|
|
1463
|
+
? 'repository revision changed while the check was running; evidence is stale and the check must be rerun'
|
|
1464
|
+
: '',
|
|
1465
|
+
liveStateStale
|
|
1466
|
+
? 'live Runtime/Recovery authority changed while the check was running; evidence is stale and the check must be rerun'
|
|
1467
|
+
: '',
|
|
1468
|
+
].filter(Boolean).join('\n'),
|
|
1469
|
+
failureClass: 'infrastructure_failure' as const,
|
|
1470
|
+
} : {}),
|
|
1471
|
+
cacheHit: false,
|
|
1472
|
+
validatedRevision: stale ? completedRevision : revision,
|
|
1473
|
+
};
|
|
1474
|
+
const { artifactPath: _artifactPath, ...withoutPath } = finalized;
|
|
1475
|
+
const artifactPath = persistCheckEvidence(storage, withoutPath, {
|
|
1476
|
+
revision,
|
|
1477
|
+
completedRevision,
|
|
1478
|
+
stale,
|
|
1479
|
+
cacheKey: stale ? undefined : cacheKey,
|
|
1480
|
+
cacheHit: false,
|
|
1481
|
+
validatedRevision: stale ? completedRevision : revision,
|
|
1482
|
+
});
|
|
1483
|
+
return { ...finalized, artifactPath };
|
|
1083
1484
|
});
|
|
1084
|
-
return { ...finalized, artifactPath };
|
|
1085
1485
|
};
|
|
1086
1486
|
const executeHeavy = async (): Promise<ControllerCheckResult> => {
|
|
1087
1487
|
assertExecutionStillRequested();
|
|
1088
|
-
const lease = await acquireHeavyCheckLock(
|
|
1488
|
+
const lease = await acquireHeavyCheckLock(storage, id);
|
|
1089
1489
|
try {
|
|
1090
1490
|
assertExecutionStillRequested();
|
|
1091
1491
|
const currentRevision = currentControllerCheckRevision(repoRoot);
|
|
1092
1492
|
if (currentRevision !== revision) {
|
|
1093
1493
|
throw new Error(`repository revision changed while heavy check ${id} was queued; resubmit the check`);
|
|
1094
1494
|
}
|
|
1095
|
-
const refreshed = readControllerCheckEvidenceByKey(
|
|
1096
|
-
?? readLatestControllerCheckEvidence(repoRoot, id);
|
|
1495
|
+
const refreshed = readControllerCheckEvidenceByKey(storage, id, cacheKey)
|
|
1496
|
+
?? readLatestControllerCheckEvidence(repoRoot, id, storage);
|
|
1097
1497
|
if (refreshed?.cacheKey === cacheKey && refreshed.ok) {
|
|
1098
1498
|
return {
|
|
1099
1499
|
check,
|
|
@@ -1104,7 +1504,7 @@ export function runControllerCheckAsync(
|
|
|
1104
1504
|
stderr: refreshed.stderr,
|
|
1105
1505
|
command: refreshed.command,
|
|
1106
1506
|
executedAt: refreshed.executedAt,
|
|
1107
|
-
artifactPath:
|
|
1507
|
+
artifactPath: logicalEvidenceArtifactPath(id),
|
|
1108
1508
|
cacheHit: true,
|
|
1109
1509
|
validatedRevision: refreshed.validatedRevision ?? refreshed.completedRevision ?? refreshed.revision ?? revision,
|
|
1110
1510
|
originalExecutedAt: refreshed.originalExecutedAt ?? refreshed.executedAt,
|