@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,18 +1,20 @@
|
|
|
1
1
|
import { existsSync, lstatSync, mkdirSync, readdirSync, readFileSync, renameSync, rmSync, writeFileSync } from 'fs';
|
|
2
2
|
import { basename, dirname, join, relative, resolve } from 'path';
|
|
3
3
|
import { tmpdir } from 'os';
|
|
4
|
+
import { assertStorageHeadroom } from '../shared/storage-capacity';
|
|
4
5
|
import { runProcess } from '../../effects/process-runner';
|
|
5
|
-
import { cleanupEditSession, getEditSession, listEditSessions
|
|
6
|
+
import { cleanupEditSession, getEditSession, listEditSessions } from '../../cli/editing/edit-session';
|
|
6
7
|
import { ensureRepositoryRuntimeStorage, type RepositoryRuntimeStorageReport } from '../../cli/repositories/runtime-storage';
|
|
8
|
+
import { getRepository, selectRepositoryCheckout, setRepositoryCheckoutLifecycle } from '../../cli/repositories/registry';
|
|
7
9
|
import type { RepositoryRecord } from '../../cli/repositories/types';
|
|
8
10
|
import { rebuildRepositoryProjection } from '../projections/materialized-view';
|
|
9
|
-
import { getWorkContract, readWorkContractStore,
|
|
10
|
-
import {
|
|
11
|
+
import { getWorkContract, readWorkContractStore, semanticWorkState, updateWorkContract } from '../../../packages/kernel/work/api/index';
|
|
12
|
+
import { assertOwnedResourceCleanupTarget, listOwnedResources, markOwnedResourceCleaned, type OwnedResource } from '../../../packages/kernel/identity/api/index';
|
|
11
13
|
import { listPlanContracts } from '../control-plane/facade/plan-contract-store';
|
|
12
14
|
import { readRequirement } from '../control-plane/persistence/requirement-store';
|
|
13
15
|
import { listControlPlaneRecords, type ControlPlaneRecord } from '../control-plane/persistence/sqlite-store';
|
|
14
|
-
import {
|
|
15
|
-
import { listSchedules } from '
|
|
16
|
+
import type { WorkContract } from '../control-plane/facade/types';
|
|
17
|
+
import { listSchedules } from '../../../packages/kernel/scheduler/api/index';
|
|
16
18
|
import {
|
|
17
19
|
collectRuntimeProcesses,
|
|
18
20
|
removeRuntimeTempEntry,
|
|
@@ -26,6 +28,19 @@ import {
|
|
|
26
28
|
type RuntimeStorageRepairPreview,
|
|
27
29
|
} from './local-jobs-repair';
|
|
28
30
|
import { gcTerminalProcesses, type ProcessGcResult } from '../execution/process-runtime/gc';
|
|
31
|
+
import { cleanupStaleWorkVerificationSnapshots, type WorkVerificationSnapshotRetentionReport } from '../control-plane/execution/work-verification-snapshot';
|
|
32
|
+
import { cleanupGeneratedRepositoryCheckoutCaches, type RepositoryGeneratedCacheRetentionReport } from '../control-plane/generated-cache-retention';
|
|
33
|
+
import { cleanupWorkPreservationArtifacts, type CleanupArtifactRetentionReport } from '../control-plane/cleanup-artifact-retention';
|
|
34
|
+
import {
|
|
35
|
+
cleanupRuntimeQuarantine,
|
|
36
|
+
quarantineRuntimePath,
|
|
37
|
+
runtimeLegacyCheckQuarantineRoot,
|
|
38
|
+
type RuntimeQuarantineRetentionReport,
|
|
39
|
+
} from './quarantine-retention';
|
|
40
|
+
import { readWorkHandle, resolveWorkDeliveryTargetBranch } from '../control-plane/execution/work-handle-store';
|
|
41
|
+
import { listRecoverableProcessRecords } from '../execution/process-runtime/store';
|
|
42
|
+
import { isManagedProcessActive } from '../execution/process-runtime/types';
|
|
43
|
+
import { managedBranchOwnedResourceId, managedBranchOwnedResourceLocator, managedWorkspaceOwnedResourceId } from '../execution/managed-workspace';
|
|
29
44
|
|
|
30
45
|
export type RuntimeMaintenanceActionId =
|
|
31
46
|
| 'local_jobs_reconcile'
|
|
@@ -137,6 +152,10 @@ export interface RuntimeMaintenanceApplyResult extends Omit<RuntimeMaintenanceSt
|
|
|
137
152
|
runtimeStorageRepairApply?: RuntimeStorageRepairApplyResult;
|
|
138
153
|
/** Existing bounded terminal-process retention, run only during explicit full maintenance. */
|
|
139
154
|
processGc?: ProcessGcResult;
|
|
155
|
+
verificationSnapshotGc?: WorkVerificationSnapshotRetentionReport;
|
|
156
|
+
quarantineGc?: RuntimeQuarantineRetentionReport;
|
|
157
|
+
generatedCacheGc?: RepositoryGeneratedCacheRetentionReport;
|
|
158
|
+
cleanupArtifactGc?: CleanupArtifactRetentionReport;
|
|
140
159
|
projection?: unknown;
|
|
141
160
|
}
|
|
142
161
|
|
|
@@ -189,10 +208,16 @@ function readJson(path: string): unknown {
|
|
|
189
208
|
}
|
|
190
209
|
|
|
191
210
|
function writeJsonAtomic(path: string, value: unknown): void {
|
|
211
|
+
const content = `${JSON.stringify(value, null, 2)}\n`;
|
|
212
|
+
assertStorageHeadroom(path, {
|
|
213
|
+
operation: 'runtime_maintenance_state_write',
|
|
214
|
+
requiredBytes: Buffer.byteLength(content),
|
|
215
|
+
reserveBytes: 16 * 1024 * 1024,
|
|
216
|
+
});
|
|
192
217
|
mkdirSync(dirname(path), { recursive: true });
|
|
193
218
|
const temporaryPath = `${path}.${process.pid}.${Date.now()}.tmp`;
|
|
194
219
|
try {
|
|
195
|
-
writeFileSync(temporaryPath,
|
|
220
|
+
writeFileSync(temporaryPath, content, { encoding: 'utf8', mode: 0o600 });
|
|
196
221
|
renameSync(temporaryPath, path);
|
|
197
222
|
} finally {
|
|
198
223
|
rmSync(temporaryPath, { force: true });
|
|
@@ -385,7 +410,11 @@ function scanRuntimeTempCandidates(
|
|
|
385
410
|
minAgeMinutes: RUNTIME_TEMP_RETENTION_MINUTES,
|
|
386
411
|
maxEntries: Math.max(maxCandidates * 3, 500),
|
|
387
412
|
});
|
|
388
|
-
|
|
413
|
+
// scanRuntimeTempEntries is the mechanical temp-ownership fence: it only
|
|
414
|
+
// returns direct Forge-prefixed children of the approved temp roots, and
|
|
415
|
+
// removeRuntimeTempEntry revalidates root/name/symlink/age/process occupancy
|
|
416
|
+
// immediately before mutation. Explicit roots narrow scope; they do not create
|
|
417
|
+
// a second ownership authority.
|
|
389
418
|
return scan.entries
|
|
390
419
|
.filter((entry) => entry.cleanupCandidate)
|
|
391
420
|
.slice(0, maxCandidates)
|
|
@@ -393,17 +422,15 @@ function scanRuntimeTempCandidates(
|
|
|
393
422
|
kind: 'stale_runtime_temp_entry',
|
|
394
423
|
id: `runtime-temp-${safeId(entry.path)}`,
|
|
395
424
|
path: entry.path,
|
|
396
|
-
safe: entry.cleanupCandidate
|
|
397
|
-
reason:
|
|
398
|
-
? '
|
|
399
|
-
: entry.
|
|
400
|
-
?
|
|
401
|
-
: entry.
|
|
402
|
-
? `Temp entry is referenced by live process ${entry.occupiedByPid}.`
|
|
403
|
-
: `Forge temp entry is unoccupied, not a symbolic link, and ${entry.ageMinutes} minute(s) old.`,
|
|
425
|
+
safe: entry.cleanupCandidate,
|
|
426
|
+
reason: entry.symbolicLink
|
|
427
|
+
? 'Symbolic links are never eligible for automatic cleanup.'
|
|
428
|
+
: entry.occupiedByPid
|
|
429
|
+
? `Temp entry is referenced by live process ${entry.occupiedByPid}.`
|
|
430
|
+
: `Forge temp entry is unoccupied, not a symbolic link, and ${entry.ageMinutes} minute(s) old.`,
|
|
404
431
|
ageMinutes: entry.ageMinutes,
|
|
405
432
|
suggestedAction: 'full_maintenance_pass',
|
|
406
|
-
ownershipStatus,
|
|
433
|
+
ownershipStatus: 'explicit' as const,
|
|
407
434
|
}));
|
|
408
435
|
}
|
|
409
436
|
|
|
@@ -444,7 +471,7 @@ function listRetainedMigratedWork(destinationHomeInput: string, repoId: string):
|
|
|
444
471
|
}
|
|
445
472
|
for (const source of sourceWork) {
|
|
446
473
|
const work = source.value;
|
|
447
|
-
if (work.repoId !== repoId ||
|
|
474
|
+
if (work.repoId !== repoId || semanticWorkState(work) === 'open') continue;
|
|
448
475
|
if (!work.worktreeRef?.trim() || !existsSync(work.worktreeRef)) continue;
|
|
449
476
|
if (destinationWorkIds.has(work.workId)) continue;
|
|
450
477
|
retained.push({ migrationId: migration.migrationId, sourceHome, work });
|
|
@@ -477,6 +504,121 @@ function looksLikeForgeManagedWorktree(path: string): boolean {
|
|
|
477
504
|
|
|
478
505
|
type StaleWorkSourceState = NonNullable<RuntimeMaintenanceCandidate['sourceState']>;
|
|
479
506
|
|
|
507
|
+
interface OwnedManagedWorktreeInspection {
|
|
508
|
+
safe: boolean;
|
|
509
|
+
path: string;
|
|
510
|
+
sourceState: StaleWorkSourceState;
|
|
511
|
+
detail: string;
|
|
512
|
+
workspaceResourceId?: string;
|
|
513
|
+
checkoutId?: string;
|
|
514
|
+
branch?: string;
|
|
515
|
+
canonicalBranch?: string;
|
|
516
|
+
}
|
|
517
|
+
|
|
518
|
+
function activeOwnedWorktreeResource(
|
|
519
|
+
controllerHome: string,
|
|
520
|
+
repoId: string,
|
|
521
|
+
path: string,
|
|
522
|
+
): OwnedResource | undefined {
|
|
523
|
+
const target = resolve(path);
|
|
524
|
+
return listOwnedResources(controllerHome, { kind: 'worktree', status: 'active', repoId })
|
|
525
|
+
.find((resource) => resource.cleanupCapable === true && resolve(resource.targetRef) === target);
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
function inspectOwnedManagedWorktree(
|
|
529
|
+
repository: RuntimeMaintenanceRepository,
|
|
530
|
+
controllerHome: string,
|
|
531
|
+
pathInput: string,
|
|
532
|
+
): OwnedManagedWorktreeInspection {
|
|
533
|
+
const path = resolve(pathInput);
|
|
534
|
+
if (!looksLikeForgeManagedWorktree(path)) {
|
|
535
|
+
return { safe: false, path, sourceState: 'source_state_unknown', detail: 'Managed worktree is outside Forge-managed storage; automatic cleanup is forbidden.' };
|
|
536
|
+
}
|
|
537
|
+
if (!existsSync(path)) {
|
|
538
|
+
return { safe: false, path, sourceState: 'source_state_unknown', detail: 'Owned managed worktree path is absent; registry/resource reconciliation is required before cleanup.' };
|
|
539
|
+
}
|
|
540
|
+
const workspaceResource = activeOwnedWorktreeResource(controllerHome, repository.repoId, path);
|
|
541
|
+
if (!workspaceResource) {
|
|
542
|
+
return { safe: false, path, sourceState: 'source_state_unknown', detail: 'No active cleanup-capable OwnedResource matches this managed worktree path.' };
|
|
543
|
+
}
|
|
544
|
+
try {
|
|
545
|
+
assertOwnedResourceCleanupTarget(controllerHome, {
|
|
546
|
+
resourceId: workspaceResource.resourceId,
|
|
547
|
+
kind: 'worktree',
|
|
548
|
+
targetRef: path,
|
|
549
|
+
});
|
|
550
|
+
} catch (error) {
|
|
551
|
+
return { safe: false, path, sourceState: 'source_state_unknown', detail: `Managed worktree OwnedResource failed exact identity validation: ${error instanceof Error ? error.message : String(error)}` };
|
|
552
|
+
}
|
|
553
|
+
const contractOwner = readWorkContractStore({ controllerHome, repoId: repository.repoId }).contracts.find((contract) =>
|
|
554
|
+
contract.worktreeRef && resolve(contract.worktreeRef) === path);
|
|
555
|
+
if (contractOwner) {
|
|
556
|
+
return { safe: false, path, sourceState: 'source_state_unknown', detail: `Managed worktree still has WorkContract owner ${contractOwner.workId}; cleanup must remain with that Work lifecycle.` };
|
|
557
|
+
}
|
|
558
|
+
let registered;
|
|
559
|
+
try { registered = getRepository(repository.repoId, controllerHome, { includeRemoved: true }); } catch (error) {
|
|
560
|
+
return { safe: false, path, sourceState: 'source_state_unknown', detail: `Repository registry could not be read for owned managed worktree: ${error instanceof Error ? error.message : String(error)}` };
|
|
561
|
+
}
|
|
562
|
+
const checkout = registered.checkouts.find((candidate) =>
|
|
563
|
+
candidate.worktree === true
|
|
564
|
+
&& (candidate.lifecycle ?? 'active') === 'active'
|
|
565
|
+
&& (resolve(candidate.canonicalRoot) === path || resolve(candidate.localRoot) === path));
|
|
566
|
+
if (!checkout) {
|
|
567
|
+
return { safe: false, path, sourceState: 'source_state_unknown', detail: 'Owned managed worktree has no active matching Repository Registry checkout.' };
|
|
568
|
+
}
|
|
569
|
+
if (registered.activeCheckoutId === checkout.checkoutId) {
|
|
570
|
+
return { safe: false, path, sourceState: 'source_state_unknown', detail: 'Owned managed worktree is unexpectedly the canonical active checkout; automatic cleanup is forbidden.' };
|
|
571
|
+
}
|
|
572
|
+
const status = runProcess('git', ['status', '--porcelain', '--untracked-files=all'], { cwd: path, timeoutMs: 10_000, maxOutputBytes: 500_000 });
|
|
573
|
+
if (!status.ok) {
|
|
574
|
+
return { safe: false, path, sourceState: 'source_state_unknown', detail: 'Owned managed worktree status could not be read.' };
|
|
575
|
+
}
|
|
576
|
+
if (status.stdout.trim()) {
|
|
577
|
+
return { safe: false, path, sourceState: 'dirty_worktree', detail: 'Owned managed worktree is dirty; unique source must be preserved.' };
|
|
578
|
+
}
|
|
579
|
+
const head = runProcess('git', ['rev-parse', 'HEAD'], { cwd: path, timeoutMs: 10_000, maxOutputBytes: 100_000 });
|
|
580
|
+
const branch = runProcess('git', ['branch', '--show-current'], { cwd: path, timeoutMs: 10_000, maxOutputBytes: 100_000 });
|
|
581
|
+
if (!head.ok || !head.stdout.trim() || !branch.ok || !branch.stdout.trim()) {
|
|
582
|
+
return { safe: false, path, sourceState: 'source_state_unknown', detail: 'Owned managed worktree HEAD/branch identity could not be resolved.' };
|
|
583
|
+
}
|
|
584
|
+
const branchName = branch.stdout.trim();
|
|
585
|
+
if (checkout.branch?.trim() && checkout.branch.trim() !== branchName) {
|
|
586
|
+
return { safe: false, path, sourceState: 'source_state_unknown', detail: 'Owned managed worktree branch no longer matches its Repository Registry checkout identity.' };
|
|
587
|
+
}
|
|
588
|
+
let canonical;
|
|
589
|
+
try { canonical = selectRepositoryCheckout(registered, registered.activeCheckoutId); } catch (error) {
|
|
590
|
+
return { safe: false, path, sourceState: 'source_state_unknown', detail: `Canonical repository checkout could not be resolved: ${error instanceof Error ? error.message : String(error)}` };
|
|
591
|
+
}
|
|
592
|
+
const canonicalBranch = runProcess('git', ['branch', '--show-current'], { cwd: canonical.canonicalRoot, timeoutMs: 10_000, maxOutputBytes: 100_000 });
|
|
593
|
+
if (!canonicalBranch.ok || !canonicalBranch.stdout.trim()) {
|
|
594
|
+
return { safe: false, path, sourceState: 'source_state_unknown', detail: 'Canonical integration branch could not be resolved for owned managed-worktree cleanup.' };
|
|
595
|
+
}
|
|
596
|
+
const canonicalBranchName = canonicalBranch.stdout.trim();
|
|
597
|
+
const contained = runProcess('git', ['merge-base', '--is-ancestor', head.stdout.trim(), `refs/heads/${canonicalBranchName}`], {
|
|
598
|
+
cwd: canonical.canonicalRoot,
|
|
599
|
+
timeoutMs: 10_000,
|
|
600
|
+
maxOutputBytes: 100_000,
|
|
601
|
+
});
|
|
602
|
+
if (!contained.ok) {
|
|
603
|
+
return {
|
|
604
|
+
safe: false,
|
|
605
|
+
path,
|
|
606
|
+
sourceState: 'unintegrated_commits',
|
|
607
|
+
detail: `Owned managed worktree HEAD ${head.stdout.trim()} is not contained in canonical branch ${canonicalBranchName}; source preservation remains required.`,
|
|
608
|
+
};
|
|
609
|
+
}
|
|
610
|
+
return {
|
|
611
|
+
safe: true,
|
|
612
|
+
path,
|
|
613
|
+
sourceState: 'clean_integrated',
|
|
614
|
+
workspaceResourceId: workspaceResource.resourceId,
|
|
615
|
+
checkoutId: checkout.checkoutId,
|
|
616
|
+
branch: branchName,
|
|
617
|
+
canonicalBranch: canonicalBranchName,
|
|
618
|
+
detail: `Canonical OwnedResource proves cleanup authority for a clean managed worktree whose HEAD ${head.stdout.trim()} is already contained in canonical branch ${canonicalBranchName}.`,
|
|
619
|
+
};
|
|
620
|
+
}
|
|
621
|
+
|
|
480
622
|
interface StaleWorkSourceInspection {
|
|
481
623
|
safeToCancel: boolean;
|
|
482
624
|
state: StaleWorkSourceState;
|
|
@@ -484,10 +626,116 @@ interface StaleWorkSourceInspection {
|
|
|
484
626
|
detail: string;
|
|
485
627
|
}
|
|
486
628
|
|
|
629
|
+
interface StaleWorkDeliveryTargetResolution {
|
|
630
|
+
targetBranch: string;
|
|
631
|
+
handle?: NonNullable<ReturnType<typeof readWorkHandle>>;
|
|
632
|
+
identityMismatch: boolean;
|
|
633
|
+
}
|
|
634
|
+
|
|
635
|
+
function resolveStaleWorkDeliveryTarget(
|
|
636
|
+
repository: RuntimeMaintenanceRepository,
|
|
637
|
+
controllerHome: string,
|
|
638
|
+
contract: WorkContract,
|
|
639
|
+
): StaleWorkDeliveryTargetResolution {
|
|
640
|
+
const handle = readWorkHandle(controllerHome, repository.repoId, contract.workId);
|
|
641
|
+
if (!handle) {
|
|
642
|
+
return { targetBranch: repository.defaultBranch?.trim() || 'main', identityMismatch: false };
|
|
643
|
+
}
|
|
644
|
+
if (!contract.checkoutId || handle.checkoutId !== contract.checkoutId) {
|
|
645
|
+
return {
|
|
646
|
+
targetBranch: repository.defaultBranch?.trim() || 'main',
|
|
647
|
+
handle,
|
|
648
|
+
identityMismatch: true,
|
|
649
|
+
};
|
|
650
|
+
}
|
|
651
|
+
return {
|
|
652
|
+
targetBranch: resolveWorkDeliveryTargetBranch(handle, repository.defaultBranch),
|
|
653
|
+
handle,
|
|
654
|
+
identityMismatch: false,
|
|
655
|
+
};
|
|
656
|
+
}
|
|
657
|
+
|
|
658
|
+
function isLegacyImplicitRemoteEffectPlacement(contract: WorkContract): boolean {
|
|
659
|
+
if (contract.workKind !== 'remote_effect' || contract.worktreePolicy.required !== true || !contract.worktreeRef || !contract.checkoutId) return false;
|
|
660
|
+
const reason = contract.worktreePolicy.reason?.trim() ?? '';
|
|
661
|
+
if (/Typed placement/i.test(reason)) return false;
|
|
662
|
+
return true;
|
|
663
|
+
}
|
|
664
|
+
|
|
665
|
+
interface LegacyRemoteEffectPlacementInspection {
|
|
666
|
+
safe: boolean;
|
|
667
|
+
path?: string;
|
|
668
|
+
detail: string;
|
|
669
|
+
checkoutId?: string;
|
|
670
|
+
canonicalCheckoutId?: string;
|
|
671
|
+
branch?: string;
|
|
672
|
+
canonicalBranch?: string;
|
|
673
|
+
}
|
|
674
|
+
|
|
675
|
+
function inspectLegacyRemoteEffectPlacement(
|
|
676
|
+
repository: RuntimeMaintenanceRepository,
|
|
677
|
+
controllerHome: string,
|
|
678
|
+
contract: WorkContract,
|
|
679
|
+
): LegacyRemoteEffectPlacementInspection | undefined {
|
|
680
|
+
if (!isLegacyImplicitRemoteEffectPlacement(contract)) return undefined;
|
|
681
|
+
const recordedPath = contract.worktreeRef?.trim();
|
|
682
|
+
if (!recordedPath) return undefined;
|
|
683
|
+
const path = resolve(recordedPath);
|
|
684
|
+
if (!looksLikeForgeManagedWorktree(path)) return { safe: false, path, detail: 'Legacy remote_effect placement is outside Forge-managed worktree storage; automatic resource detachment is forbidden.' };
|
|
685
|
+
if (readWorkHandle(controllerHome, repository.repoId, contract.workId)) return { safe: false, path, detail: 'Legacy remote_effect placement unexpectedly has a WorkHandle; repository source authority must be reconciled explicitly.' };
|
|
686
|
+
let registered;
|
|
687
|
+
try { registered = getRepository(repository.repoId, controllerHome, { includeRemoved: true }); } catch (error) {
|
|
688
|
+
return { safe: false, path, detail: `Repository registry could not be read for legacy remote_effect placement: ${error instanceof Error ? error.message : String(error)}` };
|
|
689
|
+
}
|
|
690
|
+
const checkout = registered.checkouts.find((candidate) => candidate.checkoutId === contract.checkoutId);
|
|
691
|
+
if (!checkout) return { safe: false, path, detail: 'Legacy remote_effect checkout identity is missing from the Repository Registry.' };
|
|
692
|
+
if ((checkout.lifecycle ?? 'active') !== 'active' || checkout.worktree !== true) return { safe: false, path, detail: `Legacy remote_effect checkout ${checkout.checkoutId} is not an active registered worktree.` };
|
|
693
|
+
const registeredPath = resolve(checkout.canonicalRoot);
|
|
694
|
+
if (registeredPath !== path && resolve(checkout.localRoot) !== path) return { safe: false, path, detail: 'Legacy remote_effect WorkContract path does not match its registered checkout identity.' };
|
|
695
|
+
const otherOwner = readWorkContractStore({ controllerHome, repoId: repository.repoId }).contracts.find((candidate) =>
|
|
696
|
+
candidate.workId !== contract.workId
|
|
697
|
+
&& semanticWorkState(candidate) === 'open'
|
|
698
|
+
&& candidate.worktreeRef
|
|
699
|
+
&& resolve(candidate.worktreeRef) === path);
|
|
700
|
+
if (otherOwner) return { safe: false, path, detail: `Managed worktree is also owned by active Work ${otherOwner.workId}; resource detachment is fenced.` };
|
|
701
|
+
if (!existsSync(path)) return { safe: false, path, detail: 'Legacy remote_effect managed worktree path is absent; registry/source reconciliation is required before detachment.' };
|
|
702
|
+
const status = runProcess('git', ['status', '--porcelain', '--untracked-files=all'], { cwd: path, timeoutMs: 10_000, maxOutputBytes: 500_000 });
|
|
703
|
+
if (!status.ok || status.stdout.trim()) return { safe: false, path, detail: status.ok ? 'Legacy remote_effect managed worktree is dirty; live source must be preserved.' : 'Legacy remote_effect managed worktree status could not be read.' };
|
|
704
|
+
const head = runProcess('git', ['rev-parse', 'HEAD'], { cwd: path, timeoutMs: 10_000, maxOutputBytes: 100_000 });
|
|
705
|
+
const baseRevision = contract.baseRevision?.trim();
|
|
706
|
+
if (!head.ok || !head.stdout.trim() || !baseRevision || head.stdout.trim() !== baseRevision) return { safe: false, path, detail: 'Legacy remote_effect worktree HEAD does not exactly equal the Work base revision; repository delta ownership is ambiguous.' };
|
|
707
|
+
const branch = runProcess('git', ['branch', '--show-current'], { cwd: path, timeoutMs: 10_000, maxOutputBytes: 100_000 });
|
|
708
|
+
if (!branch.ok || !branch.stdout.trim()) return { safe: false, path, detail: 'Legacy remote_effect managed worktree branch could not be resolved.' };
|
|
709
|
+
let canonical;
|
|
710
|
+
try { canonical = selectRepositoryCheckout(registered, registered.activeCheckoutId); } catch (error) {
|
|
711
|
+
return { safe: false, path, detail: `Canonical repository checkout could not be resolved: ${error instanceof Error ? error.message : String(error)}` };
|
|
712
|
+
}
|
|
713
|
+
if (canonical.activeCheckoutId === checkout.checkoutId) return { safe: false, path, detail: 'Legacy remote_effect placement unexpectedly points at the canonical active checkout; automatic detachment is forbidden.' };
|
|
714
|
+
const canonicalBranch = runProcess('git', ['branch', '--show-current'], { cwd: canonical.canonicalRoot, timeoutMs: 10_000, maxOutputBytes: 100_000 });
|
|
715
|
+
if (!canonicalBranch.ok || !canonicalBranch.stdout.trim()) return { safe: false, path, detail: 'Canonical integration branch could not be resolved for legacy remote_effect detachment.' };
|
|
716
|
+
const contained = runProcess('git', ['merge-base', '--is-ancestor', baseRevision, `refs/heads/${canonicalBranch.stdout.trim()}`], { cwd: canonical.canonicalRoot, timeoutMs: 10_000, maxOutputBytes: 100_000 });
|
|
717
|
+
if (!contained.ok) return { safe: false, path, detail: `Legacy remote_effect base revision ${baseRevision} is not contained in canonical branch ${canonicalBranch.stdout.trim()}; source preservation remains required.` };
|
|
718
|
+
return {
|
|
719
|
+
safe: true, path, checkoutId: checkout.checkoutId, canonicalCheckoutId: canonical.activeCheckoutId,
|
|
720
|
+
branch: branch.stdout.trim(), canonicalBranch: canonicalBranch.stdout.trim(),
|
|
721
|
+
detail: `Legacy remote_effect owns a clean no-delta managed worktree at base revision ${baseRevision}, which is already contained in canonical branch ${canonicalBranch.stdout.trim()}; repository placement may be detached without changing Work semantics.`,
|
|
722
|
+
};
|
|
723
|
+
}
|
|
724
|
+
|
|
487
725
|
function inspectStaleWorkRepositorySource(
|
|
488
726
|
repository: RuntimeMaintenanceRepository,
|
|
727
|
+
controllerHome: string,
|
|
489
728
|
contract: WorkContract,
|
|
490
729
|
): StaleWorkSourceInspection {
|
|
730
|
+
const legacyRemoteEffect = inspectLegacyRemoteEffectPlacement(repository, controllerHome, contract);
|
|
731
|
+
if (legacyRemoteEffect) {
|
|
732
|
+
return {
|
|
733
|
+
safeToCancel: legacyRemoteEffect.safe,
|
|
734
|
+
state: legacyRemoteEffect.safe ? 'clean_integrated' : 'source_state_unknown',
|
|
735
|
+
path: legacyRemoteEffect.path,
|
|
736
|
+
detail: legacyRemoteEffect.detail,
|
|
737
|
+
};
|
|
738
|
+
}
|
|
491
739
|
const recordedPath = contract.worktreeRef?.trim();
|
|
492
740
|
if (!recordedPath) {
|
|
493
741
|
return {
|
|
@@ -506,11 +754,62 @@ function inspectStaleWorkRepositorySource(
|
|
|
506
754
|
};
|
|
507
755
|
}
|
|
508
756
|
if (!existsSync(path)) {
|
|
757
|
+
const deliveryTarget = resolveStaleWorkDeliveryTarget(repository, controllerHome, contract);
|
|
758
|
+
const handle = deliveryTarget.handle;
|
|
759
|
+
const expectedHead = handle?.expectedHead?.trim();
|
|
760
|
+
if (deliveryTarget.identityMismatch || !handle || !expectedHead) {
|
|
761
|
+
return {
|
|
762
|
+
safeToCancel: false,
|
|
763
|
+
state: 'source_state_unknown',
|
|
764
|
+
path,
|
|
765
|
+
detail: 'Recorded managed worktree path is absent and no identity-matched durable WorkHandle head can prove source preservation; destructive stale-Work cancellation is fenced.',
|
|
766
|
+
};
|
|
767
|
+
}
|
|
768
|
+
const targetBranch = deliveryTarget.targetBranch;
|
|
769
|
+
const head = runProcess('git', ['rev-parse', '--verify', `${expectedHead}^{commit}`], {
|
|
770
|
+
cwd: repository.canonicalRoot,
|
|
771
|
+
timeoutMs: 10_000,
|
|
772
|
+
maxOutputBytes: 100_000,
|
|
773
|
+
});
|
|
774
|
+
const target = runProcess('git', ['rev-parse', '--verify', `refs/heads/${targetBranch}`], {
|
|
775
|
+
cwd: repository.canonicalRoot,
|
|
776
|
+
timeoutMs: 10_000,
|
|
777
|
+
maxOutputBytes: 100_000,
|
|
778
|
+
});
|
|
779
|
+
if (!head.ok || !head.stdout.trim() || !target.ok || !target.stdout.trim()) {
|
|
780
|
+
return {
|
|
781
|
+
safeToCancel: false,
|
|
782
|
+
state: 'source_state_unknown',
|
|
783
|
+
path,
|
|
784
|
+
detail: `Recorded managed worktree path is absent and durable source head/target ${targetBranch} could not be resolved; destructive stale-Work cancellation is fenced.`,
|
|
785
|
+
};
|
|
786
|
+
}
|
|
787
|
+
const unique = runProcess('git', ['rev-list', '--count', `${target.stdout.trim()}..${head.stdout.trim()}`], {
|
|
788
|
+
cwd: repository.canonicalRoot,
|
|
789
|
+
timeoutMs: 10_000,
|
|
790
|
+
maxOutputBytes: 100_000,
|
|
791
|
+
});
|
|
792
|
+
if (!unique.ok || !/^\d+$/.test(unique.stdout.trim())) {
|
|
793
|
+
return {
|
|
794
|
+
safeToCancel: false,
|
|
795
|
+
state: 'source_state_unknown',
|
|
796
|
+
path,
|
|
797
|
+
detail: 'Durable WorkHandle source head could not be compared with its delivery target; destructive stale-Work cancellation is fenced.',
|
|
798
|
+
};
|
|
799
|
+
}
|
|
800
|
+
if (Number(unique.stdout.trim()) > 0) {
|
|
801
|
+
return {
|
|
802
|
+
safeToCancel: false,
|
|
803
|
+
state: 'unintegrated_commits',
|
|
804
|
+
path,
|
|
805
|
+
detail: `Managed worktree is absent, but durable WorkHandle head ${expectedHead} has ${unique.stdout.trim()} commit(s) not reachable from ${targetBranch}; exact source remains preserved in Git and requires explicit adoption or cleanup authority.`,
|
|
806
|
+
};
|
|
807
|
+
}
|
|
509
808
|
return {
|
|
510
|
-
safeToCancel:
|
|
511
|
-
state: '
|
|
809
|
+
safeToCancel: true,
|
|
810
|
+
state: 'clean_integrated',
|
|
512
811
|
path,
|
|
513
|
-
detail:
|
|
812
|
+
detail: `Managed worktree is absent, but its identity-matched durable WorkHandle head ${expectedHead} is already reachable from ${targetBranch}; no unique source is being discarded.`,
|
|
514
813
|
};
|
|
515
814
|
}
|
|
516
815
|
|
|
@@ -541,7 +840,16 @@ function inspectStaleWorkRepositorySource(
|
|
|
541
840
|
timeoutMs: 10_000,
|
|
542
841
|
maxOutputBytes: 100_000,
|
|
543
842
|
});
|
|
544
|
-
const
|
|
843
|
+
const deliveryTarget = resolveStaleWorkDeliveryTarget(repository, controllerHome, contract);
|
|
844
|
+
if (deliveryTarget.identityMismatch) {
|
|
845
|
+
return {
|
|
846
|
+
safeToCancel: false,
|
|
847
|
+
state: 'source_state_unknown',
|
|
848
|
+
path,
|
|
849
|
+
detail: 'Managed worktree has a durable WorkHandle whose checkout identity does not match the WorkContract; source containment cannot be proven against that handle and destructive stale-Work cancellation is fenced.',
|
|
850
|
+
};
|
|
851
|
+
}
|
|
852
|
+
const targetBranch = deliveryTarget.targetBranch;
|
|
545
853
|
const target = runProcess('git', ['rev-parse', '--verify', `refs/heads/${targetBranch}`], {
|
|
546
854
|
cwd: repository.canonicalRoot,
|
|
547
855
|
timeoutMs: 10_000,
|
|
@@ -584,20 +892,11 @@ function inspectStaleWorkRepositorySource(
|
|
|
584
892
|
};
|
|
585
893
|
}
|
|
586
894
|
|
|
587
|
-
function
|
|
588
|
-
if (contract.phase !== 'cleanup') return false;
|
|
589
|
-
return (['implementation', 'verification', 'delivery'] as const).every((phase) =>
|
|
590
|
-
['satisfied', 'skipped'].includes(contract.phaseEvidence[phase].state));
|
|
591
|
-
}
|
|
592
|
-
|
|
593
|
-
function staleWorkCandidateReason(source: StaleWorkSourceInspection, semanticReady: boolean): string {
|
|
895
|
+
function staleWorkCandidateReason(source: StaleWorkSourceInspection): string {
|
|
594
896
|
if (!source.safeToCancel) {
|
|
595
|
-
return `Protected stale Work:
|
|
596
|
-
}
|
|
597
|
-
if (!semanticReady) {
|
|
598
|
-
return `Protected stale Work: repository source has no unique live changes, but the Work semantic lifecycle has not reached cleanup with implementation, verification, and delivery explicitly satisfied or skipped. ${source.detail} Maintenance may clean source debt, but it cannot infer that the objective or acceptance criteria are complete.`;
|
|
897
|
+
return `Protected stale Work: repository source preservation is required. ${source.detail} Maintenance may reconcile only concrete owned resources; semantic Work remains model/user-owned.`;
|
|
599
898
|
}
|
|
600
|
-
return `
|
|
899
|
+
return `Observed stale Work: repository source has no unique live changes, but liveness/legacy phase facts do not authorize semantic cancellation or completion. ${source.detail} Use explicit Work semantic CAS to close the Work.`;
|
|
601
900
|
}
|
|
602
901
|
|
|
603
902
|
function scanRetainedWorktreeCandidates(
|
|
@@ -624,12 +923,12 @@ function scanRetainedWorktreeCandidates(
|
|
|
624
923
|
if (normalized === resolve(repository.canonicalRoot) || currentOwnedPaths.has(normalized)) continue;
|
|
625
924
|
const migrated = retainedByPath.get(normalized);
|
|
626
925
|
if (migrated) {
|
|
627
|
-
const completed = migrated.work
|
|
926
|
+
const completed = semanticWorkState(migrated.work) === 'completed';
|
|
628
927
|
candidates.push({
|
|
629
928
|
kind: 'retained_migrated_work',
|
|
630
929
|
id: migrated.work.workId,
|
|
631
930
|
path: normalized,
|
|
632
|
-
status: migrated.work.
|
|
931
|
+
status: migrated.work.semanticState,
|
|
633
932
|
safe: false,
|
|
634
933
|
reason: completed
|
|
635
934
|
? 'A terminal Work from a retired Controller Home still owns a Git worktree and requires completion/cleanup reconciliation under the current Controller before lifecycle health can be reported.'
|
|
@@ -644,12 +943,28 @@ function scanRetainedWorktreeCandidates(
|
|
|
644
943
|
continue;
|
|
645
944
|
}
|
|
646
945
|
if (!looksLikeForgeManagedWorktree(normalized)) continue;
|
|
946
|
+
const ownedResource = activeOwnedWorktreeResource(controllerHome, repository.repoId, normalized);
|
|
947
|
+
if (ownedResource) {
|
|
948
|
+
const inspection = inspectOwnedManagedWorktree(repository, controllerHome, normalized);
|
|
949
|
+
candidates.push({
|
|
950
|
+
kind: 'unowned_managed_worktree',
|
|
951
|
+
id: `managed-worktree:${basename(normalized)}`,
|
|
952
|
+
path: normalized,
|
|
953
|
+
safe: inspection.safe,
|
|
954
|
+
reason: inspection.detail,
|
|
955
|
+
suggestedAction: 'full_maintenance_pass',
|
|
956
|
+
ownershipStatus: 'explicit',
|
|
957
|
+
sourceState: inspection.sourceState,
|
|
958
|
+
disposition: inspection.safe ? undefined : 'source_preservation_required',
|
|
959
|
+
});
|
|
960
|
+
continue;
|
|
961
|
+
}
|
|
647
962
|
candidates.push({
|
|
648
963
|
kind: 'unowned_managed_worktree',
|
|
649
964
|
id: `managed-worktree:${basename(normalized)}`,
|
|
650
965
|
path: normalized,
|
|
651
966
|
safe: false,
|
|
652
|
-
reason: 'Git reports a Forge-managed worktree for this repository, but the current
|
|
967
|
+
reason: 'Git reports a Forge-managed worktree for this repository, but neither the current Work store, retained migration state, nor canonical OwnedResource authority owns it. Ownership must be reconciled before lifecycle health can be reported.',
|
|
653
968
|
suggestedAction: 'full_maintenance_pass',
|
|
654
969
|
ownershipStatus: 'unknown',
|
|
655
970
|
disposition: 'ownership_reconciliation',
|
|
@@ -673,12 +988,12 @@ function scanRetainedWorktreeCandidates(
|
|
|
673
988
|
// path outside current Git inventory only remains lifecycle debt when its
|
|
674
989
|
// worktree .git marker still exists for manual reconciliation.
|
|
675
990
|
if (!existsSync(join(normalized, '.git'))) continue;
|
|
676
|
-
const completed = migrated.work
|
|
991
|
+
const completed = semanticWorkState(migrated.work) === 'completed';
|
|
677
992
|
candidates.push({
|
|
678
993
|
kind: 'retained_migrated_work',
|
|
679
994
|
id: migrated.work.workId,
|
|
680
995
|
path: normalized,
|
|
681
|
-
status: migrated.work.
|
|
996
|
+
status: migrated.work.semanticState,
|
|
682
997
|
safe: false,
|
|
683
998
|
reason: 'A terminal Work retained by a migrated Controller Home still has preserved filesystem state, but Git no longer reports it as a registered worktree. Manual lifecycle reconciliation is required; automatic cleanup is forbidden.',
|
|
684
999
|
suggestedAction: 'full_maintenance_pass',
|
|
@@ -701,26 +1016,65 @@ function normalizedOptions(options: RuntimeMaintenanceOptions = {}): Required<Ru
|
|
|
701
1016
|
};
|
|
702
1017
|
}
|
|
703
1018
|
|
|
704
|
-
|
|
1019
|
+
interface RuntimeMaintenanceAuthoritySnapshot {
|
|
1020
|
+
contracts: WorkContract[];
|
|
1021
|
+
workById: Map<string, WorkContract>;
|
|
1022
|
+
planByWorkId: Map<string, string>;
|
|
1023
|
+
activeRequirementStateById: Map<string, string>;
|
|
1024
|
+
scheduleByWorkId: Map<string, string>;
|
|
1025
|
+
processByWorkId: Map<string, string>;
|
|
1026
|
+
}
|
|
1027
|
+
|
|
1028
|
+
/**
|
|
1029
|
+
* Build one bounded read snapshot for a maintenance status pass. Discovery must
|
|
1030
|
+
* never turn N candidate Works/EditSessions into N full Plan/Schedule/Process
|
|
1031
|
+
* scans. Process liveness comes from Process Runtime's recovery index instead of
|
|
1032
|
+
* enumerating terminal process history. This snapshot is advisory only; mutation
|
|
1033
|
+
* paths still re-read current authority before terminalization.
|
|
1034
|
+
*/
|
|
1035
|
+
function buildRuntimeMaintenanceAuthoritySnapshot(
|
|
705
1036
|
repository: RuntimeMaintenanceRepository,
|
|
706
1037
|
controllerHome: string,
|
|
707
|
-
|
|
708
|
-
|
|
1038
|
+
): RuntimeMaintenanceAuthoritySnapshot {
|
|
1039
|
+
const contracts = readWorkContractStore({ controllerHome, repoId: repository.repoId }).contracts;
|
|
1040
|
+
const workById = new Map(contracts.map((contract) => [contract.workId, contract]));
|
|
1041
|
+
const planByWorkId = new Map<string, string>();
|
|
1042
|
+
for (const plan of listPlanContracts({ controllerHome, repoId: repository.repoId, status: 'active', limit: 100 })) {
|
|
1043
|
+
for (const step of plan.steps) if (step.workId) planByWorkId.set(step.workId, plan.planId);
|
|
1044
|
+
if (plan.planId) {
|
|
1045
|
+
for (const contract of contracts) if (contract.planId === plan.planId) planByWorkId.set(contract.workId, plan.planId);
|
|
1046
|
+
}
|
|
1047
|
+
}
|
|
1048
|
+
const activeRequirementStateById = new Map<string, string>();
|
|
1049
|
+
for (const requirementId of new Set(contracts.flatMap((contract) => contract.requirementId ? [contract.requirementId] : []))) {
|
|
1050
|
+
const requirement = readRequirement({ controllerHome }, requirementId)?.value;
|
|
1051
|
+
if (requirement && !['done', 'cancelled'].includes(requirement.state)) activeRequirementStateById.set(requirementId, requirement.state);
|
|
1052
|
+
}
|
|
1053
|
+
const scheduleByWorkId = new Map<string, string>();
|
|
1054
|
+
for (const schedule of listSchedules(controllerHome, repository.repoId)) {
|
|
1055
|
+
if (!schedule.enabled) continue;
|
|
1056
|
+
const workId = String((schedule.action.arguments as Record<string, unknown> | undefined)?.work_id ?? '').trim();
|
|
1057
|
+
if (workId && !scheduleByWorkId.has(workId)) scheduleByWorkId.set(workId, schedule.scheduleId);
|
|
1058
|
+
}
|
|
1059
|
+
const processByWorkId = new Map<string, string>();
|
|
1060
|
+
for (const process of listRecoverableProcessRecords(controllerHome, repository.repoId)) {
|
|
1061
|
+
if (process.workId && isManagedProcessActive(process) && !processByWorkId.has(process.workId)) processByWorkId.set(process.workId, process.processId);
|
|
1062
|
+
}
|
|
1063
|
+
return { contracts, workById, planByWorkId, activeRequirementStateById, scheduleByWorkId, processByWorkId };
|
|
1064
|
+
}
|
|
1065
|
+
|
|
1066
|
+
function activeWorkAuthorityRefs(contract: WorkContract, snapshot: RuntimeMaintenanceAuthoritySnapshot): string[] {
|
|
709
1067
|
const refs: string[] = [];
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
const plan = activePlans.find((candidate) => candidate.planId === contract.planId || candidate.steps.some((step) => step.workId === contract.workId));
|
|
713
|
-
if (plan) refs.push(`plan:${plan.planId}`);
|
|
1068
|
+
const planId = snapshot.planByWorkId.get(contract.workId);
|
|
1069
|
+
if (planId) refs.push(`plan:${planId}`);
|
|
714
1070
|
if (contract.requirementId) {
|
|
715
|
-
const
|
|
716
|
-
if (
|
|
1071
|
+
const state = snapshot.activeRequirementStateById.get(contract.requirementId);
|
|
1072
|
+
if (state) refs.push(`requirement:${contract.requirementId}:${state}`);
|
|
717
1073
|
}
|
|
718
|
-
const
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
});
|
|
723
|
-
if (boundSchedule) refs.push(`schedule:${boundSchedule.scheduleId}`);
|
|
1074
|
+
const scheduleId = snapshot.scheduleByWorkId.get(contract.workId);
|
|
1075
|
+
if (scheduleId) refs.push(`schedule:${scheduleId}`);
|
|
1076
|
+
const processId = snapshot.processByWorkId.get(contract.workId);
|
|
1077
|
+
if (processId) refs.push(`process:${processId}`);
|
|
724
1078
|
return refs;
|
|
725
1079
|
}
|
|
726
1080
|
|
|
@@ -728,170 +1082,305 @@ function scanStaleWorkContractCandidates(
|
|
|
728
1082
|
repository: RuntimeMaintenanceRepository,
|
|
729
1083
|
controllerHome: string,
|
|
730
1084
|
options: Required<RuntimeMaintenanceOptions>,
|
|
1085
|
+
snapshot: RuntimeMaintenanceAuthoritySnapshot,
|
|
731
1086
|
): RuntimeMaintenanceCandidate[] {
|
|
732
1087
|
const nowMs = Date.now();
|
|
733
|
-
return
|
|
734
|
-
.filter((contract) =>
|
|
1088
|
+
return snapshot.contracts
|
|
1089
|
+
.filter((contract) => semanticWorkState(contract) === 'open')
|
|
735
1090
|
.map((contract) => {
|
|
736
1091
|
const updatedMs = Date.parse(contract.updatedAt);
|
|
737
1092
|
const ageMinutes = Number.isFinite(updatedMs) ? Math.max(0, Math.floor((nowMs - updatedMs) / 60_000)) : 0;
|
|
738
1093
|
return { contract, ageMinutes };
|
|
739
1094
|
})
|
|
740
1095
|
.filter(({ ageMinutes }) => ageMinutes >= options.minAgeMinutes)
|
|
741
|
-
.
|
|
742
|
-
|
|
743
|
-
//
|
|
744
|
-
|
|
745
|
-
// if it later becomes unowned, the next scan will surface it as stale.
|
|
746
|
-
if (authorityRefs.length > 0) return [];
|
|
747
|
-
return [{ contract, ageMinutes, source: inspectStaleWorkRepositorySource(repository, contract) }];
|
|
1096
|
+
.filter(({ contract }) => {
|
|
1097
|
+
// A live Plan/Requirement/Schedule/Process reference is retained migration authority,
|
|
1098
|
+
// not maintenance debt. The authority inventory was read once for this status pass.
|
|
1099
|
+
return activeWorkAuthorityRefs(contract, snapshot).length === 0;
|
|
748
1100
|
})
|
|
749
1101
|
.sort((left, right) => right.ageMinutes - left.ageMinutes)
|
|
1102
|
+
// Expensive Git source inspection belongs after the visible candidate budget.
|
|
750
1103
|
.slice(0, options.maxCandidates)
|
|
1104
|
+
.map(({ contract, ageMinutes }) => ({
|
|
1105
|
+
contract, ageMinutes, source: inspectStaleWorkRepositorySource(repository, controllerHome, contract),
|
|
1106
|
+
}))
|
|
751
1107
|
.map(({ contract, ageMinutes, source }) => {
|
|
752
|
-
const
|
|
1108
|
+
const legacyRemotePlacement = isLegacyImplicitRemoteEffectPlacement(contract);
|
|
753
1109
|
return {
|
|
754
1110
|
kind: 'stale_work_contract' as const,
|
|
755
1111
|
id: contract.workId,
|
|
756
1112
|
path: source.path,
|
|
757
|
-
status: contract.
|
|
758
|
-
safe: source.safeToCancel
|
|
759
|
-
reason: staleWorkCandidateReason(source
|
|
1113
|
+
status: contract.semanticState,
|
|
1114
|
+
safe: legacyRemotePlacement ? source.safeToCancel : false,
|
|
1115
|
+
reason: legacyRemotePlacement ? source.detail : staleWorkCandidateReason(source),
|
|
760
1116
|
ageMinutes,
|
|
761
1117
|
suggestedAction: 'full_maintenance_pass' as const,
|
|
762
1118
|
ownershipStatus: 'explicit' as const,
|
|
763
1119
|
sourceState: source.state,
|
|
764
1120
|
disposition: !source.safeToCancel
|
|
765
1121
|
? ('source_preservation_required' as const)
|
|
766
|
-
: !
|
|
1122
|
+
: !legacyRemotePlacement
|
|
767
1123
|
? ('semantic_completion_required' as const)
|
|
768
1124
|
: undefined,
|
|
769
1125
|
};
|
|
770
1126
|
});
|
|
771
1127
|
}
|
|
772
1128
|
|
|
773
|
-
|
|
1129
|
+
function detachLegacyRemoteEffectPlacement(
|
|
774
1130
|
repository: RuntimeMaintenanceRepository,
|
|
775
1131
|
controllerHome: string,
|
|
1132
|
+
current: WorkContract,
|
|
776
1133
|
candidate: RuntimeMaintenanceCandidate,
|
|
777
1134
|
): RuntimeMaintenanceCandidate & { applied: boolean; result: string } {
|
|
778
|
-
const
|
|
779
|
-
if (!
|
|
780
|
-
return { ...candidate, applied: false, result: '
|
|
1135
|
+
const inspection = inspectLegacyRemoteEffectPlacement(repository, controllerHome, current);
|
|
1136
|
+
if (!inspection || !inspection.safe || !inspection.path || !inspection.checkoutId || !inspection.canonicalCheckoutId || !inspection.branch || !inspection.canonicalBranch) {
|
|
1137
|
+
return { ...candidate, safe: false, reason: inspection?.detail ?? 'Legacy remote_effect placement is no longer eligible for resource detachment.', sourceState: 'source_state_unknown', disposition: 'source_preservation_required', applied: false, result: 'legacy_remote_effect_placement_preserved' };
|
|
781
1138
|
}
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
1139
|
+
const store = { controllerHome, repoId: repository.repoId };
|
|
1140
|
+
try {
|
|
1141
|
+
assertOwnedResourceCleanupTarget(controllerHome, {
|
|
1142
|
+
resourceId: managedWorkspaceOwnedResourceId(repository.repoId, inspection.checkoutId),
|
|
1143
|
+
kind: 'worktree',
|
|
1144
|
+
targetRef: inspection.path,
|
|
1145
|
+
});
|
|
1146
|
+
} catch (error) {
|
|
1147
|
+
return {
|
|
1148
|
+
...candidate,
|
|
1149
|
+
safe: false,
|
|
1150
|
+
reason: `Canonical OwnedResource authority is required before legacy worktree detachment: ${error instanceof Error ? error.message : String(error)}`,
|
|
1151
|
+
sourceState: 'source_state_unknown',
|
|
1152
|
+
disposition: 'source_preservation_required',
|
|
1153
|
+
applied: false,
|
|
1154
|
+
result: 'legacy_remote_effect_owned_resource_required',
|
|
1155
|
+
};
|
|
1156
|
+
}
|
|
1157
|
+
const previous = { checkoutId: current.checkoutId, worktreeRef: current.worktreeRef, constraints: current.constraints, worktreePolicy: current.worktreePolicy };
|
|
1158
|
+
updateWorkContract(store, current.workId, {
|
|
1159
|
+
checkoutId: inspection.canonicalCheckoutId,
|
|
1160
|
+
worktreeRef: undefined,
|
|
1161
|
+
constraints: { ...current.constraints, workspaceMode: 'current' },
|
|
1162
|
+
worktreePolicy: { required: false, reason: 'Legacy pure remote_effect repository placement detached by explicit runtime maintenance; external-effect execution has no repository source authority.' },
|
|
1163
|
+
});
|
|
1164
|
+
try {
|
|
1165
|
+
setRepositoryCheckoutLifecycle({ controllerHome, repoId: repository.repoId, checkoutId: inspection.checkoutId, lifecycle: 'removed', reason: `Legacy remote_effect placement detached for ${current.workId}.` });
|
|
1166
|
+
const removed = runProcess('git', ['worktree', 'remove', '--force', inspection.path], { cwd: repository.canonicalRoot, timeoutMs: 60_000, maxOutputBytes: 500_000 });
|
|
1167
|
+
if (!removed.ok && existsSync(inspection.path)) throw new Error(`LEGACY_REMOTE_EFFECT_WORKTREE_REMOVE_FAILED: ${removed.stderr || removed.stdout}`);
|
|
1168
|
+
markOwnedResourceCleaned(controllerHome, managedWorkspaceOwnedResourceId(repository.repoId, inspection.checkoutId), 'forge:legacy-remote-effect-detach');
|
|
1169
|
+
if (inspection.branch !== inspection.canonicalBranch) {
|
|
1170
|
+
try {
|
|
1171
|
+
assertOwnedResourceCleanupTarget(controllerHome, {
|
|
1172
|
+
resourceId: managedBranchOwnedResourceId(repository.repoId, inspection.checkoutId),
|
|
1173
|
+
kind: 'git_branch',
|
|
1174
|
+
targetRef: inspection.branch,
|
|
1175
|
+
locator: managedBranchOwnedResourceLocator(repository.canonicalRoot, inspection.checkoutId, inspection.branch),
|
|
1176
|
+
});
|
|
1177
|
+
} catch {
|
|
1178
|
+
return { ...candidate, safe: true, reason: inspection.detail, sourceState: 'clean_integrated', disposition: undefined, applied: true, result: `legacy_remote_effect_placement_detached_branch_retained:${inspection.branch}` };
|
|
1179
|
+
}
|
|
1180
|
+
const deleted = runProcess('git', ['branch', '--delete', inspection.branch], { cwd: repository.canonicalRoot, timeoutMs: 10_000, maxOutputBytes: 100_000 });
|
|
1181
|
+
if (!deleted.ok) {
|
|
1182
|
+
const forced = runProcess('git', ['branch', '--delete', '--force', inspection.branch], { cwd: repository.canonicalRoot, timeoutMs: 10_000, maxOutputBytes: 100_000 });
|
|
1183
|
+
if (!forced.ok) return { ...candidate, safe: true, reason: inspection.detail, sourceState: 'clean_integrated', disposition: undefined, applied: true, result: `legacy_remote_effect_placement_detached_branch_retained:${inspection.branch}` };
|
|
795
1184
|
}
|
|
796
|
-
|
|
797
|
-
|
|
1185
|
+
markOwnedResourceCleaned(controllerHome, managedBranchOwnedResourceId(repository.repoId, inspection.checkoutId), 'forge:legacy-remote-effect-detach');
|
|
1186
|
+
}
|
|
1187
|
+
return { ...candidate, safe: true, reason: inspection.detail, sourceState: 'clean_integrated', disposition: undefined, applied: true, result: 'legacy_remote_effect_placement_detached' };
|
|
1188
|
+
} catch (error) {
|
|
1189
|
+
if (existsSync(inspection.path)) {
|
|
1190
|
+
try { setRepositoryCheckoutLifecycle({ controllerHome, repoId: repository.repoId, checkoutId: inspection.checkoutId, lifecycle: 'active', reason: `Rollback failed legacy remote_effect detach for ${current.workId}.` }); } catch { /* preserve primary failure */ }
|
|
1191
|
+
try { updateWorkContract(store, current.workId, previous); } catch { /* preserve primary failure */ }
|
|
1192
|
+
}
|
|
1193
|
+
throw error;
|
|
1194
|
+
}
|
|
1195
|
+
}
|
|
1196
|
+
|
|
1197
|
+
function detachOwnedManagedWorktree(
|
|
1198
|
+
repository: RuntimeMaintenanceRepository,
|
|
1199
|
+
controllerHome: string,
|
|
1200
|
+
candidate: RuntimeMaintenanceCandidate,
|
|
1201
|
+
): RuntimeMaintenanceCandidate & { applied: boolean; result: string } {
|
|
1202
|
+
if (!candidate.path) return { ...candidate, applied: false, result: 'owned_managed_worktree_path_missing' };
|
|
1203
|
+
const inspection = inspectOwnedManagedWorktree(repository, controllerHome, candidate.path);
|
|
1204
|
+
if (!inspection.safe || !inspection.workspaceResourceId || !inspection.checkoutId || !inspection.branch || !inspection.canonicalBranch) {
|
|
1205
|
+
return {
|
|
1206
|
+
...candidate,
|
|
1207
|
+
safe: false,
|
|
1208
|
+
reason: inspection.detail,
|
|
1209
|
+
sourceState: inspection.sourceState,
|
|
1210
|
+
disposition: 'source_preservation_required',
|
|
1211
|
+
applied: false,
|
|
1212
|
+
result: 'owned_managed_worktree_preserved',
|
|
1213
|
+
};
|
|
1214
|
+
}
|
|
1215
|
+
try {
|
|
1216
|
+
setRepositoryCheckoutLifecycle({
|
|
1217
|
+
controllerHome,
|
|
1218
|
+
repoId: repository.repoId,
|
|
1219
|
+
checkoutId: inspection.checkoutId,
|
|
1220
|
+
lifecycle: 'removed',
|
|
1221
|
+
reason: 'Canonical OwnedResource cleanup reconciled a WorkContract-less managed worktree whose source is already integrated.',
|
|
1222
|
+
});
|
|
1223
|
+
const removed = runProcess('git', ['worktree', 'remove', '--force', inspection.path], {
|
|
1224
|
+
cwd: repository.canonicalRoot,
|
|
1225
|
+
timeoutMs: 60_000,
|
|
1226
|
+
maxOutputBytes: 500_000,
|
|
1227
|
+
});
|
|
1228
|
+
if (!removed.ok && existsSync(inspection.path)) {
|
|
1229
|
+
throw new Error(`OWNED_MANAGED_WORKTREE_REMOVE_FAILED: ${removed.stderr || removed.stdout}`);
|
|
1230
|
+
}
|
|
1231
|
+
markOwnedResourceCleaned(controllerHome, inspection.workspaceResourceId, 'forge:runtime-maintenance-owned-worktree');
|
|
1232
|
+
if (inspection.branch !== inspection.canonicalBranch) {
|
|
1233
|
+
try {
|
|
1234
|
+
assertOwnedResourceCleanupTarget(controllerHome, {
|
|
1235
|
+
resourceId: managedBranchOwnedResourceId(repository.repoId, inspection.checkoutId),
|
|
1236
|
+
kind: 'git_branch',
|
|
1237
|
+
targetRef: inspection.branch,
|
|
1238
|
+
locator: managedBranchOwnedResourceLocator(repository.canonicalRoot, inspection.checkoutId, inspection.branch),
|
|
1239
|
+
});
|
|
1240
|
+
} catch {
|
|
798
1241
|
return {
|
|
799
1242
|
...candidate,
|
|
800
|
-
|
|
801
|
-
|
|
1243
|
+
safe: true,
|
|
1244
|
+
reason: inspection.detail,
|
|
1245
|
+
sourceState: 'clean_integrated',
|
|
1246
|
+
disposition: undefined,
|
|
1247
|
+
applied: true,
|
|
1248
|
+
result: `owned_managed_worktree_detached_branch_retained:${inspection.branch}`,
|
|
802
1249
|
};
|
|
803
1250
|
}
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
if (!
|
|
1251
|
+
const deleted = runProcess('git', ['branch', '--delete', inspection.branch], {
|
|
1252
|
+
cwd: repository.canonicalRoot,
|
|
1253
|
+
timeoutMs: 10_000,
|
|
1254
|
+
maxOutputBytes: 100_000,
|
|
1255
|
+
});
|
|
1256
|
+
if (!deleted.ok) {
|
|
1257
|
+
const forced = runProcess('git', ['branch', '--delete', '--force', inspection.branch], {
|
|
1258
|
+
cwd: repository.canonicalRoot,
|
|
1259
|
+
timeoutMs: 10_000,
|
|
1260
|
+
maxOutputBytes: 100_000,
|
|
1261
|
+
});
|
|
1262
|
+
if (!forced.ok) {
|
|
1263
|
+
return {
|
|
1264
|
+
...candidate,
|
|
1265
|
+
safe: true,
|
|
1266
|
+
reason: inspection.detail,
|
|
1267
|
+
sourceState: 'clean_integrated',
|
|
1268
|
+
disposition: undefined,
|
|
1269
|
+
applied: true,
|
|
1270
|
+
result: `owned_managed_worktree_detached_branch_retained:${inspection.branch}`,
|
|
1271
|
+
};
|
|
1272
|
+
}
|
|
1273
|
+
}
|
|
1274
|
+
markOwnedResourceCleaned(
|
|
1275
|
+
controllerHome,
|
|
1276
|
+
managedBranchOwnedResourceId(repository.repoId, inspection.checkoutId),
|
|
1277
|
+
'forge:runtime-maintenance-owned-worktree',
|
|
1278
|
+
);
|
|
1279
|
+
}
|
|
1280
|
+
return {
|
|
1281
|
+
...candidate,
|
|
1282
|
+
safe: true,
|
|
1283
|
+
reason: inspection.detail,
|
|
1284
|
+
sourceState: 'clean_integrated',
|
|
1285
|
+
disposition: undefined,
|
|
1286
|
+
applied: true,
|
|
1287
|
+
result: 'owned_managed_worktree_detached',
|
|
1288
|
+
};
|
|
1289
|
+
} catch (error) {
|
|
1290
|
+
if (existsSync(inspection.path)) {
|
|
1291
|
+
try {
|
|
1292
|
+
setRepositoryCheckoutLifecycle({
|
|
1293
|
+
controllerHome,
|
|
1294
|
+
repoId: repository.repoId,
|
|
1295
|
+
checkoutId: inspection.checkoutId,
|
|
1296
|
+
lifecycle: 'active',
|
|
1297
|
+
reason: 'Rollback failed OwnedResource managed-worktree cleanup.',
|
|
1298
|
+
});
|
|
1299
|
+
} catch { /* preserve primary failure */ }
|
|
1300
|
+
}
|
|
1301
|
+
throw error;
|
|
1302
|
+
}
|
|
1303
|
+
}
|
|
1304
|
+
|
|
1305
|
+
export function applyStaleWorkContractMaintenanceCandidate(
|
|
1306
|
+
repository: RuntimeMaintenanceRepository,
|
|
1307
|
+
controllerHome: string,
|
|
1308
|
+
candidate: RuntimeMaintenanceCandidate,
|
|
1309
|
+
): RuntimeMaintenanceCandidate & { applied: boolean; result: string } {
|
|
1310
|
+
const work = getWorkContract({ controllerHome, repoId: repository.repoId }, candidate.id);
|
|
1311
|
+
if (!work || semanticWorkState(work) !== 'open') {
|
|
1312
|
+
return { ...candidate, applied: false, result: 'already_terminal' };
|
|
1313
|
+
}
|
|
1314
|
+
|
|
1315
|
+
// The stale scan is discovery only. Re-read the exact Work and every
|
|
1316
|
+
// non-Controller authority immediately before mutation. WorkContract writes are
|
|
1317
|
+
// serialized by the canonical Work store writer; ControllerSession ownership is
|
|
1318
|
+
// continuation state and cannot fence maintenance of semantic Work.
|
|
1319
|
+
const current = getWorkContract({ controllerHome, repoId: repository.repoId }, work.workId);
|
|
1320
|
+
if (!current || semanticWorkState(current) !== 'open') {
|
|
1321
|
+
return { ...candidate, applied: false, result: 'already_terminal' };
|
|
1322
|
+
}
|
|
1323
|
+
const authorityRefs = activeWorkAuthorityRefs(current, buildRuntimeMaintenanceAuthoritySnapshot(repository, controllerHome));
|
|
1324
|
+
if (authorityRefs.length > 0) {
|
|
1325
|
+
return {
|
|
1326
|
+
...candidate,
|
|
1327
|
+
applied: false,
|
|
1328
|
+
result: `work_authority_became_active:${authorityRefs.join(',')}`,
|
|
1329
|
+
};
|
|
1330
|
+
}
|
|
1331
|
+
// Discovery and mutation are separated by an arbitrary Runtime delay.
|
|
1332
|
+
// Re-probe the live worktree immediately before mutation; concrete Git/worktree
|
|
1333
|
+
// state is the relevant safety authority, not a Controller claim.
|
|
1334
|
+
const source = inspectStaleWorkRepositorySource(repository, controllerHome, current);
|
|
1335
|
+
if (!source.safeToCancel) {
|
|
810
1336
|
return {
|
|
811
1337
|
...candidate,
|
|
812
1338
|
path: source.path ?? candidate.path,
|
|
813
1339
|
safe: false,
|
|
814
|
-
reason:
|
|
1340
|
+
reason: isLegacyImplicitRemoteEffectPlacement(current) ? source.detail : staleWorkCandidateReason(source),
|
|
815
1341
|
sourceState: source.state,
|
|
816
1342
|
disposition: 'source_preservation_required' as const,
|
|
817
1343
|
applied: false,
|
|
818
1344
|
result: `work_source_preserved:${source.state}`,
|
|
819
1345
|
};
|
|
820
1346
|
}
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
return {
|
|
824
|
-
...candidate,
|
|
825
|
-
path: source.path ?? candidate.path,
|
|
826
|
-
safe: false,
|
|
827
|
-
reason: staleWorkCandidateReason(source, false),
|
|
828
|
-
sourceState: source.state,
|
|
829
|
-
disposition: 'semantic_completion_required' as const,
|
|
830
|
-
applied: false,
|
|
831
|
-
result: 'work_semantic_completion_required',
|
|
832
|
-
};
|
|
1347
|
+
if (isLegacyImplicitRemoteEffectPlacement(current)) {
|
|
1348
|
+
return detachLegacyRemoteEffectPlacement(repository, controllerHome, current, candidate);
|
|
833
1349
|
}
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
safe: true,
|
|
845
|
-
reason: staleWorkCandidateReason(source, true),
|
|
846
|
-
sourceState: source.state,
|
|
847
|
-
disposition: undefined,
|
|
848
|
-
applied: true,
|
|
849
|
-
result: 'work_contract_cancelled_evidence_retained',
|
|
850
|
-
};
|
|
851
|
-
},
|
|
852
|
-
);
|
|
853
|
-
if (!fenced.allowed) {
|
|
854
|
-
const generation = fenced.owner?.claimGeneration;
|
|
855
|
-
return {
|
|
856
|
-
...candidate,
|
|
857
|
-
applied: false,
|
|
858
|
-
result: `work_terminalization_fenced:${fenced.reason}${typeof generation === 'number' ? `:claim_generation=${generation}` : ''}`,
|
|
859
|
-
};
|
|
860
|
-
}
|
|
861
|
-
return fenced.value;
|
|
1350
|
+
return {
|
|
1351
|
+
...candidate,
|
|
1352
|
+
path: source.path ?? candidate.path,
|
|
1353
|
+
safe: false,
|
|
1354
|
+
reason: staleWorkCandidateReason(source),
|
|
1355
|
+
sourceState: source.state,
|
|
1356
|
+
disposition: 'semantic_completion_required' as const,
|
|
1357
|
+
applied: false,
|
|
1358
|
+
result: 'work_semantic_completion_required',
|
|
1359
|
+
};
|
|
862
1360
|
}
|
|
863
1361
|
|
|
864
1362
|
function scanStaleEditSessionCandidates(
|
|
865
1363
|
repository: RuntimeMaintenanceRepository,
|
|
866
|
-
controllerHome: string,
|
|
867
1364
|
options: Required<RuntimeMaintenanceOptions>,
|
|
1365
|
+
snapshot: RuntimeMaintenanceAuthoritySnapshot,
|
|
868
1366
|
): RuntimeMaintenanceCandidate[] {
|
|
869
1367
|
const nowMs = Date.now();
|
|
870
1368
|
return listEditSessions(repository.canonicalRoot, Math.min(options.maxCandidates * 3, 500))
|
|
871
1369
|
.filter((summary) => ['open', 'dirty', 'checked', 'check_failed'].includes(summary.status))
|
|
872
|
-
.
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
if (['finalized', 'superseded', 'rolled_back'].includes(session.status)) return [];
|
|
879
|
-
const updatedMs = Date.parse(session.updatedAt);
|
|
880
|
-
const ageMinutes = Number.isFinite(updatedMs) ? Math.max(0, Math.floor((nowMs - updatedMs) / 60_000)) : 0;
|
|
881
|
-
return [{ session, ageMinutes }];
|
|
882
|
-
} catch {
|
|
883
|
-
return [];
|
|
884
|
-
}
|
|
1370
|
+
// Status discovery is read-only. Workspace hashing/Git reconciliation belongs
|
|
1371
|
+
// exclusively to explicit full maintenance for the selected candidate.
|
|
1372
|
+
.map((session) => {
|
|
1373
|
+
const updatedMs = Date.parse(session.updatedAt);
|
|
1374
|
+
const ageMinutes = Number.isFinite(updatedMs) ? Math.max(0, Math.floor((nowMs - updatedMs) / 60_000)) : 0;
|
|
1375
|
+
return { session, ageMinutes };
|
|
885
1376
|
})
|
|
886
1377
|
.filter(({ ageMinutes }) => ageMinutes >= options.minAgeMinutes)
|
|
887
1378
|
.sort((left, right) => right.ageMinutes - left.ageMinutes)
|
|
888
1379
|
.slice(0, options.maxCandidates)
|
|
889
1380
|
.flatMap(({ session, ageMinutes }) => {
|
|
890
|
-
const work = session.workId
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
const terminalWork = Boolean(work && isTerminalWorkContractStatus(work.status));
|
|
894
|
-
if (work && !terminalWork && activeWorkAuthorityRefs(repository, controllerHome, work).length > 0) {
|
|
1381
|
+
const work = session.workId ? snapshot.workById.get(session.workId) : undefined;
|
|
1382
|
+
const terminalWork = Boolean(work && semanticWorkState(work) !== 'open');
|
|
1383
|
+
if (work && !terminalWork && activeWorkAuthorityRefs(work, snapshot).length > 0) {
|
|
895
1384
|
// The Edit Session inherits the live Work lifecycle authority. Reporting it
|
|
896
1385
|
// as stale maintenance debt while that authority is active would duplicate
|
|
897
1386
|
// ownership and can permanently block release readiness for valid long work.
|
|
@@ -952,7 +1441,10 @@ export function buildRuntimeMaintenanceStatus(
|
|
|
952
1441
|
options: RuntimeMaintenanceOptions = {},
|
|
953
1442
|
): RuntimeMaintenanceStatus {
|
|
954
1443
|
const normalized = normalizedOptions(options);
|
|
1444
|
+
// Runtime-storage binding is the compatibility cutover authority for legacy test/
|
|
1445
|
+
// migrated repositories. Read lifecycle owners only after that binding is resolved.
|
|
955
1446
|
const storage = safeRuntimeStorage(repository, controllerHome);
|
|
1447
|
+
const authoritySnapshot = buildRuntimeMaintenanceAuthoritySnapshot(repository, controllerHome);
|
|
956
1448
|
const runtimeStorageRepair = previewRuntimeStorageRepair(coerceRepository(repository), controllerHome, {
|
|
957
1449
|
minAgeMinutes: normalized.minAgeMinutes,
|
|
958
1450
|
maxCandidates: normalized.maxCandidates,
|
|
@@ -960,8 +1452,8 @@ export function buildRuntimeMaintenanceStatus(
|
|
|
960
1452
|
const localJobCandidates = scanLocalJobCandidates(repository.canonicalRoot, normalized);
|
|
961
1453
|
const storageCandidates = runtimeStorageCandidates(storage.report);
|
|
962
1454
|
const tempCandidates = scanRuntimeTempCandidates(repository, normalized.maxCandidates);
|
|
963
|
-
const staleWorkCandidates = scanStaleWorkContractCandidates(repository, controllerHome, normalized);
|
|
964
|
-
const staleEditCandidates = scanStaleEditSessionCandidates(repository,
|
|
1455
|
+
const staleWorkCandidates = scanStaleWorkContractCandidates(repository, controllerHome, normalized, authoritySnapshot);
|
|
1456
|
+
const staleEditCandidates = scanStaleEditSessionCandidates(repository, normalized, authoritySnapshot);
|
|
965
1457
|
const retainedWorktreeCandidates = scanRetainedWorktreeCandidates(repository, controllerHome, normalized.maxCandidates);
|
|
966
1458
|
const candidates = [...localJobCandidates, ...storageCandidates, ...staleWorkCandidates, ...staleEditCandidates, ...retainedWorktreeCandidates, ...tempCandidates].slice(0, normalized.maxCandidates);
|
|
967
1459
|
const summary = summarize(candidates);
|
|
@@ -999,7 +1491,7 @@ export function buildRuntimeMaintenanceStatus(
|
|
|
999
1491
|
'Pending approvals are not cancelled unless cancel_pending_approvals is explicitly enabled.',
|
|
1000
1492
|
'System temp cleanup only removes direct forge-prefixed children of approved temp roots after a 24-hour retention period and a fresh process-occupancy check.',
|
|
1001
1493
|
'Runtime lifecycle changes and source repair are outside the runtime maintenance executor.',
|
|
1002
|
-
'Retained or
|
|
1494
|
+
'Retained or unknown-ownership managed worktrees remain review-only lifecycle blockers. A WorkContract-less managed worktree is cleanup-eligible only when canonical OwnedResource identity is exact, the worktree is clean, and its HEAD is already contained in the canonical branch.',
|
|
1003
1495
|
],
|
|
1004
1496
|
};
|
|
1005
1497
|
}
|
|
@@ -1110,11 +1602,6 @@ export function previewAutomaticRuntimeMaintenance(
|
|
|
1110
1602
|
};
|
|
1111
1603
|
}
|
|
1112
1604
|
|
|
1113
|
-
function quarantinePath(repoRoot: string, id: string): string {
|
|
1114
|
-
const stamp = now().replace(/[:.]/g, '-');
|
|
1115
|
-
return join(repoRoot, '.ai', 'harness', 'local-jobs-quarantine', `${stamp}-${safeId(id)}`);
|
|
1116
|
-
}
|
|
1117
|
-
|
|
1118
1605
|
function terminalizeLocalJob(candidate: RuntimeMaintenanceCandidate, status: 'orphaned' | 'cancelled' = 'orphaned'): string {
|
|
1119
1606
|
if (!candidate.path) throw new Error('LOCAL_JOB_PATH_MISSING');
|
|
1120
1607
|
const jobPath = join(candidate.path, 'job.json');
|
|
@@ -1132,14 +1619,11 @@ function terminalizeLocalJob(candidate: RuntimeMaintenanceCandidate, status: 'or
|
|
|
1132
1619
|
return status;
|
|
1133
1620
|
}
|
|
1134
1621
|
|
|
1135
|
-
function quarantineLocalJob(repoRoot: string, candidate: RuntimeMaintenanceCandidate): string {
|
|
1622
|
+
function quarantineLocalJob(controllerHome: string, repoId: string, repoRoot: string, candidate: RuntimeMaintenanceCandidate): string {
|
|
1136
1623
|
if (!candidate.path) throw new Error('LOCAL_JOB_PATH_MISSING');
|
|
1137
1624
|
const root = localJobsRoot(repoRoot);
|
|
1138
1625
|
if (!isWithin(root, candidate.path)) throw new Error('LOCAL_JOB_PATH_OUTSIDE_ROOT');
|
|
1139
|
-
|
|
1140
|
-
mkdirSync(dirname(destination), { recursive: true });
|
|
1141
|
-
renameSync(candidate.path, destination);
|
|
1142
|
-
return destination;
|
|
1626
|
+
return quarantineRuntimePath(controllerHome, repoId, candidate.path, candidate.id);
|
|
1143
1627
|
}
|
|
1144
1628
|
|
|
1145
1629
|
function rebuildActiveIndex(repoRoot: string): void {
|
|
@@ -1204,7 +1688,7 @@ export function applyRuntimeMaintenance(
|
|
|
1204
1688
|
return { ...candidate, applied: true, result: terminalizeLocalJob(candidate, 'cancelled') };
|
|
1205
1689
|
}
|
|
1206
1690
|
if (candidate.kind === 'unreadable_local_job' || candidate.kind === 'missing_job_metadata') {
|
|
1207
|
-
return { ...candidate, applied: true, result: quarantineLocalJob(repository.canonicalRoot, candidate) };
|
|
1691
|
+
return { ...candidate, applied: true, result: quarantineLocalJob(controllerHome, repository.repoId, repository.canonicalRoot, candidate) };
|
|
1208
1692
|
}
|
|
1209
1693
|
if (candidate.kind === 'stale_runtime_temp_entry') {
|
|
1210
1694
|
if (!candidate.path) throw new Error('RUNTIME_TEMP_PATH_MISSING');
|
|
@@ -1220,6 +1704,9 @@ export function applyRuntimeMaintenance(
|
|
|
1220
1704
|
if (candidate.kind === 'stale_work_contract') {
|
|
1221
1705
|
return applyStaleWorkContractMaintenanceCandidate(repository, controllerHome, candidate);
|
|
1222
1706
|
}
|
|
1707
|
+
if (candidate.kind === 'unowned_managed_worktree') {
|
|
1708
|
+
return detachOwnedManagedWorktree(repository, controllerHome, candidate);
|
|
1709
|
+
}
|
|
1223
1710
|
if (candidate.kind === 'stale_edit_session') {
|
|
1224
1711
|
const cleaned = cleanupEditSession(repository.canonicalRoot, candidate.id, {
|
|
1225
1712
|
reviewer: 'runtime-maintenance',
|
|
@@ -1242,6 +1729,48 @@ export function applyRuntimeMaintenance(
|
|
|
1242
1729
|
const processGc = options.actionId === 'full_maintenance_pass'
|
|
1243
1730
|
? gcTerminalProcesses({ controllerHome, repoId: repository.repoId })
|
|
1244
1731
|
: undefined;
|
|
1732
|
+
const currentWork = readWorkContractStore({ controllerHome, repoId: repository.repoId }).contracts;
|
|
1733
|
+
const protectedWorkIds = currentWork
|
|
1734
|
+
.filter((contract) => semanticWorkState(contract) === 'open')
|
|
1735
|
+
.map((contract) => contract.workId);
|
|
1736
|
+
const verificationSnapshotGc = options.actionId === 'full_maintenance_pass'
|
|
1737
|
+
? cleanupStaleWorkVerificationSnapshots(controllerHome, repository.repoId, {
|
|
1738
|
+
protectedWorkIds,
|
|
1739
|
+
maxEntries: Math.max(100, (options.maxCandidates ?? 50) * 3),
|
|
1740
|
+
maxRemovals: Math.max(1, options.maxCandidates ?? 50),
|
|
1741
|
+
})
|
|
1742
|
+
: undefined;
|
|
1743
|
+
const quarantineGc = options.actionId === 'full_maintenance_pass'
|
|
1744
|
+
? cleanupRuntimeQuarantine(controllerHome, repository.repoId, repository.canonicalRoot, {
|
|
1745
|
+
maxEntries: Math.max(100, (options.maxCandidates ?? 50) * 3),
|
|
1746
|
+
maxRemovals: Math.max(1, options.maxCandidates ?? 50),
|
|
1747
|
+
additionalRoots: [runtimeLegacyCheckQuarantineRoot(controllerHome, repository.repoId)],
|
|
1748
|
+
})
|
|
1749
|
+
: undefined;
|
|
1750
|
+
let generatedCacheGc: RepositoryGeneratedCacheRetentionReport | undefined;
|
|
1751
|
+
let cleanupArtifactGc: CleanupArtifactRetentionReport | undefined;
|
|
1752
|
+
if (options.actionId === 'full_maintenance_pass') {
|
|
1753
|
+
let cacheRepository: Parameters<typeof cleanupGeneratedRepositoryCheckoutCaches>[0] = {
|
|
1754
|
+
canonicalRoot: repository.canonicalRoot,
|
|
1755
|
+
checkouts: [],
|
|
1756
|
+
};
|
|
1757
|
+
try {
|
|
1758
|
+
cacheRepository = getRepository(repository.repoId, controllerHome, { includeRemoved: true });
|
|
1759
|
+
} catch {
|
|
1760
|
+
// Embedded/test repositories may not be present in the Controller registry.
|
|
1761
|
+
// The explicit maintenance action still safely covers their canonical root.
|
|
1762
|
+
}
|
|
1763
|
+
generatedCacheGc = cleanupGeneratedRepositoryCheckoutCaches(cacheRepository, {
|
|
1764
|
+
graceMs: 60_000,
|
|
1765
|
+
maxEntries: Math.max(1_000, (options.maxCandidates ?? 50) * 20),
|
|
1766
|
+
maxRemovals: Math.max(1, options.maxCandidates ?? 50),
|
|
1767
|
+
});
|
|
1768
|
+
cleanupArtifactGc = cleanupWorkPreservationArtifacts(controllerHome, {
|
|
1769
|
+
maxEntries: Math.max(1_000, (options.maxCandidates ?? 50) * 20),
|
|
1770
|
+
maxRemovals: Math.max(1, options.maxCandidates ?? 50),
|
|
1771
|
+
repositoryIds: [repository.repoId],
|
|
1772
|
+
});
|
|
1773
|
+
}
|
|
1245
1774
|
|
|
1246
1775
|
if (options.actionId === 'runtime_storage_finalize_relocation' || options.actionId === 'full_maintenance_pass' || applied.some((candidate) => candidate.applied) || runtimeStorageRepairApply) {
|
|
1247
1776
|
rebuildActiveIndex(repository.canonicalRoot);
|
|
@@ -1259,6 +1788,10 @@ export function applyRuntimeMaintenance(
|
|
|
1259
1788
|
applied,
|
|
1260
1789
|
runtimeStorageRepairApply,
|
|
1261
1790
|
processGc,
|
|
1791
|
+
verificationSnapshotGc,
|
|
1792
|
+
quarantineGc,
|
|
1793
|
+
generatedCacheGc,
|
|
1794
|
+
cleanupArtifactGc,
|
|
1262
1795
|
projection,
|
|
1263
1796
|
};
|
|
1264
1797
|
}
|