@moretea-labs/forge 1.5.1 → 1.7.0
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 +2 -0
- package/CHANGELOG.md +46 -0
- package/CLAUDE.md +2 -0
- package/DESIGN.md +7 -2
- package/README.md +4 -4
- package/README.zh-CN.md +2 -2
- package/SKILL.md +2 -2
- package/THIRD_PARTY_NOTICES.md +1 -1
- package/agents/openai.yaml +1 -1
- package/assets/hooks/hook-input.sh +11 -8
- package/assets/hooks/lib/session-state.sh +10 -7
- package/assets/hooks/lib/workflow-state.sh +13 -177
- package/assets/hooks/post-tool-observer.sh +8 -2
- package/assets/hooks/pre-edit-guard.sh +8 -39
- package/assets/hooks/prompt-guard.sh +7 -83
- package/assets/hooks/session-start-context.sh +56 -1
- package/assets/partials/05-workflow.partial.md +1 -1
- package/assets/partials-agents/03-orchestration.partial.md +1 -1
- package/assets/plugin-registry.v1.json +54 -3
- package/assets/reference-configs/document-generation.md +1 -1
- package/assets/reference-configs/harness-overview.md +1 -1
- package/assets/reference-configs/hook-operations.md +1 -1
- package/assets/reference-configs/sprint-contracts.md +3 -3
- package/assets/skill-version.json +2 -2
- package/assets/templates/contract.template.md +2 -7
- package/assets/templates/helpers/capture-plan.sh +2 -2
- package/assets/templates/helpers/check-task-workflow.sh +4 -4
- package/assets/templates/helpers/contract-worktree.sh +1 -21
- package/assets/templates/helpers/ensure-task-workflow.sh +13 -38
- package/assets/templates/helpers/migrate-project-template.sh +22 -45
- package/assets/templates/helpers/new-plan.sh +1 -1
- package/assets/templates/helpers/plan-to-todo.sh +12 -37
- package/assets/templates/helpers/ship-worktrees.sh +2 -29
- package/assets/templates/helpers/sprint-backlog.sh +6 -6
- package/assets/templates/helpers/verify-contract.sh +1 -111
- package/assets/templates/helpers/verify-sprint.sh +3 -180
- package/assets/templates/plan.template.md +1 -1
- package/assets/templates/review.template.md +9 -34
- package/assets/workflow-contract.v1.json +10 -19
- package/docs/README.md +10 -10
- package/docs/architecture/CURRENT.md +170 -0
- package/docs/architecture/EVOLUTION.md +42 -0
- package/docs/architecture/current/README.md +4 -156
- package/docs/architecture/decisions/20260803-release-identity-binding-and-exit-policy.md +2 -2
- package/docs/architecture/decisions/20260823-immediate-controller-relay.md +53 -0
- package/docs/architecture/decisions/20260826-browser-runtime-v2.md +73 -0
- package/docs/architecture/history/README.md +7 -0
- package/docs/architecture/{chatgpt-handoff-facade.md → history/chatgpt-handoff-facade.md} +4 -0
- package/docs/architecture/{global-hook-runtime.md → history/global-hook-runtime.md} +7 -3
- package/docs/architecture/{ios-semantic-automation-provider-v2.md → history/ios-semantic-automation-provider-v2.md} +6 -2
- package/docs/architecture/history.md +3 -34
- package/docs/architecture/index.md +15 -98
- package/docs/architecture/modules/controller-runtime/transport-lifecycle.md +1 -1
- package/docs/architecture/reviews/2026-08-22-semantic-harness-convergence-acceptance.md +39 -0
- package/docs/architecture/versions/1.6.md +38 -0
- package/docs/architecture/versions/1.7.md +41 -0
- package/docs/forge-chatgpt-browser-engine.md +2 -2
- package/docs/forge-chatgpt-mcp-setup.md +4 -28
- package/docs/forge-chatgpt-supervised-automation.md +3 -3
- package/docs/forge-github-issue-launcher.md +1 -1
- package/docs/forge-runtime-self-healing-loop.md +1 -1
- package/docs/operations/controller-browser-plugin.md +38 -22
- package/docs/operations/controller-performance-and-502.md +124 -0
- package/docs/operations/controller-reliability-runbook.md +1 -1
- package/docs/operations/features.md +3 -3
- package/docs/operations/github-repository.md +1 -1
- package/docs/operations/homebrew.md +2 -2
- package/docs/operations/mcp-tool-exposure.md +5 -3
- package/docs/tutorials/01-install-and-start.md +1 -1
- package/docs/tutorials/01-install-and-start.zh-CN.md +1 -1
- package/docs/wiki/Architecture.md +6 -6
- package/docs/wiki/Implementation.md +2 -2
- package/docs/wiki/Installation.md +1 -1
- package/docs/wiki/Integrations.md +2 -2
- package/docs/wiki/Quick-Start.md +1 -1
- package/docs/wiki/Work-Lifecycle.md +1 -1
- package/package.json +29 -10
- package/scripts/activate-source-baseline.ts +17 -13
- package/scripts/benchmark-background-check-overlap.ts +228 -0
- package/scripts/benchmark-mcp-host.sh +117 -0
- package/scripts/benchmark-mcp-transport.ts +170 -0
- package/scripts/benchmark-quality-harness.ts +146 -0
- package/scripts/benchmark-route-session-concurrency.ts +207 -6
- package/scripts/benchmark-thin-harness-mcp-e2e.ts +7 -1
- package/scripts/benchmark-typescript-navigation.ts +186 -0
- package/scripts/benchmark-work-efficiency.ts +334 -0
- package/scripts/capture-plan.sh +3 -3
- package/scripts/check-agent-tooling.sh +8 -35
- package/scripts/check-architecture-sync.sh +17 -86
- package/scripts/check-mcp-compatibility.ts +14 -0
- package/scripts/check-public-docs.sh +14 -1
- package/scripts/check-runtime-architecture.mjs +107 -64
- package/scripts/check-stable-baseline.ts +92 -0
- package/scripts/check-task-workflow.sh +4 -4
- package/scripts/contract-worktree.sh +1 -21
- package/scripts/ensure-task-workflow.sh +22 -55
- package/scripts/host-temporary-cloud-mcp-e2e.sh +265 -0
- package/scripts/install-standalone-recovery.ts +24 -0
- package/scripts/lib/project-init-lib.sh +15 -44
- package/scripts/migrate-chatgpt-automation-schedules.ts +64 -0
- package/scripts/migrate-project-template.sh +23 -1179
- package/scripts/new-plan.sh +1 -1
- package/scripts/plan-to-todo.sh +11 -36
- package/scripts/run-governed-gate.ts +2 -1
- package/scripts/ship-worktrees.sh +2 -29
- package/scripts/smoke-ios-physical-device.ts +4 -2
- package/scripts/smoke-runtime-recovery.ts +1 -35
- package/scripts/smoke-schedule-engine.ts +1 -20
- package/scripts/sprint-backlog.sh +1 -1
- package/scripts/verify-contract.sh +1 -111
- package/scripts/verify-forge-runtime.sh +0 -1
- package/scripts/verify-sprint.sh +3 -180
- package/scripts/workflow-contract.ts +1 -5
- package/src/cli/commands/chatgpt.ts +31 -2
- package/src/cli/commands/init-hook.ts +3 -3
- package/src/cli/commands/mcp.ts +9 -5
- package/src/cli/commands/plugin.ts +37 -10
- package/src/cli/commands/recovery.ts +25 -3
- package/src/cli/commands/runtime.ts +55 -3
- package/src/cli/commands/security.ts +12 -1
- package/src/cli/commands/setup-profile.ts +31 -21
- package/src/cli/controller/check-runner.ts +106 -3
- package/src/cli/controller/composite-result.ts +1 -1
- package/src/cli/controller/context/focus.ts +51 -0
- package/src/cli/controller/context/instruction-context.ts +114 -0
- package/src/cli/controller/context/known-paths.ts +76 -0
- package/src/cli/controller/context/query-planning.ts +110 -0
- package/src/cli/controller/context/rule-resolution.ts +532 -0
- package/src/cli/controller/context/source-materializer.ts +278 -0
- package/src/cli/controller/context/structural.ts +16 -0
- package/src/cli/controller/context/types.ts +286 -0
- package/src/cli/controller/context-pack.ts +898 -430
- package/src/cli/controller/launch-agents.ts +77 -2
- package/src/cli/controller/operational-plan.ts +2 -2
- package/src/cli/controller/work-mode.ts +6 -4
- package/src/cli/editing/edit-session.ts +60 -7
- package/src/cli/github/github.ts +133 -0
- package/src/cli/hook/prompt-guard-decision.ts +17 -18
- package/src/cli/hook/prompt-intents.ts +1 -1
- package/src/cli/installer/managed-entries.ts +15 -1
- package/src/cli/local-bridge/console-automations.ts +225 -67
- package/src/cli/local-bridge/console-view-models.ts +3 -35
- package/src/cli/local-bridge/facade-api.ts +2 -217
- package/src/cli/local-bridge/frontend/src/App.tsx +3 -3
- package/src/cli/local-bridge/frontend/src/features/automations/AutomationsView.tsx +153 -3
- package/src/cli/local-bridge/frontend/src/features/capabilities/CapabilitiesView.tsx +37 -4
- package/src/cli/local-bridge/frontend/src/features/overview/OverviewView.tsx +183 -3
- package/src/cli/local-bridge/frontend/src/features/repositories/RepositoriesView.tsx +1 -1
- package/src/cli/local-bridge/frontend/src/features/work/WorkView.tsx +4 -3
- package/src/cli/local-bridge/frontend/src/lib/api.ts +18 -11
- package/src/cli/local-bridge/frontend/src/lib/routes.ts +1 -1
- package/src/cli/local-bridge/frontend/src/shell/CommandBar.tsx +1 -1
- package/src/cli/local-bridge/frontend/src/shell/Sidebar.tsx +4 -3
- package/src/cli/local-bridge/frontend/src/styles.css +27 -11
- package/src/cli/local-bridge/frontend/src/types.ts +8 -7
- package/src/cli/local-bridge/job-store.ts +1 -490
- package/src/cli/local-bridge/server.ts +29 -532
- package/src/cli/local-bridge/ui-dist/app.css +1 -1
- package/src/cli/local-bridge/ui-dist/app.js +5101 -4967
- package/src/cli/mcp/auth.ts +5 -5
- package/src/cli/mcp/instructions.ts +3 -2
- package/src/cli/mcp/legacy-tool-service.ts +0 -189
- package/src/cli/mcp/multi-repository.ts +16 -5
- package/src/cli/mcp/oauth.ts +175 -26
- package/src/cli/mcp/paths.ts +8 -2
- package/src/cli/mcp/repository-tools.ts +356 -101
- package/src/cli/mcp/server.ts +625 -54
- package/src/cli/mcp/tool-capability-cache.ts +1 -1
- package/src/cli/mcp/toolset-selection.ts +1 -1
- package/src/cli/mcp/toolset.ts +42 -5
- package/src/cli/mcp/transports/http.ts +125 -15
- package/src/cli/mcp/transports/session-registry.ts +67 -5
- package/src/cli/mcp/types.ts +3 -3
- package/src/cli/repositories/command-classifier.ts +209 -14
- package/src/cli/repositories/command-executor.ts +55 -521
- package/src/cli/repositories/command-process.ts +108 -0
- package/src/cli/repositories/command-scope.ts +99 -41
- package/src/cli/repositories/controller-home.ts +7 -8
- package/src/cli/repositories/git-command-executor.ts +2 -0
- package/src/cli/repositories/locks.ts +53 -16
- package/src/cli/repositories/repository-snapshot.ts +121 -0
- package/src/cli/repositories/safe-patch.ts +6 -4
- package/src/cli/repositories/selected-path-actions.ts +17 -9
- package/src/cli/repositories/structured-git.ts +110 -10
- package/src/cli/repository/inspector.ts +565 -62
- package/src/cli/repository/session-cache.ts +58 -17
- package/src/cli/v81-entry.ts +1 -4
- package/src/effects/fs-transaction.ts +85 -17
- package/src/runtime/context/codegraph-read-provider.ts +233 -2
- package/src/runtime/context/codegraph-sidecar.cjs +74 -40
- package/src/runtime/context/generic-lsp-provider.ts +355 -0
- package/src/runtime/context/lsp-client.ts +283 -0
- package/src/runtime/context/semantic-navigation.ts +275 -0
- package/src/runtime/context/swift-navigation.ts +565 -0
- package/src/runtime/context/typescript-navigation.ts +226 -0
- package/src/runtime/control-plane/dispatch-priority.ts +28 -0
- package/src/runtime/control-plane/execution/direct-edit-work-completion.ts +196 -2
- package/src/runtime/control-plane/execution/edit-validation-coordinator.ts +86 -24
- package/src/runtime/control-plane/execution/execution-identity.ts +65 -14
- package/src/runtime/control-plane/execution/session-store.ts +18 -0
- package/src/runtime/control-plane/execution/validation.ts +15 -2
- package/src/runtime/control-plane/execution/verification-evidence.ts +58 -3
- package/src/runtime/control-plane/execution/work-handle-store.ts +27 -2
- package/src/runtime/control-plane/execution/work-lifecycle-audit.ts +258 -0
- package/src/runtime/control-plane/execution/work-remote-delivery.ts +215 -0
- package/src/runtime/control-plane/execution/work-task-receipt.ts +54 -11
- package/src/runtime/control-plane/execution/work-terminal-cleanup.ts +175 -8
- package/src/runtime/control-plane/execution/work-validation-reconciler.ts +28 -21
- package/src/runtime/control-plane/execution/work-verification-snapshot.ts +87 -9
- package/src/runtime/control-plane/facade/capability-registry.ts +129 -25
- package/src/runtime/control-plane/facade/controller-round-relay.ts +991 -0
- package/src/runtime/control-plane/facade/controller-session-store.ts +144 -14
- package/src/runtime/control-plane/facade/goal-workloop-access.ts +9 -2
- package/src/runtime/control-plane/facade/goal-workloop.ts +885 -105
- package/src/runtime/control-plane/facade/index.ts +1 -0
- package/src/runtime/control-plane/facade/plan-contract-store.ts +211 -26
- package/src/runtime/control-plane/facade/requirement-board.ts +24 -8
- package/src/runtime/control-plane/facade/semantic-admission.ts +205 -0
- package/src/runtime/control-plane/facade/suggested-actions.ts +5 -1
- package/src/runtime/control-plane/facade/types.ts +55 -11
- package/src/runtime/control-plane/facade/work-contract-store.ts +204 -73
- package/src/runtime/control-plane/generated-cache-retention.ts +271 -0
- package/src/runtime/control-plane/global-scheduler/config.ts +44 -0
- package/src/runtime/control-plane/global-scheduler/dispatch-capacity.ts +80 -0
- package/src/runtime/control-plane/global-scheduler/durable-admission.ts +46 -0
- package/src/runtime/control-plane/global-scheduler/maintenance.ts +145 -0
- package/src/runtime/control-plane/global-scheduler/projection-refresh.ts +84 -0
- package/src/runtime/control-plane/global-scheduler/reconciliation.ts +3 -3
- package/src/runtime/control-plane/global-scheduler/scheduler.ts +273 -542
- package/src/runtime/control-plane/global-scheduler/source-scan.ts +59 -0
- package/src/runtime/control-plane/global-scheduler/state.ts +88 -0
- package/src/runtime/control-plane/global-scheduler/worker-attachment.ts +57 -0
- package/src/runtime/control-plane/global-scheduler/worker-exit-decision.ts +38 -0
- package/src/runtime/control-plane/global-scheduler/worker-exit-reconciler.ts +175 -0
- package/src/runtime/control-plane/global-scheduler/worker-launch.ts +111 -0
- package/src/runtime/control-plane/global-scheduler/worker-lifecycle-store.ts +64 -0
- package/src/runtime/control-plane/global-scheduler/worker-lifecycle.ts +150 -0
- package/src/runtime/control-plane/global-scheduler/worker-process.ts +119 -0
- package/src/runtime/control-plane/global-scheduler/worker-stderr.ts +60 -0
- package/src/runtime/control-plane/launcher/chatgpt-work-binding-store.ts +50 -0
- package/src/runtime/control-plane/launcher/chatgpt-work-continuation.ts +642 -51
- package/src/runtime/control-plane/launcher/launch-reservation-store.ts +40 -0
- package/src/runtime/control-plane/launcher/thin-launcher.ts +194 -10
- package/src/runtime/control-plane/persistence/controller-home-migration.ts +487 -0
- package/src/runtime/control-plane/persistence/requirement-store.ts +15 -11
- package/src/runtime/control-plane/persistence/sqlite-store.ts +33 -2
- package/src/runtime/control-plane/release-retention.ts +62 -2
- package/src/runtime/control-plane/routing/route-policy.ts +7 -16
- package/src/runtime/control-plane/runtime-status-client.ts +0 -2
- package/src/runtime/diagnostics/mcp-timing.ts +19 -0
- package/src/runtime/diagnostics/mcp-transport-benchmark.ts +129 -0
- package/src/runtime/diagnostics/performance.ts +24 -1
- package/src/runtime/evidence/event-ledger.ts +1 -1
- package/src/runtime/execution/jobs/store.ts +58 -4
- package/src/runtime/execution/jobs/types.ts +1 -1
- package/src/runtime/execution/managed-workspace.ts +203 -1
- package/src/runtime/execution/process-runtime/check-facade.ts +52 -14
- package/src/runtime/execution/process-runtime/check-result.ts +63 -2
- package/src/runtime/execution/process-runtime/check-scheduling.ts +114 -0
- package/src/runtime/execution/process-runtime/command-facade.ts +346 -40
- package/src/runtime/execution/process-runtime/gc.ts +98 -12
- package/src/runtime/execution/process-runtime/lightweight-managed.ts +1184 -0
- package/src/runtime/execution/process-runtime/persisted-check.ts +57 -6
- package/src/runtime/execution/process-runtime/resource-claims.ts +97 -8
- package/src/runtime/execution/process-runtime/runtime.ts +59 -4
- package/src/runtime/execution/process-runtime/store.ts +7 -0
- package/src/runtime/execution/process-runtime/types.ts +2 -0
- package/src/runtime/execution/thin-harness/async-process.ts +12 -2
- package/src/runtime/execution/thin-harness/search-worker.ts +54 -5
- package/src/runtime/execution/workers/executor.ts +0 -48
- package/src/runtime/gateway/mcp/execution-tools.ts +1219 -126
- package/src/runtime/gateway/mcp/process-tools.ts +83 -37
- package/src/runtime/gateway/mcp/router.ts +185 -83
- package/src/runtime/gateway/mcp/runtime-tool-definitions.ts +546 -0
- package/src/runtime/gateway/mcp/runtime-tools.ts +2555 -1616
- package/src/runtime/model-clients/deepseek-adapter.ts +0 -32
- package/src/runtime/plugins/app-store-connect-adapter.ts +123 -19
- package/src/runtime/plugins/browser-adapter.ts +2925 -318
- package/src/runtime/plugins/browser-automation-service.ts +10 -0
- package/src/runtime/plugins/browser-handoff-host.ts +6 -31
- package/src/runtime/plugins/browser-handoff.ts +92 -5
- package/src/runtime/plugins/browser-macos-bridge.ts +586 -45
- package/src/runtime/plugins/browser-node-bridge.ts +6 -34
- package/src/runtime/plugins/browser-provider-registry.ts +109 -0
- package/src/runtime/plugins/browser-runtime-contract.ts +152 -0
- package/src/runtime/plugins/browser-runtime.ts +183 -0
- package/src/runtime/plugins/browser-session-authority.ts +332 -0
- package/src/runtime/plugins/capability-authorization-grants.ts +354 -0
- package/src/runtime/plugins/desktop-operator-registration.ts +15 -12
- package/src/runtime/plugins/external-adapter.ts +324 -3
- package/src/runtime/plugins/external-registration.ts +84 -5
- package/src/runtime/plugins/external-unix-socket.ts +7 -1
- package/src/runtime/plugins/first-party-registry.ts +4 -2
- package/src/runtime/plugins/github-adapter.ts +125 -0
- package/src/runtime/plugins/gmail-adapter.ts +28 -2
- package/src/runtime/plugins/ios/agent-device-provider.ts +1 -1
- package/src/runtime/plugins/ios/agent-device-typed-provider.ts +52 -9
- package/src/runtime/plugins/ios/remote-xpc-hid.ts +1171 -0
- package/src/runtime/plugins/ios-adapter.ts +106 -16
- package/src/runtime/plugins/ios-agent-device.ts +234 -64
- package/src/runtime/plugins/ios-physical-device.ts +1143 -392
- package/src/runtime/plugins/lightweight-action.ts +153 -0
- package/src/runtime/plugins/local-system-adapter.ts +125 -8
- package/src/runtime/plugins/macos-capability-broker.ts +55 -9
- package/src/runtime/plugins/plugin-action-sidecar.ts +59 -0
- package/src/runtime/plugins/plugin-management-adapter.ts +181 -0
- package/src/runtime/plugins/resend-adapter.ts +1 -1
- package/src/runtime/plugins/store.ts +366 -24
- package/src/runtime/plugins/types.ts +39 -2
- package/src/runtime/plugins/xiaohongshu-publish.ts +515 -0
- package/src/runtime/projections/git-status-sampler.ts +16 -16
- package/src/runtime/projections/materialized-view.ts +28 -10
- package/src/runtime/recovery/actions.ts +0 -10
- package/src/runtime/recovery/classifier.ts +0 -9
- package/src/runtime/recovery/maintenance-executor.ts +415 -18
- package/src/runtime/recovery/probe.ts +0 -1
- package/src/runtime/recovery/types.ts +0 -1
- package/src/runtime/root/mcp-transport.ts +180 -10
- package/src/runtime/root/package-connector-service.ts +186 -8
- package/src/runtime/root/package-runtime-release.ts +143 -17
- package/src/runtime/root/package-runtime-service.ts +430 -22
- package/src/runtime/root/release-manifest.ts +7 -2
- package/src/runtime/root/release-materialize.ts +162 -19
- package/src/runtime/root/release-store.ts +48 -11
- package/src/runtime/root/runtime.ts +23 -5
- package/src/runtime/root/service.ts +100 -27
- package/src/runtime/root/types.ts +2 -0
- package/src/runtime/safe-tooling/index.ts +0 -1
- package/src/runtime/safe-tooling/ios-development.ts +321 -63
- package/src/runtime/safe-tooling/types.ts +0 -30
- package/src/runtime/shared/trusted-executable.ts +62 -0
- package/src/runtime/shared/trusted-node-executable.ts +48 -0
- package/src/runtime/standalone-recovery/core.ts +702 -94
- package/src/runtime/standalone-recovery/entry.ts +99 -23
- package/src/runtime/standalone-recovery/installer.ts +19 -3
- package/src/runtime/standalone-recovery/service-labels.ts +2 -0
- package/src/runtime/standalone-recovery/watchdog-heartbeat.ts +160 -0
- package/src/runtime/workflow/schedules/browser-probe.ts +258 -0
- package/src/runtime/workflow/schedules/chatgpt-automation-migration.ts +40 -0
- package/src/runtime/workflow/schedules/engine.ts +509 -80
- package/src/runtime/workflow/schedules/github-issue-watch.ts +158 -0
- package/src/runtime/workflow/schedules/settlement.ts +48 -4
- package/src/runtime/workflow/schedules/store.ts +131 -10
- package/src/runtime/workflow/schedules/types.ts +6 -3
- package/src/runtime/workflow/schedules/work-continuation.ts +120 -34
- package/src/testing/test-governance.ts +8 -40
- package/assets/reference-configs/heartbeat-triage.md +0 -57
- package/assets/templates/helpers/harness-trace-grade.sh +0 -150
- package/assets/templates/helpers/heartbeat-triage.sh +0 -361
- package/assets/templates/helpers/maintenance-triage.sh +0 -167
- package/bin/forge-desktop-helper.mjs +0 -204
- package/docs/architecture/current/approved-target-architecture.zh-CN.md +0 -1501
- package/docs/architecture/current/architecture-invariants.md +0 -331
- package/docs/architecture/current/automation-and-schedule-engine.md +0 -453
- package/docs/architecture/current/codegraph-context-provider.md +0 -226
- package/docs/architecture/current/control-plane-authority-inventory.md +0 -94
- package/docs/architecture/current/controller-repository-decoupling.md +0 -148
- package/docs/architecture/current/dispatch-and-agent-strategy.md +0 -354
- package/docs/architecture/current/entity-model.md +0 -592
- package/docs/architecture/current/external-plugin-governance.md +0 -396
- package/docs/architecture/current/failure-recovery.md +0 -447
- package/docs/architecture/current/governance.md +0 -213
- package/docs/architecture/current/human-interaction-plane.md +0 -87
- package/docs/architecture/current/implementation-status.md +0 -128
- package/docs/architecture/current/job-and-run-lifecycle.md +0 -413
- package/docs/architecture/current/legacy-governance.md +0 -58
- package/docs/architecture/current/local-workspace-target-grants.md +0 -70
- package/docs/architecture/current/migration-roadmap.md +0 -105
- package/docs/architecture/current/multi-repository-execution.md +0 -371
- package/docs/architecture/current/operations-runbook.md +0 -45
- package/docs/architecture/current/peer-supercontroller-runtime.md +0 -32
- package/docs/architecture/current/personal-assistant-plugin-baseline.md +0 -206
- package/docs/architecture/current/repository-access-modes.md +0 -102
- package/docs/architecture/current/route-policy.md +0 -15
- package/docs/architecture/current/route-session-concurrency.md +0 -85
- package/docs/architecture/current/runtime-architecture-simplification.md +0 -214
- package/docs/architecture/current/runtime-directory-map.md +0 -49
- package/docs/architecture/current/runtime-health-and-resource-lifecycle.md +0 -85
- package/docs/architecture/current/scheduler-and-resource-claims.md +0 -422
- package/docs/architecture/current/session-aware-execution-and-authorization.md +0 -77
- package/docs/architecture/current/system-overview.md +0 -144
- package/docs/architecture/current/target-requirements-traceability.md +0 -202
- package/docs/architecture/current/thin-harness-governance-policy.md +0 -32
- package/docs/architecture/current/thin-harness-v1.md +0 -311
- package/docs/architecture/current/verification-and-release-gates.md +0 -391
- package/docs/forge-autonomous-goal-loop.md +0 -9
- package/docs/forge-provider-configuration.md +0 -7
- package/docs/operations/chatgpt-personal-assistant-runtime.md +0 -83
- package/docs/operations/controller-desktop-plugin.md +0 -112
- package/docs/operations/gmail-assistant-routines.md +0 -186
- package/docs/operations/personal-assistant-operator-guide.md +0 -61
- package/docs/operations/provider-configuration.md +0 -31
- package/scripts/harness-trace-grade.sh +0 -150
- package/scripts/heartbeat-triage.sh +0 -361
- package/scripts/maintenance-triage.sh +0 -167
- package/src/cli/local-bridge/frontend/src/features/settings/SettingsView.tsx +0 -2
- package/src/cli/repositories/goal-registry.ts +0 -239
- package/src/runtime/assistant/action-proposals.ts +0 -279
- package/src/runtime/assistant/intent.ts +0 -395
- package/src/runtime/assistant/model-provider.ts +0 -460
- package/src/runtime/assistant/openapi.ts +0 -223
- package/src/runtime/assistant/policy.ts +0 -89
- package/src/runtime/assistant/readiness.ts +0 -258
- package/src/runtime/assistant/routine-runtime.ts +0 -477
- package/src/runtime/assistant/schedule-binding.ts +0 -171
- package/src/runtime/assistant/standing-grants.ts +0 -375
- package/src/runtime/assistant/store.ts +0 -243
- package/src/runtime/assistant/types.ts +0 -135
- package/src/runtime/control-plane/goal-loop/config-facade.ts +0 -700
- package/src/runtime/control-plane/goal-loop/config-store.ts +0 -570
- package/src/runtime/control-plane/goal-loop/config-types.ts +0 -213
- package/src/runtime/control-plane/goal-loop/executor-router.ts +0 -109
- package/src/runtime/control-plane/goal-loop/failure-taxonomy.ts +0 -149
- package/src/runtime/control-plane/goal-loop/goal-contract-store.ts +0 -304
- package/src/runtime/control-plane/goal-loop/goal-loop-engine.ts +0 -1001
- package/src/runtime/control-plane/goal-loop/handoff-packet.ts +0 -160
- package/src/runtime/control-plane/goal-loop/index.ts +0 -13
- package/src/runtime/control-plane/goal-loop/local-tools.ts +0 -290
- package/src/runtime/control-plane/goal-loop/policy-gates.ts +0 -203
- package/src/runtime/control-plane/goal-loop/provider-dispatch.ts +0 -93
- package/src/runtime/control-plane/goal-loop/provider-registry.ts +0 -545
- package/src/runtime/control-plane/goal-loop/types.ts +0 -378
- package/src/runtime/control-plane/startup-recovery.ts +0 -198
- package/src/runtime/gateway/mcp/resource-policy.ts +0 -186
- package/src/runtime/personal-assistant/gmail-triage-manager.ts +0 -231
- package/src/runtime/personal-assistant/reporting-runtime.ts +0 -344
- package/src/runtime/personal-assistant/triage-runtime.ts +0 -748
- package/src/runtime/plugins/desktop-adapter.ts +0 -374
- package/src/runtime/safe-tooling/browser-safe.ts +0 -133
- package/src/runtime/workflow/findings/store.ts +0 -204
- package/src/runtime/workflow/findings/types.ts +0 -58
- package/src/runtime/workflow/portfolio/engine.ts +0 -20
- package/src/runtime/workflow/portfolio/store.ts +0 -185
- package/src/runtime/workflow/portfolio/types.ts +0 -29
|
@@ -1,22 +1,20 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Repository-scoped
|
|
2
|
+
* Repository-scoped Lightweight/Durable Process lifecycle MCP tools.
|
|
3
3
|
*
|
|
4
4
|
* process_get / process_wait / process_logs / process_cancel
|
|
5
5
|
*
|
|
6
|
-
* These tools attach to an existing
|
|
7
|
-
* re-execute the original command.
|
|
6
|
+
* These tools attach to an existing in-memory lightweight or persisted durable
|
|
7
|
+
* handle. They never re-execute the original command.
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
10
|
import type { McpToolDefinition, CallToolResult } from '../../../cli/mcp/tools';
|
|
11
11
|
import type { MultiRepositoryMcpToolContext } from '../../../cli/mcp/multi-repository';
|
|
12
|
-
import { getRepository } from '../../../cli/repositories/registry';
|
|
13
12
|
import {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
13
|
+
cancelRepositoryCommandProcess,
|
|
14
|
+
getRepositoryCommandProcess,
|
|
15
|
+
readRepositoryCommandProcessLogs,
|
|
16
|
+
waitRepositoryCommandProcess,
|
|
18
17
|
} from '../../execution/process-runtime';
|
|
19
|
-
import { getProcessRecord } from '../../execution/process-runtime/store';
|
|
20
18
|
import { redactSensitiveText, redactSensitiveValue } from '../../evidence/sensitive-output';
|
|
21
19
|
|
|
22
20
|
function definition(
|
|
@@ -42,17 +40,36 @@ function definition(
|
|
|
42
40
|
|
|
43
41
|
const repoIdProp = {
|
|
44
42
|
type: 'string',
|
|
45
|
-
description: '
|
|
43
|
+
description: 'Repository or ephemeral workspace scope id returned by the originating command. Process must belong to this scope.',
|
|
46
44
|
};
|
|
47
45
|
const processIdProp = {
|
|
48
46
|
type: 'string',
|
|
49
|
-
description: '
|
|
47
|
+
description: 'Lightweight or durable process id returned by run_check / repository_command_execute.',
|
|
50
48
|
};
|
|
51
49
|
|
|
52
50
|
export const processToolDefinitions: McpToolDefinition[] = [
|
|
51
|
+
definition(
|
|
52
|
+
'run_check',
|
|
53
|
+
'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.',
|
|
54
|
+
{
|
|
55
|
+
repo_id: repoIdProp,
|
|
56
|
+
checkout_id: { type: 'string' },
|
|
57
|
+
check_id: { type: 'string', description: 'Single check id. Mutually exclusive with check_ids.' },
|
|
58
|
+
check_ids: { type: 'array', items: { type: 'string' }, minItems: 1, maxItems: 32, uniqueItems: true, description: 'Batch check ids. All requested checks must fit one resource-compatible execution wave; mutually exclusive with check_id.' },
|
|
59
|
+
timeout_ms: { type: 'number' },
|
|
60
|
+
request_id: { type: 'string' },
|
|
61
|
+
issue_id: { type: 'string' },
|
|
62
|
+
task_id: { type: 'string' },
|
|
63
|
+
mode: { type: 'string', enum: ['direct', 'async', 'durable'] },
|
|
64
|
+
apply_mode: { type: 'string', enum: ['sync', 'async'] },
|
|
65
|
+
force_durable: { type: 'boolean' },
|
|
66
|
+
},
|
|
67
|
+
[],
|
|
68
|
+
false,
|
|
69
|
+
),
|
|
53
70
|
definition(
|
|
54
71
|
'process_get',
|
|
55
|
-
'
|
|
72
|
+
'Non-blocking observation of a lightweight or durable process; never re-executes. Use only when the observation can change the next decision. It is not a synchronization join.',
|
|
56
73
|
{
|
|
57
74
|
repo_id: repoIdProp,
|
|
58
75
|
process_id: processIdProp,
|
|
@@ -62,7 +79,7 @@ export const processToolDefinitions: McpToolDefinition[] = [
|
|
|
62
79
|
),
|
|
63
80
|
definition(
|
|
64
81
|
'process_wait',
|
|
65
|
-
'
|
|
82
|
+
'Explicit dependency synchronization for one lightweight or durable process. Call only when the next decision or acceptance boundary is blocked on this exact result; do not use as periodic polling. Waits never re-execute the command.',
|
|
66
83
|
{
|
|
67
84
|
repo_id: repoIdProp,
|
|
68
85
|
process_id: processIdProp,
|
|
@@ -73,7 +90,7 @@ export const processToolDefinitions: McpToolDefinition[] = [
|
|
|
73
90
|
),
|
|
74
91
|
definition(
|
|
75
92
|
'process_logs',
|
|
76
|
-
'Read a bounded tail of
|
|
93
|
+
'Read a bounded tail of lightweight or durable process stdout/stderr. Never loads unbounded logs. Readonly.',
|
|
77
94
|
{
|
|
78
95
|
repo_id: repoIdProp,
|
|
79
96
|
process_id: processIdProp,
|
|
@@ -84,7 +101,7 @@ export const processToolDefinitions: McpToolDefinition[] = [
|
|
|
84
101
|
),
|
|
85
102
|
definition(
|
|
86
103
|
'process_cancel',
|
|
87
|
-
'Cancel a
|
|
104
|
+
'Cancel a lightweight or durable process through its owning runtime handle. Classified as workspace-write / process-control.',
|
|
88
105
|
{
|
|
89
106
|
repo_id: repoIdProp,
|
|
90
107
|
process_id: processIdProp,
|
|
@@ -96,10 +113,36 @@ export const processToolDefinitions: McpToolDefinition[] = [
|
|
|
96
113
|
];
|
|
97
114
|
|
|
98
115
|
const processToolNames = new Set(processToolDefinitions.map((tool) => tool.name));
|
|
99
|
-
|
|
100
|
-
//
|
|
101
|
-
//
|
|
102
|
-
|
|
116
|
+
const processAttachmentToolNames = new Set(['process_get', 'process_wait', 'process_logs', 'process_cancel']);
|
|
117
|
+
// A long-lived MCP wait can monopolize shared Runtime request/transport capacity
|
|
118
|
+
// even though the underlying Process wait is asynchronous. Keep public waits
|
|
119
|
+
// short and return a normal running snapshot; the Process continues unchanged
|
|
120
|
+
// and callers can attach again only when the result is a real dependency.
|
|
121
|
+
export const DEFAULT_PROCESS_WAIT_ATTACH_BUDGET_MS = 5_000;
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Stable controller-facing continuation semantics for a returned Process.
|
|
125
|
+
* This is deliberately response-only: Process Runtime remains the sole owner
|
|
126
|
+
* of execution and no polling scheduler or second state authority is created.
|
|
127
|
+
*/
|
|
128
|
+
export function managedProcessContinuation(handle: { completed?: boolean }): Record<string, string> {
|
|
129
|
+
if (handle.completed === true) {
|
|
130
|
+
return {
|
|
131
|
+
state: 'terminal',
|
|
132
|
+
nextAction: 'consume_terminal_result',
|
|
133
|
+
join: 'complete',
|
|
134
|
+
reexecution: 'forbidden',
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
return {
|
|
138
|
+
state: 'background',
|
|
139
|
+
nextAction: 'continue_independent_work',
|
|
140
|
+
join: 'required_at_dependency_boundary',
|
|
141
|
+
observation: 'process_get_if_it_can_change_the_next_decision',
|
|
142
|
+
repeatedWait: 'not_recommended',
|
|
143
|
+
reexecution: 'forbidden',
|
|
144
|
+
};
|
|
145
|
+
}
|
|
103
146
|
|
|
104
147
|
function result(value: Record<string, unknown>, isError = false): CallToolResult {
|
|
105
148
|
const safe = redactSensitiveValue(value).value;
|
|
@@ -125,24 +168,18 @@ function requireRepoAndProcess(
|
|
|
125
168
|
if (!repoId) throw new Error('REPOSITORY_ID_REQUIRED: repo_id is required for process tools');
|
|
126
169
|
if (!processId) throw new Error('PROCESS_ID_REQUIRED: process_id is required for process tools');
|
|
127
170
|
|
|
128
|
-
//
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
// Process must belong to the requested repo.
|
|
135
|
-
const record = getProcessRecord(ctx.controllerHome, repoId, processId);
|
|
136
|
-
if (!record) {
|
|
171
|
+
// The Process handle is the scope authority. Ephemeral workspace targets are
|
|
172
|
+
// intentionally not registered in Repository Registry, so requiring a live
|
|
173
|
+
// repository record here would make their returned managed handles impossible
|
|
174
|
+
// to resume. Exact repo/workspace scope + process id still fails closed.
|
|
175
|
+
const handle = getRepositoryCommandProcess(ctx.controllerHome, repoId, processId);
|
|
176
|
+
if (!handle) {
|
|
137
177
|
throw new Error(`PROCESS_NOT_FOUND: process ${processId} is not registered under repo ${repoId}`);
|
|
138
178
|
}
|
|
139
|
-
if (record.repoId !== repoId) {
|
|
140
|
-
throw new Error(`PROCESS_REPO_MISMATCH: process ${processId} belongs to ${record.repoId}, not ${repoId}`);
|
|
141
|
-
}
|
|
142
179
|
return { repoId, processId };
|
|
143
180
|
}
|
|
144
181
|
|
|
145
|
-
function handleToPayload(handle: NonNullable<ReturnType<typeof
|
|
182
|
+
function handleToPayload(handle: NonNullable<ReturnType<typeof getRepositoryCommandProcess>>): Record<string, unknown> {
|
|
146
183
|
return {
|
|
147
184
|
processId: handle.processId,
|
|
148
185
|
workId: handle.workId,
|
|
@@ -161,8 +198,13 @@ function handleToPayload(handle: NonNullable<ReturnType<typeof getProcessHandle>
|
|
|
161
198
|
cancelled: handle.cancelled,
|
|
162
199
|
stdout: handle.stdout,
|
|
163
200
|
stderr: handle.stderr,
|
|
201
|
+
// Keep the bounded tail available after completion for callers that use it
|
|
202
|
+
// as their compact log view. Lightweight terminal receipts bound this tail
|
|
203
|
+
// separately, so retaining the established field does not restore the
|
|
204
|
+
// previous full-output duplication in persisted state.
|
|
164
205
|
stdoutTail: handle.stdoutTail,
|
|
165
206
|
stderrTail: handle.stderrTail,
|
|
207
|
+
continuation: managedProcessContinuation(handle),
|
|
166
208
|
durableSideEffects: handle.durableSideEffects,
|
|
167
209
|
};
|
|
168
210
|
}
|
|
@@ -172,12 +214,15 @@ export async function callProcessTool(
|
|
|
172
214
|
name: string,
|
|
173
215
|
args: Record<string, unknown>,
|
|
174
216
|
): Promise<CallToolResult | undefined> {
|
|
175
|
-
|
|
217
|
+
// run_check shares this module's public schema, but its execution authority is
|
|
218
|
+
// the Gateway check facade in router.ts. Only attachment/lifecycle operations
|
|
219
|
+
// consume an existing process_id here.
|
|
220
|
+
if (!processAttachmentToolNames.has(name)) return undefined;
|
|
176
221
|
try {
|
|
177
222
|
const { repoId, processId } = requireRepoAndProcess(ctx, args);
|
|
178
223
|
switch (name) {
|
|
179
224
|
case 'process_get': {
|
|
180
|
-
const handle =
|
|
225
|
+
const handle = getRepositoryCommandProcess(ctx.controllerHome, repoId, processId);
|
|
181
226
|
if (!handle) throw new Error(`PROCESS_NOT_FOUND: ${processId}`);
|
|
182
227
|
return result({
|
|
183
228
|
repoId,
|
|
@@ -193,12 +238,13 @@ export async function callProcessTool(
|
|
|
193
238
|
? Math.max(1, Math.trunc(testBudget))
|
|
194
239
|
: DEFAULT_PROCESS_WAIT_ATTACH_BUDGET_MS;
|
|
195
240
|
const startedAt = Date.now();
|
|
196
|
-
const handle = await
|
|
241
|
+
const handle = await waitRepositoryCommandProcess(ctx.controllerHome, repoId, processId, {
|
|
197
242
|
timeoutMs: Math.min(requestedWaitMs, attachBudgetMs),
|
|
198
243
|
});
|
|
199
244
|
return result({
|
|
200
245
|
repoId,
|
|
201
246
|
process: handleToPayload(handle),
|
|
247
|
+
synchronization: handle.completed === true ? 'terminal_result_available' : 'continue_independent_work',
|
|
202
248
|
waitedMs: Date.now() - startedAt,
|
|
203
249
|
requestedWaitMs,
|
|
204
250
|
attachBudgetMs,
|
|
@@ -209,7 +255,7 @@ export async function callProcessTool(
|
|
|
209
255
|
const maxBytes = typeof args.max_bytes === 'number' && Number.isFinite(args.max_bytes)
|
|
210
256
|
? Math.max(256, Math.trunc(args.max_bytes))
|
|
211
257
|
: 32 * 1024;
|
|
212
|
-
const logs =
|
|
258
|
+
const logs = readRepositoryCommandProcessLogs(ctx.controllerHome, repoId, processId, maxBytes);
|
|
213
259
|
if (!logs) throw new Error(`PROCESS_NOT_FOUND: ${processId}`);
|
|
214
260
|
return result({
|
|
215
261
|
repoId,
|
|
@@ -223,7 +269,7 @@ export async function callProcessTool(
|
|
|
223
269
|
});
|
|
224
270
|
}
|
|
225
271
|
case 'process_cancel': {
|
|
226
|
-
const handle = await
|
|
272
|
+
const handle = await cancelRepositoryCommandProcess(ctx.controllerHome, repoId, processId);
|
|
227
273
|
return result({
|
|
228
274
|
repoId,
|
|
229
275
|
process: handleToPayload(handle),
|
|
@@ -4,19 +4,24 @@ import {
|
|
|
4
4
|
buildMultiRepositoryToolDefinitions,
|
|
5
5
|
type MultiRepositoryMcpToolContext,
|
|
6
6
|
} from '../../../cli/mcp/multi-repository';
|
|
7
|
-
import {
|
|
7
|
+
import {
|
|
8
|
+
callRepositoryTool,
|
|
9
|
+
claimedSessionEditBinding,
|
|
10
|
+
repositoryToolDefinitions,
|
|
11
|
+
} from '../../../cli/mcp/repository-tools';
|
|
8
12
|
import { runtimeToolDefinitions } from './runtime-tools';
|
|
9
13
|
import { executionToolDefinitions } from './execution-tools';
|
|
10
14
|
import { processToolDefinitions } from './process-tools';
|
|
11
15
|
import { resolveRepositorySelection } from '../../../cli/repositories/registry';
|
|
16
|
+
import { listControllerChecks } from '../../../cli/controller/check-runner';
|
|
12
17
|
import { executionIdentityForRepository } from '../../control-plane/execution/execution-identity';
|
|
13
|
-
import {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
} from '
|
|
18
|
-
import {
|
|
19
|
-
import { classifyRepositoryCommand
|
|
18
|
+
import {
|
|
19
|
+
resolveEditValidationRepository,
|
|
20
|
+
startOrJoinEditValidation,
|
|
21
|
+
} from '../../control-plane/execution/edit-validation-coordinator';
|
|
22
|
+
import { assertEditSessionDurableBinding } from '../../../cli/editing/edit-session';
|
|
23
|
+
import type { ExecutionTimeoutPolicy } from '../../execution/jobs/types';
|
|
24
|
+
import { classifyRepositoryCommand } from '../../../cli/repositories/command-classifier';
|
|
20
25
|
import {
|
|
21
26
|
isFastEligibleTool,
|
|
22
27
|
routeExecution,
|
|
@@ -27,6 +32,7 @@ import {
|
|
|
27
32
|
classifyRepositoryCommandRoute,
|
|
28
33
|
} from '../../execution/process-runtime';
|
|
29
34
|
import { runPersistedCheckViaProcessRuntime } from './persisted-check-process';
|
|
35
|
+
import { buildCheckExecutionSchedule } from '../../execution/process-runtime/check-scheduling';
|
|
30
36
|
import {
|
|
31
37
|
isProcessIsolatedReadDiagnostic,
|
|
32
38
|
runReadOnlyDiagnosticViaProcessRuntime,
|
|
@@ -93,8 +99,17 @@ export function isGatewayIsolatedTool(name: string): boolean {
|
|
|
93
99
|
return GATEWAY_ISOLATED_TOOLS.has(name);
|
|
94
100
|
}
|
|
95
101
|
|
|
96
|
-
/**
|
|
97
|
-
|
|
102
|
+
/**
|
|
103
|
+
* Tools that own their execution boundary and must never fall through to
|
|
104
|
+
* retired generic ExecutionJob creation. Legacy iOS atomics are compatibility
|
|
105
|
+
* adapters over the typed iOS plugin authority.
|
|
106
|
+
*/
|
|
107
|
+
const SELF_MANAGED_DURABLE_TOOLS = new Set([
|
|
108
|
+
'plugin_action_execute',
|
|
109
|
+
'ios_xcode_status', 'ios_simulators_list', 'ios_project_discover', 'ios_schemes_list',
|
|
110
|
+
'ios_simulator_boot', 'ios_app_build', 'ios_app_install', 'ios_app_launch',
|
|
111
|
+
'ios_simulator_screenshot', 'ios_simulator_log_tail', 'ios_ui_smoke_test',
|
|
112
|
+
]);
|
|
98
113
|
|
|
99
114
|
export function isSelfManagedDurableTool(name: string): boolean {
|
|
100
115
|
return SELF_MANAGED_DURABLE_TOOLS.has(name);
|
|
@@ -106,7 +121,6 @@ const DIRECT_HOT_READ_TOOLS = new Set([
|
|
|
106
121
|
'work_get', 'work_list', 'work_status_digest', 'work_result_summary',
|
|
107
122
|
'controller_ready', 'repository_runtime_snapshot',
|
|
108
123
|
'rh_status', 'rh_context', 'rh_inbox',
|
|
109
|
-
'controller_context_pack',
|
|
110
124
|
'repository_git_status', 'repository_git_diff', 'git_diff_paths',
|
|
111
125
|
]);
|
|
112
126
|
|
|
@@ -145,7 +159,6 @@ const EXPLICIT_EXTERNAL_CONTROLLER_TOOLS = new Set([
|
|
|
145
159
|
'publish_issue_to_github',
|
|
146
160
|
'close_github_issue',
|
|
147
161
|
'request_release_gate',
|
|
148
|
-
'promote_candidate_finding',
|
|
149
162
|
]);
|
|
150
163
|
|
|
151
164
|
const GATEWAY_ROUTE_BEHAVIOR_PROBES: ReadonlyArray<{
|
|
@@ -296,8 +309,9 @@ function result(value: Record<string, unknown>, isError = false): CallToolResult
|
|
|
296
309
|
}
|
|
297
310
|
|
|
298
311
|
export function getMcpToolDefinition(ctx: MultiRepositoryMcpToolContext, name: string): McpToolDefinition | undefined {
|
|
299
|
-
|
|
300
|
-
|
|
312
|
+
const currentDefinitions = [...runtimeToolDefinitions, ...executionToolDefinitions, ...processToolDefinitions, ...repositoryToolDefinitions];
|
|
313
|
+
if (ctx.toolset !== 'full') return currentDefinitions.find((tool) => tool.name === name);
|
|
314
|
+
return [...currentDefinitions, ...buildMultiRepositoryToolDefinitions(ctx)].find((tool) => tool.name === name);
|
|
301
315
|
}
|
|
302
316
|
|
|
303
317
|
/**
|
|
@@ -370,10 +384,16 @@ export function classifyGatewayExecutionPath(
|
|
|
370
384
|
// run_check: Process Runtime for ordinary checks; Durable only for release/multi-phase.
|
|
371
385
|
if (name === 'run_check') {
|
|
372
386
|
const checkId = String(args.check_id ?? args.checkId ?? '').trim();
|
|
387
|
+
const batchCheckIds = Array.isArray(args.check_ids)
|
|
388
|
+
? args.check_ids.map((value) => String(value).trim()).filter(Boolean)
|
|
389
|
+
: [];
|
|
373
390
|
if (args.mode === 'durable' || args.force_durable === true) {
|
|
374
391
|
return { path: 'durable', reasons: ['caller_requested_durable_check'] };
|
|
375
392
|
}
|
|
376
|
-
|
|
393
|
+
// A batch containing release/multi-phase checks is routed through the fast
|
|
394
|
+
// facade only so the batch validator can fail closed with structured
|
|
395
|
+
// scheduling evidence. It must never create a partial Durable workflow.
|
|
396
|
+
if (batchCheckIds.length === 0 && checkId && checkRequiresDurableWorkflow(checkId)) {
|
|
377
397
|
return { path: 'durable', reasons: ['multi_phase_or_release_check'] };
|
|
378
398
|
}
|
|
379
399
|
// Route as "fast" so shouldCreateDurableJob returns false; actual execution
|
|
@@ -578,68 +598,6 @@ export function validateMcpToolArguments(name: string, definition: McpToolDefini
|
|
|
578
598
|
}
|
|
579
599
|
}
|
|
580
600
|
|
|
581
|
-
export function operationMetadataForTool(
|
|
582
|
-
name: string,
|
|
583
|
-
definition: McpToolDefinition,
|
|
584
|
-
claims: ReturnType<typeof claimsForMcpOperation>,
|
|
585
|
-
timeoutMs: number,
|
|
586
|
-
args: Record<string, unknown> = {},
|
|
587
|
-
defaultBranch?: string,
|
|
588
|
-
timeoutPolicy?: ExecutionTimeoutPolicy,
|
|
589
|
-
): ExecutionOperationMetadata {
|
|
590
|
-
if (name === 'repository_command_execute' && args.command !== undefined) {
|
|
591
|
-
const classification = classifyRepositoryCommand(args.command as string | string[], defaultBranch);
|
|
592
|
-
const replay = classifyRepositoryCommandReplay(args.command as string | string[], defaultBranch);
|
|
593
|
-
const mode = classification.risk === 'readonly'
|
|
594
|
-
? 'readonly'
|
|
595
|
-
: classification.risk === 'remote_write'
|
|
596
|
-
? 'remote_write'
|
|
597
|
-
: classification.risk === 'destructive'
|
|
598
|
-
? 'destructive'
|
|
599
|
-
: 'mutating';
|
|
600
|
-
return {
|
|
601
|
-
mode,
|
|
602
|
-
idempotent: replay.idempotent,
|
|
603
|
-
replayable: replay.replayable,
|
|
604
|
-
timeoutMs,
|
|
605
|
-
admissionTimeoutMs: timeoutPolicy?.admissionTimeoutMs,
|
|
606
|
-
queueTimeoutMs: timeoutPolicy?.queueTimeoutMs,
|
|
607
|
-
executionTimeoutMs: timeoutPolicy?.executionTimeoutMs,
|
|
608
|
-
interactiveWaitMs: timeoutPolicy?.interactiveWaitMs,
|
|
609
|
-
retryPolicy: replay.retryPolicy,
|
|
610
|
-
approvalPolicy: classification.risk === 'readonly'
|
|
611
|
-
? 'none'
|
|
612
|
-
: classification.risk === 'destructive' ? 'required' : 'request',
|
|
613
|
-
lockScope: claims.map((claim) => claim.resourceKey),
|
|
614
|
-
resourceClaims: claims,
|
|
615
|
-
};
|
|
616
|
-
}
|
|
617
|
-
const destructive = definition.annotations?.destructiveHint === true;
|
|
618
|
-
const remoteWrite = claims.some((claim) => claim.resourceKey.startsWith('remote:'));
|
|
619
|
-
const readOnly = definition.annotations?.readOnlyHint === true || claims.length === 0;
|
|
620
|
-
const mode = destructive
|
|
621
|
-
? 'destructive'
|
|
622
|
-
: remoteWrite
|
|
623
|
-
? 'remote_write'
|
|
624
|
-
: readOnly
|
|
625
|
-
? 'readonly'
|
|
626
|
-
: 'mutating';
|
|
627
|
-
return {
|
|
628
|
-
mode,
|
|
629
|
-
idempotent: readOnly,
|
|
630
|
-
replayable: readOnly,
|
|
631
|
-
timeoutMs,
|
|
632
|
-
admissionTimeoutMs: timeoutPolicy?.admissionTimeoutMs,
|
|
633
|
-
queueTimeoutMs: timeoutPolicy?.queueTimeoutMs,
|
|
634
|
-
executionTimeoutMs: timeoutPolicy?.executionTimeoutMs,
|
|
635
|
-
interactiveWaitMs: timeoutPolicy?.interactiveWaitMs,
|
|
636
|
-
retryPolicy: readOnly ? 'safe_retry' : 'idempotent_request',
|
|
637
|
-
approvalPolicy: destructive ? 'required' : remoteWrite || !readOnly ? 'request' : 'none',
|
|
638
|
-
lockScope: claims.map((claim) => claim.resourceKey),
|
|
639
|
-
resourceClaims: claims,
|
|
640
|
-
};
|
|
641
|
-
}
|
|
642
|
-
|
|
643
601
|
export function injectDurableCommandFields(tool: McpToolDefinition): McpToolDefinition {
|
|
644
602
|
const schema = tool.inputSchema as { type?: unknown; properties?: Record<string, unknown>; [key: string]: unknown };
|
|
645
603
|
if (schema.type !== 'object') return tool;
|
|
@@ -693,7 +651,14 @@ async function runEditSessionValidationViaProcessRuntime(
|
|
|
693
651
|
editSessionId: string,
|
|
694
652
|
args: Record<string, unknown>,
|
|
695
653
|
): Promise<CallToolResult> {
|
|
696
|
-
const
|
|
654
|
+
const resolved = resolveEditValidationRepository(repository, editSessionId);
|
|
655
|
+
const binding = claimedSessionEditBinding(ctx.controllerHome, resolved.repository, {
|
|
656
|
+
sessionId: ctx.sessionId,
|
|
657
|
+
principalId: ctx.principalId,
|
|
658
|
+
controllerInstanceId: ctx.controllerInstanceId,
|
|
659
|
+
}, args.work_id);
|
|
660
|
+
assertEditSessionDurableBinding(resolved.session, binding, { requireBoundIdentity: true });
|
|
661
|
+
const validation = await startOrJoinEditValidation(ctx.controllerHome, resolved.repository, {
|
|
697
662
|
editSessionId,
|
|
698
663
|
checkIds: Array.isArray(args.check_ids) ? args.check_ids.map(String) : undefined,
|
|
699
664
|
requestId: typeof args.request_id === 'string' ? args.request_id : undefined,
|
|
@@ -775,7 +740,11 @@ export async function routeDurableMcpCall(
|
|
|
775
740
|
}, true);
|
|
776
741
|
}
|
|
777
742
|
|
|
778
|
-
|
|
743
|
+
// repository_command_execute has its own durable boundary: non-destructive
|
|
744
|
+
// remote writes run through the durable Process Runtime, while destructive or
|
|
745
|
+
// explicitly delegated commands are refused by the repository facade itself.
|
|
746
|
+
// Do not intercept that tool with the retired ExecutionJob gate here.
|
|
747
|
+
if (classification.path === 'durable' && executionJobCreationRetired() && name !== 'repository_command_execute') {
|
|
779
748
|
return result({
|
|
780
749
|
accepted: false,
|
|
781
750
|
mode: 'external_controller_required',
|
|
@@ -898,7 +867,7 @@ export async function routeDurableMcpCall(
|
|
|
898
867
|
}, validation.isError === true);
|
|
899
868
|
}
|
|
900
869
|
|
|
901
|
-
const applied = await callRepositoryTool(ctx.controllerHome, name, args);
|
|
870
|
+
const applied = await callRepositoryTool(ctx.controllerHome, name, args, ctx);
|
|
902
871
|
if (!applied || applied.isError === true) return applied;
|
|
903
872
|
const patchPayload = (applied.structuredContent ?? {}) as Record<string, unknown>;
|
|
904
873
|
if (patchPayload.status !== 'applied') return applied;
|
|
@@ -947,12 +916,145 @@ export async function routeDurableMcpCall(
|
|
|
947
916
|
});
|
|
948
917
|
}
|
|
949
918
|
const checkId = String(args.check_id ?? '').trim();
|
|
950
|
-
|
|
919
|
+
const rawBatchCheckIds = args.check_ids;
|
|
920
|
+
const hasBatchInput = Array.isArray(rawBatchCheckIds);
|
|
921
|
+
const batchCheckIds: string[] = hasBatchInput
|
|
922
|
+
? [...new Set(rawBatchCheckIds.map((value: unknown) => String(value).trim()).filter(Boolean))]
|
|
923
|
+
: [];
|
|
924
|
+
if (checkId && hasBatchInput) {
|
|
951
925
|
return result({
|
|
952
926
|
accepted: false,
|
|
953
927
|
mode: 'reject',
|
|
954
928
|
path: 'reject',
|
|
955
|
-
message: 'run_check
|
|
929
|
+
message: 'run_check accepts either check_id or check_ids, not both',
|
|
930
|
+
}, true);
|
|
931
|
+
}
|
|
932
|
+
if (!checkId && batchCheckIds.length === 0) {
|
|
933
|
+
return result({
|
|
934
|
+
accepted: false,
|
|
935
|
+
mode: 'reject',
|
|
936
|
+
path: 'reject',
|
|
937
|
+
message: 'run_check requires check_id or a non-empty check_ids array',
|
|
938
|
+
}, true);
|
|
939
|
+
}
|
|
940
|
+
if (hasBatchInput) {
|
|
941
|
+
const availableChecks = listControllerChecks(repository.canonicalRoot);
|
|
942
|
+
const availableChecksById = new Map(availableChecks.map((check) => [check.id, check]));
|
|
943
|
+
const checkScheduling = buildCheckExecutionSchedule({
|
|
944
|
+
checks: availableChecks,
|
|
945
|
+
requestedCheckIds: batchCheckIds,
|
|
946
|
+
repoId: repository.repoId,
|
|
947
|
+
checkoutId: repository.activeCheckoutId,
|
|
948
|
+
});
|
|
949
|
+
const schedulePayload = {
|
|
950
|
+
waveCount: checkScheduling.waves.length,
|
|
951
|
+
maxParallel: checkScheduling.maxParallel,
|
|
952
|
+
waves: checkScheduling.waves,
|
|
953
|
+
conflicts: checkScheduling.conflicts,
|
|
954
|
+
invalidCheckIds: checkScheduling.invalidCheckIds,
|
|
955
|
+
guidance: checkScheduling.guidance,
|
|
956
|
+
};
|
|
957
|
+
if (checkScheduling.invalidCheckIds.length > 0) {
|
|
958
|
+
return result({
|
|
959
|
+
accepted: false,
|
|
960
|
+
mode: 'reject',
|
|
961
|
+
path: 'reject',
|
|
962
|
+
reason: 'invalid_check_ids',
|
|
963
|
+
checkIds: batchCheckIds,
|
|
964
|
+
checkScheduling: schedulePayload,
|
|
965
|
+
message: `run_check batch contains unregistered checks: ${checkScheduling.invalidCheckIds.join(', ')}`,
|
|
966
|
+
}, true);
|
|
967
|
+
}
|
|
968
|
+
const durableCheckIds = batchCheckIds.filter((id) => checkRequiresDurableWorkflow(id, availableChecksById.get(id)));
|
|
969
|
+
if (durableCheckIds.length > 0) {
|
|
970
|
+
return result({
|
|
971
|
+
accepted: false,
|
|
972
|
+
mode: 'reject',
|
|
973
|
+
path: 'reject',
|
|
974
|
+
reason: 'batch_contains_durable_check',
|
|
975
|
+
checkIds: batchCheckIds,
|
|
976
|
+
durableCheckIds,
|
|
977
|
+
checkScheduling: schedulePayload,
|
|
978
|
+
message: 'Batch run_check only launches ordinary focused checks; run release or multi-phase checks through an explicit durable workflow.',
|
|
979
|
+
}, true);
|
|
980
|
+
}
|
|
981
|
+
if (checkScheduling.waves.length !== 1 || checkScheduling.waves[0]?.checkIds.length !== batchCheckIds.length) {
|
|
982
|
+
return result({
|
|
983
|
+
accepted: false,
|
|
984
|
+
mode: 'reject',
|
|
985
|
+
path: 'reject',
|
|
986
|
+
reason: 'batch_spans_multiple_check_waves',
|
|
987
|
+
checkIds: batchCheckIds,
|
|
988
|
+
checkScheduling: schedulePayload,
|
|
989
|
+
message: 'Requested checks span multiple resource-conflicting waves. Launch one returned wave per run_check call; Forge will not hide serial waiting inside a batch.',
|
|
990
|
+
}, true);
|
|
991
|
+
}
|
|
992
|
+
const baseRequestId = typeof args.request_id === 'string' ? args.request_id.trim() : '';
|
|
993
|
+
const facades = await Promise.all(batchCheckIds.map((batchCheckId, index) => {
|
|
994
|
+
const suffix = createHash('sha256').update(batchCheckId).digest('hex').slice(0, 8);
|
|
995
|
+
return runPersistedCheckViaProcessRuntime({
|
|
996
|
+
controllerHome: ctx.controllerHome,
|
|
997
|
+
repoId: repository.repoId,
|
|
998
|
+
checkoutId: repository.activeCheckoutId,
|
|
999
|
+
repoRoot: repository.canonicalRoot,
|
|
1000
|
+
executionIdentity: executionIdentityForRepository(repository),
|
|
1001
|
+
checkId: batchCheckId,
|
|
1002
|
+
timeoutMs: typeof args.timeout_ms === 'number' ? args.timeout_ms : undefined,
|
|
1003
|
+
interactiveWaitMs: 0,
|
|
1004
|
+
requestId: baseRequestId ? `${baseRequestId}:batch:${index + 1}:${suffix}` : undefined,
|
|
1005
|
+
forceDurable: false,
|
|
1006
|
+
});
|
|
1007
|
+
}));
|
|
1008
|
+
const unexpectedDurable = facades.filter((facade) => facade.mode === 'durable');
|
|
1009
|
+
if (unexpectedDurable.length > 0) {
|
|
1010
|
+
return result({
|
|
1011
|
+
accepted: false,
|
|
1012
|
+
mode: 'reject',
|
|
1013
|
+
path: 'reject',
|
|
1014
|
+
reason: 'batch_check_escalated_to_durable',
|
|
1015
|
+
checkIds: batchCheckIds,
|
|
1016
|
+
checkScheduling: schedulePayload,
|
|
1017
|
+
message: 'At least one batch check unexpectedly requires Durable execution; no further batch orchestration will be created.',
|
|
1018
|
+
}, true);
|
|
1019
|
+
}
|
|
1020
|
+
const processes = facades.map((facade) => ({
|
|
1021
|
+
checkId: facade.checkId,
|
|
1022
|
+
processId: facade.process?.processId,
|
|
1023
|
+
status: facade.process?.status,
|
|
1024
|
+
completed: facade.process?.completed === true,
|
|
1025
|
+
ok: facade.process?.ok,
|
|
1026
|
+
exitCode: facade.process?.exitCode,
|
|
1027
|
+
timedOut: facade.process?.timedOut,
|
|
1028
|
+
deduplicated: facade.process?.deduplicated === true,
|
|
1029
|
+
semanticDeduplicated: facade.process?.semanticDeduplicated === true,
|
|
1030
|
+
durableSideEffects: facade.durableSideEffects,
|
|
1031
|
+
}));
|
|
1032
|
+
const completed = processes.every((process) => process.completed);
|
|
1033
|
+
const mode = processes.every((process) => process.completed) ? 'direct' : 'managed';
|
|
1034
|
+
const durableSideEffects = facades.reduce((total, facade) => ({
|
|
1035
|
+
executionJobCount: total.executionJobCount + facade.durableSideEffects.executionJobCount,
|
|
1036
|
+
localJobCount: total.localJobCount + facade.durableSideEffects.localJobCount,
|
|
1037
|
+
workerSpawnCount: total.workerSpawnCount + facade.durableSideEffects.workerSpawnCount,
|
|
1038
|
+
projectionUpdateCount: total.projectionUpdateCount + facade.durableSideEffects.projectionUpdateCount,
|
|
1039
|
+
}), { executionJobCount: 0, localJobCount: 0, workerSpawnCount: 0, projectionUpdateCount: 0 });
|
|
1040
|
+
return result({
|
|
1041
|
+
accepted: true,
|
|
1042
|
+
batch: true,
|
|
1043
|
+
mode,
|
|
1044
|
+
path: mode === 'direct' ? 'process_batch_direct' : 'process_batch_managed',
|
|
1045
|
+
routing: { path: 'fast', reasons: ['run_check_batch_process_runtime'] },
|
|
1046
|
+
repoId: repository.repoId,
|
|
1047
|
+
checkoutId: repository.activeCheckoutId,
|
|
1048
|
+
checkIds: batchCheckIds,
|
|
1049
|
+
checkScheduling: schedulePayload,
|
|
1050
|
+
processes,
|
|
1051
|
+
processIds: processes.map((process) => process.processId).filter(Boolean),
|
|
1052
|
+
completed,
|
|
1053
|
+
...(completed ? { ok: processes.every((process) => process.ok === true) } : {}),
|
|
1054
|
+
durableSideEffects,
|
|
1055
|
+
next: completed
|
|
1056
|
+
? 'Batch check wave finished on Process Runtime without ExecutionJob / LocalBridgeJob / Worker.'
|
|
1057
|
+
: 'Batch check wave is running concurrently. Continue independent work. Attach to each returned process only when that result becomes a real dependency; do not poll or re-run the checks.',
|
|
956
1058
|
});
|
|
957
1059
|
}
|
|
958
1060
|
const facade = await runPersistedCheckViaProcessRuntime({
|
|
@@ -1012,7 +1114,7 @@ export async function routeDurableMcpCall(
|
|
|
1012
1114
|
durableSideEffects: facade.durableSideEffects,
|
|
1013
1115
|
next: handle?.completed
|
|
1014
1116
|
? 'Check finished on Process Runtime without ExecutionJob / LocalBridgeJob / Worker.'
|
|
1015
|
-
: `Check still running as managed process ${handle?.processId}. Continue independent work;
|
|
1117
|
+
: `Check still running as managed process ${handle?.processId}. Continue independent work; attach with process_wait only when this exact result becomes a real dependency. An attach may return a running handle because transport time is bounded; continue useful work and attach again only at a later dependency boundary. Do not re-run or periodically poll the same check.`,
|
|
1016
1118
|
});
|
|
1017
1119
|
}
|
|
1018
1120
|
|