@moretea-labs/forge 1.6.0 → 1.7.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +4 -0
- package/CHANGELOG.md +39 -0
- package/CLAUDE.md +4 -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/02-operating-mode.partial.md +2 -0
- package/assets/partials-agents/03-orchestration.partial.md +1 -1
- package/assets/plugin-registry.v1.json +3 -3
- 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-architecture-sync.sh +17 -0
- 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/inspect-project-state.ts +8 -6
- package/assets/templates/helpers/migrate-project-template.sh +22 -45
- package/assets/templates/helpers/migrate-workflow-docs.ts +9 -7
- 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/helpers/workflow-contract.ts +5 -1
- 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 +178 -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-plugin-management.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 +143 -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 +33 -11
- package/scripts/activate-source-baseline.ts +17 -13
- package/scripts/architecture-event.ts +2 -820
- package/scripts/architecture-queue.sh +2 -645
- package/scripts/archive-architecture-request.sh +2 -242
- package/scripts/archive-workflow.sh +1 -291
- 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/capability-config.ts +2 -392
- package/scripts/capability-resolver.ts +2 -503
- package/scripts/capture-plan.sh +1 -332
- package/scripts/check-agent-tooling.sh +2 -1558
- package/scripts/check-architecture-sync.sh +2 -371
- package/scripts/check-brain-manifest.sh +2 -253
- package/scripts/check-context-files.sh +2 -47
- package/scripts/check-deploy-sql-order.sh +2 -115
- package/scripts/check-mcp-compatibility.ts +14 -0
- package/scripts/check-runtime-architecture.mjs +349 -79
- package/scripts/check-skill-version.ts +3 -191
- package/scripts/check-source-duplication.mjs +61 -0
- package/scripts/check-stable-baseline.ts +92 -0
- package/scripts/check-task-sync.sh +2 -63
- package/scripts/check-task-workflow.sh +2 -1000
- package/scripts/codex-handoff-resume.sh +2 -267
- package/scripts/context-contract-sync.sh +2 -514
- package/scripts/contract-run.ts +2 -463
- package/scripts/contract-worktree.sh +1 -722
- package/scripts/ensure-task-workflow.sh +1 -1225
- package/scripts/host-temporary-cloud-mcp-e2e.sh +265 -0
- package/scripts/inspect-project-state.ts +4 -279
- package/scripts/install-standalone-recovery.ts +24 -0
- package/scripts/lib/project-init-lib.sh +22 -46
- package/scripts/lib/run-forge-helper.sh +19 -0
- package/scripts/lib/run-forge-helper.ts +26 -0
- package/scripts/migrate-project-template.sh +1 -1189
- package/scripts/migrate-workflow-docs.ts +4 -412
- package/scripts/new-plan.sh +1 -180
- package/scripts/new-spec.sh +1 -47
- package/scripts/new-sprint.sh +1 -46
- package/scripts/plan-to-todo.sh +1 -796
- package/scripts/prepare-codex-handoff.sh +2 -201
- package/scripts/prepare-handoff.sh +1 -78
- package/scripts/refresh-current-status.sh +2 -467
- package/scripts/run-governed-gate.ts +5 -1
- package/scripts/select-agent-context-blocks.sh +2 -64
- package/scripts/ship-worktrees.sh +1 -558
- 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 -834
- package/scripts/stage-runtime-release.ts +2 -1
- package/scripts/summarize-failures.sh +2 -123
- package/scripts/switch-plan.sh +1 -150
- package/scripts/sync-brain-docs.sh +2 -379
- package/scripts/sync-generated-authority.mjs +175 -0
- package/scripts/verify-contract.sh +2 -703
- package/scripts/verify-forge-runtime.sh +0 -1
- package/scripts/verify-sprint.sh +1 -677
- package/scripts/workflow-contract.ts +4 -205
- package/scripts/workstream-sync.sh +2 -261
- package/src/cli/agent-jobs/executor-health.ts +1 -1
- package/src/cli/commands/init-hook.ts +3 -3
- package/src/cli/commands/mcp.ts +9 -5
- package/src/cli/commands/plugin.ts +12 -3
- 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 +113 -5
- 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 +828 -487
- 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/contracts.ts +16 -0
- package/src/cli/github/github.ts +135 -16
- package/src/cli/github/session.ts +2 -1
- 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 +37 -264
- 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 +2 -515
- 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 +10 -222
- package/src/cli/mcp/multi-repository.ts +16 -5
- package/src/cli/mcp/oauth.ts +175 -26
- package/src/cli/mcp/post-finalize-work-attribution.ts +150 -0
- package/src/cli/mcp/repository-tools.ts +282 -146
- package/src/cli/mcp/server.ts +586 -116
- package/src/cli/mcp/tool-capability-cache.ts +1 -1
- package/src/cli/mcp/tool-contract.ts +14 -0
- package/src/cli/mcp/toolset-selection.ts +1 -1
- package/src/cli/mcp/toolset.ts +44 -7
- package/src/cli/mcp/transports/http.ts +124 -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 +103 -21
- package/src/cli/repositories/command-executor.ts +78 -526
- 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 +124 -0
- package/src/cli/repositories/selected-path-actions.ts +17 -9
- package/src/cli/repositories/structured-git.ts +118 -6
- package/src/cli/repository/inspector.ts +563 -65
- 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-contract.ts +61 -0
- package/src/runtime/context/semantic-navigation.ts +223 -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 +48 -16
- package/src/runtime/control-plane/execution/edit-validation-coordinator.ts +86 -24
- package/src/runtime/control-plane/execution/repository-work-attribution.ts +106 -0
- package/src/runtime/control-plane/execution/retained-work-resume.ts +203 -0
- 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-completion-authority.ts +58 -0
- package/src/runtime/control-plane/execution/work-evidence-policy.ts +200 -0
- package/src/runtime/control-plane/execution/work-execution-support.ts +386 -0
- package/src/runtime/control-plane/execution/work-finalization-service.ts +1913 -0
- package/src/runtime/control-plane/execution/work-handle-authority.ts +96 -0
- 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-operation-service.ts +468 -0
- package/src/runtime/control-plane/execution/work-path-scope.ts +37 -0
- package/src/runtime/control-plane/execution/work-preparation-service.ts +479 -0
- package/src/runtime/control-plane/execution/work-process-evidence.ts +129 -0
- package/src/runtime/control-plane/execution/work-remote-delivery.ts +215 -0
- package/src/runtime/control-plane/execution/work-task-receipt.ts +22 -18
- package/src/runtime/control-plane/execution/work-terminal-cleanup.ts +156 -11
- package/src/runtime/control-plane/execution/work-validation-reconciler.ts +22 -14
- package/src/runtime/control-plane/execution/work-verification-context.ts +56 -0
- package/src/runtime/control-plane/execution/work-verification-service.ts +388 -0
- package/src/runtime/control-plane/execution/work-verification-snapshot.ts +90 -9
- package/src/runtime/control-plane/facade/capability-registry.ts +129 -25
- package/src/runtime/control-plane/facade/controller-round-relay.ts +1118 -0
- package/src/runtime/control-plane/facade/controller-session-store.ts +302 -12
- package/src/runtime/control-plane/facade/goal-workloop-access.ts +17 -1
- package/src/runtime/control-plane/facade/goal-workloop.ts +928 -190
- package/src/runtime/control-plane/facade/index.ts +3 -0
- package/src/runtime/control-plane/facade/plan-contract-store.ts +275 -42
- package/src/runtime/control-plane/facade/repository-work-admission.ts +147 -0
- package/src/runtime/control-plane/facade/requirement-authority.ts +83 -0
- 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 +90 -10
- package/src/runtime/control-plane/facade/work-contract-store.ts +157 -261
- package/src/runtime/control-plane/facade/work-state-machine.ts +250 -0
- 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 +152 -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 +278 -543
- 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 +63 -0
- package/src/runtime/control-plane/launcher/chatgpt-work-continuation.ts +365 -117
- package/src/runtime/control-plane/launcher/launch-reservation-store.ts +89 -0
- package/src/runtime/control-plane/launcher/thin-launcher.ts +244 -11
- package/src/runtime/control-plane/persistence/controller-home-migration.ts +487 -0
- package/src/runtime/control-plane/persistence/requirement-store.ts +0 -12
- 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/repo-actor/registry.ts +4 -2
- package/src/runtime/control-plane/routing/route-policy.ts +24 -21
- package/src/runtime/control-plane/routing/workspace-admission.ts +70 -0
- 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/evidence/process-check-execution.ts +18 -0
- package/src/runtime/execution/jobs/child-reference.ts +6 -2
- 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 +88 -0
- package/src/runtime/execution/process-runtime/check-runner-sidecar.ts +7 -1
- package/src/runtime/execution/process-runtime/check-scheduling.ts +114 -0
- package/src/runtime/execution/process-runtime/command-facade.ts +367 -40
- package/src/runtime/execution/process-runtime/gc.ts +38 -6
- package/src/runtime/execution/process-runtime/lightweight-managed.ts +1201 -0
- package/src/runtime/execution/process-runtime/persisted-check.ts +51 -5
- package/src/runtime/execution/process-runtime/resource-claims.ts +10 -6
- package/src/runtime/execution/process-runtime/runtime.ts +53 -3
- package/src/runtime/execution/process-runtime/store.ts +1 -0
- package/src/runtime/execution/process-runtime/types.ts +4 -12
- 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/work-activity.ts +21 -0
- package/src/runtime/execution/workers/executor.ts +18 -61
- package/src/runtime/gateway/mcp/execution-tools.ts +35 -1852
- package/src/runtime/gateway/mcp/legacy-ios-tool-adapter.ts +61 -0
- package/src/runtime/gateway/mcp/process-tools.ts +83 -37
- package/src/runtime/gateway/mcp/router.ts +186 -84
- package/src/runtime/gateway/mcp/runtime-tool-definitions.ts +565 -0
- package/src/runtime/gateway/mcp/runtime-tools.ts +2378 -1947
- package/src/runtime/plugins/app-store-connect-adapter.ts +216 -47
- package/src/runtime/plugins/browser-adapter.ts +2662 -829
- package/src/runtime/plugins/browser-automation-service.ts +10 -0
- package/src/runtime/plugins/browser-handoff-host.ts +2 -25
- package/src/runtime/plugins/browser-handoff.ts +110 -5
- package/src/runtime/plugins/browser-macos-bridge.ts +701 -63
- package/src/runtime/plugins/browser-manifest-surface.ts +603 -0
- package/src/runtime/plugins/browser-native-session-service.ts +222 -0
- 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 +154 -0
- package/src/runtime/plugins/browser-runtime.ts +193 -0
- package/src/runtime/plugins/browser-session-authority.ts +332 -0
- package/src/runtime/plugins/browser-session-store.ts +121 -0
- package/src/runtime/plugins/browser-session-types.ts +98 -0
- package/src/runtime/plugins/capability-authorization-grants.ts +354 -0
- package/src/runtime/plugins/desktop-operator-registration.ts +10 -4
- package/src/runtime/plugins/external-adapter.ts +358 -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 +47 -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 +330 -33
- package/src/runtime/plugins/types.ts +38 -3
- 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 +426 -25
- package/src/runtime/root/mcp-transport.ts +180 -10
- package/src/runtime/root/package-connector-service.ts +230 -10
- package/src/runtime/root/package-runtime-release.ts +143 -17
- package/src/runtime/root/package-runtime-service.ts +461 -22
- package/src/runtime/root/release-manifest.ts +144 -18
- package/src/runtime/root/release-materialize.ts +125 -32
- 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 +12 -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 +1079 -240
- package/src/runtime/standalone-recovery/entry.ts +100 -24
- package/src/runtime/standalone-recovery/installer.ts +20 -4
- 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 +364 -202
- package/src/runtime/workflow/schedules/github-issue-watch.ts +158 -0
- package/src/runtime/workflow/schedules/settlement.ts +64 -17
- package/src/runtime/workflow/schedules/store.ts +209 -19
- 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
|
@@ -5,6 +5,7 @@ import {
|
|
|
5
5
|
writeControlPlaneRecord,
|
|
6
6
|
} from '../persistence/sqlite-store';
|
|
7
7
|
import type { ControllerType } from '../facade/types';
|
|
8
|
+
import { redactProcessOutput } from '../../../effects/process-runner';
|
|
8
9
|
|
|
9
10
|
const NAMESPACE = 'external_controller_launch_reservation';
|
|
10
11
|
const DEFAULT_TTL_MS = 2 * 60_000;
|
|
@@ -19,8 +20,14 @@ export interface ExternalControllerLaunchReservation {
|
|
|
19
20
|
createdAt: string;
|
|
20
21
|
expiresAt: string;
|
|
21
22
|
pid?: number;
|
|
23
|
+
exitedAt?: string;
|
|
24
|
+
exitCode?: number;
|
|
25
|
+
exitSignal?: string;
|
|
22
26
|
releasedAt?: string;
|
|
23
27
|
releaseReason?: string;
|
|
28
|
+
/** Bounded, redacted provider output captured only during launcher startup. */
|
|
29
|
+
stdoutTail?: string;
|
|
30
|
+
stderrTail?: string;
|
|
24
31
|
}
|
|
25
32
|
|
|
26
33
|
export interface LaunchReservationStoreOptions {
|
|
@@ -54,6 +61,14 @@ export function getExternalControllerLaunchReservation(
|
|
|
54
61
|
return active(record(options, workId)?.value);
|
|
55
62
|
}
|
|
56
63
|
|
|
64
|
+
/** Read the latest reservation record including released/failed startup evidence. */
|
|
65
|
+
export function readExternalControllerLaunchReservationRecord(
|
|
66
|
+
options: LaunchReservationStoreOptions,
|
|
67
|
+
workId: string,
|
|
68
|
+
): ExternalControllerLaunchReservation | undefined {
|
|
69
|
+
return record(options, workId)?.value;
|
|
70
|
+
}
|
|
71
|
+
|
|
57
72
|
export function reserveExternalControllerLaunch(
|
|
58
73
|
options: LaunchReservationStoreOptions,
|
|
59
74
|
input: {
|
|
@@ -128,6 +143,80 @@ export function attachExternalControllerLaunchPid(
|
|
|
128
143
|
);
|
|
129
144
|
}
|
|
130
145
|
|
|
146
|
+
export function recordExternalControllerLaunchDiagnostics(
|
|
147
|
+
options: LaunchReservationStoreOptions,
|
|
148
|
+
workId: string,
|
|
149
|
+
reservationId: string,
|
|
150
|
+
diagnostics: { stdoutTail?: string; stderrTail?: string },
|
|
151
|
+
): ExternalControllerLaunchReservation | undefined {
|
|
152
|
+
return withControllerLock(
|
|
153
|
+
options.controllerHome,
|
|
154
|
+
{ scope: 'task', repoId: options.repoId, taskId: `controller-launch-${workId}` },
|
|
155
|
+
`controller-launch-diagnostics:${reservationId}`,
|
|
156
|
+
() => {
|
|
157
|
+
const existing = record(options, workId);
|
|
158
|
+
if (!existing || existing.value.reservationId !== reservationId) return existing?.value;
|
|
159
|
+
const next: ExternalControllerLaunchReservation = {
|
|
160
|
+
...existing.value,
|
|
161
|
+
...(diagnostics.stdoutTail ? { stdoutTail: redactProcessOutput(diagnostics.stdoutTail).slice(-8 * 1024) } : {}),
|
|
162
|
+
...(diagnostics.stderrTail ? { stderrTail: redactProcessOutput(diagnostics.stderrTail).slice(-8 * 1024) } : {}),
|
|
163
|
+
};
|
|
164
|
+
writeControlPlaneRecord(options.controllerHome, {
|
|
165
|
+
namespace: NAMESPACE,
|
|
166
|
+
scope: options.repoId,
|
|
167
|
+
key: workId,
|
|
168
|
+
schemaVersion: 1,
|
|
169
|
+
value: next,
|
|
170
|
+
action: 'external_controller_launch_diagnostics',
|
|
171
|
+
expectedRevision: existing.revision,
|
|
172
|
+
});
|
|
173
|
+
return next;
|
|
174
|
+
},
|
|
175
|
+
);
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
export function recordExternalControllerLaunchExit(
|
|
179
|
+
options: LaunchReservationStoreOptions,
|
|
180
|
+
workId: string,
|
|
181
|
+
reservationId: string,
|
|
182
|
+
exit: { exitCode: number | null; signal: string | null; stdoutTail?: string; stderrTail?: string },
|
|
183
|
+
): ExternalControllerLaunchReservation | undefined {
|
|
184
|
+
return withControllerLock(
|
|
185
|
+
options.controllerHome,
|
|
186
|
+
{ scope: 'task', repoId: options.repoId, taskId: `controller-launch-${workId}` },
|
|
187
|
+
`controller-launch-exit:${reservationId}`,
|
|
188
|
+
() => {
|
|
189
|
+
const existing = record(options, workId);
|
|
190
|
+
if (!existing || existing.value.reservationId !== reservationId) return existing?.value;
|
|
191
|
+
const exitedAt = nowIso(options);
|
|
192
|
+
const alreadyReleased = Boolean(existing.value.releasedAt);
|
|
193
|
+
const next: ExternalControllerLaunchReservation = {
|
|
194
|
+
...existing.value,
|
|
195
|
+
expiresAt: alreadyReleased ? existing.value.expiresAt : exitedAt,
|
|
196
|
+
exitedAt,
|
|
197
|
+
...(exit.exitCode === null ? {} : { exitCode: exit.exitCode }),
|
|
198
|
+
...(exit.signal ? { exitSignal: exit.signal } : {}),
|
|
199
|
+
...(exit.stdoutTail ? { stdoutTail: redactProcessOutput(exit.stdoutTail).slice(-8 * 1024) } : {}),
|
|
200
|
+
...(exit.stderrTail ? { stderrTail: redactProcessOutput(exit.stderrTail).slice(-8 * 1024) } : {}),
|
|
201
|
+
...(alreadyReleased ? {} : {
|
|
202
|
+
releasedAt: exitedAt,
|
|
203
|
+
releaseReason: `process_exit:code=${String(exit.exitCode ?? 'null')}:signal=${exit.signal ?? 'none'}`.slice(0, 240),
|
|
204
|
+
}),
|
|
205
|
+
};
|
|
206
|
+
writeControlPlaneRecord(options.controllerHome, {
|
|
207
|
+
namespace: NAMESPACE,
|
|
208
|
+
scope: options.repoId,
|
|
209
|
+
key: workId,
|
|
210
|
+
schemaVersion: 1,
|
|
211
|
+
value: next,
|
|
212
|
+
action: 'external_controller_launch_exit',
|
|
213
|
+
expectedRevision: existing.revision,
|
|
214
|
+
});
|
|
215
|
+
return next;
|
|
216
|
+
},
|
|
217
|
+
);
|
|
218
|
+
}
|
|
219
|
+
|
|
131
220
|
export function releaseExternalControllerLaunchReservation(
|
|
132
221
|
options: LaunchReservationStoreOptions,
|
|
133
222
|
workId: string,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { spawn, spawnSync } from 'child_process';
|
|
1
|
+
import { spawn, spawnSync, type ChildProcess } from 'child_process';
|
|
2
2
|
import {
|
|
3
3
|
getHandoffItem,
|
|
4
4
|
getWorkContract,
|
|
@@ -7,12 +7,17 @@ import {
|
|
|
7
7
|
} from '../facade';
|
|
8
8
|
import {
|
|
9
9
|
attachExternalControllerLaunchPid,
|
|
10
|
+
recordExternalControllerLaunchDiagnostics,
|
|
11
|
+
recordExternalControllerLaunchExit,
|
|
10
12
|
releaseExternalControllerLaunchReservation,
|
|
11
13
|
reserveExternalControllerLaunch,
|
|
12
14
|
} from './launch-reservation-store';
|
|
13
15
|
import type { ControllerType } from '../facade/types';
|
|
16
|
+
import { getControllerSession } from '../facade/controller-session-store';
|
|
14
17
|
import { codexMcpConfigArgs, resolveProviderMcpBootstrap, type ProviderMcpBootstrap } from './provider-mcp-bootstrap';
|
|
15
18
|
import { getChatgptWorkConversationBinding } from './chatgpt-work-binding-store';
|
|
19
|
+
import { repositoryChildProcessEnvironment } from '../../shared/process-environment';
|
|
20
|
+
import { redactProcessOutput } from '../../../effects/process-runner';
|
|
16
21
|
|
|
17
22
|
export interface ThinLauncherRequest {
|
|
18
23
|
controllerType: Exclude<ControllerType, 'human'>;
|
|
@@ -42,7 +47,51 @@ export interface ThinLauncherResult {
|
|
|
42
47
|
executable: string;
|
|
43
48
|
}
|
|
44
49
|
|
|
45
|
-
|
|
50
|
+
const LAUNCHER_STARTUP_GRACE_MS = 250;
|
|
51
|
+
const CODEX_WORK_CLAIM_TIMEOUT_MS = 30_000;
|
|
52
|
+
const CODEX_WORK_CLAIM_SETTLEMENT_GRACE_MS = 1_500;
|
|
53
|
+
const CODEX_WORK_CLAIM_POLL_INTERVAL_MS = 100;
|
|
54
|
+
const STARTUP_DIAGNOSTIC_BYTES = 8 * 1024;
|
|
55
|
+
|
|
56
|
+
function appendStartupDiagnosticTail(current: string, chunk: unknown): string {
|
|
57
|
+
const text = redactProcessOutput(Buffer.isBuffer(chunk) ? chunk.toString('utf8') : String(chunk ?? ''));
|
|
58
|
+
const buffer = Buffer.from(`${current}${text}`, 'utf8');
|
|
59
|
+
return buffer.length <= STARTUP_DIAGNOSTIC_BYTES
|
|
60
|
+
? buffer.toString('utf8')
|
|
61
|
+
: buffer.subarray(buffer.length - STARTUP_DIAGNOSTIC_BYTES).toString('utf8');
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function startupDiagnosticSummary(stdoutTail: string, stderrTail: string): string {
|
|
65
|
+
const value = redactProcessOutput(stderrTail.trim() || stdoutTail.trim()).replace(/\s+/g, ' ').slice(0, 1200);
|
|
66
|
+
return value ? `; startup_output=${value}` : '';
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
interface ExternalControllerClaimExpectation {
|
|
70
|
+
controllerType: 'codex';
|
|
71
|
+
controllerId: string;
|
|
72
|
+
principalId: string;
|
|
73
|
+
sessionId: string;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
export interface ThinLauncherDependencies {
|
|
77
|
+
resolveProviderMcpBootstrap?: typeof resolveProviderMcpBootstrap;
|
|
78
|
+
claimTimeoutMs?: number;
|
|
79
|
+
claimSettlementGraceMs?: number;
|
|
80
|
+
claimPollIntervalMs?: number;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
function launcherProcessEnvironment(env: NodeJS.ProcessEnv): NodeJS.ProcessEnv {
|
|
84
|
+
const repositoryEnv = repositoryChildProcessEnvironment(env);
|
|
85
|
+
return {
|
|
86
|
+
...env,
|
|
87
|
+
PATH: repositoryEnv.PATH,
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
export function resolveLauncherExecutable(
|
|
92
|
+
request: ThinLauncherRequest,
|
|
93
|
+
env: NodeJS.ProcessEnv = process.env,
|
|
94
|
+
): string {
|
|
46
95
|
const configured = request.executable?.trim();
|
|
47
96
|
if (configured) return configured;
|
|
48
97
|
const executable = request.controllerType === 'codex'
|
|
@@ -50,13 +99,14 @@ function resolveLauncherExecutable(request: ThinLauncherRequest): string {
|
|
|
50
99
|
: request.controllerType === 'claude'
|
|
51
100
|
? 'claude'
|
|
52
101
|
: request.controllerType === 'chatgpt'
|
|
53
|
-
?
|
|
102
|
+
? env.FORGE_CLI_EXECUTABLE?.trim() || 'forge'
|
|
54
103
|
: '';
|
|
55
104
|
if (!executable) throw new Error(`LAUNCHER_EXECUTABLE_REQUIRED: ${request.controllerType} requires an external launcher executable`);
|
|
56
105
|
const probe = spawnSync(executable, ['--version'], {
|
|
57
106
|
cwd: request.cwd,
|
|
58
107
|
stdio: 'ignore',
|
|
59
108
|
timeout: 5_000,
|
|
109
|
+
env: launcherProcessEnvironment(env),
|
|
60
110
|
});
|
|
61
111
|
if (probe.error || probe.status !== 0) {
|
|
62
112
|
throw new Error(`LAUNCHER_EXECUTABLE_UNAVAILABLE: ${executable}`);
|
|
@@ -64,6 +114,171 @@ function resolveLauncherExecutable(request: ThinLauncherRequest): string {
|
|
|
64
114
|
return executable;
|
|
65
115
|
}
|
|
66
116
|
|
|
117
|
+
async function awaitExternalControllerStartup(
|
|
118
|
+
child: ChildProcess,
|
|
119
|
+
stores: { work: WorkContractStoreOptions & { controllerHome: string; repoId: string } },
|
|
120
|
+
workId: string,
|
|
121
|
+
reservationId: string,
|
|
122
|
+
claimExpectation?: ExternalControllerClaimExpectation,
|
|
123
|
+
options: { claimTimeoutMs?: number; claimSettlementGraceMs?: number; claimPollIntervalMs?: number } = {},
|
|
124
|
+
): Promise<void> {
|
|
125
|
+
await new Promise<void>((resolve, reject) => {
|
|
126
|
+
let startupSettled = false;
|
|
127
|
+
let timer: ReturnType<typeof setTimeout> | undefined;
|
|
128
|
+
let stdoutTail = '';
|
|
129
|
+
let stderrTail = '';
|
|
130
|
+
const captureStdout = (chunk: unknown) => { stdoutTail = appendStartupDiagnosticTail(stdoutTail, chunk); };
|
|
131
|
+
const captureStderr = (chunk: unknown) => { stderrTail = appendStartupDiagnosticTail(stderrTail, chunk); };
|
|
132
|
+
child.stdout?.on('data', captureStdout);
|
|
133
|
+
child.stderr?.on('data', captureStderr);
|
|
134
|
+
const closeStartupPipes = () => {
|
|
135
|
+
child.stdout?.off('data', captureStdout);
|
|
136
|
+
child.stderr?.off('data', captureStderr);
|
|
137
|
+
child.stdout?.destroy();
|
|
138
|
+
child.stderr?.destroy();
|
|
139
|
+
};
|
|
140
|
+
const persistDiagnostics = () => {
|
|
141
|
+
if (!stdoutTail && !stderrTail) return;
|
|
142
|
+
try {
|
|
143
|
+
recordExternalControllerLaunchDiagnostics(stores.work, workId, reservationId, { stdoutTail, stderrTail });
|
|
144
|
+
} catch {
|
|
145
|
+
// Startup diagnostics are evidence only; preserve the primary ownership/claim outcome.
|
|
146
|
+
}
|
|
147
|
+
};
|
|
148
|
+
const clearTimer = () => {
|
|
149
|
+
if (timer) clearTimeout(timer);
|
|
150
|
+
timer = undefined;
|
|
151
|
+
};
|
|
152
|
+
const releaseFailure = (reason: string) => {
|
|
153
|
+
try {
|
|
154
|
+
releaseExternalControllerLaunchReservation(stores.work, workId, reservationId, reason);
|
|
155
|
+
} catch {
|
|
156
|
+
// Preserve the primary startup failure if diagnostic persistence itself races or fails.
|
|
157
|
+
}
|
|
158
|
+
};
|
|
159
|
+
const terminateUnclaimedChild = () => {
|
|
160
|
+
if (!child.pid || child.exitCode !== null || child.signalCode !== null) return;
|
|
161
|
+
try { child.kill('SIGTERM'); } catch { /* process may already be exiting */ }
|
|
162
|
+
};
|
|
163
|
+
const fail = (error: Error, reason: string, terminate = false) => {
|
|
164
|
+
if (startupSettled) return;
|
|
165
|
+
startupSettled = true;
|
|
166
|
+
clearTimer();
|
|
167
|
+
persistDiagnostics();
|
|
168
|
+
closeStartupPipes();
|
|
169
|
+
if (terminate) terminateUnclaimedChild();
|
|
170
|
+
releaseFailure(reason);
|
|
171
|
+
const diagnostics = startupDiagnosticSummary(stdoutTail, stderrTail);
|
|
172
|
+
reject(diagnostics ? new Error(`${error.message}${diagnostics}`) : error);
|
|
173
|
+
};
|
|
174
|
+
const expectedClaimMatches = (): { matches: boolean; mismatch?: string } => {
|
|
175
|
+
if (!claimExpectation) return { matches: true };
|
|
176
|
+
const owner = getControllerSession(stores.work, workId);
|
|
177
|
+
if (!owner) return { matches: false };
|
|
178
|
+
const ownerPrincipal = owner.principalId?.trim() || owner.controllerId;
|
|
179
|
+
const matches = owner.controllerType === claimExpectation.controllerType
|
|
180
|
+
&& owner.controllerId === claimExpectation.controllerId
|
|
181
|
+
&& ownerPrincipal === claimExpectation.principalId
|
|
182
|
+
&& owner.sessionId === claimExpectation.sessionId;
|
|
183
|
+
return matches
|
|
184
|
+
? { matches: true }
|
|
185
|
+
: {
|
|
186
|
+
matches: false,
|
|
187
|
+
mismatch: `observed type=${owner.controllerType} controller=${owner.controllerId} principal=${ownerPrincipal} session=${owner.sessionId}`,
|
|
188
|
+
};
|
|
189
|
+
};
|
|
190
|
+
|
|
191
|
+
child.once('error', (error) => {
|
|
192
|
+
fail(new Error(`LAUNCHER_STARTUP_FAILED: ${error.message}`), `spawn_error:${error.message}`);
|
|
193
|
+
});
|
|
194
|
+
|
|
195
|
+
child.once('exit', (exitCode, signal) => {
|
|
196
|
+
try {
|
|
197
|
+
recordExternalControllerLaunchExit(stores.work, workId, reservationId, {
|
|
198
|
+
exitCode,
|
|
199
|
+
signal: signal ? String(signal) : null,
|
|
200
|
+
stdoutTail,
|
|
201
|
+
stderrTail,
|
|
202
|
+
});
|
|
203
|
+
} catch {
|
|
204
|
+
// Exit evidence is best-effort after another authority has already released the reservation.
|
|
205
|
+
}
|
|
206
|
+
if (startupSettled) return;
|
|
207
|
+
startupSettled = true;
|
|
208
|
+
clearTimer();
|
|
209
|
+
closeStartupPipes();
|
|
210
|
+
const phase = claimExpectation ? 'before exact Work claim became live' : 'during startup grace';
|
|
211
|
+
reject(new Error(`LAUNCHER_STARTUP_FAILED: external Controller exited ${phase} (code=${String(exitCode ?? 'null')}, signal=${signal ?? 'none'})${startupDiagnosticSummary(stdoutTail, stderrTail)}`));
|
|
212
|
+
});
|
|
213
|
+
|
|
214
|
+
if (!claimExpectation) {
|
|
215
|
+
timer = setTimeout(() => {
|
|
216
|
+
if (startupSettled) return;
|
|
217
|
+
startupSettled = true;
|
|
218
|
+
closeStartupPipes();
|
|
219
|
+
resolve();
|
|
220
|
+
}, LAUNCHER_STARTUP_GRACE_MS);
|
|
221
|
+
return;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
const claimTimeoutMs = Math.max(100, Math.min(options.claimTimeoutMs ?? CODEX_WORK_CLAIM_TIMEOUT_MS, 60_000));
|
|
225
|
+
const claimSettlementGraceMs = Math.max(0, Math.min(options.claimSettlementGraceMs ?? CODEX_WORK_CLAIM_SETTLEMENT_GRACE_MS, 5_000));
|
|
226
|
+
const claimPollIntervalMs = Math.max(10, Math.min(options.claimPollIntervalMs ?? CODEX_WORK_CLAIM_POLL_INTERVAL_MS, 1_000));
|
|
227
|
+
const claimDeadline = Date.now() + claimTimeoutMs;
|
|
228
|
+
const claimSettlementDeadline = claimDeadline + claimSettlementGraceMs;
|
|
229
|
+
const pollClaim = () => {
|
|
230
|
+
if (startupSettled) return;
|
|
231
|
+
let observation: ReturnType<typeof expectedClaimMatches>;
|
|
232
|
+
try {
|
|
233
|
+
observation = expectedClaimMatches();
|
|
234
|
+
} catch (error) {
|
|
235
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
236
|
+
fail(new Error(`LAUNCHER_CLAIM_OBSERVATION_FAILED: ${message}`), `claim_observation_failed:${message}`, true);
|
|
237
|
+
return;
|
|
238
|
+
}
|
|
239
|
+
if (observation.mismatch) {
|
|
240
|
+
fail(
|
|
241
|
+
new Error(`LAUNCHER_CLAIM_MISMATCH: Work ${workId} expected type=${claimExpectation.controllerType} controller=${claimExpectation.controllerId} principal=${claimExpectation.principalId} session=${claimExpectation.sessionId}; ${observation.mismatch}`),
|
|
242
|
+
'claim_mismatch',
|
|
243
|
+
true,
|
|
244
|
+
);
|
|
245
|
+
return;
|
|
246
|
+
}
|
|
247
|
+
if (observation.matches) {
|
|
248
|
+
timer = setTimeout(() => {
|
|
249
|
+
if (startupSettled) return;
|
|
250
|
+
try {
|
|
251
|
+
const confirmation = expectedClaimMatches();
|
|
252
|
+
if (!confirmation.matches || confirmation.mismatch) {
|
|
253
|
+
fail(new Error(`LAUNCHER_CLAIM_LOST: Codex claim for exact Work ${workId} was not live after startup grace`), 'claim_lost', true);
|
|
254
|
+
return;
|
|
255
|
+
}
|
|
256
|
+
} catch (error) {
|
|
257
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
258
|
+
fail(new Error(`LAUNCHER_CLAIM_OBSERVATION_FAILED: ${message}`), `claim_observation_failed:${message}`, true);
|
|
259
|
+
return;
|
|
260
|
+
}
|
|
261
|
+
startupSettled = true;
|
|
262
|
+
timer = undefined;
|
|
263
|
+
closeStartupPipes();
|
|
264
|
+
resolve();
|
|
265
|
+
}, LAUNCHER_STARTUP_GRACE_MS);
|
|
266
|
+
return;
|
|
267
|
+
}
|
|
268
|
+
if (Date.now() >= claimSettlementDeadline) {
|
|
269
|
+
fail(
|
|
270
|
+
new Error(`LAUNCHER_CLAIM_TIMEOUT: Codex pid=${String(child.pid ?? 'unknown')} did not claim exact Work ${workId} through Forge MCP within ${claimTimeoutMs}ms plus ${claimSettlementGraceMs}ms settlement grace`),
|
|
271
|
+
`claim_timeout:${claimTimeoutMs}ms+${claimSettlementGraceMs}ms_settlement`,
|
|
272
|
+
true,
|
|
273
|
+
);
|
|
274
|
+
return;
|
|
275
|
+
}
|
|
276
|
+
timer = setTimeout(pollClaim, claimPollIntervalMs);
|
|
277
|
+
};
|
|
278
|
+
pollClaim();
|
|
279
|
+
});
|
|
280
|
+
}
|
|
281
|
+
|
|
67
282
|
function assertChatgptConversationUrl(value: string | undefined): string | undefined {
|
|
68
283
|
const raw = value?.trim();
|
|
69
284
|
if (!raw) return undefined;
|
|
@@ -134,13 +349,14 @@ export function buildSuperControllerInvocation(
|
|
|
134
349
|
* provider process selection and prompt construction; the execution Kernel
|
|
135
350
|
* receives neither provider-specific arguments nor model output.
|
|
136
351
|
*/
|
|
137
|
-
export function launchSuperController(
|
|
352
|
+
export async function launchSuperController(
|
|
138
353
|
stores: {
|
|
139
354
|
work: WorkContractStoreOptions & { controllerHome: string; repoId: string };
|
|
140
355
|
handoff: HandoffInboxStoreOptions;
|
|
141
356
|
},
|
|
142
357
|
request: ThinLauncherRequest,
|
|
143
|
-
|
|
358
|
+
dependencies: ThinLauncherDependencies = {},
|
|
359
|
+
): Promise<ThinLauncherResult> {
|
|
144
360
|
const executable = resolveLauncherExecutable(request);
|
|
145
361
|
const work = getWorkContract(stores.work, request.workId);
|
|
146
362
|
if (!work) throw new Error(`WORK_NOT_FOUND: ${request.workId}`);
|
|
@@ -158,7 +374,7 @@ export function launchSuperController(
|
|
|
158
374
|
`Continue Forge Work ${work.workId} in repo ${work.repoId}.`,
|
|
159
375
|
handoff ? `Handoff: ${handoff.summary}\nNext: ${handoff.recommendedContinuationPrompt ?? handoff.recommendedPrompt}` : '',
|
|
160
376
|
request.continuationPrompt?.trim() ? `Continuation: ${request.continuationPrompt.trim()}` : '',
|
|
161
|
-
`First call rh_work
|
|
377
|
+
`No Controller ownership was preclaimed for this continued conversation. First call rh_work operation=controller_claim with repo_id=${work.repoId}, work_id=${work.workId}, and controller_type=chatgpt through your authenticated MCP session; do not invent controller_id/session_id. Only after that exact Work claim succeeds, call rh_work operation=continue with the same repo_id/work_id. Treat Forge Work/Plan/evidence as source of truth; do not invent new scope from chat history. If the claim does not succeed, do not mutate. Continue the next safe action, finalize only when acceptance passes, and create a HandoffItem when judgement is required.`,
|
|
162
378
|
].filter(Boolean).join('\n')
|
|
163
379
|
: [
|
|
164
380
|
`Work: ${work.workId}`,
|
|
@@ -167,21 +383,38 @@ export function launchSuperController(
|
|
|
167
383
|
`Current status: ${work.status}`,
|
|
168
384
|
handoff ? `Handoff: ${handoff.summary}\nNext: ${handoff.recommendedContinuationPrompt ?? handoff.recommendedPrompt}` : '',
|
|
169
385
|
request.continuationPrompt?.trim() ? `Continuation: ${request.continuationPrompt.trim()}` : '',
|
|
170
|
-
`No Controller ownership was preclaimed for you. First call rh_work
|
|
386
|
+
`No Controller ownership was preclaimed for you. First call rh_work operation=controller_claim with repo_id=${work.repoId}, work_id=${work.workId}, and controller_type=${request.controllerType} through your authenticated MCP session; do not invent controller_id/session_id. Only after that exact Work claim succeeds, call rh_work operation=continue with the same repo_id/work_id and continue the returned next safe action. If the claim does not succeed, do not mutate the repository: create no patch, command, commit, or test run until ownership is established. Then use the repository MCP facade, record verification evidence, finalize only when acceptance passes, and create a HandoffItem when judgement is required.`,
|
|
171
387
|
].filter(Boolean).join('\n');
|
|
172
388
|
try {
|
|
173
389
|
const mcpBootstrap = request.controllerType === 'codex'
|
|
174
|
-
? resolveProviderMcpBootstrap(stores.work.controllerHome, 'codex', reservation.reservationId)
|
|
390
|
+
? (dependencies.resolveProviderMcpBootstrap ?? resolveProviderMcpBootstrap)(stores.work.controllerHome, 'codex', reservation.reservationId)
|
|
175
391
|
: undefined;
|
|
176
392
|
const invocation = buildSuperControllerInvocation({ ...request, controllerHome: stores.work.controllerHome, repoId: work.repoId }, executable, prompt, mcpBootstrap);
|
|
177
393
|
const child = spawn(invocation.executable, invocation.args, {
|
|
178
394
|
cwd: request.cwd,
|
|
179
395
|
detached: true,
|
|
180
|
-
stdio: 'ignore',
|
|
181
|
-
env: mcpBootstrap?.env ?? process.env,
|
|
396
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
397
|
+
env: launcherProcessEnvironment(mcpBootstrap?.env ?? process.env),
|
|
182
398
|
});
|
|
183
|
-
child.unref();
|
|
184
399
|
attachExternalControllerLaunchPid(stores.work, work.workId, reservation.reservationId, child.pid);
|
|
400
|
+
await awaitExternalControllerStartup(
|
|
401
|
+
child,
|
|
402
|
+
stores,
|
|
403
|
+
work.workId,
|
|
404
|
+
reservation.reservationId,
|
|
405
|
+
mcpBootstrap ? {
|
|
406
|
+
controllerType: 'codex',
|
|
407
|
+
controllerId: mcpBootstrap.principalId,
|
|
408
|
+
principalId: mcpBootstrap.principalId,
|
|
409
|
+
sessionId: mcpBootstrap.sessionId,
|
|
410
|
+
} : undefined,
|
|
411
|
+
{
|
|
412
|
+
claimTimeoutMs: dependencies.claimTimeoutMs,
|
|
413
|
+
claimSettlementGraceMs: dependencies.claimSettlementGraceMs,
|
|
414
|
+
claimPollIntervalMs: dependencies.claimPollIntervalMs,
|
|
415
|
+
},
|
|
416
|
+
);
|
|
417
|
+
child.unref();
|
|
185
418
|
return { controllerType: request.controllerType, reservationId: reservation.reservationId, pid: child.pid, prompt, executable };
|
|
186
419
|
} catch (error) {
|
|
187
420
|
releaseExternalControllerLaunchReservation(stores.work, work.workId, reservation.reservationId, 'spawn_failed');
|