@moretea-labs/forge 1.5.1 → 1.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +2 -0
- package/CHANGELOG.md +46 -0
- package/CLAUDE.md +2 -0
- package/DESIGN.md +7 -2
- package/README.md +4 -4
- package/README.zh-CN.md +2 -2
- package/SKILL.md +2 -2
- package/THIRD_PARTY_NOTICES.md +1 -1
- package/agents/openai.yaml +1 -1
- package/assets/hooks/hook-input.sh +11 -8
- package/assets/hooks/lib/session-state.sh +10 -7
- package/assets/hooks/lib/workflow-state.sh +13 -177
- package/assets/hooks/post-tool-observer.sh +8 -2
- package/assets/hooks/pre-edit-guard.sh +8 -39
- package/assets/hooks/prompt-guard.sh +7 -83
- package/assets/hooks/session-start-context.sh +56 -1
- package/assets/partials/05-workflow.partial.md +1 -1
- package/assets/partials-agents/03-orchestration.partial.md +1 -1
- package/assets/plugin-registry.v1.json +54 -3
- package/assets/reference-configs/document-generation.md +1 -1
- package/assets/reference-configs/harness-overview.md +1 -1
- package/assets/reference-configs/hook-operations.md +1 -1
- package/assets/reference-configs/sprint-contracts.md +3 -3
- package/assets/skill-version.json +2 -2
- package/assets/templates/contract.template.md +2 -7
- package/assets/templates/helpers/capture-plan.sh +2 -2
- package/assets/templates/helpers/check-task-workflow.sh +4 -4
- package/assets/templates/helpers/contract-worktree.sh +1 -21
- package/assets/templates/helpers/ensure-task-workflow.sh +13 -38
- package/assets/templates/helpers/migrate-project-template.sh +22 -45
- package/assets/templates/helpers/new-plan.sh +1 -1
- package/assets/templates/helpers/plan-to-todo.sh +12 -37
- package/assets/templates/helpers/ship-worktrees.sh +2 -29
- package/assets/templates/helpers/sprint-backlog.sh +6 -6
- package/assets/templates/helpers/verify-contract.sh +1 -111
- package/assets/templates/helpers/verify-sprint.sh +3 -180
- package/assets/templates/plan.template.md +1 -1
- package/assets/templates/review.template.md +9 -34
- package/assets/workflow-contract.v1.json +10 -19
- package/docs/README.md +10 -10
- package/docs/architecture/CURRENT.md +170 -0
- package/docs/architecture/EVOLUTION.md +42 -0
- package/docs/architecture/current/README.md +4 -156
- package/docs/architecture/decisions/20260803-release-identity-binding-and-exit-policy.md +2 -2
- package/docs/architecture/decisions/20260823-immediate-controller-relay.md +53 -0
- package/docs/architecture/decisions/20260826-browser-runtime-v2.md +73 -0
- package/docs/architecture/history/README.md +7 -0
- package/docs/architecture/{chatgpt-handoff-facade.md → history/chatgpt-handoff-facade.md} +4 -0
- package/docs/architecture/{global-hook-runtime.md → history/global-hook-runtime.md} +7 -3
- package/docs/architecture/{ios-semantic-automation-provider-v2.md → history/ios-semantic-automation-provider-v2.md} +6 -2
- package/docs/architecture/history.md +3 -34
- package/docs/architecture/index.md +15 -98
- package/docs/architecture/modules/controller-runtime/transport-lifecycle.md +1 -1
- package/docs/architecture/reviews/2026-08-22-semantic-harness-convergence-acceptance.md +39 -0
- package/docs/architecture/versions/1.6.md +38 -0
- package/docs/architecture/versions/1.7.md +41 -0
- package/docs/forge-chatgpt-browser-engine.md +2 -2
- package/docs/forge-chatgpt-mcp-setup.md +4 -28
- package/docs/forge-chatgpt-supervised-automation.md +3 -3
- package/docs/forge-github-issue-launcher.md +1 -1
- package/docs/forge-runtime-self-healing-loop.md +1 -1
- package/docs/operations/controller-browser-plugin.md +38 -22
- package/docs/operations/controller-performance-and-502.md +124 -0
- package/docs/operations/controller-reliability-runbook.md +1 -1
- package/docs/operations/features.md +3 -3
- package/docs/operations/github-repository.md +1 -1
- package/docs/operations/homebrew.md +2 -2
- package/docs/operations/mcp-tool-exposure.md +5 -3
- package/docs/tutorials/01-install-and-start.md +1 -1
- package/docs/tutorials/01-install-and-start.zh-CN.md +1 -1
- package/docs/wiki/Architecture.md +6 -6
- package/docs/wiki/Implementation.md +2 -2
- package/docs/wiki/Installation.md +1 -1
- package/docs/wiki/Integrations.md +2 -2
- package/docs/wiki/Quick-Start.md +1 -1
- package/docs/wiki/Work-Lifecycle.md +1 -1
- package/package.json +29 -10
- package/scripts/activate-source-baseline.ts +17 -13
- package/scripts/benchmark-background-check-overlap.ts +228 -0
- package/scripts/benchmark-mcp-host.sh +117 -0
- package/scripts/benchmark-mcp-transport.ts +170 -0
- package/scripts/benchmark-quality-harness.ts +146 -0
- package/scripts/benchmark-route-session-concurrency.ts +207 -6
- package/scripts/benchmark-thin-harness-mcp-e2e.ts +7 -1
- package/scripts/benchmark-typescript-navigation.ts +186 -0
- package/scripts/benchmark-work-efficiency.ts +334 -0
- package/scripts/capture-plan.sh +3 -3
- package/scripts/check-agent-tooling.sh +8 -35
- package/scripts/check-architecture-sync.sh +17 -86
- package/scripts/check-mcp-compatibility.ts +14 -0
- package/scripts/check-public-docs.sh +14 -1
- package/scripts/check-runtime-architecture.mjs +107 -64
- package/scripts/check-stable-baseline.ts +92 -0
- package/scripts/check-task-workflow.sh +4 -4
- package/scripts/contract-worktree.sh +1 -21
- package/scripts/ensure-task-workflow.sh +22 -55
- package/scripts/host-temporary-cloud-mcp-e2e.sh +265 -0
- package/scripts/install-standalone-recovery.ts +24 -0
- package/scripts/lib/project-init-lib.sh +15 -44
- package/scripts/migrate-chatgpt-automation-schedules.ts +64 -0
- package/scripts/migrate-project-template.sh +23 -1179
- package/scripts/new-plan.sh +1 -1
- package/scripts/plan-to-todo.sh +11 -36
- package/scripts/run-governed-gate.ts +2 -1
- package/scripts/ship-worktrees.sh +2 -29
- package/scripts/smoke-ios-physical-device.ts +4 -2
- package/scripts/smoke-runtime-recovery.ts +1 -35
- package/scripts/smoke-schedule-engine.ts +1 -20
- package/scripts/sprint-backlog.sh +1 -1
- package/scripts/verify-contract.sh +1 -111
- package/scripts/verify-forge-runtime.sh +0 -1
- package/scripts/verify-sprint.sh +3 -180
- package/scripts/workflow-contract.ts +1 -5
- package/src/cli/commands/chatgpt.ts +31 -2
- package/src/cli/commands/init-hook.ts +3 -3
- package/src/cli/commands/mcp.ts +9 -5
- package/src/cli/commands/plugin.ts +37 -10
- package/src/cli/commands/recovery.ts +25 -3
- package/src/cli/commands/runtime.ts +55 -3
- package/src/cli/commands/security.ts +12 -1
- package/src/cli/commands/setup-profile.ts +31 -21
- package/src/cli/controller/check-runner.ts +106 -3
- package/src/cli/controller/composite-result.ts +1 -1
- package/src/cli/controller/context/focus.ts +51 -0
- package/src/cli/controller/context/instruction-context.ts +114 -0
- package/src/cli/controller/context/known-paths.ts +76 -0
- package/src/cli/controller/context/query-planning.ts +110 -0
- package/src/cli/controller/context/rule-resolution.ts +532 -0
- package/src/cli/controller/context/source-materializer.ts +278 -0
- package/src/cli/controller/context/structural.ts +16 -0
- package/src/cli/controller/context/types.ts +286 -0
- package/src/cli/controller/context-pack.ts +898 -430
- package/src/cli/controller/launch-agents.ts +77 -2
- package/src/cli/controller/operational-plan.ts +2 -2
- package/src/cli/controller/work-mode.ts +6 -4
- package/src/cli/editing/edit-session.ts +60 -7
- package/src/cli/github/github.ts +133 -0
- package/src/cli/hook/prompt-guard-decision.ts +17 -18
- package/src/cli/hook/prompt-intents.ts +1 -1
- package/src/cli/installer/managed-entries.ts +15 -1
- package/src/cli/local-bridge/console-automations.ts +225 -67
- package/src/cli/local-bridge/console-view-models.ts +3 -35
- package/src/cli/local-bridge/facade-api.ts +2 -217
- package/src/cli/local-bridge/frontend/src/App.tsx +3 -3
- package/src/cli/local-bridge/frontend/src/features/automations/AutomationsView.tsx +153 -3
- package/src/cli/local-bridge/frontend/src/features/capabilities/CapabilitiesView.tsx +37 -4
- package/src/cli/local-bridge/frontend/src/features/overview/OverviewView.tsx +183 -3
- package/src/cli/local-bridge/frontend/src/features/repositories/RepositoriesView.tsx +1 -1
- package/src/cli/local-bridge/frontend/src/features/work/WorkView.tsx +4 -3
- package/src/cli/local-bridge/frontend/src/lib/api.ts +18 -11
- package/src/cli/local-bridge/frontend/src/lib/routes.ts +1 -1
- package/src/cli/local-bridge/frontend/src/shell/CommandBar.tsx +1 -1
- package/src/cli/local-bridge/frontend/src/shell/Sidebar.tsx +4 -3
- package/src/cli/local-bridge/frontend/src/styles.css +27 -11
- package/src/cli/local-bridge/frontend/src/types.ts +8 -7
- package/src/cli/local-bridge/job-store.ts +1 -490
- package/src/cli/local-bridge/server.ts +29 -532
- package/src/cli/local-bridge/ui-dist/app.css +1 -1
- package/src/cli/local-bridge/ui-dist/app.js +5101 -4967
- package/src/cli/mcp/auth.ts +5 -5
- package/src/cli/mcp/instructions.ts +3 -2
- package/src/cli/mcp/legacy-tool-service.ts +0 -189
- package/src/cli/mcp/multi-repository.ts +16 -5
- package/src/cli/mcp/oauth.ts +175 -26
- package/src/cli/mcp/paths.ts +8 -2
- package/src/cli/mcp/repository-tools.ts +356 -101
- package/src/cli/mcp/server.ts +625 -54
- package/src/cli/mcp/tool-capability-cache.ts +1 -1
- package/src/cli/mcp/toolset-selection.ts +1 -1
- package/src/cli/mcp/toolset.ts +42 -5
- package/src/cli/mcp/transports/http.ts +125 -15
- package/src/cli/mcp/transports/session-registry.ts +67 -5
- package/src/cli/mcp/types.ts +3 -3
- package/src/cli/repositories/command-classifier.ts +209 -14
- package/src/cli/repositories/command-executor.ts +55 -521
- package/src/cli/repositories/command-process.ts +108 -0
- package/src/cli/repositories/command-scope.ts +99 -41
- package/src/cli/repositories/controller-home.ts +7 -8
- package/src/cli/repositories/git-command-executor.ts +2 -0
- package/src/cli/repositories/locks.ts +53 -16
- package/src/cli/repositories/repository-snapshot.ts +121 -0
- package/src/cli/repositories/safe-patch.ts +6 -4
- package/src/cli/repositories/selected-path-actions.ts +17 -9
- package/src/cli/repositories/structured-git.ts +110 -10
- package/src/cli/repository/inspector.ts +565 -62
- package/src/cli/repository/session-cache.ts +58 -17
- package/src/cli/v81-entry.ts +1 -4
- package/src/effects/fs-transaction.ts +85 -17
- package/src/runtime/context/codegraph-read-provider.ts +233 -2
- package/src/runtime/context/codegraph-sidecar.cjs +74 -40
- package/src/runtime/context/generic-lsp-provider.ts +355 -0
- package/src/runtime/context/lsp-client.ts +283 -0
- package/src/runtime/context/semantic-navigation.ts +275 -0
- package/src/runtime/context/swift-navigation.ts +565 -0
- package/src/runtime/context/typescript-navigation.ts +226 -0
- package/src/runtime/control-plane/dispatch-priority.ts +28 -0
- package/src/runtime/control-plane/execution/direct-edit-work-completion.ts +196 -2
- package/src/runtime/control-plane/execution/edit-validation-coordinator.ts +86 -24
- package/src/runtime/control-plane/execution/execution-identity.ts +65 -14
- package/src/runtime/control-plane/execution/session-store.ts +18 -0
- package/src/runtime/control-plane/execution/validation.ts +15 -2
- package/src/runtime/control-plane/execution/verification-evidence.ts +58 -3
- package/src/runtime/control-plane/execution/work-handle-store.ts +27 -2
- package/src/runtime/control-plane/execution/work-lifecycle-audit.ts +258 -0
- package/src/runtime/control-plane/execution/work-remote-delivery.ts +215 -0
- package/src/runtime/control-plane/execution/work-task-receipt.ts +54 -11
- package/src/runtime/control-plane/execution/work-terminal-cleanup.ts +175 -8
- package/src/runtime/control-plane/execution/work-validation-reconciler.ts +28 -21
- package/src/runtime/control-plane/execution/work-verification-snapshot.ts +87 -9
- package/src/runtime/control-plane/facade/capability-registry.ts +129 -25
- package/src/runtime/control-plane/facade/controller-round-relay.ts +991 -0
- package/src/runtime/control-plane/facade/controller-session-store.ts +144 -14
- package/src/runtime/control-plane/facade/goal-workloop-access.ts +9 -2
- package/src/runtime/control-plane/facade/goal-workloop.ts +885 -105
- package/src/runtime/control-plane/facade/index.ts +1 -0
- package/src/runtime/control-plane/facade/plan-contract-store.ts +211 -26
- package/src/runtime/control-plane/facade/requirement-board.ts +24 -8
- package/src/runtime/control-plane/facade/semantic-admission.ts +205 -0
- package/src/runtime/control-plane/facade/suggested-actions.ts +5 -1
- package/src/runtime/control-plane/facade/types.ts +55 -11
- package/src/runtime/control-plane/facade/work-contract-store.ts +204 -73
- package/src/runtime/control-plane/generated-cache-retention.ts +271 -0
- package/src/runtime/control-plane/global-scheduler/config.ts +44 -0
- package/src/runtime/control-plane/global-scheduler/dispatch-capacity.ts +80 -0
- package/src/runtime/control-plane/global-scheduler/durable-admission.ts +46 -0
- package/src/runtime/control-plane/global-scheduler/maintenance.ts +145 -0
- package/src/runtime/control-plane/global-scheduler/projection-refresh.ts +84 -0
- package/src/runtime/control-plane/global-scheduler/reconciliation.ts +3 -3
- package/src/runtime/control-plane/global-scheduler/scheduler.ts +273 -542
- package/src/runtime/control-plane/global-scheduler/source-scan.ts +59 -0
- package/src/runtime/control-plane/global-scheduler/state.ts +88 -0
- package/src/runtime/control-plane/global-scheduler/worker-attachment.ts +57 -0
- package/src/runtime/control-plane/global-scheduler/worker-exit-decision.ts +38 -0
- package/src/runtime/control-plane/global-scheduler/worker-exit-reconciler.ts +175 -0
- package/src/runtime/control-plane/global-scheduler/worker-launch.ts +111 -0
- package/src/runtime/control-plane/global-scheduler/worker-lifecycle-store.ts +64 -0
- package/src/runtime/control-plane/global-scheduler/worker-lifecycle.ts +150 -0
- package/src/runtime/control-plane/global-scheduler/worker-process.ts +119 -0
- package/src/runtime/control-plane/global-scheduler/worker-stderr.ts +60 -0
- package/src/runtime/control-plane/launcher/chatgpt-work-binding-store.ts +50 -0
- package/src/runtime/control-plane/launcher/chatgpt-work-continuation.ts +642 -51
- package/src/runtime/control-plane/launcher/launch-reservation-store.ts +40 -0
- package/src/runtime/control-plane/launcher/thin-launcher.ts +194 -10
- package/src/runtime/control-plane/persistence/controller-home-migration.ts +487 -0
- package/src/runtime/control-plane/persistence/requirement-store.ts +15 -11
- package/src/runtime/control-plane/persistence/sqlite-store.ts +33 -2
- package/src/runtime/control-plane/release-retention.ts +62 -2
- package/src/runtime/control-plane/routing/route-policy.ts +7 -16
- package/src/runtime/control-plane/runtime-status-client.ts +0 -2
- package/src/runtime/diagnostics/mcp-timing.ts +19 -0
- package/src/runtime/diagnostics/mcp-transport-benchmark.ts +129 -0
- package/src/runtime/diagnostics/performance.ts +24 -1
- package/src/runtime/evidence/event-ledger.ts +1 -1
- package/src/runtime/execution/jobs/store.ts +58 -4
- package/src/runtime/execution/jobs/types.ts +1 -1
- package/src/runtime/execution/managed-workspace.ts +203 -1
- package/src/runtime/execution/process-runtime/check-facade.ts +52 -14
- package/src/runtime/execution/process-runtime/check-result.ts +63 -2
- package/src/runtime/execution/process-runtime/check-scheduling.ts +114 -0
- package/src/runtime/execution/process-runtime/command-facade.ts +346 -40
- package/src/runtime/execution/process-runtime/gc.ts +98 -12
- package/src/runtime/execution/process-runtime/lightweight-managed.ts +1184 -0
- package/src/runtime/execution/process-runtime/persisted-check.ts +57 -6
- package/src/runtime/execution/process-runtime/resource-claims.ts +97 -8
- package/src/runtime/execution/process-runtime/runtime.ts +59 -4
- package/src/runtime/execution/process-runtime/store.ts +7 -0
- package/src/runtime/execution/process-runtime/types.ts +2 -0
- package/src/runtime/execution/thin-harness/async-process.ts +12 -2
- package/src/runtime/execution/thin-harness/search-worker.ts +54 -5
- package/src/runtime/execution/workers/executor.ts +0 -48
- package/src/runtime/gateway/mcp/execution-tools.ts +1219 -126
- package/src/runtime/gateway/mcp/process-tools.ts +83 -37
- package/src/runtime/gateway/mcp/router.ts +185 -83
- package/src/runtime/gateway/mcp/runtime-tool-definitions.ts +546 -0
- package/src/runtime/gateway/mcp/runtime-tools.ts +2555 -1616
- package/src/runtime/model-clients/deepseek-adapter.ts +0 -32
- package/src/runtime/plugins/app-store-connect-adapter.ts +123 -19
- package/src/runtime/plugins/browser-adapter.ts +2925 -318
- package/src/runtime/plugins/browser-automation-service.ts +10 -0
- package/src/runtime/plugins/browser-handoff-host.ts +6 -31
- package/src/runtime/plugins/browser-handoff.ts +92 -5
- package/src/runtime/plugins/browser-macos-bridge.ts +586 -45
- package/src/runtime/plugins/browser-node-bridge.ts +6 -34
- package/src/runtime/plugins/browser-provider-registry.ts +109 -0
- package/src/runtime/plugins/browser-runtime-contract.ts +152 -0
- package/src/runtime/plugins/browser-runtime.ts +183 -0
- package/src/runtime/plugins/browser-session-authority.ts +332 -0
- package/src/runtime/plugins/capability-authorization-grants.ts +354 -0
- package/src/runtime/plugins/desktop-operator-registration.ts +15 -12
- package/src/runtime/plugins/external-adapter.ts +324 -3
- package/src/runtime/plugins/external-registration.ts +84 -5
- package/src/runtime/plugins/external-unix-socket.ts +7 -1
- package/src/runtime/plugins/first-party-registry.ts +4 -2
- package/src/runtime/plugins/github-adapter.ts +125 -0
- package/src/runtime/plugins/gmail-adapter.ts +28 -2
- package/src/runtime/plugins/ios/agent-device-provider.ts +1 -1
- package/src/runtime/plugins/ios/agent-device-typed-provider.ts +52 -9
- package/src/runtime/plugins/ios/remote-xpc-hid.ts +1171 -0
- package/src/runtime/plugins/ios-adapter.ts +106 -16
- package/src/runtime/plugins/ios-agent-device.ts +234 -64
- package/src/runtime/plugins/ios-physical-device.ts +1143 -392
- package/src/runtime/plugins/lightweight-action.ts +153 -0
- package/src/runtime/plugins/local-system-adapter.ts +125 -8
- package/src/runtime/plugins/macos-capability-broker.ts +55 -9
- package/src/runtime/plugins/plugin-action-sidecar.ts +59 -0
- package/src/runtime/plugins/plugin-management-adapter.ts +181 -0
- package/src/runtime/plugins/resend-adapter.ts +1 -1
- package/src/runtime/plugins/store.ts +366 -24
- package/src/runtime/plugins/types.ts +39 -2
- package/src/runtime/plugins/xiaohongshu-publish.ts +515 -0
- package/src/runtime/projections/git-status-sampler.ts +16 -16
- package/src/runtime/projections/materialized-view.ts +28 -10
- package/src/runtime/recovery/actions.ts +0 -10
- package/src/runtime/recovery/classifier.ts +0 -9
- package/src/runtime/recovery/maintenance-executor.ts +415 -18
- package/src/runtime/recovery/probe.ts +0 -1
- package/src/runtime/recovery/types.ts +0 -1
- package/src/runtime/root/mcp-transport.ts +180 -10
- package/src/runtime/root/package-connector-service.ts +186 -8
- package/src/runtime/root/package-runtime-release.ts +143 -17
- package/src/runtime/root/package-runtime-service.ts +430 -22
- package/src/runtime/root/release-manifest.ts +7 -2
- package/src/runtime/root/release-materialize.ts +162 -19
- package/src/runtime/root/release-store.ts +48 -11
- package/src/runtime/root/runtime.ts +23 -5
- package/src/runtime/root/service.ts +100 -27
- package/src/runtime/root/types.ts +2 -0
- package/src/runtime/safe-tooling/index.ts +0 -1
- package/src/runtime/safe-tooling/ios-development.ts +321 -63
- package/src/runtime/safe-tooling/types.ts +0 -30
- package/src/runtime/shared/trusted-executable.ts +62 -0
- package/src/runtime/shared/trusted-node-executable.ts +48 -0
- package/src/runtime/standalone-recovery/core.ts +702 -94
- package/src/runtime/standalone-recovery/entry.ts +99 -23
- package/src/runtime/standalone-recovery/installer.ts +19 -3
- package/src/runtime/standalone-recovery/service-labels.ts +2 -0
- package/src/runtime/standalone-recovery/watchdog-heartbeat.ts +160 -0
- package/src/runtime/workflow/schedules/browser-probe.ts +258 -0
- package/src/runtime/workflow/schedules/chatgpt-automation-migration.ts +40 -0
- package/src/runtime/workflow/schedules/engine.ts +509 -80
- package/src/runtime/workflow/schedules/github-issue-watch.ts +158 -0
- package/src/runtime/workflow/schedules/settlement.ts +48 -4
- package/src/runtime/workflow/schedules/store.ts +131 -10
- package/src/runtime/workflow/schedules/types.ts +6 -3
- package/src/runtime/workflow/schedules/work-continuation.ts +120 -34
- package/src/testing/test-governance.ts +8 -40
- package/assets/reference-configs/heartbeat-triage.md +0 -57
- package/assets/templates/helpers/harness-trace-grade.sh +0 -150
- package/assets/templates/helpers/heartbeat-triage.sh +0 -361
- package/assets/templates/helpers/maintenance-triage.sh +0 -167
- package/bin/forge-desktop-helper.mjs +0 -204
- package/docs/architecture/current/approved-target-architecture.zh-CN.md +0 -1501
- package/docs/architecture/current/architecture-invariants.md +0 -331
- package/docs/architecture/current/automation-and-schedule-engine.md +0 -453
- package/docs/architecture/current/codegraph-context-provider.md +0 -226
- package/docs/architecture/current/control-plane-authority-inventory.md +0 -94
- package/docs/architecture/current/controller-repository-decoupling.md +0 -148
- package/docs/architecture/current/dispatch-and-agent-strategy.md +0 -354
- package/docs/architecture/current/entity-model.md +0 -592
- package/docs/architecture/current/external-plugin-governance.md +0 -396
- package/docs/architecture/current/failure-recovery.md +0 -447
- package/docs/architecture/current/governance.md +0 -213
- package/docs/architecture/current/human-interaction-plane.md +0 -87
- package/docs/architecture/current/implementation-status.md +0 -128
- package/docs/architecture/current/job-and-run-lifecycle.md +0 -413
- package/docs/architecture/current/legacy-governance.md +0 -58
- package/docs/architecture/current/local-workspace-target-grants.md +0 -70
- package/docs/architecture/current/migration-roadmap.md +0 -105
- package/docs/architecture/current/multi-repository-execution.md +0 -371
- package/docs/architecture/current/operations-runbook.md +0 -45
- package/docs/architecture/current/peer-supercontroller-runtime.md +0 -32
- package/docs/architecture/current/personal-assistant-plugin-baseline.md +0 -206
- package/docs/architecture/current/repository-access-modes.md +0 -102
- package/docs/architecture/current/route-policy.md +0 -15
- package/docs/architecture/current/route-session-concurrency.md +0 -85
- package/docs/architecture/current/runtime-architecture-simplification.md +0 -214
- package/docs/architecture/current/runtime-directory-map.md +0 -49
- package/docs/architecture/current/runtime-health-and-resource-lifecycle.md +0 -85
- package/docs/architecture/current/scheduler-and-resource-claims.md +0 -422
- package/docs/architecture/current/session-aware-execution-and-authorization.md +0 -77
- package/docs/architecture/current/system-overview.md +0 -144
- package/docs/architecture/current/target-requirements-traceability.md +0 -202
- package/docs/architecture/current/thin-harness-governance-policy.md +0 -32
- package/docs/architecture/current/thin-harness-v1.md +0 -311
- package/docs/architecture/current/verification-and-release-gates.md +0 -391
- package/docs/forge-autonomous-goal-loop.md +0 -9
- package/docs/forge-provider-configuration.md +0 -7
- package/docs/operations/chatgpt-personal-assistant-runtime.md +0 -83
- package/docs/operations/controller-desktop-plugin.md +0 -112
- package/docs/operations/gmail-assistant-routines.md +0 -186
- package/docs/operations/personal-assistant-operator-guide.md +0 -61
- package/docs/operations/provider-configuration.md +0 -31
- package/scripts/harness-trace-grade.sh +0 -150
- package/scripts/heartbeat-triage.sh +0 -361
- package/scripts/maintenance-triage.sh +0 -167
- package/src/cli/local-bridge/frontend/src/features/settings/SettingsView.tsx +0 -2
- package/src/cli/repositories/goal-registry.ts +0 -239
- package/src/runtime/assistant/action-proposals.ts +0 -279
- package/src/runtime/assistant/intent.ts +0 -395
- package/src/runtime/assistant/model-provider.ts +0 -460
- package/src/runtime/assistant/openapi.ts +0 -223
- package/src/runtime/assistant/policy.ts +0 -89
- package/src/runtime/assistant/readiness.ts +0 -258
- package/src/runtime/assistant/routine-runtime.ts +0 -477
- package/src/runtime/assistant/schedule-binding.ts +0 -171
- package/src/runtime/assistant/standing-grants.ts +0 -375
- package/src/runtime/assistant/store.ts +0 -243
- package/src/runtime/assistant/types.ts +0 -135
- package/src/runtime/control-plane/goal-loop/config-facade.ts +0 -700
- package/src/runtime/control-plane/goal-loop/config-store.ts +0 -570
- package/src/runtime/control-plane/goal-loop/config-types.ts +0 -213
- package/src/runtime/control-plane/goal-loop/executor-router.ts +0 -109
- package/src/runtime/control-plane/goal-loop/failure-taxonomy.ts +0 -149
- package/src/runtime/control-plane/goal-loop/goal-contract-store.ts +0 -304
- package/src/runtime/control-plane/goal-loop/goal-loop-engine.ts +0 -1001
- package/src/runtime/control-plane/goal-loop/handoff-packet.ts +0 -160
- package/src/runtime/control-plane/goal-loop/index.ts +0 -13
- package/src/runtime/control-plane/goal-loop/local-tools.ts +0 -290
- package/src/runtime/control-plane/goal-loop/policy-gates.ts +0 -203
- package/src/runtime/control-plane/goal-loop/provider-dispatch.ts +0 -93
- package/src/runtime/control-plane/goal-loop/provider-registry.ts +0 -545
- package/src/runtime/control-plane/goal-loop/types.ts +0 -378
- package/src/runtime/control-plane/startup-recovery.ts +0 -198
- package/src/runtime/gateway/mcp/resource-policy.ts +0 -186
- package/src/runtime/personal-assistant/gmail-triage-manager.ts +0 -231
- package/src/runtime/personal-assistant/reporting-runtime.ts +0 -344
- package/src/runtime/personal-assistant/triage-runtime.ts +0 -748
- package/src/runtime/plugins/desktop-adapter.ts +0 -374
- package/src/runtime/safe-tooling/browser-safe.ts +0 -133
- package/src/runtime/workflow/findings/store.ts +0 -204
- package/src/runtime/workflow/findings/types.ts +0 -58
- package/src/runtime/workflow/portfolio/engine.ts +0 -20
- package/src/runtime/workflow/portfolio/store.ts +0 -185
- package/src/runtime/workflow/portfolio/types.ts +0 -29
|
@@ -1,19 +1,26 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* repository_command_execute →
|
|
2
|
+
* repository_command_execute → three explicit execution lanes.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
4
|
+
* - Ephemeral Direct: bounded ordinary reads and commands that finish inside
|
|
5
|
+
* the interactive budget.
|
|
6
|
+
* - Lightweight Managed: the same local command remains alive in memory and
|
|
7
|
+
* returns a bounded handle, without SQLite, Lease, or recovery membership.
|
|
8
|
+
* - Durable: explicit Work/external/release boundaries only.
|
|
7
9
|
*/
|
|
8
10
|
|
|
9
11
|
import type { RepositoryRecord } from '../../../cli/repositories/types';
|
|
10
|
-
import {
|
|
12
|
+
import { repositoryGitStatus } from '../../../cli/repositories/structured-git';
|
|
13
|
+
import { classifyRepositoryCommand, fixedShellWrapperCommand } from '../../../cli/repositories/command-classifier';
|
|
11
14
|
import {
|
|
12
15
|
executeRepositoryCommandAsync,
|
|
13
16
|
executeRepositoryReadOnlyCommandDirect,
|
|
14
17
|
type RepositoryCommandExecution,
|
|
15
18
|
} from '../../../cli/repositories/command-executor';
|
|
16
19
|
import { normalizeRepositoryCommand } from '../../../cli/repositories/command-normalization';
|
|
20
|
+
import {
|
|
21
|
+
assertRepositoryCommandNoPluginExecutionBypass,
|
|
22
|
+
assertRepositoryCommandStableHostIdentity,
|
|
23
|
+
} from '../../../cli/repositories/command-scope';
|
|
17
24
|
import { claimsForRepositoryCommand, scopeResourceClaims, toProcessClaims } from './resource-claims';
|
|
18
25
|
import {
|
|
19
26
|
spawnManagedProcess,
|
|
@@ -27,6 +34,15 @@ import { DEFAULT_INTERACTIVE_WAIT_MS } from './types';
|
|
|
27
34
|
import { durationAwareInteractiveWaitMs } from './interactive-admission';
|
|
28
35
|
import { isFocusedCheckCommand } from '../thin-harness/execution-router';
|
|
29
36
|
import { assertExecutionIdentity, type ResolvedExecutionIdentity } from '../../control-plane/execution/execution-identity';
|
|
37
|
+
import { readWorkHandle, transitionWorkHandle } from '../../control-plane/execution/work-handle-store';
|
|
38
|
+
import {
|
|
39
|
+
cancelLightweightProcess,
|
|
40
|
+
getLightweightProcessHandle,
|
|
41
|
+
isLightweightProcessId,
|
|
42
|
+
readLightweightProcessLogs,
|
|
43
|
+
startLightweightRepositoryCommand,
|
|
44
|
+
waitForLightweightProcess,
|
|
45
|
+
} from './lightweight-managed';
|
|
30
46
|
|
|
31
47
|
export type RepositoryCommandRoute =
|
|
32
48
|
| 'process_direct'
|
|
@@ -76,6 +92,19 @@ export interface RepositoryCommandProcessResult {
|
|
|
76
92
|
projectionUpdateCount: number;
|
|
77
93
|
};
|
|
78
94
|
suggestedOperation?: string;
|
|
95
|
+
externalEffect?: {
|
|
96
|
+
outcome: 'not_started' | 'outcome_unknown';
|
|
97
|
+
replayPolicy: 'never_auto_retry';
|
|
98
|
+
reconciliation: string;
|
|
99
|
+
};
|
|
100
|
+
executionMetrics?: {
|
|
101
|
+
lane: 'ephemeral_direct' | 'lightweight_managed' | 'durable_process' | 'durable_external';
|
|
102
|
+
preSpawnHarnessMs?: number;
|
|
103
|
+
childDurationMs?: number;
|
|
104
|
+
interactiveReturnMs?: number;
|
|
105
|
+
durableWrites: number;
|
|
106
|
+
leaseOperations: number;
|
|
107
|
+
};
|
|
79
108
|
}
|
|
80
109
|
|
|
81
110
|
const emptyEffects = {
|
|
@@ -85,6 +114,154 @@ const emptyEffects = {
|
|
|
85
114
|
projectionUpdateCount: 0,
|
|
86
115
|
};
|
|
87
116
|
|
|
117
|
+
export type WorkHeadSettlementReason =
|
|
118
|
+
| 'settled'
|
|
119
|
+
| 'no_work'
|
|
120
|
+
| 'command_not_successful'
|
|
121
|
+
| 'work_handle_missing'
|
|
122
|
+
| 'identity_mismatch'
|
|
123
|
+
| 'terminal_handle'
|
|
124
|
+
| 'branch_changed'
|
|
125
|
+
| 'head_unavailable'
|
|
126
|
+
| 'head_unchanged'
|
|
127
|
+
| 'concurrent_lifecycle_write';
|
|
128
|
+
|
|
129
|
+
export interface WorkHeadSettlementResult {
|
|
130
|
+
settled: boolean;
|
|
131
|
+
reason: WorkHeadSettlementReason;
|
|
132
|
+
previousHead?: string;
|
|
133
|
+
currentHead?: string;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* Settle the one legitimate post-command Work HEAD transition without weakening
|
|
138
|
+
* the pre-command execution identity fence. The command has already been
|
|
139
|
+
* admitted only if repo/checkout/branch/expectedHead matched the WorkHandle.
|
|
140
|
+
* After success, adopt the exact current HEAD only while the same checkout and
|
|
141
|
+
* branch still own the Work. CAS failure is a bounded no-op: finalization keeps
|
|
142
|
+
* failing closed instead of accepting a concurrent lifecycle writer.
|
|
143
|
+
*/
|
|
144
|
+
export function settleWorkHandleExpectedHeadAfterRepositoryCommand(input: {
|
|
145
|
+
controllerHome: string;
|
|
146
|
+
repository: RepositoryRecord;
|
|
147
|
+
executionIdentity: ResolvedExecutionIdentity;
|
|
148
|
+
workId?: string;
|
|
149
|
+
ok?: boolean;
|
|
150
|
+
cancelled?: boolean;
|
|
151
|
+
timedOut?: boolean;
|
|
152
|
+
}): WorkHeadSettlementResult {
|
|
153
|
+
const workId = input.workId?.trim();
|
|
154
|
+
if (!workId) return { settled: false, reason: 'no_work' };
|
|
155
|
+
if (input.ok !== true || input.cancelled === true || input.timedOut === true) {
|
|
156
|
+
return { settled: false, reason: 'command_not_successful' };
|
|
157
|
+
}
|
|
158
|
+
const handle = readWorkHandle(input.controllerHome, input.repository.repoId, workId);
|
|
159
|
+
if (!handle) return { settled: false, reason: 'work_handle_missing' };
|
|
160
|
+
if (
|
|
161
|
+
handle.repositoryId !== input.executionIdentity.repositoryId
|
|
162
|
+
|| handle.checkoutId !== input.executionIdentity.checkoutId
|
|
163
|
+
|| handle.workId !== input.executionIdentity.workId
|
|
164
|
+
) return { settled: false, reason: 'identity_mismatch' };
|
|
165
|
+
if (handle.state === 'merged' || handle.state === 'cleaned' || handle.state === 'failed_terminal_cleanup') {
|
|
166
|
+
return { settled: false, reason: 'terminal_handle' };
|
|
167
|
+
}
|
|
168
|
+
const status = repositoryGitStatus(input.repository);
|
|
169
|
+
if (!status.branch || status.branch !== handle.branch) {
|
|
170
|
+
return { settled: false, reason: 'branch_changed', previousHead: handle.expectedHead, currentHead: status.head ?? undefined };
|
|
171
|
+
}
|
|
172
|
+
const currentHead = status.head?.trim();
|
|
173
|
+
if (!currentHead) return { settled: false, reason: 'head_unavailable', previousHead: handle.expectedHead };
|
|
174
|
+
if (currentHead === handle.expectedHead) {
|
|
175
|
+
return { settled: false, reason: 'head_unchanged', previousHead: handle.expectedHead, currentHead };
|
|
176
|
+
}
|
|
177
|
+
try {
|
|
178
|
+
transitionWorkHandle(input.controllerHome, handle, handle.state, { expectedHead: currentHead });
|
|
179
|
+
return { settled: true, reason: 'settled', previousHead: handle.expectedHead, currentHead };
|
|
180
|
+
} catch (error) {
|
|
181
|
+
if (error instanceof Error && error.message.includes('CONTROL_PLANE_REVISION_CONFLICT')) {
|
|
182
|
+
return { settled: false, reason: 'concurrent_lifecycle_write', previousHead: handle.expectedHead, currentHead };
|
|
183
|
+
}
|
|
184
|
+
throw error;
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
const STANDALONE_RECOVERY_LIFECYCLE_COMMANDS = new Set([
|
|
189
|
+
'restart-runtime',
|
|
190
|
+
'bootstrap-cutover',
|
|
191
|
+
'restart-connector',
|
|
192
|
+
'stage-and-activate-runtime',
|
|
193
|
+
'recover',
|
|
194
|
+
'rollback',
|
|
195
|
+
'restart',
|
|
196
|
+
'activate-runtime',
|
|
197
|
+
'install',
|
|
198
|
+
]);
|
|
199
|
+
|
|
200
|
+
function commandBasename(value: string): string {
|
|
201
|
+
return value.split(/[\\/]/).pop()?.toLowerCase() ?? '';
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
function recoveryLifecycleFromArgv(executable: string, args: readonly string[]): string | undefined {
|
|
205
|
+
const executableName = commandBasename(executable);
|
|
206
|
+
let recoveryArgs: readonly string[];
|
|
207
|
+
if (executableName === 'forge' || executableName === 'forge.mjs') {
|
|
208
|
+
recoveryArgs = args;
|
|
209
|
+
} else if (['bun', 'node', 'nodejs'].includes(executableName)) {
|
|
210
|
+
const scriptIndex = args.findIndex((arg) => {
|
|
211
|
+
const name = commandBasename(arg);
|
|
212
|
+
return name === 'forge' || name === 'forge.mjs';
|
|
213
|
+
});
|
|
214
|
+
if (scriptIndex < 0) return undefined;
|
|
215
|
+
recoveryArgs = args.slice(scriptIndex + 1);
|
|
216
|
+
} else {
|
|
217
|
+
return undefined;
|
|
218
|
+
}
|
|
219
|
+
if (recoveryArgs[0] !== 'recovery') return undefined;
|
|
220
|
+
const subcommand = recoveryArgs[1]?.toLowerCase();
|
|
221
|
+
return subcommand && STANDALONE_RECOVERY_LIFECYCLE_COMMANDS.has(subcommand) ? subcommand : undefined;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
function recoveryLifecycleFromShell(shellCommand: string): string | undefined {
|
|
225
|
+
const match = /^\s*(?:exec\s+)?(?:(?:\S*[\\/])?(?:bun|node|nodejs)\s+)?(?:\S*[\\/])?forge(?:\.mjs)?\s+recovery\s+([a-z-]+)\b/i.exec(shellCommand);
|
|
226
|
+
const subcommand = match?.[1]?.toLowerCase();
|
|
227
|
+
return subcommand && STANDALONE_RECOVERY_LIFECYCLE_COMMANDS.has(subcommand) ? subcommand : undefined;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
function repositoryCommandRecoveryLifecycle(command: string | readonly string[]): string | undefined {
|
|
231
|
+
const normalized = normalizeRepositoryCommand(command);
|
|
232
|
+
if (normalized.kind === 'shell') return recoveryLifecycleFromShell(normalized.shellCommand ?? '');
|
|
233
|
+
const direct = recoveryLifecycleFromArgv(normalized.executable ?? '', normalized.args ?? []);
|
|
234
|
+
if (direct) return direct;
|
|
235
|
+
const argv = normalized.value as string[];
|
|
236
|
+
const wrapped = fixedShellWrapperCommand(argv);
|
|
237
|
+
return wrapped ? recoveryLifecycleFromShell(wrapped) : undefined;
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
function rawGitCommitRequiresExplicitPathScope(command: string | readonly string[]): boolean {
|
|
241
|
+
const normalized = normalizeRepositoryCommand(command);
|
|
242
|
+
if (normalized.kind === 'shell') {
|
|
243
|
+
return /(?:^|[;&|]\s*)\s*git\s+commit\b/i.test(normalized.shellCommand ?? '');
|
|
244
|
+
}
|
|
245
|
+
const executable = commandBasename(normalized.executable ?? '');
|
|
246
|
+
const args = [...(normalized.args ?? [])];
|
|
247
|
+
if (executable !== 'git') {
|
|
248
|
+
const wrapped = fixedShellWrapperCommand(normalized.value as string[]);
|
|
249
|
+
return wrapped ? /(?:^|[;&|]\s*)\s*git\s+commit\b/i.test(wrapped) : false;
|
|
250
|
+
}
|
|
251
|
+
let index = 0;
|
|
252
|
+
while (index < args.length && args[index]?.startsWith('-')) {
|
|
253
|
+
const option = args[index]!;
|
|
254
|
+
if (['-c', '-C', '--git-dir', '--work-tree', '--namespace'].includes(option)) index += 2;
|
|
255
|
+
else index += 1;
|
|
256
|
+
}
|
|
257
|
+
if (args[index]?.toLowerCase() !== 'commit') return false;
|
|
258
|
+
const commitArgs = args.slice(index + 1);
|
|
259
|
+
const pathSeparator = commitArgs.indexOf('--');
|
|
260
|
+
const hasExplicitOnly = commitArgs.includes('--only') || commitArgs.includes('-o');
|
|
261
|
+
const paths = pathSeparator >= 0 ? commitArgs.slice(pathSeparator + 1).filter(Boolean) : [];
|
|
262
|
+
return !(hasExplicitOnly && paths.length > 0);
|
|
263
|
+
}
|
|
264
|
+
|
|
88
265
|
function toProcessCommand(command: string | readonly string[], cwd: string): ProcessCommandSpec {
|
|
89
266
|
const normalized = normalizeRepositoryCommand(command);
|
|
90
267
|
if (normalized.kind === 'argv') {
|
|
@@ -113,37 +290,53 @@ export function classifyRepositoryCommandRoute(
|
|
|
113
290
|
timeoutMs?: number;
|
|
114
291
|
} = {},
|
|
115
292
|
): { route: RepositoryCommandRoute; reason: string } {
|
|
293
|
+
if (repositoryCommandRecoveryLifecycle(command)) {
|
|
294
|
+
return { route: 'reject', reason: 'standalone_recovery_lifecycle_required' };
|
|
295
|
+
}
|
|
296
|
+
if (rawGitCommitRequiresExplicitPathScope(command)) {
|
|
297
|
+
return { route: 'reject', reason: 'git_commit_requires_explicit_path_scope' };
|
|
298
|
+
}
|
|
116
299
|
if (options.forceDurable) {
|
|
117
300
|
return { route: 'durable', reason: 'force_durable_or_async' };
|
|
118
301
|
}
|
|
119
302
|
const classification = classifyRepositoryCommand(command, options.defaultBranch);
|
|
120
|
-
|
|
121
|
-
//
|
|
303
|
+
const text = Array.isArray(command) ? command.join(' ') : String(command);
|
|
304
|
+
// Classification chooses scheduling/receipt granularity only; it does not
|
|
305
|
+
// decide whether a scoped repository command is allowed to run. Known remote
|
|
306
|
+
// or broadly effectful commands use managed Process Runtime so existing
|
|
307
|
+
// resource claims and receipts can serialize/reconcile them. Unknown commands
|
|
308
|
+
// still execute instead of requiring a new allow rule.
|
|
122
309
|
if (classification.risk === 'remote_write' || classification.risk === 'destructive') {
|
|
123
|
-
return {
|
|
124
|
-
route: 'process_managed',
|
|
125
|
-
reason: `risk_${classification.risk}_via_process_runtime`,
|
|
126
|
-
};
|
|
310
|
+
return { route: 'process_managed', reason: 'effectful_command_managed' };
|
|
127
311
|
}
|
|
128
|
-
|
|
129
|
-
const
|
|
130
|
-
|
|
131
|
-
|
|
312
|
+
const argv = Array.isArray(command) ? command : [];
|
|
313
|
+
const executable = argv[0]?.split(/[\\/]/).pop()?.toLowerCase();
|
|
314
|
+
const shellWrapped = Boolean(executable
|
|
315
|
+
&& ['bash', 'sh', 'zsh', 'fish', 'dash', 'cmd', 'powershell', 'pwsh'].includes(executable)
|
|
316
|
+
&& argv.slice(1).some((arg) => ['-c', '-lc', '/c', '-Command'].includes(arg)));
|
|
317
|
+
const wrappedShellCommand = shellWrapped ? fixedShellWrapperCommand(argv) : undefined;
|
|
318
|
+
const wrapsInlineInterpreter = Boolean(wrappedShellCommand
|
|
319
|
+
&& /^\s*(?:exec\s+)?(?:node|nodejs|bun|deno|ruby|perl|python\d*)\b[^\n]*(?:\s-c\b|\s-e\b|\s--eval\b)/i.test(wrappedShellCommand));
|
|
320
|
+
const wrapsObviousExternalIo = Boolean(wrappedShellCommand
|
|
321
|
+
&& /\b(?:curl|wget|ssh|scp|sftp|ftp|telnet|nc|ncat)\b|https?:\/\//i.test(wrappedShellCommand));
|
|
322
|
+
if (shellWrapped && classification.risk !== 'readonly') {
|
|
323
|
+
if (wrapsObviousExternalIo && !wrapsInlineInterpreter) {
|
|
324
|
+
return { route: 'process_managed', reason: 'shell_wrapper_requires_managed_boundary' };
|
|
325
|
+
}
|
|
326
|
+
return { route: 'process_direct', reason: 'lightweight_local_shell_wrapper' };
|
|
327
|
+
}
|
|
328
|
+
if (executable && ['node', 'nodejs', 'bun', 'deno', 'ruby', 'perl', 'python', 'python3'].includes(executable)
|
|
329
|
+
&& argv.slice(1).some((arg) => ['-c', '-e', '--eval'].includes(arg))) {
|
|
330
|
+
return { route: 'process_direct', reason: 'lightweight_local_inline_interpreter' };
|
|
132
331
|
}
|
|
133
332
|
if (classification.risk === 'readonly') {
|
|
134
|
-
// Short readonly → direct. Only an *explicit* long timeout upgrades to managed.
|
|
135
|
-
if (typeof options.timeoutMs === 'number' && options.timeoutMs > 30_000) {
|
|
136
|
-
return { route: 'process_managed', reason: 'readonly_long_timeout' };
|
|
137
|
-
}
|
|
138
333
|
return { route: 'process_direct', reason: 'readonly_fast_path' };
|
|
139
334
|
}
|
|
140
335
|
// workspace_write / build-test
|
|
141
336
|
if (isFocusedCheckCommand(command) || /\b(?:test|typecheck|lint|build|check)\b/i.test(text)) {
|
|
142
|
-
return { route: '
|
|
337
|
+
return { route: 'process_direct', reason: 'ephemeral_local_build_or_test' };
|
|
143
338
|
}
|
|
144
|
-
|
|
145
|
-
// a process lifecycle budget and must never select a different architecture.
|
|
146
|
-
return { route: 'process_managed', reason: 'local_workspace_mutation' };
|
|
339
|
+
return { route: 'process_direct', reason: 'ephemeral_local_workspace_mutation' };
|
|
147
340
|
}
|
|
148
341
|
|
|
149
342
|
/**
|
|
@@ -153,18 +346,38 @@ export function classifyRepositoryCommandRoute(
|
|
|
153
346
|
export async function executeRepositoryCommandViaProcessRuntime(
|
|
154
347
|
input: RepositoryCommandProcessInput,
|
|
155
348
|
): Promise<RepositoryCommandProcessResult> {
|
|
349
|
+
// Process Runtime intentionally supports some command forms that the legacy
|
|
350
|
+
// repository executor rejects (for example bounded typed eval). Keep that
|
|
351
|
+
// surface, but fail closed before routing any macOS TCC-sensitive host tool:
|
|
352
|
+
// a release-specific forge-runtime executable must never own those grants.
|
|
353
|
+
assertRepositoryCommandStableHostIdentity(input.command);
|
|
354
|
+
assertRepositoryCommandNoPluginExecutionBypass(input.command);
|
|
156
355
|
const decision = classifyRepositoryCommandRoute(input.command, {
|
|
157
356
|
forceDurable: input.forceDurable,
|
|
357
|
+
// Work identity is continuity/audit metadata only. It must not change the
|
|
358
|
+
// execution lane of an otherwise ordinary local repository command.
|
|
158
359
|
defaultBranch: input.repository.defaultBranch,
|
|
159
360
|
timeoutMs: input.timeoutMs,
|
|
160
361
|
});
|
|
161
|
-
|
|
162
|
-
|
|
362
|
+
// Only explicit lifecycle/delivery rejection or a caller-requested durable
|
|
363
|
+
// mode stops here. Ordinary command effects, including remote writes, execute
|
|
364
|
+
// through Process Runtime; classification does not become an authorization gate.
|
|
365
|
+
if (decision.route === 'reject' || decision.route === 'durable') {
|
|
163
366
|
return {
|
|
164
367
|
route: decision.route,
|
|
165
368
|
reason: decision.reason,
|
|
166
369
|
durableSideEffects: emptyEffects,
|
|
167
|
-
suggestedOperation:
|
|
370
|
+
suggestedOperation: decision.reason === 'standalone_recovery_lifecycle_required'
|
|
371
|
+
? 'Use the standalone Forge Recovery connector for canonical Runtime/connector lifecycle operations.'
|
|
372
|
+
: 'repository_command_execute via Durable Work / Local Job',
|
|
373
|
+
externalEffect: decision.route === 'durable'
|
|
374
|
+
? {
|
|
375
|
+
outcome: 'not_started',
|
|
376
|
+
replayPolicy: 'never_auto_retry',
|
|
377
|
+
reconciliation: 'If a separate external controller later loses the result after dispatch, report outcome_unknown and inspect remote state before any retry.',
|
|
378
|
+
}
|
|
379
|
+
: undefined,
|
|
380
|
+
executionMetrics: { lane: 'durable_external', durableWrites: 0, leaseOperations: 0 },
|
|
168
381
|
};
|
|
169
382
|
}
|
|
170
383
|
|
|
@@ -191,12 +404,12 @@ export async function executeRepositoryCommandViaProcessRuntime(
|
|
|
191
404
|
};
|
|
192
405
|
}
|
|
193
406
|
|
|
194
|
-
//
|
|
195
|
-
//
|
|
196
|
-
// non-persistent
|
|
197
|
-
//
|
|
407
|
+
// Ordinary local commands own no durable Process/Lease state. Validate the
|
|
408
|
+
// immutable repository identity first, then execute through the authorized
|
|
409
|
+
// non-persistent repository executor. Runtime/release durability is not a
|
|
410
|
+
// command-execution tax.
|
|
198
411
|
const canonicalCommand = normalizeRepositoryCommand(input.command);
|
|
199
|
-
if (decision.route === 'process_direct'
|
|
412
|
+
if (decision.route === 'process_direct') {
|
|
200
413
|
assertExecutionIdentity({
|
|
201
414
|
controllerHome: input.controllerHome,
|
|
202
415
|
identity: executionIdentity,
|
|
@@ -204,14 +417,68 @@ export async function executeRepositoryCommandViaProcessRuntime(
|
|
|
204
417
|
requestedRepoId: input.repository.repoId,
|
|
205
418
|
requestedCheckoutId: input.repository.activeCheckoutId,
|
|
206
419
|
});
|
|
207
|
-
const
|
|
420
|
+
const directInput = {
|
|
208
421
|
command: input.command,
|
|
209
422
|
cwd: input.cwd,
|
|
210
|
-
timeoutMs:
|
|
423
|
+
timeoutMs: input.timeoutMs,
|
|
211
424
|
maxOutputBytes: input.maxOutputBytes,
|
|
212
425
|
signal: input.signal,
|
|
213
426
|
allowNonGitWorkspace: executionIdentity.authority === 'ephemeral_workspace',
|
|
214
|
-
|
|
427
|
+
allowOpaqueLocalScript: decision.reason === 'lightweight_local_shell_wrapper'
|
|
428
|
+
|| decision.reason === 'lightweight_local_inline_interpreter',
|
|
429
|
+
};
|
|
430
|
+
const readonly = canonicalCommand.kind === 'argv'
|
|
431
|
+
&& classifyRepositoryCommand(input.command, input.repository.defaultBranch).risk === 'readonly';
|
|
432
|
+
if (!readonly) {
|
|
433
|
+
const deferLongPreparation = decision.reason === 'ephemeral_local_build_or_test';
|
|
434
|
+
const interactiveWaitMs = deferLongPreparation
|
|
435
|
+
? 0
|
|
436
|
+
: durationAwareInteractiveWaitMs(
|
|
437
|
+
input.command,
|
|
438
|
+
input.returnHandleImmediately ? 0 : input.interactiveWaitMs,
|
|
439
|
+
Math.min(DEFAULT_INTERACTIVE_WAIT_MS, 250),
|
|
440
|
+
);
|
|
441
|
+
const timeoutMs = Math.max(
|
|
442
|
+
interactiveWaitMs + 1,
|
|
443
|
+
Math.min(input.timeoutMs ?? 15 * 60_000, 24 * 60 * 60_000),
|
|
444
|
+
);
|
|
445
|
+
const lightweight = await startLightweightRepositoryCommand({
|
|
446
|
+
controllerHome: input.controllerHome,
|
|
447
|
+
repository: input.repository,
|
|
448
|
+
execution: directInput,
|
|
449
|
+
interactiveWaitMs,
|
|
450
|
+
timeoutMs,
|
|
451
|
+
maxOutputBytes: input.maxOutputBytes,
|
|
452
|
+
workId: input.workId,
|
|
453
|
+
commandId: input.commandId ?? input.requestId,
|
|
454
|
+
deferStart: deferLongPreparation,
|
|
455
|
+
reuseActiveEquivalent: deferLongPreparation,
|
|
456
|
+
onCompleted: (result) => {
|
|
457
|
+
settleWorkHandleExpectedHeadAfterRepositoryCommand({
|
|
458
|
+
controllerHome: input.controllerHome,
|
|
459
|
+
repository: input.repository,
|
|
460
|
+
executionIdentity,
|
|
461
|
+
workId: input.workId,
|
|
462
|
+
ok: result.ok,
|
|
463
|
+
cancelled: result.cancelled,
|
|
464
|
+
timedOut: result.timedOut,
|
|
465
|
+
});
|
|
466
|
+
},
|
|
467
|
+
});
|
|
468
|
+
const handle = lightweight.handle;
|
|
469
|
+
return {
|
|
470
|
+
route: handle.completed ? 'process_direct' : 'process_managed',
|
|
471
|
+
reason: handle.completed ? decision.reason : 'interactive_budget_exceeded_lightweight_handle',
|
|
472
|
+
process: handle,
|
|
473
|
+
ok: handle.ok,
|
|
474
|
+
exitCode: handle.exitCode,
|
|
475
|
+
stdout: handle.stdout,
|
|
476
|
+
stderr: handle.stderr,
|
|
477
|
+
durableSideEffects: emptyEffects,
|
|
478
|
+
executionMetrics: lightweight.metrics,
|
|
479
|
+
};
|
|
480
|
+
}
|
|
481
|
+
const direct = await executeRepositoryReadOnlyCommandDirect(input.repository, directInput);
|
|
215
482
|
return {
|
|
216
483
|
route: 'process_direct',
|
|
217
484
|
reason: decision.reason,
|
|
@@ -224,6 +491,7 @@ export async function executeRepositoryCommandViaProcessRuntime(
|
|
|
224
491
|
authorizationDecision: direct.authorizationDecision,
|
|
225
492
|
approvalRequestId: direct.approvalRequestId,
|
|
226
493
|
durableSideEffects: emptyEffects,
|
|
494
|
+
executionMetrics: { lane: 'ephemeral_direct', durableWrites: 0, leaseOperations: 0 },
|
|
227
495
|
};
|
|
228
496
|
}
|
|
229
497
|
|
|
@@ -273,6 +541,7 @@ export async function executeRepositoryCommandViaProcessRuntime(
|
|
|
273
541
|
executionIdentity.repositoryId,
|
|
274
542
|
executionIdentity.checkoutId,
|
|
275
543
|
input.repository.defaultBranch,
|
|
544
|
+
input.repository.canonicalRoot,
|
|
276
545
|
),
|
|
277
546
|
executionIdentity.repositoryId,
|
|
278
547
|
executionIdentity.checkoutId,
|
|
@@ -312,12 +581,49 @@ export async function executeRepositoryCommandViaProcessRuntime(
|
|
|
312
581
|
stdout: handle.stdout,
|
|
313
582
|
stderr: handle.stderr,
|
|
314
583
|
durableSideEffects: handle.durableSideEffects,
|
|
584
|
+
executionMetrics: {
|
|
585
|
+
lane: 'durable_process',
|
|
586
|
+
interactiveReturnMs: interactiveWaitMs,
|
|
587
|
+
durableWrites: 1,
|
|
588
|
+
leaseOperations: claims.length,
|
|
589
|
+
},
|
|
315
590
|
};
|
|
316
591
|
}
|
|
317
592
|
|
|
318
|
-
export {
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
593
|
+
export function getRepositoryCommandProcess(controllerHome: string, repoId: string, processId: string): ProcessHandle | undefined {
|
|
594
|
+
return isLightweightProcessId(processId)
|
|
595
|
+
? getLightweightProcessHandle(controllerHome, repoId, processId)
|
|
596
|
+
: getProcessHandle(controllerHome, repoId, processId);
|
|
597
|
+
}
|
|
598
|
+
|
|
599
|
+
export function waitRepositoryCommandProcess(
|
|
600
|
+
controllerHome: string,
|
|
601
|
+
repoId: string,
|
|
602
|
+
processId: string,
|
|
603
|
+
options?: Parameters<typeof waitForProcess>[3],
|
|
604
|
+
): Promise<ProcessHandle> {
|
|
605
|
+
return isLightweightProcessId(processId)
|
|
606
|
+
? waitForLightweightProcess(controllerHome, repoId, processId, options)
|
|
607
|
+
: waitForProcess(controllerHome, repoId, processId, options);
|
|
608
|
+
}
|
|
609
|
+
|
|
610
|
+
export function cancelRepositoryCommandProcess(
|
|
611
|
+
controllerHome: string,
|
|
612
|
+
repoId: string,
|
|
613
|
+
processId: string,
|
|
614
|
+
): Promise<ProcessHandle> {
|
|
615
|
+
return isLightweightProcessId(processId)
|
|
616
|
+
? cancelLightweightProcess(controllerHome, repoId, processId)
|
|
617
|
+
: cancelProcess(controllerHome, repoId, processId);
|
|
618
|
+
}
|
|
619
|
+
|
|
620
|
+
export function readRepositoryCommandProcessLogs(
|
|
621
|
+
controllerHome: string,
|
|
622
|
+
repoId: string,
|
|
623
|
+
processId: string,
|
|
624
|
+
maxBytes?: number,
|
|
625
|
+
) {
|
|
626
|
+
return isLightweightProcessId(processId)
|
|
627
|
+
? readLightweightProcessLogs(controllerHome, repoId, processId, maxBytes)
|
|
628
|
+
: readProcessLogs(controllerHome, repoId, processId, maxBytes);
|
|
629
|
+
}
|