@moretea-labs/forge 1.8.0 → 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 +70 -7
- package/CHANGELOG.md +14 -0
- package/CLAUDE.md +17 -2
- package/CONTRIBUTING.md +3 -2
- package/THIRD_PARTY_NOTICES.md +1 -1
- package/adapters/chatgpt/browser-delivery-host.ts +7 -1
- package/adapters/chatgpt/browser-delivery-runtime.ts +529 -56
- package/adapters/chatgpt/controller-binding-store.ts +101 -22
- package/adapters/chatgpt/controller-round-host.ts +15 -25
- package/adapters/chatgpt/controller-round-settlement-store.ts +58 -4
- package/adapters/chatgpt/provider-delivery.ts +228 -1
- package/adapters/chatgpt/work-conversation-binding-store.ts +79 -53
- 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-discovery.ts +11 -31
- package/adapters/computer/interaction-target-authority.ts +142 -18
- package/adapters/mcp/auth.ts +0 -1
- package/adapters/mcp/instructions.ts +5 -4
- package/adapters/mcp/multi-repository.ts +3 -19
- package/adapters/mcp/oauth.ts +73 -0
- package/adapters/mcp/paths.ts +4 -1
- 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 +411 -73
- package/adapters/mcp/runtime-gateway/context-pack-sidecar.ts +91 -0
- package/adapters/mcp/runtime-gateway/controller-authority-adapter.ts +20 -5
- package/adapters/mcp/runtime-gateway/core-capability-adapter.ts +258 -0
- package/adapters/mcp/runtime-gateway/engineering-preconditions.ts +10 -27
- package/adapters/mcp/runtime-gateway/engineering-tool-contract.ts +15 -0
- package/adapters/mcp/runtime-gateway/execution-tools.ts +8 -42
- package/adapters/mcp/runtime-gateway/gateway-execution-adapter.ts +2 -1
- package/adapters/mcp/runtime-gateway/plugin-adapter.ts +117 -45
- package/adapters/mcp/runtime-gateway/process-tools.ts +190 -22
- package/adapters/mcp/runtime-gateway/protected-computer-adapter.ts +16 -4
- package/adapters/mcp/runtime-gateway/recovery-adapter.ts +69 -52
- package/adapters/mcp/runtime-gateway/repository-compat-adapter.ts +4 -35
- package/adapters/mcp/runtime-gateway/result-adapter.ts +10 -4
- package/adapters/mcp/runtime-gateway/router.ts +18 -504
- package/adapters/mcp/runtime-gateway/routing-policy.ts +499 -0
- package/adapters/mcp/runtime-gateway/runtime-observation-adapter.ts +14 -65
- package/adapters/mcp/runtime-gateway/runtime-readiness-observation.ts +218 -0
- package/adapters/mcp/runtime-gateway/runtime-tool-definitions.ts +113 -173
- package/adapters/mcp/runtime-gateway/runtime-tools.ts +15 -5
- package/adapters/mcp/runtime-gateway/scheduler-adapter.ts +1 -0
- package/adapters/mcp/runtime-gateway/shared-adapter.ts +20 -0
- package/adapters/mcp/runtime-gateway/status-inbox-adapter.ts +358 -266
- package/adapters/mcp/runtime-gateway/typescript-navigation-sidecar.ts +136 -0
- package/adapters/mcp/runtime-gateway/work-adapter.ts +261 -3122
- 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-workflow-operations.ts +113 -0
- package/adapters/mcp/runtime-gateway/workflow-supervisor-adapter.ts +156 -0
- package/adapters/mcp/server.ts +67 -23
- package/adapters/mcp/setup.ts +1 -3
- package/adapters/mcp/tool-mapping/legacy-tool-service.ts +44 -170
- package/adapters/mcp/tool-mapping/post-finalize-work-attribution.ts +4 -9
- package/adapters/mcp/tool-mapping/repository-tools.ts +133 -142
- package/adapters/mcp/toolset-names.ts +5 -0
- package/adapters/mcp/toolset.ts +6 -5
- package/adapters/mcp/transports/http-observation.ts +365 -0
- package/adapters/mcp/transports/http.ts +154 -677
- package/adapters/mcp/transports/oauth-http.ts +322 -0
- package/adapters/mcp/transports/session-registry.ts +6 -0
- package/adapters/mcp/tunnels/openai-secure-tunnel.ts +89 -5
- package/assets/plugin-registry.v1.json +6 -4
- package/assets/reference-configs/agentic-development-flow.md +25 -0
- package/assets/reference-configs/global-working-rules.md +19 -0
- package/assets/skill-version.json +2 -2
- package/docs/architecture/CURRENT.md +111 -41
- 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/20260907-assistant-learning-loop.md +2 -0
- package/docs/architecture/decisions/20260907-controller-round-transition-policy.md +19 -4
- package/docs/architecture/decisions/20260916-workflow-supervisor-authority.md +249 -0
- package/docs/architecture/decisions/20260917-cognitive-memory-foundation.md +82 -0
- package/docs/architecture/decisions/20260918-stable-candidate-release-lifecycle.md +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 +1 -0
- package/docs/architecture/domains/workflow-engine.md +6 -0
- package/docs/architecture/modules/controller-runtime/transport-lifecycle.md +1 -1
- package/docs/forge-plugin-management.md +2 -2
- 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/releasing.md +2 -0
- package/docs/operations/standalone-disaster-recovery.md +14 -6
- package/docs/wiki/Implementation.md +1 -1
- package/package.json +25 -14
- package/packages/kernel/cognition/api/index.ts +6 -0
- package/packages/kernel/cognition/application/activation-service.ts +451 -0
- package/packages/kernel/cognition/application/consolidation-service.ts +185 -0
- package/packages/kernel/cognition/application/legacy-experience-adapter.ts +38 -0
- package/packages/kernel/cognition/application/memory-service.ts +64 -0
- package/packages/kernel/cognition/domain/learning.ts +106 -0
- package/packages/kernel/cognition/domain/memory.ts +254 -0
- package/packages/kernel/controller/api/index.ts +1 -0
- package/packages/kernel/controller/application/continuation-service.ts +281 -0
- package/packages/kernel/controller/application/controller-round-service.ts +12 -0
- package/packages/kernel/controller/domain/controller-round-transition-policy.ts +242 -21
- package/packages/kernel/controller/domain/controller-round.ts +4 -1
- package/packages/kernel/controller/domain/execution-quality.ts +3 -1
- package/packages/kernel/controller/infrastructure/controller-round-store.ts +689 -103
- package/packages/kernel/controller/infrastructure/controller-session-store.ts +297 -71
- package/packages/kernel/controller/ports/controller-host.ts +2 -0
- package/packages/kernel/identity/api/index.ts +10 -0
- package/packages/kernel/identity/domain/activity-projection.ts +43 -0
- package/packages/kernel/identity/domain/capability-broker.ts +60 -0
- package/packages/kernel/identity/domain/grant.ts +72 -0
- package/packages/kernel/identity/domain/owned-resource.ts +116 -0
- package/packages/kernel/identity/domain/user-request.ts +93 -0
- package/packages/kernel/identity/infrastructure/activity-projection-store.ts +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/owned-resource-store.ts +259 -0
- package/packages/kernel/identity/infrastructure/user-request-store.ts +182 -0
- package/packages/kernel/scheduler/api/index.ts +0 -2
- package/packages/kernel/scheduler/application/schedule-service.ts +3 -0
- package/packages/kernel/scheduler/application/settlement.ts +0 -15
- package/packages/kernel/scheduler/domain/schedule.ts +87 -0
- package/packages/kernel/scheduler/infrastructure/schedule-store.ts +153 -133
- package/packages/kernel/work/api/index.ts +3 -2
- package/packages/kernel/work/application/work-service.ts +17 -42
- package/packages/kernel/work/domain/current-task-lineage.ts +104 -0
- package/packages/kernel/work/domain/engineering-design.ts +10 -5
- package/packages/kernel/work/domain/engineering-profile.ts +8 -12
- package/packages/kernel/work/domain/evaluation-promotion-receipt.ts +186 -0
- package/packages/kernel/work/domain/execution-concurrency.ts +19 -26
- package/packages/kernel/work/domain/execution-snapshot.ts +0 -31
- package/packages/kernel/work/domain/implementation-review.ts +14 -331
- package/packages/kernel/work/domain/objective-graph.ts +119 -0
- package/packages/kernel/work/domain/project-engineering-contract.ts +23 -1
- package/packages/kernel/work/domain/repository-completion-receipt.ts +1 -1
- package/packages/kernel/work/domain/state-machine.ts +25 -63
- package/packages/kernel/work/domain/types.ts +57 -51
- package/packages/kernel/work/infrastructure/work-contract-store.ts +819 -728
- package/packages/kernel/work/ports/work-contract-store.ts +5 -2
- package/packages/plugin-runtime/browser/session-authority.ts +2 -1
- package/packages/plugin-runtime/computer/chatgpt-identity.ts +24 -0
- package/packages/plugin-runtime/computer/conversation-target.ts +143 -0
- package/packages/plugin-runtime/computer/index.ts +2 -0
- package/packages/plugin-runtime/computer/target-authority.ts +26 -1
- package/packages/plugin-runtime/external/unix-jsonl-transport.ts +142 -18
- package/packages/protocols/computer/contract.ts +27 -1
- package/scripts/activate-source-baseline.ts +7 -9
- package/scripts/canary-controller-semantic-wait.ts +12 -24
- package/scripts/check-mcp-compatibility.ts +48 -136
- package/scripts/check-runtime-architecture.mjs +622 -217
- package/scripts/forge-local-recovery-helper.mjs +93 -15
- package/scripts/lib/project-init-lib.sh +3 -0
- package/scripts/open-source-audit-allowlist.txt +1 -2
- package/scripts/run-bounded-command.mjs +5 -0
- package/scripts/run-governed-gate.ts +0 -1
- 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 +5 -0
- package/scripts/smoke-runtime-recovery.ts +12 -43
- package/scripts/smoke-schedule-engine.ts +23 -15
- package/scripts/smoke-unattended-transport-recovery.ts +223 -0
- package/scripts/smoke-user-request-continuation-restart.ts +232 -0
- package/scripts/smoke-workflow-supervisor-chrome-adapter.ts +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/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 +7 -3
- package/src/cli/commands/brain-assistant.ts +27 -13
- package/src/cli/commands/brain.ts +13 -15
- package/src/cli/commands/chatgpt.ts +1 -163
- package/src/cli/commands/recovery.ts +135 -121
- package/src/cli/commands/runtime.ts +3 -3
- package/src/cli/commands/setup-profile.ts +8 -0
- package/src/cli/controller/check-runner.ts +13 -2
- package/src/cli/controller/completion-backlog.ts +3 -3
- package/src/cli/controller/completion-orchestrator.ts +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-pack.ts +10 -8
- 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 +39 -1
- package/src/cli/editing/edit-session.ts +1 -7
- package/src/cli/local-bridge/console-automations.ts +18 -13
- package/src/cli/local-bridge/console-view-models.ts +3 -12
- package/src/cli/local-bridge/facade-api.ts +64 -191
- package/src/cli/local-bridge/server.ts +24 -147
- package/src/cli/local-bridge/types.ts +0 -1
- package/src/cli/mcp/oauth-client-retirement.ts +74 -0
- package/src/cli/repositories/command-executor.ts +29 -23
- package/src/cli/repositories/command-scope.ts +35 -16
- package/src/cli/repositories/controller-home.ts +48 -0
- package/src/cli/repositories/ephemeral-workspace.ts +20 -30
- package/src/cli/repositories/git-command-executor.ts +2 -2
- package/src/cli/repositories/registry.ts +77 -11
- package/src/cli/repositories/structured-git.ts +62 -2
- package/src/cli/repository/session-cache.ts +92 -6
- package/src/runtime/context/assistant-context.ts +20 -7
- package/src/runtime/context/assistant-work-context.ts +89 -27
- package/src/runtime/context/automatic-learning.ts +565 -0
- package/src/runtime/context/cognitive-attention.ts +173 -0
- package/src/runtime/context/cognitive-skill-canary.ts +158 -0
- package/src/runtime/context/context-closure.ts +46 -9
- package/src/runtime/context/context-pack-process.ts +103 -0
- package/src/runtime/context/context-plane.ts +1 -9
- package/src/runtime/context/direct-controller-learning.ts +298 -0
- package/src/runtime/context/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/cleanup-artifact-retention.ts +212 -9
- package/src/runtime/control-plane/concurrency/work-execution-concurrency.ts +9 -47
- package/src/runtime/control-plane/execution/controller-authority-recovery.ts +34 -4
- package/src/runtime/control-plane/execution/edit-validation-coordinator.ts +29 -20
- package/src/runtime/control-plane/execution/execution-identity.ts +23 -3
- package/src/runtime/control-plane/execution/repository-work-attribution.ts +7 -30
- package/src/runtime/control-plane/execution/retained-work-resume.ts +206 -199
- package/src/runtime/control-plane/execution/session-store.ts +31 -1
- package/src/runtime/control-plane/execution/validation.ts +6 -8
- package/src/runtime/control-plane/execution/work-authority-reconciler.ts +13 -42
- package/src/runtime/control-plane/execution/work-check-evidence.ts +137 -0
- package/src/runtime/control-plane/execution/work-completion-authority.ts +30 -85
- package/src/runtime/control-plane/execution/work-delivery-service.ts +497 -0
- package/src/runtime/control-plane/execution/work-evidence-policy.ts +12 -50
- package/src/runtime/control-plane/execution/work-execution-support.ts +50 -149
- package/src/runtime/control-plane/execution/work-handle-authority.ts +188 -109
- package/src/runtime/control-plane/execution/work-handle-store.ts +19 -43
- package/src/runtime/control-plane/execution/work-head-settlement.ts +53 -20
- package/src/runtime/control-plane/execution/work-lifecycle-audit.ts +52 -29
- package/src/runtime/control-plane/execution/work-operation-service.ts +43 -27
- package/src/runtime/control-plane/execution/work-preparation-service.ts +126 -266
- 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 +173 -186
- package/src/runtime/control-plane/execution/work-validation-reconciler.ts +28 -84
- package/src/runtime/control-plane/execution/work-verification-service.ts +406 -50
- package/src/runtime/control-plane/execution/work-verification-snapshot.ts +5 -1
- package/src/runtime/control-plane/facade/capability-registry.ts +362 -37
- package/src/runtime/control-plane/facade/check-normalization.ts +3 -9
- package/src/runtime/control-plane/facade/codex-delegation.ts +10 -11
- package/src/runtime/control-plane/facade/controller-connection.ts +135 -0
- package/src/runtime/control-plane/facade/goal-workloop-access.ts +1 -20
- package/src/runtime/control-plane/facade/goal-workloop.ts +281 -1753
- package/src/runtime/control-plane/facade/handoff-inbox-application.ts +12 -25
- package/src/runtime/control-plane/facade/handoff-inbox-store.ts +256 -52
- package/src/runtime/control-plane/facade/index.ts +0 -1
- package/src/runtime/control-plane/facade/operation-digest.ts +12 -15
- package/src/runtime/control-plane/facade/plan-contract-store.ts +451 -991
- package/src/runtime/control-plane/facade/policy-gate.ts +0 -23
- package/src/runtime/control-plane/facade/repository-work-admission.ts +12 -22
- package/src/runtime/control-plane/facade/requirement-authority.ts +102 -199
- package/src/runtime/control-plane/facade/requirement-board.ts +3 -3
- package/src/runtime/control-plane/facade/rh-work-operation-contract.ts +51 -14
- package/src/runtime/control-plane/facade/self-healing-loop.ts +18 -53
- package/src/runtime/control-plane/facade/suggested-actions.ts +15 -18
- package/src/runtime/control-plane/facade/types.ts +49 -108
- package/src/runtime/control-plane/facade/work-continuation.ts +8 -8
- package/src/runtime/control-plane/generated-cache-retention.ts +97 -1
- package/src/runtime/control-plane/global-scheduler/autonomous-continuation.ts +248 -0
- package/src/runtime/control-plane/global-scheduler/durable-admission.ts +1 -1
- package/src/runtime/control-plane/global-scheduler/maintenance.ts +239 -112
- package/src/runtime/control-plane/global-scheduler/reconciliation.ts +2 -1
- package/src/runtime/control-plane/global-scheduler/scheduler.ts +66 -40
- package/src/runtime/control-plane/global-scheduler/wake-signal.ts +42 -2
- package/src/runtime/control-plane/governance/access-policy.ts +19 -2
- package/src/runtime/control-plane/governance/authorization.ts +20 -3
- package/src/runtime/control-plane/launcher/chatgpt-round-continuation.ts +63 -300
- package/src/runtime/control-plane/launcher/chatgpt-work-continuation.ts +28 -300
- package/src/runtime/control-plane/launcher/local-conversation-controller.ts +238 -0
- package/src/runtime/control-plane/launcher/provider-mcp-bootstrap.ts +5 -2
- package/src/runtime/control-plane/launcher/thin-launcher.ts +96 -240
- package/src/runtime/control-plane/persistence/cognition-store.ts +820 -0
- package/src/runtime/control-plane/persistence/experience-store.ts +162 -29
- package/src/runtime/control-plane/persistence/requirement-store.ts +216 -74
- package/src/runtime/control-plane/persistence/sqlite-store.ts +113 -6
- package/src/runtime/control-plane/release-retention.ts +135 -47
- package/src/runtime/control-plane/repository-namespace-retention.ts +2 -2
- package/src/runtime/control-plane/runtime-cleanup.ts +290 -21
- package/src/runtime/control-plane/workspace/project-onboarding.ts +80 -0
- package/src/runtime/control-plane/workspace/semantic-sync-service.ts +19 -5
- package/src/runtime/control-plane/workspace/workspace-store.ts +169 -0
- package/src/runtime/diagnostics/incident-repair.ts +313 -146
- package/src/runtime/diagnostics/mcp-timing.ts +114 -0
- package/src/runtime/evidence/artifact-store.ts +158 -40
- package/src/runtime/evidence/evidence-store.ts +112 -8
- package/src/runtime/evidence/output-handle-index.ts +225 -0
- package/src/runtime/evidence/result-store.ts +158 -44
- package/src/runtime/execution/jobs/store.ts +3 -4
- package/src/runtime/execution/managed-workspace.ts +57 -0
- package/src/runtime/execution/process-runtime/check-facade.ts +1 -1
- package/src/runtime/execution/process-runtime/check-result-retention.ts +2 -2
- package/src/runtime/execution/process-runtime/check-result.ts +105 -1
- package/src/runtime/execution/process-runtime/check-runner-sidecar.ts +18 -8
- package/src/runtime/execution/process-runtime/command-facade.ts +79 -27
- package/src/runtime/execution/process-runtime/gc.ts +15 -2
- package/src/runtime/execution/process-runtime/handle-index.ts +176 -0
- package/src/runtime/execution/process-runtime/host-command-lane.ts +139 -0
- package/src/runtime/execution/process-runtime/index.ts +3 -0
- package/src/runtime/execution/process-runtime/lightweight-managed.ts +251 -72
- package/src/runtime/execution/process-runtime/persisted-check.ts +3 -3
- package/src/runtime/execution/process-runtime/process-runner-entry.ts +47 -5
- package/src/runtime/execution/process-runtime/process-scope.ts +160 -0
- package/src/runtime/execution/process-runtime/resource-claims.ts +65 -61
- package/src/runtime/execution/process-runtime/runtime.ts +35 -2
- package/src/runtime/execution/process-runtime/store.ts +30 -2
- package/src/runtime/execution/process-runtime/types.ts +6 -1
- package/src/runtime/execution/workers/executor.ts +2 -6
- package/src/runtime/platform/service-inventory.ts +130 -0
- package/src/runtime/platform/service-manager.ts +8 -0
- package/src/runtime/plugins/action-application.ts +85 -28
- package/src/runtime/plugins/app-store-connect-adapter.ts +38 -14
- package/src/runtime/plugins/browser-adapter.ts +757 -34
- package/src/runtime/plugins/browser-automation-service.ts +23 -3
- package/src/runtime/plugins/browser-macos-bridge.ts +321 -29
- package/src/runtime/plugins/browser-manifest-surface.ts +45 -11
- package/src/runtime/plugins/browser-native-session-service.ts +63 -13
- package/src/runtime/plugins/browser-registration.ts +16 -0
- package/src/runtime/plugins/browser-runtime.ts +14 -1
- package/src/runtime/plugins/browser-session-authority.ts +2 -2
- package/src/runtime/plugins/browser-session-store.ts +46 -76
- package/src/runtime/plugins/capability-authorization-grants.ts +258 -62
- package/src/runtime/plugins/computer-chatgpt-browser-adapter-installer.ts +219 -0
- package/src/runtime/plugins/computer-chatgpt-macos-target.ts +891 -0
- package/src/runtime/plugins/computer-registration.ts +222 -11
- package/src/runtime/plugins/desktop-operator-external-policy.ts +36 -4
- package/src/runtime/plugins/desktop-operator-registration.ts +12 -4
- package/src/runtime/plugins/external-adapter.ts +42 -6
- package/src/runtime/plugins/external-registration.ts +21 -1
- package/src/runtime/plugins/gmail-adapter.ts +23 -2
- package/src/runtime/plugins/google-calendar-adapter.ts +2 -2
- package/src/runtime/plugins/google-shared.ts +14 -7
- package/src/runtime/plugins/google-tasks-adapter.ts +2 -2
- package/src/runtime/plugins/ios-adapter.ts +1 -1
- package/src/runtime/plugins/lightweight-action.ts +208 -2
- package/src/runtime/plugins/local-system-adapter.ts +12 -2
- package/src/runtime/plugins/managed-process-adapter.ts +12 -5
- package/src/runtime/plugins/plugin-action-sidecar.ts +17 -13
- package/src/runtime/plugins/plugin-management-adapter.ts +1 -1
- package/src/runtime/plugins/store.ts +602 -428
- package/src/runtime/plugins/types.ts +20 -0
- package/src/runtime/plugins/xiaohongshu-publish.ts +16 -0
- package/src/runtime/projections/invalidation.ts +7 -3
- package/src/runtime/projections/materialized-view.ts +80 -36
- package/src/runtime/recovery/actions.ts +3 -3
- package/src/runtime/recovery/capability-action-application.ts +46 -45
- package/src/runtime/recovery/lifecycle-inventory.ts +29 -29
- package/src/runtime/recovery/maintenance-executor.ts +374 -123
- package/src/runtime/recovery/store.ts +29 -11
- 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/computer-composition.ts +191 -6
- package/src/runtime/root/controller-progression-composition.ts +192 -0
- package/src/runtime/root/controller-round-composition.ts +20 -1
- package/src/runtime/root/deployment-topology.ts +106 -0
- package/src/runtime/root/entry.ts +4 -3
- package/src/runtime/root/known-good-recovery.ts +184 -0
- package/src/runtime/root/local-bridge.ts +0 -1
- package/src/runtime/root/mcp-transport.ts +111 -18
- package/src/runtime/root/ownership.ts +261 -9
- package/src/runtime/root/package-connector-service.ts +105 -19
- package/src/runtime/root/package-runtime-release.ts +117 -18
- package/src/runtime/root/package-runtime-service.ts +17 -11
- package/src/runtime/root/release-execution-canary.ts +44 -12
- package/src/runtime/root/release-loader.ts +90 -8
- package/src/runtime/root/release-manifest.ts +80 -6
- package/src/runtime/root/release-materialize.ts +372 -28
- package/src/runtime/root/release-store.ts +395 -36
- package/src/runtime/root/runtime-lane.ts +191 -0
- package/src/runtime/root/runtime.ts +159 -27
- package/src/runtime/root/scheduled-controller-composition.ts +28 -3
- package/src/runtime/root/service-runner.ts +2 -2
- package/src/runtime/root/service.ts +36 -33
- package/src/runtime/root/status.ts +48 -0
- package/src/runtime/root/types.ts +32 -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/process-environment.ts +20 -9
- package/src/runtime/shared/response-budget.ts +1 -3
- package/src/runtime/standalone-recovery/controller-home-migration.ts +16 -24
- package/src/runtime/standalone-recovery/core.ts +3702 -342
- package/src/runtime/standalone-recovery/entry.ts +469 -39
- package/src/runtime/standalone-recovery/installer.ts +262 -148
- package/src/runtime/standalone-recovery/mcp-server.ts +29 -193
- package/src/runtime/standalone-recovery/operation-lock.ts +1 -1
- package/src/runtime/standalone-recovery/performance.ts +54 -16
- package/src/runtime/standalone-recovery/release.ts +53 -5
- package/src/runtime/standalone-recovery/service-labels.ts +5 -2
- package/src/runtime/standalone-recovery/watchdog-heartbeat.ts +5 -2
- package/src/runtime/workflow/schedules/browser-probe.ts +17 -6
- package/src/runtime/workflow/schedules/chatgpt-automation-migration.ts +10 -3
- package/src/runtime/workflow/schedules/engine.ts +138 -172
- package/src/runtime/workflow/schedules/work-continuation.ts +44 -5
- package/src/runtime/workflows/runtime.ts +15 -19
- package/src/testing/test-governance.ts +5 -1
- package/supervisor/chatgpt-conversation.ts +23 -0
- package/supervisor/client.ts +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/adapters/chatgpt/controller-host.ts +0 -119
- package/adapters/mcp/controller-round-compatibility.ts +0 -184
- package/adapters/mcp/frozen-client-semantic-compatibility.ts +0 -292
- package/adapters/mcp/runtime-gateway/work-compat-adapter.ts +0 -502
- package/packages/kernel/progression/api/index.ts +0 -2
- package/packages/kernel/progression/application/projector.ts +0 -211
- package/packages/kernel/progression/domain/types.ts +0 -116
- package/packages/kernel/progression/index.ts +0 -1
- package/packages/kernel/scheduler/application/continuation-service.ts +0 -212
- package/packages/kernel/scheduler/domain/continuation.ts +0 -38
- package/packages/kernel/scheduler/infrastructure/continuation-dispatch-store.ts +0 -38
- package/packages/kernel/work/domain/admission-policy.ts +0 -34
- package/scripts/benchmark-background-check-overlap.ts +0 -228
- package/scripts/benchmark-computer-hotpath.ts +0 -255
- package/scripts/benchmark-controller-hotpath.ts +0 -212
- package/scripts/benchmark-controller-round2.ts +0 -191
- package/scripts/benchmark-ios-agent-device.ts +0 -511
- package/scripts/benchmark-mcp-host.sh +0 -117
- package/scripts/benchmark-mcp-transport.ts +0 -169
- package/scripts/benchmark-operational-memory-activation.ts +0 -235
- package/scripts/benchmark-operational-shadow.ts +0 -28
- package/scripts/benchmark-quality-harness.ts +0 -146
- package/scripts/benchmark-route-session-concurrency.ts +0 -915
- package/scripts/benchmark-thin-harness-gateway-ab.ts +0 -632
- package/scripts/benchmark-thin-harness-mcp-e2e.ts +0 -498
- package/scripts/benchmark-thin-harness.ts +0 -251
- package/scripts/benchmark-typescript-navigation.ts +0 -186
- package/scripts/benchmark-work-efficiency.ts +0 -334
- package/scripts/build-controller-ui.ts +0 -28
- package/scripts/check-npm-release.sh +0 -32
- package/scripts/check-public-release-surface.sh +0 -19
- package/scripts/check-release-published.sh +0 -57
- package/scripts/check-release-readiness.sh +0 -37
- package/scripts/check-release-version.mjs +0 -74
- package/scripts/check-tarball-install-smoke.sh +0 -150
- 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/stage-runtime-release.ts +0 -44
- 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/content-equivalent-commit-authority.ts +0 -169
- package/src/runtime/control-plane/execution/direct-canonical-work-reconciliation.ts +0 -85
- package/src/runtime/control-plane/execution/direct-edit-work-completion.ts +0 -655
- package/src/runtime/control-plane/execution/work-finalization-service.ts +0 -2850
- package/src/runtime/control-plane/execution/work-path-scope.ts +0 -37
- package/src/runtime/control-plane/execution/work-task-receipt.ts +0 -468
- package/src/runtime/control-plane/facade/controller-round-relay.ts +0 -3
- package/src/runtime/control-plane/facade/work-admission-policy.ts +0 -142
- package/src/runtime/control-plane/facade/work-implementation-review.ts +0 -2
- package/src/runtime/control-plane/facade/work-state-machine.ts +0 -2
- package/src/runtime/control-plane/facade/work-task-projection.ts +0 -66
- package/src/runtime/control-plane/routing/index.ts +0 -1
- package/src/runtime/control-plane/routing/route-policy.ts +0 -401
- package/src/runtime/control-plane/routing/workspace-admission.ts +0 -70
|
@@ -4,34 +4,55 @@ import { runProcess } from '../../../src/effects/process-runner';
|
|
|
4
4
|
import type { MultiRepositoryMcpToolContext } from "../multi-repository";
|
|
5
5
|
import { allControllerToolDefinitions, controllerExposureSnapshot, controllerToolSurfaceStatus } from "../toolset";
|
|
6
6
|
import { result } from "./result-adapter";
|
|
7
|
-
import { selected } from "./shared-adapter";
|
|
8
|
-
import {
|
|
9
|
-
import { listExecutionJobs } from "../../../src/runtime/execution/jobs/store";
|
|
7
|
+
import { selected, selectedOptional } from "./shared-adapter";
|
|
8
|
+
import { SEMANTIC_SCOPE_KEY } from "../../../src/cli/repositories/controller-home";
|
|
10
9
|
import type { ExecutionJob } from '../../../src/runtime/execution/jobs/types';
|
|
11
10
|
import { getProcessRecord, isManagedProcessActive, processRuntimeResourceDiagnostics } from "../../../src/runtime/execution/process-runtime";
|
|
12
|
-
import {
|
|
13
|
-
import { readSchedulerHealthSnapshot } from "../../../src/runtime/control-plane/global-scheduler/scheduler";
|
|
14
|
-
import { evaluateActiveRuntimeSourceDrift, formatRuntimeSourceDriftMessage, readRuntimeGeneration, type RuntimeSourceIdentity } from "../../../src/runtime/control-plane/runtime-generation";
|
|
15
|
-
import { projectionObservation, readRepositoryProjectionSnapshot } from "../../../src/runtime/projections/materialized-view";
|
|
16
|
-
import { buildRuntimeOperationalView, classifyRuntimeReadinessSemantics, evaluateRuntimeHealth, RUNTIME_HEALTH_THRESHOLDS, type RuntimeOperationalView, type GradedObservation } from "../../../src/runtime/health";
|
|
17
|
-
import { buildControllerTaskLedgerProjection } from "../../../src/cli/controller/task-ledger";
|
|
18
|
-
import { legacyIssueAuthorityRetired } from "../../../src/cli/controller/legacy-issue-cutover";
|
|
11
|
+
import { formatRuntimeSourceDriftMessage, readRuntimeGeneration } from "../../../src/runtime/control-plane/runtime-generation";
|
|
19
12
|
import { listControllerChecks } from "../../../src/cli/controller/check-runner";
|
|
20
13
|
import { buildCheckExecutionSchedule } from "../../../src/runtime/execution/process-runtime/check-scheduling";
|
|
21
|
-
import { FORGE_MCP_SCHEMA_VERSION, FORGE_TOOL_SURFACE, FORGE_VERSION } from "../../../src/cli/controller/runtime-config";
|
|
22
|
-
import { resolveLocalBridgeSurface } from "../../../src/runtime/shared/local-bridge-surface";
|
|
23
14
|
import { listAssistantPluginManifests } from "../../../src/runtime/plugins/store";
|
|
24
15
|
import { cachedGitIdentity, gitSnapshot } from "../../../src/cli/repository/inspector";
|
|
25
16
|
import { buildRuntimeMaintenanceStatus } from "../../../src/runtime/recovery";
|
|
26
|
-
import { allowedFacadeOperations, buildFacadeResult, listCapabilityDescriptors, summarizeCapabilityGroups, listHandoffAttentionItems,
|
|
17
|
+
import { allowedFacadeOperations, buildFacadeResult, listCapabilityDescriptors, summarizeCapabilityGroups, listHandoffAttentionItems, normalizeCheckIds, buildWorkContinuationSnapshot, listPlanContracts, summarizePlanContract, runHandoffInboxApplication, type FacadeTool } from "../../../src/runtime/control-plane/facade";
|
|
27
18
|
import { buildJobOperationDigest } from '../../../src/runtime/control-plane/facade/operation-digest';
|
|
28
19
|
import { readActiveWorkCandidates, type InvalidActiveWorkCandidate } from "../../../packages/kernel/work/api/index";
|
|
29
20
|
import { observeRuntimeStatus } from "../../../src/runtime/root/status";
|
|
30
21
|
import { getControllerSession } from "../../../packages/kernel/controller/api/index";
|
|
22
|
+
import { listActiveOccurrences, listSchedules, scheduleOwnsWork } from "../../../packages/kernel/scheduler/api/index";
|
|
31
23
|
import { summarizeHandoffItem } from '../../../src/runtime/control-plane/facade';
|
|
32
24
|
import type { CallToolResult } from '../../../packages/protocols/mcp/tool-contract';
|
|
33
|
-
import {
|
|
25
|
+
import { triggerResolvedHandoffContinuation } from '../../../src/runtime/workflow/schedules/work-continuation';
|
|
26
|
+
import { getUserRequest, listUserRequests, recordUserRequest, resolveUserRequest, type UserRequest } from '../../../packages/kernel/identity/api/index';
|
|
27
|
+
import { controllerReadinessEvidence, runtimeSourceSnapshotStatus } from './runtime-readiness-observation';
|
|
28
|
+
import { readRuntimeReleaseAuthority } from '../../../src/runtime/root/release-store';
|
|
29
|
+
import { getWorkflowSupervisorConsumerStatus, getWorkflowSupervisorContinuationProof } from '../../../supervisor/client';
|
|
30
|
+
import { resolveWorkflowSupervisorForgeHome } from '../../../supervisor/paths';
|
|
31
|
+
export { ageMs, probeLocalControllerHealth, localControllerDiagnosticMatchesRuntime, controllerReadinessEvidence, runtimeSourceSnapshotStatus } from './runtime-readiness-observation';
|
|
32
|
+
export type { ControllerReadinessSignals } from './runtime-readiness-observation';
|
|
34
33
|
|
|
34
|
+
export const PRIMARY_WORK_RUNTIME_ACTIVITIES = [
|
|
35
|
+
'running',
|
|
36
|
+
'waiting_for_user',
|
|
37
|
+
'scheduled',
|
|
38
|
+
'recoverable',
|
|
39
|
+
'needs_reconciliation',
|
|
40
|
+
] as const;
|
|
41
|
+
export type PrimaryWorkRuntimeActivity = (typeof PRIMARY_WORK_RUNTIME_ACTIVITIES)[number];
|
|
42
|
+
|
|
43
|
+
/** Read-only runtime projection. These facts never mutate or extend semantic Work state. */
|
|
44
|
+
export function primaryWorkRuntimeActivity(facts: {
|
|
45
|
+
running: boolean;
|
|
46
|
+
waitingForUser: boolean;
|
|
47
|
+
scheduled: boolean;
|
|
48
|
+
needsReconciliation: boolean;
|
|
49
|
+
}): PrimaryWorkRuntimeActivity {
|
|
50
|
+
if (facts.running) return 'running';
|
|
51
|
+
if (facts.waitingForUser) return 'waiting_for_user';
|
|
52
|
+
if (facts.scheduled) return 'scheduled';
|
|
53
|
+
if (facts.needsReconciliation) return 'needs_reconciliation';
|
|
54
|
+
return 'recoverable';
|
|
55
|
+
}
|
|
35
56
|
|
|
36
57
|
export const GIT_IDENTITY_SAMPLE_TTL_MS = Math.max(1_000, Number(process.env.FORGE_GIT_IDENTITY_SAMPLE_TTL_MS ?? 3_000));
|
|
37
58
|
|
|
@@ -79,7 +100,7 @@ export function summarizeWorkListItem(job: ExecutionJob): Record<string, unknown
|
|
|
79
100
|
createdAt: job.createdAt,
|
|
80
101
|
updatedAt: job.updatedAt,
|
|
81
102
|
suggestedNextAction: digest.suggestedNextActions[0],
|
|
82
|
-
detailPointer: { tool: '
|
|
103
|
+
detailPointer: { tool: 'rh_work', operation: 'get', work_id: job.jobId },
|
|
83
104
|
};
|
|
84
105
|
}
|
|
85
106
|
|
|
@@ -103,210 +124,6 @@ export function invalidFacadeOperation(tool: FacadeTool, operation: string): Cal
|
|
|
103
124
|
}
|
|
104
125
|
|
|
105
126
|
|
|
106
|
-
export function ageMs(value: string | undefined): number | undefined {
|
|
107
|
-
if (!value) return undefined;
|
|
108
|
-
const parsed = Date.parse(value);
|
|
109
|
-
return Number.isFinite(parsed) ? Math.max(0, Date.now() - parsed) : undefined;
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
export async function probeLocalControllerHealth(endpoint: string | undefined): Promise<Record<string, unknown> | null> {
|
|
113
|
-
if (!endpoint) return null;
|
|
114
|
-
const controller = new AbortController();
|
|
115
|
-
const timeout = setTimeout(() => controller.abort(), 1_500);
|
|
116
|
-
try {
|
|
117
|
-
const url = new URL(endpoint);
|
|
118
|
-
url.pathname = '/health';
|
|
119
|
-
url.search = '';
|
|
120
|
-
url.hash = '';
|
|
121
|
-
const response = await fetch(url, { signal: controller.signal, headers: { accept: 'application/json' } });
|
|
122
|
-
if (!response.ok) return null;
|
|
123
|
-
return await response.json() as Record<string, unknown>;
|
|
124
|
-
} catch {
|
|
125
|
-
return null;
|
|
126
|
-
} finally {
|
|
127
|
-
clearTimeout(timeout);
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
export function localControllerDiagnosticMatchesRuntime(
|
|
132
|
-
payload: Record<string, unknown> | null,
|
|
133
|
-
expected: { generation?: string } = {},
|
|
134
|
-
): boolean {
|
|
135
|
-
return payload?.status === 'ok'
|
|
136
|
-
&& payload.toolSurface === FORGE_TOOL_SURFACE
|
|
137
|
-
&& payload.schemaVersion === FORGE_MCP_SCHEMA_VERSION
|
|
138
|
-
&& payload.version === FORGE_VERSION
|
|
139
|
-
&& (expected.generation === undefined || payload.generation === expected.generation);
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
export interface ControllerReadinessSignals {
|
|
143
|
-
externalEndpoint?: GradedObservation;
|
|
144
|
-
mcpHandshake?: GradedObservation;
|
|
145
|
-
sessionContinuity?: GradedObservation;
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
export async function controllerReadinessEvidence(
|
|
149
|
-
ctx: MultiRepositoryMcpToolContext,
|
|
150
|
-
repository = ctx.explicitRepository,
|
|
151
|
-
signals: ControllerReadinessSignals = {},
|
|
152
|
-
) {
|
|
153
|
-
const daemon = readForgeRuntimeStatus(ctx.controllerHome);
|
|
154
|
-
const scheduler = readSchedulerHealthSnapshot(ctx.controllerHome);
|
|
155
|
-
const projectionSnapshot = repository ? readRepositoryProjectionSnapshot(ctx.controllerHome, repository.repoId) : undefined;
|
|
156
|
-
const projection = projectionSnapshot?.projection;
|
|
157
|
-
const taskLedger = repository && !legacyIssueAuthorityRetired(repository.canonicalRoot)
|
|
158
|
-
? buildControllerTaskLedgerProjection(repository.canonicalRoot)
|
|
159
|
-
: undefined;
|
|
160
|
-
const projectionReconciliation = projectionSnapshot
|
|
161
|
-
? reconcileReadinessProjectionSource(projectionSnapshot, taskLedger)
|
|
162
|
-
: undefined;
|
|
163
|
-
const localBridgeSurface = repository
|
|
164
|
-
? resolveLocalBridgeSurface({
|
|
165
|
-
controllerHome: ctx.controllerHome,
|
|
166
|
-
repoRoot: repository.canonicalRoot,
|
|
167
|
-
allowProcessScan: false,
|
|
168
|
-
})
|
|
169
|
-
: undefined;
|
|
170
|
-
const localBridgeEndpoint = localBridgeSurface?.endpoint;
|
|
171
|
-
const shouldProbeLocalBridge = Boolean(
|
|
172
|
-
localBridgeSurface?.enabled
|
|
173
|
-
&& localBridgeSurface.endpointConfigured
|
|
174
|
-
&& localBridgeEndpoint
|
|
175
|
-
&& localBridgeSurface.mode !== 'disabled',
|
|
176
|
-
);
|
|
177
|
-
const localBridgeLiveHealth = shouldProbeLocalBridge
|
|
178
|
-
? await probeLocalControllerHealth(localBridgeEndpoint)
|
|
179
|
-
: null;
|
|
180
|
-
const localBridgeEndpointReachable = localBridgeLiveHealth !== null;
|
|
181
|
-
const localBridgeExpectedSurface = shouldProbeLocalBridge
|
|
182
|
-
? localControllerDiagnosticMatchesRuntime(localBridgeLiveHealth, {
|
|
183
|
-
generation: localBridgeSurface?.generation,
|
|
184
|
-
})
|
|
185
|
-
: true;
|
|
186
|
-
const schedulerHeartbeatAgeMs = ageMs(scheduler.lastTickAt);
|
|
187
|
-
const dispatchHeartbeatAgeMs = ageMs(scheduler.lastDispatchAt);
|
|
188
|
-
const localBridgeObservation = {
|
|
189
|
-
enabled: localBridgeSurface?.enabled ?? false,
|
|
190
|
-
requiredForReadiness: localBridgeSurface?.requiredForReadiness ?? false,
|
|
191
|
-
mode: localBridgeSurface?.mode ?? ('disabled' as const),
|
|
192
|
-
endpoint: localBridgeEndpoint,
|
|
193
|
-
endpointReachable: shouldProbeLocalBridge ? localBridgeEndpointReachable : true,
|
|
194
|
-
expectedSurface: localBridgeExpectedSurface,
|
|
195
|
-
processAlive: localBridgeSurface?.processRunning,
|
|
196
|
-
runtimeStateFresh: localBridgeSurface?.source === 'service-runtime'
|
|
197
|
-
|| localBridgeSurface?.source === 'repo-runtime',
|
|
198
|
-
error: localBridgeSurface?.error,
|
|
199
|
-
};
|
|
200
|
-
const runtimeHealth = evaluateRuntimeHealth({
|
|
201
|
-
daemon: {
|
|
202
|
-
status: daemon.status,
|
|
203
|
-
error: daemon.error,
|
|
204
|
-
// Scheduler ticks are emitted by the Canonical Forge Runtime process and provide
|
|
205
|
-
// its continuously refreshed heartbeat without introducing a second timer.
|
|
206
|
-
heartbeatAgeMs: schedulerHeartbeatAgeMs,
|
|
207
|
-
},
|
|
208
|
-
scheduler: {
|
|
209
|
-
status: daemon.degraded ? 'degraded' : daemon.status,
|
|
210
|
-
heartbeatAgeMs: schedulerHeartbeatAgeMs,
|
|
211
|
-
dispatchHeartbeatAgeMs,
|
|
212
|
-
},
|
|
213
|
-
workers: {
|
|
214
|
-
queueDepth: projection?.queueDepth,
|
|
215
|
-
runningWorkers: projection?.runningWorkers,
|
|
216
|
-
activeLeases: projection?.activeLeases,
|
|
217
|
-
activeAttentionCount: projection?.currentAttention.length,
|
|
218
|
-
},
|
|
219
|
-
projection: projectionSnapshot ? projectionObservation(projectionSnapshot, projectionReconciliation) : {
|
|
220
|
-
readable: true,
|
|
221
|
-
persisted: true,
|
|
222
|
-
},
|
|
223
|
-
localBridge: localBridgeObservation,
|
|
224
|
-
runtimeStorage: { readable: true, ready: true },
|
|
225
|
-
...signals,
|
|
226
|
-
});
|
|
227
|
-
const operationalView: RuntimeOperationalView = buildRuntimeOperationalView({
|
|
228
|
-
health: runtimeHealth,
|
|
229
|
-
handoffs: repository
|
|
230
|
-
? listHandoffItems({ controllerHome: ctx.controllerHome, repoId: repository.repoId, status: 'all', limit: 100 })
|
|
231
|
-
: [],
|
|
232
|
-
jobs: repository ? listExecutionJobs(ctx.controllerHome, repository.repoId, 100) : [],
|
|
233
|
-
});
|
|
234
|
-
const reasons: Array<{ code: string; message: string }> = runtimeHealth.activeBlockers.map((item) => ({
|
|
235
|
-
code: item.code === 'SCHEDULER_NOT_PROGRESSING'
|
|
236
|
-
? 'DISPATCH_LOOP_STALLED'
|
|
237
|
-
: item.code === 'LEASE_WITHOUT_WORKER' || item.code === 'WORKER_NOT_RUNNING'
|
|
238
|
-
? 'WORKER_NOT_RUNNING'
|
|
239
|
-
: item.code,
|
|
240
|
-
message: item.message,
|
|
241
|
-
}));
|
|
242
|
-
if (
|
|
243
|
-
reasons.some((item) => item.code === 'WORKER_NOT_RUNNING')
|
|
244
|
-
&& (dispatchHeartbeatAgeMs === undefined || dispatchHeartbeatAgeMs > RUNTIME_HEALTH_THRESHOLDS.queueProgressStaleMs)
|
|
245
|
-
) {
|
|
246
|
-
reasons.push({
|
|
247
|
-
code: 'QUEUE_NOT_PROGRESSING',
|
|
248
|
-
message: 'Queued Jobs have not received a recent dispatch heartbeat.',
|
|
249
|
-
});
|
|
250
|
-
}
|
|
251
|
-
const ready = runtimeHealth.ready;
|
|
252
|
-
return {
|
|
253
|
-
ready,
|
|
254
|
-
state: ready ? runtimeHealth.state === 'healthy' ? 'ready' as const : 'degraded' as const : daemon.status === 'ready' ? 'degraded' as const : 'not_ready' as const,
|
|
255
|
-
reasons,
|
|
256
|
-
warnings: runtimeHealth.warnings.map((item) => ({ code: item.code, message: item.message })),
|
|
257
|
-
health: runtimeHealth,
|
|
258
|
-
operationalView,
|
|
259
|
-
daemon,
|
|
260
|
-
durableScheduler: {
|
|
261
|
-
status: runtimeHealth.components.scheduler.ready ? 'ready' : daemon.status === 'ready' ? 'degraded' : 'not_ready',
|
|
262
|
-
loopStartedAt: scheduler.loopStartedAt,
|
|
263
|
-
lastTickAt: scheduler.lastTickAt,
|
|
264
|
-
lastDispatchAt: scheduler.lastDispatchAt,
|
|
265
|
-
lastReconcileAt: scheduler.lastReconcileAt,
|
|
266
|
-
heartbeatAgeMs: schedulerHeartbeatAgeMs,
|
|
267
|
-
dispatchHeartbeatAgeMs,
|
|
268
|
-
},
|
|
269
|
-
workerLoop: {
|
|
270
|
-
status: projection?.runningWorkers ? 'running' : projection?.queueDepth ? 'idle' : 'ready',
|
|
271
|
-
queueDepth: projection?.queueDepth ?? 0,
|
|
272
|
-
runningWorkers: projection?.runningWorkers ?? 0,
|
|
273
|
-
activeLeases: projection?.activeLeases ?? 0,
|
|
274
|
-
activeAttentionCount: projection?.currentAttention.length ?? 0,
|
|
275
|
-
consuming: (projection?.queueDepth ?? 0) === 0 || (projection?.runningWorkers ?? 0) > 0,
|
|
276
|
-
},
|
|
277
|
-
localBridge: repository ? {
|
|
278
|
-
running: Boolean(localBridgeSurface?.enabled)
|
|
279
|
-
&& runtimeHealth.components.localBridge.ready
|
|
280
|
-
&& (!shouldProbeLocalBridge || (localBridgeEndpointReachable && localBridgeExpectedSurface)),
|
|
281
|
-
endpoint: localBridgeEndpoint,
|
|
282
|
-
error: localBridgeSurface?.error,
|
|
283
|
-
inferredPid: localBridgeSurface?.pid,
|
|
284
|
-
statusSource: localBridgeSurface?.source ?? 'none',
|
|
285
|
-
health: runtimeHealth.components.localBridge,
|
|
286
|
-
} : undefined,
|
|
287
|
-
projection,
|
|
288
|
-
projectionSnapshot,
|
|
289
|
-
taskLedger,
|
|
290
|
-
projectionReconciliation,
|
|
291
|
-
semantics: classifyRuntimeReadinessSemantics(runtimeHealth),
|
|
292
|
-
};
|
|
293
|
-
}
|
|
294
|
-
|
|
295
|
-
export function runtimeSourceSnapshotStatus(
|
|
296
|
-
active: RuntimeSourceIdentity | undefined,
|
|
297
|
-
currentRuntimeRoot?: string,
|
|
298
|
-
) {
|
|
299
|
-
const drift = evaluateActiveRuntimeSourceDrift(active, {
|
|
300
|
-
currentRuntimeRoot,
|
|
301
|
-
});
|
|
302
|
-
return {
|
|
303
|
-
current: drift.current,
|
|
304
|
-
restartRequired: drift.restartRequired,
|
|
305
|
-
reasons: drift.reasons,
|
|
306
|
-
code: drift.code,
|
|
307
|
-
};
|
|
308
|
-
}
|
|
309
|
-
|
|
310
127
|
export function repositoryExecutionReadiness(
|
|
311
128
|
repoRoot: string,
|
|
312
129
|
availableChecks: ReturnType<typeof listControllerChecks>,
|
|
@@ -406,21 +223,35 @@ export async function callStatusInboxAdapter(
|
|
|
406
223
|
ports: StatusInboxAdapterPorts,
|
|
407
224
|
): Promise<CallToolResult | undefined> {
|
|
408
225
|
if (name === 'rh_status') {
|
|
409
|
-
const repository =
|
|
226
|
+
const repository = selectedOptional(ctx, args);
|
|
410
227
|
const operation = String(args.operation ?? 'get');
|
|
411
228
|
if (!allowedFacadeOperations('rh_status').includes(operation)) {
|
|
412
229
|
return invalidFacadeOperation('rh_status', operation);
|
|
413
230
|
}
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
231
|
+
// Instance-level status stays available with zero (or several) registered
|
|
232
|
+
// repositories: only the repository-derived sections need a target.
|
|
233
|
+
const store = repository
|
|
234
|
+
? {
|
|
235
|
+
controllerHome: ctx.controllerHome,
|
|
236
|
+
repoId: repository.repoId,
|
|
237
|
+
revisionContains: (ancestorRevision: string, descendantRevision: string) =>
|
|
238
|
+
repositoryRevisionContains(repository.canonicalRoot, ancestorRevision, descendantRevision),
|
|
239
|
+
}
|
|
240
|
+
: undefined;
|
|
420
241
|
if (operation === 'repair') {
|
|
242
|
+
if (!repository) {
|
|
243
|
+
return result(buildFacadeResult({
|
|
244
|
+
status: 'blocked',
|
|
245
|
+
summary: 'REPOSITORY_CONTEXT_REQUIRED_FOR_REPAIR: rh_status repair needs an explicit repository target.',
|
|
246
|
+
data: { operation, repositoryContext: null },
|
|
247
|
+
}) as unknown as Record<string, unknown>, true);
|
|
248
|
+
}
|
|
421
249
|
return await ports.repair(ctx, repository, args);
|
|
422
250
|
}
|
|
423
|
-
const
|
|
251
|
+
const requestedDetailLevel = args.detail_level === 'detail' ? 'detail' : 'summary';
|
|
252
|
+
// Repository detail needs a repository; the instance-level summary remains
|
|
253
|
+
// available and reports the downgrade explicitly instead of failing.
|
|
254
|
+
const detailLevel = repository ? requestedDetailLevel : 'summary';
|
|
424
255
|
if (detailLevel === 'summary') {
|
|
425
256
|
const startedAt = performance.now();
|
|
426
257
|
let summaryTimingMark = startedAt;
|
|
@@ -435,8 +266,8 @@ export async function callStatusInboxAdapter(
|
|
|
435
266
|
// Summary answers only whether this repository can work now. Reuse one
|
|
436
267
|
// porcelain-v2 sample for branch/HEAD/dirty and avoid the full Git
|
|
437
268
|
// status/diff-stat, access-policy, and inventory construction paths.
|
|
438
|
-
const repositoryIdentity = cachedGitIdentity(repository.canonicalRoot);
|
|
439
|
-
const repositoryIdentityAgeMs = Math.max(0, Date.now() - repositoryIdentity.sampledAt);
|
|
269
|
+
const repositoryIdentity = repository ? cachedGitIdentity(repository.canonicalRoot) : undefined;
|
|
270
|
+
const repositoryIdentityAgeMs = repositoryIdentity ? Math.max(0, Date.now() - repositoryIdentity.sampledAt) : undefined;
|
|
440
271
|
markSummaryPhase('git');
|
|
441
272
|
const runtimeGeneration = readRuntimeGeneration(ctx.controllerHome);
|
|
442
273
|
const runtimeSource = runtimeSourceSnapshotStatus(
|
|
@@ -457,29 +288,39 @@ export async function callStatusInboxAdapter(
|
|
|
457
288
|
: 'RUNTIME_SOURCE_SNAPSHOT_STALE');
|
|
458
289
|
const runtimeReadiness = observation.snapshot?.readiness;
|
|
459
290
|
const releaseDiagnostic = runtimeReadiness?.diagnostics.releaseCoherence;
|
|
460
|
-
const activeWorkProjection =
|
|
291
|
+
const activeWorkProjection = repository && store
|
|
292
|
+
? readActiveWorkCandidates({ ...store, limit: 3 })
|
|
293
|
+
: { contracts: [], invalid: [] };
|
|
461
294
|
const activeWorkSnapshot = activeWorkProjection.contracts.map((entry) => ({
|
|
462
295
|
workId: entry.workId,
|
|
463
|
-
|
|
464
|
-
mode: entry.mode,
|
|
296
|
+
state: entry.semanticState,
|
|
465
297
|
objective: entry.objective.slice(0, 160),
|
|
466
298
|
semantics: buildWorkContinuationSnapshot(entry).semantics,
|
|
467
299
|
nextSafeAction: buildWorkContinuationSnapshot(entry).nextSafeAction,
|
|
468
300
|
}));
|
|
469
|
-
|
|
470
|
-
|
|
301
|
+
// Plans are authored semantic context: without a repository target the
|
|
302
|
+
// instance-level semantic scope carries them.
|
|
303
|
+
const activePlanSnapshot = (repository && store
|
|
304
|
+
? listPlanContracts({ ...store, status: 'active', limit: 3 })
|
|
305
|
+
: listPlanContracts({ controllerHome: ctx.controllerHome, scopeKey: SEMANTIC_SCOPE_KEY, status: 'active', limit: 3 })
|
|
306
|
+
).map(summarizePlanContract);
|
|
307
|
+
const pendingHandoffAttention = store ? listHandoffAttentionItems(store, 100) : [];
|
|
471
308
|
const pendingHandoffSnapshot = pendingHandoffAttention.slice(0, 4);
|
|
472
309
|
const pendingHandoffCount = pendingHandoffAttention.length;
|
|
473
310
|
markSummaryPhase('controller_state');
|
|
474
|
-
const preferredFacadeTools = ['rh_access', 'rh_status', 'rh_inbox', 'rh_context', 'rh_work'] as const;
|
|
311
|
+
const preferredFacadeTools = ['rh_access', 'rh_status', 'rh_inbox', 'rh_context', 'rh_work', 'capability_execute'] as const;
|
|
475
312
|
const facade = buildFacadeResult({
|
|
476
313
|
status: ready ? 'ok' : 'blocked',
|
|
477
314
|
summary: ready ? 'Controller and MCP tool surface are ready for bounded work.' : 'Controller or MCP tool surface needs attention before work.',
|
|
478
315
|
data: {
|
|
479
316
|
operation,
|
|
480
|
-
repoId: repository.repoId,
|
|
317
|
+
...(repository ? { repoId: repository.repoId } : {}),
|
|
318
|
+
/** Null means this answer is ForgeInstance-scoped, not repository-scoped. */
|
|
319
|
+
repositoryContext: repository ? { repoId: repository.repoId, checkoutId: repository.activeCheckoutId } : null,
|
|
320
|
+
requestedDetailLevel,
|
|
481
321
|
readiness: {
|
|
482
322
|
ready,
|
|
323
|
+
readyFor: 'bounded_execution',
|
|
483
324
|
reasonCodes: [...new Set(reasonCodes)],
|
|
484
325
|
diagnostics: {
|
|
485
326
|
runtime: { ready: observation.ready },
|
|
@@ -503,6 +344,11 @@ export async function callStatusInboxAdapter(
|
|
|
503
344
|
},
|
|
504
345
|
semantics: {
|
|
505
346
|
executionReady: observation.ready,
|
|
347
|
+
// Summary is intentionally the cheap Runtime snapshot path. It
|
|
348
|
+
// reports bounded execution readiness without pretending that the
|
|
349
|
+
// full scheduler/worker diagnostics for unattended continuation ran.
|
|
350
|
+
autonomousContinuationReady: null,
|
|
351
|
+
autonomousContinuationBlockers: null,
|
|
506
352
|
maintenanceHealthy: null,
|
|
507
353
|
maintenanceCandidateCount: 0,
|
|
508
354
|
releaseReady: releaseDiagnostic?.outcome === 'pass',
|
|
@@ -513,21 +359,23 @@ export async function callStatusInboxAdapter(
|
|
|
513
359
|
},
|
|
514
360
|
observedAt: observation.observedAt,
|
|
515
361
|
},
|
|
516
|
-
repositoryState:
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
362
|
+
repositoryState: repositoryIdentity
|
|
363
|
+
? {
|
|
364
|
+
branch: repositoryIdentity.branch,
|
|
365
|
+
head: repositoryIdentity.head,
|
|
366
|
+
dirty: repositoryIdentity.dirty,
|
|
367
|
+
observedAt: new Date(repositoryIdentity.sampledAt).toISOString(),
|
|
368
|
+
observationAgeMs: repositoryIdentityAgeMs,
|
|
369
|
+
observationMaxAgeMs: GIT_IDENTITY_SAMPLE_TTL_MS,
|
|
370
|
+
observationPolicy: 'bounded_sample_with_mutation_invalidation',
|
|
371
|
+
sourceSnapshotAgeMs: runtimeGeneration?.source.observedAt
|
|
372
|
+
? Math.max(0, Date.now() - Date.parse(runtimeGeneration.source.observedAt))
|
|
373
|
+
: undefined,
|
|
374
|
+
sourceSnapshotStale,
|
|
375
|
+
sourceSnapshotReasons: runtimeSource.reasons,
|
|
376
|
+
runtimeSourceDirty: runtimeSource.current?.dirty === true,
|
|
377
|
+
}
|
|
378
|
+
: null,
|
|
531
379
|
toolArchitecture: {
|
|
532
380
|
facadeTools: [...preferredFacadeTools],
|
|
533
381
|
domainSchemaLoading: 'status_summary_runtime_snapshot',
|
|
@@ -581,6 +429,15 @@ export async function callStatusInboxAdapter(
|
|
|
581
429
|
(payload.responseMeta as { structuredPayloadBytes: number }).structuredPayloadBytes = Buffer.byteLength(JSON.stringify(payload), 'utf8');
|
|
582
430
|
return result(payload, facade.status !== 'ok');
|
|
583
431
|
}
|
|
432
|
+
// Detail is repository-derived; without a repository target the requested
|
|
433
|
+
// detail level was already downgraded to the instance-level summary above.
|
|
434
|
+
if (!repository || !store) {
|
|
435
|
+
return result(buildFacadeResult({
|
|
436
|
+
status: 'blocked',
|
|
437
|
+
summary: 'REPOSITORY_CONTEXT_REQUIRED_FOR_DETAIL: rh_status detail needs an explicit repository target.',
|
|
438
|
+
data: { operation, repositoryContext: null },
|
|
439
|
+
}) as unknown as Record<string, unknown>, true);
|
|
440
|
+
}
|
|
584
441
|
const detailTimingStartedAt = performance.now();
|
|
585
442
|
let detailTimingMark = detailTimingStartedAt;
|
|
586
443
|
const detailPhaseTimingsMs: Record<string, number> = {};
|
|
@@ -647,8 +504,77 @@ export async function callStatusInboxAdapter(
|
|
|
647
504
|
});
|
|
648
505
|
}
|
|
649
506
|
const toolSurfaceComputed = exposure.expectedToolNames.length > 0 || exposure.actualToolNames.length > 0 || toolSurfaceReady;
|
|
507
|
+
const activeReleaseAuthority = readRuntimeReleaseAuthority(ctx.controllerHome);
|
|
508
|
+
let autonomousContinuationProof: Awaited<ReturnType<typeof getWorkflowSupervisorContinuationProof>>;
|
|
509
|
+
let autonomousContinuationProofObservation: 'proven' | 'missing' | 'unavailable' = 'missing';
|
|
510
|
+
if (activeReleaseAuthority?.committedAt) {
|
|
511
|
+
try {
|
|
512
|
+
autonomousContinuationProof = await getWorkflowSupervisorContinuationProof(
|
|
513
|
+
resolveWorkflowSupervisorForgeHome(ctx.controllerHome),
|
|
514
|
+
{
|
|
515
|
+
repoId: repository.repoId,
|
|
516
|
+
activeReleaseId: activeReleaseAuthority.active.releaseId,
|
|
517
|
+
notBefore: activeReleaseAuthority.committedAt,
|
|
518
|
+
},
|
|
519
|
+
);
|
|
520
|
+
autonomousContinuationProofObservation = autonomousContinuationProof ? 'proven' : 'missing';
|
|
521
|
+
} catch {
|
|
522
|
+
autonomousContinuationProofObservation = 'unavailable';
|
|
523
|
+
}
|
|
524
|
+
}
|
|
525
|
+
let autonomousContinuationConsumerStatus: Awaited<ReturnType<typeof getWorkflowSupervisorConsumerStatus>> | undefined;
|
|
526
|
+
let autonomousContinuationConsumerObservation: 'observed' | 'unavailable' = 'unavailable';
|
|
527
|
+
try {
|
|
528
|
+
autonomousContinuationConsumerStatus = await getWorkflowSupervisorConsumerStatus(
|
|
529
|
+
resolveWorkflowSupervisorForgeHome(ctx.controllerHome),
|
|
530
|
+
);
|
|
531
|
+
autonomousContinuationConsumerObservation = 'observed';
|
|
532
|
+
} catch {
|
|
533
|
+
autonomousContinuationConsumerObservation = 'unavailable';
|
|
534
|
+
}
|
|
535
|
+
const dueConsumerFailure = Boolean(
|
|
536
|
+
autonomousContinuationConsumerStatus?.dueCommand
|
|
537
|
+
&& autonomousContinuationConsumerStatus.lastFailure
|
|
538
|
+
&& (!autonomousContinuationConsumerStatus.lastFailure.effectId
|
|
539
|
+
|| autonomousContinuationConsumerStatus.lastFailure.effectId === autonomousContinuationConsumerStatus.dueCommand.effectId),
|
|
540
|
+
);
|
|
541
|
+
const autonomousContinuationConsumerReady = autonomousContinuationConsumerObservation === 'observed'
|
|
542
|
+
&& autonomousContinuationConsumerStatus?.enabled === true
|
|
543
|
+
&& autonomousContinuationConsumerStatus.running === true
|
|
544
|
+
&& autonomousContinuationConsumerStatus.lastTickStartedAt !== undefined
|
|
545
|
+
&& autonomousContinuationConsumerStatus.stalled === false
|
|
546
|
+
&& !dueConsumerFailure;
|
|
547
|
+
const autonomousContinuationReady = readiness.ready
|
|
548
|
+
&& toolSurfaceReady
|
|
549
|
+
&& !sourceSnapshotStale
|
|
550
|
+
&& autonomousContinuationProofObservation === 'proven'
|
|
551
|
+
&& autonomousContinuationConsumerReady;
|
|
552
|
+
const autonomousContinuationBlockers = [...new Set([
|
|
553
|
+
...readinessReasons
|
|
554
|
+
.map((reason) => reason.code)
|
|
555
|
+
.filter((code): code is string => typeof code === 'string' && code.length > 0),
|
|
556
|
+
...(autonomousContinuationProofObservation === 'proven'
|
|
557
|
+
? []
|
|
558
|
+
: [autonomousContinuationProofObservation === 'unavailable'
|
|
559
|
+
? 'AUTONOMOUS_CONTINUATION_LIVE_PROOF_UNAVAILABLE'
|
|
560
|
+
: 'AUTONOMOUS_CONTINUATION_LIVE_PROOF_MISSING']),
|
|
561
|
+
...(autonomousContinuationConsumerObservation === 'unavailable'
|
|
562
|
+
? ['AUTONOMOUS_CONTINUATION_CONSUMER_STATUS_UNAVAILABLE']
|
|
563
|
+
: autonomousContinuationConsumerStatus?.enabled !== true
|
|
564
|
+
? ['AUTONOMOUS_CONTINUATION_CONSUMER_DISABLED']
|
|
565
|
+
: autonomousContinuationConsumerStatus.running !== true
|
|
566
|
+
? ['AUTONOMOUS_CONTINUATION_CONSUMER_NOT_RUNNING']
|
|
567
|
+
: autonomousContinuationConsumerStatus.lastTickStartedAt === undefined
|
|
568
|
+
? ['AUTONOMOUS_CONTINUATION_CONSUMER_NOT_OBSERVED']
|
|
569
|
+
: autonomousContinuationConsumerStatus.stalled
|
|
570
|
+
? ['AUTONOMOUS_CONTINUATION_CONSUMER_STALLED']
|
|
571
|
+
: dueConsumerFailure
|
|
572
|
+
? ['AUTONOMOUS_CONTINUATION_CONSUMER_DEGRADED']
|
|
573
|
+
: []),
|
|
574
|
+
])];
|
|
650
575
|
const readinessWithToolSurface = {
|
|
651
576
|
ready: effectiveReady,
|
|
577
|
+
readyFor: 'bounded_execution' as const,
|
|
652
578
|
reasonCodes: [...new Set(
|
|
653
579
|
readinessReasons
|
|
654
580
|
.map((reason) => reason.code)
|
|
@@ -672,6 +598,22 @@ export async function callStatusInboxAdapter(
|
|
|
672
598
|
},
|
|
673
599
|
semantics: {
|
|
674
600
|
executionReady,
|
|
601
|
+
// Runtime/tool health is necessary but not sufficient. Thin acceptance
|
|
602
|
+
// requires a fresh exact-active-release Supervisor ledger proof of
|
|
603
|
+
// CONTINUE -> CONTINUE -> DONE spanning at least one Runtime reconnect.
|
|
604
|
+
autonomousContinuationReady,
|
|
605
|
+
autonomousContinuationBlockers,
|
|
606
|
+
autonomousContinuationConsumer: {
|
|
607
|
+
observation: autonomousContinuationConsumerObservation,
|
|
608
|
+
...(autonomousContinuationConsumerStatus ? { status: autonomousContinuationConsumerStatus } : {}),
|
|
609
|
+
},
|
|
610
|
+
autonomousContinuationProof: {
|
|
611
|
+
observation: autonomousContinuationProofObservation,
|
|
612
|
+
activeReleaseId: activeReleaseAuthority?.active.releaseId,
|
|
613
|
+
activeReleaseAuthorityRevision: activeReleaseAuthority?.revision,
|
|
614
|
+
activeReleaseCommittedAt: activeReleaseAuthority?.committedAt,
|
|
615
|
+
...(autonomousContinuationProof ? { proof: autonomousContinuationProof } : {}),
|
|
616
|
+
},
|
|
675
617
|
maintenanceHealthy,
|
|
676
618
|
maintenanceCandidateCount,
|
|
677
619
|
maintenanceObservation,
|
|
@@ -712,14 +654,62 @@ export async function callStatusInboxAdapter(
|
|
|
712
654
|
.map((processId) => getProcessRecord(ctx.controllerHome, repository.repoId, processId))
|
|
713
655
|
.filter((process): process is NonNullable<typeof process> => Boolean(process && isManagedProcessActive(process)));
|
|
714
656
|
markDetailPhase('process_state');
|
|
715
|
-
const
|
|
716
|
-
const
|
|
717
|
-
|
|
657
|
+
const activePrimaryWorkIds = new Set(activePrimaryWork.map((contract) => contract.workId));
|
|
658
|
+
const activeProcessWorkIds = new Set(
|
|
659
|
+
activeProcessRecords
|
|
660
|
+
.map((process) => process.workId)
|
|
661
|
+
.filter((workId): workId is string => Boolean(workId && activePrimaryWorkIds.has(workId))),
|
|
662
|
+
);
|
|
663
|
+
const activeControllerWorkIds = new Set(
|
|
664
|
+
activePrimaryWork
|
|
665
|
+
.filter((contract) => Boolean(getControllerSession({ controllerHome: ctx.controllerHome, repoId: repository.repoId }, contract.workId)))
|
|
666
|
+
.map((contract) => contract.workId),
|
|
667
|
+
);
|
|
668
|
+
const runningPrimaryWorkIds = new Set([...activeProcessWorkIds, ...activeControllerWorkIds]);
|
|
718
669
|
markDetailPhase('controller_sessions');
|
|
719
|
-
|
|
670
|
+
|
|
671
|
+
const waitingForUserPrimaryWorkIds = new Set(
|
|
672
|
+
pendingHandoffAttention
|
|
673
|
+
.map((item) => item.workId?.trim())
|
|
674
|
+
.filter((workId): workId is string => Boolean(workId && activePrimaryWorkIds.has(workId))),
|
|
675
|
+
);
|
|
676
|
+
const schedules = listSchedules(ctx.controllerHome, repository.repoId);
|
|
677
|
+
const activeOccurrenceScheduleIds = new Set(
|
|
678
|
+
listActiveOccurrences(ctx.controllerHome, repository.repoId).map((occurrence) => occurrence.scheduleId),
|
|
679
|
+
);
|
|
680
|
+
const scheduledPrimaryWorkIds = new Set<string>();
|
|
681
|
+
for (const schedule of schedules) {
|
|
682
|
+
if (!schedule.enabled && !activeOccurrenceScheduleIds.has(schedule.scheduleId)) continue;
|
|
683
|
+
for (const workId of activePrimaryWorkIds) {
|
|
684
|
+
if (scheduleOwnsWork(schedule, workId)) scheduledPrimaryWorkIds.add(workId);
|
|
685
|
+
}
|
|
686
|
+
}
|
|
687
|
+
const primaryWorkActivities = activePrimaryWork.map((contract) => ({
|
|
688
|
+
workId: contract.workId,
|
|
689
|
+
activity: primaryWorkRuntimeActivity({
|
|
690
|
+
running: runningPrimaryWorkIds.has(contract.workId),
|
|
691
|
+
waitingForUser: waitingForUserPrimaryWorkIds.has(contract.workId),
|
|
692
|
+
scheduled: scheduledPrimaryWorkIds.has(contract.workId),
|
|
693
|
+
needsReconciliation: buildWorkContinuationSnapshot(contract).reconciliationRequired,
|
|
694
|
+
}),
|
|
695
|
+
}));
|
|
696
|
+
const primaryWorkActivityCounts: Record<PrimaryWorkRuntimeActivity, number> = {
|
|
697
|
+
running: 0,
|
|
698
|
+
waiting_for_user: 0,
|
|
699
|
+
scheduled: 0,
|
|
700
|
+
recoverable: 0,
|
|
701
|
+
needs_reconciliation: 0,
|
|
702
|
+
};
|
|
703
|
+
for (const projection of primaryWorkActivities) primaryWorkActivityCounts[projection.activity] += 1;
|
|
704
|
+
markDetailPhase('work_activity');
|
|
705
|
+
const preferredFacadeTools = ['rh_access', 'rh_status', 'rh_inbox', 'rh_context', 'rh_work', 'capability_execute'] as const;
|
|
720
706
|
const facade = buildFacadeResult({
|
|
721
707
|
status: effectiveReady ? 'ok' : 'blocked',
|
|
722
|
-
summary: effectiveReady
|
|
708
|
+
summary: effectiveReady
|
|
709
|
+
? autonomousContinuationReady
|
|
710
|
+
? 'Controller and MCP tool surface are ready for bounded work and autonomous continuation.'
|
|
711
|
+
: 'Controller and MCP tool surface are ready for bounded work; autonomous continuation needs attention.'
|
|
712
|
+
: 'Controller or MCP tool surface needs attention before bounded work.',
|
|
723
713
|
data: {
|
|
724
714
|
operation,
|
|
725
715
|
repoId: repository.repoId,
|
|
@@ -750,8 +740,8 @@ export async function callStatusInboxAdapter(
|
|
|
750
740
|
activePrimaryWorkCount: activePrimaryWork.length,
|
|
751
741
|
activeExecutionChildCount: activeExecutionChildren.length,
|
|
752
742
|
activeProcessCount: activeProcessRecords.length,
|
|
753
|
-
|
|
754
|
-
|
|
743
|
+
primaryWorkActivityCounts,
|
|
744
|
+
primaryWorkActivities,
|
|
755
745
|
activeContractCount: activeContracts.length,
|
|
756
746
|
invalidActiveContractCount: activeWorkProjection.invalid.length,
|
|
757
747
|
invalidActiveContracts: activeWorkProjection.invalid.slice(0, 10).map(summarizeInvalidActiveWorkCandidate),
|
|
@@ -792,10 +782,118 @@ export async function callStatusInboxAdapter(
|
|
|
792
782
|
return undefined;
|
|
793
783
|
}
|
|
794
784
|
|
|
785
|
+
function summarizeUserRequest(request: UserRequest) {
|
|
786
|
+
return {
|
|
787
|
+
requestId: request.requestId,
|
|
788
|
+
kind: request.kind,
|
|
789
|
+
title: request.title,
|
|
790
|
+
summary: request.summary,
|
|
791
|
+
actionRequired: request.actionRequired,
|
|
792
|
+
status: request.status,
|
|
793
|
+
targetScope: request.targetScope,
|
|
794
|
+
resolution: request.resolution,
|
|
795
|
+
updatedAt: request.updatedAt,
|
|
796
|
+
};
|
|
797
|
+
}
|
|
798
|
+
|
|
799
|
+
// `request_id` is Process Runtime idempotency/correlation only. UserRequest
|
|
800
|
+
// selection stays on `handoff_id` so retry identity can never change Inbox semantics.
|
|
801
|
+
export function findCanonicalUserRequest(controllerHome: string, args: Record<string, unknown>): UserRequest | undefined {
|
|
802
|
+
const handoffId = typeof args.handoff_id === 'string' ? args.handoff_id.trim() : '';
|
|
803
|
+
if (!handoffId) return undefined;
|
|
804
|
+
return getUserRequest(controllerHome, handoffId)
|
|
805
|
+
?? listUserRequests(controllerHome, 'all').find((request) => request.presentation?.legacyHandoffId === handoffId);
|
|
806
|
+
}
|
|
807
|
+
|
|
808
|
+
export function shouldUseCanonicalUserRequestInbox(
|
|
809
|
+
repositoryRepoId: string | undefined,
|
|
810
|
+
operation: string,
|
|
811
|
+
request: UserRequest | undefined,
|
|
812
|
+
): boolean {
|
|
813
|
+
if (!repositoryRepoId) return true;
|
|
814
|
+
if (operation === 'list' || operation === 'create') return false;
|
|
815
|
+
return Boolean(request && !request.targetScope?.repoId?.trim());
|
|
816
|
+
}
|
|
817
|
+
|
|
818
|
+
function callCanonicalUserRequestInbox(ctx: MultiRepositoryMcpToolContext, args: Record<string, unknown>, operation: string): CallToolResult {
|
|
819
|
+
const limit = Math.max(1, Math.min(Math.trunc(typeof args.limit === 'number' ? args.limit : 50), 100));
|
|
820
|
+
if (operation === 'list') {
|
|
821
|
+
const items = listUserRequests(ctx.controllerHome, 'pending').slice(0, limit);
|
|
822
|
+
return result(buildFacadeResult({
|
|
823
|
+
summary: items.length ? `${items.length} pending UserRequest item(s).` : 'No pending UserRequest items.',
|
|
824
|
+
data: { items: items.map(summarizeUserRequest) },
|
|
825
|
+
suggestedNextActions: items.slice(0, 1).map((item) => ({ label: `Read ${item.requestId}`, tool: 'rh_inbox', operation: 'get', payload: { handoff_id: item.requestId }, risk: 'readonly' as const })),
|
|
826
|
+
}) as unknown as Record<string, unknown>);
|
|
827
|
+
}
|
|
828
|
+
if (operation === 'create') {
|
|
829
|
+
const title = typeof args.title === 'string' ? args.title.trim() : '';
|
|
830
|
+
const summary = typeof args.summary === 'string' ? args.summary.trim() : typeof args.reason === 'string' ? args.reason.trim() : '';
|
|
831
|
+
if (!title || !summary) throw new Error('USER_REQUEST_TITLE_SUMMARY_REQUIRED');
|
|
832
|
+
const workId = typeof args.work_id === 'string' ? args.work_id.trim() : '';
|
|
833
|
+
const explicitId = typeof args.handoff_id === 'string' ? args.handoff_id.trim() : '';
|
|
834
|
+
const actionRequired = (typeof args.action_required === 'string' ? args.action_required : 'product_decision') as 'login' | 'grant_permission' | 'confirm_destructive' | 'product_decision';
|
|
835
|
+
const kind = (typeof args.request_kind === 'string' ? args.request_kind : actionRequired === 'product_decision' ? 'user_decision_request' : 'user_action_request') as 'user_action_request' | 'user_decision_request';
|
|
836
|
+
const rootCauseKey = typeof args.root_cause_key === 'string' && args.root_cause_key.trim()
|
|
837
|
+
? args.root_cause_key.trim()
|
|
838
|
+
: `rh_inbox:${explicitId || workId || title}:${summary}`;
|
|
839
|
+
const item = recordUserRequest(ctx.controllerHome, {
|
|
840
|
+
...(explicitId ? { requestId: explicitId } : {}),
|
|
841
|
+
kind,
|
|
842
|
+
rootCauseKey,
|
|
843
|
+
title,
|
|
844
|
+
summary,
|
|
845
|
+
actionRequired,
|
|
846
|
+
...(workId ? { targetScope: { scopeKind: 'work', scopeId: workId, workId } } : {}),
|
|
847
|
+
presentation: {
|
|
848
|
+
...(typeof args.handoff_id === 'string' && args.handoff_id.trim() ? { legacyHandoffId: args.handoff_id.trim() } : {}),
|
|
849
|
+
...(typeof args.reason === 'string' ? { reason: args.reason } : {}),
|
|
850
|
+
...(typeof args.recommended_decision === 'string' ? { recommendedDecision: args.recommended_decision } : {}),
|
|
851
|
+
...(typeof args.recommended_prompt === 'string' ? { recommendedPrompt: args.recommended_prompt } : {}),
|
|
852
|
+
},
|
|
853
|
+
});
|
|
854
|
+
return result(buildFacadeResult({ summary: `Created UserRequest ${item.requestId}.`, data: { item: summarizeUserRequest(item) } }) as unknown as Record<string, unknown>);
|
|
855
|
+
}
|
|
856
|
+
const current = findCanonicalUserRequest(ctx.controllerHome, args);
|
|
857
|
+
if (operation === 'get') {
|
|
858
|
+
const facade = buildFacadeResult({
|
|
859
|
+
status: current ? 'ok' : 'not_found',
|
|
860
|
+
summary: current ? `UserRequest ${current.requestId}.` : 'UserRequest not found.',
|
|
861
|
+
data: { item: current ? summarizeUserRequest(current) : undefined },
|
|
862
|
+
suggestedNextActions: current?.status === 'pending' ? [{ label: 'Resolve request', tool: 'rh_inbox', operation: 'resolve', payload: { request_id: current.requestId }, risk: 'workspace_write' }] : [],
|
|
863
|
+
});
|
|
864
|
+
return result(facade as unknown as Record<string, unknown>, facade.status === 'not_found');
|
|
865
|
+
}
|
|
866
|
+
if (!current) throw new Error('USER_REQUEST_NOT_FOUND');
|
|
867
|
+
if (operation === 'ack' || operation === 'accept') {
|
|
868
|
+
return result(buildFacadeResult({
|
|
869
|
+
summary: `${operation === 'accept' ? 'Accepted' : 'Acknowledged'} UserRequest ${current.requestId}; semantic state remains pending until resolve/dismiss.`,
|
|
870
|
+
data: { item: summarizeUserRequest(current), compatibilityNoop: true },
|
|
871
|
+
}) as unknown as Record<string, unknown>);
|
|
872
|
+
}
|
|
873
|
+
if (operation === 'resolve' || operation === 'dismiss') {
|
|
874
|
+
const decision = operation === 'dismiss'
|
|
875
|
+
? (typeof args.decision === 'string' && args.decision.trim() ? args.decision.trim() : 'dismissed')
|
|
876
|
+
: (typeof args.decision === 'string' ? args.decision.trim() : '');
|
|
877
|
+
if (!decision) throw new Error('USER_REQUEST_DECISION_REQUIRED');
|
|
878
|
+
const resolved = resolveUserRequest(ctx.controllerHome, {
|
|
879
|
+
requestId: current.requestId,
|
|
880
|
+
decision,
|
|
881
|
+
resolvedBy: typeof args.resolver === 'string' && args.resolver.trim() ? args.resolver.trim() : (ctx.principalId?.trim() || 'mcp-user'),
|
|
882
|
+
});
|
|
883
|
+
return result(buildFacadeResult({ summary: `Resolved UserRequest ${resolved.requestId}.`, data: { item: summarizeUserRequest(resolved) } }) as unknown as Record<string, unknown>);
|
|
884
|
+
}
|
|
885
|
+
throw new Error(`USER_REQUEST_OPERATION_UNSUPPORTED:${operation}`);
|
|
886
|
+
}
|
|
887
|
+
|
|
795
888
|
async function callInboxAdapter(ctx: MultiRepositoryMcpToolContext, args: Record<string, unknown>): Promise<CallToolResult> {
|
|
796
|
-
const repository =
|
|
889
|
+
const repository = selectedOptional(ctx, args);
|
|
797
890
|
const operation = String(args.operation ?? 'list');
|
|
798
891
|
if (!allowedFacadeOperations('rh_inbox').includes(operation)) return invalidFacadeOperation('rh_inbox', operation);
|
|
892
|
+
const canonicalRequest = findCanonicalUserRequest(ctx.controllerHome, args);
|
|
893
|
+
if (shouldUseCanonicalUserRequestInbox(repository?.repoId, operation, canonicalRequest)) {
|
|
894
|
+
return callCanonicalUserRequestInbox(ctx, args, operation);
|
|
895
|
+
}
|
|
896
|
+
if (!repository) throw new Error('REPOSITORY_CONTEXT_REQUIRED_FOR_HANDOFF');
|
|
799
897
|
const app = await runHandoffInboxApplication({
|
|
800
898
|
operation: operation as 'get' | 'list' | 'ack' | 'accept' | 'resolve' | 'dismiss' | 'create',
|
|
801
899
|
store: { controllerHome: ctx.controllerHome, repoId: repository.repoId },
|
|
@@ -814,13 +912,7 @@ async function callInboxAdapter(ctx: MultiRepositoryMcpToolContext, args: Record
|
|
|
814
912
|
resolver: typeof args.resolver === 'string' ? args.resolver : undefined,
|
|
815
913
|
controllerIdentity: { principalId: ctx.principalId, sessionId: ctx.sessionId },
|
|
816
914
|
}, {
|
|
817
|
-
triggerResolvedContinuation: (item) =>
|
|
818
|
-
ctx.controllerHome,
|
|
819
|
-
repository.repoId,
|
|
820
|
-
handoffResolvedContinuationEventName(item.id),
|
|
821
|
-
`handoff:${item.id}:${item.updatedAt}`,
|
|
822
|
-
{ workId: item.workId, data: { handoffId: item.id, status: item.status, decision: item.decision } },
|
|
823
|
-
),
|
|
915
|
+
triggerResolvedContinuation: (item) => triggerResolvedHandoffContinuation(ctx.controllerHome, repository.repoId, item),
|
|
824
916
|
});
|
|
825
917
|
if (operation === 'get') {
|
|
826
918
|
const item = 'item' in app ? app.item : undefined;
|