@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
|
@@ -1,26 +1,73 @@
|
|
|
1
1
|
import type { CallToolResult } from '../../../packages/protocols/mcp/tool-contract';
|
|
2
|
+
import { FORGE_INSTANCE_SCOPE_KEY } from '../../../src/cli/repositories/controller-home';
|
|
2
3
|
import type { MultiRepositoryMcpToolContext } from '../multi-repository';
|
|
3
4
|
import { buildWorkspaceAuthStatus, prepareWorkspaceAuthLogin, summarizePluginForLowInterception } from '../../../src/runtime/safe-tooling';
|
|
4
5
|
import {
|
|
5
6
|
assistantPluginScope,
|
|
6
|
-
controllerPluginRepository,
|
|
7
7
|
getAssistantPluginManifest,
|
|
8
|
+
getControllerPluginManifest,
|
|
8
9
|
listAssistantPluginManifests,
|
|
10
|
+
listControllerPluginManifests,
|
|
9
11
|
} from '../../../src/runtime/plugins/store';
|
|
10
12
|
import { executeAssistantPluginActionApplication } from '../../../src/runtime/plugins/action-application';
|
|
11
13
|
import { mcpPluginExecutionOrigin } from '../../../src/runtime/plugins/execution-origin';
|
|
12
14
|
import type { AssistantPluginManifest } from '../../../src/runtime/plugins/types';
|
|
13
15
|
import { result, resultWithPluginArtifactImages } from './result-adapter';
|
|
16
|
+
import { boundedRuntimeResult } from './bounded-result-runtime';
|
|
14
17
|
import { selected } from './shared-adapter';
|
|
15
18
|
|
|
16
|
-
|
|
19
|
+
type PluginTransportScope =
|
|
20
|
+
| { kind: 'controller' }
|
|
21
|
+
| { kind: 'repository'; repository: ReturnType<typeof selected> };
|
|
22
|
+
|
|
23
|
+
function explicitRepositoryContextRequested(args: Record<string, unknown>): boolean {
|
|
24
|
+
return (typeof args.repo_id === 'string' && Boolean(args.repo_id.trim()))
|
|
25
|
+
|| (typeof args.checkout_id === 'string' && Boolean(args.checkout_id.trim()));
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function pluginTransportScope(
|
|
17
29
|
ctx: MultiRepositoryMcpToolContext,
|
|
18
30
|
args: Record<string, unknown>,
|
|
19
31
|
pluginId: string,
|
|
20
|
-
) {
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
32
|
+
): PluginTransportScope {
|
|
33
|
+
const explicitRepoId = typeof args.repo_id === 'string' ? args.repo_id.trim() : '';
|
|
34
|
+
if (explicitRepoId === '__controller__') {
|
|
35
|
+
throw new Error('PLUGIN_CONTROLLER_REPOSITORY_SENTINEL_RETIRED: controller-scoped plugins no longer use a synthetic repository id');
|
|
36
|
+
}
|
|
37
|
+
const scope = assistantPluginScope(pluginId, ctx.controllerHome);
|
|
38
|
+
if (scope === 'controller') return { kind: 'controller' };
|
|
39
|
+
if (scope === 'controller_with_repository_overlay') {
|
|
40
|
+
return explicitRepositoryContextRequested(args)
|
|
41
|
+
? { kind: 'repository', repository: selected(ctx, args) }
|
|
42
|
+
: { kind: 'controller' };
|
|
43
|
+
}
|
|
44
|
+
return { kind: 'repository', repository: selected(ctx, args) };
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function pluginManifestForScope(
|
|
48
|
+
ctx: MultiRepositoryMcpToolContext,
|
|
49
|
+
scope: PluginTransportScope,
|
|
50
|
+
pluginId: string,
|
|
51
|
+
): AssistantPluginManifest {
|
|
52
|
+
return scope.kind === 'controller'
|
|
53
|
+
? getControllerPluginManifest(ctx.controllerHome, pluginId)
|
|
54
|
+
: getAssistantPluginManifest(ctx.controllerHome, scope.repository, pluginId);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function pluginScopeLabel(scope: PluginTransportScope): 'controller' | 'repository' {
|
|
58
|
+
return scope.kind;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function detailArgumentsForScope(
|
|
62
|
+
scope: PluginTransportScope,
|
|
63
|
+
pluginId: string,
|
|
64
|
+
actionId?: string,
|
|
65
|
+
): Record<string, unknown> {
|
|
66
|
+
return {
|
|
67
|
+
...(scope.kind === 'repository' ? { repo_id: scope.repository.repoId } : {}),
|
|
68
|
+
capability_id: actionId ? `plugin.${pluginId}.${actionId}` : `plugin.${pluginId}`,
|
|
69
|
+
detail_level: 'detail',
|
|
70
|
+
};
|
|
24
71
|
}
|
|
25
72
|
|
|
26
73
|
function summarizePlugin(manifest: AssistantPluginManifest): Record<string, unknown> {
|
|
@@ -93,20 +140,17 @@ export async function callPluginAdapter(
|
|
|
93
140
|
): Promise<CallToolResult | undefined> {
|
|
94
141
|
switch (name) {
|
|
95
142
|
case 'list_plugins': {
|
|
96
|
-
const
|
|
97
|
-
const controllerPlugins = listAssistantPluginManifests(ctx.controllerHome, controllerRepository, {
|
|
143
|
+
const controllerPlugins = listControllerPluginManifests(ctx.controllerHome, {
|
|
98
144
|
forceRefresh: true,
|
|
99
145
|
}).map(summarizePlugin);
|
|
100
146
|
let repositoryPlugins: ReturnType<typeof summarizePlugin>[] = [];
|
|
101
147
|
let repositoryId: string | undefined;
|
|
102
|
-
|
|
148
|
+
if (explicitRepositoryContextRequested(args)) {
|
|
103
149
|
const repository = selected(ctx, args);
|
|
104
150
|
repositoryId = repository.repoId;
|
|
105
151
|
repositoryPlugins = listAssistantPluginManifests(ctx.controllerHome, repository, {
|
|
106
152
|
forceRefresh: true,
|
|
107
153
|
}).map(summarizePlugin);
|
|
108
|
-
} catch (error) {
|
|
109
|
-
if (typeof args.repo_id === 'string' && args.repo_id.trim()) throw error;
|
|
110
154
|
}
|
|
111
155
|
return result({
|
|
112
156
|
scope: repositoryPlugins.length > 0 ? 'combined' : 'controller',
|
|
@@ -117,16 +161,16 @@ export async function callPluginAdapter(
|
|
|
117
161
|
}
|
|
118
162
|
case 'get_plugin': {
|
|
119
163
|
const pluginId = String(args.plugin_id ?? '').trim();
|
|
120
|
-
const
|
|
164
|
+
const scope = pluginTransportScope(ctx, args, pluginId);
|
|
121
165
|
return result({
|
|
122
|
-
scope:
|
|
123
|
-
plugin: summarizePlugin(
|
|
166
|
+
scope: pluginScopeLabel(scope),
|
|
167
|
+
plugin: summarizePlugin(pluginManifestForScope(ctx, scope, pluginId)),
|
|
124
168
|
});
|
|
125
169
|
}
|
|
126
170
|
case 'plugin_action_execute': {
|
|
127
171
|
const pluginId = String(args.plugin_id ?? '').trim();
|
|
128
172
|
const workId = typeof args.work_id === 'string' && args.work_id.trim() ? args.work_id.trim() : undefined;
|
|
129
|
-
const
|
|
173
|
+
const scope = pluginTransportScope(ctx, args, pluginId);
|
|
130
174
|
const workRepository = workId ? selected(ctx, args) : undefined;
|
|
131
175
|
const actionId = String(args.action_id ?? '').trim();
|
|
132
176
|
const requestId = String(args.request_id ?? '').trim();
|
|
@@ -148,14 +192,25 @@ export async function callPluginAdapter(
|
|
|
148
192
|
};
|
|
149
193
|
const application = await executeAssistantPluginActionApplication({
|
|
150
194
|
controllerHome: ctx.controllerHome,
|
|
151
|
-
|
|
195
|
+
scope: scope.kind === 'controller'
|
|
196
|
+
? { kind: 'controller' }
|
|
197
|
+
: { kind: 'repository', repository: scope.repository },
|
|
152
198
|
request,
|
|
153
|
-
interactiveWaitMs: typeof args.interactive_wait_ms === 'number' ? args.interactive_wait_ms : 750,
|
|
154
|
-
wait: args.wait === true,
|
|
199
|
+
interactiveWaitMs: args.apply_mode === 'async' ? 0 : (typeof args.interactive_wait_ms === 'number' ? args.interactive_wait_ms : 750),
|
|
200
|
+
wait: args.apply_mode === 'async' ? false : args.wait === true,
|
|
155
201
|
waitMs: typeof args.wait_ms === 'number' ? args.wait_ms : 15_000,
|
|
156
202
|
});
|
|
157
203
|
|
|
158
204
|
if (application.kind === 'direct_read') {
|
|
205
|
+
const resultScopeRepoId = scope.kind === 'repository' ? scope.repository.repoId : FORGE_INSTANCE_SCOPE_KEY;
|
|
206
|
+
const boundedPluginResult = boundedRuntimeResult({
|
|
207
|
+
controllerHome: ctx.controllerHome,
|
|
208
|
+
repoId: resultScopeRepoId,
|
|
209
|
+
sessionId: ctx.sessionId,
|
|
210
|
+
principalId: ctx.principalId,
|
|
211
|
+
controllerInstanceId: ctx.controllerInstanceId,
|
|
212
|
+
workId,
|
|
213
|
+
}, application.result);
|
|
159
214
|
const value = {
|
|
160
215
|
accepted: true,
|
|
161
216
|
direct: true,
|
|
@@ -166,22 +221,37 @@ export async function callPluginAdapter(
|
|
|
166
221
|
risk: application.action.risk,
|
|
167
222
|
confirmation: application.action.confirmation,
|
|
168
223
|
},
|
|
169
|
-
scope:
|
|
170
|
-
|
|
224
|
+
scope: pluginScopeLabel(scope),
|
|
225
|
+
requestId: application.receipt.requestId,
|
|
226
|
+
observationReceiptId: application.receipt.receiptId,
|
|
227
|
+
evidenceRef: application.receipt.receiptId,
|
|
228
|
+
resultDigest: application.receipt.resultDigest,
|
|
229
|
+
result: boundedPluginResult.value,
|
|
171
230
|
detail: {
|
|
172
231
|
tool: 'rh_context',
|
|
173
232
|
arguments: {
|
|
174
|
-
...(
|
|
175
|
-
capability_id: `plugin.${pluginId}.${actionId}`,
|
|
176
|
-
detail_level: 'detail',
|
|
233
|
+
...detailArgumentsForScope(scope, pluginId, actionId),
|
|
177
234
|
},
|
|
178
235
|
},
|
|
179
|
-
next: 'Continue with the returned bounded result; use rh_context capability detail only when the typed action schema/policy is needed.',
|
|
236
|
+
next: 'Continue with the returned bounded result. The compact observationReceiptId/evidenceRef may support model-selected learning without creating Work or effect replay state; use rh_context capability detail only when the typed action schema/policy is needed.',
|
|
180
237
|
};
|
|
181
|
-
return resultWithPluginArtifactImages(
|
|
238
|
+
return resultWithPluginArtifactImages(
|
|
239
|
+
value,
|
|
240
|
+
ctx.controllerHome,
|
|
241
|
+
resultScopeRepoId,
|
|
242
|
+
application.result,
|
|
243
|
+
);
|
|
182
244
|
}
|
|
183
245
|
|
|
184
246
|
if (application.kind === 'direct_non_persistent') {
|
|
247
|
+
const boundedPluginResult = boundedRuntimeResult({
|
|
248
|
+
controllerHome: ctx.controllerHome,
|
|
249
|
+
repoId: scope.kind === 'repository' ? scope.repository.repoId : FORGE_INSTANCE_SCOPE_KEY,
|
|
250
|
+
sessionId: ctx.sessionId,
|
|
251
|
+
principalId: ctx.principalId,
|
|
252
|
+
controllerInstanceId: ctx.controllerInstanceId,
|
|
253
|
+
workId,
|
|
254
|
+
}, application.result);
|
|
185
255
|
return result({
|
|
186
256
|
accepted: true,
|
|
187
257
|
direct: true,
|
|
@@ -194,27 +264,25 @@ export async function callPluginAdapter(
|
|
|
194
264
|
risk: application.action.risk,
|
|
195
265
|
confirmation: application.action.confirmation,
|
|
196
266
|
},
|
|
197
|
-
scope:
|
|
267
|
+
scope: pluginScopeLabel(scope),
|
|
198
268
|
requestId,
|
|
199
|
-
result:
|
|
269
|
+
result: boundedPluginResult.value,
|
|
200
270
|
detail: {
|
|
201
271
|
tool: 'rh_context',
|
|
202
272
|
arguments: {
|
|
203
|
-
...(
|
|
204
|
-
capability_id: `plugin.${pluginId}.${actionId}`,
|
|
205
|
-
detail_level: 'detail',
|
|
273
|
+
...detailArgumentsForScope(scope, pluginId, actionId),
|
|
206
274
|
},
|
|
207
275
|
},
|
|
208
276
|
next: 'This protected action completed inline without durable replay state. Use the returned result only for the immediate next protected action.',
|
|
209
277
|
});
|
|
210
278
|
}
|
|
211
279
|
|
|
212
|
-
if (application.kind === '
|
|
280
|
+
if (application.kind === 'managed_running') {
|
|
213
281
|
return result({
|
|
214
282
|
accepted: true,
|
|
215
283
|
direct: false,
|
|
216
|
-
durable:
|
|
217
|
-
mode: '
|
|
284
|
+
durable: true,
|
|
285
|
+
mode: 'process_managed',
|
|
218
286
|
plugin: summarizePluginActionReceipt(application.manifest),
|
|
219
287
|
action: application.action ? {
|
|
220
288
|
actionId: application.action.actionId,
|
|
@@ -222,21 +290,22 @@ export async function callPluginAdapter(
|
|
|
222
290
|
confirmation: application.action.confirmation,
|
|
223
291
|
requiredConfirmationText: application.action.requiredConfirmationText,
|
|
224
292
|
} : { actionId },
|
|
225
|
-
scope:
|
|
293
|
+
scope: pluginScopeLabel(scope),
|
|
226
294
|
requestId,
|
|
227
295
|
process: application.process,
|
|
228
296
|
resultRef: { kind: 'process_logs', processId: application.process.processId },
|
|
229
|
-
|
|
297
|
+
observation: { status: 'in_progress', outcome: 'unknown_until_process_terminal', retryPolicy: 'reattach_same_request_id' },
|
|
298
|
+
next: 'Execution is durably detached from this MCP stream. Observe processId/resultRef; after terminal completion, call plugin_action_execute with the same request_id to retrieve the deduplicated structured receipt. Never redispatch with a new request id because observation was interrupted.',
|
|
230
299
|
});
|
|
231
300
|
}
|
|
232
301
|
|
|
233
|
-
if (application.kind === '
|
|
302
|
+
if (application.kind === 'managed_failed') {
|
|
234
303
|
const handle = application.process;
|
|
235
304
|
return result({
|
|
236
305
|
accepted: true,
|
|
237
306
|
direct: false,
|
|
238
|
-
durable:
|
|
239
|
-
mode: '
|
|
307
|
+
durable: true,
|
|
308
|
+
mode: 'process_managed',
|
|
240
309
|
requestId,
|
|
241
310
|
process: handle,
|
|
242
311
|
error: {
|
|
@@ -260,7 +329,7 @@ export async function callPluginAdapter(
|
|
|
260
329
|
confirmation: submitted.action.confirmation,
|
|
261
330
|
requiredConfirmationText: submitted.action.requiredConfirmationText,
|
|
262
331
|
},
|
|
263
|
-
scope:
|
|
332
|
+
scope: pluginScopeLabel(scope),
|
|
264
333
|
receiptId: submitted.receipt.receiptId,
|
|
265
334
|
requestId: submitted.receipt.requestId,
|
|
266
335
|
...(submitted.receipt.workId ? { workId: submitted.receipt.workId } : {}),
|
|
@@ -269,14 +338,17 @@ export async function callPluginAdapter(
|
|
|
269
338
|
detail: {
|
|
270
339
|
tool: 'rh_context',
|
|
271
340
|
arguments: {
|
|
272
|
-
...(
|
|
273
|
-
capability_id: `plugin.${pluginId}.${actionId}`,
|
|
274
|
-
detail_level: 'detail',
|
|
341
|
+
...detailArgumentsForScope(scope, pluginId, actionId),
|
|
275
342
|
},
|
|
276
343
|
},
|
|
277
344
|
next: 'Continue with the returned bounded plugin result; use rh_context capability detail only when the typed action schema/policy is needed.',
|
|
278
345
|
};
|
|
279
|
-
return resultWithPluginArtifactImages(
|
|
346
|
+
return resultWithPluginArtifactImages(
|
|
347
|
+
value,
|
|
348
|
+
ctx.controllerHome,
|
|
349
|
+
scope.kind === 'repository' ? scope.repository.repoId : FORGE_INSTANCE_SCOPE_KEY,
|
|
350
|
+
compactResult,
|
|
351
|
+
);
|
|
280
352
|
}
|
|
281
353
|
case 'workspace_auth_status': {
|
|
282
354
|
const repository = selected(ctx, args);
|
|
@@ -292,8 +364,8 @@ export async function callPluginAdapter(
|
|
|
292
364
|
}
|
|
293
365
|
case 'toolchain_plugin_summary': {
|
|
294
366
|
const pluginId = String(args.plugin_id ?? '').trim();
|
|
295
|
-
const
|
|
296
|
-
const manifest =
|
|
367
|
+
const scope = pluginTransportScope(ctx, args, pluginId);
|
|
368
|
+
const manifest = pluginManifestForScope(ctx, scope, pluginId);
|
|
297
369
|
return result({
|
|
298
370
|
plugin: summarizePluginForLowInterception(manifest),
|
|
299
371
|
nonOpaque: true,
|
|
@@ -11,11 +11,20 @@ import type { McpToolDefinition, CallToolResult } from '../../../packages/protoc
|
|
|
11
11
|
import type { MultiRepositoryMcpToolContext } from '../multi-repository';
|
|
12
12
|
import {
|
|
13
13
|
cancelRepositoryCommandProcess,
|
|
14
|
+
executeHostCommand,
|
|
14
15
|
getRepositoryCommandProcess,
|
|
15
16
|
readRepositoryCommandProcessLogs,
|
|
16
17
|
waitRepositoryCommandProcess,
|
|
17
18
|
} from '../../../src/runtime/execution/process-runtime';
|
|
18
19
|
import { redactSensitiveText, redactSensitiveValue } from '../../../src/runtime/evidence/sensitive-output';
|
|
20
|
+
import { getProcessRecord } from '../../../src/runtime/execution/process-runtime/store';
|
|
21
|
+
import { forgeInstanceIdFor, readProcessHandleIndexEntry } from '../../../src/runtime/execution/process-runtime/handle-index';
|
|
22
|
+
import { isForgeInstanceProcessScopeKey, isRepositoryProcessScopeKey, processScopeKeyForHandle } from '../../../src/runtime/execution/process-runtime/process-scope';
|
|
23
|
+
import { reconcileTerminalWorkVerifications } from '../../../src/runtime/control-plane/execution/work-verification-service';
|
|
24
|
+
import type { WorkHandleState } from '../../../src/runtime/control-plane/execution/work-handle-store';
|
|
25
|
+
import { findControlPlaneRecordsByKey } from '../../../src/runtime/control-plane/persistence/sqlite-store';
|
|
26
|
+
import { sanitizeFileComponent } from '../../../src/runtime/shared/json-files';
|
|
27
|
+
import { selected, stringList } from './shared-adapter';
|
|
19
28
|
|
|
20
29
|
function definition(
|
|
21
30
|
name: string,
|
|
@@ -40,7 +49,7 @@ function definition(
|
|
|
40
49
|
|
|
41
50
|
const repoIdProp = {
|
|
42
51
|
type: 'string',
|
|
43
|
-
description: '
|
|
52
|
+
description: 'Optional repository or ephemeral workspace scope id returned by the originating command. When omitted, the process handle resolves its own recorded execution target.',
|
|
44
53
|
};
|
|
45
54
|
const processIdProp = {
|
|
46
55
|
type: 'string',
|
|
@@ -48,6 +57,23 @@ const processIdProp = {
|
|
|
48
57
|
};
|
|
49
58
|
|
|
50
59
|
export const processToolDefinitions: McpToolDefinition[] = [
|
|
60
|
+
definition(
|
|
61
|
+
'process_exec',
|
|
62
|
+
'Execute one command on the Forge instance itself: cwd is an execution argument and no repository, checkout, or Work is required. Requires an explicit broad `process:exec` canonical Grant for this ForgeInstance; Forge does not parse the command to prove path safety. Returns a process handle; attach with process_get/process_wait/process_logs/process_cancel using the handle only.',
|
|
63
|
+
{
|
|
64
|
+
command: { type: 'array', items: { type: 'string' }, maxItems: 512, description: 'Typed argv command; command[0] is the executable. Mutually exclusive with shell_command.' },
|
|
65
|
+
shell_command: { type: 'string', maxLength: 32_000, description: 'Explicit broad shell form. Mutually exclusive with command. Never parsed for path safety.' },
|
|
66
|
+
cwd: { type: 'string', description: 'Optional absolute working directory. With work_id and no cwd, Forge uses that Work handle\'s exact workspace/worktree as a convenience default; this never grants permission and explicit authorized cwd may be elsewhere.' },
|
|
67
|
+
timeout_ms: { type: 'number' },
|
|
68
|
+
interactive_wait_ms: { type: 'number' },
|
|
69
|
+
max_output_bytes: { type: 'number' },
|
|
70
|
+
request_id: { type: 'string', description: 'Stable invocation id. A retry with the same id attaches to the existing process instead of re-executing.' },
|
|
71
|
+
work_id: { type: 'string', description: 'Optional Work provenance; Work is never required to run a host command.' },
|
|
72
|
+
},
|
|
73
|
+
[],
|
|
74
|
+
false,
|
|
75
|
+
true,
|
|
76
|
+
),
|
|
51
77
|
definition(
|
|
52
78
|
'run_check',
|
|
53
79
|
'Run one focused repository check, or launch one resource-compatible check wave, through Process Runtime. Use check_id for the existing single-check behavior or check_ids for a batch; do not send both. Batch mode validates the existing check-scheduling resource model and starts every check in one compatible wave concurrently without waiting for completion or creating a second scheduler. Cross-wave, invalid, release, and multi-phase batches fail closed. Long ordinary checks return managed handles; attach only at a real dependency boundary.',
|
|
@@ -74,7 +100,7 @@ export const processToolDefinitions: McpToolDefinition[] = [
|
|
|
74
100
|
repo_id: repoIdProp,
|
|
75
101
|
process_id: processIdProp,
|
|
76
102
|
},
|
|
77
|
-
['
|
|
103
|
+
['process_id'],
|
|
78
104
|
true,
|
|
79
105
|
),
|
|
80
106
|
definition(
|
|
@@ -85,7 +111,7 @@ export const processToolDefinitions: McpToolDefinition[] = [
|
|
|
85
111
|
process_id: processIdProp,
|
|
86
112
|
timeout_ms: { type: 'number', description: 'Max wait milliseconds (default 15000).' },
|
|
87
113
|
},
|
|
88
|
-
['
|
|
114
|
+
['process_id'],
|
|
89
115
|
true,
|
|
90
116
|
),
|
|
91
117
|
definition(
|
|
@@ -96,7 +122,7 @@ export const processToolDefinitions: McpToolDefinition[] = [
|
|
|
96
122
|
process_id: processIdProp,
|
|
97
123
|
max_bytes: { type: 'number', description: 'Max tail bytes per stream (default 32KiB).' },
|
|
98
124
|
},
|
|
99
|
-
['
|
|
125
|
+
['process_id'],
|
|
100
126
|
true,
|
|
101
127
|
),
|
|
102
128
|
definition(
|
|
@@ -106,7 +132,7 @@ export const processToolDefinitions: McpToolDefinition[] = [
|
|
|
106
132
|
repo_id: repoIdProp,
|
|
107
133
|
process_id: processIdProp,
|
|
108
134
|
},
|
|
109
|
-
['
|
|
135
|
+
['process_id'],
|
|
110
136
|
false,
|
|
111
137
|
true,
|
|
112
138
|
),
|
|
@@ -114,6 +140,33 @@ export const processToolDefinitions: McpToolDefinition[] = [
|
|
|
114
140
|
|
|
115
141
|
const processToolNames = new Set(processToolDefinitions.map((tool) => tool.name));
|
|
116
142
|
const processAttachmentToolNames = new Set(['process_get', 'process_wait', 'process_logs', 'process_cancel']);
|
|
143
|
+
|
|
144
|
+
function reconcileAttachedWorkVerification(
|
|
145
|
+
ctx: MultiRepositoryMcpToolContext,
|
|
146
|
+
repoId: string,
|
|
147
|
+
processId: string,
|
|
148
|
+
handle: { completed?: boolean; workId?: string },
|
|
149
|
+
): Record<string, unknown> | undefined {
|
|
150
|
+
if (handle.completed !== true || !handle.workId) return undefined;
|
|
151
|
+
const record = getProcessRecord(ctx.controllerHome, repoId, processId);
|
|
152
|
+
if (record?.origin?.workVerificationSnapshot !== true) return undefined;
|
|
153
|
+
try {
|
|
154
|
+
const repository = selected(ctx, { repo_id: repoId, checkout_id: record.checkoutId });
|
|
155
|
+
const reconciled = reconcileTerminalWorkVerifications({
|
|
156
|
+
controllerHome: ctx.controllerHome,
|
|
157
|
+
repository,
|
|
158
|
+
workId: handle.workId,
|
|
159
|
+
});
|
|
160
|
+
return {
|
|
161
|
+
workId: handle.workId,
|
|
162
|
+
processId,
|
|
163
|
+
status: reconciled.reconciledProcessIds.includes(processId) ? 'reconciled' : 'already_current_or_non_authoritative',
|
|
164
|
+
reconciledProcessIds: reconciled.reconciledProcessIds,
|
|
165
|
+
};
|
|
166
|
+
} catch {
|
|
167
|
+
return { workId: handle.workId, processId, status: 'non_authoritative' };
|
|
168
|
+
}
|
|
169
|
+
}
|
|
117
170
|
// A long-lived MCP wait can monopolize shared Runtime request/transport capacity
|
|
118
171
|
// even though the underlying Process wait is asynchronous. Keep public waits
|
|
119
172
|
// short and return a normal running snapshot; the Process continues unchanged
|
|
@@ -162,21 +215,58 @@ function failure(error: unknown): CallToolResult {
|
|
|
162
215
|
function requireRepoAndProcess(
|
|
163
216
|
ctx: MultiRepositoryMcpToolContext,
|
|
164
217
|
args: Record<string, unknown>,
|
|
165
|
-
): { repoId
|
|
218
|
+
): { repoId?: string; processId: string; handle: NonNullable<ReturnType<typeof getRepositoryCommandProcess>> } {
|
|
166
219
|
const repoId = typeof args.repo_id === 'string' ? args.repo_id.trim() : '';
|
|
167
220
|
const processId = typeof args.process_id === 'string' ? args.process_id.trim() : '';
|
|
168
|
-
if (!repoId) throw new Error('REPOSITORY_ID_REQUIRED: repo_id is required for process tools');
|
|
169
221
|
if (!processId) throw new Error('PROCESS_ID_REQUIRED: process_id is required for process tools');
|
|
222
|
+
assertProcessHandleAccess(ctx, processId);
|
|
170
223
|
|
|
171
|
-
// The Process handle is the scope authority.
|
|
172
|
-
//
|
|
173
|
-
//
|
|
174
|
-
//
|
|
175
|
-
|
|
224
|
+
// The Process handle is the scope authority. An explicit repo_id is validated
|
|
225
|
+
// against the handle's recorded target; when it is omitted the handle index
|
|
226
|
+
// resolves the target so attachment never needs placement replay. Ephemeral
|
|
227
|
+
// workspace targets are intentionally not registered in Repository Registry,
|
|
228
|
+
// so requiring a live repository record here would make their returned
|
|
229
|
+
// managed handles impossible to resume.
|
|
230
|
+
const recordedScopeKey = processScopeKeyForHandle(ctx.controllerHome, processId);
|
|
231
|
+
// A ForgeInstance-scoped handle keeps its instance target even when a client
|
|
232
|
+
// always sends repo_id; the index remains the target authority.
|
|
233
|
+
const effectiveScopeKey = recordedScopeKey && isForgeInstanceProcessScopeKey(recordedScopeKey)
|
|
234
|
+
? recordedScopeKey
|
|
235
|
+
: (repoId || recordedScopeKey);
|
|
236
|
+
const handle = getRepositoryCommandProcess(ctx.controllerHome, effectiveScopeKey, processId);
|
|
176
237
|
if (!handle) {
|
|
177
|
-
throw new Error(
|
|
238
|
+
throw new Error(repoId
|
|
239
|
+
? `PROCESS_NOT_FOUND: process ${processId} is not registered under repo ${repoId}`
|
|
240
|
+
: `PROCESS_NOT_FOUND: ${processId}`);
|
|
241
|
+
}
|
|
242
|
+
const resolvedScopeKey = recordedScopeKey && isForgeInstanceProcessScopeKey(recordedScopeKey) ? recordedScopeKey : (repoId || recordedScopeKey);
|
|
243
|
+
const resolvedRepoId = resolvedScopeKey && isRepositoryProcessScopeKey(resolvedScopeKey) ? resolvedScopeKey : undefined;
|
|
244
|
+
return { repoId: resolvedRepoId || undefined, processId, handle };
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
/**
|
|
248
|
+
* A process handle id locates a record; it never authorizes attachment by
|
|
249
|
+
* itself. Instance-level handles are principal-bound and ForgeInstance-bound,
|
|
250
|
+
* and a recorded repository principal is enforced when the caller presents one.
|
|
251
|
+
*/
|
|
252
|
+
function assertProcessHandleAccess(ctx: MultiRepositoryMcpToolContext, processId: string): void {
|
|
253
|
+
const entry = readProcessHandleIndexEntry(ctx.controllerHome, processId);
|
|
254
|
+
if (!entry) return;
|
|
255
|
+
const caller = ctx.principalId?.trim();
|
|
256
|
+
const recorded = entry.principalId?.trim();
|
|
257
|
+
if (entry.target.scope === 'forge_instance') {
|
|
258
|
+
const servingInstance = forgeInstanceIdFor(ctx.controllerHome);
|
|
259
|
+
if (entry.target.forgeInstanceId && servingInstance && entry.target.forgeInstanceId !== servingInstance) {
|
|
260
|
+
throw new Error(`PROCESS_HANDLE_INSTANCE_MISMATCH: process ${processId} belongs to ForgeInstance ${entry.target.forgeInstanceId}`);
|
|
261
|
+
}
|
|
262
|
+
if (!recorded) throw new Error(`PROCESS_HANDLE_PRINCIPAL_UNBOUND: process ${processId} has no recorded principal`);
|
|
263
|
+
if (!caller) throw new Error(`PROCESS_HANDLE_PRINCIPAL_REQUIRED: process ${processId} requires an authenticated principal`);
|
|
264
|
+
if (recorded !== caller) throw new Error(`PROCESS_HANDLE_PRINCIPAL_MISMATCH: process ${processId} is owned by another principal`);
|
|
265
|
+
return;
|
|
266
|
+
}
|
|
267
|
+
if (recorded && caller && recorded !== caller) {
|
|
268
|
+
throw new Error(`PROCESS_HANDLE_PRINCIPAL_MISMATCH: process ${processId} is owned by another principal`);
|
|
178
269
|
}
|
|
179
|
-
return { repoId, processId };
|
|
180
270
|
}
|
|
181
271
|
|
|
182
272
|
function handleToPayload(handle: NonNullable<ReturnType<typeof getRepositoryCommandProcess>>): Record<string, unknown> {
|
|
@@ -214,19 +304,23 @@ export async function callProcessTool(
|
|
|
214
304
|
name: string,
|
|
215
305
|
args: Record<string, unknown>,
|
|
216
306
|
): Promise<CallToolResult | undefined> {
|
|
307
|
+
if (name === 'process_exec') return callProcessExecTool(ctx, args);
|
|
217
308
|
// run_check shares this module's public schema, but its execution authority is
|
|
218
309
|
// the Gateway check facade in router.ts. Only attachment/lifecycle operations
|
|
219
310
|
// consume an existing process_id here.
|
|
220
311
|
if (!processAttachmentToolNames.has(name)) return undefined;
|
|
221
312
|
try {
|
|
222
|
-
const { repoId, processId } = requireRepoAndProcess(ctx, args);
|
|
313
|
+
const { repoId, processId, handle: attachedHandle } = requireRepoAndProcess(ctx, args);
|
|
314
|
+
const scopePayload = repoId ? { repoId } : {};
|
|
223
315
|
switch (name) {
|
|
224
316
|
case 'process_get': {
|
|
225
|
-
const
|
|
226
|
-
|
|
317
|
+
const workVerificationReconciliation = repoId
|
|
318
|
+
? reconcileAttachedWorkVerification(ctx, repoId, processId, attachedHandle)
|
|
319
|
+
: undefined;
|
|
227
320
|
return result({
|
|
228
|
-
|
|
229
|
-
process: handleToPayload(
|
|
321
|
+
...scopePayload,
|
|
322
|
+
process: handleToPayload(attachedHandle),
|
|
323
|
+
...(workVerificationReconciliation ? { workVerificationReconciliation } : {}),
|
|
230
324
|
});
|
|
231
325
|
}
|
|
232
326
|
case 'process_wait': {
|
|
@@ -241,9 +335,13 @@ export async function callProcessTool(
|
|
|
241
335
|
const handle = await waitRepositoryCommandProcess(ctx.controllerHome, repoId, processId, {
|
|
242
336
|
timeoutMs: Math.min(requestedWaitMs, attachBudgetMs),
|
|
243
337
|
});
|
|
338
|
+
const workVerificationReconciliation = repoId
|
|
339
|
+
? reconcileAttachedWorkVerification(ctx, repoId, processId, handle)
|
|
340
|
+
: undefined;
|
|
244
341
|
return result({
|
|
245
|
-
|
|
342
|
+
...scopePayload,
|
|
246
343
|
process: handleToPayload(handle),
|
|
344
|
+
...(workVerificationReconciliation ? { workVerificationReconciliation } : {}),
|
|
247
345
|
synchronization: handle.completed === true ? 'terminal_result_available' : 'continue_independent_work',
|
|
248
346
|
waitedMs: Date.now() - startedAt,
|
|
249
347
|
requestedWaitMs,
|
|
@@ -258,7 +356,7 @@ export async function callProcessTool(
|
|
|
258
356
|
const logs = readRepositoryCommandProcessLogs(ctx.controllerHome, repoId, processId, maxBytes);
|
|
259
357
|
if (!logs) throw new Error(`PROCESS_NOT_FOUND: ${processId}`);
|
|
260
358
|
return result({
|
|
261
|
-
|
|
359
|
+
...scopePayload,
|
|
262
360
|
processId,
|
|
263
361
|
stdout: logs.stdout,
|
|
264
362
|
stderr: logs.stderr,
|
|
@@ -271,7 +369,7 @@ export async function callProcessTool(
|
|
|
271
369
|
case 'process_cancel': {
|
|
272
370
|
const handle = await cancelRepositoryCommandProcess(ctx.controllerHome, repoId, processId);
|
|
273
371
|
return result({
|
|
274
|
-
|
|
372
|
+
...scopePayload,
|
|
275
373
|
process: handleToPayload(handle),
|
|
276
374
|
cancelled: handle.cancelled === true || handle.status === 'cancelled' || handle.status === 'completed_unknown',
|
|
277
375
|
});
|
|
@@ -284,6 +382,76 @@ export async function callProcessTool(
|
|
|
284
382
|
}
|
|
285
383
|
}
|
|
286
384
|
|
|
385
|
+
/**
|
|
386
|
+
* `process_exec` — the canonical host-local command lane.
|
|
387
|
+
*
|
|
388
|
+
* Repo-less by construction: the Forge instance is the target and `cwd` is an
|
|
389
|
+
* execution argument. Authorization is one explicit canonical `process:exec`
|
|
390
|
+
* Grant for this instance, enforced in the lane before any spawn.
|
|
391
|
+
*/
|
|
392
|
+
function workDefaultCommandCwd(ctx: MultiRepositoryMcpToolContext, workId: string): string | undefined {
|
|
393
|
+
if (!workId) return undefined;
|
|
394
|
+
const matches = findControlPlaneRecordsByKey<WorkHandleState>(ctx.controllerHome, {
|
|
395
|
+
namespace: 'execution_work_handle',
|
|
396
|
+
key: sanitizeFileComponent(workId),
|
|
397
|
+
limit: 2,
|
|
398
|
+
});
|
|
399
|
+
if (matches.length > 1) {
|
|
400
|
+
throw new Error(`WORK_EXECUTION_PLACEMENT_AMBIGUOUS: ${workId} resolves to multiple execution handles`);
|
|
401
|
+
}
|
|
402
|
+
const handle = matches[0]?.value;
|
|
403
|
+
if (!handle) return undefined;
|
|
404
|
+
if (handle.workId !== workId) throw new Error(`WORK_EXECUTION_PLACEMENT_IDENTITY_MISMATCH: ${workId}`);
|
|
405
|
+
const workspace = handle.worktreePath?.trim();
|
|
406
|
+
return workspace || undefined;
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
async function callProcessExecTool(
|
|
410
|
+
ctx: MultiRepositoryMcpToolContext,
|
|
411
|
+
args: Record<string, unknown>,
|
|
412
|
+
): Promise<CallToolResult> {
|
|
413
|
+
try {
|
|
414
|
+
const command = stringList(args.command);
|
|
415
|
+
const shellCommand = typeof args.shell_command === 'string' && args.shell_command.trim()
|
|
416
|
+
? args.shell_command
|
|
417
|
+
: undefined;
|
|
418
|
+
if (command.length > 0 && shellCommand) {
|
|
419
|
+
throw new Error('HOST_COMMAND_AMBIGUOUS: provide exactly one of command or shell_command');
|
|
420
|
+
}
|
|
421
|
+
if (command.length === 0 && !shellCommand) {
|
|
422
|
+
throw new Error('HOST_COMMAND_REQUIRED: provide command (argv) or shell_command');
|
|
423
|
+
}
|
|
424
|
+
const requestId = typeof args.request_id === 'string' ? args.request_id.trim() : '';
|
|
425
|
+
const workId = typeof args.work_id === 'string' ? args.work_id.trim() : '';
|
|
426
|
+
const explicitCwd = typeof args.cwd === 'string' ? args.cwd.trim() : '';
|
|
427
|
+
const cwd = explicitCwd || workDefaultCommandCwd(ctx, workId) || '';
|
|
428
|
+
const executed = await executeHostCommand({
|
|
429
|
+
controllerHome: ctx.controllerHome,
|
|
430
|
+
principalId: ctx.principalId ?? '',
|
|
431
|
+
...(command.length > 0 ? { command } : {}),
|
|
432
|
+
...(shellCommand ? { shellCommand } : {}),
|
|
433
|
+
cwd,
|
|
434
|
+
...(typeof args.timeout_ms === 'number' ? { timeoutMs: args.timeout_ms } : {}),
|
|
435
|
+
...(typeof args.interactive_wait_ms === 'number' ? { interactiveWaitMs: args.interactive_wait_ms } : {}),
|
|
436
|
+
...(typeof args.max_output_bytes === 'number' ? { maxOutputBytes: args.max_output_bytes } : {}),
|
|
437
|
+
...(requestId ? { commandId: requestId } : {}),
|
|
438
|
+
...(workId ? { workId } : {}),
|
|
439
|
+
});
|
|
440
|
+
return result({
|
|
441
|
+
process: handleToPayload(executed.handle),
|
|
442
|
+
target: {
|
|
443
|
+
scope: 'forge_instance',
|
|
444
|
+
forgeInstanceId: executed.target.forgeInstanceId,
|
|
445
|
+
cwd: executed.target.cwd,
|
|
446
|
+
},
|
|
447
|
+
authorization: { capability: 'process:exec', grantId: executed.target.grantId },
|
|
448
|
+
executionMetrics: executed.metrics,
|
|
449
|
+
});
|
|
450
|
+
} catch (error) {
|
|
451
|
+
return failure(error);
|
|
452
|
+
}
|
|
453
|
+
}
|
|
454
|
+
|
|
287
455
|
export function isProcessTool(name: string): boolean {
|
|
288
456
|
return processToolNames.has(name);
|
|
289
457
|
}
|