@moretea-labs/forge 1.7.2 → 1.8.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +121 -62
- package/CHANGELOG.md +40 -0
- package/CLAUDE.md +57 -62
- package/CONTRIBUTING.md +3 -2
- package/README.md +2 -2
- package/SKILL.md +0 -1
- package/THIRD_PARTY_NOTICES.md +5 -2
- package/adapters/browser/index.ts +2 -0
- package/adapters/chatgpt/browser-delivery-host.ts +77 -0
- package/adapters/chatgpt/browser-delivery-runtime.ts +1256 -0
- package/adapters/chatgpt/controller-binding-store.ts +134 -0
- package/adapters/chatgpt/controller-round-host.ts +68 -0
- package/adapters/chatgpt/controller-round-settlement-store.ts +99 -0
- package/adapters/chatgpt/provider-delivery.ts +340 -0
- package/adapters/chatgpt/work-conversation-binding-store.ts +218 -0
- package/adapters/chatgpt/wsl-bridge-delivery-host.ts +63 -0
- package/adapters/computer/chatgpt-extension-target.ts +463 -0
- package/adapters/computer/chatgpt-target-router.ts +103 -0
- package/adapters/computer/chrome-extension/background.js +385 -0
- package/adapters/computer/chrome-extension/content.js +378 -0
- package/adapters/computer/chrome-extension/core.js +24 -0
- package/adapters/computer/chrome-extension/manifest.json +30 -0
- package/adapters/computer/desktop-operator-contract.ts +7 -0
- package/adapters/computer/desktop-operator-discovery.ts +181 -0
- package/adapters/computer/desktop-operator-negotiation.ts +174 -0
- package/adapters/computer/desktop-operator-provider.ts +312 -0
- package/adapters/computer/index.ts +1 -0
- package/adapters/computer/interaction-target-authority.ts +1068 -0
- package/adapters/controller-process/binding-store.ts +34 -0
- package/adapters/controller-process/controller-host.ts +26 -0
- package/adapters/mcp/access-mode.ts +132 -0
- package/adapters/mcp/audit.ts +32 -0
- package/adapters/mcp/auth.ts +406 -0
- package/adapters/mcp/instructions.ts +37 -0
- package/adapters/mcp/legacy-context.ts +18 -0
- package/adapters/mcp/multi-repository.ts +421 -0
- package/adapters/mcp/oauth.ts +464 -0
- package/adapters/mcp/paths.ts +143 -0
- package/adapters/mcp/policy.ts +232 -0
- package/adapters/mcp/proxy-env.ts +62 -0
- package/adapters/mcp/readiness-projection.ts +24 -0
- package/adapters/mcp/redaction.ts +21 -0
- package/adapters/mcp/repo.ts +24 -0
- package/adapters/mcp/runtime-gateway/artifact-adapter.ts +52 -0
- package/adapters/mcp/runtime-gateway/automation-receipt-adapter.ts +87 -0
- package/adapters/mcp/runtime-gateway/bounded-result-runtime.ts +62 -0
- package/adapters/mcp/runtime-gateway/cognition-settlement.ts +201 -0
- package/adapters/mcp/runtime-gateway/context-adapter.ts +1167 -0
- package/adapters/mcp/runtime-gateway/context-pack-sidecar.ts +91 -0
- package/adapters/mcp/runtime-gateway/controller-authority-adapter.ts +206 -0
- package/adapters/mcp/runtime-gateway/core-capability-adapter.ts +258 -0
- package/adapters/mcp/runtime-gateway/engineering-preconditions.ts +130 -0
- package/adapters/mcp/runtime-gateway/engineering-tool-contract.ts +15 -0
- package/adapters/mcp/runtime-gateway/execution-control-adapter.ts +28 -0
- package/adapters/mcp/runtime-gateway/execution-tools.ts +173 -0
- package/adapters/mcp/runtime-gateway/filesystem-adapter.ts +38 -0
- package/adapters/mcp/runtime-gateway/gateway-execution-adapter.ts +412 -0
- package/adapters/mcp/runtime-gateway/legacy-ios-tool-adapter.ts +105 -0
- package/adapters/mcp/runtime-gateway/maintenance-adapter.ts +44 -0
- package/adapters/mcp/runtime-gateway/model-adapter.ts +63 -0
- package/adapters/mcp/runtime-gateway/persisted-check-process.ts +3 -0
- package/adapters/mcp/runtime-gateway/plugin-adapter.ts +380 -0
- package/adapters/mcp/runtime-gateway/process-tools.ts +457 -0
- package/adapters/mcp/runtime-gateway/protected-computer-adapter.ts +88 -0
- package/adapters/mcp/runtime-gateway/recovery-adapter.ts +285 -0
- package/adapters/mcp/runtime-gateway/recovery-client-adapter.ts +70 -0
- package/adapters/mcp/runtime-gateway/recovery-tool-contract.ts +99 -0
- package/adapters/mcp/runtime-gateway/repository-compat-adapter.ts +79 -0
- package/adapters/mcp/runtime-gateway/result-adapter.ts +114 -0
- package/adapters/mcp/runtime-gateway/router.ts +242 -0
- package/adapters/mcp/runtime-gateway/routing-policy.ts +499 -0
- package/adapters/mcp/runtime-gateway/runtime-observation-adapter.ts +1200 -0
- package/adapters/mcp/runtime-gateway/runtime-readiness-observation.ts +218 -0
- package/adapters/mcp/runtime-gateway/runtime-tool-definitions.ts +574 -0
- package/adapters/mcp/runtime-gateway/runtime-tool-shared.ts +27 -0
- package/adapters/mcp/runtime-gateway/runtime-tools.ts +78 -0
- package/adapters/mcp/runtime-gateway/scheduler-adapter.ts +187 -0
- package/adapters/mcp/runtime-gateway/shared-adapter.ts +45 -0
- package/adapters/mcp/runtime-gateway/status-inbox-adapter.ts +962 -0
- package/adapters/mcp/runtime-gateway/typescript-navigation-sidecar.ts +136 -0
- package/adapters/mcp/runtime-gateway/work-adapter.ts +325 -0
- package/adapters/mcp/runtime-gateway/work-controller-operations.ts +257 -0
- package/adapters/mcp/runtime-gateway/work-detail-projection.ts +60 -0
- package/adapters/mcp/runtime-gateway/work-input-wire-migration.ts +246 -0
- package/adapters/mcp/runtime-gateway/work-learning-operations.ts +145 -0
- package/adapters/mcp/runtime-gateway/work-list-projection.ts +38 -0
- package/adapters/mcp/runtime-gateway/work-plan-operations.ts +382 -0
- package/adapters/mcp/runtime-gateway/work-repair-adapter.ts +308 -0
- package/adapters/mcp/runtime-gateway/work-requirement-operations.ts +148 -0
- package/adapters/mcp/runtime-gateway/work-semantic-operations.ts +263 -0
- package/adapters/mcp/runtime-gateway/work-validation-reconciler.ts +1 -0
- package/adapters/mcp/runtime-gateway/work-workflow-operations.ts +113 -0
- package/adapters/mcp/runtime-gateway/workflow-supervisor-adapter.ts +156 -0
- package/adapters/mcp/server.ts +1092 -0
- package/adapters/mcp/setup.ts +789 -0
- package/adapters/mcp/tool-capability-cache.ts +87 -0
- package/adapters/mcp/tool-mapping/access-tools.ts +387 -0
- package/adapters/mcp/tool-mapping/legacy-tool-service.ts +5139 -0
- package/adapters/mcp/tool-mapping/post-finalize-work-attribution.ts +145 -0
- package/adapters/mcp/tool-mapping/repository-tools.ts +1682 -0
- package/adapters/mcp/tool-mapping/tools.ts +9 -0
- package/adapters/mcp/tool-mapping/umbrella-tools.ts +117 -0
- package/adapters/mcp/toolset-names.ts +79 -0
- package/adapters/mcp/toolset-selection.ts +41 -0
- package/adapters/mcp/toolset.ts +337 -0
- package/adapters/mcp/transports/http-observation.ts +365 -0
- package/adapters/mcp/transports/http.ts +933 -0
- package/adapters/mcp/transports/oauth-http.ts +322 -0
- package/adapters/mcp/transports/session-registry.ts +519 -0
- package/adapters/mcp/transports/stdio.ts +8 -0
- package/adapters/mcp/tunnels/openai-secure-tunnel.ts +223 -0
- package/adapters/mcp/types.ts +41 -0
- package/assets/AGENTS.md +2 -16
- package/assets/CLAUDE.md +2 -16
- package/assets/hooks/AGENTS.md +3 -14
- package/assets/hooks/CLAUDE.md +3 -14
- package/assets/hooks/hook-input.sh +9 -2
- package/assets/hooks/lib/workflow-state.sh +28 -10
- package/assets/hooks/prompt-guard.sh +63 -37
- package/assets/hooks/security-sentinel.sh +2 -1
- package/assets/hooks/session-start-context.sh +7 -5
- package/assets/hooks/stop-orchestrator.sh +13 -3
- package/assets/initializer-question-pack.v4.json +11 -7
- package/assets/partials/05-workflow.partial.md +18 -73
- package/assets/partials/07-footer.partial.md +1 -1
- package/assets/partials-agents/02-operating-mode.partial.md +1 -2
- package/assets/partials-agents/04-task-protocol.partial.md +14 -59
- package/assets/partials-agents/06-quality-safety.partial.md +11 -16
- package/assets/partials-agents/08-deep-docs.partial.md +1 -2
- package/assets/plan-map.json +11 -11
- package/assets/plugin-registry.v1.json +11 -3
- package/assets/plugin-trust-policy.v1.json +6 -0
- package/assets/recovery/ForgeRecovery.ps1 +100 -0
- package/assets/recovery/forge-wsl-rescue +271 -0
- package/assets/reference-configs/agentic-development-flow.md +25 -0
- package/assets/reference-configs/development-protocol.md +11 -15
- package/assets/reference-configs/document-generation.md +1 -1
- package/assets/reference-configs/global-working-rules.md +28 -1
- package/assets/reference-configs/harness-overview.md +22 -112
- package/assets/reference-configs/hook-operations.md +1 -1
- package/assets/reference-configs/sprint-contracts.md +2 -2
- package/assets/skill-version.json +2 -2
- package/assets/templates/helpers/architecture-event.ts +3 -34
- package/assets/templates/helpers/architecture-queue.sh +61 -10
- package/assets/templates/helpers/archive-workflow.sh +90 -180
- package/assets/templates/helpers/capability-config.ts +8 -11
- package/assets/templates/helpers/capability-resolver.ts +37 -19
- package/assets/templates/helpers/capture-plan.sh +2 -2
- package/assets/templates/helpers/check-architecture-sync.sh +1 -9
- package/assets/templates/helpers/check-task-sync.sh +82 -11
- package/assets/templates/helpers/check-task-workflow.sh +1 -3
- package/assets/templates/helpers/context-contract-sync.sh +1 -12
- package/assets/templates/helpers/contract-worktree.sh +26 -24
- package/assets/templates/helpers/ensure-task-workflow.sh +6 -8
- package/assets/templates/helpers/inspect-project-state.ts +1 -1
- package/assets/templates/helpers/migrate-project-template.sh +1 -1
- package/assets/templates/helpers/migrate-workflow-docs.ts +53 -239
- package/assets/templates/helpers/new-plan.sh +2 -2
- package/assets/templates/helpers/plan-to-todo.sh +3 -31
- package/assets/templates/helpers/sprint-backlog.sh +1 -1
- package/assets/templates/helpers/switch-plan.sh +1 -1
- package/assets/templates/helpers/workflow-contract.ts +1 -0
- package/assets/workflow-contract.v1.json +63 -171
- package/assets/workflows/xiaohongshu/xiaohongshu.collect-metrics.v1.draft.json +118 -0
- package/assets/workflows/xiaohongshu/xiaohongshu.publish-image-note.v1.draft.json +316 -0
- package/assets/workflows/xiaohongshu/xiaohongshu.publish-long-text.v1.draft.json +324 -0
- package/docs/architecture/CURRENT.md +233 -28
- package/docs/architecture/EVOLUTION.md +13 -0
- package/docs/architecture/decisions/20260801-controller-home-sqlite-state.md +2 -1
- package/docs/architecture/decisions/20260803-release-identity-binding-and-exit-policy.md +14 -5
- package/docs/architecture/decisions/20260823-immediate-controller-relay.md +6 -3
- package/docs/architecture/decisions/20260831-independent-windows-wsl-host-rescue.md +59 -0
- package/docs/architecture/decisions/20260904-ios-device-migration-baseline.md +120 -0
- package/docs/architecture/decisions/20260904-repository-runtime-data-boundary.md +42 -0
- package/docs/architecture/decisions/20260907-assistant-learning-loop.md +37 -0
- package/docs/architecture/decisions/20260907-controller-round-transition-policy.md +311 -0
- package/docs/architecture/decisions/20260907-maintenance-diagnosis-bounded-read.md +39 -0
- package/docs/architecture/decisions/20260916-workflow-supervisor-authority.md +249 -0
- package/docs/architecture/decisions/20260917-cognitive-memory-foundation.md +82 -0
- package/docs/architecture/decisions/20260918-stable-candidate-release-lifecycle.md +221 -0
- package/docs/architecture/decisions/20260919-autonomous-work-liveness.md +62 -0
- package/docs/architecture/decisions/20260924-thin-semantic-working-context.md +72 -0
- package/docs/architecture/decisions/20261001-supervisor-turn-authority.md +237 -0
- package/docs/architecture/decisions/20261005-forge-v3-desktop-client-boundary.md +77 -0
- package/docs/architecture/domains/verification.md +8 -0
- package/docs/architecture/domains/workflow-engine.md +7 -1
- package/docs/architecture/index.md +3 -3
- package/docs/architecture/modules/controller-runtime/transport-lifecycle.md +19 -8
- package/docs/architecture/requests/2026-09-04-computer-plugin-workflow-taxonomy.md +124 -0
- package/docs/forge-chatgpt-mcp-setup.md +5 -3
- package/docs/forge-plugin-management.md +20 -4
- package/docs/forge-runtime-self-healing-loop.md +2 -0
- package/docs/operations/benchmark-cross-version-freeze.md +38 -0
- package/docs/operations/controller-browser-plugin.md +3 -1
- package/docs/operations/controller-performance-and-502.md +17 -0
- package/docs/operations/controller-reliability-runbook.md +2 -2
- package/docs/operations/features.md +1 -1
- package/docs/operations/features.zh-CN.md +1 -1
- package/docs/operations/homebrew.md +2 -2
- package/docs/operations/mcp-tool-exposure.md +2 -0
- package/docs/operations/platform-support.md +16 -8
- package/docs/operations/platform-support.zh-CN.md +2 -2
- package/docs/operations/releasing.md +2 -0
- package/docs/operations/standalone-disaster-recovery.md +38 -5
- package/docs/operations/uu-remote-rescue.md +41 -0
- package/docs/operations/windows-wsl-host-rescue.md +133 -0
- package/docs/public-usage-guide.md +1 -1
- package/docs/public-usage-guide.zh-CN.md +1 -1
- package/docs/tutorials/01-install-and-start.md +1 -1
- package/docs/tutorials/01-install-and-start.zh-CN.md +1 -1
- package/docs/tutorials/02-connect-chatgpt.md +4 -4
- package/docs/tutorials/02-connect-chatgpt.zh-CN.md +4 -4
- package/docs/wiki/Implementation.md +1 -1
- package/package.json +46 -26
- package/packages/kernel/cognition/api/index.ts +6 -0
- package/packages/kernel/cognition/application/activation-service.ts +451 -0
- package/packages/kernel/cognition/application/consolidation-service.ts +185 -0
- package/packages/kernel/cognition/application/legacy-experience-adapter.ts +38 -0
- package/packages/kernel/cognition/application/memory-service.ts +64 -0
- package/packages/kernel/cognition/domain/learning.ts +106 -0
- package/packages/kernel/cognition/domain/memory.ts +254 -0
- package/packages/kernel/controller/api/index.ts +3 -0
- package/packages/kernel/controller/application/continuation-service.ts +281 -0
- package/packages/kernel/controller/application/controller-round-service.ts +41 -0
- package/packages/kernel/controller/application/controller-service.ts +30 -0
- package/packages/kernel/controller/domain/controller-round-transition-policy.ts +529 -0
- package/packages/kernel/controller/domain/controller-round.ts +110 -0
- package/packages/kernel/controller/domain/execution-quality.ts +135 -0
- package/packages/kernel/controller/domain/types.ts +56 -0
- package/packages/kernel/controller/index.ts +1 -0
- package/packages/kernel/controller/infrastructure/controller-binding-store.ts +84 -0
- package/packages/kernel/controller/infrastructure/controller-round-store.ts +1970 -0
- package/packages/kernel/controller/infrastructure/controller-session-store.ts +804 -0
- package/packages/kernel/controller/ports/controller-host.ts +18 -0
- package/packages/kernel/goal/api/index.ts +1 -0
- package/packages/kernel/goal/domain/types.ts +40 -0
- package/packages/kernel/goal/index.ts +1 -0
- package/packages/kernel/identity/api/index.ts +15 -0
- package/packages/kernel/identity/application/identity-service.ts +67 -0
- package/packages/kernel/identity/domain/activity-projection.ts +43 -0
- package/packages/kernel/identity/domain/capability-broker.ts +60 -0
- package/packages/kernel/identity/domain/grant.ts +72 -0
- package/packages/kernel/identity/domain/owned-resource.ts +116 -0
- package/packages/kernel/identity/domain/scope.ts +63 -0
- package/packages/kernel/identity/domain/semantic-sync.ts +81 -0
- package/packages/kernel/identity/domain/types.ts +44 -0
- package/packages/kernel/identity/domain/user-request.ts +93 -0
- package/packages/kernel/identity/domain/workspace.ts +56 -0
- package/packages/kernel/identity/index.ts +1 -0
- package/packages/kernel/identity/infrastructure/activity-projection-store.ts +77 -0
- package/packages/kernel/identity/infrastructure/capability-broker.ts +81 -0
- package/packages/kernel/identity/infrastructure/grant-store.ts +284 -0
- package/packages/kernel/identity/infrastructure/identity-store.ts +75 -0
- package/packages/kernel/identity/infrastructure/owned-resource-store.ts +259 -0
- package/packages/kernel/identity/infrastructure/user-request-store.ts +182 -0
- package/packages/kernel/memory/api/index.ts +5 -0
- package/packages/kernel/memory/application/experience-service.ts +118 -0
- package/packages/kernel/memory/application/outcome-service.ts +77 -0
- package/packages/kernel/memory/domain/experience.ts +103 -0
- package/packages/kernel/memory/domain/operational-prior.ts +92 -0
- package/packages/kernel/memory/index.ts +1 -0
- package/packages/kernel/scheduler/api/index.ts +4 -0
- package/packages/kernel/scheduler/application/eligibility.ts +252 -0
- package/packages/kernel/scheduler/application/schedule-service.ts +27 -0
- package/packages/kernel/scheduler/application/settlement.ts +182 -0
- package/packages/kernel/scheduler/domain/schedule.ts +236 -0
- package/packages/kernel/scheduler/index.ts +1 -0
- package/packages/kernel/scheduler/infrastructure/schedule-store.ts +805 -0
- package/packages/kernel/work/api/index.ts +16 -0
- package/packages/kernel/work/application/work-service.ts +123 -0
- package/packages/kernel/work/domain/check-receipt.ts +43 -0
- package/packages/kernel/work/domain/context-closure-receipt.ts +32 -0
- package/packages/kernel/work/domain/current-task-lineage.ts +104 -0
- package/packages/kernel/work/domain/engineering-contracts.ts +157 -0
- package/packages/kernel/work/domain/engineering-design.ts +286 -0
- package/packages/kernel/work/domain/engineering-profile.ts +238 -0
- package/packages/kernel/work/domain/evaluation-promotion-receipt.ts +186 -0
- package/packages/kernel/work/domain/execution-concurrency.ts +247 -0
- package/packages/kernel/work/domain/execution-snapshot.ts +2 -0
- package/packages/kernel/work/domain/implementation-review.ts +193 -0
- package/packages/kernel/work/domain/objective-graph.ts +119 -0
- package/packages/kernel/work/domain/project-engineering-contract.ts +224 -0
- package/packages/kernel/work/domain/repository-completion-receipt.ts +73 -0
- package/{src/runtime/control-plane/facade/work-state-machine.ts → packages/kernel/work/domain/state-machine.ts} +37 -66
- package/packages/kernel/work/domain/types.ts +534 -0
- package/packages/kernel/work/index.ts +1 -0
- package/packages/kernel/work/infrastructure/work-contract-store.ts +1967 -0
- package/packages/kernel/work/ports/work-contract-store.ts +21 -0
- package/packages/plugin-runtime/browser/index.ts +3 -0
- package/packages/plugin-runtime/browser/provider-registry.ts +110 -0
- package/packages/plugin-runtime/browser/runtime-contract.ts +150 -0
- package/packages/plugin-runtime/browser/session-authority.ts +62 -0
- package/packages/plugin-runtime/computer/chatgpt-identity.ts +24 -0
- package/packages/plugin-runtime/computer/conversation-target.ts +143 -0
- package/packages/plugin-runtime/computer/index.ts +8 -0
- package/packages/plugin-runtime/computer/provider-error.ts +26 -0
- package/packages/plugin-runtime/computer/provider-registration.ts +52 -0
- package/packages/plugin-runtime/computer/provider-registry.ts +63 -0
- package/packages/plugin-runtime/computer/provider.ts +19 -0
- package/packages/plugin-runtime/computer/target-authority.ts +215 -0
- package/packages/plugin-runtime/computer/target-persistence.ts +54 -0
- package/packages/plugin-runtime/external/index.ts +1 -0
- package/packages/plugin-runtime/external/unix-jsonl-transport.ts +581 -0
- package/packages/plugin-runtime/index.ts +3 -0
- package/packages/protocols/browser/index.ts +1 -0
- package/packages/protocols/browser/session.ts +98 -0
- package/packages/protocols/computer/contract.ts +225 -0
- package/packages/protocols/computer/index.ts +1 -0
- package/packages/protocols/failure/contract.ts +158 -0
- package/packages/protocols/failure/index.ts +1 -0
- package/packages/protocols/handoff/index.ts +1 -0
- package/packages/protocols/handoff/status.ts +22 -0
- package/packages/protocols/mcp/execution-context.ts +11 -0
- package/packages/protocols/mcp/index.ts +2 -0
- package/packages/protocols/mcp/tool-contract.ts +42 -0
- package/packages/workflow-runtime/api/index.ts +2 -0
- package/packages/workflow-runtime/application/interpreter.ts +342 -0
- package/packages/workflow-runtime/domain/workflow-asset.ts +223 -0
- package/packages/workflow-runtime/index.ts +1 -0
- package/scripts/activate-source-baseline.ts +7 -9
- package/scripts/assemble-template.ts +1 -1
- package/scripts/bootstrap-runtime-maintenance-recovery.sh +4 -1
- package/scripts/canary-chatgpt-provider-delivery.ts +97 -0
- package/scripts/canary-controller-semantic-wait.ts +183 -0
- package/scripts/canary-global-hook.sh +2 -2
- package/scripts/check-mcp-compatibility.ts +85 -7
- package/scripts/check-platform-support.mjs +28 -2
- package/scripts/check-public-docs.sh +1 -1
- package/scripts/check-repository-hygiene.mjs +92 -0
- package/scripts/check-runtime-architecture.mjs +1643 -127
- package/scripts/check-source-duplication.mjs +9 -1
- package/scripts/controller-ngrok-rotation.sh +5 -4
- package/scripts/create-project-dirs.sh +10 -74
- package/scripts/forge-local-recovery-helper.mjs +282 -0
- package/scripts/forge-uu-remote-rescue-helper.d.mts +31 -0
- package/scripts/forge-uu-remote-rescue-helper.mjs +409 -0
- package/scripts/forge-windows-host-recovery-helper.mjs +136 -0
- package/scripts/hook-shim.sh +2 -2
- package/scripts/init-project.sh +12 -70
- package/scripts/install-desktop-operator-registration.ts +4 -2
- package/scripts/install-independent-windows-wsl-recovery.ts +125 -0
- package/scripts/install-standalone-recovery.ts +122 -10
- package/scripts/install-uu-remote-rescue-registration.ts +74 -0
- package/scripts/install-windows-host-recovery-registration.ts +22 -0
- package/scripts/lib/controller-home-env.sh +6 -3
- package/scripts/lib/project-init-lib.sh +42 -582
- package/scripts/migrate-chatgpt-automation-schedules.ts +2 -2
- package/scripts/migrate-windows-wsl-controller-home.ts +306 -0
- package/scripts/open-source-audit-allowlist.txt +11 -1
- package/scripts/portability-bindings.mjs +70 -0
- package/scripts/run-bounded-command.mjs +60 -0
- package/scripts/run-bun-test-file.ts +22 -6
- package/scripts/run-governed-gate.ts +4 -2
- package/scripts/run-mobile-monitor-bridge.ts +0 -1
- package/scripts/smoke-control-plane-failure-domain.ts +94 -0
- package/scripts/smoke-mcp-http-runtime.ts +6 -1
- package/scripts/smoke-runtime-recovery.ts +13 -11
- package/scripts/smoke-schedule-engine.ts +24 -16
- package/scripts/smoke-unattended-transport-recovery.ts +223 -0
- package/scripts/smoke-user-request-continuation-restart.ts +232 -0
- package/scripts/smoke-workflow-supervisor-chrome-adapter.ts +92 -0
- package/scripts/smoke-workflow-supervisor-process-restart.ts +276 -0
- package/scripts/smoke-workflow-supervisor-restart-recovery.ts +150 -0
- package/scripts/smoke-workflow-supervisor.ts +103 -0
- package/scripts/test-governance.ts +51 -2
- package/scripts/verify-forge-runtime.sh +2 -1
- package/src/cli/agent-jobs/executor-health.ts +11 -34
- package/src/cli/agent-jobs/integration.ts +18 -49
- package/src/cli/agent-jobs/job-manager.ts +17 -4
- package/src/cli/chatgpt-browser/bind-server.ts +2 -1
- package/src/cli/chatgpt-browser/binding.ts +20 -10
- package/src/cli/chatgpt-browser/bridge-extension.ts +75 -0
- package/src/cli/chatgpt-browser/bridge-provider.ts +376 -11
- package/src/cli/chatgpt-browser/engine.ts +10 -11
- package/src/cli/chatgpt-browser/native-provider.ts +24 -83
- package/src/cli/chatgpt-browser/oracle-provider.ts +5 -3
- package/src/cli/chatgpt-browser/types.ts +1 -0
- package/src/cli/commands/bootstrap-control.ts +334 -0
- package/src/cli/commands/brain-assistant.ts +52 -0
- package/src/cli/commands/brain.ts +191 -40
- package/src/cli/commands/chatgpt.ts +32 -67
- package/src/cli/commands/computer.ts +437 -0
- package/src/cli/commands/doctor.ts +18 -1
- package/src/cli/commands/init-hook.ts +71 -61
- package/src/cli/commands/init.ts +3 -1
- package/src/cli/commands/mcp.ts +16 -10
- package/src/cli/commands/plugin.ts +38 -12
- package/src/cli/commands/recovery.ts +507 -80
- package/src/cli/commands/runtime.ts +12 -7
- package/src/cli/commands/setup-profile.ts +97 -39
- package/src/cli/commands/status.ts +2 -1
- package/src/cli/controller/check-runner.ts +500 -100
- package/src/cli/controller/completion-backlog.ts +3 -3
- package/src/cli/controller/completion-orchestrator.ts +4 -43
- package/src/cli/controller/completion-target.ts +3 -72
- package/src/cli/controller/context/source-materializer.ts +81 -100
- package/src/cli/controller/context/types.ts +7 -1
- package/src/cli/controller/context-pack.ts +28 -6
- package/src/cli/controller/execution-completion.ts +4 -7
- package/src/cli/controller/execution-policy.ts +36 -153
- package/src/cli/controller/governance.ts +2 -3
- package/src/cli/controller/issue-store.ts +4 -99
- package/src/cli/controller/launch-agents.ts +59 -18
- package/src/cli/controller/operational-plan.ts +24 -51
- package/src/cli/controller/runtime-config.ts +5 -1
- package/src/cli/controller/stuck-state-migration.ts +2 -3
- package/src/cli/controller/systemd-user.ts +148 -0
- package/src/cli/controller/types.ts +10 -70
- package/src/cli/controller/worklog.ts +67 -13
- package/src/cli/editing/edit-operation-contract.ts +92 -0
- package/src/cli/editing/edit-session.ts +290 -20
- package/src/cli/github/plugin.ts +17 -12
- package/src/cli/hook/route-registry.ts +3 -5
- package/src/cli/hook/runtime.ts +49 -3
- package/src/cli/index.ts +3 -0
- package/src/cli/local-bridge/connector-freshness.ts +2 -2
- package/src/cli/local-bridge/console-automations.ts +20 -15
- package/src/cli/local-bridge/console-view-models.ts +3 -12
- package/src/cli/local-bridge/facade-api.ts +105 -205
- package/src/cli/local-bridge/job-store.ts +1 -1
- package/src/cli/local-bridge/server.ts +48 -174
- package/src/cli/local-bridge/types.ts +0 -1
- package/src/cli/mcp/access-mode.ts +2 -132
- package/src/cli/mcp/access-tools.ts +2 -387
- package/src/cli/mcp/audit.ts +2 -32
- package/src/cli/mcp/auth.ts +2 -404
- package/src/cli/mcp/instructions.ts +2 -34
- package/src/cli/mcp/legacy-context.ts +2 -16
- package/src/cli/mcp/legacy-tool-service.ts +2 -5308
- package/src/cli/mcp/multi-repository.ts +2 -436
- package/src/cli/mcp/oauth-client-retirement.ts +74 -0
- package/src/cli/mcp/oauth.ts +2 -375
- package/src/cli/mcp/openai-secure-tunnel.ts +2 -0
- package/src/cli/mcp/paths.ts +2 -140
- package/src/cli/mcp/policy.ts +2 -232
- package/src/cli/mcp/post-finalize-work-attribution.ts +2 -150
- package/src/cli/mcp/proxy-env.ts +2 -62
- package/src/cli/mcp/readiness-projection.ts +2 -24
- package/src/cli/mcp/redaction.ts +2 -21
- package/src/cli/mcp/repo.ts +2 -24
- package/src/cli/mcp/repository-tools.ts +2 -1613
- package/src/cli/mcp/server.ts +2 -951
- package/src/cli/mcp/setup.ts +2 -737
- package/src/cli/mcp/tool-capability-cache.ts +2 -87
- package/src/cli/mcp/tool-contract.ts +2 -14
- package/src/cli/mcp/tools.ts +2 -9
- package/src/cli/mcp/toolset-names.ts +2 -70
- package/src/cli/mcp/toolset-selection.ts +2 -41
- package/src/cli/mcp/toolset.ts +2 -336
- package/src/cli/mcp/transports/AGENTS.md +1 -10
- package/src/cli/mcp/transports/CLAUDE.md +1 -10
- package/src/cli/mcp/transports/http.ts +2 -1414
- package/src/cli/mcp/transports/session-registry.ts +2 -490
- package/src/cli/mcp/transports/stdio.ts +2 -8
- package/src/cli/mcp/types.ts +2 -41
- package/src/cli/mcp/umbrella-tools.ts +2 -117
- package/src/cli/repositories/command-executor.ts +91 -39
- package/src/cli/repositories/command-scope.ts +139 -4
- package/src/cli/repositories/controller-home.ts +167 -1
- package/src/cli/repositories/ephemeral-workspace.ts +20 -30
- package/src/cli/repositories/git-command-executor.ts +2 -2
- package/src/cli/repositories/identity.ts +13 -0
- package/src/cli/repositories/registry.ts +145 -60
- package/src/cli/repositories/repository-snapshot.ts +53 -7
- package/src/cli/repositories/runtime-storage.ts +27 -2
- package/src/cli/repositories/safe-patch.ts +34 -38
- package/src/cli/repositories/selected-path-actions.ts +22 -2
- package/src/cli/repositories/structured-git.ts +167 -27
- package/src/cli/repository/session-cache.ts +92 -6
- package/src/cli/runtime/helper-runner.ts +7 -0
- package/src/cli/runtime-invocation.ts +8 -1
- package/src/cli/tools/codegraph.ts +44 -25
- package/src/core/adoption/manifest-templates.ts +1 -1
- package/src/core/adoption/plan.ts +3 -26
- package/src/core/adoption/workflow-contract-plan.ts +17 -9
- package/src/effects/process-runner.ts +8 -14
- package/src/runtime/context/assistant-context.ts +167 -0
- package/src/runtime/context/assistant-work-context.ts +209 -0
- package/src/runtime/context/automatic-learning.ts +565 -0
- package/src/runtime/context/codegraph-cache-boundary.ts +255 -0
- package/src/runtime/context/codegraph-read-provider.ts +55 -22
- package/src/runtime/context/codegraph-sidecar.cjs +8 -1
- package/src/runtime/context/cognitive-attention.ts +173 -0
- package/src/runtime/context/cognitive-skill-canary.ts +158 -0
- package/src/runtime/context/context-closure.ts +305 -0
- package/src/runtime/context/context-pack-process.ts +103 -0
- package/src/runtime/context/context-plane.ts +203 -0
- package/src/runtime/context/direct-controller-learning.ts +298 -0
- package/src/runtime/context/project-engineering-contract.ts +60 -0
- package/src/runtime/context/semantic-navigation-contract.ts +9 -0
- package/src/runtime/context/semantic-navigation.ts +6 -34
- package/src/runtime/context/typescript-navigation-process.ts +145 -0
- package/src/runtime/context/typescript-navigation.ts +89 -3
- package/src/runtime/control-plane/bootstrap/capability-provider.ts +74 -0
- package/src/runtime/control-plane/bootstrap/control-api.ts +57 -0
- package/src/runtime/control-plane/bootstrap/index.ts +5 -0
- package/src/runtime/control-plane/bootstrap/state-machine.ts +141 -0
- package/src/runtime/control-plane/bootstrap/store.ts +21 -0
- package/src/runtime/control-plane/bootstrap/types.ts +87 -0
- package/src/runtime/control-plane/cleanup-artifact-retention.ts +531 -0
- package/src/runtime/control-plane/codegraph-cache-retention.ts +164 -0
- package/src/runtime/control-plane/concurrency/work-execution-concurrency.ts +282 -0
- package/src/runtime/control-plane/execution/controller-authority-recovery.ts +380 -0
- package/src/runtime/control-plane/execution/edit-validation-coordinator.ts +113 -16
- package/src/runtime/control-plane/execution/execution-identity.ts +23 -3
- package/src/runtime/control-plane/execution/implementation-review-content.ts +95 -0
- package/src/runtime/control-plane/execution/repository-work-attribution.ts +7 -30
- package/src/runtime/control-plane/execution/retained-work-resume.ts +439 -102
- package/src/runtime/control-plane/execution/session-store.ts +31 -1
- package/src/runtime/control-plane/execution/validation.ts +34 -11
- package/src/runtime/control-plane/execution/work-authority-reconciler.ts +87 -0
- package/src/runtime/control-plane/execution/work-check-evidence.ts +137 -0
- package/src/runtime/control-plane/execution/work-completion-authority.ts +31 -44
- package/src/runtime/control-plane/execution/work-delivery-service.ts +497 -0
- package/src/runtime/control-plane/execution/work-evidence-policy.ts +46 -53
- package/src/runtime/control-plane/execution/work-execution-support.ts +85 -164
- package/src/runtime/control-plane/execution/work-handle-authority.ts +349 -73
- package/src/runtime/control-plane/execution/work-handle-store.ts +55 -2
- package/src/runtime/control-plane/execution/work-head-settlement.ts +108 -0
- package/src/runtime/control-plane/execution/work-lifecycle-audit.ts +173 -28
- package/src/runtime/control-plane/execution/work-operation-service.ts +92 -40
- package/src/runtime/control-plane/execution/work-preparation-service.ts +145 -269
- package/src/runtime/control-plane/execution/work-remote-delivery.ts +2 -3
- package/src/runtime/control-plane/execution/work-revision-diff.ts +39 -0
- package/src/runtime/control-plane/execution/work-terminal-cleanup.ts +543 -225
- package/src/runtime/control-plane/execution/work-validation-reconciler.ts +59 -45
- package/src/runtime/control-plane/execution/work-verification-context.ts +1 -1
- package/src/runtime/control-plane/execution/work-verification-service.ts +662 -52
- package/src/runtime/control-plane/execution/work-verification-snapshot.ts +205 -16
- package/src/runtime/control-plane/facade/capability-registry.ts +380 -44
- package/src/runtime/control-plane/facade/check-normalization.ts +3 -9
- package/src/runtime/control-plane/facade/codex-delegation.ts +10 -11
- package/src/runtime/control-plane/facade/controller-connection.ts +135 -0
- package/src/runtime/control-plane/facade/controller-session-store.ts +2 -488
- package/src/runtime/control-plane/facade/goal-workloop-access.ts +6 -22
- package/src/runtime/control-plane/facade/goal-workloop.ts +565 -1202
- package/src/runtime/control-plane/facade/handoff-inbox-application.ts +145 -0
- package/src/runtime/control-plane/facade/handoff-inbox-store.ts +266 -52
- package/src/runtime/control-plane/facade/index.ts +4 -3
- package/src/runtime/control-plane/facade/operation-digest.ts +34 -73
- package/src/runtime/control-plane/facade/plan-contract-store.ts +671 -245
- package/src/runtime/control-plane/facade/policy-gate.ts +0 -23
- package/src/runtime/control-plane/facade/repository-work-admission.ts +31 -23
- package/src/runtime/control-plane/facade/requirement-authority.ts +121 -0
- package/src/runtime/control-plane/facade/requirement-board.ts +9 -4
- package/src/runtime/control-plane/facade/rh-work-operation-contract.ts +85 -0
- package/src/runtime/control-plane/facade/self-healing-loop.ts +18 -53
- package/src/runtime/control-plane/facade/semantic-admission.ts +8 -16
- package/src/runtime/control-plane/facade/suggested-actions.ts +15 -15
- package/src/runtime/control-plane/facade/types.ts +218 -620
- package/src/runtime/control-plane/facade/work-continuation.ts +8 -8
- package/src/runtime/control-plane/facade/work-contract-store.ts +2 -1043
- package/src/runtime/control-plane/generated-cache-retention.ts +336 -19
- package/src/runtime/control-plane/global-scheduler/autonomous-continuation.ts +248 -0
- package/src/runtime/control-plane/global-scheduler/durable-admission.ts +13 -2
- package/src/runtime/control-plane/global-scheduler/maintenance.ts +274 -84
- package/src/runtime/control-plane/global-scheduler/periodic-cleanup-entry.ts +55 -0
- package/src/runtime/control-plane/global-scheduler/periodic-cleanup-process.ts +98 -0
- package/src/runtime/control-plane/global-scheduler/reconciliation.ts +3 -2
- package/src/runtime/control-plane/global-scheduler/scheduler-worker-entry.ts +10 -0
- package/src/runtime/control-plane/global-scheduler/scheduler.ts +227 -109
- package/src/runtime/control-plane/global-scheduler/wake-signal.ts +42 -2
- package/src/runtime/control-plane/global-scheduler/worker-launch.ts +18 -6
- package/src/runtime/control-plane/governance/access-policy.ts +19 -2
- package/src/runtime/control-plane/governance/authorization.ts +20 -3
- package/src/runtime/control-plane/launcher/chatgpt-round-continuation.ts +160 -0
- package/src/runtime/control-plane/launcher/chatgpt-work-binding-store.ts +2 -177
- package/src/runtime/control-plane/launcher/chatgpt-work-continuation.ts +139 -670
- package/src/runtime/control-plane/launcher/local-conversation-controller.ts +238 -0
- package/src/runtime/control-plane/launcher/provider-mcp-bootstrap.ts +25 -6
- package/src/runtime/control-plane/launcher/thin-launcher.ts +96 -194
- package/src/runtime/control-plane/lifecycle-retention-metrics.ts +60 -0
- package/src/runtime/control-plane/persistence/cognition-store.ts +820 -0
- package/src/runtime/control-plane/persistence/experience-store.ts +302 -0
- package/src/runtime/control-plane/persistence/operational-prior-store.ts +348 -0
- package/src/runtime/control-plane/persistence/requirement-store.ts +230 -80
- package/src/runtime/control-plane/persistence/sqlite-store.ts +654 -78
- package/src/runtime/control-plane/persistence/workflow-content-store.ts +98 -0
- package/src/runtime/control-plane/persistence/workflow-registry-store.ts +186 -0
- package/src/runtime/control-plane/persistence/workflow-run-store.ts +123 -0
- package/src/runtime/control-plane/release-retention.ts +154 -26
- package/src/runtime/control-plane/repository-namespace-retention.ts +208 -0
- package/src/runtime/control-plane/runtime-cleanup.ts +844 -38
- package/src/runtime/control-plane/runtime-generation.ts +6 -0
- package/src/runtime/control-plane/workspace/project-onboarding.ts +80 -0
- package/src/runtime/control-plane/workspace/semantic-sync-service.ts +479 -0
- package/src/runtime/control-plane/workspace/workspace-store.ts +249 -0
- package/src/runtime/diagnostics/incident-repair.ts +573 -0
- package/src/runtime/diagnostics/mcp-timing.ts +239 -6
- package/src/runtime/diagnostics/performance.ts +6 -14
- package/src/runtime/diagnostics/read-only-tool.ts +1 -1
- package/src/runtime/evidence/artifact-store.ts +216 -35
- package/src/runtime/evidence/evidence-store.ts +112 -8
- package/src/runtime/evidence/operational-shadow.ts +38 -0
- package/src/runtime/evidence/output-handle-index.ts +225 -0
- package/src/runtime/evidence/process-check-receipt.ts +5 -43
- package/src/runtime/evidence/result-store.ts +158 -44
- package/src/runtime/evidence/sensitive-output.ts +4 -4
- package/src/runtime/execution/jobs/receipt-recovery.ts +1 -1
- package/src/runtime/execution/jobs/store.ts +124 -6
- package/src/runtime/execution/managed-workspace.ts +112 -5
- package/src/runtime/execution/process-runtime/canary.ts +19 -5
- package/src/runtime/execution/process-runtime/check-classification.ts +48 -0
- package/src/runtime/execution/process-runtime/check-facade.ts +24 -10
- package/src/runtime/execution/process-runtime/check-receipt.ts +1 -1
- package/src/runtime/execution/process-runtime/check-result-retention.ts +132 -0
- package/src/runtime/execution/process-runtime/check-result.ts +177 -2
- package/src/runtime/execution/process-runtime/check-runner-sidecar.ts +58 -9
- package/src/runtime/execution/process-runtime/check-storage.ts +187 -0
- package/src/runtime/execution/process-runtime/command-facade.ts +117 -114
- package/src/runtime/execution/process-runtime/gc.ts +15 -2
- package/src/runtime/execution/process-runtime/handle-index.ts +176 -0
- package/src/runtime/execution/process-runtime/host-command-lane.ts +139 -0
- package/src/runtime/execution/process-runtime/index.ts +4 -0
- package/src/runtime/execution/process-runtime/interactive-admission.ts +2 -1
- package/src/runtime/execution/process-runtime/lightweight-managed.ts +283 -73
- package/src/runtime/execution/process-runtime/persisted-check.ts +130 -23
- package/src/runtime/execution/process-runtime/process-runner-entry.ts +47 -5
- package/src/runtime/execution/process-runtime/process-scope.ts +160 -0
- package/src/runtime/execution/process-runtime/resource-claims.ts +125 -64
- package/src/runtime/execution/process-runtime/runtime.ts +167 -17
- package/src/runtime/execution/process-runtime/store.ts +30 -2
- package/src/runtime/execution/process-runtime/types.ts +27 -0
- package/src/runtime/execution/workers/executor.ts +18 -19
- package/src/runtime/execution/workers/worker-entry.ts +1 -1
- package/src/runtime/gateway/mcp/execution-tools.ts +2 -207
- package/src/runtime/gateway/mcp/legacy-ios-tool-adapter.ts +2 -61
- package/src/runtime/gateway/mcp/persisted-check-process.ts +2 -3
- package/src/runtime/gateway/mcp/process-tools.ts +2 -289
- package/src/runtime/gateway/mcp/router.ts +2 -1125
- package/src/runtime/gateway/mcp/runtime-tool-definitions.ts +2 -565
- package/src/runtime/gateway/mcp/runtime-tools.ts +2 -6655
- package/src/runtime/gateway/mcp/work-validation-reconciler.ts +2 -1
- package/src/runtime/maintenance/cleanup.ts +38 -24
- package/src/runtime/platform/browser-product-discovery.ts +174 -0
- package/src/runtime/platform/computer-platform.ts +14 -0
- package/src/runtime/platform/executable-discovery.ts +54 -0
- package/src/runtime/platform/fetch-http-server.ts +90 -0
- package/src/runtime/platform/service-inventory.ts +130 -0
- package/src/runtime/platform/service-manager.ts +146 -0
- package/src/runtime/platform/windows-host-discovery.ts +118 -0
- package/src/runtime/platform/windows-recovery-deployment.ts +67 -0
- package/src/runtime/plugins/action-application.ts +192 -0
- package/src/runtime/plugins/app-store-connect-adapter.ts +47 -35
- package/src/runtime/plugins/browser-adapter.ts +898 -135
- package/src/runtime/plugins/browser-automation-service.ts +33 -34
- package/src/runtime/plugins/browser-macos-bridge.ts +386 -46
- package/src/runtime/plugins/browser-manifest-surface.ts +75 -17
- package/src/runtime/plugins/browser-native-session-service.ts +64 -14
- package/src/runtime/plugins/browser-provider-registry.ts +2 -109
- package/src/runtime/plugins/browser-registration.ts +32 -0
- package/src/runtime/plugins/browser-runtime-contract.ts +2 -154
- package/src/runtime/plugins/browser-runtime.ts +55 -10
- package/src/runtime/plugins/browser-session-authority.ts +101 -291
- package/src/runtime/plugins/browser-session-legacy-migration.ts +203 -0
- package/src/runtime/plugins/browser-session-store.ts +243 -80
- package/src/runtime/plugins/browser-session-types.ts +2 -98
- package/src/runtime/plugins/capability-authorization-grants.ts +272 -59
- package/src/runtime/plugins/catalog-trust.ts +82 -0
- package/src/runtime/plugins/computer-chatgpt-browser-adapter-installer.ts +219 -0
- package/src/runtime/plugins/computer-chatgpt-macos-target.ts +891 -0
- package/src/runtime/plugins/computer-registration.ts +1050 -0
- package/src/runtime/plugins/config-store.ts +119 -0
- package/src/runtime/plugins/desktop-operator-external-policy.ts +964 -0
- package/src/runtime/plugins/desktop-operator-registration.ts +123 -12
- package/src/runtime/plugins/errors.ts +8 -1
- package/src/runtime/plugins/external-adapter.ts +82 -323
- package/src/runtime/plugins/external-provider-policy.ts +48 -0
- package/src/runtime/plugins/external-registration.ts +30 -2
- package/src/runtime/plugins/external-unix-socket-probe.cjs +9 -3
- package/src/runtime/plugins/external-unix-socket.ts +64 -193
- package/src/runtime/plugins/first-party-external-registration.ts +163 -0
- package/src/runtime/plugins/first-party-registry.ts +3 -1
- package/src/runtime/plugins/github-adapter.ts +1 -2
- package/src/runtime/plugins/gmail-adapter.ts +29 -8
- package/src/runtime/plugins/google-calendar-adapter.ts +8 -8
- package/src/runtime/plugins/google-shared.ts +45 -53
- package/src/runtime/plugins/google-tasks-adapter.ts +8 -8
- package/src/runtime/plugins/ios-adapter.ts +2 -3
- package/src/runtime/plugins/lightweight-action.ts +208 -2
- package/src/runtime/plugins/local-system-adapter.ts +192 -2
- package/src/runtime/plugins/macos-capability-broker.ts +15 -105
- package/src/runtime/plugins/managed-process-adapter.ts +12 -5
- package/src/runtime/plugins/plugin-action-sidecar.ts +17 -13
- package/src/runtime/plugins/plugin-management-adapter.ts +1 -1
- package/src/runtime/plugins/resend-adapter.ts +15 -24
- package/src/runtime/plugins/store.ts +1003 -387
- package/src/runtime/plugins/types.ts +28 -1
- package/src/runtime/plugins/uu-remote-rescue-registration.ts +155 -0
- package/src/runtime/plugins/windows-host-recovery-install.ts +68 -0
- package/src/runtime/plugins/windows-host-recovery-registration.ts +85 -0
- package/src/runtime/plugins/xiaohongshu-publish.ts +102 -430
- package/src/runtime/projections/controller-context.ts +12 -6
- package/src/runtime/projections/git-status-sampler.ts +73 -22
- package/src/runtime/projections/invalidation.ts +7 -3
- package/src/runtime/projections/materialized-view.ts +93 -43
- package/src/runtime/recovery/actions.ts +3 -3
- package/src/runtime/recovery/capability-action-application.ts +229 -0
- package/src/runtime/recovery/index.ts +3 -0
- package/src/runtime/recovery/lifecycle-inventory.ts +338 -0
- package/src/runtime/recovery/local-jobs-repair.ts +14 -14
- package/src/runtime/recovery/maintenance-executor.ts +701 -168
- package/src/runtime/recovery/quarantine-retention.ts +256 -0
- package/src/runtime/recovery/store.ts +29 -11
- package/src/runtime/release/identity.ts +6 -0
- package/src/runtime/release/release-coordinator.ts +296 -0
- package/src/runtime/release/release-session.ts +716 -0
- package/src/runtime/release/release-state-migration.ts +25 -0
- package/src/runtime/resources/leases/store.ts +56 -25
- package/src/runtime/root/active-execution-power-assertion.ts +139 -0
- package/src/runtime/root/assistant-learning-loop.ts +45 -0
- package/src/runtime/root/browser-session-composition.ts +59 -0
- package/src/runtime/root/computer-composition.ts +376 -0
- package/src/runtime/root/computer-target-composition.ts +16 -0
- package/src/runtime/root/computer-target-persistence.ts +39 -0
- package/src/runtime/root/controller-progression-composition.ts +192 -0
- package/src/runtime/root/controller-round-composition.ts +126 -0
- package/src/runtime/root/controller-services.ts +2 -0
- package/src/runtime/root/deployment-topology.ts +106 -0
- package/src/runtime/root/entry.ts +8 -6
- package/src/runtime/root/gateway-adapter.ts +3 -3
- package/src/runtime/root/known-good-recovery.ts +184 -0
- package/src/runtime/root/local-bridge.ts +5 -3
- package/src/runtime/root/mcp-transport.ts +116 -23
- package/src/runtime/root/ownership.ts +261 -9
- package/src/runtime/root/package-connector-service.ts +212 -74
- package/src/runtime/root/package-runtime-release.ts +199 -33
- package/src/runtime/root/package-runtime-service.ts +77 -108
- package/src/runtime/root/release-execution-canary.ts +103 -0
- package/src/runtime/root/release-loader.ts +150 -0
- package/src/runtime/root/release-manifest.ts +185 -7
- package/src/runtime/root/release-materialize.ts +474 -31
- package/src/runtime/root/release-store.ts +425 -37
- package/src/runtime/root/runtime-lane.ts +191 -0
- package/src/runtime/root/runtime.ts +379 -32
- package/src/runtime/root/scheduled-controller-composition.ts +76 -0
- package/src/runtime/root/scheduler.ts +12 -4
- package/src/runtime/root/service-runner.ts +3 -3
- package/src/runtime/root/service.ts +73 -45
- package/src/runtime/root/status.ts +49 -0
- package/src/runtime/root/types.ts +55 -3
- package/src/runtime/root/workflow-supervisor-composition.ts +493 -0
- package/src/runtime/root/workflow-supervisor-runtime.ts +209 -0
- package/src/runtime/root/write-fence.ts +50 -2
- package/src/runtime/safe-tooling/google-credential-store.ts +76 -21
- package/src/runtime/safe-tooling/google-oauth-broker.ts +25 -7
- package/src/runtime/safe-tooling/workspace-auth.ts +1 -1
- package/src/runtime/shared/bounded-child-supervisor.ts +9 -1
- package/src/runtime/shared/local-bridge-surface.ts +1 -1
- package/src/runtime/shared/process-environment.ts +36 -10
- package/src/runtime/shared/response-budget.ts +1 -3
- package/src/runtime/shared/storage-capacity.ts +68 -0
- package/src/runtime/standalone-recovery/controller-home-migration.ts +1108 -0
- package/src/runtime/standalone-recovery/core.ts +4609 -495
- package/src/runtime/standalone-recovery/entry.ts +642 -81
- package/src/runtime/standalone-recovery/independent-host-rescue.ts +172 -0
- package/src/runtime/standalone-recovery/installer.ts +399 -177
- package/src/runtime/standalone-recovery/mcp-server.ts +79 -0
- package/src/runtime/standalone-recovery/mutation-identity-contract.ts +21 -0
- package/src/runtime/standalone-recovery/operation-lock.ts +160 -0
- package/src/runtime/standalone-recovery/performance.ts +173 -0
- package/src/runtime/standalone-recovery/release.ts +58 -5
- package/src/runtime/standalone-recovery/service-labels.ts +5 -2
- package/src/runtime/standalone-recovery/watchdog-heartbeat.ts +5 -2
- package/src/runtime/watchdog/workflow-watchdog.ts +1 -1
- package/src/runtime/workflow/schedules/browser-probe.ts +17 -6
- package/src/runtime/workflow/schedules/chatgpt-automation-migration.ts +11 -4
- package/src/runtime/workflow/schedules/engine.ts +298 -484
- package/src/runtime/workflow/schedules/pending-activation.ts +1 -1
- package/src/runtime/workflow/schedules/settlement.ts +2 -191
- package/src/runtime/workflow/schedules/store.ts +2 -607
- package/src/runtime/workflow/schedules/types.ts +2 -127
- package/src/runtime/workflow/schedules/work-continuation.ts +220 -16
- package/src/runtime/workflows/first-party/xiaohongshu.ts +122 -0
- package/src/runtime/workflows/runtime.ts +482 -0
- package/src/testing/test-governance.ts +95 -30
- package/supervisor/chatgpt-conversation.ts +23 -0
- package/supervisor/client.ts +201 -0
- package/supervisor/control-plane.ts +868 -0
- package/supervisor/entry.ts +15 -0
- package/supervisor/forge-validators.ts +80 -0
- package/supervisor/index.ts +5 -0
- package/supervisor/native-browser-adapter.ts +786 -0
- package/supervisor/native-messaging/host.ts +39 -0
- package/supervisor/native-messaging/manifest.ts +26 -0
- package/supervisor/native-messaging/protocol.ts +27 -0
- package/supervisor/paths.ts +18 -0
- package/supervisor/protocol.ts +202 -0
- package/supervisor/server.ts +404 -0
- package/supervisor/store.ts +1451 -0
- package/supervisor/tsconfig.json +8 -0
- package/supervisor/types.ts +255 -0
- package/assets/templates/helpers/archive-architecture-request.sh +0 -244
- package/docs/architecture/history/README.md +0 -7
- package/docs/architecture/history/chatgpt-handoff-facade.md +0 -397
- package/docs/architecture/history/global-hook-runtime.md +0 -166
- package/docs/architecture/history/ios-semantic-automation-provider-v2.md +0 -170
- package/docs/architecture/requests/archive/2026/20260528-154740-ai-hooks-ai-hooks-hook-input-sh.md +0 -59
- package/docs/architecture/requests/archive/2026/20260528-154816-assets-hooks-assets-hooks-hook-input-sh.md +0 -59
- package/docs/architecture/requests/archive/2026/20260528-161851-ai-harness-workflow-contract-json-ai-harness-workflow-contract-json.md +0 -59
- package/docs/architecture/requests/archive/2026/20260528-161853-scripts-check-task-workflow-sh-scripts-check-task-workflow-sh.md +0 -59
- package/docs/architecture/requests/archive/2026/20260528-161911-assets-workflow-contract-v1-json-assets-workflow-contract-v1-json.md +0 -59
- package/docs/architecture/requests/archive/2026/20260528-222416-ai-hooks-ai-hooks-hook-input-sh.md +0 -59
- package/docs/architecture/requests/archive/2026/20260528-222444-ai-hooks-ai-hooks-pre-edit-guard-sh.md +0 -59
- package/docs/architecture/requests/archive/2026/20260528-222457-ai-hooks-ai-hooks-pre-edit-guard-sh.md +0 -59
- package/docs/architecture/requests/archive/2026/20260528-222648-ai-hooks-ai-hooks-pre-edit-guard-sh.md +0 -59
- package/docs/architecture/requests/archive/2026/20260528-222705-ai-hooks-ai-hooks-worktree-guard-sh.md +0 -59
- package/docs/architecture/requests/archive/2026/20260528-222726-ai-hooks-ai-hooks-prompt-guard-sh.md +0 -59
- package/docs/architecture/requests/archive/2026/20260528-222727-ai-hooks-ai-hooks-prompt-guard-sh.md +0 -59
- package/docs/architecture/requests/archive/2026/20260528-224736-ai-hooks-ai-hooks-hook-input-sh.md +0 -59
- package/docs/architecture/requests/archive/2026/20260528-233259-ai-hooks-ai-hooks-prompt-guard-sh.md +0 -59
- package/docs/architecture/requests/archive/2026/20260528-233335-assets-hooks-assets-hooks-prompt-guard-sh.md +0 -59
- package/docs/architecture/requests/archive/2026/20260528-233456-ai-hooks-ai-hooks-prompt-guard-sh.md +0 -59
- package/docs/architecture/requests/archive/2026/20260528-233457-assets-hooks-assets-hooks-prompt-guard-sh.md +0 -59
- package/docs/architecture/requests/archive/2026/20260528-233637-ai-hooks-ai-hooks-prompt-guard-sh.md +0 -59
- package/docs/architecture/requests/archive/2026/20260528-233638-assets-hooks-assets-hooks-prompt-guard-sh.md +0 -59
- package/docs/architecture/requests/archive/2026/20260529-000322-root-package-json.md +0 -59
- package/docs/architecture/requests/archive/2026/20260529-004238-ai-hooks-ai-hooks-lib-workflow-state-sh.md +0 -59
- package/docs/architecture/requests/archive/2026/20260529-020654-ai-harness-policy-json-ai-harness-policy-json.md +0 -63
- package/docs/architecture/requests/archive/2026/20260529-094236-ai-hooks-ai-hooks-prompt-guard-sh.md +0 -60
- package/docs/architecture/requests/archive/2026/20260529-094323-assets-hooks-assets-hooks-prompt-guard-sh.md +0 -60
- package/docs/architecture/requests/archive/2026/20260529-094331-ai-hooks-ai-hooks-prompt-guard-sh.md +0 -60
- package/docs/architecture/requests/archive/2026/20260529-094339-assets-hooks-assets-hooks-prompt-guard-sh.md +0 -60
- package/docs/architecture/requests/archive/2026/20260529-094430-assets-hooks-assets-hooks-session-start-context-sh.md +0 -60
- package/docs/architecture/requests/archive/2026/20260529-094446-ai-hooks-ai-hooks-session-start-context-sh.md +0 -60
- package/docs/architecture/requests/archive/2026/20260613-002040-runtime-harness-hook-adapters.md +0 -68
- package/docs/architecture/requests/archive/2026/root.md +0 -68
- package/docs/architecture/requests/archive/2026/runtime-harness-hook-adapters.md +0 -76
- package/docs/architecture/requests/archive/2026/verification-evals-checks.md +0 -68
- package/docs/architecture/requests/archive/2026/workflow-engine-contract-assets.md +0 -69
- package/scripts/archive-architecture-request.sh +0 -4
- package/scripts/benchmark-background-check-overlap.ts +0 -228
- package/scripts/benchmark-controller-hotpath.ts +0 -212
- package/scripts/benchmark-controller-round2.ts +0 -139
- package/scripts/benchmark-ios-agent-device.ts +0 -514
- package/scripts/benchmark-mcp-host.sh +0 -117
- package/scripts/benchmark-mcp-transport.ts +0 -170
- package/scripts/benchmark-quality-harness.ts +0 -146
- package/scripts/benchmark-route-session-concurrency.ts +0 -915
- package/scripts/benchmark-thin-harness-gateway-ab.ts +0 -632
- package/scripts/benchmark-thin-harness-mcp-e2e.ts +0 -498
- package/scripts/benchmark-thin-harness.ts +0 -251
- package/scripts/benchmark-typescript-navigation.ts +0 -186
- package/scripts/benchmark-work-efficiency.ts +0 -334
- package/scripts/build-controller-ui.ts +0 -28
- package/scripts/check-npm-release.sh +0 -32
- package/scripts/check-public-release-surface.sh +0 -19
- package/scripts/check-release-published.sh +0 -57
- package/scripts/check-release-readiness.sh +0 -37
- package/scripts/check-release-version.mjs +0 -74
- package/scripts/check-tarball-install-smoke.sh +0 -67
- package/scripts/package-source-archive.sh +0 -147
- package/scripts/public-release-files.txt +0 -39
- package/scripts/public-release.ts +0 -174
- package/scripts/publish-release-tarball.sh +0 -27
- package/scripts/route-nl-vs-ts-eval.ts +0 -679
- package/scripts/run-skill-evals.ts +0 -1022
- package/scripts/stage-runtime-release.ts +0 -39
- package/src/cli/controller/progress.ts +0 -656
- package/src/cli/controller/work-mode.ts +0 -181
- package/src/cli/local-bridge/console-assets.ts +0 -17
- package/src/cli/local-bridge/dashboard.ts +0 -17
- package/src/cli/local-bridge/frontend/src/App.tsx +0 -10
- package/src/cli/local-bridge/frontend/src/components/Button.tsx +0 -1
- package/src/cli/local-bridge/frontend/src/components/DetailPane.tsx +0 -3
- package/src/cli/local-bridge/frontend/src/components/SearchField.tsx +0 -1
- package/src/cli/local-bridge/frontend/src/components/SectionHeader.tsx +0 -1
- package/src/cli/local-bridge/frontend/src/components/Segmented.tsx +0 -1
- package/src/cli/local-bridge/frontend/src/components/StatusText.tsx +0 -3
- package/src/cli/local-bridge/frontend/src/design/icons.tsx +0 -11
- package/src/cli/local-bridge/frontend/src/design/tokens.css +0 -8
- package/src/cli/local-bridge/frontend/src/features/automations/AutomationsView.tsx +0 -153
- package/src/cli/local-bridge/frontend/src/features/capabilities/CapabilitiesView.tsx +0 -37
- package/src/cli/local-bridge/frontend/src/features/overview/OverviewView.tsx +0 -183
- package/src/cli/local-bridge/frontend/src/features/repositories/RepositoriesView.tsx +0 -2
- package/src/cli/local-bridge/frontend/src/features/system/SystemView.tsx +0 -2
- package/src/cli/local-bridge/frontend/src/features/work/WorkView.tsx +0 -4
- package/src/cli/local-bridge/frontend/src/lib/api.ts +0 -30
- package/src/cli/local-bridge/frontend/src/lib/format.ts +0 -4
- package/src/cli/local-bridge/frontend/src/lib/routes.ts +0 -7
- package/src/cli/local-bridge/frontend/src/main.tsx +0 -1
- package/src/cli/local-bridge/frontend/src/shell/AppShell.tsx +0 -1
- package/src/cli/local-bridge/frontend/src/shell/CommandBar.tsx +0 -2
- package/src/cli/local-bridge/frontend/src/shell/Sidebar.tsx +0 -4
- package/src/cli/local-bridge/frontend/src/styles.css +0 -28
- package/src/cli/local-bridge/frontend/src/types.ts +0 -15
- package/src/cli/local-bridge/frontend/src/vite-env.d.ts +0 -1
- package/src/cli/local-bridge/frontend/vite.config.ts +0 -27
- package/src/cli/local-bridge/ui-dist/app.css +0 -1
- package/src/cli/local-bridge/ui-dist/app.js +0 -11228
- package/src/runtime/control-plane/execution/direct-edit-work-completion.ts +0 -385
- package/src/runtime/control-plane/execution/work-finalization-service.ts +0 -1913
- package/src/runtime/control-plane/execution/work-path-scope.ts +0 -37
- package/src/runtime/control-plane/execution/work-task-receipt.ts +0 -449
- package/src/runtime/control-plane/facade/controller-round-relay.ts +0 -1118
- package/src/runtime/control-plane/facade/work-admission-policy.ts +0 -93
- package/src/runtime/control-plane/facade/work-task-projection.ts +0 -66
- package/src/runtime/control-plane/routing/index.ts +0 -1
- package/src/runtime/control-plane/routing/route-policy.ts +0 -382
- package/src/runtime/control-plane/routing/workspace-admission.ts +0 -70
|
@@ -1,1613 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
import { resolveEphemeralWorkspaceTarget } from '../repositories/ephemeral-workspace';
|
|
4
|
-
import type { ResolvedExecutionIdentity } from '../../runtime/control-plane/execution/execution-identity';
|
|
5
|
-
import { assertNoBoundExecutionSessionMutation, resolveClaimedRepositoryWorkId, resolveExplicitClaimedRepositoryWork, type RepositoryWorkAttributionCaller } from '../../runtime/control-plane/execution/repository-work-attribution';
|
|
6
|
-
import { getWorkContract } from '../../runtime/control-plane/facade/work-contract-store';
|
|
7
|
-
import { assertWorkPathsWithinScope } from '../../runtime/control-plane/execution/work-path-scope';
|
|
8
|
-
import { ensureRepositoryMutationWorkHandle } from '../../runtime/control-plane/execution/work-handle-authority';
|
|
9
|
-
import { isTerminalWorkContractStatus } from '../../runtime/control-plane/facade/types';
|
|
10
|
-
import { executeRepositoryCommand, previewRepositoryCommandExecution } from '../repositories/command-executor';
|
|
11
|
-
import { withControllerLock } from '../repositories/locks';
|
|
12
|
-
import {
|
|
13
|
-
disableRepository,
|
|
14
|
-
findIdenticalRepositoryRegistration,
|
|
15
|
-
getRepository,
|
|
16
|
-
listRepositories,
|
|
17
|
-
reconcileRepositoryCheckouts,
|
|
18
|
-
refreshRepository,
|
|
19
|
-
registerRepository,
|
|
20
|
-
removeRepository,
|
|
21
|
-
repositorySummary,
|
|
22
|
-
resolveRepositorySelection,
|
|
23
|
-
updateRepository,
|
|
24
|
-
validateRepository,
|
|
25
|
-
} from '../repositories/registry';
|
|
26
|
-
import { buildControllerWorkbench } from '../repositories/workbench';
|
|
27
|
-
import { applySafePatch, buildSafePatchPlan } from '../repositories/safe-patch';
|
|
28
|
-
import { getEditSession, getEditSessionDiff, type EditSessionBinding } from '../editing/edit-session';
|
|
29
|
-
import { buildSyncOperationDigest, classifyUserFacingError } from '../../runtime/control-plane/facade/operation-digest';
|
|
30
|
-
import {
|
|
31
|
-
repositoryGitCommit,
|
|
32
|
-
repositoryGitCreateBranch,
|
|
33
|
-
repositoryGitDeleteBranch,
|
|
34
|
-
repositoryGitDiff,
|
|
35
|
-
repositoryGitFinishWorkflow,
|
|
36
|
-
repositoryGitMergeBranch,
|
|
37
|
-
repositoryGitStatus,
|
|
38
|
-
repositoryGitSwitchBranch,
|
|
39
|
-
} from '../repositories/structured-git';
|
|
40
|
-
import {
|
|
41
|
-
readRepositoryGitStatusSample,
|
|
42
|
-
writeRepositoryGitStatusSample,
|
|
43
|
-
} from '../../runtime/projections/git-status-sampler';
|
|
44
|
-
import {
|
|
45
|
-
executeLightweightLanes,
|
|
46
|
-
executeRepositoryBatch,
|
|
47
|
-
integratePatchProposals,
|
|
48
|
-
listFastReceipts,
|
|
49
|
-
readFastReceipt,
|
|
50
|
-
routeExecution,
|
|
51
|
-
} from '../../runtime/execution/thin-harness';
|
|
52
|
-
import {
|
|
53
|
-
classifyRepositoryCommandRoute,
|
|
54
|
-
executeRepositoryCommandViaProcessRuntime,
|
|
55
|
-
} from '../../runtime/execution/process-runtime/command-facade';
|
|
56
|
-
import { assessWorkMode, parseExplicitTaskMode } from '../controller/work-mode';
|
|
57
|
-
import { classifyRepositoryCommand } from '../repositories/command-classifier';
|
|
58
|
-
import { normalizeRepositoryCommand } from '../repositories/command-normalization';
|
|
59
|
-
import { readRepositoryRange } from '../repository/inspector';
|
|
60
|
-
import { getMcpPolicy } from './policy';
|
|
61
|
-
import { redactMcpText } from './redaction';
|
|
62
|
-
import type { CallToolResult, McpToolDefinition } from './tool-contract';
|
|
63
|
-
import {
|
|
64
|
-
boundUtf8,
|
|
65
|
-
compactCommandOutput,
|
|
66
|
-
compactErrorMessage,
|
|
67
|
-
compactRoutingSummary,
|
|
68
|
-
RESPONSE_BUDGET,
|
|
69
|
-
} from '../../runtime/shared/response-budget';
|
|
70
|
-
|
|
71
|
-
export type RepositoryToolResult = CallToolResult;
|
|
72
|
-
|
|
73
|
-
function definition(
|
|
74
|
-
name: string,
|
|
75
|
-
description: string,
|
|
76
|
-
properties: Record<string, unknown>,
|
|
77
|
-
required: string[] = [],
|
|
78
|
-
readOnlyHint = false,
|
|
79
|
-
destructiveHint = false,
|
|
80
|
-
): McpToolDefinition {
|
|
81
|
-
return {
|
|
82
|
-
name,
|
|
83
|
-
description,
|
|
84
|
-
inputSchema: {
|
|
85
|
-
type: 'object',
|
|
86
|
-
properties,
|
|
87
|
-
...(required.length > 0 ? { required } : {}),
|
|
88
|
-
additionalProperties: false,
|
|
89
|
-
},
|
|
90
|
-
annotations: { readOnlyHint, openWorldHint: false, destructiveHint },
|
|
91
|
-
};
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
const repoId = { type: 'string', description: 'Stable Repository Registry repoId.' };
|
|
95
|
-
|
|
96
|
-
export const repositoryToolDefinitions: McpToolDefinition[] = [
|
|
97
|
-
definition('repository_register', 'Register a Git repository with the Controller.', {
|
|
98
|
-
path: { type: 'string' },
|
|
99
|
-
display_name: { type: 'string' },
|
|
100
|
-
remote_url: { type: 'string' },
|
|
101
|
-
default_branch: { type: 'string' },
|
|
102
|
-
detail_level: { type: 'string', enum: ['summary', 'detail'], description: 'Defaults to summary; detail returns full checkout and migration evidence.' },
|
|
103
|
-
}, ['path']),
|
|
104
|
-
definition('repository_latest_source_diagnose', 'Read-only diagnosis that compares sibling project directories and recommends the latest usable source tree.', {
|
|
105
|
-
path: { type: 'string', description: 'Absolute local project path.' },
|
|
106
|
-
repo_id: repoId,
|
|
107
|
-
}, [], true),
|
|
108
|
-
definition('repository_bootstrap_local_project', 'Safely initialize and optionally register a trusted non-Git local project directory.', {
|
|
109
|
-
path: { type: 'string', description: 'Absolute local project path.' },
|
|
110
|
-
display_name: { type: 'string' },
|
|
111
|
-
default_branch: { type: 'string' },
|
|
112
|
-
mode: { type: 'string', enum: ['init_git_only', 'init_git_and_register', 'replace_registration'] },
|
|
113
|
-
replace_registered_repo_id: repoId,
|
|
114
|
-
confirm_authorization: { type: 'boolean', description: 'Must be true to authorize Git initialization and registration.' },
|
|
115
|
-
}, ['path', 'confirm_authorization'], false, true),
|
|
116
|
-
definition('repository_list', 'List registered repositories.', {
|
|
117
|
-
include_removed: { type: 'boolean' },
|
|
118
|
-
}, [], true),
|
|
119
|
-
definition('repository_get', 'Inspect one registered repository.', {
|
|
120
|
-
repo_id: repoId,
|
|
121
|
-
include_removed: { type: 'boolean' },
|
|
122
|
-
detail_level: { type: 'string', enum: ['summary', 'detail'], description: 'Defaults to summary; detail returns the complete checkout history.' },
|
|
123
|
-
}, ['repo_id'], true),
|
|
124
|
-
definition('read_repository_file', 'Read a line range from one policy-readable repository file.', {
|
|
125
|
-
repo_id: repoId,
|
|
126
|
-
checkout_id: { type: 'string' },
|
|
127
|
-
path: { type: 'string' },
|
|
128
|
-
start_line: { type: 'number' },
|
|
129
|
-
end_line: { type: 'number' },
|
|
130
|
-
}, ['path'], true),
|
|
131
|
-
definition('repository_validate', 'Validate repository identity and migrate legacy ownership.', {
|
|
132
|
-
repo_id: repoId,
|
|
133
|
-
detail_level: { type: 'string', enum: ['summary', 'detail'], description: 'Defaults to summary; detail returns full migration evidence.' },
|
|
134
|
-
}, ['repo_id']),
|
|
135
|
-
definition('repository_refresh', 'Refresh repository Git and checkout metadata.', {
|
|
136
|
-
repo_id: repoId,
|
|
137
|
-
detail_level: { type: 'string', enum: ['summary', 'detail'], description: 'Defaults to summary; detail returns full checkout and migration evidence.' },
|
|
138
|
-
}, ['repo_id']),
|
|
139
|
-
definition('repository_update', 'Update mutable repository metadata.', {
|
|
140
|
-
repo_id: repoId,
|
|
141
|
-
display_name: { type: 'string' },
|
|
142
|
-
default_branch: { type: 'string' },
|
|
143
|
-
enabled: { type: 'boolean' },
|
|
144
|
-
}, ['repo_id']),
|
|
145
|
-
definition('repository_disable', 'Disable new execution while retaining audit history.', {
|
|
146
|
-
repo_id: repoId,
|
|
147
|
-
}, ['repo_id']),
|
|
148
|
-
definition('repository_remove', 'Soft-remove a repository while retaining audit history.', {
|
|
149
|
-
repo_id: repoId,
|
|
150
|
-
}, ['repo_id']),
|
|
151
|
-
definition('repository_workbench', 'Return Workbench state or invoke one bounded Thin Harness operation without adding top-level MCP tools. Prefer batch_execute for multi-step status→search→read→diff or read→patch→check flows so ChatGPT pays one routing/receipt ownership cycle.', {
|
|
152
|
-
repo_id: repoId,
|
|
153
|
-
checkout_id: { type: 'string', description: 'Optional checkout identity for repository-scoped operations.' },
|
|
154
|
-
include_removed: { type: 'boolean' },
|
|
155
|
-
operation: {
|
|
156
|
-
type: 'string',
|
|
157
|
-
enum: ['summary', 'batch_execute', 'lanes_execute', 'lanes_integrate', 'fast_receipt_get', 'fast_receipt_list', 'execution_route', 'assess_work_mode'],
|
|
158
|
-
description: 'Defaults to summary. Use batch_execute for multi-step Fast Path (one parent receipt). Use lanes_execute for limited parallel reads. Use assess_work_mode for Fast/Durable routing advice.',
|
|
159
|
-
},
|
|
160
|
-
payload: {
|
|
161
|
-
type: 'object',
|
|
162
|
-
description: 'Operation-specific bounded arguments. Batch write operations should include request_id. For batch_execute: { steps:[{id?, kind, input}], stop_on_error?, allowed_paths?, timeout_ms?, request_id?, purpose? }. For assess_work_mode: { description, known_paths?, expected_files?, requires_parallelism?, independent_task_count?, agent_requested? }. Agent routing is opt-in only.',
|
|
163
|
-
additionalProperties: true,
|
|
164
|
-
},
|
|
165
|
-
}),
|
|
166
|
-
definition('repository_git_status', 'Return a structured Git status snapshot for the selected repository checkout.', {
|
|
167
|
-
repo_id: repoId,
|
|
168
|
-
checkout_id: { type: 'string', description: 'Optional checkout identity for repositories with multiple local clones.' },
|
|
169
|
-
refresh: { type: 'boolean', description: 'When true, explicitly refresh the Git status sample. The default public hot path only reads the latest daemon sample.' },
|
|
170
|
-
}, [], true),
|
|
171
|
-
|
|
172
|
-
definition('repository_git_diff', 'Return a bounded structured git diff for the selected repository, optionally staged and path-scoped.', {
|
|
173
|
-
repo_id: repoId,
|
|
174
|
-
checkout_id: { type: 'string', description: 'Optional checkout identity for repositories with multiple local clones.' },
|
|
175
|
-
staged: { type: 'boolean' },
|
|
176
|
-
paths: { type: 'array', items: { type: 'string' } },
|
|
177
|
-
max_bytes: { type: 'number' },
|
|
178
|
-
}, [], true),
|
|
179
|
-
definition('repository_git_create_branch', 'Create a safe local Git branch, optionally switching to it.', {
|
|
180
|
-
repo_id: repoId,
|
|
181
|
-
checkout_id: { type: 'string', description: 'Optional checkout identity for repositories with multiple local clones.' },
|
|
182
|
-
branch: { type: 'string' },
|
|
183
|
-
start_point: { type: 'string' },
|
|
184
|
-
switch_to: { type: 'boolean', description: 'Defaults to true. False creates the branch without switching.' },
|
|
185
|
-
}, ['branch']),
|
|
186
|
-
definition('repository_git_switch_branch', 'Switch to a safe local Git branch name.', {
|
|
187
|
-
repo_id: repoId,
|
|
188
|
-
checkout_id: { type: 'string', description: 'Optional checkout identity for repositories with multiple local clones.' },
|
|
189
|
-
branch: { type: 'string' },
|
|
190
|
-
}, ['branch']),
|
|
191
|
-
definition('repository_git_merge_branch', 'Merge a branch into the current branch using --ff-only by default.', {
|
|
192
|
-
repo_id: repoId,
|
|
193
|
-
checkout_id: { type: 'string', description: 'Optional checkout identity for repositories with multiple local clones.' },
|
|
194
|
-
branch: { type: 'string' },
|
|
195
|
-
no_ff: { type: 'boolean', description: 'Use --no-ff instead of the default --ff-only.' },
|
|
196
|
-
}, ['branch']),
|
|
197
|
-
definition('repository_git_delete_branch', 'Delete a safe local Git branch after it has been merged or intentionally discarded.', {
|
|
198
|
-
repo_id: repoId,
|
|
199
|
-
checkout_id: { type: 'string', description: 'Optional checkout identity for repositories with multiple local clones.' },
|
|
200
|
-
branch: { type: 'string' },
|
|
201
|
-
force: { type: 'boolean' },
|
|
202
|
-
}, ['branch']),
|
|
203
|
-
|
|
204
|
-
definition('repository_git_commit', 'Stage optional explicit paths and commit through a structured Git action.', {
|
|
205
|
-
repo_id: repoId,
|
|
206
|
-
checkout_id: { type: 'string', description: 'Optional checkout identity for repositories with multiple local clones.' },
|
|
207
|
-
message: { type: 'string' },
|
|
208
|
-
paths: { type: 'array', items: { type: 'string' } },
|
|
209
|
-
allow_empty: { type: 'boolean' },
|
|
210
|
-
}, ['message']),
|
|
211
|
-
definition('repository_git_finish_workflow', 'Finish the current feature workflow: require clean tree, switch to target, merge feature branch, and delete it by default.', {
|
|
212
|
-
repo_id: repoId,
|
|
213
|
-
checkout_id: { type: 'string', description: 'Optional checkout identity for repositories with multiple local clones.' },
|
|
214
|
-
feature_branch: { type: 'string', description: 'Defaults to the current branch.' },
|
|
215
|
-
target_branch: { type: 'string', description: 'Defaults to repository defaultBranch or main.' },
|
|
216
|
-
delete_branch: { type: 'boolean', description: 'Defaults to true.' },
|
|
217
|
-
no_ff: { type: 'boolean', description: 'Use --no-ff instead of the default --ff-only.' },
|
|
218
|
-
}, []),
|
|
219
|
-
definition('repository_safe_patch_plan', 'Plan a deterministic chunked repository patch with fresh file fingerprints before applying.', {
|
|
220
|
-
repo_id: repoId,
|
|
221
|
-
checkout_id: { type: 'string', description: 'Optional checkout identity for repositories with multiple local clones.' },
|
|
222
|
-
operations: { type: 'array', items: { type: 'object' }, description: 'Edit operations using the same shape as apply_patch.' },
|
|
223
|
-
chunk_size: { type: 'number', description: 'Maximum operations per deterministic chunk. Capped at 100.' },
|
|
224
|
-
}, ['operations'], true),
|
|
225
|
-
definition('repository_safe_patch_apply', 'Apply one coherent deterministic edit batch and return bounded review evidence. Checks are opt-in: pass check_ids only when the batch is stable. Long checks return managed Process handles instead of blocking the MCP call; use validation_only with the returned session/request ids to join later without replaying the patch.', {
|
|
226
|
-
repo_id: repoId,
|
|
227
|
-
checkout_id: { type: 'string', description: 'Optional checkout identity for repositories with multiple local clones.' },
|
|
228
|
-
work_id: { type: 'string', description: 'Optional durable Work identity. Workflow controllers should pass the exact claimed Work id so attribution survives transient MCP transport sessions.' },
|
|
229
|
-
session_id: { type: 'string', description: 'Existing edit session id. Required for validation_only; otherwise omit to create one.' },
|
|
230
|
-
purpose: { type: 'string', description: 'Purpose for a newly created edit session.' },
|
|
231
|
-
operations: { type: 'array', items: { type: 'object' }, description: 'Edit operations using the same shape as apply_patch. Required unless validation_only=true.' },
|
|
232
|
-
chunk_size: { type: 'number', description: 'Maximum operations per deterministic chunk. Capped at 100.' },
|
|
233
|
-
expected_revision: { type: 'number', description: 'Expected starting edit-session revision.' },
|
|
234
|
-
allowed_paths: { type: 'array', items: { type: 'string' }, description: 'Optional allowed path globs for a newly created session.' },
|
|
235
|
-
continue_on_error: { type: 'boolean', description: 'Continue applying later independent chunks after a failed chunk. Defaults to false.' },
|
|
236
|
-
refresh_fingerprints: { type: 'boolean', description: 'Refresh file fingerprints before every chunk. Defaults to true.' },
|
|
237
|
-
recover_stale_session: { type: 'boolean', description: 'For new sessions, recover stale edit-session fingerprints into a fresh session. Defaults to true.' },
|
|
238
|
-
check_ids: { type: 'array', items: { type: 'string' }, description: 'Optional focused validation for this stable coherent edit batch. Omit to edit without running tests.' },
|
|
239
|
-
check_timeout_ms: { type: 'number', description: 'Per-check execution budget. Long checks still return managed handles immediately.' },
|
|
240
|
-
lease_wait_ms: { type: 'number', description: 'Bounded resource-lease wait for conflicting validation lanes.' },
|
|
241
|
-
validation_request_id: { type: 'string', description: 'Stable validation identity returned by a prior edit+validation call; reuse with validation_only to join without replaying edits.' },
|
|
242
|
-
validation_only: { type: 'boolean', description: 'When true, do not edit. Reconcile/reuse the existing session validation Processes identified by session_id/check_ids/validation_request_id.' },
|
|
243
|
-
apply_mode: { type: 'string', enum: ['sync', 'async'], description: 'Defaults to sync for interactive development. Set async only for a separately durable operation.' },
|
|
244
|
-
}),
|
|
245
|
-
definition('repository_command_preview', 'Preview one repository-scoped local command with classification, approval token, and Git snapshots.', {
|
|
246
|
-
repo_id: repoId,
|
|
247
|
-
checkout_id: { type: 'string', description: 'Optional checkout identity for repositories with multiple local clones.' },
|
|
248
|
-
command: { anyOf: [{ type: 'string' }, { type: 'array', items: { type: 'string' }, minItems: 1 }], description: 'Legacy shell string or typed argv array. Typed argv executes without a shell.' },
|
|
249
|
-
cwd: { type: 'string', description: 'Optional root-relative working directory.' },
|
|
250
|
-
workspace_root: { type: 'string', description: 'Absolute existing local directory used as an ephemeral execution root. Mutually exclusive with repo_id/checkout_id; does not register or initialize the directory.' },
|
|
251
|
-
}, ['command'], true),
|
|
252
|
-
definition('repository_command_execute', 'Execute one repository-scoped command through the thinnest eligible lane: ephemeral for ordinary local work, an in-memory lightweight handle when it outlives the interaction budget, or explicit Durable handling for Work/external/release effects. Lightweight handles have no SQLite, Lease, recovery, or replay membership. Use rh_context for routine code discovery/reading; shell exploration is fallback-only.', {
|
|
253
|
-
repo_id: repoId,
|
|
254
|
-
checkout_id: { type: 'string', description: 'Optional checkout identity for repositories with multiple local clones.' },
|
|
255
|
-
work_id: { type: 'string', description: 'Optional durable Work identity. Workflow controllers should pass the exact claimed Work id so attribution survives transient MCP transport sessions.' },
|
|
256
|
-
command: { anyOf: [{ type: 'string' }, { type: 'array', items: { type: 'string' }, minItems: 1 }], description: 'Legacy shell string or typed argv array. Typed argv executes without a shell.' },
|
|
257
|
-
cwd: { type: 'string', description: 'Optional root-relative working directory.' },
|
|
258
|
-
workspace_root: { type: 'string', description: 'Absolute existing local directory used as an ephemeral execution root. Mutually exclusive with repo_id/checkout_id; does not register or initialize the directory.' },
|
|
259
|
-
approval_token: { type: 'string', description: 'Exact approval token returned by repository_command_preview.' },
|
|
260
|
-
approval_request_id: { type: 'string', description: 'Resolved approvalRequestId returned by approval_resolve.' },
|
|
261
|
-
timeout_ms: { type: 'number', description: 'Optional execution timeout in milliseconds.' },
|
|
262
|
-
max_output_bytes: { type: 'number', description: 'Optional cap for captured stdout/stderr.' },
|
|
263
|
-
}, ['command']),
|
|
264
|
-
|
|
265
|
-
// Thin Harness V1 is exposed through repository_workbench operations to keep the stable tool surface bounded.
|
|
266
|
-
];
|
|
267
|
-
|
|
268
|
-
export const repositoryToolNames = repositoryToolDefinitions.map((tool) => tool.name);
|
|
269
|
-
|
|
270
|
-
function result(value: Record<string, unknown>): RepositoryToolResult {
|
|
271
|
-
// Compact text channel by default; structuredContent remains the machine view.
|
|
272
|
-
return {
|
|
273
|
-
content: [{ type: 'text', text: JSON.stringify(value) }],
|
|
274
|
-
structuredContent: value,
|
|
275
|
-
};
|
|
276
|
-
}
|
|
277
|
-
|
|
278
|
-
const DEFAULT_MIGRATION_SAMPLE_LIMIT = 3;
|
|
279
|
-
|
|
280
|
-
function withResponseMeta(payload: Record<string, unknown>, startedAt: number): Record<string, unknown> {
|
|
281
|
-
const response = {
|
|
282
|
-
...payload,
|
|
283
|
-
responseMeta: {
|
|
284
|
-
serverDurationMs: Math.round((performance.now() - startedAt) * 100) / 100,
|
|
285
|
-
structuredPayloadBytes: 0,
|
|
286
|
-
},
|
|
287
|
-
};
|
|
288
|
-
response.responseMeta.structuredPayloadBytes = Buffer.byteLength(JSON.stringify(response), 'utf8');
|
|
289
|
-
return response;
|
|
290
|
-
}
|
|
291
|
-
|
|
292
|
-
export type RepositoryToolCallerContext = RepositoryWorkAttributionCaller;
|
|
293
|
-
|
|
294
|
-
export function claimedSessionEditBinding(
|
|
295
|
-
controllerHome: string,
|
|
296
|
-
repository: ReturnType<typeof resolveRepositorySelection>,
|
|
297
|
-
caller?: RepositoryToolCallerContext,
|
|
298
|
-
explicitWorkId?: unknown,
|
|
299
|
-
): EditSessionBinding | undefined {
|
|
300
|
-
const workId = resolveClaimedRepositoryWorkId(controllerHome, repository, caller, explicitWorkId);
|
|
301
|
-
if (!workId || !caller?.principalId?.trim()) return undefined;
|
|
302
|
-
const work = getWorkContract({ controllerHome, repoId: repository.repoId }, workId);
|
|
303
|
-
if (!work) return undefined;
|
|
304
|
-
return {
|
|
305
|
-
workId,
|
|
306
|
-
repoId: repository.repoId,
|
|
307
|
-
checkoutId: repository.activeCheckoutId,
|
|
308
|
-
principalId: caller.principalId.trim(),
|
|
309
|
-
controllerInstanceId: caller.controllerInstanceId,
|
|
310
|
-
routeDecisionFingerprint: work.routeDecisionFingerprint,
|
|
311
|
-
};
|
|
312
|
-
}
|
|
313
|
-
|
|
314
|
-
function safePatchEditBinding(
|
|
315
|
-
controllerHome: string,
|
|
316
|
-
repository: ReturnType<typeof resolveRepositorySelection>,
|
|
317
|
-
caller: RepositoryToolCallerContext | undefined,
|
|
318
|
-
args: Record<string, unknown>,
|
|
319
|
-
): EditSessionBinding | undefined {
|
|
320
|
-
const explicitWorkId = typeof args.work_id === 'string' ? args.work_id.trim() : '';
|
|
321
|
-
if (explicitWorkId) return claimedSessionEditBinding(controllerHome, repository, caller, explicitWorkId);
|
|
322
|
-
const sessionId = typeof args.session_id === 'string' ? args.session_id.trim() : '';
|
|
323
|
-
if (sessionId) {
|
|
324
|
-
const existingWorkId = getEditSession(repository.canonicalRoot, sessionId).workId?.trim();
|
|
325
|
-
return existingWorkId
|
|
326
|
-
? claimedSessionEditBinding(controllerHome, repository, caller, existingWorkId)
|
|
327
|
-
: undefined;
|
|
328
|
-
}
|
|
329
|
-
assertNoBoundExecutionSessionMutation(controllerHome, repository, caller);
|
|
330
|
-
return undefined;
|
|
331
|
-
}
|
|
332
|
-
|
|
333
|
-
function resolveRepositorySelectionForClaimedWork(
|
|
334
|
-
controllerHome: string,
|
|
335
|
-
args: Record<string, unknown>,
|
|
336
|
-
repoIdValue: string,
|
|
337
|
-
caller?: RepositoryToolCallerContext,
|
|
338
|
-
): ReturnType<typeof resolveRepositorySelection> {
|
|
339
|
-
const checkoutId = typeof args.checkout_id === 'string' ? args.checkout_id.trim() : '';
|
|
340
|
-
const explicitWorkId = typeof args.work_id === 'string' ? args.work_id.trim() : '';
|
|
341
|
-
const repository = resolveRepositorySelection({
|
|
342
|
-
repoId: repoIdValue || undefined,
|
|
343
|
-
checkoutId: checkoutId || undefined,
|
|
344
|
-
controllerHome,
|
|
345
|
-
allowSoleRepository: true,
|
|
346
|
-
});
|
|
347
|
-
if (!explicitWorkId || checkoutId) return repository;
|
|
348
|
-
const work = resolveExplicitClaimedRepositoryWork(controllerHome, repository, caller, explicitWorkId);
|
|
349
|
-
if (!work?.checkoutId || work.checkoutId === repository.activeCheckoutId) return repository;
|
|
350
|
-
return resolveRepositorySelection({
|
|
351
|
-
repoId: repository.repoId,
|
|
352
|
-
checkoutId: work.checkoutId,
|
|
353
|
-
controllerHome,
|
|
354
|
-
allowSoleRepository: true,
|
|
355
|
-
});
|
|
356
|
-
}
|
|
357
|
-
|
|
358
|
-
function rawDefaultBranchMergeCommand(repository: ReturnType<typeof resolveRepositorySelection>, command: unknown): boolean {
|
|
359
|
-
if (!repository.defaultBranch) return false;
|
|
360
|
-
const checkout = repository.checkouts.find((entry) => entry.checkoutId === repository.activeCheckoutId);
|
|
361
|
-
if (checkout?.branch !== repository.defaultBranch) return false;
|
|
362
|
-
const normalized = normalizeRepositoryCommand(command);
|
|
363
|
-
if (normalized.kind === 'argv') {
|
|
364
|
-
const executable = normalized.executable?.split('/').pop();
|
|
365
|
-
return executable === 'git' && normalized.args?.[0] === 'merge';
|
|
366
|
-
}
|
|
367
|
-
return /(?:^|[;&|]\s*)git\s+merge\b/.test(normalized.shellCommand ?? '');
|
|
368
|
-
}
|
|
369
|
-
|
|
370
|
-
interface HistoricalReadOnlyWorkContext {
|
|
371
|
-
workId: string;
|
|
372
|
-
status: string;
|
|
373
|
-
mode: 'historical_read_only_observation';
|
|
374
|
-
attribution: 'not_active_work';
|
|
375
|
-
}
|
|
376
|
-
|
|
377
|
-
function historicalReadOnlyWorkContext(
|
|
378
|
-
controllerHome: string,
|
|
379
|
-
repository: ReturnType<typeof resolveRepositorySelection>,
|
|
380
|
-
args: Record<string, unknown>,
|
|
381
|
-
): HistoricalReadOnlyWorkContext | undefined {
|
|
382
|
-
const requestedWorkId = typeof args.work_id === 'string' ? args.work_id.trim() : '';
|
|
383
|
-
if (!requestedWorkId) return undefined;
|
|
384
|
-
const work = getWorkContract({ controllerHome, repoId: repository.repoId }, requestedWorkId);
|
|
385
|
-
if (!work || !isTerminalWorkContractStatus(work.status)) return undefined;
|
|
386
|
-
const classification = classifyRepositoryCommand(args.command as string | string[], repository.defaultBranch);
|
|
387
|
-
if (classification.risk !== 'readonly') return undefined;
|
|
388
|
-
return {
|
|
389
|
-
workId: work.workId,
|
|
390
|
-
status: work.status,
|
|
391
|
-
mode: 'historical_read_only_observation',
|
|
392
|
-
attribution: 'not_active_work',
|
|
393
|
-
};
|
|
394
|
-
}
|
|
395
|
-
|
|
396
|
-
function resolveRepositoryCommandTarget(
|
|
397
|
-
controllerHome: string,
|
|
398
|
-
args: Record<string, unknown>,
|
|
399
|
-
repoIdValue: string,
|
|
400
|
-
caller?: RepositoryToolCallerContext,
|
|
401
|
-
): {
|
|
402
|
-
repository: ReturnType<typeof resolveRepositorySelection>;
|
|
403
|
-
executionIdentity: ResolvedExecutionIdentity;
|
|
404
|
-
workspace?: { workspaceId: string; root: string; registered: false };
|
|
405
|
-
historicalWorkContext?: HistoricalReadOnlyWorkContext;
|
|
406
|
-
} {
|
|
407
|
-
const workspaceRoot = typeof args.workspace_root === 'string' ? args.workspace_root.trim() : '';
|
|
408
|
-
const checkoutId = typeof args.checkout_id === 'string' ? args.checkout_id.trim() : '';
|
|
409
|
-
if (workspaceRoot) {
|
|
410
|
-
if (repoIdValue || checkoutId) {
|
|
411
|
-
throw new Error('EPHEMERAL_WORKSPACE_TARGET_CONFLICT: workspace_root cannot be combined with repo_id or checkout_id');
|
|
412
|
-
}
|
|
413
|
-
const target = resolveEphemeralWorkspaceTarget(workspaceRoot, controllerHome);
|
|
414
|
-
return {
|
|
415
|
-
repository: target.repository,
|
|
416
|
-
executionIdentity: {
|
|
417
|
-
schemaVersion: 1,
|
|
418
|
-
authority: 'ephemeral_workspace',
|
|
419
|
-
repositoryId: target.workspaceId,
|
|
420
|
-
checkoutId: target.checkoutId,
|
|
421
|
-
canonicalRoot: target.canonicalRoot,
|
|
422
|
-
},
|
|
423
|
-
workspace: { workspaceId: target.workspaceId, root: target.canonicalRoot, registered: false },
|
|
424
|
-
};
|
|
425
|
-
}
|
|
426
|
-
// A terminal Work no longer owns mutation or checkout authority. An exact
|
|
427
|
-
// terminal work_id may still accompany a read-only observation immediately
|
|
428
|
-
// after finalize, so preserve it as explicit historical context while
|
|
429
|
-
// executing against the caller-selected/current repository checkout. Any
|
|
430
|
-
// non-read-only command continues through claimed Work resolution and fails
|
|
431
|
-
// closed for terminal attribution.
|
|
432
|
-
const selectedRepository = resolveRepositorySelection({
|
|
433
|
-
repoId: repoIdValue || undefined,
|
|
434
|
-
checkoutId: checkoutId || undefined,
|
|
435
|
-
controllerHome,
|
|
436
|
-
allowSoleRepository: true,
|
|
437
|
-
});
|
|
438
|
-
const historicalWorkContext = historicalReadOnlyWorkContext(controllerHome, selectedRepository, args);
|
|
439
|
-
if (historicalWorkContext) {
|
|
440
|
-
return {
|
|
441
|
-
repository: selectedRepository,
|
|
442
|
-
executionIdentity: {
|
|
443
|
-
schemaVersion: 1,
|
|
444
|
-
authority: 'repository',
|
|
445
|
-
repositoryId: selectedRepository.repoId,
|
|
446
|
-
checkoutId: selectedRepository.activeCheckoutId,
|
|
447
|
-
canonicalRoot: selectedRepository.canonicalRoot,
|
|
448
|
-
},
|
|
449
|
-
historicalWorkContext,
|
|
450
|
-
};
|
|
451
|
-
}
|
|
452
|
-
|
|
453
|
-
const repository = resolveRepositorySelectionForClaimedWork(controllerHome, args, repoIdValue, caller);
|
|
454
|
-
const explicitWorkId = typeof args.work_id === 'string' ? args.work_id.trim() : '';
|
|
455
|
-
const workId = explicitWorkId
|
|
456
|
-
? resolveClaimedRepositoryWorkId(controllerHome, repository, caller, explicitWorkId)
|
|
457
|
-
: undefined;
|
|
458
|
-
return {
|
|
459
|
-
repository,
|
|
460
|
-
executionIdentity: {
|
|
461
|
-
schemaVersion: 1,
|
|
462
|
-
authority: 'repository',
|
|
463
|
-
repositoryId: repository.repoId,
|
|
464
|
-
checkoutId: repository.activeCheckoutId,
|
|
465
|
-
canonicalRoot: repository.canonicalRoot,
|
|
466
|
-
...(workId ? { workId } : {}),
|
|
467
|
-
},
|
|
468
|
-
};
|
|
469
|
-
}
|
|
470
|
-
|
|
471
|
-
export function summarizeEntityMigrationReport(
|
|
472
|
-
report: ReturnType<typeof bindRepositoryEntities>,
|
|
473
|
-
detail = false,
|
|
474
|
-
): ReturnType<typeof bindRepositoryEntities> | Record<string, unknown> {
|
|
475
|
-
if (detail) return report;
|
|
476
|
-
const files = report.files.slice(0, DEFAULT_MIGRATION_SAMPLE_LIMIT);
|
|
477
|
-
const errors = report.errors.slice(0, DEFAULT_MIGRATION_SAMPLE_LIMIT);
|
|
478
|
-
return {
|
|
479
|
-
repoId: report.repoId,
|
|
480
|
-
checkoutId: report.checkoutId,
|
|
481
|
-
scanned: report.scanned,
|
|
482
|
-
updated: report.updated,
|
|
483
|
-
unresolved: report.unresolved,
|
|
484
|
-
fileCount: report.files.length,
|
|
485
|
-
errorCount: report.errors.length,
|
|
486
|
-
files,
|
|
487
|
-
errors,
|
|
488
|
-
truncated: report.files.length > files.length || report.errors.length > errors.length,
|
|
489
|
-
omittedFileCount: Math.max(0, report.files.length - files.length),
|
|
490
|
-
omittedErrorCount: Math.max(0, report.errors.length - errors.length),
|
|
491
|
-
};
|
|
492
|
-
}
|
|
493
|
-
|
|
494
|
-
export function summarizeRepositoryRegistration(
|
|
495
|
-
repository: ReturnType<typeof registerRepository>,
|
|
496
|
-
migration: ReturnType<typeof bindRepositoryEntities>,
|
|
497
|
-
detail = false,
|
|
498
|
-
fastPath = false,
|
|
499
|
-
): Record<string, unknown> {
|
|
500
|
-
if (detail) {
|
|
501
|
-
return { detailLevel: 'detail', repository, migration, fastPath };
|
|
502
|
-
}
|
|
503
|
-
const checkoutCounts = repository.checkouts.reduce<Record<string, number>>((counts, checkout) => {
|
|
504
|
-
const lifecycle = checkout.lifecycle ?? 'active';
|
|
505
|
-
counts[lifecycle] = (counts[lifecycle] ?? 0) + 1;
|
|
506
|
-
return counts;
|
|
507
|
-
}, {});
|
|
508
|
-
return {
|
|
509
|
-
detailLevel: 'summary',
|
|
510
|
-
repository: {
|
|
511
|
-
...repositorySummary(repository),
|
|
512
|
-
activeCheckoutId: repository.activeCheckoutId,
|
|
513
|
-
checkoutCount: repository.checkouts.length,
|
|
514
|
-
checkoutCounts,
|
|
515
|
-
},
|
|
516
|
-
migration: summarizeEntityMigrationReport(migration),
|
|
517
|
-
fastPath,
|
|
518
|
-
next: 'Re-call with detail_level=detail only when full checkout or migration evidence is required.',
|
|
519
|
-
};
|
|
520
|
-
}
|
|
521
|
-
|
|
522
|
-
export function summarizeRepositoryInspection(
|
|
523
|
-
repository: ReturnType<typeof getRepository>,
|
|
524
|
-
detail = false,
|
|
525
|
-
): Record<string, unknown> {
|
|
526
|
-
if (detail) return { detailLevel: 'detail', repository };
|
|
527
|
-
const checkoutCounts = repository.checkouts.reduce<Record<string, number>>((counts, checkout) => {
|
|
528
|
-
const lifecycle = checkout.lifecycle ?? 'active';
|
|
529
|
-
counts[lifecycle] = (counts[lifecycle] ?? 0) + 1;
|
|
530
|
-
return counts;
|
|
531
|
-
}, {});
|
|
532
|
-
const activeCheckout = repository.checkouts.find((checkout) => checkout.checkoutId === repository.activeCheckoutId);
|
|
533
|
-
return {
|
|
534
|
-
detailLevel: 'summary',
|
|
535
|
-
repository: {
|
|
536
|
-
...repositorySummary(repository),
|
|
537
|
-
activeCheckoutId: repository.activeCheckoutId,
|
|
538
|
-
...(activeCheckout ? { activeCheckout } : {}),
|
|
539
|
-
checkoutCount: repository.checkouts.length,
|
|
540
|
-
checkoutCounts,
|
|
541
|
-
},
|
|
542
|
-
omittedCheckoutCount: Math.max(0, repository.checkouts.length - (activeCheckout ? 1 : 0)),
|
|
543
|
-
next: 'Re-call with detail_level=detail only when complete checkout history is required.',
|
|
544
|
-
};
|
|
545
|
-
}
|
|
546
|
-
|
|
547
|
-
function failure(error: unknown): RepositoryToolResult {
|
|
548
|
-
const message = compactErrorMessage(error);
|
|
549
|
-
const code = message.includes(':') ? message.slice(0, message.indexOf(':')) : 'REPOSITORY_TOOL_FAILED';
|
|
550
|
-
const details = typeof error === 'object' && error !== null && 'details' in error ? (error as { details?: unknown }).details : undefined;
|
|
551
|
-
const compactDetails = details !== undefined && Buffer.byteLength(JSON.stringify(details) ?? '', 'utf8') > RESPONSE_BUDGET.previewBytes
|
|
552
|
-
? { omitted: true, message: 'Error details exceeded budget; inspect job/artifact/result refs.' }
|
|
553
|
-
: details;
|
|
554
|
-
return { ...result({ error: { code, message, ...(compactDetails !== undefined ? { details: compactDetails } : {}) } }), isError: true };
|
|
555
|
-
}
|
|
556
|
-
|
|
557
|
-
interface RepositoryExplorationGuidance {
|
|
558
|
-
code: 'FRAGMENTED_REPOSITORY_EXPLORATION';
|
|
559
|
-
recommendedTool: 'rh_context';
|
|
560
|
-
recommendedOperation: 'search';
|
|
561
|
-
message: string;
|
|
562
|
-
}
|
|
563
|
-
|
|
564
|
-
function fragmentedRepositoryExplorationGuidance(command: unknown): RepositoryExplorationGuidance | undefined {
|
|
565
|
-
if (typeof command !== 'string') return undefined;
|
|
566
|
-
const segments = command.split(/(?:&&|\|\||[;|])/g);
|
|
567
|
-
const readPrograms = new Set<string>();
|
|
568
|
-
let readStepCount = 0;
|
|
569
|
-
for (const segment of segments) {
|
|
570
|
-
const match = segment.trim().match(/^(?:(?:command|env)\s+)?(?:[A-Za-z_][A-Za-z0-9_]*=[^\s]+\s+)*(rg|grep|sed|cat|head|tail)\b/i);
|
|
571
|
-
if (!match) continue;
|
|
572
|
-
readStepCount += 1;
|
|
573
|
-
readPrograms.add(match[1]!.toLowerCase());
|
|
574
|
-
}
|
|
575
|
-
if (readStepCount < 2) return undefined;
|
|
576
|
-
return {
|
|
577
|
-
code: 'FRAGMENTED_REPOSITORY_EXPLORATION',
|
|
578
|
-
recommendedTool: 'rh_context',
|
|
579
|
-
recommendedOperation: 'search',
|
|
580
|
-
message: `Detected ${readStepCount} chained repository read steps (${[...readPrograms].join(', ')}). Prefer a broad rh_context request first, then repeat rh_context with selected paths or relationships when more evidence can improve correctness; keep shell search as fallback when the Context Plane cannot supply the needed evidence.`,
|
|
581
|
-
};
|
|
582
|
-
}
|
|
583
|
-
|
|
584
|
-
function compactProcessCommandPayload(input: {
|
|
585
|
-
accepted?: boolean;
|
|
586
|
-
mode: string;
|
|
587
|
-
path: string;
|
|
588
|
-
route?: string;
|
|
589
|
-
reasons: string[];
|
|
590
|
-
decision?: unknown;
|
|
591
|
-
repoId: string;
|
|
592
|
-
checkoutId?: string;
|
|
593
|
-
workspace?: { workspaceId: string; root: string; registered: false };
|
|
594
|
-
historicalWorkContext?: HistoricalReadOnlyWorkContext;
|
|
595
|
-
processId?: string;
|
|
596
|
-
process?: unknown;
|
|
597
|
-
completed?: boolean;
|
|
598
|
-
ok?: boolean;
|
|
599
|
-
exitCode?: number | null;
|
|
600
|
-
stdout?: string;
|
|
601
|
-
stderr?: string;
|
|
602
|
-
durableSideEffects?: Record<string, number>;
|
|
603
|
-
next: string;
|
|
604
|
-
/** summary (default) omits nested process / routing dumps; detail restores diagnostics. */
|
|
605
|
-
detailLevel?: 'summary' | 'detail';
|
|
606
|
-
includeFullProcess?: boolean;
|
|
607
|
-
guidance?: RepositoryExplorationGuidance;
|
|
608
|
-
}): Record<string, unknown> {
|
|
609
|
-
const output = compactCommandOutput(input.stdout, input.stderr, { ok: input.ok === true });
|
|
610
|
-
const detail = input.detailLevel === 'detail' || input.includeFullProcess === true;
|
|
611
|
-
const effects = input.durableSideEffects ?? {
|
|
612
|
-
executionJobCount: 0,
|
|
613
|
-
localJobCount: 0,
|
|
614
|
-
workerSpawnCount: 0,
|
|
615
|
-
projectionUpdateCount: 0,
|
|
616
|
-
};
|
|
617
|
-
const reason = input.reasons[0] ?? 'readonly_fast_path';
|
|
618
|
-
|
|
619
|
-
// Default success/failure: one authoritative stdout/stderr pair, no nested process dump.
|
|
620
|
-
if (!detail) {
|
|
621
|
-
const completed = input.completed !== false;
|
|
622
|
-
const ok = input.ok === true;
|
|
623
|
-
const payload: Record<string, unknown> = {
|
|
624
|
-
...(completed ? { ok } : {}),
|
|
625
|
-
accepted: input.accepted ?? true,
|
|
626
|
-
mode: input.mode,
|
|
627
|
-
path: input.path,
|
|
628
|
-
route: input.route ?? input.path,
|
|
629
|
-
reason,
|
|
630
|
-
repoId: input.repoId,
|
|
631
|
-
...(input.checkoutId ? { checkoutId: input.checkoutId } : {}),
|
|
632
|
-
...(input.workspace ? { workspace: input.workspace } : {}),
|
|
633
|
-
...(input.historicalWorkContext ? { historicalWorkContext: input.historicalWorkContext } : {}),
|
|
634
|
-
...(input.processId ? { processId: input.processId } : {}),
|
|
635
|
-
...(completed ? { exitCode: input.exitCode ?? (ok ? 0 : 1) } : {}),
|
|
636
|
-
// A running default response otherwise loses its only dependency-bound
|
|
637
|
-
// continuation advice when the detailed Process record is omitted.
|
|
638
|
-
...(!completed ? { next: input.next } : {}),
|
|
639
|
-
stdout: output.stdout ?? '',
|
|
640
|
-
stderr: output.stderr ?? '',
|
|
641
|
-
...(output.stdoutTruncated ? { stdoutTruncated: true, stdoutBytes: output.stdoutBytes } : {}),
|
|
642
|
-
...(output.stderrTruncated ? { stderrTruncated: true, stderrBytes: output.stderrBytes } : {}),
|
|
643
|
-
...(input.guidance ? { guidance: input.guidance, suggestedOperation: 'rh_context' } : {}),
|
|
644
|
-
};
|
|
645
|
-
if (completed && !ok) {
|
|
646
|
-
payload.error = {
|
|
647
|
-
code: 'PROCESS_COMMAND_FAILED',
|
|
648
|
-
message: (output.stderr || 'process_direct command failed').slice(0, 800),
|
|
649
|
-
retryable: false,
|
|
650
|
-
exitCode: input.exitCode ?? 1,
|
|
651
|
-
};
|
|
652
|
-
}
|
|
653
|
-
// Zero side-effects are implicit for process_direct summary; only surface non-zero.
|
|
654
|
-
const nonZeroEffects = Object.fromEntries(
|
|
655
|
-
Object.entries(effects).filter(([, value]) => typeof value === 'number' && value > 0),
|
|
656
|
-
);
|
|
657
|
-
if (Object.keys(nonZeroEffects).length > 0) payload.durableSideEffects = nonZeroEffects;
|
|
658
|
-
return payload;
|
|
659
|
-
}
|
|
660
|
-
|
|
661
|
-
return {
|
|
662
|
-
accepted: input.accepted ?? true,
|
|
663
|
-
mode: input.mode,
|
|
664
|
-
path: input.path,
|
|
665
|
-
route: input.route ?? input.path,
|
|
666
|
-
routing: {
|
|
667
|
-
...compactRoutingSummary({ path: input.path, mode: input.mode, reasons: input.reasons }),
|
|
668
|
-
...(input.decision ? { decision: input.decision } : {}),
|
|
669
|
-
},
|
|
670
|
-
reason,
|
|
671
|
-
repoId: input.repoId,
|
|
672
|
-
...(input.checkoutId ? { checkoutId: input.checkoutId } : {}),
|
|
673
|
-
...(input.workspace ? { workspace: input.workspace } : {}),
|
|
674
|
-
...(input.historicalWorkContext ? { historicalWorkContext: input.historicalWorkContext } : {}),
|
|
675
|
-
...(input.processId ? { processId: input.processId } : {}),
|
|
676
|
-
ok: input.ok,
|
|
677
|
-
exitCode: input.exitCode,
|
|
678
|
-
...output,
|
|
679
|
-
// Nested process only in detail mode; never duplicate stdout/stderr there.
|
|
680
|
-
...(input.process && typeof input.process === 'object'
|
|
681
|
-
? {
|
|
682
|
-
process: (() => {
|
|
683
|
-
const record = { ...(input.process as Record<string, unknown>) };
|
|
684
|
-
delete record.stdout;
|
|
685
|
-
delete record.stderr;
|
|
686
|
-
delete record.durableSideEffects;
|
|
687
|
-
return record;
|
|
688
|
-
})(),
|
|
689
|
-
}
|
|
690
|
-
: {}),
|
|
691
|
-
durableSideEffects: effects,
|
|
692
|
-
...(input.guidance ? { guidance: input.guidance, suggestedOperation: 'rh_context' } : {}),
|
|
693
|
-
next: input.next,
|
|
694
|
-
detailLevel: 'detail',
|
|
695
|
-
};
|
|
696
|
-
}
|
|
697
|
-
|
|
698
|
-
function emptyRepositoryMigration(repository: ReturnType<typeof registerRepository>) {
|
|
699
|
-
return {
|
|
700
|
-
repoId: repository.repoId,
|
|
701
|
-
checkoutId: repository.activeCheckoutId,
|
|
702
|
-
scanned: 0,
|
|
703
|
-
updated: 0,
|
|
704
|
-
unresolved: 0,
|
|
705
|
-
files: [] as string[],
|
|
706
|
-
errors: [] as Array<{ path: string; error: string }>,
|
|
707
|
-
};
|
|
708
|
-
}
|
|
709
|
-
|
|
710
|
-
function registrationOnlyMetadataRefresh(
|
|
711
|
-
match: ReturnType<typeof findIdenticalRepositoryRegistration>,
|
|
712
|
-
): boolean {
|
|
713
|
-
if (!match || match.identical || match.reasons.length === 0) return false;
|
|
714
|
-
const metadataReasons = new Set([
|
|
715
|
-
'remote_identity_changed',
|
|
716
|
-
'default_branch_changed',
|
|
717
|
-
'display_name_changed',
|
|
718
|
-
]);
|
|
719
|
-
return match.reasons.every((reason) => metadataReasons.has(reason));
|
|
720
|
-
}
|
|
721
|
-
|
|
722
|
-
function registrationOnlyAttachedExistingWorktree(repository: ReturnType<typeof registerRepository>): boolean {
|
|
723
|
-
const selected = repository.checkouts.find((checkout) => checkout.checkoutId === repository.activeCheckoutId);
|
|
724
|
-
return selected?.worktree === true
|
|
725
|
-
&& repository.checkouts.some((checkout) => checkout.checkoutId !== selected.checkoutId);
|
|
726
|
-
}
|
|
727
|
-
|
|
728
|
-
export async function callRepositoryTool(
|
|
729
|
-
controllerHome: string,
|
|
730
|
-
name: string,
|
|
731
|
-
args: Record<string, unknown>,
|
|
732
|
-
caller?: RepositoryToolCallerContext,
|
|
733
|
-
): Promise<RepositoryToolResult | undefined> {
|
|
734
|
-
if (!name.startsWith('repository_') && name !== 'read_repository_file') return undefined;
|
|
735
|
-
try {
|
|
736
|
-
const repoIdValue = typeof args.repo_id === 'string' ? args.repo_id.trim() : '';
|
|
737
|
-
switch (name) {
|
|
738
|
-
case 'read_repository_file': {
|
|
739
|
-
const repository = resolveRepositorySelection({
|
|
740
|
-
repoId: typeof args.repo_id === 'string' ? args.repo_id : undefined,
|
|
741
|
-
checkoutId: typeof args.checkout_id === 'string' ? args.checkout_id : undefined,
|
|
742
|
-
controllerHome,
|
|
743
|
-
allowSoleRepository: true,
|
|
744
|
-
});
|
|
745
|
-
const path = String(args.path ?? '').trim();
|
|
746
|
-
if (!path) throw new Error('REPOSITORY_PATH_REQUIRED: path is required');
|
|
747
|
-
const session = caller?.sessionId
|
|
748
|
-
? { sessionId: caller.sessionId, repoId: repository.repoId, checkoutId: repository.activeCheckoutId }
|
|
749
|
-
: undefined;
|
|
750
|
-
const range = readRepositoryRange(
|
|
751
|
-
repository.canonicalRoot,
|
|
752
|
-
getMcpPolicy('controller', { repoRoot: repository.canonicalRoot }),
|
|
753
|
-
path,
|
|
754
|
-
typeof args.start_line === 'number' ? args.start_line : 1,
|
|
755
|
-
typeof args.end_line === 'number' ? args.end_line : 200,
|
|
756
|
-
session,
|
|
757
|
-
);
|
|
758
|
-
const redacted = redactMcpText(range.content);
|
|
759
|
-
return result({ ...range, content: redacted.text, redactions: redacted.redactions });
|
|
760
|
-
}
|
|
761
|
-
case 'repository_register': {
|
|
762
|
-
const startedAt = performance.now();
|
|
763
|
-
const registerInput = {
|
|
764
|
-
path: String(args.path ?? ''),
|
|
765
|
-
controllerHome,
|
|
766
|
-
displayName: typeof args.display_name === 'string' ? args.display_name : undefined,
|
|
767
|
-
remoteUrl: typeof args.remote_url === 'string' ? args.remote_url : undefined,
|
|
768
|
-
defaultBranch: typeof args.default_branch === 'string' ? args.default_branch : undefined,
|
|
769
|
-
};
|
|
770
|
-
const identical = findIdenticalRepositoryRegistration(registerInput);
|
|
771
|
-
if (identical?.identical) {
|
|
772
|
-
const repository = identical.repository;
|
|
773
|
-
// Repeat registration with identical identity returns immediately.
|
|
774
|
-
// No legacy migration / edit-session migration / historical issue
|
|
775
|
-
// scan / old issue rebinding runs on this hot path.
|
|
776
|
-
const migration = emptyRepositoryMigration(repository);
|
|
777
|
-
return result(withResponseMeta(
|
|
778
|
-
summarizeRepositoryRegistration(repository, migration, args.detail_level === 'detail', true),
|
|
779
|
-
startedAt,
|
|
780
|
-
));
|
|
781
|
-
}
|
|
782
|
-
const metadataRefresh = registrationOnlyMetadataRefresh(identical);
|
|
783
|
-
const repository = registerRepository(registerInput);
|
|
784
|
-
// Adding a worktree checkout or changing only display/remote/default-branch
|
|
785
|
-
// metadata preserves repository + checkout authority. Existing entities
|
|
786
|
-
// are already bound to the stable repoId, so a historical migration scan
|
|
787
|
-
// would only add latency and stale unresolved diagnostics.
|
|
788
|
-
const migration = registrationOnlyAttachedExistingWorktree(repository) || metadataRefresh
|
|
789
|
-
? emptyRepositoryMigration(repository)
|
|
790
|
-
: bindRepositoryEntities(repository);
|
|
791
|
-
return result(withResponseMeta(
|
|
792
|
-
summarizeRepositoryRegistration(repository, migration, args.detail_level === 'detail', metadataRefresh),
|
|
793
|
-
startedAt,
|
|
794
|
-
));
|
|
795
|
-
}
|
|
796
|
-
case 'repository_latest_source_diagnose':
|
|
797
|
-
return result({
|
|
798
|
-
diagnosis: diagnoseLatestLocalProjectSource({
|
|
799
|
-
path: typeof args.path === 'string' ? args.path : undefined,
|
|
800
|
-
repoId: typeof args.repo_id === 'string' ? args.repo_id : undefined,
|
|
801
|
-
controllerHome,
|
|
802
|
-
}),
|
|
803
|
-
});
|
|
804
|
-
case 'repository_bootstrap_local_project':
|
|
805
|
-
return result({
|
|
806
|
-
bootstrap: bootstrapLocalProject({
|
|
807
|
-
path: String(args.path ?? ''),
|
|
808
|
-
controllerHome,
|
|
809
|
-
displayName: typeof args.display_name === 'string' ? args.display_name : undefined,
|
|
810
|
-
defaultBranch: typeof args.default_branch === 'string' ? args.default_branch : undefined,
|
|
811
|
-
mode: typeof args.mode === 'string' ? args.mode as 'init_git_only' | 'init_git_and_register' | 'replace_registration' : undefined,
|
|
812
|
-
replaceRegisteredRepoId: typeof args.replace_registered_repo_id === 'string' ? args.replace_registered_repo_id : undefined,
|
|
813
|
-
confirmAuthorization: args.confirm_authorization === true,
|
|
814
|
-
}),
|
|
815
|
-
});
|
|
816
|
-
case 'repository_list':
|
|
817
|
-
return result({ repositories: listRepositories(controllerHome, { includeRemoved: args.include_removed === true }).map(repositorySummary) });
|
|
818
|
-
case 'repository_get': {
|
|
819
|
-
// Repository inspection is also the bounded reconciliation point for
|
|
820
|
-
// checkout lifecycle drift caused by worktrees being removed outside
|
|
821
|
-
// Forge. Reuse the existing registry reconciler so stale worktrees are
|
|
822
|
-
// not exposed as lifecycle=active to automation callers.
|
|
823
|
-
reconcileRepositoryCheckouts(repoIdValue, controllerHome);
|
|
824
|
-
const repository = getRepository(repoIdValue, controllerHome, { includeRemoved: args.include_removed === true });
|
|
825
|
-
return result(summarizeRepositoryInspection(repository, args.detail_level === 'detail'));
|
|
826
|
-
}
|
|
827
|
-
case 'repository_validate': {
|
|
828
|
-
const startedAt = performance.now();
|
|
829
|
-
const repository = getRepository(repoIdValue, controllerHome, { includeRemoved: true });
|
|
830
|
-
const payload = {
|
|
831
|
-
detailLevel: args.detail_level === 'detail' ? 'detail' : 'summary',
|
|
832
|
-
validation: validateRepository(repoIdValue, controllerHome),
|
|
833
|
-
migration: summarizeEntityMigrationReport(bindRepositoryEntities(repository), args.detail_level === 'detail'),
|
|
834
|
-
};
|
|
835
|
-
return result(withResponseMeta(payload, startedAt));
|
|
836
|
-
}
|
|
837
|
-
case 'repository_refresh': {
|
|
838
|
-
const startedAt = performance.now();
|
|
839
|
-
const repository = refreshRepository(repoIdValue, controllerHome);
|
|
840
|
-
const migration = bindRepositoryEntities(repository);
|
|
841
|
-
return result(withResponseMeta(
|
|
842
|
-
summarizeRepositoryRegistration(repository, migration, args.detail_level === 'detail'),
|
|
843
|
-
startedAt,
|
|
844
|
-
));
|
|
845
|
-
}
|
|
846
|
-
case 'repository_update':
|
|
847
|
-
return result({ repository: updateRepository(repoIdValue, {
|
|
848
|
-
displayName: typeof args.display_name === 'string' ? args.display_name : undefined,
|
|
849
|
-
defaultBranch: typeof args.default_branch === 'string' ? args.default_branch : undefined,
|
|
850
|
-
enabled: typeof args.enabled === 'boolean' ? args.enabled : undefined,
|
|
851
|
-
}, controllerHome) });
|
|
852
|
-
case 'repository_disable':
|
|
853
|
-
return result({ repository: disableRepository(repoIdValue, controllerHome) });
|
|
854
|
-
case 'repository_remove':
|
|
855
|
-
return result({ repository: removeRepository(repoIdValue, controllerHome) });
|
|
856
|
-
case 'repository_workbench': {
|
|
857
|
-
const operation = typeof args.operation === 'string' ? args.operation : 'summary';
|
|
858
|
-
if (operation === 'summary') {
|
|
859
|
-
return result({ workbench: buildControllerWorkbench(controllerHome, {
|
|
860
|
-
repoId: repoIdValue || undefined,
|
|
861
|
-
includeRemoved: args.include_removed === true,
|
|
862
|
-
}) });
|
|
863
|
-
}
|
|
864
|
-
const payload = typeof args.payload === 'object' && args.payload !== null
|
|
865
|
-
? args.payload as Record<string, unknown>
|
|
866
|
-
: {};
|
|
867
|
-
if (operation === 'assess_work_mode') {
|
|
868
|
-
const description = typeof payload.description === 'string'
|
|
869
|
-
? payload.description
|
|
870
|
-
: typeof args.description === 'string' ? args.description : '';
|
|
871
|
-
const assessment = assessWorkMode({
|
|
872
|
-
description,
|
|
873
|
-
knownPaths: Array.isArray(payload.known_paths) ? payload.known_paths.map(String) : undefined,
|
|
874
|
-
expectedFiles: typeof payload.expected_files === 'number' ? payload.expected_files : undefined,
|
|
875
|
-
expectedChangedLines: typeof payload.expected_changed_lines === 'number' ? payload.expected_changed_lines : undefined,
|
|
876
|
-
requiresInvestigation: payload.requires_investigation === true,
|
|
877
|
-
requiresParallelism: payload.requires_parallelism === true,
|
|
878
|
-
requiresLongRunningChecks: payload.requires_long_running_checks === true,
|
|
879
|
-
needsDependencies: payload.needs_dependencies === true,
|
|
880
|
-
requiresIndependentDeliverables: payload.requires_independent_deliverables === true,
|
|
881
|
-
independentTaskCount: typeof payload.independent_task_count === 'number' ? payload.independent_task_count : undefined,
|
|
882
|
-
requiresRemoteWrite: payload.requires_remote_write === true || payload.remote_write === true,
|
|
883
|
-
requiresRecovery: payload.requires_recovery === true,
|
|
884
|
-
agentRequested: payload.agent_requested === true || payload.requires_worker === true,
|
|
885
|
-
requiresWorkerIsolation: payload.requires_worker_isolation === true,
|
|
886
|
-
risk: typeof payload.risk === 'string' ? payload.risk as 'low' | 'medium' | 'high' | 'destructive' : undefined,
|
|
887
|
-
explicitMode: parseExplicitTaskMode(payload.mode),
|
|
888
|
-
});
|
|
889
|
-
return result({
|
|
890
|
-
assessment,
|
|
891
|
-
routing: {
|
|
892
|
-
path: assessment.executionPath,
|
|
893
|
-
reasons: assessment.reasons,
|
|
894
|
-
recommendedMode: assessment.recommendedMode,
|
|
895
|
-
issueRequired: assessment.issueRequired,
|
|
896
|
-
},
|
|
897
|
-
nextTools: assessment.nextTools,
|
|
898
|
-
});
|
|
899
|
-
}
|
|
900
|
-
const internalTool = {
|
|
901
|
-
batch_execute: 'repository_batch_execute',
|
|
902
|
-
lanes_execute: 'repository_lanes_execute',
|
|
903
|
-
lanes_integrate: 'repository_lanes_integrate',
|
|
904
|
-
fast_receipt_get: 'repository_fast_receipt_get',
|
|
905
|
-
fast_receipt_list: 'repository_fast_receipt_list',
|
|
906
|
-
execution_route: 'repository_execution_route',
|
|
907
|
-
}[operation];
|
|
908
|
-
if (!internalTool) {
|
|
909
|
-
return failure(new Error(`REPOSITORY_WORKBENCH_OPERATION_INVALID: ${operation}`));
|
|
910
|
-
}
|
|
911
|
-
return callRepositoryTool(controllerHome, internalTool, {
|
|
912
|
-
...payload,
|
|
913
|
-
repo_id: repoIdValue || payload.repo_id,
|
|
914
|
-
checkout_id: typeof args.checkout_id === 'string' ? args.checkout_id : payload.checkout_id,
|
|
915
|
-
});
|
|
916
|
-
}
|
|
917
|
-
case 'repository_git_status': {
|
|
918
|
-
const repository = resolveRepositorySelection({ repoId: repoIdValue || undefined, checkoutId: typeof args.checkout_id === 'string' ? args.checkout_id : undefined, controllerHome, allowSoleRepository: true });
|
|
919
|
-
const status = args.refresh === true
|
|
920
|
-
? writeRepositoryGitStatusSample(controllerHome, repository)
|
|
921
|
-
: readRepositoryGitStatusSample(controllerHome, repository.repoId, repository.activeCheckoutId);
|
|
922
|
-
return result({
|
|
923
|
-
status: status ?? {
|
|
924
|
-
repoId: repository.repoId,
|
|
925
|
-
checkoutId: repository.activeCheckoutId,
|
|
926
|
-
sampleSource: 'daemon-sample',
|
|
927
|
-
sampled: false,
|
|
928
|
-
observedAt: null,
|
|
929
|
-
staleAgeMs: null,
|
|
930
|
-
message: 'Git status has not been sampled by the Forge Runtime yet. Retry after scheduler heartbeat or call with refresh=true for an explicit live refresh.',
|
|
931
|
-
},
|
|
932
|
-
});
|
|
933
|
-
}
|
|
934
|
-
|
|
935
|
-
case 'repository_git_diff': {
|
|
936
|
-
const repository = resolveRepositorySelection({ repoId: repoIdValue || undefined, checkoutId: typeof args.checkout_id === 'string' ? args.checkout_id : undefined, controllerHome, allowSoleRepository: true });
|
|
937
|
-
return result({ diff: repositoryGitDiff(repository, { staged: args.staged, paths: args.paths, maxBytes: args.max_bytes }) });
|
|
938
|
-
}
|
|
939
|
-
case 'repository_git_create_branch': {
|
|
940
|
-
const repository = resolveRepositorySelection({ repoId: repoIdValue || undefined, checkoutId: typeof args.checkout_id === 'string' ? args.checkout_id : undefined, controllerHome, allowSoleRepository: true });
|
|
941
|
-
return result({ repoId: repository.repoId, checkoutId: repository.activeCheckoutId, ...repositoryGitCreateBranch(controllerHome, repository, { branch: args.branch, startPoint: args.start_point, switchTo: args.switch_to }) as unknown as Record<string, unknown> });
|
|
942
|
-
}
|
|
943
|
-
case 'repository_git_switch_branch': {
|
|
944
|
-
const repository = resolveRepositorySelection({ repoId: repoIdValue || undefined, checkoutId: typeof args.checkout_id === 'string' ? args.checkout_id : undefined, controllerHome, allowSoleRepository: true });
|
|
945
|
-
return result({ repoId: repository.repoId, checkoutId: repository.activeCheckoutId, ...repositoryGitSwitchBranch(controllerHome, repository, { branch: args.branch }) as unknown as Record<string, unknown> });
|
|
946
|
-
}
|
|
947
|
-
case 'repository_git_merge_branch': {
|
|
948
|
-
const repository = resolveRepositorySelection({ repoId: repoIdValue || undefined, checkoutId: typeof args.checkout_id === 'string' ? args.checkout_id : undefined, controllerHome, allowSoleRepository: true });
|
|
949
|
-
return result({ repoId: repository.repoId, checkoutId: repository.activeCheckoutId, ...repositoryGitMergeBranch(controllerHome, repository, { branch: args.branch, noFf: args.no_ff }) as unknown as Record<string, unknown> });
|
|
950
|
-
}
|
|
951
|
-
case 'repository_git_delete_branch': {
|
|
952
|
-
const repository = resolveRepositorySelection({ repoId: repoIdValue || undefined, checkoutId: typeof args.checkout_id === 'string' ? args.checkout_id : undefined, controllerHome, allowSoleRepository: true });
|
|
953
|
-
return result({ repoId: repository.repoId, checkoutId: repository.activeCheckoutId, ...repositoryGitDeleteBranch(controllerHome, repository, { branch: args.branch, force: args.force }) as unknown as Record<string, unknown> });
|
|
954
|
-
}
|
|
955
|
-
|
|
956
|
-
case 'repository_git_commit': {
|
|
957
|
-
const repository = resolveRepositorySelection({ repoId: repoIdValue || undefined, checkoutId: typeof args.checkout_id === 'string' ? args.checkout_id : undefined, controllerHome, allowSoleRepository: true });
|
|
958
|
-
return result({ commit: repositoryGitCommit(controllerHome, repository, { message: args.message, paths: args.paths, allowEmpty: args.allow_empty }) });
|
|
959
|
-
}
|
|
960
|
-
case 'repository_git_finish_workflow': {
|
|
961
|
-
const repository = resolveRepositorySelection({ repoId: repoIdValue || undefined, checkoutId: typeof args.checkout_id === 'string' ? args.checkout_id : undefined, controllerHome, allowSoleRepository: true });
|
|
962
|
-
return result({ finish: repositoryGitFinishWorkflow(controllerHome, repository, { featureBranch: args.feature_branch, targetBranch: args.target_branch, deleteBranch: args.delete_branch, noFf: args.no_ff }) });
|
|
963
|
-
}
|
|
964
|
-
case 'repository_safe_patch_plan': {
|
|
965
|
-
const repository = resolveRepositorySelection({
|
|
966
|
-
repoId: repoIdValue || undefined,
|
|
967
|
-
checkoutId: typeof args.checkout_id === 'string' ? args.checkout_id : undefined,
|
|
968
|
-
controllerHome,
|
|
969
|
-
allowSoleRepository: true,
|
|
970
|
-
});
|
|
971
|
-
return result({
|
|
972
|
-
repoId: repository.repoId,
|
|
973
|
-
checkoutId: repository.activeCheckoutId,
|
|
974
|
-
plan: buildSafePatchPlan(repository, { operations: args.operations, chunkSize: args.chunk_size }),
|
|
975
|
-
});
|
|
976
|
-
}
|
|
977
|
-
case 'repository_safe_patch_apply': {
|
|
978
|
-
const repository = resolveRepositorySelectionForClaimedWork(controllerHome, args, repoIdValue, caller);
|
|
979
|
-
const binding = safePatchEditBinding(controllerHome, repository, caller, args);
|
|
980
|
-
if (binding?.workId) {
|
|
981
|
-
const work = getWorkContract({ controllerHome, repoId: repository.repoId }, binding.workId);
|
|
982
|
-
if (!work) throw new Error(`WORK_NOT_FOUND: ${binding.workId}`);
|
|
983
|
-
const requestedPaths = buildSafePatchPlan(repository, { operations: args.operations, chunkSize: args.chunk_size })
|
|
984
|
-
.chunks.flatMap((chunk) => chunk.paths);
|
|
985
|
-
assertWorkPathsWithinScope(work, requestedPaths, {
|
|
986
|
-
forbidden: 'WORK_MUTATION_FORBIDDEN_PATH',
|
|
987
|
-
outOfScope: 'WORK_MUTATION_PATH_OUT_OF_SCOPE',
|
|
988
|
-
});
|
|
989
|
-
}
|
|
990
|
-
const applied = withControllerLock(
|
|
991
|
-
controllerHome,
|
|
992
|
-
{ scope: 'repository', repoId: repository.repoId },
|
|
993
|
-
'mcp:repository_safe_patch_apply',
|
|
994
|
-
() => {
|
|
995
|
-
if (binding?.workId) {
|
|
996
|
-
ensureRepositoryMutationWorkHandle({
|
|
997
|
-
controllerHome,
|
|
998
|
-
repository,
|
|
999
|
-
workId: binding.workId,
|
|
1000
|
-
principalId: binding.principalId ?? caller?.principalId ?? '',
|
|
1001
|
-
});
|
|
1002
|
-
}
|
|
1003
|
-
return applySafePatch(repository, {
|
|
1004
|
-
sessionId: args.session_id,
|
|
1005
|
-
purpose: args.purpose,
|
|
1006
|
-
operations: args.operations,
|
|
1007
|
-
chunkSize: args.chunk_size,
|
|
1008
|
-
expectedRevision: args.expected_revision,
|
|
1009
|
-
allowedPaths: args.allowed_paths,
|
|
1010
|
-
continueOnError: args.continue_on_error,
|
|
1011
|
-
refreshFingerprints: args.refresh_fingerprints,
|
|
1012
|
-
recoverStaleSession: args.recover_stale_session,
|
|
1013
|
-
binding,
|
|
1014
|
-
});
|
|
1015
|
-
},
|
|
1016
|
-
60_000,
|
|
1017
|
-
);
|
|
1018
|
-
const changedFiles = [
|
|
1019
|
-
...new Set(
|
|
1020
|
-
(applied.appliedChunks ?? []).flatMap((chunk) => chunk.paths ?? []),
|
|
1021
|
-
),
|
|
1022
|
-
];
|
|
1023
|
-
const ok = applied.status === 'applied';
|
|
1024
|
-
const firstFailure = applied.failures?.[0];
|
|
1025
|
-
const editDiff = applied.appliedChunks.length > 0
|
|
1026
|
-
? getEditSessionDiff(repository.canonicalRoot, applied.session.sessionId)
|
|
1027
|
-
: undefined;
|
|
1028
|
-
const boundedEditDiff = editDiff
|
|
1029
|
-
? boundUtf8(editDiff.patch, RESPONSE_BUDGET.inlineOutputBytes)
|
|
1030
|
-
: undefined;
|
|
1031
|
-
const reviewEvidence = editDiff && boundedEditDiff
|
|
1032
|
-
? {
|
|
1033
|
-
source: 'edit_session' as const,
|
|
1034
|
-
sessionId: editDiff.sessionId,
|
|
1035
|
-
revision: editDiff.revision,
|
|
1036
|
-
sha256: editDiff.sha256,
|
|
1037
|
-
patchPreview: boundedEditDiff.text,
|
|
1038
|
-
truncated: boundedEditDiff.truncated,
|
|
1039
|
-
byteLength: boundedEditDiff.byteLength,
|
|
1040
|
-
semanticReviewAuthority: 'chatgpt' as const,
|
|
1041
|
-
next: boundedEditDiff.truncated
|
|
1042
|
-
? 'The edit diff exceeds the inline budget. Expand only the affected ranges or diff needed for semantic review.'
|
|
1043
|
-
: 'Review this exact edit-session diff before deciding whether more edits or focused validation are needed.',
|
|
1044
|
-
}
|
|
1045
|
-
: undefined;
|
|
1046
|
-
const digest = buildSyncOperationDigest({
|
|
1047
|
-
ok,
|
|
1048
|
-
operation: 'repository_safe_patch_apply',
|
|
1049
|
-
summary: ok
|
|
1050
|
-
? `补丁已同步应用,涉及 ${changedFiles.length} 个文件。`
|
|
1051
|
-
: applied.status === 'partial'
|
|
1052
|
-
? `补丁部分应用:${changedFiles.length} 个文件成功,存在失败 chunk。`
|
|
1053
|
-
: `补丁应用失败:${firstFailure?.message || '请检查 failures 摘要'}`,
|
|
1054
|
-
changedFiles,
|
|
1055
|
-
errorClass: ok ? undefined : classifyUserFacingError({
|
|
1056
|
-
code: firstFailure?.code,
|
|
1057
|
-
message: firstFailure?.message,
|
|
1058
|
-
infrastructure: firstFailure?.code === 'APPLY_FAILED',
|
|
1059
|
-
}),
|
|
1060
|
-
errorMessage: firstFailure?.message,
|
|
1061
|
-
});
|
|
1062
|
-
const payload = {
|
|
1063
|
-
repoId: repository.repoId,
|
|
1064
|
-
checkoutId: repository.activeCheckoutId,
|
|
1065
|
-
...applied as unknown as Record<string, unknown>,
|
|
1066
|
-
phase: digest.phase,
|
|
1067
|
-
statusLabel: digest.statusLabel,
|
|
1068
|
-
summary: digest.summary,
|
|
1069
|
-
terminal: true,
|
|
1070
|
-
applyMode: 'sync',
|
|
1071
|
-
digest,
|
|
1072
|
-
...(reviewEvidence ? { reviewEvidence } : {}),
|
|
1073
|
-
suggestedNextActions: digest.suggestedNextActions,
|
|
1074
|
-
};
|
|
1075
|
-
return ok ? result(payload) : { ...result(payload), isError: true };
|
|
1076
|
-
}
|
|
1077
|
-
case 'repository_command_preview': {
|
|
1078
|
-
const target = resolveRepositoryCommandTarget(controllerHome, args, repoIdValue, caller);
|
|
1079
|
-
const { repository } = target;
|
|
1080
|
-
const execution = withControllerLock(
|
|
1081
|
-
controllerHome,
|
|
1082
|
-
{ scope: 'repository', repoId: repository.repoId },
|
|
1083
|
-
'mcp:repository_command_preview',
|
|
1084
|
-
() => executeRepositoryCommand(controllerHome, repository, {
|
|
1085
|
-
command: args.command as string | string[],
|
|
1086
|
-
cwd: typeof args.cwd === 'string' ? args.cwd : undefined,
|
|
1087
|
-
dryRun: true,
|
|
1088
|
-
allowNonGitWorkspace: target.workspace !== undefined,
|
|
1089
|
-
}),
|
|
1090
|
-
60_000,
|
|
1091
|
-
);
|
|
1092
|
-
return result({
|
|
1093
|
-
...execution as unknown as Record<string, unknown>,
|
|
1094
|
-
...(target.workspace ? { workspace: target.workspace } : {}),
|
|
1095
|
-
});
|
|
1096
|
-
}
|
|
1097
|
-
case 'repository_command_execute': {
|
|
1098
|
-
const explorationGuidance = fragmentedRepositoryExplorationGuidance(args.command);
|
|
1099
|
-
const target = resolveRepositoryCommandTarget(controllerHome, args, repoIdValue, caller);
|
|
1100
|
-
const { repository, executionIdentity, historicalWorkContext } = target;
|
|
1101
|
-
const explicitWorkId = typeof args.work_id === 'string' ? args.work_id.trim() : '';
|
|
1102
|
-
if (!explicitWorkId) assertNoBoundExecutionSessionMutation(controllerHome, repository, caller);
|
|
1103
|
-
const deliveryWorkId = rawDefaultBranchMergeCommand(repository, args.command)
|
|
1104
|
-
? executionIdentity.workId
|
|
1105
|
-
: undefined;
|
|
1106
|
-
if (deliveryWorkId) {
|
|
1107
|
-
throw new Error(`WORK_DELIVERY_REQUIRES_FINALIZE: ${deliveryWorkId} must pass Work verification and use rh_work finalize before default-branch integration`);
|
|
1108
|
-
}
|
|
1109
|
-
if (executionIdentity.workId) {
|
|
1110
|
-
const mutationClassification = classifyRepositoryCommand(args.command as string | string[], repository.defaultBranch);
|
|
1111
|
-
if (mutationClassification.risk === 'workspace_write' || mutationClassification.risk === 'destructive') {
|
|
1112
|
-
withControllerLock(
|
|
1113
|
-
controllerHome,
|
|
1114
|
-
{ scope: 'repository', repoId: repository.repoId },
|
|
1115
|
-
'mcp:repository_command_execute:mutation-authority',
|
|
1116
|
-
() => ensureRepositoryMutationWorkHandle({
|
|
1117
|
-
controllerHome,
|
|
1118
|
-
repository,
|
|
1119
|
-
workId: executionIdentity.workId!,
|
|
1120
|
-
principalId: caller?.principalId ?? '',
|
|
1121
|
-
}),
|
|
1122
|
-
60_000,
|
|
1123
|
-
);
|
|
1124
|
-
}
|
|
1125
|
-
}
|
|
1126
|
-
const timeoutMs = typeof args.timeout_ms === 'number'
|
|
1127
|
-
? args.timeout_ms
|
|
1128
|
-
: typeof args.timeout_ms === 'string'
|
|
1129
|
-
? Number(args.timeout_ms)
|
|
1130
|
-
: undefined;
|
|
1131
|
-
const maxOutputBytes = typeof args.max_output_bytes === 'number'
|
|
1132
|
-
? args.max_output_bytes
|
|
1133
|
-
: typeof args.max_output_bytes === 'string'
|
|
1134
|
-
? Number(args.max_output_bytes)
|
|
1135
|
-
: undefined;
|
|
1136
|
-
// Worker-owned durable executions must not re-enter Fast Path or create a
|
|
1137
|
-
// nested ExecutionJob. Local Job remains the worker settlement surface.
|
|
1138
|
-
const fromDurableWorker = args.__from_durable_worker === true
|
|
1139
|
-
|| typeof args.__execution_job_id === 'string';
|
|
1140
|
-
// Process Runtime owns local async execution. apply_mode=async means
|
|
1141
|
-
// return its Process handle immediately; it must not promote a local
|
|
1142
|
-
// command into the retired ExecutionJob path. Explicit mode=durable
|
|
1143
|
-
// remains a separate external-Controller boundary.
|
|
1144
|
-
const returnHandleImmediately = args.apply_mode === 'async'
|
|
1145
|
-
|| args.mode === 'async'
|
|
1146
|
-
|| args.async === true
|
|
1147
|
-
|| args.background === true;
|
|
1148
|
-
const forceDurable = fromDurableWorker
|
|
1149
|
-
|| args.mode === 'durable'
|
|
1150
|
-
|| args.force_durable === true;
|
|
1151
|
-
// repository_command_execute owns its command execution architecture.
|
|
1152
|
-
// Do not send ordinary command text through Thin Harness semantic risk
|
|
1153
|
-
// routing: that creates duplicate regex/classifier policy and turns
|
|
1154
|
-
// unknown CLI shapes into false durable/reject decisions. Only an
|
|
1155
|
-
// explicitly requested durable mode uses the generic durable router.
|
|
1156
|
-
const routingDecision = forceDurable
|
|
1157
|
-
? routeExecution({
|
|
1158
|
-
operation: 'repository_command_execute',
|
|
1159
|
-
mode: 'durable',
|
|
1160
|
-
timeoutMs,
|
|
1161
|
-
background: args.background === true || args.async === true,
|
|
1162
|
-
})
|
|
1163
|
-
: {
|
|
1164
|
-
mode: 'fast' as const,
|
|
1165
|
-
reasons: ['repository_command_process_runtime_authoritative'],
|
|
1166
|
-
risk: 'unknown' as const,
|
|
1167
|
-
estimatedClass: 'unknown' as const,
|
|
1168
|
-
requiresIsolation: false,
|
|
1169
|
-
requiresRecovery: false,
|
|
1170
|
-
suggestedOperation: undefined,
|
|
1171
|
-
effects: {
|
|
1172
|
-
readsWorkspace: true,
|
|
1173
|
-
mutatesWorkspace: true,
|
|
1174
|
-
mutatesGitRefs: false,
|
|
1175
|
-
remoteWrite: false,
|
|
1176
|
-
},
|
|
1177
|
-
};
|
|
1178
|
-
// Unified Process Runtime for local commands (Direct/Managed) when not forced durable.
|
|
1179
|
-
// Ephemeral workspaces cannot persist a recoverable async Process handle,
|
|
1180
|
-
// so their async requests remain promotion-required below.
|
|
1181
|
-
if (!forceDurable && !fromDurableWorker && !(target.workspace && returnHandleImmediately)) {
|
|
1182
|
-
try {
|
|
1183
|
-
const routeClass = classifyRepositoryCommandRoute(args.command as string | string[], {
|
|
1184
|
-
forceDurable: false,
|
|
1185
|
-
defaultBranch: repository.defaultBranch,
|
|
1186
|
-
timeoutMs,
|
|
1187
|
-
});
|
|
1188
|
-
if (routeClass.route === 'reject') {
|
|
1189
|
-
return result({
|
|
1190
|
-
accepted: false,
|
|
1191
|
-
mode: 'reject',
|
|
1192
|
-
path: routeClass.reason,
|
|
1193
|
-
route: 'reject',
|
|
1194
|
-
status: 'rejected',
|
|
1195
|
-
repoId: repository.repoId,
|
|
1196
|
-
checkoutId: repository.activeCheckoutId,
|
|
1197
|
-
workspace: target.workspace,
|
|
1198
|
-
message: routeClass.reason === 'standalone_recovery_lifecycle_required'
|
|
1199
|
-
? 'Canonical Runtime and connector lifecycle operations must be submitted to the standalone Forge Recovery owner, not executed as a child of repository Process Runtime.'
|
|
1200
|
-
: 'Repository command execution was rejected by Process Runtime routing policy.',
|
|
1201
|
-
suggestedOperation: routeClass.reason === 'standalone_recovery_lifecycle_required'
|
|
1202
|
-
? 'Use the standalone Forge Recovery connector.'
|
|
1203
|
-
: routingDecision.suggestedOperation,
|
|
1204
|
-
durableSideEffects: {
|
|
1205
|
-
executionJobCount: 0,
|
|
1206
|
-
localJobCount: 0,
|
|
1207
|
-
workerSpawnCount: 0,
|
|
1208
|
-
projectionUpdateCount: 0,
|
|
1209
|
-
},
|
|
1210
|
-
});
|
|
1211
|
-
}
|
|
1212
|
-
if (routeClass.route === 'durable' && target.workspace) {
|
|
1213
|
-
return result({
|
|
1214
|
-
accepted: false,
|
|
1215
|
-
mode: 'durable',
|
|
1216
|
-
path: 'ephemeral_workspace_promotion_required',
|
|
1217
|
-
repoId: repository.repoId,
|
|
1218
|
-
checkoutId: repository.activeCheckoutId,
|
|
1219
|
-
workspace: target.workspace,
|
|
1220
|
-
message: 'Ephemeral workspaces must be registered before durable remote effects so Process identity and reconciliation have a stable repository authority.',
|
|
1221
|
-
suggestedOperation: 'repository_register',
|
|
1222
|
-
});
|
|
1223
|
-
}
|
|
1224
|
-
if (routeClass.route === 'process_direct' || routeClass.route === 'process_managed' || routeClass.route === 'durable') {
|
|
1225
|
-
const processRequestId = typeof args.request_id === 'string' ? args.request_id.trim() : '';
|
|
1226
|
-
if (executionIdentity.workId && !processRequestId) {
|
|
1227
|
-
throw new Error(
|
|
1228
|
-
`WORK_PROCESS_REQUEST_ID_REQUIRED: ${executionIdentity.workId}; `
|
|
1229
|
-
+ 'Work-attributed Process Runtime commands require a stable request_id so reconnect/retry can resume the original Process without duplicate execution.',
|
|
1230
|
-
);
|
|
1231
|
-
}
|
|
1232
|
-
const processResult = await executeRepositoryCommandViaProcessRuntime({
|
|
1233
|
-
controllerHome,
|
|
1234
|
-
repository,
|
|
1235
|
-
command: args.command as string | string[],
|
|
1236
|
-
cwd: typeof args.cwd === 'string' ? args.cwd : undefined,
|
|
1237
|
-
timeoutMs,
|
|
1238
|
-
interactiveWaitMs: returnHandleImmediately
|
|
1239
|
-
? 0
|
|
1240
|
-
: typeof args.interactive_wait_ms === 'number' ? args.interactive_wait_ms : undefined,
|
|
1241
|
-
maxOutputBytes,
|
|
1242
|
-
returnHandleImmediately,
|
|
1243
|
-
requestId: processRequestId || undefined,
|
|
1244
|
-
workId: executionIdentity.workId,
|
|
1245
|
-
executionIdentity,
|
|
1246
|
-
allowNonGitWorkspace: target.workspace !== undefined,
|
|
1247
|
-
});
|
|
1248
|
-
if (processResult.route === 'process_direct' || processResult.route === 'process_managed') {
|
|
1249
|
-
const handle = processResult.process;
|
|
1250
|
-
const detailLevel = args.detail_level === 'detail' || args.detail === true
|
|
1251
|
-
? 'detail'
|
|
1252
|
-
: 'summary';
|
|
1253
|
-
const directWithoutHandle = processResult.route === 'process_direct' && !handle;
|
|
1254
|
-
const directNotExecuted = directWithoutHandle
|
|
1255
|
-
&& processResult.executionStatus !== undefined
|
|
1256
|
-
&& processResult.executionStatus !== 'executed';
|
|
1257
|
-
if (directNotExecuted) {
|
|
1258
|
-
const authorization = processResult.authorizationDecision ?? {
|
|
1259
|
-
decision: 'deny' as const,
|
|
1260
|
-
reason: 'Command was not executed because the required authorization was not satisfied.',
|
|
1261
|
-
};
|
|
1262
|
-
return result({
|
|
1263
|
-
accepted: false,
|
|
1264
|
-
mode: processResult.route,
|
|
1265
|
-
path: processResult.reason ?? routeClass.reason,
|
|
1266
|
-
route: processResult.route,
|
|
1267
|
-
repoId: repository.repoId,
|
|
1268
|
-
checkoutId: repository.activeCheckoutId,
|
|
1269
|
-
workspace: target.workspace,
|
|
1270
|
-
status: processResult.executionStatus,
|
|
1271
|
-
policyDecision: processResult.policyDecision ?? 'approval_required',
|
|
1272
|
-
authorization,
|
|
1273
|
-
...(processResult.approvalRequestId ? { approvalRequestId: processResult.approvalRequestId } : {}),
|
|
1274
|
-
message: authorization.decision === 'user_confirmation_required'
|
|
1275
|
-
? authorization.humanSummary
|
|
1276
|
-
: authorization.reason,
|
|
1277
|
-
suggestedOperation: 'repository_command_preview',
|
|
1278
|
-
});
|
|
1279
|
-
}
|
|
1280
|
-
const completed = directWithoutHandle || handle?.completed === true;
|
|
1281
|
-
const status = directWithoutHandle
|
|
1282
|
-
? (processResult.ok === true ? 'succeeded' : 'failed')
|
|
1283
|
-
: !handle
|
|
1284
|
-
? 'rejected'
|
|
1285
|
-
: completed
|
|
1286
|
-
? (handle.cancelled ? 'cancelled' : handle.timedOut ? 'timed_out' : processResult.ok === true ? 'succeeded' : 'failed')
|
|
1287
|
-
: 'running';
|
|
1288
|
-
const payload = compactProcessCommandPayload({
|
|
1289
|
-
accepted: true,
|
|
1290
|
-
mode: processResult.route,
|
|
1291
|
-
path: processResult.route,
|
|
1292
|
-
route: processResult.route,
|
|
1293
|
-
reasons: [processResult.reason ?? routeClass.reason, ...routingDecision.reasons],
|
|
1294
|
-
decision: detailLevel === 'detail' ? routingDecision : undefined,
|
|
1295
|
-
repoId: repository.repoId,
|
|
1296
|
-
checkoutId: repository.activeCheckoutId,
|
|
1297
|
-
workspace: target.workspace,
|
|
1298
|
-
historicalWorkContext,
|
|
1299
|
-
processId: handle?.processId,
|
|
1300
|
-
process: detailLevel === 'detail' ? handle : undefined,
|
|
1301
|
-
completed,
|
|
1302
|
-
ok: completed ? processResult.ok : undefined,
|
|
1303
|
-
exitCode: completed ? processResult.exitCode : undefined,
|
|
1304
|
-
stdout: processResult.stdout,
|
|
1305
|
-
stderr: processResult.stderr,
|
|
1306
|
-
durableSideEffects: processResult.durableSideEffects,
|
|
1307
|
-
guidance: explorationGuidance,
|
|
1308
|
-
next: directWithoutHandle
|
|
1309
|
-
? processResult.reason === 'readonly_fast_path'
|
|
1310
|
-
? 'Bounded readonly execution completed without Process record / Lease / Local Job / ExecutionJob / Worker.'
|
|
1311
|
-
: 'Bounded ephemeral workspace execution completed without Process record / Lease / Local Job / ExecutionJob / Worker.'
|
|
1312
|
-
: processResult.route === 'process_direct' || completed
|
|
1313
|
-
? 'Process Runtime completed without Local Job / ExecutionJob / Worker.'
|
|
1314
|
-
: `Process Runtime is managing ${handle?.processId}. Continue independent work; use process_get only if an observation can change the next decision, then join with process_wait when this result becomes a dependency. Do not re-run or periodically poll.`,
|
|
1315
|
-
detailLevel,
|
|
1316
|
-
});
|
|
1317
|
-
payload.status = status;
|
|
1318
|
-
payload.processId = handle?.processId;
|
|
1319
|
-
payload.authorization = {
|
|
1320
|
-
decision: 'allow',
|
|
1321
|
-
source: directWithoutHandle ? 'bounded_read_direct' : 'process_runtime',
|
|
1322
|
-
reason: directWithoutHandle
|
|
1323
|
-
? 'Readonly repository command executed through the bounded non-persistent direct path.'
|
|
1324
|
-
: 'Repository command executed through Unified Process Runtime.',
|
|
1325
|
-
};
|
|
1326
|
-
if (directWithoutHandle && processResult.reason !== 'readonly_fast_path') {
|
|
1327
|
-
payload.authorization = processResult.authorizationDecision?.decision === 'allow'
|
|
1328
|
-
? processResult.authorizationDecision
|
|
1329
|
-
: {
|
|
1330
|
-
decision: 'allow',
|
|
1331
|
-
source: 'ephemeral_workspace_direct',
|
|
1332
|
-
reason: 'Bounded ephemeral workspace command executed through the non-persistent direct path.',
|
|
1333
|
-
};
|
|
1334
|
-
}
|
|
1335
|
-
if (handle?.processId) {
|
|
1336
|
-
payload.resultRef = { kind: 'process_logs', processId: handle.processId };
|
|
1337
|
-
}
|
|
1338
|
-
// Keep accepted true once the command was admitted to Process Runtime.
|
|
1339
|
-
payload.accepted = true;
|
|
1340
|
-
return processResult.ok === true || !completed
|
|
1341
|
-
? result(payload)
|
|
1342
|
-
: { ...result(payload), isError: true };
|
|
1343
|
-
}
|
|
1344
|
-
}
|
|
1345
|
-
} catch (error) {
|
|
1346
|
-
// Process Runtime is authoritative. Falling through could spawn the
|
|
1347
|
-
// same command again through the legacy Fast/Local Job path.
|
|
1348
|
-
if (process.env.FORGE_DEBUG_PROCESS_RUNTIME === '1') {
|
|
1349
|
-
console.error('[repository_command_execute] process runtime error', error);
|
|
1350
|
-
}
|
|
1351
|
-
return failure(error);
|
|
1352
|
-
}
|
|
1353
|
-
}
|
|
1354
|
-
if (target.workspace && (forceDurable || returnHandleImmediately)) {
|
|
1355
|
-
return result({
|
|
1356
|
-
accepted: false,
|
|
1357
|
-
mode: 'durable',
|
|
1358
|
-
path: 'ephemeral_workspace_promotion_required',
|
|
1359
|
-
repoId: repository.repoId,
|
|
1360
|
-
checkoutId: repository.activeCheckoutId,
|
|
1361
|
-
workspace: target.workspace,
|
|
1362
|
-
message: 'Ephemeral workspaces support bounded local Direct/Managed execution only. Register the directory before durable, remote, release, or resumable Work.',
|
|
1363
|
-
suggestedOperation: 'repository_register',
|
|
1364
|
-
});
|
|
1365
|
-
}
|
|
1366
|
-
// Durable Worker calls skip Process/Fast above, then use the Local Bridge
|
|
1367
|
-
// compatibility projection below for writes/long commands so the worker
|
|
1368
|
-
// can settle the legacy child without creating a nested ExecutionJob.
|
|
1369
|
-
// Short readonly commands keep the zero-Local-Job direct path.
|
|
1370
|
-
if (fromDurableWorker) {
|
|
1371
|
-
try {
|
|
1372
|
-
const routeClass = classifyRepositoryCommandRoute(args.command as string | string[], {
|
|
1373
|
-
forceDurable: false,
|
|
1374
|
-
defaultBranch: repository.defaultBranch,
|
|
1375
|
-
timeoutMs,
|
|
1376
|
-
});
|
|
1377
|
-
if (routeClass.route === 'process_direct') {
|
|
1378
|
-
const processResult = await executeRepositoryCommandViaProcessRuntime({
|
|
1379
|
-
controllerHome,
|
|
1380
|
-
repository,
|
|
1381
|
-
command: args.command as string | string[],
|
|
1382
|
-
cwd: typeof args.cwd === 'string' ? args.cwd : undefined,
|
|
1383
|
-
timeoutMs,
|
|
1384
|
-
maxOutputBytes,
|
|
1385
|
-
requestId: typeof args.request_id === 'string' ? args.request_id : undefined,
|
|
1386
|
-
workId: executionIdentity.workId,
|
|
1387
|
-
executionIdentity,
|
|
1388
|
-
});
|
|
1389
|
-
if (processResult.route === 'process_direct') {
|
|
1390
|
-
const execRecord = processResult.process as unknown as Record<string, unknown> | undefined;
|
|
1391
|
-
const ok = processResult.ok === true;
|
|
1392
|
-
const inlinePayload = {
|
|
1393
|
-
accepted: ok,
|
|
1394
|
-
mode: 'durable',
|
|
1395
|
-
path: 'durable_worker_inline',
|
|
1396
|
-
routing: compactRoutingSummary({
|
|
1397
|
-
path: 'durable',
|
|
1398
|
-
mode: 'durable',
|
|
1399
|
-
reasons: ['durable_worker_inline_process_direct', routeClass.reason, ...routingDecision.reasons],
|
|
1400
|
-
}),
|
|
1401
|
-
repoId: repository.repoId,
|
|
1402
|
-
checkoutId: repository.activeCheckoutId,
|
|
1403
|
-
ok,
|
|
1404
|
-
processId: typeof execRecord?.processId === 'string' ? execRecord.processId : undefined,
|
|
1405
|
-
status: typeof execRecord?.status === 'string' ? execRecord.status : undefined,
|
|
1406
|
-
exitCode: typeof processResult.exitCode === 'number' ? processResult.exitCode : undefined,
|
|
1407
|
-
...compactCommandOutput(
|
|
1408
|
-
typeof processResult.stdout === 'string' ? processResult.stdout : undefined,
|
|
1409
|
-
typeof processResult.stderr === 'string' ? processResult.stderr : undefined,
|
|
1410
|
-
{ ok },
|
|
1411
|
-
),
|
|
1412
|
-
durableSideEffects: processResult.durableSideEffects,
|
|
1413
|
-
next: 'Durable Worker executed a short readonly repository command inline without a Local Job.',
|
|
1414
|
-
};
|
|
1415
|
-
return ok ? result(inlinePayload) : { ...result(inlinePayload), isError: true };
|
|
1416
|
-
}
|
|
1417
|
-
}
|
|
1418
|
-
} catch (error) {
|
|
1419
|
-
if (process.env.FORGE_DEBUG_PROCESS_RUNTIME === '1') {
|
|
1420
|
-
console.error('[repository_command_execute] durable worker inline process runtime error', error);
|
|
1421
|
-
}
|
|
1422
|
-
}
|
|
1423
|
-
}
|
|
1424
|
-
return result({
|
|
1425
|
-
accepted: false,
|
|
1426
|
-
mode: 'durable',
|
|
1427
|
-
path: 'external_controller_required',
|
|
1428
|
-
routing: compactRoutingSummary({ path: 'durable', mode: 'durable', reasons: [routingDecision.reasons.join(','), 'local_bridge_execution_retired'] }),
|
|
1429
|
-
message: 'This command requires explicit external Controller handling; Local Bridge Jobs are retired for repository commands.',
|
|
1430
|
-
suggestedOperation: 'Create or claim WorkContract, then use rh_work.launcher_start or a Process Runtime-compatible command.',
|
|
1431
|
-
externalEffect: {
|
|
1432
|
-
outcome: 'not_started',
|
|
1433
|
-
ambiguousFailureOutcome: 'outcome_unknown',
|
|
1434
|
-
replayPolicy: 'never_auto_retry',
|
|
1435
|
-
reconciliation: 'After an ambiguous dispatch failure, inspect the remote ref/registry/release state before deciding whether to retry.',
|
|
1436
|
-
},
|
|
1437
|
-
});
|
|
1438
|
-
}
|
|
1439
|
-
case 'repository_batch_execute': {
|
|
1440
|
-
const repository = resolveRepositorySelection({
|
|
1441
|
-
repoId: repoIdValue || undefined,
|
|
1442
|
-
checkoutId: typeof args.checkout_id === 'string' ? args.checkout_id : undefined,
|
|
1443
|
-
controllerHome,
|
|
1444
|
-
allowSoleRepository: true,
|
|
1445
|
-
});
|
|
1446
|
-
const steps = Array.isArray(args.steps)
|
|
1447
|
-
? args.steps
|
|
1448
|
-
.filter((entry): entry is Record<string, unknown> => typeof entry === 'object' && entry !== null)
|
|
1449
|
-
.map((entry) => ({
|
|
1450
|
-
id: typeof entry.id === 'string' ? entry.id : undefined,
|
|
1451
|
-
kind: String(entry.kind ?? '') as
|
|
1452
|
-
| 'read_file'
|
|
1453
|
-
| 'search'
|
|
1454
|
-
| 'git_status'
|
|
1455
|
-
| 'git_diff'
|
|
1456
|
-
| 'apply_patch'
|
|
1457
|
-
| 'run_short_command'
|
|
1458
|
-
| 'run_focused_check'
|
|
1459
|
-
| 'stage_paths'
|
|
1460
|
-
| 'commit_paths',
|
|
1461
|
-
input: (typeof entry.input === 'object' && entry.input !== null
|
|
1462
|
-
? entry.input
|
|
1463
|
-
: {}) as Record<string, unknown>,
|
|
1464
|
-
}))
|
|
1465
|
-
: [];
|
|
1466
|
-
const batch = await executeRepositoryBatch(
|
|
1467
|
-
{ controllerHome, repository },
|
|
1468
|
-
{
|
|
1469
|
-
repoId: repository.repoId,
|
|
1470
|
-
checkoutId: repository.activeCheckoutId,
|
|
1471
|
-
mode: args.mode === 'fast' || args.mode === 'durable' || args.mode === 'auto' ? args.mode : 'auto',
|
|
1472
|
-
steps,
|
|
1473
|
-
stopOnError: args.stop_on_error !== false,
|
|
1474
|
-
allowedPaths: Array.isArray(args.allowed_paths) ? args.allowed_paths.map(String) : undefined,
|
|
1475
|
-
timeoutMs: typeof args.timeout_ms === 'number' ? args.timeout_ms : undefined,
|
|
1476
|
-
includeLatencyBreakdown: args.include_latency_breakdown === true,
|
|
1477
|
-
purpose: typeof args.purpose === 'string' ? args.purpose : undefined,
|
|
1478
|
-
requestId: typeof args.request_id === 'string' ? args.request_id.trim() || undefined : undefined,
|
|
1479
|
-
},
|
|
1480
|
-
);
|
|
1481
|
-
const payload = batch as unknown as Record<string, unknown>;
|
|
1482
|
-
return batch.ok ? result(payload) : { ...result(payload), isError: true };
|
|
1483
|
-
}
|
|
1484
|
-
case 'repository_lanes_execute': {
|
|
1485
|
-
const repository = resolveRepositorySelection({
|
|
1486
|
-
repoId: repoIdValue || undefined,
|
|
1487
|
-
checkoutId: typeof args.checkout_id === 'string' ? args.checkout_id : undefined,
|
|
1488
|
-
controllerHome,
|
|
1489
|
-
allowSoleRepository: true,
|
|
1490
|
-
});
|
|
1491
|
-
const lanes = await executeLightweightLanes(
|
|
1492
|
-
{ controllerHome, repository },
|
|
1493
|
-
{
|
|
1494
|
-
repoId: repository.repoId,
|
|
1495
|
-
checkoutId: repository.activeCheckoutId,
|
|
1496
|
-
readLanes: Array.isArray(args.read_lanes)
|
|
1497
|
-
? args.read_lanes
|
|
1498
|
-
.filter((entry): entry is Record<string, unknown> => typeof entry === 'object' && entry !== null)
|
|
1499
|
-
.map((entry) => ({
|
|
1500
|
-
id: typeof entry.id === 'string' ? entry.id : undefined,
|
|
1501
|
-
kind: String(entry.kind ?? 'search') as 'search' | 'read_file' | 'git_status' | 'git_diff' | 'run_short_command',
|
|
1502
|
-
input: (typeof entry.input === 'object' && entry.input !== null
|
|
1503
|
-
? entry.input
|
|
1504
|
-
: {}) as Record<string, unknown>,
|
|
1505
|
-
}))
|
|
1506
|
-
: undefined,
|
|
1507
|
-
patchProposalLanes: Array.isArray(args.patch_proposal_lanes)
|
|
1508
|
-
? args.patch_proposal_lanes
|
|
1509
|
-
.filter((entry): entry is Record<string, unknown> => typeof entry === 'object' && entry !== null)
|
|
1510
|
-
.map((entry) => ({
|
|
1511
|
-
id: typeof entry.id === 'string' ? entry.id : undefined,
|
|
1512
|
-
readPaths: Array.isArray(entry.read_paths) ? entry.read_paths.map(String) : [],
|
|
1513
|
-
writePaths: Array.isArray(entry.write_paths) ? entry.write_paths.map(String) : [],
|
|
1514
|
-
proposedOperations: Array.isArray(entry.proposed_operations) ? entry.proposed_operations : [],
|
|
1515
|
-
assumptions: Array.isArray(entry.assumptions) ? entry.assumptions.map(String) : undefined,
|
|
1516
|
-
riskNotes: Array.isArray(entry.risk_notes) ? entry.risk_notes.map(String) : undefined,
|
|
1517
|
-
suggestedFocusedCheck: entry.suggested_focused_check as string | string[] | undefined,
|
|
1518
|
-
}))
|
|
1519
|
-
: undefined,
|
|
1520
|
-
failFast: args.fail_fast === true,
|
|
1521
|
-
maxConcurrency: typeof args.max_concurrency === 'number' ? args.max_concurrency : undefined,
|
|
1522
|
-
includeLatencyBreakdown: args.include_latency_breakdown === true,
|
|
1523
|
-
},
|
|
1524
|
-
);
|
|
1525
|
-
const payload = lanes as unknown as Record<string, unknown>;
|
|
1526
|
-
return lanes.ok ? result(payload) : { ...result(payload), isError: true };
|
|
1527
|
-
}
|
|
1528
|
-
case 'repository_lanes_integrate': {
|
|
1529
|
-
const repository = resolveRepositorySelection({
|
|
1530
|
-
repoId: repoIdValue || undefined,
|
|
1531
|
-
checkoutId: typeof args.checkout_id === 'string' ? args.checkout_id : undefined,
|
|
1532
|
-
controllerHome,
|
|
1533
|
-
allowSoleRepository: true,
|
|
1534
|
-
});
|
|
1535
|
-
const proposals = Array.isArray(args.proposals)
|
|
1536
|
-
? args.proposals
|
|
1537
|
-
.filter((entry): entry is Record<string, unknown> => typeof entry === 'object' && entry !== null)
|
|
1538
|
-
.map((entry) => ({
|
|
1539
|
-
id: String(entry.id ?? 'proposal'),
|
|
1540
|
-
ok: entry.ok !== false,
|
|
1541
|
-
durationMs: 0,
|
|
1542
|
-
readPaths: Array.isArray(entry.read_paths) ? entry.read_paths.map(String) : [],
|
|
1543
|
-
writePaths: Array.isArray(entry.write_paths) ? entry.write_paths.map(String) : [],
|
|
1544
|
-
proposedOperations: Array.isArray(entry.proposed_operations) ? entry.proposed_operations : [],
|
|
1545
|
-
analysisOnly: entry.analysis_only === true,
|
|
1546
|
-
proposalId: typeof entry.proposal_id === 'string'
|
|
1547
|
-
? entry.proposal_id
|
|
1548
|
-
: typeof entry.proposalId === 'string'
|
|
1549
|
-
? entry.proposalId
|
|
1550
|
-
: undefined,
|
|
1551
|
-
}))
|
|
1552
|
-
: [];
|
|
1553
|
-
const integrated = await integratePatchProposals(
|
|
1554
|
-
{ controllerHome, repository },
|
|
1555
|
-
proposals,
|
|
1556
|
-
{
|
|
1557
|
-
sessionId: typeof args.session_id === 'string' ? args.session_id : undefined,
|
|
1558
|
-
allowedPaths: Array.isArray(args.allowed_paths) ? args.allowed_paths.map(String) : undefined,
|
|
1559
|
-
purpose: typeof args.purpose === 'string' ? args.purpose : undefined,
|
|
1560
|
-
requestId: typeof args.request_id === 'string' ? args.request_id.trim() || undefined : undefined,
|
|
1561
|
-
continueOnError: args.continue_on_error === true,
|
|
1562
|
-
},
|
|
1563
|
-
);
|
|
1564
|
-
const payload = integrated as unknown as Record<string, unknown>;
|
|
1565
|
-
return integrated.ok ? result(payload) : { ...result(payload), isError: true };
|
|
1566
|
-
}
|
|
1567
|
-
case 'repository_fast_receipt_get': {
|
|
1568
|
-
const repository = resolveRepositorySelection({
|
|
1569
|
-
repoId: repoIdValue || undefined,
|
|
1570
|
-
checkoutId: typeof args.checkout_id === 'string' ? args.checkout_id : undefined,
|
|
1571
|
-
controllerHome,
|
|
1572
|
-
allowSoleRepository: true,
|
|
1573
|
-
});
|
|
1574
|
-
const receipt = readFastReceipt(controllerHome, repository.repoId, String(args.execution_id ?? ''));
|
|
1575
|
-
if (!receipt) return failure(new Error(`FAST_RECEIPT_NOT_FOUND: ${String(args.execution_id ?? '')}`));
|
|
1576
|
-
return result({ receipt });
|
|
1577
|
-
}
|
|
1578
|
-
case 'repository_fast_receipt_list': {
|
|
1579
|
-
const repository = resolveRepositorySelection({
|
|
1580
|
-
repoId: repoIdValue || undefined,
|
|
1581
|
-
checkoutId: typeof args.checkout_id === 'string' ? args.checkout_id : undefined,
|
|
1582
|
-
controllerHome,
|
|
1583
|
-
allowSoleRepository: true,
|
|
1584
|
-
});
|
|
1585
|
-
const limit = typeof args.limit === 'number' ? args.limit : undefined;
|
|
1586
|
-
return result({ receipts: listFastReceipts(controllerHome, repository.repoId, limit) });
|
|
1587
|
-
}
|
|
1588
|
-
case 'repository_execution_route': {
|
|
1589
|
-
const repository = resolveRepositorySelection({
|
|
1590
|
-
repoId: repoIdValue || undefined,
|
|
1591
|
-
checkoutId: typeof args.checkout_id === 'string' ? args.checkout_id : undefined,
|
|
1592
|
-
controllerHome,
|
|
1593
|
-
allowSoleRepository: true,
|
|
1594
|
-
});
|
|
1595
|
-
const decision = routeExecution({
|
|
1596
|
-
operation: String(args.operation ?? ''),
|
|
1597
|
-
mode: args.mode === 'fast' || args.mode === 'durable' || args.mode === 'auto' ? args.mode : 'auto',
|
|
1598
|
-
command: args.command as string | string[] | undefined,
|
|
1599
|
-
timeoutMs: typeof args.timeout_ms === 'number' ? args.timeout_ms : undefined,
|
|
1600
|
-
background: args.background === true,
|
|
1601
|
-
paths: Array.isArray(args.paths) ? args.paths.map(String) : undefined,
|
|
1602
|
-
allowedPaths: Array.isArray(args.allowed_paths) ? args.allowed_paths.map(String) : undefined,
|
|
1603
|
-
defaultBranch: repository.defaultBranch,
|
|
1604
|
-
});
|
|
1605
|
-
return result({ decision, repoId: repository.repoId, checkoutId: repository.activeCheckoutId });
|
|
1606
|
-
}
|
|
1607
|
-
default:
|
|
1608
|
-
return failure(new Error(`UNKNOWN_REPOSITORY_TOOL: ${name}`));
|
|
1609
|
-
}
|
|
1610
|
-
} catch (error) {
|
|
1611
|
-
return failure(error);
|
|
1612
|
-
}
|
|
1613
|
-
}
|
|
1
|
+
/** @deprecated Kernel V2 compatibility shim. MCP adapter owns this surface. */
|
|
2
|
+
export * from '../../../adapters/mcp/tool-mapping/repository-tools';
|