@moretea-labs/forge 1.6.0 → 1.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +2 -0
- package/CHANGELOG.md +26 -0
- package/CLAUDE.md +2 -0
- package/README.md +2 -2
- package/README.zh-CN.md +1 -1
- package/SKILL.md +2 -2
- package/THIRD_PARTY_NOTICES.md +1 -1
- package/agents/openai.yaml +1 -1
- package/assets/hooks/hook-input.sh +11 -8
- package/assets/hooks/lib/session-state.sh +10 -7
- package/assets/hooks/lib/workflow-state.sh +13 -177
- package/assets/hooks/post-tool-observer.sh +8 -2
- package/assets/hooks/prompt-guard.sh +5 -81
- package/assets/hooks/session-start-context.sh +56 -1
- package/assets/partials/05-workflow.partial.md +1 -1
- package/assets/partials-agents/03-orchestration.partial.md +1 -1
- package/assets/plugin-registry.v1.json +1 -1
- package/assets/reference-configs/document-generation.md +1 -1
- package/assets/reference-configs/harness-overview.md +1 -1
- package/assets/reference-configs/sprint-contracts.md +3 -3
- package/assets/skill-version.json +2 -2
- package/assets/templates/contract.template.md +2 -7
- package/assets/templates/helpers/capture-plan.sh +2 -2
- package/assets/templates/helpers/check-task-workflow.sh +4 -4
- package/assets/templates/helpers/contract-worktree.sh +1 -21
- package/assets/templates/helpers/ensure-task-workflow.sh +11 -36
- package/assets/templates/helpers/migrate-project-template.sh +22 -45
- package/assets/templates/helpers/new-plan.sh +1 -1
- package/assets/templates/helpers/plan-to-todo.sh +12 -37
- package/assets/templates/helpers/ship-worktrees.sh +2 -29
- package/assets/templates/helpers/verify-contract.sh +1 -111
- package/assets/templates/helpers/verify-sprint.sh +3 -180
- package/assets/templates/plan.template.md +1 -1
- package/assets/templates/review.template.md +9 -34
- package/assets/workflow-contract.v1.json +10 -19
- package/docs/README.md +10 -10
- package/docs/architecture/CURRENT.md +170 -0
- package/docs/architecture/EVOLUTION.md +42 -0
- package/docs/architecture/current/README.md +4 -156
- package/docs/architecture/decisions/20260803-release-identity-binding-and-exit-policy.md +2 -2
- package/docs/architecture/decisions/20260823-immediate-controller-relay.md +53 -0
- package/docs/architecture/decisions/20260826-browser-runtime-v2.md +73 -0
- package/docs/architecture/history/README.md +7 -0
- package/docs/architecture/{chatgpt-handoff-facade.md → history/chatgpt-handoff-facade.md} +4 -0
- package/docs/architecture/{global-hook-runtime.md → history/global-hook-runtime.md} +7 -3
- package/docs/architecture/{ios-semantic-automation-provider-v2.md → history/ios-semantic-automation-provider-v2.md} +6 -2
- package/docs/architecture/history.md +3 -34
- package/docs/architecture/index.md +15 -98
- package/docs/architecture/modules/controller-runtime/transport-lifecycle.md +1 -1
- package/docs/architecture/reviews/2026-08-22-semantic-harness-convergence-acceptance.md +39 -0
- package/docs/architecture/versions/1.6.md +38 -0
- package/docs/architecture/versions/1.7.md +41 -0
- package/docs/forge-chatgpt-browser-engine.md +2 -2
- package/docs/forge-chatgpt-mcp-setup.md +4 -28
- package/docs/forge-chatgpt-supervised-automation.md +3 -3
- package/docs/forge-github-issue-launcher.md +1 -1
- package/docs/forge-runtime-self-healing-loop.md +1 -1
- package/docs/operations/controller-browser-plugin.md +26 -6
- package/docs/operations/controller-performance-and-502.md +124 -0
- package/docs/operations/controller-reliability-runbook.md +1 -1
- package/docs/operations/features.md +2 -2
- package/docs/operations/github-repository.md +1 -1
- package/docs/operations/homebrew.md +2 -2
- package/docs/operations/mcp-tool-exposure.md +5 -3
- package/docs/wiki/Architecture.md +6 -6
- package/docs/wiki/Implementation.md +2 -2
- package/docs/wiki/Integrations.md +2 -2
- package/docs/wiki/Work-Lifecycle.md +1 -1
- package/package.json +29 -10
- package/scripts/activate-source-baseline.ts +17 -13
- package/scripts/benchmark-background-check-overlap.ts +228 -0
- package/scripts/benchmark-mcp-host.sh +117 -0
- package/scripts/benchmark-mcp-transport.ts +170 -0
- package/scripts/benchmark-quality-harness.ts +146 -0
- package/scripts/benchmark-route-session-concurrency.ts +207 -6
- package/scripts/benchmark-thin-harness-mcp-e2e.ts +7 -1
- package/scripts/benchmark-typescript-navigation.ts +186 -0
- package/scripts/benchmark-work-efficiency.ts +334 -0
- package/scripts/capture-plan.sh +3 -3
- package/scripts/check-agent-tooling.sh +8 -35
- package/scripts/check-architecture-sync.sh +17 -86
- package/scripts/check-mcp-compatibility.ts +14 -0
- package/scripts/check-runtime-architecture.mjs +107 -64
- package/scripts/check-stable-baseline.ts +92 -0
- package/scripts/check-task-workflow.sh +4 -4
- package/scripts/contract-worktree.sh +1 -21
- package/scripts/ensure-task-workflow.sh +22 -55
- package/scripts/host-temporary-cloud-mcp-e2e.sh +265 -0
- package/scripts/install-standalone-recovery.ts +24 -0
- package/scripts/lib/project-init-lib.sh +15 -44
- package/scripts/migrate-project-template.sh +23 -1179
- package/scripts/new-plan.sh +1 -1
- package/scripts/plan-to-todo.sh +11 -36
- package/scripts/run-governed-gate.ts +2 -1
- package/scripts/ship-worktrees.sh +2 -29
- package/scripts/smoke-ios-physical-device.ts +4 -2
- package/scripts/smoke-runtime-recovery.ts +1 -35
- package/scripts/smoke-schedule-engine.ts +1 -20
- package/scripts/verify-contract.sh +1 -111
- package/scripts/verify-forge-runtime.sh +0 -1
- package/scripts/verify-sprint.sh +3 -180
- package/scripts/workflow-contract.ts +1 -5
- package/src/cli/commands/init-hook.ts +3 -3
- package/src/cli/commands/mcp.ts +9 -5
- package/src/cli/commands/plugin.ts +1 -1
- package/src/cli/commands/recovery.ts +25 -3
- package/src/cli/commands/runtime.ts +55 -3
- package/src/cli/commands/security.ts +12 -1
- package/src/cli/commands/setup-profile.ts +31 -21
- package/src/cli/controller/check-runner.ts +106 -3
- package/src/cli/controller/composite-result.ts +1 -1
- package/src/cli/controller/context/focus.ts +51 -0
- package/src/cli/controller/context/instruction-context.ts +114 -0
- package/src/cli/controller/context/known-paths.ts +76 -0
- package/src/cli/controller/context/query-planning.ts +110 -0
- package/src/cli/controller/context/rule-resolution.ts +532 -0
- package/src/cli/controller/context/source-materializer.ts +278 -0
- package/src/cli/controller/context/structural.ts +16 -0
- package/src/cli/controller/context/types.ts +286 -0
- package/src/cli/controller/context-pack.ts +785 -469
- package/src/cli/controller/launch-agents.ts +77 -2
- package/src/cli/controller/operational-plan.ts +2 -2
- package/src/cli/controller/work-mode.ts +6 -4
- package/src/cli/editing/edit-session.ts +60 -7
- package/src/cli/github/github.ts +133 -0
- package/src/cli/installer/managed-entries.ts +15 -1
- package/src/cli/local-bridge/console-automations.ts +54 -78
- package/src/cli/local-bridge/console-view-models.ts +1 -35
- package/src/cli/local-bridge/facade-api.ts +0 -217
- package/src/cli/local-bridge/frontend/src/App.tsx +3 -3
- package/src/cli/local-bridge/frontend/src/features/automations/AutomationsView.tsx +23 -13
- package/src/cli/local-bridge/frontend/src/features/capabilities/CapabilitiesView.tsx +37 -4
- package/src/cli/local-bridge/frontend/src/features/overview/OverviewView.tsx +6 -4
- package/src/cli/local-bridge/frontend/src/lib/api.ts +1 -6
- package/src/cli/local-bridge/frontend/src/lib/routes.ts +1 -1
- package/src/cli/local-bridge/frontend/src/shell/Sidebar.tsx +2 -2
- package/src/cli/local-bridge/frontend/src/styles.css +1 -1
- package/src/cli/local-bridge/frontend/src/types.ts +5 -8
- package/src/cli/local-bridge/job-store.ts +1 -490
- package/src/cli/local-bridge/server.ts +0 -513
- package/src/cli/local-bridge/ui-dist/app.css +1 -1
- package/src/cli/local-bridge/ui-dist/app.js +3703 -3757
- package/src/cli/mcp/auth.ts +5 -5
- package/src/cli/mcp/instructions.ts +3 -2
- package/src/cli/mcp/legacy-tool-service.ts +0 -189
- package/src/cli/mcp/multi-repository.ts +16 -5
- package/src/cli/mcp/oauth.ts +175 -26
- package/src/cli/mcp/repository-tools.ts +247 -107
- package/src/cli/mcp/server.ts +537 -111
- package/src/cli/mcp/tool-capability-cache.ts +1 -1
- package/src/cli/mcp/toolset-selection.ts +1 -1
- package/src/cli/mcp/toolset.ts +42 -5
- package/src/cli/mcp/transports/http.ts +101 -14
- package/src/cli/mcp/transports/session-registry.ts +43 -5
- package/src/cli/mcp/types.ts +3 -3
- package/src/cli/repositories/command-classifier.ts +101 -19
- package/src/cli/repositories/command-executor.ts +55 -521
- package/src/cli/repositories/command-process.ts +108 -0
- package/src/cli/repositories/command-scope.ts +99 -41
- package/src/cli/repositories/controller-home.ts +7 -8
- package/src/cli/repositories/git-command-executor.ts +2 -0
- package/src/cli/repositories/locks.ts +53 -16
- package/src/cli/repositories/repository-snapshot.ts +121 -0
- package/src/cli/repositories/selected-path-actions.ts +17 -9
- package/src/cli/repositories/structured-git.ts +61 -3
- package/src/cli/repository/inspector.ts +553 -63
- package/src/cli/repository/session-cache.ts +58 -17
- package/src/cli/v81-entry.ts +1 -4
- package/src/effects/fs-transaction.ts +85 -17
- package/src/runtime/context/codegraph-read-provider.ts +233 -2
- package/src/runtime/context/codegraph-sidecar.cjs +74 -40
- package/src/runtime/context/generic-lsp-provider.ts +355 -0
- package/src/runtime/context/lsp-client.ts +283 -0
- package/src/runtime/context/semantic-navigation.ts +275 -0
- package/src/runtime/context/swift-navigation.ts +565 -0
- package/src/runtime/context/typescript-navigation.ts +226 -0
- package/src/runtime/control-plane/dispatch-priority.ts +28 -0
- package/src/runtime/control-plane/execution/direct-edit-work-completion.ts +47 -8
- package/src/runtime/control-plane/execution/edit-validation-coordinator.ts +86 -24
- package/src/runtime/control-plane/execution/session-store.ts +18 -0
- package/src/runtime/control-plane/execution/verification-evidence.ts +58 -3
- package/src/runtime/control-plane/execution/work-handle-store.ts +27 -2
- package/src/runtime/control-plane/execution/work-lifecycle-audit.ts +258 -0
- package/src/runtime/control-plane/execution/work-remote-delivery.ts +215 -0
- package/src/runtime/control-plane/execution/work-task-receipt.ts +54 -11
- package/src/runtime/control-plane/execution/work-terminal-cleanup.ts +143 -8
- package/src/runtime/control-plane/execution/work-validation-reconciler.ts +22 -14
- package/src/runtime/control-plane/execution/work-verification-snapshot.ts +85 -8
- package/src/runtime/control-plane/facade/capability-registry.ts +129 -25
- package/src/runtime/control-plane/facade/controller-round-relay.ts +991 -0
- package/src/runtime/control-plane/facade/controller-session-store.ts +132 -1
- package/src/runtime/control-plane/facade/goal-workloop-access.ts +2 -0
- package/src/runtime/control-plane/facade/goal-workloop.ts +686 -129
- package/src/runtime/control-plane/facade/index.ts +1 -0
- package/src/runtime/control-plane/facade/plan-contract-store.ts +185 -20
- package/src/runtime/control-plane/facade/semantic-admission.ts +205 -0
- package/src/runtime/control-plane/facade/suggested-actions.ts +5 -1
- package/src/runtime/control-plane/facade/types.ts +22 -5
- package/src/runtime/control-plane/facade/work-contract-store.ts +175 -73
- package/src/runtime/control-plane/generated-cache-retention.ts +271 -0
- package/src/runtime/control-plane/global-scheduler/config.ts +44 -0
- package/src/runtime/control-plane/global-scheduler/dispatch-capacity.ts +80 -0
- package/src/runtime/control-plane/global-scheduler/durable-admission.ts +46 -0
- package/src/runtime/control-plane/global-scheduler/maintenance.ts +145 -0
- package/src/runtime/control-plane/global-scheduler/projection-refresh.ts +84 -0
- package/src/runtime/control-plane/global-scheduler/reconciliation.ts +3 -3
- package/src/runtime/control-plane/global-scheduler/scheduler.ts +273 -542
- package/src/runtime/control-plane/global-scheduler/source-scan.ts +59 -0
- package/src/runtime/control-plane/global-scheduler/state.ts +88 -0
- package/src/runtime/control-plane/global-scheduler/worker-attachment.ts +57 -0
- package/src/runtime/control-plane/global-scheduler/worker-exit-decision.ts +38 -0
- package/src/runtime/control-plane/global-scheduler/worker-exit-reconciler.ts +175 -0
- package/src/runtime/control-plane/global-scheduler/worker-launch.ts +111 -0
- package/src/runtime/control-plane/global-scheduler/worker-lifecycle-store.ts +64 -0
- package/src/runtime/control-plane/global-scheduler/worker-lifecycle.ts +150 -0
- package/src/runtime/control-plane/global-scheduler/worker-process.ts +119 -0
- package/src/runtime/control-plane/global-scheduler/worker-stderr.ts +60 -0
- package/src/runtime/control-plane/launcher/chatgpt-work-binding-store.ts +50 -0
- package/src/runtime/control-plane/launcher/chatgpt-work-continuation.ts +355 -116
- package/src/runtime/control-plane/launcher/launch-reservation-store.ts +40 -0
- package/src/runtime/control-plane/launcher/thin-launcher.ts +194 -10
- package/src/runtime/control-plane/persistence/controller-home-migration.ts +487 -0
- package/src/runtime/control-plane/persistence/sqlite-store.ts +33 -2
- package/src/runtime/control-plane/release-retention.ts +62 -2
- package/src/runtime/control-plane/routing/route-policy.ts +7 -16
- package/src/runtime/control-plane/runtime-status-client.ts +0 -2
- package/src/runtime/diagnostics/mcp-timing.ts +13 -0
- package/src/runtime/diagnostics/mcp-transport-benchmark.ts +129 -0
- package/src/runtime/diagnostics/performance.ts +24 -1
- package/src/runtime/evidence/event-ledger.ts +1 -1
- package/src/runtime/execution/jobs/store.ts +58 -4
- package/src/runtime/execution/jobs/types.ts +1 -1
- package/src/runtime/execution/managed-workspace.ts +203 -1
- package/src/runtime/execution/process-runtime/check-facade.ts +51 -4
- package/src/runtime/execution/process-runtime/check-result.ts +53 -0
- package/src/runtime/execution/process-runtime/check-scheduling.ts +114 -0
- package/src/runtime/execution/process-runtime/command-facade.ts +345 -40
- package/src/runtime/execution/process-runtime/gc.ts +38 -6
- package/src/runtime/execution/process-runtime/lightweight-managed.ts +1184 -0
- package/src/runtime/execution/process-runtime/persisted-check.ts +47 -4
- package/src/runtime/execution/process-runtime/resource-claims.ts +10 -6
- package/src/runtime/execution/process-runtime/runtime.ts +43 -3
- package/src/runtime/execution/process-runtime/store.ts +1 -0
- package/src/runtime/execution/process-runtime/types.ts +2 -0
- package/src/runtime/execution/thin-harness/async-process.ts +12 -2
- package/src/runtime/execution/thin-harness/search-worker.ts +54 -5
- package/src/runtime/execution/workers/executor.ts +0 -48
- package/src/runtime/gateway/mcp/execution-tools.ts +1192 -114
- package/src/runtime/gateway/mcp/process-tools.ts +83 -37
- package/src/runtime/gateway/mcp/router.ts +184 -82
- package/src/runtime/gateway/mcp/runtime-tool-definitions.ts +546 -0
- package/src/runtime/gateway/mcp/runtime-tools.ts +2224 -1589
- package/src/runtime/plugins/app-store-connect-adapter.ts +123 -19
- package/src/runtime/plugins/browser-adapter.ts +2901 -241
- package/src/runtime/plugins/browser-automation-service.ts +10 -0
- package/src/runtime/plugins/browser-handoff.ts +92 -2
- package/src/runtime/plugins/browser-macos-bridge.ts +582 -49
- package/src/runtime/plugins/browser-node-bridge.ts +6 -34
- package/src/runtime/plugins/browser-provider-registry.ts +109 -0
- package/src/runtime/plugins/browser-runtime-contract.ts +152 -0
- package/src/runtime/plugins/browser-runtime.ts +183 -0
- package/src/runtime/plugins/browser-session-authority.ts +332 -0
- package/src/runtime/plugins/capability-authorization-grants.ts +354 -0
- package/src/runtime/plugins/desktop-operator-registration.ts +8 -2
- package/src/runtime/plugins/external-adapter.ts +324 -3
- package/src/runtime/plugins/external-unix-socket.ts +7 -1
- package/src/runtime/plugins/first-party-registry.ts +2 -0
- package/src/runtime/plugins/github-adapter.ts +125 -0
- package/src/runtime/plugins/ios/agent-device-provider.ts +1 -1
- package/src/runtime/plugins/ios/agent-device-typed-provider.ts +52 -9
- package/src/runtime/plugins/ios/remote-xpc-hid.ts +1171 -0
- package/src/runtime/plugins/ios-adapter.ts +106 -16
- package/src/runtime/plugins/ios-agent-device.ts +234 -64
- package/src/runtime/plugins/ios-physical-device.ts +1143 -392
- package/src/runtime/plugins/lightweight-action.ts +153 -0
- package/src/runtime/plugins/local-system-adapter.ts +123 -6
- package/src/runtime/plugins/macos-capability-broker.ts +55 -9
- package/src/runtime/plugins/plugin-action-sidecar.ts +59 -0
- package/src/runtime/plugins/plugin-management-adapter.ts +49 -8
- package/src/runtime/plugins/resend-adapter.ts +1 -1
- package/src/runtime/plugins/store.ts +269 -29
- package/src/runtime/plugins/types.ts +35 -2
- package/src/runtime/plugins/xiaohongshu-publish.ts +515 -0
- package/src/runtime/projections/git-status-sampler.ts +16 -16
- package/src/runtime/projections/materialized-view.ts +28 -10
- package/src/runtime/recovery/maintenance-executor.ts +393 -28
- package/src/runtime/root/mcp-transport.ts +180 -10
- package/src/runtime/root/package-connector-service.ts +186 -8
- package/src/runtime/root/package-runtime-release.ts +143 -17
- package/src/runtime/root/package-runtime-service.ts +430 -22
- package/src/runtime/root/release-manifest.ts +7 -2
- package/src/runtime/root/release-materialize.ts +19 -0
- package/src/runtime/root/release-store.ts +48 -11
- package/src/runtime/root/runtime.ts +23 -5
- package/src/runtime/root/service.ts +100 -29
- package/src/runtime/root/types.ts +2 -0
- package/src/runtime/safe-tooling/ios-development.ts +321 -63
- package/src/runtime/shared/trusted-executable.ts +62 -0
- package/src/runtime/shared/trusted-node-executable.ts +48 -0
- package/src/runtime/standalone-recovery/core.ts +700 -92
- package/src/runtime/standalone-recovery/entry.ts +99 -23
- package/src/runtime/standalone-recovery/installer.ts +19 -3
- package/src/runtime/standalone-recovery/service-labels.ts +2 -0
- package/src/runtime/standalone-recovery/watchdog-heartbeat.ts +160 -0
- package/src/runtime/workflow/schedules/browser-probe.ts +81 -3
- package/src/runtime/workflow/schedules/engine.ts +287 -151
- package/src/runtime/workflow/schedules/github-issue-watch.ts +158 -0
- package/src/runtime/workflow/schedules/settlement.ts +48 -4
- package/src/runtime/workflow/schedules/store.ts +131 -10
- package/src/runtime/workflow/schedules/types.ts +2 -4
- package/src/runtime/workflow/schedules/work-continuation.ts +26 -13
- package/src/testing/test-governance.ts +8 -40
- package/assets/reference-configs/heartbeat-triage.md +0 -57
- package/assets/templates/helpers/harness-trace-grade.sh +0 -150
- package/assets/templates/helpers/heartbeat-triage.sh +0 -361
- package/assets/templates/helpers/maintenance-triage.sh +0 -167
- package/docs/architecture/current/approved-target-architecture.zh-CN.md +0 -1501
- package/docs/architecture/current/architecture-invariants.md +0 -331
- package/docs/architecture/current/automation-and-schedule-engine.md +0 -459
- package/docs/architecture/current/codegraph-context-provider.md +0 -238
- package/docs/architecture/current/control-plane-authority-inventory.md +0 -94
- package/docs/architecture/current/controller-repository-decoupling.md +0 -148
- package/docs/architecture/current/dispatch-and-agent-strategy.md +0 -373
- package/docs/architecture/current/entity-model.md +0 -612
- package/docs/architecture/current/external-plugin-governance.md +0 -396
- package/docs/architecture/current/failure-recovery.md +0 -447
- package/docs/architecture/current/governance.md +0 -213
- package/docs/architecture/current/human-interaction-plane.md +0 -87
- package/docs/architecture/current/implementation-status.md +0 -128
- package/docs/architecture/current/job-and-run-lifecycle.md +0 -413
- package/docs/architecture/current/legacy-governance.md +0 -58
- package/docs/architecture/current/local-workspace-target-grants.md +0 -70
- package/docs/architecture/current/migration-roadmap.md +0 -105
- package/docs/architecture/current/multi-repository-execution.md +0 -371
- package/docs/architecture/current/operations-runbook.md +0 -45
- package/docs/architecture/current/peer-supercontroller-runtime.md +0 -32
- package/docs/architecture/current/personal-assistant-plugin-baseline.md +0 -206
- package/docs/architecture/current/repository-access-modes.md +0 -102
- package/docs/architecture/current/route-policy.md +0 -15
- package/docs/architecture/current/route-session-concurrency.md +0 -85
- package/docs/architecture/current/runtime-architecture-simplification.md +0 -214
- package/docs/architecture/current/runtime-directory-map.md +0 -49
- package/docs/architecture/current/runtime-health-and-resource-lifecycle.md +0 -85
- package/docs/architecture/current/scheduler-and-resource-claims.md +0 -422
- package/docs/architecture/current/session-aware-execution-and-authorization.md +0 -77
- package/docs/architecture/current/system-overview.md +0 -169
- package/docs/architecture/current/target-requirements-traceability.md +0 -202
- package/docs/architecture/current/thin-harness-governance-policy.md +0 -32
- package/docs/architecture/current/thin-harness-v1.md +0 -321
- package/docs/architecture/current/verification-and-release-gates.md +0 -391
- package/docs/forge-autonomous-goal-loop.md +0 -9
- package/docs/forge-provider-configuration.md +0 -7
- package/docs/operations/chatgpt-personal-assistant-runtime.md +0 -93
- package/docs/operations/gmail-assistant-routines.md +0 -186
- package/docs/operations/personal-assistant-operator-guide.md +0 -61
- package/docs/operations/provider-configuration.md +0 -31
- package/scripts/harness-trace-grade.sh +0 -150
- package/scripts/heartbeat-triage.sh +0 -361
- package/scripts/maintenance-triage.sh +0 -167
- package/src/cli/local-bridge/frontend/src/features/settings/SettingsView.tsx +0 -2
- package/src/cli/repositories/goal-registry.ts +0 -239
- package/src/runtime/assistant/action-proposals.ts +0 -279
- package/src/runtime/assistant/intent.ts +0 -395
- package/src/runtime/assistant/model-provider.ts +0 -460
- package/src/runtime/assistant/openapi.ts +0 -223
- package/src/runtime/assistant/policy.ts +0 -89
- package/src/runtime/assistant/readiness.ts +0 -258
- package/src/runtime/assistant/routine-runtime.ts +0 -477
- package/src/runtime/assistant/schedule-binding.ts +0 -171
- package/src/runtime/assistant/standing-grants.ts +0 -375
- package/src/runtime/assistant/store.ts +0 -243
- package/src/runtime/assistant/types.ts +0 -135
- package/src/runtime/control-plane/goal-loop/config-facade.ts +0 -700
- package/src/runtime/control-plane/goal-loop/config-store.ts +0 -570
- package/src/runtime/control-plane/goal-loop/config-types.ts +0 -213
- package/src/runtime/control-plane/goal-loop/executor-router.ts +0 -109
- package/src/runtime/control-plane/goal-loop/failure-taxonomy.ts +0 -149
- package/src/runtime/control-plane/goal-loop/goal-contract-store.ts +0 -304
- package/src/runtime/control-plane/goal-loop/goal-loop-engine.ts +0 -1001
- package/src/runtime/control-plane/goal-loop/handoff-packet.ts +0 -160
- package/src/runtime/control-plane/goal-loop/index.ts +0 -13
- package/src/runtime/control-plane/goal-loop/local-tools.ts +0 -290
- package/src/runtime/control-plane/goal-loop/policy-gates.ts +0 -203
- package/src/runtime/control-plane/goal-loop/provider-dispatch.ts +0 -93
- package/src/runtime/control-plane/goal-loop/provider-registry.ts +0 -545
- package/src/runtime/control-plane/goal-loop/types.ts +0 -378
- package/src/runtime/control-plane/startup-recovery.ts +0 -198
- package/src/runtime/gateway/mcp/resource-policy.ts +0 -186
- package/src/runtime/personal-assistant/gmail-triage-manager.ts +0 -231
- package/src/runtime/personal-assistant/reporting-runtime.ts +0 -344
- package/src/runtime/personal-assistant/triage-runtime.ts +0 -748
- package/src/runtime/workflow/findings/store.ts +0 -204
- package/src/runtime/workflow/findings/types.ts +0 -58
- package/src/runtime/workflow/portfolio/engine.ts +0 -20
- package/src/runtime/workflow/portfolio/store.ts +0 -185
- package/src/runtime/workflow/portfolio/types.ts +0 -29
|
@@ -24,9 +24,8 @@ import {
|
|
|
24
24
|
} from '../repositories/registry';
|
|
25
25
|
import { buildControllerWorkbench } from '../repositories/workbench';
|
|
26
26
|
import { applySafePatch, buildSafePatchPlan } from '../repositories/safe-patch';
|
|
27
|
-
import { getEditSessionDiff, type EditSessionBinding } from '../editing/edit-session';
|
|
27
|
+
import { getEditSession, getEditSessionDiff, type EditSessionBinding } from '../editing/edit-session';
|
|
28
28
|
import { buildSyncOperationDigest, classifyUserFacingError } from '../../runtime/control-plane/facade/operation-digest';
|
|
29
|
-
import { diagnoseRepositoryStuckState, listRepositoryGoalRuns, readRepositoryGoalRegistry, runRepositoryGoal, upsertRepositoryGoal } from '../repositories/goal-registry';
|
|
30
29
|
import {
|
|
31
30
|
repositoryGitCommit,
|
|
32
31
|
repositoryGitCreateBranch,
|
|
@@ -55,6 +54,9 @@ import {
|
|
|
55
54
|
} from '../../runtime/execution/process-runtime/command-facade';
|
|
56
55
|
import { assessWorkMode, parseExplicitTaskMode } from '../controller/work-mode';
|
|
57
56
|
import { normalizeRepositoryCommand } from '../repositories/command-normalization';
|
|
57
|
+
import { readRepositoryRange } from '../repository/inspector';
|
|
58
|
+
import { getMcpPolicy } from './policy';
|
|
59
|
+
import { redactMcpText } from './redaction';
|
|
58
60
|
import type { CallToolResult, McpToolDefinition } from './tools';
|
|
59
61
|
import {
|
|
60
62
|
boundUtf8,
|
|
@@ -117,6 +119,13 @@ export const repositoryToolDefinitions: McpToolDefinition[] = [
|
|
|
117
119
|
include_removed: { type: 'boolean' },
|
|
118
120
|
detail_level: { type: 'string', enum: ['summary', 'detail'], description: 'Defaults to summary; detail returns the complete checkout history.' },
|
|
119
121
|
}, ['repo_id'], true),
|
|
122
|
+
definition('read_repository_file', 'Read a line range from one policy-readable repository file.', {
|
|
123
|
+
repo_id: repoId,
|
|
124
|
+
checkout_id: { type: 'string' },
|
|
125
|
+
path: { type: 'string' },
|
|
126
|
+
start_line: { type: 'number' },
|
|
127
|
+
end_line: { type: 'number' },
|
|
128
|
+
}, ['path'], true),
|
|
120
129
|
definition('repository_validate', 'Validate repository identity and migrate legacy ownership.', {
|
|
121
130
|
repo_id: repoId,
|
|
122
131
|
detail_level: { type: 'string', enum: ['summary', 'detail'], description: 'Defaults to summary; detail returns full migration evidence.' },
|
|
@@ -136,7 +145,7 @@ export const repositoryToolDefinitions: McpToolDefinition[] = [
|
|
|
136
145
|
}, ['repo_id']),
|
|
137
146
|
definition('repository_remove', 'Soft-remove a repository while retaining audit history.', {
|
|
138
147
|
repo_id: repoId,
|
|
139
|
-
}, ['repo_id']
|
|
148
|
+
}, ['repo_id']),
|
|
140
149
|
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.', {
|
|
141
150
|
repo_id: repoId,
|
|
142
151
|
checkout_id: { type: 'string', description: 'Optional checkout identity for repository-scoped operations.' },
|
|
@@ -152,38 +161,6 @@ export const repositoryToolDefinitions: McpToolDefinition[] = [
|
|
|
152
161
|
additionalProperties: true,
|
|
153
162
|
},
|
|
154
163
|
}),
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
definition('repository_goal_list', 'List durable repository goals stored inside the checkout.', {
|
|
159
|
-
repo_id: repoId,
|
|
160
|
-
checkout_id: { type: 'string', description: 'Optional checkout identity for repositories with multiple local clones.' },
|
|
161
|
-
}, [], true),
|
|
162
|
-
definition('repository_goal_upsert', 'Create or update one durable repository goal for repeated assistant workflows.', {
|
|
163
|
-
repo_id: repoId,
|
|
164
|
-
checkout_id: { type: 'string', description: 'Optional checkout identity for repositories with multiple local clones.' },
|
|
165
|
-
id: { type: 'string' },
|
|
166
|
-
title: { type: 'string' },
|
|
167
|
-
status: { type: 'string', enum: ['active', 'paused', 'done'] },
|
|
168
|
-
checks: { type: 'array', items: { type: 'string' } },
|
|
169
|
-
notes: { type: 'string' },
|
|
170
|
-
}, []),
|
|
171
|
-
definition('repository_stuck_diagnose', 'Diagnose likely repository workflow blockers from Git state and registered goals.', {
|
|
172
|
-
repo_id: repoId,
|
|
173
|
-
checkout_id: { type: 'string', description: 'Optional checkout identity for repositories with multiple local clones.' },
|
|
174
|
-
}, [], true),
|
|
175
|
-
definition('repository_goal_run', 'Run one durable repository goal iteration, optionally executing its configured checks and recording a goal-run artifact.', {
|
|
176
|
-
repo_id: repoId,
|
|
177
|
-
checkout_id: { type: 'string', description: 'Optional checkout identity for repositories with multiple local clones.' },
|
|
178
|
-
goal_id: { type: 'string', description: 'Goal id. Defaults to the first active goal.' },
|
|
179
|
-
run_checks: { type: 'boolean', description: 'When true, execute configured checks. Defaults to diagnosis-only.' },
|
|
180
|
-
}, []),
|
|
181
|
-
definition('repository_goal_runs', 'List recent repository goal-run artifacts.', {
|
|
182
|
-
repo_id: repoId,
|
|
183
|
-
checkout_id: { type: 'string', description: 'Optional checkout identity for repositories with multiple local clones.' },
|
|
184
|
-
limit: { type: 'number' },
|
|
185
|
-
}, [], true),
|
|
186
|
-
|
|
187
164
|
definition('repository_git_status', 'Return a structured Git status snapshot for the selected repository checkout.', {
|
|
188
165
|
repo_id: repoId,
|
|
189
166
|
checkout_id: { type: 'string', description: 'Optional checkout identity for repositories with multiple local clones.' },
|
|
@@ -270,7 +247,7 @@ export const repositoryToolDefinitions: McpToolDefinition[] = [
|
|
|
270
247
|
cwd: { type: 'string', description: 'Optional root-relative working directory.' },
|
|
271
248
|
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.' },
|
|
272
249
|
}, ['command'], true),
|
|
273
|
-
definition('repository_command_execute', 'Execute one repository-scoped
|
|
250
|
+
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.', {
|
|
274
251
|
repo_id: repoId,
|
|
275
252
|
checkout_id: { type: 'string', description: 'Optional checkout identity for repositories with multiple local clones.' },
|
|
276
253
|
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.' },
|
|
@@ -316,23 +293,56 @@ export interface RepositoryToolCallerContext {
|
|
|
316
293
|
controllerInstanceId?: string;
|
|
317
294
|
}
|
|
318
295
|
|
|
296
|
+
function claimedExplicitWork(
|
|
297
|
+
controllerHome: string,
|
|
298
|
+
repoId: string,
|
|
299
|
+
caller: RepositoryToolCallerContext | undefined,
|
|
300
|
+
requestedWorkId: string,
|
|
301
|
+
) {
|
|
302
|
+
if (!caller?.principalId?.trim()) return undefined;
|
|
303
|
+
const work = getWorkContract({ controllerHome, repoId }, requestedWorkId);
|
|
304
|
+
if (!work || isTerminalWorkContractStatus(work.status)) throw new Error(`WORK_ATTRIBUTION_INVALID: ${requestedWorkId}`);
|
|
305
|
+
const owner = getControllerSession({ controllerHome, repoId }, requestedWorkId);
|
|
306
|
+
if (!owner) throw new Error(`WORK_CONTROLLER_CLAIM_REQUIRED: ${requestedWorkId}`);
|
|
307
|
+
if ((owner.principalId?.trim() || owner.controllerId) !== caller.principalId.trim()) throw new Error(`WORK_CONTROLLER_OWNERSHIP_MISMATCH: ${requestedWorkId}`);
|
|
308
|
+
return work;
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
function assertNoBoundExecutionSessionMutation(
|
|
312
|
+
controllerHome: string,
|
|
313
|
+
repository: ReturnType<typeof resolveRepositorySelection>,
|
|
314
|
+
caller?: RepositoryToolCallerContext,
|
|
315
|
+
): void {
|
|
316
|
+
if (!caller?.principalId?.trim() || !caller.sessionId?.trim()) return;
|
|
317
|
+
const executionSession = readExecutionSession(controllerHome, {
|
|
318
|
+
sessionId: caller.sessionId,
|
|
319
|
+
principalId: caller.principalId,
|
|
320
|
+
controllerInstanceId: caller.controllerInstanceId,
|
|
321
|
+
});
|
|
322
|
+
const workId = executionSession?.activeWorkId?.trim();
|
|
323
|
+
if (!workId || executionSession?.activeRepositoryId !== repository.repoId) return;
|
|
324
|
+
const work = getWorkContract({ controllerHome, repoId: repository.repoId }, workId);
|
|
325
|
+
if (!work) throw new Error(`WORK_ATTRIBUTION_INVALID: ${workId}`);
|
|
326
|
+
if (isTerminalWorkContractStatus(work.status)) {
|
|
327
|
+
throw new Error(`WORK_ATTRIBUTION_TERMINAL: ${work.workId}:${work.status}`);
|
|
328
|
+
}
|
|
329
|
+
throw new Error(`WORK_ATTRIBUTION_REQUIRED: ${work.workId}; active execution session mutations must pass work_id explicitly`);
|
|
330
|
+
}
|
|
331
|
+
|
|
319
332
|
function claimedSessionWorkId(
|
|
320
333
|
controllerHome: string,
|
|
321
334
|
repository: ReturnType<typeof resolveRepositorySelection>,
|
|
322
335
|
caller?: RepositoryToolCallerContext,
|
|
323
336
|
explicitWorkId?: unknown,
|
|
324
337
|
): string | undefined {
|
|
325
|
-
if (!caller?.principalId?.trim()) return undefined;
|
|
326
338
|
const requestedWorkId = typeof explicitWorkId === 'string' ? explicitWorkId.trim() : '';
|
|
327
339
|
if (requestedWorkId) {
|
|
328
|
-
const work =
|
|
329
|
-
if (!work
|
|
340
|
+
const work = claimedExplicitWork(controllerHome, repository.repoId, caller, requestedWorkId);
|
|
341
|
+
if (!work) return undefined;
|
|
330
342
|
if (work.checkoutId && work.checkoutId !== repository.activeCheckoutId) throw new Error(`WORK_CHECKOUT_MISMATCH: ${requestedWorkId}:${repository.activeCheckoutId}`);
|
|
331
|
-
const owner = getControllerSession({ controllerHome, repoId: repository.repoId }, requestedWorkId);
|
|
332
|
-
if (!owner) throw new Error(`WORK_CONTROLLER_CLAIM_REQUIRED: ${requestedWorkId}`);
|
|
333
|
-
if ((owner.principalId?.trim() || owner.controllerId) !== caller.principalId.trim()) throw new Error(`WORK_CONTROLLER_OWNERSHIP_MISMATCH: ${requestedWorkId}`);
|
|
334
343
|
return requestedWorkId;
|
|
335
344
|
}
|
|
345
|
+
if (!caller?.principalId?.trim()) return undefined;
|
|
336
346
|
if (caller.sessionId?.trim()) {
|
|
337
347
|
const executionSession = readExecutionSession(controllerHome, {
|
|
338
348
|
sessionId: caller.sessionId,
|
|
@@ -342,8 +352,11 @@ function claimedSessionWorkId(
|
|
|
342
352
|
const workId = executionSession?.activeWorkId?.trim();
|
|
343
353
|
if (workId && executionSession?.activeRepositoryId === repository.repoId && (!executionSession.activeCheckoutId || executionSession.activeCheckoutId === repository.activeCheckoutId)) {
|
|
344
354
|
const work = getWorkContract({ controllerHome, repoId: repository.repoId }, workId);
|
|
355
|
+
if (work && isTerminalWorkContractStatus(work.status)) {
|
|
356
|
+
throw new Error(`WORK_ATTRIBUTION_TERMINAL: ${work.workId}:${work.status}`);
|
|
357
|
+
}
|
|
345
358
|
const owner = getControllerSession({ controllerHome, repoId: repository.repoId }, workId);
|
|
346
|
-
if (work &&
|
|
359
|
+
if (work && owner?.sessionId === caller.sessionId && (owner.principalId?.trim() || owner.controllerId) === caller.principalId.trim()) return workId;
|
|
347
360
|
}
|
|
348
361
|
}
|
|
349
362
|
const principal = caller.principalId.trim();
|
|
@@ -356,7 +369,7 @@ function claimedSessionWorkId(
|
|
|
356
369
|
return undefined;
|
|
357
370
|
}
|
|
358
371
|
|
|
359
|
-
function claimedSessionEditBinding(
|
|
372
|
+
export function claimedSessionEditBinding(
|
|
360
373
|
controllerHome: string,
|
|
361
374
|
repository: ReturnType<typeof resolveRepositorySelection>,
|
|
362
375
|
caller?: RepositoryToolCallerContext,
|
|
@@ -376,8 +389,52 @@ function claimedSessionEditBinding(
|
|
|
376
389
|
};
|
|
377
390
|
}
|
|
378
391
|
|
|
379
|
-
function
|
|
380
|
-
|
|
392
|
+
function safePatchEditBinding(
|
|
393
|
+
controllerHome: string,
|
|
394
|
+
repository: ReturnType<typeof resolveRepositorySelection>,
|
|
395
|
+
caller: RepositoryToolCallerContext | undefined,
|
|
396
|
+
args: Record<string, unknown>,
|
|
397
|
+
): EditSessionBinding | undefined {
|
|
398
|
+
const explicitWorkId = typeof args.work_id === 'string' ? args.work_id.trim() : '';
|
|
399
|
+
if (explicitWorkId) return claimedSessionEditBinding(controllerHome, repository, caller, explicitWorkId);
|
|
400
|
+
const sessionId = typeof args.session_id === 'string' ? args.session_id.trim() : '';
|
|
401
|
+
if (sessionId) {
|
|
402
|
+
const existingWorkId = getEditSession(repository.canonicalRoot, sessionId).workId?.trim();
|
|
403
|
+
return existingWorkId
|
|
404
|
+
? claimedSessionEditBinding(controllerHome, repository, caller, existingWorkId)
|
|
405
|
+
: undefined;
|
|
406
|
+
}
|
|
407
|
+
assertNoBoundExecutionSessionMutation(controllerHome, repository, caller);
|
|
408
|
+
return undefined;
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
function resolveRepositorySelectionForClaimedWork(
|
|
412
|
+
controllerHome: string,
|
|
413
|
+
args: Record<string, unknown>,
|
|
414
|
+
repoIdValue: string,
|
|
415
|
+
caller?: RepositoryToolCallerContext,
|
|
416
|
+
): ReturnType<typeof resolveRepositorySelection> {
|
|
417
|
+
const checkoutId = typeof args.checkout_id === 'string' ? args.checkout_id.trim() : '';
|
|
418
|
+
const explicitWorkId = typeof args.work_id === 'string' ? args.work_id.trim() : '';
|
|
419
|
+
const repository = resolveRepositorySelection({
|
|
420
|
+
repoId: repoIdValue || undefined,
|
|
421
|
+
checkoutId: checkoutId || undefined,
|
|
422
|
+
controllerHome,
|
|
423
|
+
allowSoleRepository: true,
|
|
424
|
+
});
|
|
425
|
+
if (!explicitWorkId || checkoutId) return repository;
|
|
426
|
+
const work = claimedExplicitWork(controllerHome, repository.repoId, caller, explicitWorkId);
|
|
427
|
+
if (!work?.checkoutId || work.checkoutId === repository.activeCheckoutId) return repository;
|
|
428
|
+
return resolveRepositorySelection({
|
|
429
|
+
repoId: repository.repoId,
|
|
430
|
+
checkoutId: work.checkoutId,
|
|
431
|
+
controllerHome,
|
|
432
|
+
allowSoleRepository: true,
|
|
433
|
+
});
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
function rawDefaultBranchMergeCommand(repository: ReturnType<typeof resolveRepositorySelection>, command: unknown): boolean {
|
|
437
|
+
if (!repository.defaultBranch) return false;
|
|
381
438
|
const checkout = repository.checkouts.find((entry) => entry.checkoutId === repository.activeCheckoutId);
|
|
382
439
|
if (checkout?.branch !== repository.defaultBranch) return false;
|
|
383
440
|
const normalized = normalizeRepositoryCommand(command);
|
|
@@ -417,13 +474,11 @@ function resolveRepositoryCommandTarget(
|
|
|
417
474
|
workspace: { workspaceId: target.workspaceId, root: target.canonicalRoot, registered: false },
|
|
418
475
|
};
|
|
419
476
|
}
|
|
420
|
-
const repository =
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
controllerHome,
|
|
424
|
-
|
|
425
|
-
});
|
|
426
|
-
const workId = claimedSessionWorkId(controllerHome, repository, caller, args.work_id);
|
|
477
|
+
const repository = resolveRepositorySelectionForClaimedWork(controllerHome, args, repoIdValue, caller);
|
|
478
|
+
const explicitWorkId = typeof args.work_id === 'string' ? args.work_id.trim() : '';
|
|
479
|
+
const workId = explicitWorkId
|
|
480
|
+
? claimedSessionWorkId(controllerHome, repository, caller, explicitWorkId)
|
|
481
|
+
: undefined;
|
|
427
482
|
return {
|
|
428
483
|
repository,
|
|
429
484
|
executionIdentity: {
|
|
@@ -523,6 +578,33 @@ function failure(error: unknown): RepositoryToolResult {
|
|
|
523
578
|
return { ...result({ error: { code, message, ...(compactDetails !== undefined ? { details: compactDetails } : {}) } }), isError: true };
|
|
524
579
|
}
|
|
525
580
|
|
|
581
|
+
interface RepositoryExplorationGuidance {
|
|
582
|
+
code: 'FRAGMENTED_REPOSITORY_EXPLORATION';
|
|
583
|
+
recommendedTool: 'rh_context';
|
|
584
|
+
recommendedOperation: 'search';
|
|
585
|
+
message: string;
|
|
586
|
+
}
|
|
587
|
+
|
|
588
|
+
function fragmentedRepositoryExplorationGuidance(command: unknown): RepositoryExplorationGuidance | undefined {
|
|
589
|
+
if (typeof command !== 'string') return undefined;
|
|
590
|
+
const segments = command.split(/(?:&&|\|\||[;|])/g);
|
|
591
|
+
const readPrograms = new Set<string>();
|
|
592
|
+
let readStepCount = 0;
|
|
593
|
+
for (const segment of segments) {
|
|
594
|
+
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);
|
|
595
|
+
if (!match) continue;
|
|
596
|
+
readStepCount += 1;
|
|
597
|
+
readPrograms.add(match[1]!.toLowerCase());
|
|
598
|
+
}
|
|
599
|
+
if (readStepCount < 2) return undefined;
|
|
600
|
+
return {
|
|
601
|
+
code: 'FRAGMENTED_REPOSITORY_EXPLORATION',
|
|
602
|
+
recommendedTool: 'rh_context',
|
|
603
|
+
recommendedOperation: 'search',
|
|
604
|
+
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.`,
|
|
605
|
+
};
|
|
606
|
+
}
|
|
607
|
+
|
|
526
608
|
function compactProcessCommandPayload(input: {
|
|
527
609
|
accepted?: boolean;
|
|
528
610
|
mode: string;
|
|
@@ -545,6 +627,7 @@ function compactProcessCommandPayload(input: {
|
|
|
545
627
|
/** summary (default) omits nested process / routing dumps; detail restores diagnostics. */
|
|
546
628
|
detailLevel?: 'summary' | 'detail';
|
|
547
629
|
includeFullProcess?: boolean;
|
|
630
|
+
guidance?: RepositoryExplorationGuidance;
|
|
548
631
|
}): Record<string, unknown> {
|
|
549
632
|
const output = compactCommandOutput(input.stdout, input.stderr, { ok: input.ok === true });
|
|
550
633
|
const detail = input.detailLevel === 'detail' || input.includeFullProcess === true;
|
|
@@ -572,10 +655,14 @@ function compactProcessCommandPayload(input: {
|
|
|
572
655
|
...(input.workspace ? { workspace: input.workspace } : {}),
|
|
573
656
|
...(input.processId ? { processId: input.processId } : {}),
|
|
574
657
|
...(completed ? { exitCode: input.exitCode ?? (ok ? 0 : 1) } : {}),
|
|
658
|
+
// A running default response otherwise loses its only dependency-bound
|
|
659
|
+
// continuation advice when the detailed Process record is omitted.
|
|
660
|
+
...(!completed ? { next: input.next } : {}),
|
|
575
661
|
stdout: output.stdout ?? '',
|
|
576
662
|
stderr: output.stderr ?? '',
|
|
577
663
|
...(output.stdoutTruncated ? { stdoutTruncated: true, stdoutBytes: output.stdoutBytes } : {}),
|
|
578
664
|
...(output.stderrTruncated ? { stderrTruncated: true, stderrBytes: output.stderrBytes } : {}),
|
|
665
|
+
...(input.guidance ? { guidance: input.guidance, suggestedOperation: 'rh_context' } : {}),
|
|
579
666
|
};
|
|
580
667
|
if (completed && !ok) {
|
|
581
668
|
payload.error = {
|
|
@@ -623,6 +710,7 @@ function compactProcessCommandPayload(input: {
|
|
|
623
710
|
}
|
|
624
711
|
: {}),
|
|
625
712
|
durableSideEffects: effects,
|
|
713
|
+
...(input.guidance ? { guidance: input.guidance, suggestedOperation: 'rh_context' } : {}),
|
|
626
714
|
next: input.next,
|
|
627
715
|
detailLevel: 'detail',
|
|
628
716
|
};
|
|
@@ -664,10 +752,33 @@ export async function callRepositoryTool(
|
|
|
664
752
|
args: Record<string, unknown>,
|
|
665
753
|
caller?: RepositoryToolCallerContext,
|
|
666
754
|
): Promise<RepositoryToolResult | undefined> {
|
|
667
|
-
if (!name.startsWith('repository_')) return undefined;
|
|
755
|
+
if (!name.startsWith('repository_') && name !== 'read_repository_file') return undefined;
|
|
668
756
|
try {
|
|
669
757
|
const repoIdValue = typeof args.repo_id === 'string' ? args.repo_id.trim() : '';
|
|
670
758
|
switch (name) {
|
|
759
|
+
case 'read_repository_file': {
|
|
760
|
+
const repository = resolveRepositorySelection({
|
|
761
|
+
repoId: typeof args.repo_id === 'string' ? args.repo_id : undefined,
|
|
762
|
+
checkoutId: typeof args.checkout_id === 'string' ? args.checkout_id : undefined,
|
|
763
|
+
controllerHome,
|
|
764
|
+
allowSoleRepository: true,
|
|
765
|
+
});
|
|
766
|
+
const path = String(args.path ?? '').trim();
|
|
767
|
+
if (!path) throw new Error('REPOSITORY_PATH_REQUIRED: path is required');
|
|
768
|
+
const session = caller?.sessionId
|
|
769
|
+
? { sessionId: caller.sessionId, repoId: repository.repoId, checkoutId: repository.activeCheckoutId }
|
|
770
|
+
: undefined;
|
|
771
|
+
const range = readRepositoryRange(
|
|
772
|
+
repository.canonicalRoot,
|
|
773
|
+
getMcpPolicy('controller', { repoRoot: repository.canonicalRoot }),
|
|
774
|
+
path,
|
|
775
|
+
typeof args.start_line === 'number' ? args.start_line : 1,
|
|
776
|
+
typeof args.end_line === 'number' ? args.end_line : 200,
|
|
777
|
+
session,
|
|
778
|
+
);
|
|
779
|
+
const redacted = redactMcpText(range.content);
|
|
780
|
+
return result({ ...range, content: redacted.text, redactions: redacted.redactions });
|
|
781
|
+
}
|
|
671
782
|
case 'repository_register': {
|
|
672
783
|
const startedAt = performance.now();
|
|
673
784
|
const registerInput = {
|
|
@@ -824,38 +935,6 @@ export async function callRepositoryTool(
|
|
|
824
935
|
checkout_id: typeof args.checkout_id === 'string' ? args.checkout_id : payload.checkout_id,
|
|
825
936
|
});
|
|
826
937
|
}
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
case 'repository_goal_list': {
|
|
831
|
-
const repository = resolveRepositorySelection({ repoId: repoIdValue || undefined, checkoutId: typeof args.checkout_id === 'string' ? args.checkout_id : undefined, controllerHome, allowSoleRepository: true });
|
|
832
|
-
return result({ repoId: repository.repoId, checkoutId: repository.activeCheckoutId, registry: readRepositoryGoalRegistry(repository) });
|
|
833
|
-
}
|
|
834
|
-
case 'repository_goal_upsert': {
|
|
835
|
-
const repository = resolveRepositorySelection({ repoId: repoIdValue || undefined, checkoutId: typeof args.checkout_id === 'string' ? args.checkout_id : undefined, controllerHome, allowSoleRepository: true });
|
|
836
|
-
return result({ repoId: repository.repoId, checkoutId: repository.activeCheckoutId, ...upsertRepositoryGoal(repository, { id: args.id, title: args.title, status: args.status, checks: args.checks, notes: args.notes }) as unknown as Record<string, unknown> });
|
|
837
|
-
}
|
|
838
|
-
case 'repository_stuck_diagnose': {
|
|
839
|
-
const repository = resolveRepositorySelection({ repoId: repoIdValue || undefined, checkoutId: typeof args.checkout_id === 'string' ? args.checkout_id : undefined, controllerHome, allowSoleRepository: true });
|
|
840
|
-
return result({ diagnosis: diagnoseRepositoryStuckState(repository) });
|
|
841
|
-
}
|
|
842
|
-
|
|
843
|
-
case 'repository_goal_run': {
|
|
844
|
-
const repository = resolveRepositorySelection({ repoId: repoIdValue || undefined, checkoutId: typeof args.checkout_id === 'string' ? args.checkout_id : undefined, controllerHome, allowSoleRepository: true });
|
|
845
|
-
const ran = withControllerLock(
|
|
846
|
-
controllerHome,
|
|
847
|
-
{ scope: 'repository', repoId: repository.repoId },
|
|
848
|
-
'mcp:repository_goal_run',
|
|
849
|
-
() => runRepositoryGoal(repository, { goalId: args.goal_id, runChecks: args.run_checks }),
|
|
850
|
-
60_000,
|
|
851
|
-
);
|
|
852
|
-
return result({ repoId: repository.repoId, checkoutId: repository.activeCheckoutId, ...ran as unknown as Record<string, unknown> });
|
|
853
|
-
}
|
|
854
|
-
case 'repository_goal_runs': {
|
|
855
|
-
const repository = resolveRepositorySelection({ repoId: repoIdValue || undefined, checkoutId: typeof args.checkout_id === 'string' ? args.checkout_id : undefined, controllerHome, allowSoleRepository: true });
|
|
856
|
-
const limit = typeof args.limit === 'number' ? args.limit : typeof args.limit === 'string' ? Number(args.limit) : undefined;
|
|
857
|
-
return result({ repoId: repository.repoId, checkoutId: repository.activeCheckoutId, runs: listRepositoryGoalRuns(repository, limit) });
|
|
858
|
-
}
|
|
859
938
|
case 'repository_git_status': {
|
|
860
939
|
const repository = resolveRepositorySelection({ repoId: repoIdValue || undefined, checkoutId: typeof args.checkout_id === 'string' ? args.checkout_id : undefined, controllerHome, allowSoleRepository: true });
|
|
861
940
|
const status = args.refresh === true
|
|
@@ -917,13 +996,8 @@ export async function callRepositoryTool(
|
|
|
917
996
|
});
|
|
918
997
|
}
|
|
919
998
|
case 'repository_safe_patch_apply': {
|
|
920
|
-
const repository =
|
|
921
|
-
|
|
922
|
-
checkoutId: typeof args.checkout_id === 'string' ? args.checkout_id : undefined,
|
|
923
|
-
controllerHome,
|
|
924
|
-
allowSoleRepository: true,
|
|
925
|
-
});
|
|
926
|
-
const binding = claimedSessionEditBinding(controllerHome, repository, caller, args.work_id);
|
|
999
|
+
const repository = resolveRepositorySelectionForClaimedWork(controllerHome, args, repoIdValue, caller);
|
|
1000
|
+
const binding = safePatchEditBinding(controllerHome, repository, caller, args);
|
|
927
1001
|
const applied = withControllerLock(
|
|
928
1002
|
controllerHome,
|
|
929
1003
|
{ scope: 'repository', repoId: repository.repoId },
|
|
@@ -1022,10 +1096,16 @@ export async function callRepositoryTool(
|
|
|
1022
1096
|
});
|
|
1023
1097
|
}
|
|
1024
1098
|
case 'repository_command_execute': {
|
|
1099
|
+
const explorationGuidance = fragmentedRepositoryExplorationGuidance(args.command);
|
|
1025
1100
|
const target = resolveRepositoryCommandTarget(controllerHome, args, repoIdValue, caller);
|
|
1026
1101
|
const { repository, executionIdentity } = target;
|
|
1027
|
-
|
|
1028
|
-
|
|
1102
|
+
const explicitWorkId = typeof args.work_id === 'string' ? args.work_id.trim() : '';
|
|
1103
|
+
if (!explicitWorkId) assertNoBoundExecutionSessionMutation(controllerHome, repository, caller);
|
|
1104
|
+
const deliveryWorkId = rawDefaultBranchMergeCommand(repository, args.command)
|
|
1105
|
+
? executionIdentity.workId
|
|
1106
|
+
: undefined;
|
|
1107
|
+
if (deliveryWorkId) {
|
|
1108
|
+
throw new Error(`WORK_DELIVERY_REQUIRES_FINALIZE: ${deliveryWorkId} must pass Work verification and use rh_work finalize before default-branch integration`);
|
|
1029
1109
|
}
|
|
1030
1110
|
const timeoutMs = typeof args.timeout_ms === 'number'
|
|
1031
1111
|
? args.timeout_ms
|
|
@@ -1052,16 +1132,33 @@ export async function callRepositoryTool(
|
|
|
1052
1132
|
const forceDurable = fromDurableWorker
|
|
1053
1133
|
|| args.mode === 'durable'
|
|
1054
1134
|
|| args.force_durable === true;
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1135
|
+
// repository_command_execute owns its command execution architecture.
|
|
1136
|
+
// Do not send ordinary command text through Thin Harness semantic risk
|
|
1137
|
+
// routing: that creates duplicate regex/classifier policy and turns
|
|
1138
|
+
// unknown CLI shapes into false durable/reject decisions. Only an
|
|
1139
|
+
// explicitly requested durable mode uses the generic durable router.
|
|
1140
|
+
const routingDecision = forceDurable
|
|
1141
|
+
? routeExecution({
|
|
1142
|
+
operation: 'repository_command_execute',
|
|
1143
|
+
mode: 'durable',
|
|
1144
|
+
timeoutMs,
|
|
1145
|
+
background: args.background === true || args.async === true,
|
|
1146
|
+
})
|
|
1147
|
+
: {
|
|
1148
|
+
mode: 'fast' as const,
|
|
1149
|
+
reasons: ['repository_command_process_runtime_authoritative'],
|
|
1150
|
+
risk: 'unknown' as const,
|
|
1151
|
+
estimatedClass: 'unknown' as const,
|
|
1152
|
+
requiresIsolation: false,
|
|
1153
|
+
requiresRecovery: false,
|
|
1154
|
+
suggestedOperation: undefined,
|
|
1155
|
+
effects: {
|
|
1156
|
+
readsWorkspace: true,
|
|
1157
|
+
mutatesWorkspace: true,
|
|
1158
|
+
mutatesGitRefs: false,
|
|
1159
|
+
remoteWrite: false,
|
|
1160
|
+
},
|
|
1161
|
+
};
|
|
1065
1162
|
// Unified Process Runtime for local commands (Direct/Managed) when not forced durable.
|
|
1066
1163
|
// Ephemeral workspaces cannot persist a recoverable async Process handle,
|
|
1067
1164
|
// so their async requests remain promotion-required below.
|
|
@@ -1072,7 +1169,43 @@ export async function callRepositoryTool(
|
|
|
1072
1169
|
defaultBranch: repository.defaultBranch,
|
|
1073
1170
|
timeoutMs,
|
|
1074
1171
|
});
|
|
1075
|
-
if (routeClass.route === '
|
|
1172
|
+
if (routeClass.route === 'reject') {
|
|
1173
|
+
return result({
|
|
1174
|
+
accepted: false,
|
|
1175
|
+
mode: 'reject',
|
|
1176
|
+
path: routeClass.reason,
|
|
1177
|
+
route: 'reject',
|
|
1178
|
+
status: 'rejected',
|
|
1179
|
+
repoId: repository.repoId,
|
|
1180
|
+
checkoutId: repository.activeCheckoutId,
|
|
1181
|
+
workspace: target.workspace,
|
|
1182
|
+
message: routeClass.reason === 'standalone_recovery_lifecycle_required'
|
|
1183
|
+
? 'Canonical Runtime and connector lifecycle operations must be submitted to the standalone Forge Recovery owner, not executed as a child of repository Process Runtime.'
|
|
1184
|
+
: 'Repository command execution was rejected by Process Runtime routing policy.',
|
|
1185
|
+
suggestedOperation: routeClass.reason === 'standalone_recovery_lifecycle_required'
|
|
1186
|
+
? 'Use the standalone Forge Recovery connector.'
|
|
1187
|
+
: routingDecision.suggestedOperation,
|
|
1188
|
+
durableSideEffects: {
|
|
1189
|
+
executionJobCount: 0,
|
|
1190
|
+
localJobCount: 0,
|
|
1191
|
+
workerSpawnCount: 0,
|
|
1192
|
+
projectionUpdateCount: 0,
|
|
1193
|
+
},
|
|
1194
|
+
});
|
|
1195
|
+
}
|
|
1196
|
+
if (routeClass.route === 'durable' && target.workspace) {
|
|
1197
|
+
return result({
|
|
1198
|
+
accepted: false,
|
|
1199
|
+
mode: 'durable',
|
|
1200
|
+
path: 'ephemeral_workspace_promotion_required',
|
|
1201
|
+
repoId: repository.repoId,
|
|
1202
|
+
checkoutId: repository.activeCheckoutId,
|
|
1203
|
+
workspace: target.workspace,
|
|
1204
|
+
message: 'Ephemeral workspaces must be registered before durable remote effects so Process identity and reconciliation have a stable repository authority.',
|
|
1205
|
+
suggestedOperation: 'repository_register',
|
|
1206
|
+
});
|
|
1207
|
+
}
|
|
1208
|
+
if (routeClass.route === 'process_direct' || routeClass.route === 'process_managed' || routeClass.route === 'durable') {
|
|
1076
1209
|
const processResult = await executeRepositoryCommandViaProcessRuntime({
|
|
1077
1210
|
controllerHome,
|
|
1078
1211
|
repository,
|
|
@@ -1147,13 +1280,14 @@ export async function callRepositoryTool(
|
|
|
1147
1280
|
stdout: processResult.stdout,
|
|
1148
1281
|
stderr: processResult.stderr,
|
|
1149
1282
|
durableSideEffects: processResult.durableSideEffects,
|
|
1283
|
+
guidance: explorationGuidance,
|
|
1150
1284
|
next: directWithoutHandle
|
|
1151
1285
|
? processResult.reason === 'readonly_fast_path'
|
|
1152
1286
|
? 'Bounded readonly execution completed without Process record / Lease / Local Job / ExecutionJob / Worker.'
|
|
1153
1287
|
: 'Bounded ephemeral workspace execution completed without Process record / Lease / Local Job / ExecutionJob / Worker.'
|
|
1154
1288
|
: processResult.route === 'process_direct' || completed
|
|
1155
1289
|
? 'Process Runtime completed without Local Job / ExecutionJob / Worker.'
|
|
1156
|
-
: `Process Runtime is managing ${handle?.processId};
|
|
1290
|
+
: `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.`,
|
|
1157
1291
|
detailLevel,
|
|
1158
1292
|
});
|
|
1159
1293
|
payload.status = status;
|
|
@@ -1270,6 +1404,12 @@ export async function callRepositoryTool(
|
|
|
1270
1404
|
routing: compactRoutingSummary({ path: 'durable', mode: 'durable', reasons: [routingDecision.reasons.join(','), 'local_bridge_execution_retired'] }),
|
|
1271
1405
|
message: 'This command requires explicit external Controller handling; Local Bridge Jobs are retired for repository commands.',
|
|
1272
1406
|
suggestedOperation: 'Create or claim WorkContract, then use rh_work.launcher_start or a Process Runtime-compatible command.',
|
|
1407
|
+
externalEffect: {
|
|
1408
|
+
outcome: 'not_started',
|
|
1409
|
+
ambiguousFailureOutcome: 'outcome_unknown',
|
|
1410
|
+
replayPolicy: 'never_auto_retry',
|
|
1411
|
+
reconciliation: 'After an ambiguous dispatch failure, inspect the remote ref/registry/release state before deciding whether to retry.',
|
|
1412
|
+
},
|
|
1273
1413
|
});
|
|
1274
1414
|
}
|
|
1275
1415
|
case 'repository_batch_execute': {
|