@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
|
@@ -26,8 +26,8 @@ These features are part of the default local setup:
|
|
|
26
26
|
| Tailscale / Cloudflare | Stable HTTPS endpoint for ChatGPT MCP | Tunnel client and appropriate account/domain configuration. |
|
|
27
27
|
| Browser | Playwright navigation, screenshots, and bounded browser evidence | Browser binaries and HTTP(S) URL scheme validation. |
|
|
28
28
|
| CodeGraph | Additional code relationships and impact navigation | CodeGraph CLI; native Windows automatic setup is not yet enabled. |
|
|
29
|
-
| Google Workspace | Gmail and Calendar
|
|
30
|
-
| Schedules
|
|
29
|
+
| Google Workspace | Gmail and Calendar plugin actions | Explicit OAuth setup and plugin permission. |
|
|
30
|
+
| Schedules | Supervised recurring checks | Canonical Forge Runtime running; live actions remain policy-gated. |
|
|
31
31
|
|
|
32
32
|
## Tool exposure
|
|
33
33
|
|
|
@@ -42,7 +42,7 @@ Use Issues for reproducible defects and scoped feature requests. Use Discussions
|
|
|
42
42
|
|
|
43
43
|
## Documentation ownership
|
|
44
44
|
|
|
45
|
-
The GitHub Wiki is a presentation target. Versioned source lives under `docs/wiki/`. Deeper engineering detail remains under `docs/architecture/
|
|
45
|
+
The GitHub Wiki is a presentation target. Versioned source lives under `docs/wiki/`. Deeper engineering detail remains under `docs/architecture/CURRENT.md` and `docs/operations/`.
|
|
46
46
|
|
|
47
47
|
Public documentation must distinguish current facts from historical evidence. Avoid hard-coding “next release” versions in operational runbooks; derive versions from `package.json` so routine releases do not leave stale docs behind.
|
|
48
48
|
|
|
@@ -6,8 +6,8 @@ Homebrew is planned as a convenience layer after the first stable npm/GitHub rel
|
|
|
6
6
|
|
|
7
7
|
Do not publish a formula until all of the following are true:
|
|
8
8
|
|
|
9
|
-
- `@moretea-labs/forge@1.
|
|
10
|
-
- Git tag and GitHub Release `v1.
|
|
9
|
+
- `@moretea-labs/forge@1.7.0` exists on npm;
|
|
10
|
+
- Git tag and GitHub Release `v1.7.0` exist and point to the tested commit;
|
|
11
11
|
- the npm tarball has an immutable checksum;
|
|
12
12
|
- macOS installation and `forge --version` / `forge doctor` tests pass;
|
|
13
13
|
- upgrade and uninstall behavior is documented.
|
|
@@ -6,8 +6,9 @@ Controller MCP uses one stable default schema so ChatGPT can reliably read, edit
|
|
|
6
6
|
|
|
7
7
|
| Toolset | CLI | Behavior |
|
|
8
8
|
| --- | --- | --- |
|
|
9
|
-
| **
|
|
10
|
-
| **
|
|
9
|
+
| **facade** (opt-in) | `--toolset facade` | Five-tool ChatGPT orchestration surface: `rh_access`, `rh_status`, `rh_inbox`, `rh_context`, `rh_work`. Internal handlers and capabilities remain registered; only MCP discovery is reduced. Intended for latency/tool-selection A/B before any default migration. |
|
|
10
|
+
| **advanced** (default) | `--toolset advanced` | Current stable 19-tool controller surface. Includes the five `rh_*` facades plus repository, Direct Edit, command, check, plugin-dispatch, Process, and result/evidence tools. |
|
|
11
|
+
| **core** | `--toolset core` | Compatibility label for the same stable default 19-tool schema. It does not reduce capability or require reconnecting. |
|
|
11
12
|
| **full** | `--toolset full` | Every historical legacy and runtime definition. Use only for old integrations or deep compatibility diagnosis because the much larger schema can reduce tool-selection quality. |
|
|
12
13
|
|
|
13
14
|
Configure via CLI flags, `FORGE_MCP_TOOLSET`, or Controller Home MCP config. Empty/default controller configuration resolves to `advanced`.
|
|
@@ -31,7 +32,7 @@ The current implementation separates orchestration from capability without delet
|
|
|
31
32
|
2. **Typed atomic tools:** repository inspection, Direct Edit, command, Git, Work/Job, Issue/Task, Goal/Work, plugin, browser, iOS, artifact, and recovery handlers remain public because their schemas preserve operation-specific validation and evidence.
|
|
32
33
|
3. **Internal handlers and capability registry:** capabilities are grouped as `controller`, `repository-core`, `git`, `issue-task`, `browser`, `ios`, `plugin`, `evidence`, and `runtime-maintenance`. `rh_status`, `rh_context`, and `controller_capabilities` expose this metadata.
|
|
33
34
|
|
|
34
|
-
The MCP transport
|
|
35
|
+
The MCP transport publishes a static schema for each selected toolset. It does **not** dynamically load a domain schema after ChatGPT selects that domain. The opt-in `facade` toolset reduces initial discovery to five facade tools while retaining the same internal handlers; `core`/`advanced` keep the current 19-tool stable schema and `full` keeps the exhaustive compatibility schema.
|
|
35
36
|
|
|
36
37
|
Capability metadata changes do not change `tools/list`; restart the Controller to load new code, but reconnect/rescan ChatGPT only when tool names or input schemas change.
|
|
37
38
|
|
|
@@ -45,6 +46,7 @@ Remote writes, destructive actions, outside-repository paths, and secret access
|
|
|
45
46
|
|
|
46
47
|
- Prefer `rh_status`, `rh_access`, `rh_context`, `rh_work`, and `rh_inbox` for normal orchestration.
|
|
47
48
|
- Use first-class Direct Edit, command, Git, `quick_agent_session`, Goal/Work, iOS, plugin, and artifact tools when the facade is not the shortest reliable path.
|
|
49
|
+
- Use `--toolset facade` only for explicit experiments/clients until latency and workflow coverage are validated; the default remains the stable 19-tool surface.
|
|
48
50
|
- Keep the stable surface unique and at or below 128 tools.
|
|
49
51
|
- Add new public tools only when they unlock a real end-to-end workflow; otherwise route capabilities through an existing facade or plugin action.
|
|
50
52
|
|
|
@@ -75,11 +75,11 @@ One Canonical Runtime owns the active local execution authority and one whole-re
|
|
|
75
75
|
|
|
76
76
|
## Authoritative documents
|
|
77
77
|
|
|
78
|
-
- [System overview](https://github.com/moretea-labs/forge/blob/main/docs/architecture/
|
|
79
|
-
- [Architecture invariants](https://github.com/moretea-labs/forge/blob/main/docs/architecture/
|
|
80
|
-
- [Multi-repository execution](https://github.com/moretea-labs/forge/blob/main/docs/architecture/
|
|
81
|
-
- [Verification and release gates](https://github.com/moretea-labs/forge/blob/main/docs/architecture/
|
|
82
|
-
- [Implementation status](https://github.com/moretea-labs/forge/blob/main/docs/architecture/
|
|
83
|
-
- [Runtime directory map](https://github.com/moretea-labs/forge/blob/main/docs/architecture/
|
|
78
|
+
- [System overview](https://github.com/moretea-labs/forge/blob/main/docs/architecture/../architecture/CURRENT.md)
|
|
79
|
+
- [Architecture invariants](https://github.com/moretea-labs/forge/blob/main/docs/architecture/../architecture/CURRENT.md)
|
|
80
|
+
- [Multi-repository execution](https://github.com/moretea-labs/forge/blob/main/docs/architecture/../architecture/CURRENT.md)
|
|
81
|
+
- [Verification and release gates](https://github.com/moretea-labs/forge/blob/main/docs/architecture/../architecture/CURRENT.md)
|
|
82
|
+
- [Implementation status](https://github.com/moretea-labs/forge/blob/main/docs/architecture/../architecture/CURRENT.md)
|
|
83
|
+
- [Runtime directory map](https://github.com/moretea-labs/forge/blob/main/docs/architecture/../architecture/CURRENT.md)
|
|
84
84
|
|
|
85
85
|
Historical snapshots explain previous designs but are not current Runtime contracts.
|
|
@@ -143,8 +143,8 @@ Primary code and docs:
|
|
|
143
143
|
```text
|
|
144
144
|
src/runtime/root/release-store.ts
|
|
145
145
|
src/runtime/health/
|
|
146
|
-
docs/architecture/
|
|
147
|
-
docs/architecture/
|
|
146
|
+
docs/architecture/../architecture/CURRENT.md
|
|
147
|
+
docs/architecture/../architecture/CURRENT.md
|
|
148
148
|
```
|
|
149
149
|
|
|
150
150
|
The primary Runtime cannot be the only authority deciding its own recovery. Standalone Recovery observes the Runtime independently and may perform bounded whole-release restart/rollback only under its own evidence and lock contract.
|
|
@@ -18,9 +18,9 @@ GitHub operations cover issues, pull requests, checks, repository settings, Wiki
|
|
|
18
18
|
|
|
19
19
|
Browser and local-system plugins are optional controller capabilities. They use separate grants and do not turn repository access into unrestricted machine access.
|
|
20
20
|
|
|
21
|
-
## Google Workspace
|
|
21
|
+
## Google Workspace
|
|
22
22
|
|
|
23
|
-
Gmail, Calendar, Contacts, and
|
|
23
|
+
Gmail, Calendar, Contacts, and other Workspace integrations remain connector-specific. Credentials and personal data are not stored in repository source.
|
|
24
24
|
|
|
25
25
|
## Apple tooling
|
|
26
26
|
|
|
@@ -28,4 +28,4 @@ Commit explicit paths, merge through the intended strategy, and record the integ
|
|
|
28
28
|
|
|
29
29
|
Update task evidence, delete merged branches and temporary worktrees, and verify the target branch is clean. Blocked or failed states remain recoverable; they are not treated as immutable terminal truth.
|
|
30
30
|
|
|
31
|
-
For detailed lifecycle contracts, see [Job and Run Lifecycle](https://github.com/moretea-labs/forge/blob/main/docs/architecture/
|
|
31
|
+
For detailed lifecycle contracts, see [Job and Run Lifecycle](https://github.com/moretea-labs/forge/blob/main/docs/architecture/../architecture/CURRENT.md).
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@moretea-labs/forge",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.7.0",
|
|
4
4
|
"description": "Local-first action assistant for software work with resumable execution, bounded tools, and reviewable evidence",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Moretea Labs contributors",
|
|
@@ -54,8 +54,6 @@
|
|
|
54
54
|
"docs/forge-chatgpt-mcp-setup.md",
|
|
55
55
|
"docs/forge-github-issue-launcher.md",
|
|
56
56
|
"docs/forge-runtime-self-healing-loop.md",
|
|
57
|
-
"docs/forge-autonomous-goal-loop.md",
|
|
58
|
-
"docs/forge-provider-configuration.md",
|
|
59
57
|
"docs/forge-plugin-management.md",
|
|
60
58
|
"README.en.md",
|
|
61
59
|
"README.zh-CN.md",
|
|
@@ -83,7 +81,21 @@
|
|
|
83
81
|
"check:controller-ui": "bun scripts/build-controller-ui.ts --check",
|
|
84
82
|
"check:design": "npx -y @google/design.md@0.4.0 lint DESIGN.md",
|
|
85
83
|
"benchmark:skills": "bun scripts/run-skill-evals.ts",
|
|
84
|
+
"benchmark:controller-hotpath": "bun scripts/benchmark-controller-hotpath.ts",
|
|
85
|
+
"benchmark:thin-harness-mcp-e2e": "bun scripts/benchmark-thin-harness-mcp-e2e.ts --json",
|
|
86
|
+
"benchmark:mcp-transport": "bun scripts/benchmark-mcp-transport.ts",
|
|
87
|
+
"benchmark:mcp-host": "bash scripts/benchmark-mcp-host.sh",
|
|
88
|
+
"benchmark:work-efficiency": "bun scripts/benchmark-work-efficiency.ts",
|
|
86
89
|
"benchmark:route-session-concurrency": "bun scripts/benchmark-route-session-concurrency.ts",
|
|
90
|
+
"benchmark:quality-harness": "bun scripts/benchmark-quality-harness.ts",
|
|
91
|
+
"benchmark:background-check-overlap": "bun scripts/benchmark-background-check-overlap.ts",
|
|
92
|
+
"check:quality-harness": "bun scripts/benchmark-quality-harness.ts",
|
|
93
|
+
"check:evaluation-framework": "bun test tests/evaluation-framework.test.ts",
|
|
94
|
+
"check:background-check-overlap": "bun scripts/benchmark-background-check-overlap.ts",
|
|
95
|
+
"check:typescript-navigation": "bun scripts/benchmark-typescript-navigation.ts",
|
|
96
|
+
"check:semantic-navigation-providers": "bun test tests/runtime/semantic-navigation-provider.test.ts",
|
|
97
|
+
"check:check-scheduling": "bun test tests/runtime/check-scheduling.test.ts",
|
|
98
|
+
"check:bootstrap-files": "bun test tests/bootstrap-files.test.ts",
|
|
87
99
|
"test": "bun scripts/test-governance.ts affected",
|
|
88
100
|
"test:browser-live": "bun tests/live/browser-native-silent.e2e.ts",
|
|
89
101
|
"test:core": "bun scripts/test-governance.ts core",
|
|
@@ -106,6 +118,7 @@
|
|
|
106
118
|
"check:main": "bun scripts/run-governed-gate.ts main",
|
|
107
119
|
"check:ci": "bun run check:main",
|
|
108
120
|
"check:release": "bun scripts/run-governed-gate.ts release",
|
|
121
|
+
"check:stable-baseline": "bun scripts/check-stable-baseline.ts",
|
|
109
122
|
"check:release-surface": "bash scripts/check-public-release-surface.sh",
|
|
110
123
|
"check:release-readiness": "bash scripts/check-release-readiness.sh",
|
|
111
124
|
"check:open-source-surface": "bash scripts/check-open-source-tracked-surface.sh",
|
|
@@ -125,8 +138,8 @@
|
|
|
125
138
|
"check:context-files": "forge run check-context-files",
|
|
126
139
|
"check:deploy-sql": "forge run check-deploy-sql-order",
|
|
127
140
|
"check:architecture-sync": "forge run check-architecture-sync",
|
|
128
|
-
"check:task-sync": "
|
|
129
|
-
"check:task-workflow": "
|
|
141
|
+
"check:task-sync": "forge run check-task-sync",
|
|
142
|
+
"check:task-workflow": "forge run check-task-workflow --strict",
|
|
130
143
|
"runtime:activate-source-baseline": "bun scripts/activate-source-baseline.ts request",
|
|
131
144
|
"plugin:install-desktop-operator": "bun scripts/install-desktop-operator-registration.ts",
|
|
132
145
|
"sync:brain-docs": "forge run sync-brain-docs --all",
|
|
@@ -143,10 +156,10 @@
|
|
|
143
156
|
"devDependencies": {
|
|
144
157
|
"@colbymchenry/codegraph": "1.0.1",
|
|
145
158
|
"@types/bun": "latest",
|
|
146
|
-
"@types/cors": "^2.8.
|
|
147
|
-
"@types/express": "^5.0.
|
|
148
|
-
"@types/react": "^19.2.
|
|
149
|
-
"@types/react-dom": "^19.2.
|
|
159
|
+
"@types/cors": "^2.8.19",
|
|
160
|
+
"@types/express": "^5.0.6",
|
|
161
|
+
"@types/react": "^19.2.18",
|
|
162
|
+
"@types/react-dom": "^19.2.4",
|
|
150
163
|
"@vitejs/plugin-react": "^5.2.0",
|
|
151
164
|
"vite": "^7.3.0"
|
|
152
165
|
},
|
|
@@ -156,11 +169,17 @@
|
|
|
156
169
|
"express": "^5.2.1",
|
|
157
170
|
"playwright": "^1.54.1",
|
|
158
171
|
"react": "^19.2.0",
|
|
159
|
-
"react-dom": "^19.2.
|
|
172
|
+
"react-dom": "^19.2.8",
|
|
160
173
|
"typescript": "^6.0.3"
|
|
161
174
|
},
|
|
162
175
|
"packageManager": "npm@10.0.0",
|
|
163
176
|
"optionalDependencies": {
|
|
177
|
+
"@colbymchenry/codegraph-darwin-arm64": "1.0.1",
|
|
178
|
+
"@colbymchenry/codegraph-darwin-x64": "1.0.1",
|
|
179
|
+
"@colbymchenry/codegraph-linux-arm64": "1.0.1",
|
|
180
|
+
"@colbymchenry/codegraph-linux-x64": "1.0.1",
|
|
181
|
+
"@colbymchenry/codegraph-win32-arm64": "1.0.1",
|
|
182
|
+
"@colbymchenry/codegraph-win32-x64": "1.0.1",
|
|
164
183
|
"agent-device": "0.20.2"
|
|
165
184
|
}
|
|
166
185
|
}
|
|
@@ -64,19 +64,17 @@ interface CheckDefinition {
|
|
|
64
64
|
const CHECKS: readonly CheckDefinition[] = [
|
|
65
65
|
{ id: 'package:check:type', args: ['run', 'check:type'], timeoutMs: 10 * 60_000 },
|
|
66
66
|
{ id: 'package:check:runtime-architecture', args: ['run', 'check:runtime-architecture'], timeoutMs: 3 * 60_000 },
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
timeoutMs: 15 * 60_000,
|
|
79
|
-
},
|
|
67
|
+
...[
|
|
68
|
+
'tests/runtime/process-runtime.test.ts',
|
|
69
|
+
'tests/runtime/work-terminal-cleanup.test.ts',
|
|
70
|
+
'tests/runtime/canonical-single-runtime.test.ts',
|
|
71
|
+
'tests/cli/runtime-command.test.ts',
|
|
72
|
+
'tests/cli/mcp-http.test.ts',
|
|
73
|
+
].map((path) => ({
|
|
74
|
+
id: `focused:runtime-architecture-replacement:${path}`,
|
|
75
|
+
args: ['test', '--max-concurrency', '1', `./${path}`],
|
|
76
|
+
timeoutMs: 5 * 60_000,
|
|
77
|
+
})),
|
|
80
78
|
{ id: 'package:test:core', args: ['run', 'test:core'], timeoutMs: 30 * 60_000 },
|
|
81
79
|
];
|
|
82
80
|
|
|
@@ -172,6 +170,12 @@ function terminalOutcome(handle: ReturnType<typeof listWorkHandles>[number]): Wo
|
|
|
172
170
|
|
|
173
171
|
function cleanupSafety(repoRoot: string, worktreePath: string): { safe: boolean; reason?: string } {
|
|
174
172
|
if (!existsSync(worktreePath)) return { safe: true };
|
|
173
|
+
const repository = runProcess('git', ['rev-parse', '--is-inside-work-tree'], {
|
|
174
|
+
cwd: worktreePath,
|
|
175
|
+
timeoutMs: 10_000,
|
|
176
|
+
maxOutputBytes: 100_000,
|
|
177
|
+
});
|
|
178
|
+
if (!repository.ok || repository.stdout.trim() !== 'true') return { safe: false, reason: 'WORKTREE_NOT_GIT_REPOSITORY' };
|
|
175
179
|
const status = git(worktreePath, ['status', '--porcelain']);
|
|
176
180
|
if (status) return { safe: false, reason: 'WORKTREE_DIRTY' };
|
|
177
181
|
const head = git(worktreePath, ['rev-parse', 'HEAD']);
|
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
#!/usr/bin/env bun
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Executable goal-drift guard for the managed-check controller path.
|
|
5
|
+
*
|
|
6
|
+
* It deliberately performs useful rh_context work after run_check returns and
|
|
7
|
+
* before its one final dependency join. A future change that turns this into
|
|
8
|
+
* periodic process_wait polling, re-executes the check, or blocks the initial
|
|
9
|
+
* handle return fails the benchmark rather than only a local Process test.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import { execFileSync } from 'child_process';
|
|
13
|
+
import { mkdtempSync, mkdirSync, readFileSync, rmSync, writeFileSync } from 'fs';
|
|
14
|
+
import { tmpdir } from 'os';
|
|
15
|
+
import { join } from 'path';
|
|
16
|
+
import { performance } from 'perf_hooks';
|
|
17
|
+
import { createMcpToolContext } from '../src/cli/mcp/server';
|
|
18
|
+
import { registerRepository } from '../src/cli/repositories/registry';
|
|
19
|
+
import { callRuntimeTool } from '../src/runtime/gateway/mcp/runtime-tools';
|
|
20
|
+
import { callProcessTool } from '../src/runtime/gateway/mcp/process-tools';
|
|
21
|
+
import { routeDurableMcpCall } from '../src/runtime/gateway/mcp/router';
|
|
22
|
+
import { getProcessRecord } from '../src/runtime/execution/process-runtime/store';
|
|
23
|
+
import {
|
|
24
|
+
clearGitIdentityCacheForTest,
|
|
25
|
+
clearGitSnapshotCacheForTest,
|
|
26
|
+
gitSnapshotPerformanceSnapshot,
|
|
27
|
+
} from '../src/cli/repository/inspector';
|
|
28
|
+
|
|
29
|
+
const CHECK_DURATION_MS = 1_200;
|
|
30
|
+
const MAX_INITIAL_HANDLE_LATENCY_MS = 700;
|
|
31
|
+
const MAX_TERMINAL_OBSERVATION_LATENCY_MS = 1_000;
|
|
32
|
+
const root = mkdtempSync(join(tmpdir(), 'forge-background-check-overlap-'));
|
|
33
|
+
const controllerHome = join(root, 'controller');
|
|
34
|
+
const repoRoot = join(root, 'repo');
|
|
35
|
+
|
|
36
|
+
const behavioralContract = {
|
|
37
|
+
originalUserFacingGoal: 'A long focused check must run in the background while Forge continues useful independent work, then synchronize once at the true dependency boundary.',
|
|
38
|
+
invariants: {
|
|
39
|
+
backgroundCheck: 'long_check_returns_a_managed_handle_promptly',
|
|
40
|
+
noPollingWhileUsefulWorkExists: 'zero_process_wait_calls_before_independent_work_finishes',
|
|
41
|
+
dependencyDrivenJoin: 'one_final_process_wait_after_the_dependency_boundary',
|
|
42
|
+
exactlyOnce: 'one_physical_check_execution',
|
|
43
|
+
resultCorrectness: 'terminal_result_matches_the_returned_process_id',
|
|
44
|
+
noAdditionalOrchestration: 'no_execution_job_created_for_the_fast_check_route',
|
|
45
|
+
sourceRetrievalStaysFocused: 'ordinary_rh_context_search_skips_execution_preflight',
|
|
46
|
+
summaryStaysCheap: 'rh_status_summary_avoids_detail_diagnostics',
|
|
47
|
+
},
|
|
48
|
+
antiGoals: [
|
|
49
|
+
'periodic_process_wait_polling',
|
|
50
|
+
'synchronous_wait_before_independent_work',
|
|
51
|
+
'duplicate_check_execution',
|
|
52
|
+
'source_retrieval_building_unrequested_check_readiness',
|
|
53
|
+
'summary_status_triggering_detail_diagnostics',
|
|
54
|
+
],
|
|
55
|
+
validation: 'Runs a real managed check, performs rh_context work before the sole join, and separately asserts the rh_status summary hot path.',
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
function percentile(values: number[], ratio: number): number {
|
|
59
|
+
const sorted = [...values].sort((left, right) => left - right);
|
|
60
|
+
return Math.round((sorted[Math.min(sorted.length - 1, Math.floor(sorted.length * ratio))] ?? 0) * 100) / 100;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
try {
|
|
64
|
+
mkdirSync(join(repoRoot, 'src'), { recursive: true });
|
|
65
|
+
mkdirSync(join(repoRoot, '.forge'), { recursive: true });
|
|
66
|
+
execFileSync('git', ['init', '-q', '-b', 'main'], { cwd: repoRoot });
|
|
67
|
+
execFileSync('git', ['config', 'user.email', 'benchmark@example.test'], { cwd: repoRoot });
|
|
68
|
+
execFileSync('git', ['config', 'user.name', 'Forge Benchmark'], { cwd: repoRoot });
|
|
69
|
+
writeFileSync(join(repoRoot, 'src', 'fixture.ts'), 'export const backgroundFixture = true;\n');
|
|
70
|
+
const executionMarker = join(root, 'physical-check-executions.txt');
|
|
71
|
+
writeFileSync(join(repoRoot, '.forge', 'checks.json'), JSON.stringify({
|
|
72
|
+
version: 1,
|
|
73
|
+
checks: {
|
|
74
|
+
background: {
|
|
75
|
+
description: 'Synthetic long check for controller overlap behavior.',
|
|
76
|
+
command: [
|
|
77
|
+
process.execPath,
|
|
78
|
+
'-e',
|
|
79
|
+
[
|
|
80
|
+
`require('fs').appendFileSync(${JSON.stringify(executionMarker)}, '1');`,
|
|
81
|
+
`setTimeout(() => { process.stdout.write('BACKGROUND_CHECK_DONE\\n'); process.exit(0); }, ${CHECK_DURATION_MS});`,
|
|
82
|
+
].join(' '),
|
|
83
|
+
],
|
|
84
|
+
timeoutMs: 10_000,
|
|
85
|
+
},
|
|
86
|
+
},
|
|
87
|
+
}, null, 2));
|
|
88
|
+
execFileSync('git', ['add', '.'], { cwd: repoRoot });
|
|
89
|
+
execFileSync('git', ['commit', '-qm', 'fixture'], { cwd: repoRoot });
|
|
90
|
+
|
|
91
|
+
const repository = registerRepository({ path: repoRoot, controllerHome, displayName: 'background-check-overlap' });
|
|
92
|
+
const ctx = createMcpToolContext({ controllerHome, profile: 'controller', repo: repoRoot });
|
|
93
|
+
|
|
94
|
+
const startedAt = performance.now();
|
|
95
|
+
const started = await routeDurableMcpCall(ctx, 'run_check', {
|
|
96
|
+
repo_id: repository.repoId,
|
|
97
|
+
check_id: 'background',
|
|
98
|
+
interactive_wait_ms: 0,
|
|
99
|
+
});
|
|
100
|
+
const initialHandleLatencyMs = performance.now() - startedAt;
|
|
101
|
+
const startPayload = started?.structuredContent as Record<string, unknown> | undefined;
|
|
102
|
+
const processId = typeof startPayload?.processId === 'string' ? startPayload.processId : '';
|
|
103
|
+
|
|
104
|
+
const independentStartedAt = performance.now();
|
|
105
|
+
const independent = await callRuntimeTool(ctx, 'rh_context', {
|
|
106
|
+
repo_id: repository.repoId,
|
|
107
|
+
operation: 'search',
|
|
108
|
+
query: 'backgroundFixture',
|
|
109
|
+
known_paths: ['src/fixture.ts'],
|
|
110
|
+
structural_context: 'off',
|
|
111
|
+
});
|
|
112
|
+
const independentOperationLatencyMs = performance.now() - independentStartedAt;
|
|
113
|
+
const independentPayload = independent?.structuredContent as { data?: Record<string, unknown> } | undefined;
|
|
114
|
+
const independentData = independentPayload?.data;
|
|
115
|
+
const independentRetrievalPolicy = independentData?.retrievalPolicy as Record<string, unknown> | undefined;
|
|
116
|
+
const sourceRetrievalSkippedExecutionPreflight = independentData?.executionReadiness === undefined
|
|
117
|
+
&& independentData?.registeredChecks === undefined
|
|
118
|
+
&& independentRetrievalPolicy?.executionReadiness === 'requested_check_ids_only';
|
|
119
|
+
const processWaitCallsBeforeDependencyBoundary = 0;
|
|
120
|
+
|
|
121
|
+
const joinStartedAtMs = Date.now();
|
|
122
|
+
const joined = processId
|
|
123
|
+
? await callProcessTool(ctx, 'process_wait', {
|
|
124
|
+
repo_id: repository.repoId,
|
|
125
|
+
process_id: processId,
|
|
126
|
+
timeout_ms: 10_000,
|
|
127
|
+
})
|
|
128
|
+
: undefined;
|
|
129
|
+
const resultObservedAtMs = Date.now();
|
|
130
|
+
const finalSynchronizationCount = processId ? 1 : 0;
|
|
131
|
+
const joinedPayload = joined?.structuredContent as { process?: { processId?: string; completed?: boolean; ok?: boolean } } | undefined;
|
|
132
|
+
const record = processId ? getProcessRecord(controllerHome, repository.repoId, processId) : undefined;
|
|
133
|
+
const finishedAtMs = record?.finishedAt ? Date.parse(record.finishedAt) : NaN;
|
|
134
|
+
const completionToObservationLatencyMs = Number.isFinite(finishedAtMs)
|
|
135
|
+
? Math.max(0, resultObservedAtMs - finishedAtMs)
|
|
136
|
+
: undefined;
|
|
137
|
+
const physicalExecutionCount = readFileSync(executionMarker, 'utf8').length;
|
|
138
|
+
|
|
139
|
+
// Summary is a separate hot path: it must answer readiness without falling
|
|
140
|
+
// into the full Git status/diff-stat or maintenance/detail projection.
|
|
141
|
+
clearGitIdentityCacheForTest();
|
|
142
|
+
clearGitSnapshotCacheForTest();
|
|
143
|
+
const statusSummaryDurations: number[] = [];
|
|
144
|
+
let summaryPayload: Record<string, unknown> | undefined;
|
|
145
|
+
for (let iteration = 0; iteration < 7; iteration += 1) {
|
|
146
|
+
const statusStartedAt = performance.now();
|
|
147
|
+
const status = await callRuntimeTool(ctx, 'rh_status', { repo_id: repository.repoId, detail_level: 'summary' });
|
|
148
|
+
statusSummaryDurations.push(performance.now() - statusStartedAt);
|
|
149
|
+
summaryPayload = status?.structuredContent as Record<string, unknown> | undefined;
|
|
150
|
+
}
|
|
151
|
+
// Snapshot this before the intentional detail call below: detail is allowed
|
|
152
|
+
// to build the full Git projection, while summary is not.
|
|
153
|
+
const summaryGitSnapshot = gitSnapshotPerformanceSnapshot();
|
|
154
|
+
const detailStartedAt = performance.now();
|
|
155
|
+
const detail = await callRuntimeTool(ctx, 'rh_status', { repo_id: repository.repoId, detail_level: 'detail' });
|
|
156
|
+
const detailElapsedMs = performance.now() - detailStartedAt;
|
|
157
|
+
const detailPayload = detail?.structuredContent as Record<string, unknown> | undefined;
|
|
158
|
+
const detailMeta = detailPayload?.responseMeta as Record<string, unknown> | undefined;
|
|
159
|
+
const summaryData = summaryPayload?.data as Record<string, unknown> | undefined;
|
|
160
|
+
const summaryRepositoryState = summaryData?.repositoryState as Record<string, unknown> | undefined;
|
|
161
|
+
const summaryUsesCompactPayload = Boolean(summaryData)
|
|
162
|
+
&& summaryData?.access === undefined
|
|
163
|
+
&& summaryData?.pendingHandoffCount === undefined
|
|
164
|
+
&& summaryData?.activeWorkCount === undefined
|
|
165
|
+
&& summaryData?.activeProcessCount === undefined
|
|
166
|
+
&& summaryRepositoryState?.status === undefined
|
|
167
|
+
&& summaryRepositoryState?.diffStat === undefined;
|
|
168
|
+
|
|
169
|
+
const assertions = {
|
|
170
|
+
initialManagedHandle: Boolean(processId) && startPayload?.path === 'process_managed' && initialHandleLatencyMs <= MAX_INITIAL_HANDLE_LATENCY_MS,
|
|
171
|
+
independentUsefulOperation: independent?.isError !== true,
|
|
172
|
+
sourceRetrievalSkipsExecutionPreflight: sourceRetrievalSkippedExecutionPreflight,
|
|
173
|
+
noPollingBeforeDependencyBoundary: processWaitCallsBeforeDependencyBoundary === 0,
|
|
174
|
+
oneDependencyJoin: finalSynchronizationCount === 1,
|
|
175
|
+
exactlyOnce: physicalExecutionCount === 1,
|
|
176
|
+
terminalResultCorrect: joinedPayload?.process?.processId === processId && joinedPayload?.process?.completed === true && joinedPayload?.process?.ok === true,
|
|
177
|
+
promptResultObservation: completionToObservationLatencyMs === undefined || completionToObservationLatencyMs <= MAX_TERMINAL_OBSERVATION_LATENCY_MS,
|
|
178
|
+
statusSummaryUsesCompactProjection: Boolean(summaryPayload?.data)
|
|
179
|
+
&& summaryGitSnapshot.refreshes === 0
|
|
180
|
+
&& summaryGitSnapshot.subprocesses === 0
|
|
181
|
+
&& summaryUsesCompactPayload,
|
|
182
|
+
};
|
|
183
|
+
const output = {
|
|
184
|
+
schemaVersion: 1,
|
|
185
|
+
behavioralContract,
|
|
186
|
+
check: {
|
|
187
|
+
configuredDurationMs: CHECK_DURATION_MS,
|
|
188
|
+
initialManagedHandleLatencyMs: Number(initialHandleLatencyMs.toFixed(2)),
|
|
189
|
+
processWaitCallsBeforeDependencyBoundary,
|
|
190
|
+
independentOperation: {
|
|
191
|
+
tool: 'rh_context.search',
|
|
192
|
+
latencyMs: Number(independentOperationLatencyMs.toFixed(2)),
|
|
193
|
+
completed: independent?.isError !== true,
|
|
194
|
+
executionPreflight: sourceRetrievalSkippedExecutionPreflight ? 'not_requested' : 'unexpected',
|
|
195
|
+
},
|
|
196
|
+
finalSynchronizationCount,
|
|
197
|
+
finalJoinDurationMs: resultObservedAtMs - joinStartedAtMs,
|
|
198
|
+
physicalExecutionCount,
|
|
199
|
+
terminalCompletionToObservationLatencyMs: completionToObservationLatencyMs,
|
|
200
|
+
processId,
|
|
201
|
+
},
|
|
202
|
+
status: {
|
|
203
|
+
summaryP50Ms: percentile(statusSummaryDurations, 0.5),
|
|
204
|
+
summaryP95Ms: percentile(statusSummaryDurations, 0.95),
|
|
205
|
+
detailElapsedMs: Number(detailElapsedMs.toFixed(2)),
|
|
206
|
+
detailServerDurationMs: detailMeta?.serverDurationMs,
|
|
207
|
+
detailPhaseTimingsMs: detailMeta?.phaseTimingsMs,
|
|
208
|
+
fullGitSnapshot: summaryGitSnapshot,
|
|
209
|
+
summaryOmissions: {
|
|
210
|
+
maintenance: true,
|
|
211
|
+
plugins: true,
|
|
212
|
+
workState: true,
|
|
213
|
+
accessPolicy: true,
|
|
214
|
+
gitStatusAndDiffStat: true,
|
|
215
|
+
},
|
|
216
|
+
},
|
|
217
|
+
thresholds: {
|
|
218
|
+
initialManagedHandleLatencyMs: MAX_INITIAL_HANDLE_LATENCY_MS,
|
|
219
|
+
terminalCompletionToObservationLatencyMs: MAX_TERMINAL_OBSERVATION_LATENCY_MS,
|
|
220
|
+
},
|
|
221
|
+
assertions,
|
|
222
|
+
passed: Object.values(assertions).every(Boolean),
|
|
223
|
+
};
|
|
224
|
+
process.stdout.write(`${JSON.stringify(output, null, 2)}\n`);
|
|
225
|
+
if (!output.passed) process.exitCode = 1;
|
|
226
|
+
} finally {
|
|
227
|
+
rmSync(root, { recursive: true, force: true });
|
|
228
|
+
}
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
set -euo pipefail
|
|
3
|
+
|
|
4
|
+
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
|
5
|
+
BUN_BIN="${BUN_BIN:-bun}"
|
|
6
|
+
LABEL="${FORGE_MCP_BENCH_LABEL:-host-runtime-direct}"
|
|
7
|
+
PORT="${FORGE_MCP_BENCH_PORT:-18765}"
|
|
8
|
+
ITERATIONS="${FORGE_MCP_BENCH_ITERATIONS:-50}"
|
|
9
|
+
CONNECT_ITERATIONS="${FORGE_MCP_BENCH_CONNECT_ITERATIONS:-30}"
|
|
10
|
+
|
|
11
|
+
for value in "$PORT" "$ITERATIONS" "$CONNECT_ITERATIONS"; do
|
|
12
|
+
if ! [[ "$value" =~ ^[0-9]+$ ]] || [[ "$value" == "0" ]]; then
|
|
13
|
+
echo "benchmark:mcp-host requires positive integer port/iteration values" >&2
|
|
14
|
+
exit 2
|
|
15
|
+
fi
|
|
16
|
+
done
|
|
17
|
+
if (( PORT < 1024 || PORT > 65535 )); then
|
|
18
|
+
echo "FORGE_MCP_BENCH_PORT must be between 1024 and 65535" >&2
|
|
19
|
+
exit 2
|
|
20
|
+
fi
|
|
21
|
+
|
|
22
|
+
TMP_ROOT="$(mktemp -d "${TMPDIR:-/tmp}/forge-mcp-host-bench.XXXXXX")"
|
|
23
|
+
CONTROLLER_HOME="$TMP_ROOT/controller-home"
|
|
24
|
+
REGISTER_JSON="$TMP_ROOT/repository.json"
|
|
25
|
+
INSTALL_JSON="$TMP_ROOT/runtime-install.json"
|
|
26
|
+
READY_JSON="$TMP_ROOT/runtime-ready.json"
|
|
27
|
+
STEADY_JSON="$TMP_ROOT/steady.json"
|
|
28
|
+
CONNECT_JSON="$TMP_ROOT/connect.json"
|
|
29
|
+
RUNTIME_PID=""
|
|
30
|
+
|
|
31
|
+
cleanup() {
|
|
32
|
+
if [[ -n "$RUNTIME_PID" ]] && kill -0 "$RUNTIME_PID" 2>/dev/null; then
|
|
33
|
+
kill "$RUNTIME_PID" 2>/dev/null || true
|
|
34
|
+
for _ in $(seq 1 20); do
|
|
35
|
+
kill -0 "$RUNTIME_PID" 2>/dev/null || break
|
|
36
|
+
sleep 0.1
|
|
37
|
+
done
|
|
38
|
+
kill -9 "$RUNTIME_PID" 2>/dev/null || true
|
|
39
|
+
fi
|
|
40
|
+
for _ in $(seq 1 5); do
|
|
41
|
+
rm -rf "$TMP_ROOT" 2>/dev/null && return 0
|
|
42
|
+
sleep 0.1
|
|
43
|
+
done
|
|
44
|
+
rm -rf "$TMP_ROOT" 2>/dev/null || true
|
|
45
|
+
}
|
|
46
|
+
trap cleanup EXIT INT TERM
|
|
47
|
+
|
|
48
|
+
TOKEN="$(node -e "process.stdout.write(require('crypto').randomBytes(32).toString('hex'))")"
|
|
49
|
+
export FORGE_MCP_TOKEN="$TOKEN"
|
|
50
|
+
export FORGE_MCP_BENCH_TOKEN="$TOKEN"
|
|
51
|
+
|
|
52
|
+
cd "$ROOT"
|
|
53
|
+
"$BUN_BIN" bin/forge.mjs repo register "$ROOT" \
|
|
54
|
+
--controller-home "$CONTROLLER_HOME" \
|
|
55
|
+
--json > "$REGISTER_JSON"
|
|
56
|
+
REPO_ID="$(node -e "const x=require(process.argv[1]); const id=x?.repository?.repoId; if(!id) process.exit(2); process.stdout.write(id)" "$REGISTER_JSON")"
|
|
57
|
+
|
|
58
|
+
"$BUN_BIN" bin/forge.mjs runtime service install-package \
|
|
59
|
+
--controller-home "$CONTROLLER_HOME" \
|
|
60
|
+
--host 127.0.0.1 \
|
|
61
|
+
--port "$PORT" \
|
|
62
|
+
--portable > "$INSTALL_JSON"
|
|
63
|
+
RUNTIME_PID="$(node -e "const x=require(process.argv[1]); const pid=x?.pid; if(!Number.isInteger(pid)||pid<=0) process.exit(2); process.stdout.write(String(pid))" "$INSTALL_JSON")"
|
|
64
|
+
|
|
65
|
+
curl --fail --silent --show-error \
|
|
66
|
+
--retry 30 --retry-delay 1 --retry-connrefused \
|
|
67
|
+
"http://127.0.0.1:${PORT}/ready" > "$READY_JSON"
|
|
68
|
+
|
|
69
|
+
"$BUN_BIN" run benchmark:mcp-transport -- \
|
|
70
|
+
--endpoint "http://127.0.0.1:${PORT}/mcp" \
|
|
71
|
+
--label "$LABEL" \
|
|
72
|
+
--repo-id "$REPO_ID" \
|
|
73
|
+
--tool rh_status \
|
|
74
|
+
--iterations "$ITERATIONS" \
|
|
75
|
+
--warmup 3 \
|
|
76
|
+
--timing-log "$CONTROLLER_HOME/audit/mcp-timings.jsonl" > "$STEADY_JSON"
|
|
77
|
+
|
|
78
|
+
"$BUN_BIN" run benchmark:mcp-transport -- \
|
|
79
|
+
--endpoint "http://127.0.0.1:${PORT}/mcp" \
|
|
80
|
+
--label "$LABEL" \
|
|
81
|
+
--repo-id "$REPO_ID" \
|
|
82
|
+
--tool rh_status \
|
|
83
|
+
--iterations "$CONNECT_ITERATIONS" \
|
|
84
|
+
--warmup 0 \
|
|
85
|
+
--include-connect \
|
|
86
|
+
--timing-log "$CONTROLLER_HOME/audit/mcp-timings.jsonl" > "$CONNECT_JSON"
|
|
87
|
+
|
|
88
|
+
node - "$STEADY_JSON" "$CONNECT_JSON" "$READY_JSON" <<'NODE'
|
|
89
|
+
const fs = require('fs');
|
|
90
|
+
const os = require('os');
|
|
91
|
+
const path = require('path');
|
|
92
|
+
const [steadyPath, connectPath, readyPath] = process.argv.slice(2);
|
|
93
|
+
const steady = JSON.parse(fs.readFileSync(steadyPath, 'utf8'));
|
|
94
|
+
const connect = JSON.parse(fs.readFileSync(connectPath, 'utf8'));
|
|
95
|
+
const ready = JSON.parse(fs.readFileSync(readyPath, 'utf8'));
|
|
96
|
+
const report = {
|
|
97
|
+
schemaVersion: 1,
|
|
98
|
+
generatedAt: new Date().toISOString(),
|
|
99
|
+
host: {
|
|
100
|
+
platform: process.platform,
|
|
101
|
+
arch: process.arch,
|
|
102
|
+
cpuCount: os.cpus().length,
|
|
103
|
+
totalMemoryBytes: os.totalmem(),
|
|
104
|
+
},
|
|
105
|
+
ready,
|
|
106
|
+
steady,
|
|
107
|
+
connectInclusive: connect,
|
|
108
|
+
};
|
|
109
|
+
const text = `${JSON.stringify(report, null, 2)}\n`;
|
|
110
|
+
const output = process.env.FORGE_MCP_BENCH_OUTPUT?.trim();
|
|
111
|
+
if (output) {
|
|
112
|
+
const target = path.resolve(output);
|
|
113
|
+
fs.mkdirSync(path.dirname(target), { recursive: true });
|
|
114
|
+
fs.writeFileSync(target, text, 'utf8');
|
|
115
|
+
}
|
|
116
|
+
process.stdout.write(text);
|
|
117
|
+
NODE
|