@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,4 +1,4 @@
|
|
|
1
|
-
import { createHash
|
|
1
|
+
import { createHash } from 'crypto';
|
|
2
2
|
import { execFile } from 'child_process';
|
|
3
3
|
import { promisify } from 'util';
|
|
4
4
|
import { getRepository } from '../../../cli/repositories/registry';
|
|
@@ -10,27 +10,35 @@ import {
|
|
|
10
10
|
previewAutomaticRuntimeMaintenance,
|
|
11
11
|
type RuntimeMaintenanceActionId,
|
|
12
12
|
} from '../../recovery/maintenance-executor';
|
|
13
|
-
import { appendWorkEvidence,
|
|
14
|
-
import { launchSuperController } from '../../control-plane/launcher/thin-launcher';
|
|
15
|
-
import { getExternalControllerLaunchReservation } from '../../control-plane/launcher/launch-reservation-store';
|
|
16
|
-
import { runStandaloneChatgptPrompt, runWorkChatgptContinuation } from '../../control-plane/launcher/chatgpt-work-continuation';
|
|
13
|
+
import { appendWorkEvidence, getWorkContract, semanticWorkState } from '../../../../packages/kernel/work/api/index';
|
|
17
14
|
import {
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
15
|
+
controllerSessionBlocksRecovery,
|
|
16
|
+
getControllerSession,
|
|
17
|
+
getControllerWorkBinding,
|
|
18
|
+
getRetainedControllerSession,
|
|
19
|
+
} from '../../../../packages/kernel/controller/api/index';
|
|
22
20
|
import {
|
|
21
|
+
applyScheduleFailure,
|
|
22
|
+
applyScheduleRetryableFailure,
|
|
23
|
+
cronDue,
|
|
24
|
+
evaluateScheduleOccurrenceAdmission,
|
|
25
|
+
evaluateScheduleTriggerEligibility,
|
|
23
26
|
getOccurrence,
|
|
24
27
|
getSchedule,
|
|
25
28
|
listActiveOccurrences,
|
|
26
29
|
listOccurrences,
|
|
27
|
-
|
|
30
|
+
reclaimStaleCreatedOccurrences,
|
|
28
31
|
listSchedules,
|
|
29
32
|
saveOccurrence,
|
|
30
33
|
saveScheduleDecision,
|
|
31
34
|
updateSchedule,
|
|
32
|
-
} from '
|
|
33
|
-
|
|
35
|
+
} from '../../../../packages/kernel/scheduler/api/index';
|
|
36
|
+
export { cronDue };
|
|
37
|
+
import { ensureScheduledControllerBinding } from '../../root/scheduled-controller-composition';
|
|
38
|
+
import { reconcileControllerProgression } from '../../root/controller-progression-composition';
|
|
39
|
+
import { listUserRequests } from '../../../../packages/kernel/identity/api/index';
|
|
40
|
+
import { runStandaloneChatgptPrompt } from '../../control-plane/launcher/chatgpt-work-continuation';
|
|
41
|
+
|
|
34
42
|
import { classifyScheduledBrowserObservation, executeScheduledBrowserProbe } from './browser-probe';
|
|
35
43
|
import { executeScheduledGithubIssueWatch } from './github-issue-watch';
|
|
36
44
|
import type {
|
|
@@ -38,7 +46,7 @@ import type {
|
|
|
38
46
|
ScheduleDecisionType,
|
|
39
47
|
ScheduleOccurrence,
|
|
40
48
|
ScheduleTriggerContext,
|
|
41
|
-
} from '
|
|
49
|
+
} from '../../../../packages/kernel/scheduler/api/index';
|
|
42
50
|
|
|
43
51
|
const execFileAsync = promisify(execFile);
|
|
44
52
|
const LIVE_MAINTENANCE_OPERATION = 'runtime_maintenance_apply';
|
|
@@ -65,128 +73,6 @@ function retiredScheduleReason(schedule: RepositorySchedule): string | undefined
|
|
|
65
73
|
return undefined;
|
|
66
74
|
}
|
|
67
75
|
|
|
68
|
-
function normalizedWindow(minutes: number, at = Date.now()): string {
|
|
69
|
-
return String(Math.floor(at / (Math.max(1, minutes) * 60_000)));
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
interface ZonedDateParts {
|
|
73
|
-
year: number;
|
|
74
|
-
month: number;
|
|
75
|
-
day: number;
|
|
76
|
-
hour: number;
|
|
77
|
-
minute: number;
|
|
78
|
-
weekday: number;
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
function zonedDateParts(at: number, timezone = 'UTC'): ZonedDateParts {
|
|
82
|
-
let formatter: Intl.DateTimeFormat;
|
|
83
|
-
try {
|
|
84
|
-
formatter = new Intl.DateTimeFormat('en-US-u-ca-iso8601', {
|
|
85
|
-
timeZone: timezone,
|
|
86
|
-
year: 'numeric', month: '2-digit', day: '2-digit',
|
|
87
|
-
hour: '2-digit', minute: '2-digit', weekday: 'short',
|
|
88
|
-
hourCycle: 'h23',
|
|
89
|
-
});
|
|
90
|
-
} catch {
|
|
91
|
-
throw new Error(`SCHEDULE_TIMEZONE_INVALID: ${timezone}`);
|
|
92
|
-
}
|
|
93
|
-
const values = Object.fromEntries(formatter.formatToParts(new Date(at)).map((entry) => [entry.type, entry.value]));
|
|
94
|
-
const weekdays: Record<string, number> = { Sun: 0, Mon: 1, Tue: 2, Wed: 3, Thu: 4, Fri: 5, Sat: 6 };
|
|
95
|
-
return {
|
|
96
|
-
year: Number(values.year),
|
|
97
|
-
month: Number(values.month),
|
|
98
|
-
day: Number(values.day),
|
|
99
|
-
hour: Number(values.hour),
|
|
100
|
-
minute: Number(values.minute),
|
|
101
|
-
weekday: weekdays[String(values.weekday)] ?? 0,
|
|
102
|
-
};
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
function fixedCronTime(expression: string | undefined): { minute: number; hour: number; day: string; month: string; weekday: string } | undefined {
|
|
106
|
-
if (!expression) return undefined;
|
|
107
|
-
const fields = expression.trim().split(/\s+/);
|
|
108
|
-
if (fields.length !== 5 || !/^\d+$/.test(fields[0]) || !/^\d+$/.test(fields[1])) return undefined;
|
|
109
|
-
const minute = Number(fields[0]);
|
|
110
|
-
const hour = Number(fields[1]);
|
|
111
|
-
if (minute < 0 || minute > 59 || hour < 0 || hour > 23) return undefined;
|
|
112
|
-
return { minute, hour, day: fields[2], month: fields[3], weekday: fields[4] };
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
function cronWindowKey(schedule: RepositorySchedule, at = Date.now()): string {
|
|
116
|
-
const timezone = schedule.trigger.timezone ?? 'UTC';
|
|
117
|
-
const parts = zonedDateParts(at, timezone);
|
|
118
|
-
const fixed = fixedCronTime(schedule.trigger.cronExpression);
|
|
119
|
-
if (fixed) {
|
|
120
|
-
return `${parts.year}-${String(parts.month).padStart(2, '0')}-${String(parts.day).padStart(2, '0')}@${String(fixed.hour).padStart(2, '0')}:${String(fixed.minute).padStart(2, '0')}[${timezone}]`;
|
|
121
|
-
}
|
|
122
|
-
return `${parts.year}-${String(parts.month).padStart(2, '0')}-${String(parts.day).padStart(2, '0')}T${String(parts.hour).padStart(2, '0')}:${String(parts.minute).padStart(2, '0')}[${timezone}]`;
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
function triggerWindowKey(schedule: RepositorySchedule, context: ScheduleTriggerContext | undefined, at = Date.now()): string {
|
|
126
|
-
// Explicit control-plane triggers use a separate identity namespace from timer/cron windows.
|
|
127
|
-
// A caller-supplied event/request id is the stable retry key; otherwise each manual trigger is distinct.
|
|
128
|
-
if (context?.source === 'manual' && schedule.trigger.type !== 'manual') {
|
|
129
|
-
const stableManualKey = context.eventId?.trim();
|
|
130
|
-
return `manual:${stableManualKey || randomUUID()}`;
|
|
131
|
-
}
|
|
132
|
-
switch (schedule.trigger.type) {
|
|
133
|
-
case 'cron':
|
|
134
|
-
return cronWindowKey(schedule, at);
|
|
135
|
-
case 'calendar':
|
|
136
|
-
return schedule.trigger.calendarAt ?? new Date(at).toISOString().slice(0, 16);
|
|
137
|
-
case 'repository-event':
|
|
138
|
-
return context?.eventId?.trim() || `${context?.eventName ?? schedule.trigger.eventName ?? 'event'}:${normalizedWindow(1, at)}`;
|
|
139
|
-
case 'dependency-checkpoint':
|
|
140
|
-
return createHash('sha256').update(JSON.stringify(schedule.trigger.dependencyJobIds ?? [])).digest('hex').slice(0, 20);
|
|
141
|
-
case 'manual':
|
|
142
|
-
return context?.eventId?.trim() || normalizedWindow(1, at);
|
|
143
|
-
case 'condition':
|
|
144
|
-
case 'interval':
|
|
145
|
-
default:
|
|
146
|
-
return normalizedWindow(schedule.trigger.everyMinutes ?? 60, at);
|
|
147
|
-
}
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
function cronFieldMatches(value: number, field: string, min: number, max: number): boolean {
|
|
151
|
-
return field.split(',').some((part) => {
|
|
152
|
-
const trimmed = part.trim();
|
|
153
|
-
if (trimmed === '*') return true;
|
|
154
|
-
const stepMatch = trimmed.match(/^\*\/(\d+)$/);
|
|
155
|
-
if (stepMatch) return value % Math.max(1, Number(stepMatch[1])) === 0;
|
|
156
|
-
const rangeMatch = trimmed.match(/^(\d+)-(\d+)(?:\/(\d+))?$/);
|
|
157
|
-
if (rangeMatch) {
|
|
158
|
-
const start = Math.max(min, Number(rangeMatch[1]));
|
|
159
|
-
const end = Math.min(max, Number(rangeMatch[2]));
|
|
160
|
-
const step = Math.max(1, Number(rangeMatch[3] ?? 1));
|
|
161
|
-
return value >= start && value <= end && (value - start) % step === 0;
|
|
162
|
-
}
|
|
163
|
-
const exact = Number(trimmed);
|
|
164
|
-
return Number.isInteger(exact) && exact >= min && exact <= max && value === exact;
|
|
165
|
-
});
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
export function cronDue(
|
|
169
|
-
expression: string | undefined,
|
|
170
|
-
at = Date.now(),
|
|
171
|
-
timezone = 'UTC',
|
|
172
|
-
catchUpMinutes = 0,
|
|
173
|
-
): boolean {
|
|
174
|
-
if (!expression) return false;
|
|
175
|
-
const fields = expression.trim().split(/\s+/);
|
|
176
|
-
if (fields.length !== 5) throw new Error(`SCHEDULE_CRON_INVALID: expected five fields, received ${fields.length}`);
|
|
177
|
-
const parts = zonedDateParts(at, timezone);
|
|
178
|
-
const calendarMatches = cronFieldMatches(parts.day, fields[2], 1, 31)
|
|
179
|
-
&& cronFieldMatches(parts.month, fields[3], 1, 12)
|
|
180
|
-
&& cronFieldMatches(parts.weekday, fields[4], 0, 6);
|
|
181
|
-
if (!calendarMatches) return false;
|
|
182
|
-
if (cronFieldMatches(parts.minute, fields[0], 0, 59) && cronFieldMatches(parts.hour, fields[1], 0, 23)) return true;
|
|
183
|
-
const fixed = fixedCronTime(expression);
|
|
184
|
-
if (!fixed || catchUpMinutes <= 0) return false;
|
|
185
|
-
const scheduledMinute = fixed.hour * 60 + fixed.minute;
|
|
186
|
-
const currentMinute = parts.hour * 60 + parts.minute;
|
|
187
|
-
return currentMinute >= scheduledMinute && currentMinute - scheduledMinute <= Math.min(24 * 60, catchUpMinutes);
|
|
188
|
-
}
|
|
189
|
-
|
|
190
76
|
async function workspaceDirty(controllerHome: string, repoId: string): Promise<boolean> {
|
|
191
77
|
try {
|
|
192
78
|
const repository = getRepository(repoId, controllerHome, { includeRemoved: true });
|
|
@@ -199,64 +85,6 @@ async function workspaceDirty(controllerHome: string, repoId: string): Promise<b
|
|
|
199
85
|
}
|
|
200
86
|
}
|
|
201
87
|
|
|
202
|
-
async function triggerDue(
|
|
203
|
-
controllerHome: string,
|
|
204
|
-
schedule: RepositorySchedule,
|
|
205
|
-
force: boolean,
|
|
206
|
-
context?: ScheduleTriggerContext,
|
|
207
|
-
): Promise<{ due: boolean; reason?: string; evidence?: Record<string, unknown> }> {
|
|
208
|
-
if (force && schedule.trigger.type !== 'repository-event') return { due: true };
|
|
209
|
-
switch (schedule.trigger.type) {
|
|
210
|
-
case 'manual':
|
|
211
|
-
return { due: force, reason: force ? undefined : 'Manual Schedule requires an explicit trigger.' };
|
|
212
|
-
case 'interval':
|
|
213
|
-
return { due: true };
|
|
214
|
-
case 'cron':
|
|
215
|
-
return {
|
|
216
|
-
due: cronDue(schedule.trigger.cronExpression, Date.now(), schedule.trigger.timezone ?? 'UTC', schedule.trigger.catchUpMinutes ?? 0),
|
|
217
|
-
reason: `Cron expression is not due in the current ${schedule.trigger.timezone ?? 'UTC'} minute or catch-up window.`,
|
|
218
|
-
};
|
|
219
|
-
case 'calendar': {
|
|
220
|
-
const at = Date.parse(schedule.trigger.calendarAt ?? '');
|
|
221
|
-
if (!Number.isFinite(at)) throw new Error('SCHEDULE_CALENDAR_INVALID: calendarAt must be an ISO-8601 timestamp');
|
|
222
|
-
return { due: Date.now() >= at, reason: 'Calendar trigger is not due yet.', evidence: { calendarAt: schedule.trigger.calendarAt } };
|
|
223
|
-
}
|
|
224
|
-
case 'repository-event': {
|
|
225
|
-
const expected = schedule.trigger.eventName?.trim();
|
|
226
|
-
const actual = context?.eventName?.trim();
|
|
227
|
-
const due = context?.source === 'repository-event' && Boolean(actual) && (!expected || expected === actual);
|
|
228
|
-
return { due, reason: due ? undefined : 'Repository event did not match this Schedule.', evidence: { expected, actual, eventId: context?.eventId } };
|
|
229
|
-
}
|
|
230
|
-
case 'dependency-checkpoint': {
|
|
231
|
-
const dependencyJobIds = schedule.trigger.dependencyJobIds ?? [];
|
|
232
|
-
if (dependencyJobIds.length === 0) throw new Error('SCHEDULE_DEPENDENCY_REQUIRED: dependency checkpoint has no Job ids');
|
|
233
|
-
const jobs = dependencyJobIds.map((jobId) => findExecutionJob(controllerHome, jobId));
|
|
234
|
-
const due = jobs.every((job) => job?.status === 'succeeded');
|
|
235
|
-
return {
|
|
236
|
-
due,
|
|
237
|
-
reason: due ? undefined : 'Dependency checkpoint is not ready.',
|
|
238
|
-
evidence: { dependencies: dependencyJobIds.map((jobId, index) => ({ jobId, status: jobs[index]?.status ?? 'missing' })) },
|
|
239
|
-
};
|
|
240
|
-
}
|
|
241
|
-
case 'condition': {
|
|
242
|
-
const condition = schedule.trigger.condition;
|
|
243
|
-
if (!condition) throw new Error('SCHEDULE_CONDITION_REQUIRED');
|
|
244
|
-
if (condition.kind === 'repository_clean') {
|
|
245
|
-
const clean = !(await workspaceDirty(controllerHome, schedule.repoId));
|
|
246
|
-
return { due: clean, reason: clean ? undefined : 'Repository is not clean.', evidence: { clean } };
|
|
247
|
-
}
|
|
248
|
-
if (condition.kind === 'job_succeeded' || condition.kind === 'job_terminal') {
|
|
249
|
-
const job = condition.jobId ? findExecutionJob(controllerHome, condition.jobId) : undefined;
|
|
250
|
-
const terminal = Boolean(job && ['succeeded', 'failed', 'timed_out', 'cancelled', 'orphaned', 'stale', 'human_attention_required'].includes(job.status));
|
|
251
|
-
const due = condition.kind === 'job_succeeded' ? job?.status === 'succeeded' : terminal;
|
|
252
|
-
return { due, reason: due ? undefined : `Condition ${condition.kind} is not met.`, evidence: { jobId: condition.jobId, status: job?.status ?? 'missing' } };
|
|
253
|
-
}
|
|
254
|
-
}
|
|
255
|
-
default:
|
|
256
|
-
return { due: false, reason: 'Unsupported Schedule trigger.' };
|
|
257
|
-
}
|
|
258
|
-
}
|
|
259
|
-
|
|
260
88
|
function workBoundScheduleWorkId(schedule: RepositorySchedule): string | undefined {
|
|
261
89
|
if (schedule.action.operation !== EXTERNAL_CONTROLLER_WAKE_OPERATION
|
|
262
90
|
&& schedule.action.operation !== BROWSER_PROBE_OPERATION) return undefined;
|
|
@@ -264,30 +92,18 @@ function workBoundScheduleWorkId(schedule: RepositorySchedule): string | undefin
|
|
|
264
92
|
return typeof value === 'string' && value.trim() ? value.trim() : undefined;
|
|
265
93
|
}
|
|
266
94
|
|
|
267
|
-
const HUMAN_ONLY_HANDOFF_REASONS = new Set([
|
|
268
|
-
'policy_approval_required',
|
|
269
|
-
'missing_authorization',
|
|
270
|
-
'invalid_objective',
|
|
271
|
-
'destructive_action_requires_confirmation',
|
|
272
|
-
]);
|
|
273
|
-
|
|
274
|
-
function handoffRequiresHumanReview(item: ReturnType<typeof listHandoffItems>[number]): boolean {
|
|
275
|
-
if (item.approvalAction) return true;
|
|
276
|
-
if (!item.creationReason) return true;
|
|
277
|
-
return HUMAN_ONLY_HANDOFF_REASONS.has(item.creationReason);
|
|
278
|
-
}
|
|
279
|
-
|
|
280
95
|
async function stopReason(controllerHome: string, schedule: RepositorySchedule): Promise<string | undefined> {
|
|
281
96
|
const projection = readRepositoryProjection(controllerHome, schedule.repoId);
|
|
282
97
|
const workId = workBoundScheduleWorkId(schedule);
|
|
283
98
|
const work = workId ? getWorkContract({ controllerHome, repoId: schedule.repoId }, workId) : undefined;
|
|
284
99
|
if (schedule.stopConditions.includes('human_review_required')) {
|
|
100
|
+
const pendingUserRequests = listUserRequests(controllerHome, 'pending');
|
|
285
101
|
if (workId) {
|
|
286
|
-
const
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
return
|
|
102
|
+
const request = pendingUserRequests.find((item) => item.targetScope?.workId === workId);
|
|
103
|
+
if (request) return `Work ${workId} has pending UserRequest ${request.requestId} requiring human action.`;
|
|
104
|
+
} else {
|
|
105
|
+
const request = pendingUserRequests.find((item) => item.targetScope?.repoId === schedule.repoId);
|
|
106
|
+
if (request) return `Repository ${schedule.repoId} has pending UserRequest ${request.requestId}.`;
|
|
291
107
|
}
|
|
292
108
|
}
|
|
293
109
|
if (schedule.stopConditions.includes('release_ready') && projection.releaseFrozen) return 'Repository is in release freeze.';
|
|
@@ -430,20 +246,6 @@ export function classifyChatgptWakeFailure(reason: string): ChatgptWakeFailureCl
|
|
|
430
246
|
return 'ordinary_failure';
|
|
431
247
|
}
|
|
432
248
|
|
|
433
|
-
function externalControllerLaunchArgs(args: Record<string, unknown>, controllerType: string): string[] {
|
|
434
|
-
const launchArgs = Array.isArray(args.launch_args) ? args.launch_args.map(String) : [];
|
|
435
|
-
if (controllerType !== 'chatgpt') return launchArgs;
|
|
436
|
-
const explicit = new Set(launchArgs.filter((value) => value.startsWith('--')).map((value) => value.split('=', 1)[0]));
|
|
437
|
-
const add = (flag: string, value: unknown) => {
|
|
438
|
-
if (explicit.has(flag) || typeof value !== 'string' || !value.trim()) return;
|
|
439
|
-
launchArgs.push(flag, value.trim());
|
|
440
|
-
};
|
|
441
|
-
add('--model', args.model);
|
|
442
|
-
add('--reasoning', args.reasoning);
|
|
443
|
-
add('--tab-policy', args.tab_policy);
|
|
444
|
-
return launchArgs;
|
|
445
|
-
}
|
|
446
|
-
|
|
447
249
|
async function executeExternalControllerWake(
|
|
448
250
|
controllerHome: string,
|
|
449
251
|
schedule: RepositorySchedule,
|
|
@@ -454,167 +256,228 @@ async function executeExternalControllerWake(
|
|
|
454
256
|
options: { transientWakeFailure?: boolean } = {},
|
|
455
257
|
): Promise<ScheduleOccurrence> {
|
|
456
258
|
const workId = typeof args.work_id === 'string' ? args.work_id.trim() : '';
|
|
457
|
-
const controllerType = typeof args.controller_type === 'string' ? args.controller_type.trim() : 'chatgpt';
|
|
458
259
|
if (!workId) {
|
|
459
260
|
return decideOccurrence(controllerHome, schedule, occurrence, 'operation_blocked', 'skipped', 'EXTERNAL_CONTROLLER_WAKE_WORK_ID_REQUIRED');
|
|
460
261
|
}
|
|
461
|
-
if (!['chatgpt', 'codex', 'claude', 'grok'].includes(controllerType)) {
|
|
462
|
-
return decideOccurrence(controllerHome, schedule, occurrence, 'operation_blocked', 'skipped', 'EXTERNAL_CONTROLLER_WAKE_TYPE_INVALID');
|
|
463
|
-
}
|
|
464
262
|
const workStore = { controllerHome, repoId: schedule.repoId };
|
|
465
263
|
const work = getWorkContract(workStore, workId);
|
|
466
264
|
if (!work) {
|
|
467
265
|
updateSchedule(controllerHome, schedule.repoId, schedule.scheduleId, () => ({ enabled: false, pausedReason: `Work ${workId} no longer exists.`, lastTriggeredAt: timestamp, lastOccurrenceId: occurrence.occurrenceId }));
|
|
468
266
|
return decideOccurrence(controllerHome, schedule, occurrence, 'operation_blocked', 'skipped', `EXTERNAL_CONTROLLER_WAKE_WORK_NOT_FOUND:${workId}`);
|
|
469
267
|
}
|
|
470
|
-
if (
|
|
471
|
-
updateSchedule(controllerHome, schedule.repoId, schedule.scheduleId, () => ({ enabled: false, pausedReason: `Work ${workId} is terminal (${work.
|
|
472
|
-
return decideOccurrence(controllerHome, schedule, occurrence, 'nothing_to_do', 'skipped', `Work ${workId} is terminal (${work.
|
|
268
|
+
if (semanticWorkState(work) !== 'open') {
|
|
269
|
+
updateSchedule(controllerHome, schedule.repoId, schedule.scheduleId, () => ({ enabled: false, pausedReason: `Work ${workId} is terminal (${work.semanticState}).`, lastTriggeredAt: timestamp, lastOccurrenceId: occurrence.occurrenceId }));
|
|
270
|
+
return decideOccurrence(controllerHome, schedule, occurrence, 'nothing_to_do', 'skipped', `Work ${workId} is terminal (${work.semanticState}); automatic continuation stopped.`);
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
const retainedSession = getRetainedControllerSession(workStore, workId);
|
|
274
|
+
if (!retainedSession) {
|
|
275
|
+
return decideOccurrence(controllerHome, schedule, occurrence, 'operation_blocked', 'skipped', `SCHEDULE_CONTINUATION_CONTROLLER_SESSION_REQUIRED:${workId}`);
|
|
276
|
+
}
|
|
277
|
+
const requestedControllerType = typeof args.controller_type === 'string' ? args.controller_type.trim() : '';
|
|
278
|
+
if (requestedControllerType && requestedControllerType !== retainedSession.controllerType) {
|
|
279
|
+
return decideOccurrence(
|
|
280
|
+
controllerHome,
|
|
281
|
+
schedule,
|
|
282
|
+
occurrence,
|
|
283
|
+
'operation_blocked',
|
|
284
|
+
'skipped',
|
|
285
|
+
`SCHEDULE_CONTINUATION_CONTROLLER_TYPE_MISMATCH:${workId}:expected=${retainedSession.controllerType}:requested=${requestedControllerType}`,
|
|
286
|
+
);
|
|
473
287
|
}
|
|
474
|
-
const existingOwner = getControllerSession(workStore, workId);
|
|
475
288
|
const occurrenceNowMs = Date.parse(timestamp);
|
|
476
289
|
const nowMs = Number.isFinite(occurrenceNowMs) ? occurrenceNowMs : Date.now();
|
|
477
290
|
if (workHasActiveExecution(controllerHome, schedule.repoId, workId)) {
|
|
478
291
|
updateSchedule(controllerHome, schedule.repoId, schedule.scheduleId, () => ({ lastTriggeredAt: timestamp, lastOccurrenceId: occurrence.occurrenceId }));
|
|
479
292
|
return decideOccurrence(controllerHome, schedule, occurrence, 'nothing_to_do', 'skipped', `Work ${workId} has active execution; duplicate Controller wake suppressed.`);
|
|
480
293
|
}
|
|
294
|
+
const existingOwner = getControllerSession(workStore, workId);
|
|
481
295
|
if (existingOwner && controllerSessionBlocksRecovery(workStore, workId, { nowMs })) {
|
|
482
296
|
updateSchedule(controllerHome, schedule.repoId, schedule.scheduleId, () => ({ lastTriggeredAt: timestamp, lastOccurrenceId: occurrence.occurrenceId }));
|
|
483
297
|
return decideOccurrence(controllerHome, schedule, occurrence, 'nothing_to_do', 'skipped', `Work ${workId} has a recently active Controller ${existingOwner.controllerId}.`);
|
|
484
298
|
}
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
299
|
+
|
|
300
|
+
const repository = getRepository(schedule.repoId, controllerHome, { includeRemoved: true });
|
|
301
|
+
let bindingId = typeof args.controller_binding_id === 'string' ? args.controller_binding_id.trim() : '';
|
|
302
|
+
let bindingRecord = getControllerWorkBinding(workStore, workId);
|
|
303
|
+
if (bindingRecord && bindingRecord.binding.bindingId !== bindingId) {
|
|
304
|
+
return decideOccurrence(
|
|
305
|
+
controllerHome,
|
|
306
|
+
schedule,
|
|
307
|
+
occurrence,
|
|
308
|
+
'operation_blocked',
|
|
309
|
+
'skipped',
|
|
310
|
+
`SCHEDULE_CONTINUATION_BINDING_DRIFT:${workId}:expected=${bindingId}:actual=${bindingRecord.binding.bindingId}`,
|
|
311
|
+
);
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
const hadLegacySessionIdentity = typeof args.controller_session_id === 'string' && args.controller_session_id.trim().length > 0;
|
|
315
|
+
|
|
316
|
+
// Explicit compatibility migration for schedules written before Kernel V2 B4.
|
|
317
|
+
// Provider metadata is copied once into the adapter-owned binding and the
|
|
318
|
+
// Schedule is rewritten to exact Work/ControllerSession/ControllerBinding ids.
|
|
319
|
+
if (!bindingRecord) {
|
|
320
|
+
const binding = ensureScheduledControllerBinding(
|
|
321
|
+
{ controllerHome, repoId: schedule.repoId },
|
|
322
|
+
{ workId, session: retainedSession, scheduleName: schedule.name, args },
|
|
323
|
+
);
|
|
324
|
+
bindingId = binding.bindingId;
|
|
325
|
+
bindingRecord = getControllerWorkBinding(workStore, workId);
|
|
326
|
+
if (!bindingRecord || bindingRecord.binding.bindingId !== bindingId) {
|
|
327
|
+
throw new Error(`SCHEDULE_CONTINUATION_BINDING_MIGRATION_FAILED:${workId}`);
|
|
328
|
+
}
|
|
489
329
|
}
|
|
330
|
+
|
|
331
|
+
const continuationHintForMigration = typeof args.continuation_hint === 'string'
|
|
332
|
+
? args.continuation_hint
|
|
333
|
+
: typeof args.continuation_prompt === 'string'
|
|
334
|
+
? args.continuation_prompt
|
|
335
|
+
: undefined;
|
|
336
|
+
const relayScopeIdForMigration = typeof args.relay_scope_id === 'string' ? args.relay_scope_id.trim() : undefined;
|
|
337
|
+
if (hadLegacySessionIdentity || bindingId !== bindingRecord.binding.bindingId) {
|
|
338
|
+
bindingId = bindingRecord.binding.bindingId;
|
|
339
|
+
schedule = updateSchedule(controllerHome, schedule.repoId, schedule.scheduleId, (current) => ({
|
|
340
|
+
action: {
|
|
341
|
+
...current.action,
|
|
342
|
+
arguments: {
|
|
343
|
+
work_id: workId,
|
|
344
|
+
controller_type: retainedSession.controllerType,
|
|
345
|
+
controller_binding_id: bindingId,
|
|
346
|
+
...(relayScopeIdForMigration ? { relay_scope_id: relayScopeIdForMigration } : {}),
|
|
347
|
+
...(continuationHintForMigration?.trim() ? { continuation_hint: continuationHintForMigration.trim() } : {}),
|
|
348
|
+
},
|
|
349
|
+
},
|
|
350
|
+
}));
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
const controllerType = retainedSession.controllerType;
|
|
354
|
+
const continuationHint = typeof schedule.action.arguments?.continuation_hint === 'string'
|
|
355
|
+
? schedule.action.arguments.continuation_hint
|
|
356
|
+
: undefined;
|
|
357
|
+
const relayScopeId = typeof schedule.action.arguments?.relay_scope_id === 'string'
|
|
358
|
+
? schedule.action.arguments.relay_scope_id
|
|
359
|
+
: undefined;
|
|
360
|
+
const controllerRoundOccurrenceId = typeof occurrence.triggerContext?.data?.controllerRoundOccurrenceId === 'string'
|
|
361
|
+
&& occurrence.triggerContext.data.controllerRoundOccurrenceId.trim()
|
|
362
|
+
? occurrence.triggerContext.data.controllerRoundOccurrenceId.trim()
|
|
363
|
+
: occurrence.occurrenceId;
|
|
490
364
|
const wakeDecision = decideOccurrence(
|
|
491
365
|
controllerHome,
|
|
492
366
|
schedule,
|
|
493
367
|
occurrence,
|
|
494
368
|
'execute',
|
|
495
369
|
'running',
|
|
496
|
-
'Deterministic
|
|
370
|
+
'Deterministic Controller continuation is starting through Kernel Scheduler and ControllerHost.',
|
|
497
371
|
occurrenceDecisionEvidence({
|
|
498
372
|
operation: schedule.action.operation,
|
|
499
373
|
workId,
|
|
500
374
|
controllerType,
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
reasoning: typeof args.reasoning === 'string' ? args.reasoning : 'high',
|
|
504
|
-
tabPolicy: typeof args.tab_policy === 'string' ? args.tab_policy : 'auto',
|
|
505
|
-
} : {}),
|
|
375
|
+
controllerSessionId: retainedSession.sessionId,
|
|
376
|
+
controllerBindingId: bindingRecord.binding.bindingId,
|
|
506
377
|
...extraEvidence,
|
|
507
378
|
}),
|
|
508
379
|
);
|
|
380
|
+
|
|
509
381
|
try {
|
|
510
|
-
const
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
repoId: schedule.repoId,
|
|
537
|
-
repoRoot: repository.canonicalRoot,
|
|
538
|
-
workId,
|
|
539
|
-
prompt: relayPrompt,
|
|
540
|
-
title: schedule.name,
|
|
541
|
-
browserSessionId: typeof args.browser_session_id === 'string' ? args.browser_session_id : undefined,
|
|
542
|
-
conversationUrl: typeof args.conversation_url === 'string' ? args.conversation_url : undefined,
|
|
543
|
-
model: typeof args.model === 'string' ? args.model : 'gpt-5.6',
|
|
544
|
-
reasoning,
|
|
545
|
-
tabPolicy,
|
|
546
|
-
timeoutMs,
|
|
547
|
-
}), timeoutMs);
|
|
548
|
-
if (dispatched.status === 'failed') throw new Error(dispatched.error?.message ?? 'CHATGPT_WORK_CONTINUATION_FAILED');
|
|
549
|
-
const completedRelay = finishControllerRoundRelayDispatch(workStore, {
|
|
550
|
-
workId,
|
|
551
|
-
ok: true,
|
|
552
|
-
browserSessionId: dispatched.browserSessionId,
|
|
553
|
-
conversationUrl: dispatched.conversationUrl,
|
|
554
|
-
});
|
|
555
|
-
updateSchedule(controllerHome, schedule.repoId, schedule.scheduleId, (current) => ({
|
|
556
|
-
lastTriggeredAt: timestamp,
|
|
557
|
-
lastOccurrenceId: occurrence.occurrenceId,
|
|
558
|
-
consecutiveFailures: 0,
|
|
559
|
-
nextEligibleAt: undefined,
|
|
560
|
-
...(current.enabled ? { pausedReason: undefined } : {}),
|
|
561
|
-
}));
|
|
562
|
-
const succeededOccurrence = saveOccurrence(controllerHome, {
|
|
563
|
-
...wakeDecision,
|
|
564
|
-
status: 'succeeded',
|
|
565
|
-
reason: `ChatGPT dispatch action succeeded via ${dispatched.browserSessionId}; relay ${completedRelay?.relayScopeId ?? relay.relayScopeId} remains dispatched until the new Controller claims Work ${workId}.`,
|
|
566
|
-
});
|
|
567
|
-
appendWorkEvidence(workStore, workId, {
|
|
568
|
-
evidenceId: succeededOccurrence.occurrenceId,
|
|
569
|
-
title: 'scheduled ChatGPT continuation dispatched',
|
|
570
|
-
summary: `Schedule ${schedule.scheduleId} timer occurrence ${succeededOccurrence.occurrenceId} dispatched the Work-bound ChatGPT continuation successfully.`,
|
|
571
|
-
detailLevel: 'summary',
|
|
572
|
-
});
|
|
573
|
-
return succeededOccurrence;
|
|
574
|
-
} catch (error) {
|
|
575
|
-
if (relay) {
|
|
576
|
-
finishControllerRoundRelayDispatch(workStore, {
|
|
577
|
-
workId,
|
|
578
|
-
ok: false,
|
|
579
|
-
error: error instanceof Error ? error.message : String(error),
|
|
580
|
-
});
|
|
581
|
-
}
|
|
582
|
-
if (error instanceof Error && error.message.startsWith('CONTROLLER_RELAY_ROUND_ALREADY_OPEN:')) {
|
|
583
|
-
updateSchedule(controllerHome, schedule.repoId, schedule.scheduleId, () => ({ lastTriggeredAt: timestamp, lastOccurrenceId: occurrence.occurrenceId }));
|
|
584
|
-
return decideOccurrence(controllerHome, schedule, wakeDecision, 'nothing_to_do', 'skipped', `Work ${workId} already has an open ChatGPT controller round awaiting claim or disposition.`);
|
|
585
|
-
}
|
|
586
|
-
throw error;
|
|
587
|
-
}
|
|
382
|
+
const progression = await reconcileControllerProgression(
|
|
383
|
+
{ controllerHome, repoId: schedule.repoId, repoRoot: repository.canonicalRoot },
|
|
384
|
+
{
|
|
385
|
+
occurrenceId: controllerRoundOccurrenceId,
|
|
386
|
+
workId,
|
|
387
|
+
relayScopeId,
|
|
388
|
+
continuationHint,
|
|
389
|
+
allowSemanticWaitRecovery: controllerType === 'chatgpt',
|
|
390
|
+
scheduleName: schedule.name,
|
|
391
|
+
bindingArgs: args,
|
|
392
|
+
},
|
|
393
|
+
);
|
|
394
|
+
|
|
395
|
+
if (progression.status === 'terminal_or_missing') {
|
|
396
|
+
updateSchedule(controllerHome, schedule.repoId, schedule.scheduleId, () => ({
|
|
397
|
+
enabled: false,
|
|
398
|
+
pausedReason: progression.reason,
|
|
399
|
+
lastTriggeredAt: timestamp,
|
|
400
|
+
lastOccurrenceId: occurrence.occurrenceId,
|
|
401
|
+
}));
|
|
402
|
+
return saveOccurrence(controllerHome, {
|
|
403
|
+
...wakeDecision,
|
|
404
|
+
status: 'skipped',
|
|
405
|
+
decision: 'nothing_to_do',
|
|
406
|
+
reason: progression.reason,
|
|
407
|
+
});
|
|
588
408
|
}
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
409
|
+
|
|
410
|
+
if (progression.status === 'semantic_wait'
|
|
411
|
+
|| progression.status === 'wait_for_user'
|
|
412
|
+
|| progression.status === 'retained_session_missing'
|
|
413
|
+
|| progression.status === 'human_controller') {
|
|
414
|
+
updateSchedule(controllerHome, schedule.repoId, schedule.scheduleId, () => ({
|
|
415
|
+
lastTriggeredAt: timestamp,
|
|
416
|
+
lastOccurrenceId: occurrence.occurrenceId,
|
|
417
|
+
}));
|
|
418
|
+
return saveOccurrence(controllerHome, {
|
|
419
|
+
...wakeDecision,
|
|
420
|
+
status: 'skipped',
|
|
421
|
+
decision: 'nothing_to_do',
|
|
422
|
+
reason: progression.reason ?? `Work ${workId} is not currently eligible for provider progression.`,
|
|
423
|
+
});
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
if (progression.status === 'rejected') {
|
|
427
|
+
throw new Error(progression.reason ?? 'CONTROLLER_HOST_RESUME_REJECTED');
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
if (progression.status === 'chatgpt_not_enrolled') {
|
|
431
|
+
updateSchedule(controllerHome, schedule.repoId, schedule.scheduleId, () => ({
|
|
432
|
+
lastTriggeredAt: timestamp,
|
|
433
|
+
lastOccurrenceId: occurrence.occurrenceId,
|
|
434
|
+
}));
|
|
435
|
+
return saveOccurrence(controllerHome, {
|
|
436
|
+
...wakeDecision,
|
|
437
|
+
status: 'skipped',
|
|
438
|
+
decision: 'nothing_to_do',
|
|
439
|
+
reason: `Workflow Supervisor enrollment is not yet ready (${progression.supervisorEnrollment.status}); no ChatGPT provider attempt was consumed.`,
|
|
440
|
+
});
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
const supervisorEnrollment = progression.status === 'chatgpt_enrolled'
|
|
444
|
+
? progression.supervisorEnrollment
|
|
445
|
+
: { status: 'not_eligible' as const };
|
|
604
446
|
updateSchedule(controllerHome, schedule.repoId, schedule.scheduleId, (current) => ({
|
|
605
447
|
lastTriggeredAt: timestamp,
|
|
606
448
|
lastOccurrenceId: occurrence.occurrenceId,
|
|
607
449
|
consecutiveFailures: 0,
|
|
608
450
|
nextEligibleAt: undefined,
|
|
609
|
-
...(
|
|
451
|
+
...(supervisorEnrollment.status === 'enrolled'
|
|
452
|
+
? { enabled: false, pausedReason: 'workflow_supervisor_owns_outer_turn' }
|
|
453
|
+
: current.enabled ? { pausedReason: undefined } : {}),
|
|
610
454
|
}));
|
|
611
|
-
|
|
455
|
+
const dispatchedOccurrence = saveOccurrence(controllerHome, {
|
|
612
456
|
...wakeDecision,
|
|
613
|
-
status: '
|
|
614
|
-
reason:
|
|
457
|
+
status: 'dispatched',
|
|
458
|
+
reason: progression.status === 'chatgpt_enrolled'
|
|
459
|
+
? `Workflow Supervisor reserved the exact ChatGPT effect ${progression.supervisorEnrollment.effectId ?? progression.relayScopeId}; Scheduler issued no provider send.`
|
|
460
|
+
: progression.reused
|
|
461
|
+
? `Controller continuation occurrence ${occurrence.occurrenceId} was already durably dispatched; external replay suppressed and semantic round closure is still pending.`
|
|
462
|
+
: `ControllerHost accepted durable binding ${bindingRecord.binding.bindingId} for Work ${workId}; dispatch ${progression.providerDispatchReceiptId ?? progression.relayScopeId}; semantic round closure is still pending.`,
|
|
463
|
+
});
|
|
464
|
+
appendWorkEvidence(workStore, workId, {
|
|
465
|
+
evidenceId: dispatchedOccurrence.occurrenceId,
|
|
466
|
+
title: progression.status === 'chatgpt_enrolled'
|
|
467
|
+
? 'scheduled Workflow Supervisor effect reserved'
|
|
468
|
+
: 'scheduled Controller continuation dispatched',
|
|
469
|
+
summary: progression.status === 'chatgpt_enrolled'
|
|
470
|
+
? `Schedule ${schedule.scheduleId} materialized the exact ControllerRound occurrence and Supervisor effect; Supervisor owns ChatGPT delivery.`
|
|
471
|
+
: `Schedule ${schedule.scheduleId} occurrence ${dispatchedOccurrence.occurrenceId} resumed the exact Work-bound ControllerSession through ControllerHost.`,
|
|
472
|
+
detailLevel: 'summary',
|
|
615
473
|
});
|
|
474
|
+
return dispatchedOccurrence;
|
|
616
475
|
} catch (error) {
|
|
617
476
|
const reason = error instanceof Error ? error.message : String(error);
|
|
477
|
+
if (reason.startsWith('CONTROLLER_CONTINUATION_ROUND_ALREADY_OPEN:') || reason.startsWith('CONTROLLER_CONTINUATION_ALREADY_DISPATCHING:')) {
|
|
478
|
+
updateSchedule(controllerHome, schedule.repoId, schedule.scheduleId, () => ({ lastTriggeredAt: timestamp, lastOccurrenceId: occurrence.occurrenceId }));
|
|
479
|
+
return decideOccurrence(controllerHome, schedule, wakeDecision, 'nothing_to_do', 'skipped', `Work ${workId} already has an open Controller round awaiting claim or disposition.`);
|
|
480
|
+
}
|
|
618
481
|
const failureClass = controllerType === 'chatgpt' ? classifyChatgptWakeFailure(reason) : 'ordinary_failure';
|
|
619
482
|
if (options.transientWakeFailure || failureClass === 'retryable_readiness' || failureClass === 'semantic_wait') {
|
|
620
483
|
const semanticWait = failureClass === 'semantic_wait';
|
|
@@ -642,18 +505,20 @@ async function executeExternalControllerWake(
|
|
|
642
505
|
decision: 'execute',
|
|
643
506
|
reason,
|
|
644
507
|
...(failureClass === 'user_action_required' ? { pauseReason: reason } : {}),
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
508
|
+
...(failureClass === 'user_action_required' ? {
|
|
509
|
+
handoff: {
|
|
510
|
+
title: `External Controller wake ${occurrence.occurrenceId} requires user authorization`,
|
|
511
|
+
summary: 'Forge cannot resume the configured ControllerSession until the required user authorization is restored.',
|
|
512
|
+
reason,
|
|
513
|
+
creationReason: 'missing_authorization' as const,
|
|
514
|
+
blockingDecision: 'Restore the required authenticated/authorized controller capability, then retry the same scheduled Work.',
|
|
515
|
+
recommendedDecision: 'Restore authorization only; do not create replacement Work or replay an unknown external effect.',
|
|
516
|
+
recommendedPrompt: `Restore authorization for Work ${workId} and retry scheduled continuation ${occurrence.occurrenceId}.`,
|
|
517
|
+
statusSummary: 'Scheduled Controller continuation is waiting on user authorization.',
|
|
518
|
+
blockedBy: ['controller_authorization_required'],
|
|
519
|
+
attemptedActions: [`schedule:${schedule.scheduleId}`, `work:${workId}`, `controller:${controllerType}`, `session:${retainedSession.sessionId}`, `binding:${bindingRecord.binding.bindingId}`],
|
|
520
|
+
},
|
|
521
|
+
} : {}),
|
|
657
522
|
});
|
|
658
523
|
updateSchedule(controllerHome, schedule.repoId, schedule.scheduleId, () => ({ lastTriggeredAt: timestamp, lastOccurrenceId: occurrence.occurrenceId }));
|
|
659
524
|
return failed.occurrence ?? saveOccurrence(controllerHome, { ...wakeDecision, status: 'failed', reason });
|
|
@@ -673,11 +538,23 @@ export async function evaluateSchedule(
|
|
|
673
538
|
// Preserve retired schedule records as evidence, but do not create a new
|
|
674
539
|
// occurrence or resume a controller/external action from their old payload.
|
|
675
540
|
if (retiredScheduleReason(schedule)) return undefined;
|
|
676
|
-
|
|
677
|
-
const
|
|
678
|
-
if (
|
|
541
|
+
const eligibilityNowMs = Date.now();
|
|
542
|
+
const triggerJobIds = new Set<string>(schedule.trigger.dependencyJobIds ?? []);
|
|
543
|
+
if (schedule.trigger.condition?.jobId) triggerJobIds.add(schedule.trigger.condition.jobId);
|
|
544
|
+
const jobStatuses = Object.fromEntries([...triggerJobIds].map((jobId) => [jobId, findExecutionJob(controllerHome, jobId)?.status]));
|
|
545
|
+
const repositoryClean = schedule.trigger.condition?.kind === 'repository_clean'
|
|
546
|
+
? !(await workspaceDirty(controllerHome, schedule.repoId))
|
|
547
|
+
: undefined;
|
|
548
|
+
const due = evaluateScheduleTriggerEligibility(schedule, {
|
|
549
|
+
nowMs: eligibilityNowMs,
|
|
550
|
+
force,
|
|
551
|
+
context: triggerContext,
|
|
552
|
+
repositoryClean,
|
|
553
|
+
jobStatuses,
|
|
554
|
+
});
|
|
555
|
+
if (!due.due || !due.windowKey) return undefined;
|
|
679
556
|
|
|
680
|
-
const key =
|
|
557
|
+
const key = due.windowKey;
|
|
681
558
|
const occurrenceId = `OCC-${schedule.scheduleId}-${createHash('sha256').update(key).digest('hex').slice(0, 20)}`;
|
|
682
559
|
const existing = getOccurrence(controllerHome, schedule.repoId, occurrenceId);
|
|
683
560
|
if (existing) return existing;
|
|
@@ -696,41 +573,36 @@ export async function evaluateSchedule(
|
|
|
696
573
|
updatedAt: timestamp,
|
|
697
574
|
});
|
|
698
575
|
|
|
699
|
-
// Semantic
|
|
700
|
-
//
|
|
576
|
+
// Semantic/model-owned schedule actions record the trigger only. A trigger is
|
|
577
|
+
// continuation input for the external Controller/Supervisor, not a human
|
|
578
|
+
// blocker and therefore must not manufacture Handoff/UserRequest state.
|
|
701
579
|
if (!isDeterministicSchedule(schedule)) {
|
|
702
|
-
const
|
|
580
|
+
const recorded = decideOccurrence(
|
|
703
581
|
controllerHome,
|
|
704
582
|
schedule,
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
'skipped',
|
|
711
|
-
'Schedule execution is external-controller-owned; no ExecutionJob was created.',
|
|
712
|
-
occurrenceDecisionEvidence({ operation: schedule.action.operation, trigger: occurrence.triggerContext?.source }),
|
|
713
|
-
),
|
|
714
|
-
{
|
|
715
|
-
title: `Schedule ${schedule.name} requires an external Controller`,
|
|
716
|
-
summary: 'The scheduled trigger was recorded without dispatching a Kernel Job.',
|
|
717
|
-
reason: 'Schedule execution is external-controller-owned.',
|
|
718
|
-
creationReason: 'ambiguous_outcome',
|
|
719
|
-
blockingDecision: 'Claim or create the related Work before executing the scheduled operation.',
|
|
720
|
-
recommendedDecision: 'Review the trigger evidence and continue it through an explicitly claimed external Controller session.',
|
|
721
|
-
recommendedPrompt: `Review schedule ${schedule.scheduleId} occurrence ${occurrence.occurrenceId}; create or claim Work for ${schedule.action.operation} and continue through Process Runtime or Thin Launcher.`,
|
|
722
|
-
statusSummary: 'Schedule trigger is waiting for external Controller ownership.',
|
|
723
|
-
blockedBy: ['external_controller_required'],
|
|
724
|
-
attemptedActions: [`operation:${schedule.action.operation}`],
|
|
725
|
-
},
|
|
583
|
+
occurrence,
|
|
584
|
+
'operation_blocked',
|
|
585
|
+
'skipped',
|
|
586
|
+
'Schedule trigger recorded for external Controller continuation; no Kernel ExecutionJob or human Handoff was created.',
|
|
587
|
+
occurrenceDecisionEvidence({ operation: schedule.action.operation, trigger: occurrence.triggerContext?.source }),
|
|
726
588
|
);
|
|
727
589
|
updateSchedule(controllerHome, schedule.repoId, schedule.scheduleId, () => ({ lastTriggeredAt: timestamp, lastOccurrenceId: occurrenceId }));
|
|
728
|
-
return
|
|
590
|
+
return recorded;
|
|
729
591
|
}
|
|
730
592
|
|
|
731
593
|
const recent = listOccurrences(controllerHome, schedule.repoId, schedule.scheduleId, 1000);
|
|
732
|
-
|
|
733
|
-
|
|
594
|
+
reclaimStaleCreatedOccurrences(controllerHome, schedule.repoId, schedule.scheduleId);
|
|
595
|
+
const active = listActiveOccurrences(controllerHome, schedule.repoId, schedule.scheduleId)
|
|
596
|
+
.filter((entry) => entry.occurrenceId !== occurrence.occurrenceId);
|
|
597
|
+
const admission = evaluateScheduleOccurrenceAdmission(schedule, {
|
|
598
|
+
nowMs: Date.now(),
|
|
599
|
+
force,
|
|
600
|
+
stopReason: await stopReason(controllerHome, schedule),
|
|
601
|
+
activeOccurrenceCount: active.length,
|
|
602
|
+
dailyRuntimeMinutes: dailyRuntimeMinutes(controllerHome, recent),
|
|
603
|
+
});
|
|
604
|
+
if (admission.kind === 'stop_condition') {
|
|
605
|
+
const stop = admission.reason ?? 'Schedule stop condition is active.';
|
|
734
606
|
const stopped = decideOccurrence(controllerHome, schedule, occurrence, 'stopped', 'skipped', stop);
|
|
735
607
|
if (!isLiveMaintenanceSchedule(schedule)) return stopped;
|
|
736
608
|
const failed = applyScheduleFailure(controllerHome, schedule.scheduleId, schedule.repoId, occurrence.occurrenceId, {
|
|
@@ -739,42 +611,25 @@ export async function evaluateSchedule(
|
|
|
739
611
|
reason: stop,
|
|
740
612
|
countFailure: false,
|
|
741
613
|
pauseReason: stop,
|
|
742
|
-
|
|
743
|
-
title: `Scheduled maintenance occurrence ${occurrence.occurrenceId} stopped`,
|
|
744
|
-
summary: 'A live maintenance occurrence was blocked by an explicit schedule stop condition and requires review before automation resumes.',
|
|
745
|
-
reason: stop,
|
|
746
|
-
creationReason: 'ambiguous_outcome',
|
|
747
|
-
blockingDecision: 'Review the stop condition and decide whether automatic maintenance should stay paused.',
|
|
748
|
-
recommendedDecision: 'Resolve the stop condition, then explicitly re-enable or retrigger the maintenance schedule.',
|
|
749
|
-
recommendedPrompt: `Review maintenance schedule ${schedule.scheduleId} for repo ${schedule.repoId}, inspect stop condition ${stop}, and decide whether to resume the schedule.`,
|
|
750
|
-
statusSummary: 'Scheduled maintenance occurrence stopped before dispatch.',
|
|
751
|
-
blockedBy: ['schedule_stop_condition'],
|
|
752
|
-
attemptedActions: [`schedule:${schedule.scheduleId}`, `operation:${schedule.action.operation}`],
|
|
753
|
-
},
|
|
614
|
+
|
|
754
615
|
});
|
|
755
616
|
return failed.occurrence ?? stopped;
|
|
756
617
|
}
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
.filter((entry) => entry.occurrenceId !== occurrence.occurrenceId);
|
|
760
|
-
if (active.length >= schedule.policy.maxActiveOccurrences) {
|
|
761
|
-
return decideOccurrence(controllerHome, schedule, occurrence, 'active_occurrence', 'skipped', 'Maximum active occurrences reached.');
|
|
618
|
+
if (admission.kind === 'active_occurrence') {
|
|
619
|
+
return decideOccurrence(controllerHome, schedule, occurrence, 'active_occurrence', 'skipped', admission.reason);
|
|
762
620
|
}
|
|
763
|
-
if (
|
|
621
|
+
if (admission.kind === 'failure_limit') {
|
|
764
622
|
updateSchedule(controllerHome, schedule.repoId, schedule.scheduleId, (current) => ({
|
|
765
623
|
enabled: false,
|
|
766
624
|
pausedReason: current.enabled ? 'Maximum consecutive failures reached.' : current.pausedReason,
|
|
767
625
|
}));
|
|
768
|
-
return decideOccurrence(controllerHome, schedule, occurrence, 'stopped', 'skipped',
|
|
626
|
+
return decideOccurrence(controllerHome, schedule, occurrence, 'stopped', 'skipped', admission.reason);
|
|
769
627
|
}
|
|
770
|
-
if (
|
|
771
|
-
return decideOccurrence(controllerHome, schedule, occurrence, 'cooldown', 'skipped',
|
|
628
|
+
if (admission.kind === 'cooldown') {
|
|
629
|
+
return decideOccurrence(controllerHome, schedule, occurrence, 'cooldown', 'skipped', admission.reason);
|
|
772
630
|
}
|
|
773
|
-
if (
|
|
774
|
-
return decideOccurrence(controllerHome, schedule, occurrence, '
|
|
775
|
-
}
|
|
776
|
-
if (dailyRuntimeMinutes(controllerHome, recent) >= schedule.policy.dailyBudgetMinutes) {
|
|
777
|
-
return decideOccurrence(controllerHome, schedule, occurrence, 'budget_exhausted', 'skipped', 'Daily schedule budget exhausted.');
|
|
631
|
+
if (admission.kind === 'budget_exhausted') {
|
|
632
|
+
return decideOccurrence(controllerHome, schedule, occurrence, 'budget_exhausted', 'skipped', admission.reason);
|
|
778
633
|
}
|
|
779
634
|
if (schedule.policy.shadowMode) {
|
|
780
635
|
if (isLiveMaintenanceSchedule(schedule)) {
|
|
@@ -793,22 +648,20 @@ export async function evaluateSchedule(
|
|
|
793
648
|
reason: preview.blockedReason ?? 'Automatic maintenance preview blocked the occurrence.',
|
|
794
649
|
countFailure: !preview.blockedPermanently,
|
|
795
650
|
pauseReason: preview.blockedPermanently ? preview.blockedReason : undefined,
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
: '
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
:
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
attemptedActions: [`schedule:${schedule.scheduleId}`, `operation:${schedule.action.operation}`],
|
|
811
|
-
},
|
|
651
|
+
...(preview.blockedPermanently ? {
|
|
652
|
+
handoff: {
|
|
653
|
+
title: `Scheduled maintenance occurrence ${occurrence.occurrenceId} needs a user decision`,
|
|
654
|
+
summary: 'Automatic maintenance is permanently blocked and requires an explicit user decision before the schedule can resume.',
|
|
655
|
+
reason: preview.blockedReason ?? 'Automatic maintenance preview blocked the occurrence.',
|
|
656
|
+
creationReason: 'ambiguous_outcome' as const,
|
|
657
|
+
blockingDecision: 'Correct the configuration/authorization or intentionally keep this schedule paused.',
|
|
658
|
+
recommendedDecision: 'Review the permanent blocker and explicitly decide whether to repair configuration and resume.',
|
|
659
|
+
recommendedPrompt: `Review permanently blocked maintenance occurrence ${occurrence.occurrenceId} for schedule ${schedule.scheduleId} and decide whether to repair and resume it.`,
|
|
660
|
+
statusSummary: 'Scheduled maintenance is permanently blocked pending a user decision.',
|
|
661
|
+
blockedBy: [decision],
|
|
662
|
+
attemptedActions: [`schedule:${schedule.scheduleId}`, `operation:${schedule.action.operation}`],
|
|
663
|
+
},
|
|
664
|
+
} : {}),
|
|
812
665
|
});
|
|
813
666
|
return failed.occurrence ?? blocked;
|
|
814
667
|
}
|
|
@@ -845,22 +698,20 @@ export async function evaluateSchedule(
|
|
|
845
698
|
reason: preview.blockedReason ?? 'Automatic maintenance preview blocked the occurrence.',
|
|
846
699
|
countFailure: !preview.blockedPermanently,
|
|
847
700
|
pauseReason: preview.blockedPermanently ? preview.blockedReason : undefined,
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
: '
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
:
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
attemptedActions: [`schedule:${schedule.scheduleId}`, `operation:${schedule.action.operation}`],
|
|
863
|
-
},
|
|
701
|
+
...(preview.blockedPermanently ? {
|
|
702
|
+
handoff: {
|
|
703
|
+
title: `Scheduled maintenance occurrence ${occurrence.occurrenceId} needs a user decision`,
|
|
704
|
+
summary: 'Automatic maintenance is permanently blocked and requires an explicit user decision before the schedule can resume.',
|
|
705
|
+
reason: preview.blockedReason ?? 'Automatic maintenance preview blocked the occurrence.',
|
|
706
|
+
creationReason: 'ambiguous_outcome' as const,
|
|
707
|
+
blockingDecision: 'Correct the configuration/authorization or intentionally keep this schedule paused.',
|
|
708
|
+
recommendedDecision: 'Review the permanent blocker and explicitly decide whether to repair configuration and resume.',
|
|
709
|
+
recommendedPrompt: `Review permanently blocked maintenance occurrence ${occurrence.occurrenceId} for schedule ${schedule.scheduleId} and decide whether to repair and resume it.`,
|
|
710
|
+
statusSummary: 'Scheduled maintenance is permanently blocked pending a user decision.',
|
|
711
|
+
blockedBy: [decision],
|
|
712
|
+
attemptedActions: [`schedule:${schedule.scheduleId}`, `operation:${schedule.action.operation}`],
|
|
713
|
+
},
|
|
714
|
+
} : {}),
|
|
864
715
|
});
|
|
865
716
|
return failed.occurrence ?? blocked;
|
|
866
717
|
}
|
|
@@ -930,18 +781,7 @@ export async function evaluateSchedule(
|
|
|
930
781
|
outcome: 'failed',
|
|
931
782
|
decision: 'execute',
|
|
932
783
|
reason,
|
|
933
|
-
|
|
934
|
-
title: `GitHub issue watcher occurrence ${occurrence.occurrenceId} failed`,
|
|
935
|
-
summary: 'The local GitHub issue poll failed before Forge could compare issue state.',
|
|
936
|
-
reason,
|
|
937
|
-
creationReason: 'repeated_infrastructure_failure',
|
|
938
|
-
blockingDecision: 'Repair GitHub CLI authentication/connectivity before unattended issue monitoring resumes.',
|
|
939
|
-
recommendedDecision: 'Restore gh read access, then retrigger the watcher.',
|
|
940
|
-
recommendedPrompt: `Inspect GitHub issue watcher occurrence ${occurrence.occurrenceId} and restore the local read-only gh issue polling path.`,
|
|
941
|
-
statusSummary: 'GitHub issue watcher poll failed.',
|
|
942
|
-
blockedBy: ['github_issue_watch_failed'],
|
|
943
|
-
attemptedActions: [`schedule:${schedule.scheduleId}`, 'gh:api:issues'],
|
|
944
|
-
},
|
|
784
|
+
|
|
945
785
|
});
|
|
946
786
|
return failed.occurrence ?? occurrence;
|
|
947
787
|
}
|
|
@@ -960,9 +800,9 @@ export async function evaluateSchedule(
|
|
|
960
800
|
updateSchedule(controllerHome, schedule.repoId, schedule.scheduleId, () => ({ enabled: false, pausedReason: `Work ${workId} no longer exists.`, lastTriggeredAt: timestamp, lastOccurrenceId: occurrenceId }));
|
|
961
801
|
return decideOccurrence(controllerHome, schedule, occurrence, 'operation_blocked', 'skipped', `SCHEDULE_BROWSER_PROBE_WORK_NOT_FOUND:${workId}`);
|
|
962
802
|
}
|
|
963
|
-
if (
|
|
964
|
-
updateSchedule(controllerHome, schedule.repoId, schedule.scheduleId, () => ({ enabled: false, pausedReason: `Work ${workId} is terminal (${work.
|
|
965
|
-
return decideOccurrence(controllerHome, schedule, occurrence, 'nothing_to_do', 'skipped', `Work ${workId} is terminal (${work.
|
|
803
|
+
if (semanticWorkState(work) !== 'open') {
|
|
804
|
+
updateSchedule(controllerHome, schedule.repoId, schedule.scheduleId, () => ({ enabled: false, pausedReason: `Work ${workId} is terminal (${work.semanticState}).`, lastTriggeredAt: timestamp, lastOccurrenceId: occurrenceId }));
|
|
805
|
+
return decideOccurrence(controllerHome, schedule, occurrence, 'nothing_to_do', 'skipped', `Work ${workId} is terminal (${work.semanticState}); browser watcher stopped before probing.`);
|
|
966
806
|
}
|
|
967
807
|
}
|
|
968
808
|
|
|
@@ -1084,18 +924,7 @@ export async function evaluateSchedule(
|
|
|
1084
924
|
outcome: 'failed',
|
|
1085
925
|
decision: 'execute',
|
|
1086
926
|
reason,
|
|
1087
|
-
|
|
1088
|
-
title: `Browser watcher occurrence ${occurrence.occurrenceId} failed`,
|
|
1089
|
-
summary: 'A bounded browser probe failed before Forge could compare the external observation.',
|
|
1090
|
-
reason,
|
|
1091
|
-
creationReason: 'repeated_infrastructure_failure',
|
|
1092
|
-
blockingDecision: 'Repair browser/session readiness or update the watcher target before unattended probing resumes.',
|
|
1093
|
-
recommendedDecision: 'Inspect the browser plugin/session and retrigger the watcher after the target is readable.',
|
|
1094
|
-
recommendedPrompt: `Inspect browser watcher schedule ${schedule.scheduleId} for Work ${workId}, repair the failed browser probe, then retrigger one bounded occurrence.`,
|
|
1095
|
-
statusSummary: 'Scheduled browser watcher failed.',
|
|
1096
|
-
blockedBy: ['browser_probe_failed'],
|
|
1097
|
-
attemptedActions: [`schedule:${schedule.scheduleId}`, `work:${workId}`, 'operation:browser_probe'],
|
|
1098
|
-
},
|
|
927
|
+
|
|
1099
928
|
});
|
|
1100
929
|
updateSchedule(controllerHome, schedule.repoId, schedule.scheduleId, () => ({ lastTriggeredAt: timestamp, lastOccurrenceId: occurrenceId }));
|
|
1101
930
|
return failed.occurrence ?? saveOccurrence(controllerHome, { ...occurrence, status: 'failed', decision: 'execute', reason });
|
|
@@ -1160,22 +989,7 @@ export async function evaluateSchedule(
|
|
|
1160
989
|
outcome: 'failed',
|
|
1161
990
|
decision: 'execute',
|
|
1162
991
|
reason,
|
|
1163
|
-
|
|
1164
|
-
title: `Scheduled maintenance occurrence ${occurrence.occurrenceId} failed`,
|
|
1165
|
-
summary: 'A bounded live maintenance occurrence failed during deterministic apply and requires review before the schedule continues unattended.',
|
|
1166
|
-
reason,
|
|
1167
|
-
creationReason: 'repeated_infrastructure_failure',
|
|
1168
|
-
blockingDecision: 'Review the failed maintenance occurrence and decide whether the schedule should continue automatically.',
|
|
1169
|
-
recommendedDecision: 'Inspect the failed occurrence, fix the runtime blocker, then re-enable or retrigger the schedule intentionally.',
|
|
1170
|
-
recommendedPrompt: `Review schedule occurrence ${occurrence.occurrenceId} for ${schedule.scheduleId}, inspect the failed runtime maintenance action, and decide whether to resume automatic maintenance.`,
|
|
1171
|
-
statusSummary: 'Scheduled maintenance execution failed.',
|
|
1172
|
-
blockedBy: ['scheduled_execution_failed'],
|
|
1173
|
-
attemptedActions: [
|
|
1174
|
-
`schedule:${schedule.scheduleId}`,
|
|
1175
|
-
`operation:${schedule.action.operation}`,
|
|
1176
|
-
actionIdRaw ? `action:${actionIdRaw}` : 'action:unknown',
|
|
1177
|
-
],
|
|
1178
|
-
},
|
|
992
|
+
|
|
1179
993
|
});
|
|
1180
994
|
updateSchedule(controllerHome, schedule.repoId, schedule.scheduleId, () => ({
|
|
1181
995
|
lastTriggeredAt: timestamp,
|