@moretea-labs/forge 1.8.0 → 1.8.2
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 +73 -7
- package/CHANGELOG.md +34 -0
- package/CLAUDE.md +17 -2
- package/CONTRIBUTING.md +3 -2
- package/README.en.md +24 -3
- package/README.md +10 -6
- package/README.zh-CN.md +5 -3
- package/THIRD_PARTY_NOTICES.md +1 -2
- package/adapters/chatgpt/browser-delivery-host.ts +7 -1
- package/adapters/chatgpt/browser-delivery-runtime.ts +531 -56
- package/adapters/chatgpt/controller-binding-store.ts +101 -22
- package/adapters/chatgpt/controller-round-host.ts +15 -25
- package/adapters/chatgpt/controller-round-settlement-store.ts +58 -4
- package/adapters/chatgpt/provider-delivery.ts +229 -2
- package/adapters/chatgpt/work-conversation-binding-store.ts +99 -54
- package/adapters/computer/chatgpt-extension-target.ts +708 -0
- package/adapters/computer/chrome-extension/background.js +541 -0
- package/adapters/computer/chrome-extension/content.js +402 -0
- package/adapters/computer/chrome-extension/core.js +24 -0
- package/adapters/computer/chrome-extension/manifest.json +32 -0
- package/adapters/computer/desktop-operator-discovery.ts +11 -31
- package/adapters/computer/desktop-operator-provider.ts +18 -6
- package/adapters/computer/interaction-target-authority.ts +178 -24
- package/adapters/mcp/access-mode.ts +18 -39
- package/adapters/mcp/auth.ts +2 -7
- package/adapters/mcp/instructions.ts +6 -5
- package/adapters/mcp/multi-repository.ts +10 -47
- package/adapters/mcp/oauth.ts +73 -0
- package/adapters/mcp/paths.ts +4 -1
- package/adapters/mcp/runtime-gateway/bounded-result-runtime.ts +62 -0
- package/adapters/mcp/runtime-gateway/cognition-settlement.ts +201 -0
- package/adapters/mcp/runtime-gateway/context-adapter.ts +490 -113
- package/adapters/mcp/runtime-gateway/context-pack-sidecar.ts +83 -0
- package/adapters/mcp/runtime-gateway/controller-authority-adapter.ts +20 -5
- package/adapters/mcp/runtime-gateway/core-capability-adapter.ts +258 -0
- package/adapters/mcp/runtime-gateway/engineering-preconditions.ts +10 -27
- package/adapters/mcp/runtime-gateway/engineering-tool-contract.ts +15 -0
- package/adapters/mcp/runtime-gateway/execution-tools.ts +14 -54
- package/adapters/mcp/runtime-gateway/gateway-execution-adapter.ts +2 -1
- package/adapters/mcp/runtime-gateway/plugin-adapter.ts +132 -47
- package/adapters/mcp/runtime-gateway/process-tools.ts +173 -23
- package/adapters/mcp/runtime-gateway/protected-computer-adapter.ts +16 -4
- package/adapters/mcp/runtime-gateway/recovery-adapter.ts +69 -52
- package/adapters/mcp/runtime-gateway/repository-compat-adapter.ts +4 -35
- package/adapters/mcp/runtime-gateway/result-adapter.ts +10 -4
- package/adapters/mcp/runtime-gateway/router.ts +19 -507
- package/adapters/mcp/runtime-gateway/routing-policy.ts +506 -0
- package/adapters/mcp/runtime-gateway/runtime-observation-adapter.ts +15 -66
- package/adapters/mcp/runtime-gateway/runtime-readiness-observation.ts +218 -0
- package/adapters/mcp/runtime-gateway/runtime-tool-definitions.ts +123 -178
- package/adapters/mcp/runtime-gateway/runtime-tools.ts +11 -5
- package/adapters/mcp/runtime-gateway/scheduler-adapter.ts +37 -1
- package/adapters/mcp/runtime-gateway/shared-adapter.ts +20 -0
- package/adapters/mcp/runtime-gateway/status-inbox-adapter.ts +416 -270
- package/adapters/mcp/runtime-gateway/typescript-navigation-sidecar.ts +140 -0
- package/adapters/mcp/runtime-gateway/work-adapter.ts +262 -3123
- package/adapters/mcp/runtime-gateway/work-controller-operations.ts +257 -0
- package/adapters/mcp/runtime-gateway/work-detail-projection.ts +60 -0
- package/adapters/mcp/runtime-gateway/work-input-wire-migration.ts +229 -0
- package/adapters/mcp/runtime-gateway/work-learning-operations.ts +145 -0
- package/adapters/mcp/runtime-gateway/work-list-projection.ts +38 -0
- package/adapters/mcp/runtime-gateway/work-plan-operations.ts +382 -0
- package/adapters/mcp/runtime-gateway/work-repair-adapter.ts +308 -0
- package/adapters/mcp/runtime-gateway/work-requirement-operations.ts +148 -0
- package/adapters/mcp/runtime-gateway/work-semantic-operations.ts +320 -0
- package/adapters/mcp/runtime-gateway/work-workflow-operations.ts +113 -0
- package/adapters/mcp/runtime-gateway/workflow-supervisor-adapter.ts +180 -0
- package/adapters/mcp/server.ts +91 -26
- package/adapters/mcp/setup.ts +5 -13
- package/adapters/mcp/tool-mapping/access-tools.ts +0 -6
- package/adapters/mcp/tool-mapping/legacy-tool-service.ts +703 -3092
- package/adapters/mcp/tool-mapping/post-finalize-work-attribution.ts +5 -10
- package/adapters/mcp/tool-mapping/repository-tools.ts +170 -213
- package/adapters/mcp/toolset-names.ts +11 -37
- package/adapters/mcp/toolset.ts +19 -92
- package/{src/cli → adapters}/mcp/transports/AGENTS.md +5 -5
- package/{src/cli → adapters}/mcp/transports/CLAUDE.md +5 -5
- package/adapters/mcp/transports/http-observation.ts +377 -0
- package/adapters/mcp/transports/http-post-lifecycle.ts +19 -0
- package/adapters/mcp/transports/http.ts +200 -683
- package/adapters/mcp/transports/oauth-http.ts +322 -0
- package/adapters/mcp/transports/session-registry.ts +6 -0
- package/adapters/mcp/tunnels/openai-secure-tunnel.ts +89 -5
- package/adapters/mcp/types.ts +0 -6
- package/assets/hooks/lib/session-state.sh +0 -38
- package/assets/hooks/post-bash.sh +1 -1
- package/assets/hooks/post-tool-observer.sh +0 -5
- package/assets/hooks/prompt-guard.sh +0 -55
- package/assets/partials/04-project-structure.partial.md +1 -1
- package/assets/partials/07-footer.partial.md +1 -1
- package/assets/partials-agents/02-operating-mode.partial.md +1 -1
- package/assets/partials-agents/08-deep-docs.partial.md +1 -1
- package/assets/plugin-registry.v1.json +6 -4
- package/assets/reference-configs/agentic-development-flow.md +26 -1
- package/assets/reference-configs/external-tooling.md +0 -76
- package/assets/reference-configs/global-working-rules.md +19 -0
- package/assets/reference-configs/release-deploy.md +1 -1
- package/assets/templates/helpers/architecture-queue.sh +1 -1
- package/assets/templates/helpers/check-agent-tooling.sh +1 -327
- package/assets/templates/helpers/check-task-workflow.sh +1 -1
- package/assets/templates/helpers/ensure-task-workflow.sh +0 -14
- package/assets/templates/helpers/migrate-project-template.sh +2 -2
- package/assets/workflow-contract.v1.json +0 -2
- package/docs/README.md +5 -2
- package/docs/architecture/CURRENT.md +205 -51
- package/docs/architecture/decisions/20260803-release-identity-binding-and-exit-policy.md +14 -5
- package/docs/architecture/decisions/20260823-immediate-controller-relay.md +6 -3
- package/docs/architecture/decisions/20260904-ios-device-migration-baseline.md +42 -0
- package/docs/architecture/decisions/20260907-assistant-learning-loop.md +2 -0
- package/docs/architecture/decisions/20260907-controller-round-transition-policy.md +19 -4
- package/docs/architecture/decisions/20260916-workflow-supervisor-authority.md +249 -0
- package/docs/architecture/decisions/20260917-cognitive-memory-foundation.md +82 -0
- package/docs/architecture/decisions/20260918-stable-candidate-release-lifecycle.md +234 -0
- package/docs/architecture/decisions/20260919-autonomous-work-liveness.md +62 -0
- package/docs/architecture/decisions/20260924-thin-semantic-working-context.md +74 -0
- package/docs/architecture/decisions/20261001-supervisor-turn-authority.md +342 -0
- package/docs/architecture/decisions/20261005-forge-v3-desktop-client-boundary.md +77 -0
- package/docs/architecture/decisions/20261009-exact-code-context-discovery.md +19 -0
- package/docs/architecture/decisions/20261009-generated-xcode-cache-retention.md +37 -0
- package/docs/architecture/decisions/20261011-autonomous-continuation-convergence.md +597 -0
- package/docs/architecture/decisions/20261017-edit-session-finalization-reconciliation.md +17 -0
- package/docs/architecture/decisions/20261019-retire-host-skills.md +16 -0
- package/docs/architecture/diagrams/agentic-dev-plugin-architecture.html +1 -1
- package/docs/architecture/domains/public-surface.md +3 -5
- package/docs/architecture/domains/verification.md +6 -5
- package/docs/architecture/domains/workflow-engine.md +6 -0
- package/docs/architecture/modules/controller-runtime/transport-lifecycle.md +3 -3
- package/docs/architecture/requests/2026-09-04-computer-plugin-workflow-taxonomy.md +4 -4
- package/docs/architecture/reviews/20261015-code-search-runtime-acceptance.md +75 -0
- package/docs/forge-plugin-management.md +16 -4
- package/docs/operations/controller-browser-plugin.md +23 -0
- package/docs/operations/controller-performance-and-502.md +17 -0
- package/docs/operations/controller-reliability-runbook.md +2 -2
- package/docs/operations/features.md +6 -7
- package/docs/operations/features.zh-CN.md +1 -1
- package/docs/operations/github-repository.md +4 -4
- package/docs/operations/github-semantic-release-projection.md +20 -0
- package/docs/operations/homebrew.md +2 -2
- package/docs/operations/mcp-tool-exposure.md +13 -52
- package/docs/operations/releasing.md +2 -0
- package/docs/operations/runtime-performance-diagnostics.md +8 -0
- package/docs/operations/standalone-disaster-recovery.md +15 -7
- package/docs/tutorials/01-install-and-start.zh-CN.md +1 -1
- package/docs/tutorials/03-first-repository-task.md +2 -0
- package/docs/wiki/Computer-and-Plugins.md +78 -0
- package/docs/wiki/Computer-and-Plugins.zh-CN.md +88 -0
- package/docs/wiki/Home.md +16 -2
- package/docs/wiki/Implementation.md +25 -13
- package/docs/wiki/Installation.md +28 -32
- package/docs/wiki/Integrations.md +4 -0
- package/docs/wiki/Quick-Start.md +35 -22
- package/docs/wiki/Releases-and-Upgrades.md +15 -25
- package/docs/wiki/_Sidebar.md +5 -1
- package/package.json +25 -25
- package/packages/kernel/cognition/api/index.ts +6 -0
- package/packages/kernel/cognition/application/activation-service.ts +451 -0
- package/packages/kernel/cognition/application/consolidation-service.ts +185 -0
- package/packages/kernel/cognition/application/legacy-experience-adapter.ts +38 -0
- package/packages/kernel/cognition/application/memory-service.ts +64 -0
- package/packages/kernel/cognition/domain/learning.ts +106 -0
- package/packages/kernel/cognition/domain/memory.ts +254 -0
- package/packages/kernel/controller/api/index.ts +1 -0
- package/packages/kernel/controller/application/continuation-service.ts +281 -0
- package/packages/kernel/controller/application/controller-round-service.ts +12 -0
- package/packages/kernel/controller/domain/controller-round-transition-policy.ts +242 -21
- package/packages/kernel/controller/domain/controller-round.ts +4 -1
- package/packages/kernel/controller/domain/execution-quality.ts +3 -1
- package/packages/kernel/controller/infrastructure/controller-round-store.ts +689 -103
- package/packages/kernel/controller/infrastructure/controller-session-store.ts +348 -97
- package/packages/kernel/controller/ports/controller-host.ts +2 -0
- package/packages/kernel/identity/api/index.ts +10 -0
- package/packages/kernel/identity/domain/activity-projection.ts +43 -0
- package/packages/kernel/identity/domain/capability-broker.ts +60 -0
- package/packages/kernel/identity/domain/grant.ts +72 -0
- package/packages/kernel/identity/domain/owned-resource.ts +116 -0
- package/packages/kernel/identity/domain/user-request.ts +93 -0
- package/packages/kernel/identity/infrastructure/activity-projection-store.ts +87 -0
- package/packages/kernel/identity/infrastructure/capability-broker.ts +81 -0
- package/packages/kernel/identity/infrastructure/grant-store.ts +284 -0
- package/packages/kernel/identity/infrastructure/owned-resource-store.ts +259 -0
- package/packages/kernel/identity/infrastructure/user-request-store.ts +182 -0
- package/packages/kernel/scheduler/api/index.ts +0 -2
- package/packages/kernel/scheduler/application/eligibility.ts +4 -1
- package/packages/kernel/scheduler/application/schedule-service.ts +3 -0
- package/packages/kernel/scheduler/application/settlement.ts +0 -15
- package/packages/kernel/scheduler/domain/schedule.ts +87 -0
- package/packages/kernel/scheduler/infrastructure/schedule-store.ts +166 -143
- package/packages/kernel/work/api/index.ts +3 -2
- package/packages/kernel/work/application/work-service.ts +18 -42
- package/packages/kernel/work/domain/current-task-lineage.ts +104 -0
- package/packages/kernel/work/domain/engineering-design.ts +10 -5
- package/packages/kernel/work/domain/engineering-profile.ts +8 -12
- package/packages/kernel/work/domain/evaluation-promotion-receipt.ts +186 -0
- package/packages/kernel/work/domain/execution-concurrency.ts +19 -26
- package/packages/kernel/work/domain/execution-snapshot.ts +0 -31
- package/packages/kernel/work/domain/implementation-review.ts +14 -331
- package/packages/kernel/work/domain/objective-graph.ts +119 -0
- package/packages/kernel/work/domain/project-engineering-contract.ts +23 -1
- package/packages/kernel/work/domain/repository-completion-receipt.ts +1 -1
- package/packages/kernel/work/domain/state-machine.ts +34 -65
- package/packages/kernel/work/domain/types.ts +57 -51
- package/packages/kernel/work/infrastructure/work-contract-store.ts +847 -729
- package/packages/kernel/work/ports/work-contract-store.ts +5 -2
- package/packages/plugin-runtime/browser/provider-registry.ts +12 -36
- package/packages/plugin-runtime/browser/session-authority.ts +2 -1
- package/packages/plugin-runtime/computer/chatgpt-identity.ts +24 -0
- package/packages/plugin-runtime/computer/conversation-target.ts +153 -0
- package/packages/plugin-runtime/computer/index.ts +2 -0
- package/packages/plugin-runtime/computer/target-authority.ts +26 -1
- package/packages/plugin-runtime/external/unix-jsonl-transport.ts +142 -18
- package/packages/protocols/computer/contract.ts +27 -1
- package/scripts/activate-source-baseline.ts +7 -9
- package/scripts/assemble-template.ts +11 -72
- package/scripts/canary-controller-semantic-wait.ts +12 -24
- package/scripts/check-mcp-compatibility.ts +94 -201
- package/scripts/check-package-identity.mjs +0 -5
- package/scripts/check-runtime-architecture.mjs +921 -239
- package/scripts/forge-local-recovery-helper.mjs +93 -15
- package/scripts/init-project.sh +0 -46
- package/scripts/install-ios-hid-toolchain.sh +60 -0
- package/scripts/install-standalone-recovery.ts +1 -1
- package/scripts/lib/project-init-lib.sh +6 -3
- package/scripts/migrate-windows-wsl-controller-home.ts +2 -0
- package/scripts/open-source-audit-allowlist.txt +1 -3
- package/scripts/run-bounded-command.mjs +5 -0
- package/scripts/run-governed-gate.ts +2 -1
- package/scripts/run-mobile-monitor-bridge.ts +0 -1
- package/scripts/smoke-control-plane-failure-domain.ts +94 -0
- package/scripts/smoke-ios-physical-device.ts +38 -10
- package/scripts/smoke-mcp-http-runtime.ts +12 -8
- package/scripts/smoke-mcp-tool-surface.ts +27 -41
- package/scripts/smoke-runtime-recovery.ts +12 -43
- package/scripts/smoke-schedule-engine.ts +23 -15
- package/scripts/smoke-unattended-transport-recovery.ts +223 -0
- package/scripts/smoke-user-request-continuation-restart.ts +232 -0
- package/scripts/smoke-workflow-supervisor-chrome-adapter.ts +95 -0
- package/scripts/smoke-workflow-supervisor-process-restart.ts +276 -0
- package/scripts/smoke-workflow-supervisor-restart-recovery.ts +150 -0
- package/scripts/smoke-workflow-supervisor.ts +103 -0
- package/scripts/sync-generated-authority.mjs +0 -1
- package/scripts/verify-forge-runtime.sh +2 -1
- package/src/cli/agent-jobs/executor-health.ts +12 -35
- package/src/cli/agent-jobs/integration.ts +20 -51
- package/src/cli/agent-jobs/job-manager.ts +7 -3
- package/src/cli/chatgpt-browser/file-policy.ts +2 -2
- package/src/cli/commands/brain-assistant.ts +27 -13
- package/src/cli/commands/brain.ts +13 -15
- package/src/cli/commands/chatgpt.ts +1 -163
- package/src/cli/commands/doctor.ts +1 -143
- package/src/cli/commands/global-runtime.ts +3 -196
- package/src/cli/commands/init-hook.ts +6 -23
- package/src/cli/commands/init.ts +3 -252
- package/src/cli/commands/mcp.ts +0 -5
- package/src/cli/commands/prompt-guard-decision.ts +0 -2
- package/src/cli/commands/recovery.ts +137 -135
- package/src/cli/commands/repository.ts +17 -1
- package/src/cli/commands/runtime.ts +3 -3
- package/src/cli/commands/setup-execution.ts +41 -0
- package/src/cli/commands/setup-profile.ts +8 -0
- package/src/cli/controller/check-runner.ts +13 -2
- package/src/cli/controller/completion-backlog.ts +3 -3
- package/src/cli/controller/completion-orchestrator.ts +5 -44
- package/src/cli/controller/completion-target.ts +3 -72
- package/src/cli/controller/composite-operations.ts +1 -1
- package/src/cli/controller/context/instruction-context.ts +1 -1
- package/src/cli/controller/context/known-paths.ts +2 -2
- package/src/cli/controller/context/query-planning.ts +11 -4
- package/src/cli/controller/context/rule-resolution.ts +2 -2
- package/src/cli/controller/context/source-materializer.ts +83 -102
- package/src/cli/controller/context/structural-provider.ts +84 -0
- package/src/cli/controller/context/structural.ts +6 -6
- package/src/cli/controller/context/types.ts +8 -9
- package/src/cli/controller/context-pack.ts +107 -84
- package/src/cli/controller/execution-completion.ts +4 -7
- package/src/cli/controller/execution-policy.ts +36 -153
- package/src/cli/controller/governance.ts +2 -3
- package/src/cli/controller/issue-store.ts +4 -99
- package/src/cli/controller/launch-agents.ts +59 -18
- package/src/cli/controller/operational-plan.ts +25 -52
- package/src/cli/controller/runtime-config.ts +5 -1
- package/src/cli/controller/stuck-state-migration.ts +2 -3
- package/src/cli/controller/systemd-user.ts +42 -10
- package/src/cli/editing/edit-session.ts +18 -12
- package/src/cli/github/github.ts +4 -4
- package/src/cli/github/semantic-projection.ts +174 -0
- package/src/cli/hook/prompt-intents.ts +0 -9
- package/src/cli/index.ts +1 -43
- package/src/cli/local-bridge/connector-freshness.ts +1 -12
- package/src/cli/local-bridge/console-automations.ts +19 -14
- package/src/cli/local-bridge/console-view-models.ts +4 -13
- package/src/cli/local-bridge/facade-api.ts +64 -193
- package/src/cli/local-bridge/server.ts +24 -147
- package/src/cli/local-bridge/types.ts +0 -1
- package/src/cli/mcp/oauth-client-retirement.ts +74 -0
- package/src/cli/repositories/command-classifier.ts +0 -9
- package/src/cli/repositories/command-executor.ts +29 -23
- package/src/cli/repositories/command-scope.ts +37 -18
- package/src/cli/repositories/controller-home.ts +48 -0
- package/src/cli/repositories/ephemeral-workspace.ts +20 -30
- package/src/cli/repositories/git-command-executor.ts +2 -2
- package/src/cli/repositories/locks.ts +20 -0
- package/src/cli/repositories/registry.ts +79 -12
- package/src/cli/repositories/safe-patch.ts +2 -12
- package/src/cli/repositories/structured-git.ts +101 -5
- package/src/cli/repository/inspector.ts +185 -343
- package/src/cli/repository/session-cache.ts +92 -6
- package/src/effects/process-runner.ts +17 -1
- package/src/runtime/context/assistant-context.ts +20 -7
- package/src/runtime/context/assistant-work-context.ts +89 -27
- package/src/runtime/context/automatic-learning.ts +565 -0
- package/src/runtime/context/cognitive-attention.ts +173 -0
- package/src/runtime/context/cognitive-skill-canary.ts +158 -0
- package/src/runtime/context/context-closure.ts +46 -9
- package/src/runtime/context/context-pack-process.ts +103 -0
- package/src/runtime/context/context-plane.ts +1 -9
- package/src/runtime/context/direct-controller-learning.ts +298 -0
- package/src/runtime/context/generic-lsp-provider.ts +1 -1
- package/src/runtime/context/semantic-navigation-contract.ts +16 -0
- package/src/runtime/context/semantic-navigation.ts +7 -35
- package/src/runtime/context/typescript-navigation-process.ts +145 -0
- package/src/runtime/context/typescript-navigation.ts +89 -3
- package/src/runtime/control-plane/cleanup-artifact-retention.ts +215 -12
- package/src/runtime/control-plane/concurrency/work-execution-concurrency.ts +9 -47
- package/src/runtime/control-plane/execution/controller-authority-recovery.ts +34 -4
- package/src/runtime/control-plane/execution/edit-validation-coordinator.ts +29 -20
- package/src/runtime/control-plane/execution/execution-identity.ts +23 -3
- package/src/runtime/control-plane/execution/repository-work-attribution.ts +7 -30
- package/src/runtime/control-plane/execution/retained-work-resume.ts +206 -199
- package/src/runtime/control-plane/execution/session-store.ts +31 -1
- package/src/runtime/control-plane/execution/validation.ts +6 -8
- package/src/runtime/control-plane/execution/work-authority-reconciler.ts +13 -42
- package/src/runtime/control-plane/execution/work-check-evidence.ts +137 -0
- package/src/runtime/control-plane/execution/work-completion-authority.ts +30 -85
- package/src/runtime/control-plane/execution/work-delivery-service.ts +616 -0
- package/src/runtime/control-plane/execution/work-evidence-policy.ts +12 -50
- package/src/runtime/control-plane/execution/work-execution-support.ts +50 -149
- package/src/runtime/control-plane/execution/work-handle-authority.ts +197 -110
- package/src/runtime/control-plane/execution/work-handle-store.ts +72 -44
- package/src/runtime/control-plane/execution/work-head-settlement.ts +53 -20
- package/src/runtime/control-plane/execution/work-lifecycle-audit.ts +52 -29
- package/src/runtime/control-plane/execution/work-operation-service.ts +60 -34
- package/src/runtime/control-plane/execution/work-preparation-service.ts +231 -267
- package/src/runtime/control-plane/execution/work-process-evidence.ts +2 -2
- package/src/runtime/control-plane/execution/work-remote-delivery.ts +2 -3
- package/src/runtime/control-plane/execution/work-revision-diff.ts +39 -0
- package/src/runtime/control-plane/execution/work-terminal-cleanup.ts +201 -199
- package/src/runtime/control-plane/execution/work-validation-reconciler.ts +33 -85
- package/src/runtime/control-plane/execution/work-verification-service.ts +406 -50
- package/src/runtime/control-plane/execution/work-verification-snapshot.ts +6 -2
- package/src/runtime/control-plane/facade/capability-registry.ts +364 -37
- package/src/runtime/control-plane/facade/check-normalization.ts +3 -9
- package/src/runtime/control-plane/facade/codex-delegation.ts +10 -11
- package/src/runtime/control-plane/facade/controller-connection.ts +135 -0
- package/src/runtime/control-plane/facade/goal-workloop-access.ts +1 -20
- package/src/runtime/control-plane/facade/goal-workloop.ts +281 -1753
- package/src/runtime/control-plane/facade/handoff-inbox-application.ts +12 -25
- package/src/runtime/control-plane/facade/handoff-inbox-store.ts +256 -52
- package/src/runtime/control-plane/facade/index.ts +0 -1
- package/src/runtime/control-plane/facade/operation-digest.ts +12 -15
- package/src/runtime/control-plane/facade/plan-contract-store.ts +451 -991
- package/src/runtime/control-plane/facade/policy-gate.ts +0 -23
- package/src/runtime/control-plane/facade/repository-work-admission.ts +12 -22
- package/src/runtime/control-plane/facade/requirement-authority.ts +102 -199
- package/src/runtime/control-plane/facade/requirement-board.ts +3 -3
- package/src/runtime/control-plane/facade/rh-work-operation-contract.ts +51 -14
- package/src/runtime/control-plane/facade/self-healing-loop.ts +18 -53
- package/src/runtime/control-plane/facade/suggested-actions.ts +15 -18
- package/src/runtime/control-plane/facade/types.ts +49 -108
- package/src/runtime/control-plane/facade/work-continuation.ts +9 -9
- package/src/runtime/control-plane/generated-cache-retention.ts +206 -59
- package/src/runtime/control-plane/global-scheduler/autonomous-continuation.ts +248 -0
- package/src/runtime/control-plane/global-scheduler/durable-admission.ts +1 -1
- package/src/runtime/control-plane/global-scheduler/maintenance.ts +256 -117
- package/src/runtime/control-plane/global-scheduler/reconciliation.ts +3 -12
- package/src/runtime/control-plane/global-scheduler/scheduler.ts +66 -40
- package/src/runtime/control-plane/global-scheduler/wake-signal.ts +42 -2
- package/src/runtime/control-plane/governance/access-policy.ts +19 -2
- package/src/runtime/control-plane/governance/authorization.ts +20 -3
- package/src/runtime/control-plane/governance/external-effects.ts +1 -1
- package/src/runtime/control-plane/launcher/chatgpt-round-continuation.ts +63 -300
- package/src/runtime/control-plane/launcher/chatgpt-work-continuation.ts +29 -300
- package/src/runtime/control-plane/launcher/local-conversation-controller.ts +238 -0
- package/src/runtime/control-plane/launcher/provider-mcp-bootstrap.ts +5 -2
- package/src/runtime/control-plane/launcher/thin-launcher.ts +96 -240
- package/src/runtime/control-plane/persistence/cognition-store.ts +820 -0
- package/src/runtime/control-plane/persistence/experience-store.ts +162 -29
- package/src/runtime/control-plane/persistence/requirement-store.ts +216 -74
- package/src/runtime/control-plane/persistence/sqlite-store.ts +113 -6
- package/src/runtime/control-plane/release-retention.ts +135 -47
- package/src/runtime/control-plane/repository-namespace-retention.ts +2 -2
- package/src/runtime/control-plane/runtime-cleanup.ts +295 -107
- package/src/runtime/control-plane/workspace/project-onboarding.ts +80 -0
- package/src/runtime/control-plane/workspace/semantic-sync-service.ts +19 -5
- package/src/runtime/control-plane/workspace/workspace-store.ts +169 -0
- package/src/runtime/diagnostics/incident-repair.ts +313 -146
- package/src/runtime/diagnostics/mcp-timing.ts +114 -0
- package/src/runtime/evidence/artifact-store.ts +158 -40
- package/src/runtime/evidence/evidence-store.ts +112 -8
- package/src/runtime/evidence/output-handle-index.ts +225 -0
- package/src/runtime/evidence/result-store.ts +158 -44
- package/src/runtime/evidence/sensitive-output.ts +22 -2
- package/src/runtime/execution/jobs/child-reference.ts +11 -0
- package/src/runtime/execution/jobs/receipt-recovery.ts +1 -11
- package/src/runtime/execution/jobs/store.ts +3 -4
- package/src/runtime/execution/managed-workspace.ts +57 -0
- package/src/runtime/execution/process-runtime/check-facade.ts +1 -1
- package/src/runtime/execution/process-runtime/check-result-retention.ts +2 -2
- package/src/runtime/execution/process-runtime/check-result.ts +105 -1
- package/src/runtime/execution/process-runtime/check-runner-sidecar.ts +18 -8
- package/src/runtime/execution/process-runtime/command-facade.ts +82 -30
- package/src/runtime/execution/process-runtime/gc.ts +15 -2
- package/src/runtime/execution/process-runtime/handle-index.ts +176 -0
- package/src/runtime/execution/process-runtime/host-command-lane.ts +139 -0
- package/src/runtime/execution/process-runtime/index.ts +3 -0
- package/src/runtime/execution/process-runtime/lightweight-managed.ts +251 -72
- package/src/runtime/execution/process-runtime/persisted-check.ts +3 -3
- package/src/runtime/execution/process-runtime/process-runner-entry.ts +47 -5
- package/src/runtime/execution/process-runtime/process-scope.ts +160 -0
- package/src/runtime/execution/process-runtime/resource-claims.ts +65 -61
- package/src/runtime/execution/process-runtime/runtime.ts +55 -18
- package/src/runtime/execution/process-runtime/store.ts +30 -2
- package/src/runtime/execution/process-runtime/types.ts +6 -1
- package/src/runtime/execution/thin-harness/execution-router.ts +16 -16
- package/src/runtime/execution/thin-harness/fast-executor.ts +2 -2
- package/src/runtime/execution/thin-harness/search-worker.ts +2 -2
- package/src/runtime/execution/workers/executor.ts +3 -8
- package/src/runtime/maintenance/cleanup.ts +41 -5
- package/src/runtime/platform/service-inventory.ts +130 -0
- package/src/runtime/platform/service-manager.ts +8 -0
- package/src/runtime/plugins/action-application.ts +97 -29
- package/src/runtime/plugins/app-store-connect-adapter.ts +290 -18
- package/src/runtime/plugins/browser-adapter.ts +1124 -333
- package/src/runtime/plugins/browser-automation-service.ts +23 -3
- package/src/runtime/plugins/browser-macos-bridge.ts +431 -137
- package/src/runtime/plugins/browser-manifest-surface.ts +47 -12
- package/src/runtime/plugins/browser-native-session-service.ts +63 -13
- package/src/runtime/plugins/browser-registration.ts +18 -0
- package/src/runtime/plugins/browser-runtime.ts +40 -36
- package/src/runtime/plugins/browser-session-authority.ts +2 -2
- package/src/runtime/plugins/browser-session-store.ts +46 -76
- package/src/runtime/plugins/capability-authorization-grants.ts +258 -62
- package/src/runtime/plugins/computer-chatgpt-browser-adapter-installer.ts +228 -0
- package/src/runtime/plugins/computer-registration.ts +298 -20
- package/src/runtime/plugins/desktop-operator-external-policy.ts +36 -4
- package/src/runtime/plugins/desktop-operator-registration.ts +12 -4
- package/src/runtime/plugins/external-adapter.ts +42 -6
- package/src/runtime/plugins/external-registration.ts +21 -1
- package/src/runtime/plugins/github-adapter.ts +30 -3
- package/src/runtime/plugins/gmail-adapter.ts +189 -3
- package/src/runtime/plugins/google-calendar-adapter.ts +2 -2
- package/src/runtime/plugins/google-shared.ts +24 -12
- package/src/runtime/plugins/google-tasks-adapter.ts +2 -2
- package/src/runtime/plugins/ios/remote-xpc-hid.ts +70 -30
- package/src/runtime/plugins/ios-adapter.ts +46 -41
- package/src/runtime/plugins/ios-agent-device.ts +54 -4
- package/src/runtime/plugins/ios-device-ownership.ts +103 -0
- package/src/runtime/plugins/ios-physical-device.ts +497 -79
- package/src/runtime/plugins/lightweight-action.ts +208 -2
- package/src/runtime/plugins/local-system-adapter.ts +12 -100
- package/src/runtime/plugins/managed-process-adapter.ts +12 -5
- package/src/runtime/plugins/plugin-action-sidecar.ts +17 -13
- package/src/runtime/plugins/plugin-management-adapter.ts +1 -1
- package/src/runtime/plugins/store.ts +682 -435
- package/src/runtime/plugins/types.ts +24 -0
- package/src/runtime/plugins/xiaohongshu-publish.ts +16 -0
- package/src/runtime/projections/git-status-sampler.ts +2 -19
- package/src/runtime/projections/invalidation.ts +7 -3
- package/src/runtime/projections/materialized-view.ts +80 -36
- package/src/runtime/recovery/actions.ts +4 -4
- package/src/runtime/recovery/capability-action-application.ts +46 -45
- package/src/runtime/recovery/lifecycle-inventory.ts +30 -40
- package/src/runtime/recovery/maintenance-executor.ts +374 -123
- package/src/runtime/recovery/probe.ts +2 -2
- package/src/runtime/recovery/store.ts +29 -11
- package/src/runtime/release/release-coordinator.ts +312 -0
- package/src/runtime/release/release-session.ts +716 -0
- package/src/runtime/release/release-state-migration.ts +25 -0
- package/src/runtime/resources/leases/store.ts +56 -25
- package/src/runtime/root/computer-composition.ts +191 -6
- package/src/runtime/root/controller-progression-composition.ts +254 -0
- package/src/runtime/root/controller-round-composition.ts +20 -1
- package/src/runtime/root/deployment-topology.ts +106 -0
- package/src/runtime/root/entry.ts +4 -3
- package/src/runtime/root/known-good-recovery.ts +184 -0
- package/src/runtime/root/local-bridge.ts +0 -1
- package/src/runtime/root/mcp-transport.ts +111 -18
- package/src/runtime/root/ownership.ts +261 -9
- package/src/runtime/root/package-connector-service.ts +227 -29
- package/src/runtime/root/package-runtime-release.ts +117 -30
- package/src/runtime/root/package-runtime-service.ts +24 -24
- package/src/runtime/root/release-execution-canary.ts +57 -12
- package/src/runtime/root/release-loader.ts +90 -8
- package/src/runtime/root/release-manifest.ts +80 -40
- package/src/runtime/root/release-materialize.ts +372 -106
- package/src/runtime/root/release-store.ts +395 -36
- package/src/runtime/root/runtime-lane.ts +191 -0
- package/src/runtime/root/runtime.ts +160 -29
- package/src/runtime/root/scheduled-controller-composition.ts +29 -3
- package/src/runtime/root/service-runner.ts +2 -2
- package/src/runtime/root/service.ts +126 -44
- package/src/runtime/root/status.ts +48 -0
- package/src/runtime/root/types.ts +32 -9
- package/src/runtime/root/workflow-supervisor-composition.ts +681 -0
- package/src/runtime/root/workflow-supervisor-runtime.ts +564 -0
- package/src/runtime/root/write-fence.ts +50 -2
- package/src/runtime/safe-tooling/google-credential-store.ts +67 -22
- package/src/runtime/safe-tooling/google-oauth-broker.ts +25 -7
- package/src/runtime/safe-tooling/ios-development.ts +22 -8
- package/src/runtime/safe-tooling/job-summary.ts +1 -1
- package/src/runtime/safe-tooling/workspace-auth.ts +5 -2
- package/src/runtime/shared/atomic-text-file.ts +21 -0
- package/src/runtime/shared/bounded-child-supervisor.ts +9 -1
- package/src/runtime/shared/json-files.ts +8 -3
- package/src/runtime/shared/process-environment.ts +20 -9
- package/src/runtime/shared/response-budget.ts +1 -3
- package/src/runtime/standalone-recovery/controller-home-migration.ts +16 -24
- package/src/runtime/standalone-recovery/core.ts +3792 -417
- package/src/runtime/standalone-recovery/entry.ts +507 -45
- package/src/runtime/standalone-recovery/installer.ts +262 -148
- package/src/runtime/standalone-recovery/mcp-server.ts +29 -193
- package/src/runtime/standalone-recovery/operation-lock.ts +12 -2
- package/src/runtime/standalone-recovery/performance.ts +54 -16
- package/src/runtime/standalone-recovery/release.ts +53 -5
- package/src/runtime/standalone-recovery/service-labels.ts +5 -2
- package/src/runtime/standalone-recovery/watchdog-heartbeat.ts +5 -2
- package/src/runtime/workflow/schedules/browser-probe.ts +17 -6
- package/src/runtime/workflow/schedules/chatgpt-automation-migration.ts +11 -3
- package/src/runtime/workflow/schedules/engine.ts +166 -178
- package/src/runtime/workflow/schedules/pending-activation.ts +11 -4
- package/src/runtime/workflow/schedules/work-continuation.ts +95 -11
- package/src/runtime/workflows/runtime.ts +15 -19
- package/src/testing/test-governance.ts +5 -1
- package/supervisor/chatgpt-conversation.ts +23 -0
- package/supervisor/client.ts +218 -0
- package/supervisor/control-plane.ts +963 -0
- package/supervisor/entry.ts +15 -0
- package/supervisor/forge-validators.ts +147 -0
- package/supervisor/index.ts +5 -0
- package/supervisor/native-browser-adapter.ts +1151 -0
- package/supervisor/native-messaging/host.ts +58 -0
- package/supervisor/native-messaging/manifest.ts +26 -0
- package/supervisor/native-messaging/protocol.ts +27 -0
- package/supervisor/paths.ts +18 -0
- package/supervisor/protocol.ts +250 -0
- package/supervisor/server.ts +412 -0
- package/supervisor/store.ts +1870 -0
- package/supervisor/tsconfig.json +8 -0
- package/supervisor/types.ts +261 -0
- package/SKILL.md +0 -427
- package/adapters/chatgpt/controller-host.ts +0 -119
- package/adapters/mcp/controller-round-compatibility.ts +0 -184
- package/adapters/mcp/frozen-client-semantic-compatibility.ts +0 -292
- package/adapters/mcp/runtime-gateway/work-compat-adapter.ts +0 -502
- package/adapters/mcp/runtime-gateway/work-validation-reconciler.ts +0 -1
- package/adapters/mcp/toolset-selection.ts +0 -41
- package/agents/openai.yaml +0 -4
- package/assets/skill-hooks.json +0 -41
- package/assets/skill-version.json +0 -189
- package/assets/skills/claude-review/SKILL.md +0 -231
- package/assets/skills/codex-review/SKILL.md +0 -103
- package/assets/templates/helpers/check-skill-version.ts +0 -193
- package/packages/kernel/progression/api/index.ts +0 -2
- package/packages/kernel/progression/application/projector.ts +0 -211
- package/packages/kernel/progression/domain/types.ts +0 -116
- package/packages/kernel/progression/index.ts +0 -1
- package/packages/kernel/scheduler/application/continuation-service.ts +0 -212
- package/packages/kernel/scheduler/domain/continuation.ts +0 -38
- package/packages/kernel/scheduler/infrastructure/continuation-dispatch-store.ts +0 -38
- package/packages/kernel/work/domain/admission-policy.ts +0 -34
- package/scripts/benchmark-background-check-overlap.ts +0 -228
- package/scripts/benchmark-computer-hotpath.ts +0 -255
- package/scripts/benchmark-controller-hotpath.ts +0 -212
- package/scripts/benchmark-controller-round2.ts +0 -191
- package/scripts/benchmark-ios-agent-device.ts +0 -511
- package/scripts/benchmark-mcp-host.sh +0 -117
- package/scripts/benchmark-mcp-transport.ts +0 -169
- package/scripts/benchmark-operational-memory-activation.ts +0 -235
- package/scripts/benchmark-operational-shadow.ts +0 -28
- package/scripts/benchmark-quality-harness.ts +0 -146
- package/scripts/benchmark-route-session-concurrency.ts +0 -915
- package/scripts/benchmark-thin-harness-gateway-ab.ts +0 -632
- package/scripts/benchmark-thin-harness-mcp-e2e.ts +0 -498
- package/scripts/benchmark-thin-harness.ts +0 -251
- package/scripts/benchmark-typescript-navigation.ts +0 -186
- package/scripts/benchmark-work-efficiency.ts +0 -334
- package/scripts/build-controller-ui.ts +0 -28
- package/scripts/check-npm-release.sh +0 -32
- package/scripts/check-public-release-surface.sh +0 -19
- package/scripts/check-release-published.sh +0 -57
- package/scripts/check-release-readiness.sh +0 -37
- package/scripts/check-release-version.mjs +0 -74
- package/scripts/check-skill-version.ts +0 -5
- package/scripts/check-tarball-install-smoke.sh +0 -150
- package/scripts/ensure-codegraph.sh +0 -16
- package/scripts/package-source-archive.sh +0 -147
- package/scripts/public-release-files.txt +0 -39
- package/scripts/public-release.ts +0 -174
- package/scripts/publish-release-tarball.sh +0 -27
- package/scripts/route-nl-vs-ts-eval.ts +0 -679
- package/scripts/run-skill-hook.ts +0 -244
- package/scripts/stage-runtime-release.ts +0 -44
- package/scripts/sync-codex-installed-copies.sh +0 -182
- package/src/cli/commands/tools.ts +0 -167
- package/src/cli/controller/progress.ts +0 -656
- package/src/cli/controller/work-mode.ts +0 -181
- package/src/cli/local-bridge/console-assets.ts +0 -17
- package/src/cli/local-bridge/dashboard.ts +0 -17
- package/src/cli/local-bridge/frontend/src/App.tsx +0 -10
- package/src/cli/local-bridge/frontend/src/components/Button.tsx +0 -1
- package/src/cli/local-bridge/frontend/src/components/DetailPane.tsx +0 -3
- package/src/cli/local-bridge/frontend/src/components/SearchField.tsx +0 -1
- package/src/cli/local-bridge/frontend/src/components/SectionHeader.tsx +0 -1
- package/src/cli/local-bridge/frontend/src/components/Segmented.tsx +0 -1
- package/src/cli/local-bridge/frontend/src/components/StatusText.tsx +0 -3
- package/src/cli/local-bridge/frontend/src/design/icons.tsx +0 -11
- package/src/cli/local-bridge/frontend/src/design/tokens.css +0 -8
- package/src/cli/local-bridge/frontend/src/features/automations/AutomationsView.tsx +0 -153
- package/src/cli/local-bridge/frontend/src/features/capabilities/CapabilitiesView.tsx +0 -37
- package/src/cli/local-bridge/frontend/src/features/overview/OverviewView.tsx +0 -183
- package/src/cli/local-bridge/frontend/src/features/repositories/RepositoriesView.tsx +0 -2
- package/src/cli/local-bridge/frontend/src/features/system/SystemView.tsx +0 -2
- package/src/cli/local-bridge/frontend/src/features/work/WorkView.tsx +0 -4
- package/src/cli/local-bridge/frontend/src/lib/api.ts +0 -30
- package/src/cli/local-bridge/frontend/src/lib/format.ts +0 -4
- package/src/cli/local-bridge/frontend/src/lib/routes.ts +0 -7
- package/src/cli/local-bridge/frontend/src/main.tsx +0 -1
- package/src/cli/local-bridge/frontend/src/shell/AppShell.tsx +0 -1
- package/src/cli/local-bridge/frontend/src/shell/CommandBar.tsx +0 -2
- package/src/cli/local-bridge/frontend/src/shell/Sidebar.tsx +0 -4
- package/src/cli/local-bridge/frontend/src/styles.css +0 -28
- package/src/cli/local-bridge/frontend/src/types.ts +0 -15
- package/src/cli/local-bridge/frontend/src/vite-env.d.ts +0 -1
- package/src/cli/local-bridge/frontend/vite.config.ts +0 -27
- package/src/cli/local-bridge/ui-dist/app.css +0 -1
- package/src/cli/local-bridge/ui-dist/app.js +0 -11228
- package/src/cli/mcp/access-mode.ts +0 -2
- package/src/cli/mcp/access-tools.ts +0 -2
- package/src/cli/mcp/audit.ts +0 -2
- package/src/cli/mcp/auth.ts +0 -2
- package/src/cli/mcp/instructions.ts +0 -2
- package/src/cli/mcp/legacy-context.ts +0 -2
- package/src/cli/mcp/legacy-tool-service.ts +0 -2
- package/src/cli/mcp/multi-repository.ts +0 -2
- package/src/cli/mcp/oauth.ts +0 -2
- package/src/cli/mcp/openai-secure-tunnel.ts +0 -2
- package/src/cli/mcp/paths.ts +0 -2
- package/src/cli/mcp/policy.ts +0 -2
- package/src/cli/mcp/post-finalize-work-attribution.ts +0 -2
- package/src/cli/mcp/proxy-env.ts +0 -2
- package/src/cli/mcp/readiness-projection.ts +0 -2
- package/src/cli/mcp/redaction.ts +0 -2
- package/src/cli/mcp/repo.ts +0 -2
- package/src/cli/mcp/repository-tools.ts +0 -2
- package/src/cli/mcp/server.ts +0 -2
- package/src/cli/mcp/setup.ts +0 -2
- package/src/cli/mcp/tool-capability-cache.ts +0 -2
- package/src/cli/mcp/tool-contract.ts +0 -2
- package/src/cli/mcp/tools.ts +0 -2
- package/src/cli/mcp/toolset-names.ts +0 -2
- package/src/cli/mcp/toolset-selection.ts +0 -2
- package/src/cli/mcp/toolset.ts +0 -2
- package/src/cli/mcp/transports/http.ts +0 -2
- package/src/cli/mcp/transports/session-registry.ts +0 -2
- package/src/cli/mcp/transports/stdio.ts +0 -2
- package/src/cli/mcp/types.ts +0 -2
- package/src/cli/mcp/umbrella-tools.ts +0 -2
- package/src/cli/tools/codegraph.ts +0 -695
- package/src/core/adoption/helper-wrapper-plan.ts +0 -159
- package/src/runtime/context/codegraph-cache-boundary.ts +0 -255
- package/src/runtime/context/codegraph-read-provider.ts +0 -611
- package/src/runtime/context/codegraph-sidecar.cjs +0 -248
- package/src/runtime/control-plane/codegraph-cache-retention.ts +0 -164
- package/src/runtime/control-plane/execution/content-equivalent-commit-authority.ts +0 -169
- package/src/runtime/control-plane/execution/direct-canonical-work-reconciliation.ts +0 -85
- package/src/runtime/control-plane/execution/direct-edit-work-completion.ts +0 -655
- package/src/runtime/control-plane/execution/work-finalization-service.ts +0 -2850
- package/src/runtime/control-plane/execution/work-path-scope.ts +0 -37
- package/src/runtime/control-plane/execution/work-task-receipt.ts +0 -468
- package/src/runtime/control-plane/facade/controller-round-relay.ts +0 -3
- package/src/runtime/control-plane/facade/work-admission-policy.ts +0 -142
- package/src/runtime/control-plane/facade/work-implementation-review.ts +0 -2
- package/src/runtime/control-plane/facade/work-state-machine.ts +0 -2
- package/src/runtime/control-plane/facade/work-task-projection.ts +0 -66
- package/src/runtime/control-plane/routing/index.ts +0 -1
- package/src/runtime/control-plane/routing/route-policy.ts +0 -401
- package/src/runtime/control-plane/routing/workspace-admission.ts +0 -70
- package/src/runtime/gateway/mcp/execution-tools.ts +0 -2
- package/src/runtime/gateway/mcp/legacy-ios-tool-adapter.ts +0 -2
- package/src/runtime/gateway/mcp/persisted-check-process.ts +0 -2
- package/src/runtime/gateway/mcp/process-tools.ts +0 -2
- package/src/runtime/gateway/mcp/router.ts +0 -2
- package/src/runtime/gateway/mcp/runtime-tool-definitions.ts +0 -2
- package/src/runtime/gateway/mcp/runtime-tools.ts +0 -2
- package/src/runtime/gateway/mcp/work-validation-reconciler.ts +0 -2
- package/src/runtime/plugins/browser-provider-registry.ts +0 -2
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { resolve } from 'path';
|
|
2
2
|
import { resolveControllerHome } from '../../cli/repositories/controller-home';
|
|
3
3
|
import { isProcessAlive } from '../shared/process-tree';
|
|
4
|
-
import { readRuntimeOwner, type RuntimeOwnerRecord } from './ownership';
|
|
4
|
+
import { readRuntimeIncarnation, readRuntimeOwner, type RuntimeOwnerRecord } from './ownership';
|
|
5
5
|
import {
|
|
6
6
|
readRuntimeReleaseAuthority,
|
|
7
7
|
type RuntimeReleaseAuthority,
|
|
@@ -29,6 +29,7 @@ export type RuntimeWriteAction = (typeof RUNTIME_WRITE_ACTIONS)[number];
|
|
|
29
29
|
export interface RuntimeWriteClaim {
|
|
30
30
|
controllerHome: string;
|
|
31
31
|
runtimeInstanceId: string;
|
|
32
|
+
fencingGeneration: number;
|
|
32
33
|
ownerPid: number;
|
|
33
34
|
releaseAuthorityRevision: number;
|
|
34
35
|
releaseFencingToken: string;
|
|
@@ -50,6 +51,7 @@ export interface RuntimeWriteFenceCheck {
|
|
|
50
51
|
export const RUNTIME_WRITE_CLAIM_ENV = {
|
|
51
52
|
controllerHome: 'FORGE_CONTROLLER_HOME',
|
|
52
53
|
runtimeInstanceId: 'FORGE_RUNTIME_INSTANCE_ID',
|
|
54
|
+
fencingGeneration: 'FORGE_RUNTIME_INCARNATION_GENERATION',
|
|
53
55
|
ownerPid: 'FORGE_RUNTIME_OWNER_PID',
|
|
54
56
|
releaseAuthorityRevision: 'FORGE_RELEASE_AUTHORITY_REVISION',
|
|
55
57
|
releaseFencingToken: 'FORGE_RELEASE_FENCING_TOKEN',
|
|
@@ -75,6 +77,7 @@ function claimFromAuthority(
|
|
|
75
77
|
return {
|
|
76
78
|
controllerHome: resolveControllerHome(controllerHome),
|
|
77
79
|
runtimeInstanceId: owner.runtimeInstanceId,
|
|
80
|
+
fencingGeneration: owner.fencingGeneration ?? 0,
|
|
78
81
|
ownerPid: owner.pid,
|
|
79
82
|
releaseAuthorityRevision: authority.revision,
|
|
80
83
|
releaseFencingToken: authority.fencingToken,
|
|
@@ -85,11 +88,22 @@ function claimFromAuthority(
|
|
|
85
88
|
};
|
|
86
89
|
}
|
|
87
90
|
|
|
91
|
+
export function currentRuntimeWriteClaimEnvironment(controllerHome: string): Record<string, string> {
|
|
92
|
+
const home = resolveControllerHome(controllerHome);
|
|
93
|
+
const owner = readRuntimeOwner(home);
|
|
94
|
+
const authority = readRuntimeReleaseAuthority(home);
|
|
95
|
+
if (!owner || !authority) {
|
|
96
|
+
throw new Error('RUNTIME_WRITE_CLAIM_BIND_FAILED: Runtime owner or release authority is missing');
|
|
97
|
+
}
|
|
98
|
+
return runtimeWriteClaimEnvironment(claimFromAuthority(home, owner, authority));
|
|
99
|
+
}
|
|
100
|
+
|
|
88
101
|
export function runtimeWriteClaimEnvironment(claim: RuntimeWriteClaim): Record<string, string> {
|
|
89
102
|
if (claim.unmanaged) return {};
|
|
90
103
|
return {
|
|
91
104
|
[RUNTIME_WRITE_CLAIM_ENV.controllerHome]: claim.controllerHome,
|
|
92
105
|
[RUNTIME_WRITE_CLAIM_ENV.runtimeInstanceId]: claim.runtimeInstanceId,
|
|
106
|
+
[RUNTIME_WRITE_CLAIM_ENV.fencingGeneration]: String(claim.fencingGeneration),
|
|
93
107
|
[RUNTIME_WRITE_CLAIM_ENV.ownerPid]: String(claim.ownerPid),
|
|
94
108
|
[RUNTIME_WRITE_CLAIM_ENV.releaseAuthorityRevision]: String(claim.releaseAuthorityRevision),
|
|
95
109
|
[RUNTIME_WRITE_CLAIM_ENV.releaseFencingToken]: claim.releaseFencingToken,
|
|
@@ -130,6 +144,7 @@ export const clearRuntimeWriteClaimForTests = clearRuntimeWriteClaim;
|
|
|
130
144
|
export function bindRuntimeWriteClaim(input: {
|
|
131
145
|
controllerHome: string;
|
|
132
146
|
runtimeInstanceId?: string;
|
|
147
|
+
fencingGeneration?: number;
|
|
133
148
|
ownerPid?: number;
|
|
134
149
|
releaseAuthorityRevision?: number;
|
|
135
150
|
releaseFencingToken?: string;
|
|
@@ -146,6 +161,7 @@ export function bindRuntimeWriteClaim(input: {
|
|
|
146
161
|
|
|
147
162
|
const explicit = {
|
|
148
163
|
runtimeInstanceId: input.runtimeInstanceId?.trim(),
|
|
164
|
+
fencingGeneration: input.fencingGeneration,
|
|
149
165
|
ownerPid: input.ownerPid,
|
|
150
166
|
releaseAuthorityRevision: input.releaseAuthorityRevision,
|
|
151
167
|
releaseFencingToken: input.releaseFencingToken?.trim(),
|
|
@@ -157,6 +173,7 @@ export function bindRuntimeWriteClaim(input: {
|
|
|
157
173
|
const hasAnyExplicit = explicitValues.some((value) => value !== undefined && value !== '');
|
|
158
174
|
const hasFullExplicit = Boolean(
|
|
159
175
|
explicit.runtimeInstanceId
|
|
176
|
+
&& Number.isInteger(explicit.fencingGeneration) && explicit.fencingGeneration! > 0
|
|
160
177
|
&& Number.isInteger(explicit.ownerPid) && explicit.ownerPid! > 0
|
|
161
178
|
&& Number.isInteger(explicit.releaseAuthorityRevision) && explicit.releaseAuthorityRevision! > 0
|
|
162
179
|
&& explicit.releaseFencingToken
|
|
@@ -169,6 +186,7 @@ export function bindRuntimeWriteClaim(input: {
|
|
|
169
186
|
return installClaim({
|
|
170
187
|
controllerHome: home,
|
|
171
188
|
runtimeInstanceId: explicit.runtimeInstanceId!,
|
|
189
|
+
fencingGeneration: explicit.fencingGeneration!,
|
|
172
190
|
ownerPid: explicit.ownerPid!,
|
|
173
191
|
releaseAuthorityRevision: explicit.releaseAuthorityRevision!,
|
|
174
192
|
releaseFencingToken: explicit.releaseFencingToken!,
|
|
@@ -190,6 +208,7 @@ export function bindRuntimeWriteClaim(input: {
|
|
|
190
208
|
return installClaim({
|
|
191
209
|
controllerHome: home,
|
|
192
210
|
runtimeInstanceId: `unmanaged-${process.pid}`,
|
|
211
|
+
fencingGeneration: 0,
|
|
193
212
|
ownerPid: process.pid,
|
|
194
213
|
releaseAuthorityRevision: 0,
|
|
195
214
|
releaseFencingToken: 'unmanaged',
|
|
@@ -220,6 +239,7 @@ export function bindInheritedRuntimeWriteClaimFromEnvironment(
|
|
|
220
239
|
return bindRuntimeWriteClaim({
|
|
221
240
|
controllerHome,
|
|
222
241
|
runtimeInstanceId,
|
|
242
|
+
fencingGeneration: positiveInteger(env[RUNTIME_WRITE_CLAIM_ENV.fencingGeneration]),
|
|
223
243
|
ownerPid: positiveInteger(env[RUNTIME_WRITE_CLAIM_ENV.ownerPid]),
|
|
224
244
|
releaseAuthorityRevision: positiveInteger(env[RUNTIME_WRITE_CLAIM_ENV.releaseAuthorityRevision]),
|
|
225
245
|
releaseFencingToken: env[RUNTIME_WRITE_CLAIM_ENV.releaseFencingToken]?.trim(),
|
|
@@ -256,6 +276,7 @@ export function assertRuntimeMayWrite(
|
|
|
256
276
|
const home = explicitHome ?? claim?.controllerHome;
|
|
257
277
|
if (!home) return { allowed: true, reason: 'unbound_no_controller_home' };
|
|
258
278
|
const owner = readRuntimeOwner(home);
|
|
279
|
+
const incarnation = readRuntimeIncarnation(home);
|
|
259
280
|
const authority = readRuntimeReleaseAuthority(home);
|
|
260
281
|
if (!claim) {
|
|
261
282
|
if (!owner && !authority) return { allowed: true, reason: 'unbound_no_runtime_authority' };
|
|
@@ -276,9 +297,18 @@ export function assertRuntimeMayWrite(
|
|
|
276
297
|
}
|
|
277
298
|
if (!owner) return { allowed: false, reason: 'runtime_owner_missing', authority };
|
|
278
299
|
if (!isProcessAlive(owner.pid)) return { allowed: false, reason: 'runtime_owner_dead', owner, authority };
|
|
300
|
+
if (!incarnation) return { allowed: false, reason: 'runtime_incarnation_missing', owner, authority };
|
|
301
|
+
if (
|
|
302
|
+
incarnation.runtimeInstanceId !== owner.runtimeInstanceId
|
|
303
|
+
|| incarnation.pid !== owner.pid
|
|
304
|
+
|| incarnation.fencingGeneration !== (owner.fencingGeneration ?? 0)
|
|
305
|
+
) return { allowed: false, reason: 'runtime_incarnation_authority_mismatch', owner, authority };
|
|
279
306
|
if (owner.runtimeInstanceId !== claim.runtimeInstanceId) {
|
|
280
307
|
return { allowed: false, reason: 'runtime_instance_fenced', owner, authority };
|
|
281
308
|
}
|
|
309
|
+
if (incarnation.fencingGeneration !== claim.fencingGeneration) {
|
|
310
|
+
return { allowed: false, reason: 'runtime_incarnation_generation_fenced', owner, authority };
|
|
311
|
+
}
|
|
282
312
|
if (owner.pid !== claim.ownerPid) return { allowed: false, reason: 'runtime_owner_pid_fenced', owner, authority };
|
|
283
313
|
if (!authority) return { allowed: false, reason: 'runtime_release_authority_missing', owner };
|
|
284
314
|
if (authority.revision !== claim.releaseAuthorityRevision) {
|
|
@@ -299,11 +329,29 @@ export function assertRuntimeMayWrite(
|
|
|
299
329
|
return { allowed: true, owner, authority };
|
|
300
330
|
}
|
|
301
331
|
|
|
332
|
+
export class RuntimeWriteFenceError extends Error {
|
|
333
|
+
readonly code = 'WRITER_FENCED' as const;
|
|
334
|
+
|
|
335
|
+
constructor(
|
|
336
|
+
readonly action: RuntimeWriteAction,
|
|
337
|
+
readonly reason: string,
|
|
338
|
+
) {
|
|
339
|
+
super(`WRITER_FENCED:${action}:${reason}`);
|
|
340
|
+
this.name = 'RuntimeWriteFenceError';
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
export function isRuntimeWriteFenceError(error: unknown): error is RuntimeWriteFenceError {
|
|
345
|
+
return Boolean(error
|
|
346
|
+
&& typeof error === 'object'
|
|
347
|
+
&& (error as { code?: unknown }).code === 'WRITER_FENCED');
|
|
348
|
+
}
|
|
349
|
+
|
|
302
350
|
export function assertRuntimeMayWriteOrThrow(
|
|
303
351
|
action: RuntimeWriteAction,
|
|
304
352
|
controllerHomeOverride?: string,
|
|
305
353
|
): RuntimeReleaseAuthority | undefined {
|
|
306
354
|
const check = assertRuntimeMayWrite(action, controllerHomeOverride);
|
|
307
|
-
if (!check.allowed) throw new
|
|
355
|
+
if (!check.allowed) throw new RuntimeWriteFenceError(action, check.reason ?? 'denied');
|
|
308
356
|
return check.authority;
|
|
309
357
|
}
|
|
@@ -1,16 +1,19 @@
|
|
|
1
1
|
import { execFileSync } from 'child_process';
|
|
2
2
|
|
|
3
3
|
export type StoredGoogleService = 'gmail' | 'calendar' | 'tasks' | 'google-workspace';
|
|
4
|
+
export type StoredGoogleCredentialKind = 'refresh-token' | 'client-secret';
|
|
4
5
|
|
|
5
6
|
export interface GoogleCredentialStoreAdapter {
|
|
6
7
|
available(): boolean;
|
|
7
|
-
read(service: StoredGoogleService): string | undefined;
|
|
8
|
-
write(service: StoredGoogleService,
|
|
8
|
+
read(service: StoredGoogleService, kind?: StoredGoogleCredentialKind): string | undefined;
|
|
9
|
+
write(service: StoredGoogleService, value: string, kind?: StoredGoogleCredentialKind): void;
|
|
9
10
|
}
|
|
10
11
|
|
|
11
12
|
const KEYCHAIN_SERVICE_PREFIX = 'forge.google-oauth';
|
|
12
|
-
const KEYCHAIN_ACCOUNT =
|
|
13
|
-
|
|
13
|
+
const KEYCHAIN_ACCOUNT: Record<StoredGoogleCredentialKind, string> = {
|
|
14
|
+
'refresh-token': 'refresh-token',
|
|
15
|
+
'client-secret': 'client-secret',
|
|
16
|
+
};
|
|
14
17
|
|
|
15
18
|
function keychainService(service: StoredGoogleService): string {
|
|
16
19
|
return `${KEYCHAIN_SERVICE_PREFIX}.${service}`;
|
|
@@ -18,13 +21,13 @@ function keychainService(service: StoredGoogleService): string {
|
|
|
18
21
|
|
|
19
22
|
const macKeychainAdapter: GoogleCredentialStoreAdapter = {
|
|
20
23
|
available: () => process.platform === 'darwin',
|
|
21
|
-
read(service) {
|
|
24
|
+
read(service, kind = 'refresh-token') {
|
|
22
25
|
if (process.platform !== 'darwin') return undefined;
|
|
23
26
|
try {
|
|
24
27
|
const value = execFileSync('/usr/bin/security', [
|
|
25
28
|
'find-generic-password',
|
|
26
29
|
'-s', keychainService(service),
|
|
27
|
-
'-a', KEYCHAIN_ACCOUNT,
|
|
30
|
+
'-a', KEYCHAIN_ACCOUNT[kind],
|
|
28
31
|
'-w',
|
|
29
32
|
], {
|
|
30
33
|
encoding: 'utf-8',
|
|
@@ -36,7 +39,7 @@ const macKeychainAdapter: GoogleCredentialStoreAdapter = {
|
|
|
36
39
|
return undefined;
|
|
37
40
|
}
|
|
38
41
|
},
|
|
39
|
-
write(service,
|
|
42
|
+
write(service, value, kind = 'refresh-token') {
|
|
40
43
|
if (process.platform !== 'darwin') {
|
|
41
44
|
throw new Error('GOOGLE_CREDENTIAL_STORE_UNAVAILABLE: macOS Keychain is required for local OAuth credential persistence');
|
|
42
45
|
}
|
|
@@ -44,8 +47,8 @@ const macKeychainAdapter: GoogleCredentialStoreAdapter = {
|
|
|
44
47
|
'add-generic-password',
|
|
45
48
|
'-U',
|
|
46
49
|
'-s', keychainService(service),
|
|
47
|
-
'-a', KEYCHAIN_ACCOUNT,
|
|
48
|
-
'-w',
|
|
50
|
+
'-a', KEYCHAIN_ACCOUNT[kind],
|
|
51
|
+
'-w', value,
|
|
49
52
|
], {
|
|
50
53
|
encoding: 'utf-8',
|
|
51
54
|
stdio: ['ignore', 'ignore', 'pipe'],
|
|
@@ -58,7 +61,6 @@ let adapter: GoogleCredentialStoreAdapter = macKeychainAdapter;
|
|
|
58
61
|
|
|
59
62
|
export function setGoogleCredentialStoreAdapterForTest(next?: GoogleCredentialStoreAdapter): void {
|
|
60
63
|
adapter = next ?? macKeychainAdapter;
|
|
61
|
-
memoryCache.clear();
|
|
62
64
|
}
|
|
63
65
|
|
|
64
66
|
export function googleCredentialStoreStatus(): Record<string, unknown> {
|
|
@@ -67,29 +69,72 @@ export function googleCredentialStoreStatus(): Record<string, unknown> {
|
|
|
67
69
|
available: adapter.available(),
|
|
68
70
|
repositoryPersistence: false,
|
|
69
71
|
controllerStatePersistence: false,
|
|
72
|
+
credentialKinds: ['refresh-token', 'client-secret'],
|
|
70
73
|
};
|
|
71
74
|
}
|
|
72
75
|
|
|
73
|
-
|
|
76
|
+
function readStoredGoogleCredential(
|
|
77
|
+
service: StoredGoogleService,
|
|
78
|
+
kind: StoredGoogleCredentialKind,
|
|
79
|
+
): { value: string; source: string } | undefined {
|
|
74
80
|
const candidates: StoredGoogleService[] = service === 'google-workspace'
|
|
75
81
|
? ['google-workspace']
|
|
76
82
|
: [service, 'google-workspace'];
|
|
77
83
|
for (const candidate of candidates) {
|
|
78
|
-
const cached = memoryCache.get(candidate);
|
|
79
|
-
if (cached) return { token: cached, source: `keychain:${candidate}` };
|
|
80
84
|
if (!adapter.available()) continue;
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
return {
|
|
85
|
+
// Keychain is the authority: another Forge process may have rotated this credential.
|
|
86
|
+
const value = adapter.read(candidate, kind)?.trim();
|
|
87
|
+
if (!value) continue;
|
|
88
|
+
return { value, source: `keychain:${candidate}:${kind}` };
|
|
85
89
|
}
|
|
86
90
|
return undefined;
|
|
87
91
|
}
|
|
88
92
|
|
|
89
|
-
|
|
90
|
-
const
|
|
91
|
-
if (!
|
|
93
|
+
function writeStoredGoogleCredential(service: StoredGoogleService, kind: StoredGoogleCredentialKind, value: string): void {
|
|
94
|
+
const normalized = value.trim();
|
|
95
|
+
if (!normalized) throw new Error(kind === 'refresh-token' ? 'GOOGLE_REFRESH_TOKEN_REQUIRED' : 'GOOGLE_CLIENT_SECRET_REQUIRED');
|
|
92
96
|
if (!adapter.available()) throw new Error('GOOGLE_CREDENTIAL_STORE_UNAVAILABLE');
|
|
93
|
-
adapter.write(service,
|
|
94
|
-
|
|
97
|
+
adapter.write(service, normalized, kind);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
export function readStoredGoogleRefreshToken(service: StoredGoogleService): { token: string; source: string } | undefined {
|
|
101
|
+
const stored = readStoredGoogleCredential(service, 'refresh-token');
|
|
102
|
+
return stored ? { token: stored.value, source: stored.source } : undefined;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
export function writeStoredGoogleRefreshToken(service: StoredGoogleService, refreshToken: string): void {
|
|
106
|
+
writeStoredGoogleCredential(service, 'refresh-token', refreshToken);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
export function readStoredGoogleClientSecret(service: StoredGoogleService): { secret: string; source: string } | undefined {
|
|
110
|
+
const stored = readStoredGoogleCredential(service, 'client-secret');
|
|
111
|
+
return stored ? { secret: stored.value, source: stored.source } : undefined;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
export function writeStoredGoogleClientSecret(service: StoredGoogleService, clientSecret: string): void {
|
|
115
|
+
writeStoredGoogleCredential(service, 'client-secret', clientSecret);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
export function importStoredGoogleClientSecretFromClipboard(service: StoredGoogleService): Record<string, unknown> {
|
|
119
|
+
if (process.platform !== 'darwin' || !adapter.available()) throw new Error('GOOGLE_CREDENTIAL_STORE_UNAVAILABLE');
|
|
120
|
+
const secret = execFileSync('/usr/bin/pbpaste', [], {
|
|
121
|
+
encoding: 'utf-8',
|
|
122
|
+
stdio: ['ignore', 'pipe', 'ignore'],
|
|
123
|
+
timeout: 2_000,
|
|
124
|
+
}).trim();
|
|
125
|
+
if (!secret || secret.length > 1024 || /\s/.test(secret)) throw new Error('GOOGLE_CLIENT_SECRET_CLIPBOARD_INVALID');
|
|
126
|
+
writeStoredGoogleClientSecret(service, secret);
|
|
127
|
+
execFileSync('/usr/bin/pbcopy', [], {
|
|
128
|
+
encoding: 'utf-8',
|
|
129
|
+
input: '',
|
|
130
|
+
stdio: ['pipe', 'ignore', 'ignore'],
|
|
131
|
+
timeout: 2_000,
|
|
132
|
+
});
|
|
133
|
+
return {
|
|
134
|
+
stored: true,
|
|
135
|
+
service,
|
|
136
|
+
backend: 'macos-keychain',
|
|
137
|
+
clipboardCleared: true,
|
|
138
|
+
credentialMaterialReturned: false,
|
|
139
|
+
};
|
|
95
140
|
}
|
|
@@ -5,6 +5,7 @@ import { URLSearchParams } from 'url';
|
|
|
5
5
|
import { installGoogleAccessToken } from '../plugins/google-shared';
|
|
6
6
|
import {
|
|
7
7
|
googleCredentialStoreStatus,
|
|
8
|
+
readStoredGoogleClientSecret,
|
|
8
9
|
type StoredGoogleService,
|
|
9
10
|
writeStoredGoogleRefreshToken,
|
|
10
11
|
} from './google-credential-store';
|
|
@@ -138,16 +139,33 @@ function base64Url(value: Buffer): string {
|
|
|
138
139
|
return value.toString('base64url');
|
|
139
140
|
}
|
|
140
141
|
|
|
141
|
-
function clientId(): string | undefined {
|
|
142
|
-
|
|
142
|
+
function clientId(service: GoogleOAuthService): string | undefined {
|
|
143
|
+
const serviceSpecific = service === 'gmail'
|
|
144
|
+
? process.env.FORGE_GMAIL_CLIENT_ID?.trim()
|
|
145
|
+
: service === 'calendar'
|
|
146
|
+
? process.env.FORGE_GOOGLE_CALENDAR_CLIENT_ID?.trim()
|
|
147
|
+
: service === 'tasks'
|
|
148
|
+
? process.env.FORGE_GOOGLE_TASKS_CLIENT_ID?.trim()
|
|
149
|
+
: undefined;
|
|
150
|
+
return serviceSpecific
|
|
151
|
+
|| process.env.FORGE_GOOGLE_WORKSPACE_CLIENT_ID?.trim()
|
|
143
152
|
|| process.env.FORGE_GOOGLE_CLIENT_ID?.trim()
|
|
144
153
|
|| process.env.GOOGLE_CLIENT_ID?.trim();
|
|
145
154
|
}
|
|
146
155
|
|
|
147
|
-
function clientSecret(): string | undefined {
|
|
148
|
-
|
|
156
|
+
function clientSecret(service: GoogleOAuthService): string | undefined {
|
|
157
|
+
const serviceSpecific = service === 'gmail'
|
|
158
|
+
? process.env.FORGE_GMAIL_CLIENT_SECRET?.trim()
|
|
159
|
+
: service === 'calendar'
|
|
160
|
+
? process.env.FORGE_GOOGLE_CALENDAR_CLIENT_SECRET?.trim()
|
|
161
|
+
: service === 'tasks'
|
|
162
|
+
? process.env.FORGE_GOOGLE_TASKS_CLIENT_SECRET?.trim()
|
|
163
|
+
: undefined;
|
|
164
|
+
return serviceSpecific
|
|
165
|
+
|| process.env.FORGE_GOOGLE_WORKSPACE_CLIENT_SECRET?.trim()
|
|
149
166
|
|| process.env.FORGE_GOOGLE_CLIENT_SECRET?.trim()
|
|
150
|
-
|| process.env.GOOGLE_CLIENT_SECRET?.trim()
|
|
167
|
+
|| process.env.GOOGLE_CLIENT_SECRET?.trim()
|
|
168
|
+
|| readStoredGoogleClientSecret(service)?.secret;
|
|
151
169
|
}
|
|
152
170
|
|
|
153
171
|
export function prepareGoogleOAuthLogin(
|
|
@@ -157,7 +175,7 @@ export function prepareGoogleOAuthLogin(
|
|
|
157
175
|
pruneOAuthRequests(controllerHome);
|
|
158
176
|
const redirectUri = validateRedirectUri(input.redirectUri);
|
|
159
177
|
const scopes = validateScopes(input.service, input.scopes);
|
|
160
|
-
const configuredClientId = clientId();
|
|
178
|
+
const configuredClientId = clientId(input.service);
|
|
161
179
|
if (!configuredClientId) {
|
|
162
180
|
return {
|
|
163
181
|
schemaVersion: 1,
|
|
@@ -236,7 +254,7 @@ export async function completeGoogleOAuthLogin(
|
|
|
236
254
|
}
|
|
237
255
|
const code = input.code?.trim();
|
|
238
256
|
if (!code) throw new Error('GOOGLE_OAUTH_CODE_REQUIRED');
|
|
239
|
-
const configuredSecret = clientSecret();
|
|
257
|
+
const configuredSecret = clientSecret(selected.record.service);
|
|
240
258
|
if (!configuredSecret) throw new Error('GOOGLE_OAUTH_CLIENT_SECRET_REQUIRED');
|
|
241
259
|
const body = new URLSearchParams({
|
|
242
260
|
grant_type: 'authorization_code',
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { createHash } from 'crypto';
|
|
2
|
-
import { existsSync, mkdirSync, readdirSync, readFileSync, realpathSync, writeFileSync } from 'fs';
|
|
2
|
+
import { existsSync, mkdirSync, readdirSync, readFileSync, realpathSync, utimesSync, writeFileSync } from 'fs';
|
|
3
3
|
import { basename, dirname, join, relative, resolve, sep } from 'path';
|
|
4
4
|
import { spawnSync } from 'child_process';
|
|
5
5
|
import type { RepositoryRecord } from '../../cli/repositories/types';
|
|
@@ -155,13 +155,26 @@ function sanitize(value: string): string {
|
|
|
155
155
|
|
|
156
156
|
function stableBuildDerivedDataPath(
|
|
157
157
|
repository: RepositoryRecord,
|
|
158
|
-
input: { workspace?: string; project?: string; scheme: string; configuration: string;
|
|
158
|
+
input: { workspace?: string; project?: string; scheme: string; configuration: string; destinationPlatform: 'ios_simulator' | 'ios' },
|
|
159
159
|
): string {
|
|
160
|
-
const identity = JSON.stringify([input.workspace ?? '', input.project ?? '', input.scheme, input.configuration, input.
|
|
160
|
+
const identity = JSON.stringify([input.workspace ?? '', input.project ?? '', input.scheme, input.configuration, input.destinationPlatform]);
|
|
161
161
|
const digest = createHash('sha256').update(identity).digest('hex').slice(0, 16);
|
|
162
162
|
return join(safeArtifactDir(repository, 'DerivedData'), `build-${sanitize(input.scheme)}-${digest}`);
|
|
163
163
|
}
|
|
164
164
|
|
|
165
|
+
// Xcode owns invalidation within this checkout-local, platform/configuration bucket.
|
|
166
|
+
// Device identity and test selectors affect execution, not the reusable build cache.
|
|
167
|
+
function runCachedXcodeCommand(repository: RepositoryRecord, derivedDataPath: string, args: string[], timeoutMs: number): IosCommandResult {
|
|
168
|
+
const touch = (): void => { const usedAt = now(); utimesSync(derivedDataPath, usedAt, usedAt); };
|
|
169
|
+
touch();
|
|
170
|
+
try {
|
|
171
|
+
return runCommand('xcodebuild', args, { cwd: repository.canonicalRoot, timeoutMs });
|
|
172
|
+
} finally {
|
|
173
|
+
// Reuse may only modify descendants; keep last-use grace on the bucket itself.
|
|
174
|
+
touch();
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
|
|
165
178
|
function boundedText(value: string, maxBytes = 20_000): { content: string; truncated: boolean } {
|
|
166
179
|
const buffer = Buffer.from(value, 'utf-8');
|
|
167
180
|
if (buffer.byteLength <= maxBytes) return { content: value, truncated: false };
|
|
@@ -427,7 +440,7 @@ export function iosAppBuild(repository: RepositoryRecord, input: {
|
|
|
427
440
|
: udid
|
|
428
441
|
? `platform=iOS Simulator,id=${udid}`
|
|
429
442
|
: `platform=iOS Simulator,name=${input.simulatorName ?? 'iPhone 16 Pro'}`;
|
|
430
|
-
const derivedDataPath = stableBuildDerivedDataPath(repository, { workspace, project, scheme, configuration,
|
|
443
|
+
const derivedDataPath = stableBuildDerivedDataPath(repository, { workspace, project, scheme, configuration, destinationPlatform });
|
|
431
444
|
const derivedDataReused = existsSync(derivedDataPath);
|
|
432
445
|
mkdirSync(derivedDataPath, { recursive: true });
|
|
433
446
|
const priorBuiltApps = derivedDataReused ? findBuiltApps(repository, derivedDataPath) : [];
|
|
@@ -445,7 +458,7 @@ export function iosAppBuild(repository: RepositoryRecord, input: {
|
|
|
445
458
|
'-authenticationKeyIssuerID', authentication.issuerId,
|
|
446
459
|
);
|
|
447
460
|
}
|
|
448
|
-
const result =
|
|
461
|
+
const result = runCachedXcodeCommand(repository, derivedDataPath, args, input.timeoutMs ?? 10 * 60_000);
|
|
449
462
|
const sensitiveValues = authentication
|
|
450
463
|
? [authentication.privateKeyPath, authentication.keyId, authentication.issuerId]
|
|
451
464
|
: [];
|
|
@@ -509,8 +522,9 @@ export function iosXcodeTest(repository: RepositoryRecord, input: {
|
|
|
509
522
|
if (!scheme) throw new Error('IOS_SCHEME_REQUIRED: provide scheme or share at least one Xcode scheme');
|
|
510
523
|
const workspace = safeRepoRelativePath(repository.canonicalRoot, input.workspace ?? listedReady.workspace);
|
|
511
524
|
const project = safeRepoRelativePath(repository.canonicalRoot, input.project ?? listedReady.project);
|
|
512
|
-
const
|
|
513
|
-
const
|
|
525
|
+
const configuration = input.configuration ?? 'Debug';
|
|
526
|
+
const derivedDataPath = stableBuildDerivedDataPath(repository, { workspace, project, scheme, configuration, destinationPlatform: 'ios_simulator' });
|
|
527
|
+
const resultBundlePath = join(safeArtifactDir(repository, 'test-results'), `${artifactStamp()}-${sanitize(scheme)}.xcresult`);
|
|
514
528
|
mkdirSync(derivedDataPath, { recursive: true });
|
|
515
529
|
const args = ['test'];
|
|
516
530
|
if (workspace) args.push('-workspace', workspace);
|
|
@@ -531,7 +545,7 @@ export function iosXcodeTest(repository: RepositoryRecord, input: {
|
|
|
531
545
|
if (normalized) args.push(`-only-testing:${normalized}`);
|
|
532
546
|
}
|
|
533
547
|
args.push('-derivedDataPath', derivedDataPath, '-resultBundlePath', resultBundlePath);
|
|
534
|
-
const result =
|
|
548
|
+
const result = runCachedXcodeCommand(repository, derivedDataPath, args, input.timeoutMs ?? 15 * 60_000);
|
|
535
549
|
return {
|
|
536
550
|
ready: result.ok,
|
|
537
551
|
ok: result.ok,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { redactMcpText } from '
|
|
1
|
+
import { redactMcpText } from '../../../adapters/mcp/redaction';
|
|
2
2
|
import type { ExecutionJob } from '../execution/jobs/types';
|
|
3
3
|
import { buildJobOperationDigest } from '../control-plane/facade/operation-digest';
|
|
4
4
|
import {
|
|
@@ -56,6 +56,7 @@ function pluginAuthSummary(manifest: AssistantPluginManifest): Record<string, un
|
|
|
56
56
|
lifecycleReason: manifest.lifecycle.reason,
|
|
57
57
|
healthState: manifest.health.state,
|
|
58
58
|
ready: manifest.health.ready,
|
|
59
|
+
readinessMode: manifest.health.details?.readinessMode,
|
|
59
60
|
authRequired: manifest.health.errors.some((error) => /access token|auth|authorization|oauth/i.test(error)),
|
|
60
61
|
errors: manifest.health.errors.slice(0, 5),
|
|
61
62
|
warnings: manifest.health.warnings.slice(0, 5),
|
|
@@ -74,7 +75,9 @@ export function buildWorkspaceAuthStatus(manifests: AssistantPluginManifest[]):
|
|
|
74
75
|
actionRequired: summaries.filter((entry) => entry.authRequired === true || entry.ready !== true).map((entry) => ({
|
|
75
76
|
pluginId: entry.pluginId,
|
|
76
77
|
reason: entry.lifecycleReason,
|
|
77
|
-
next:
|
|
78
|
+
next: entry.readinessMode === 'live_token_unverified'
|
|
79
|
+
? 'Run a read-only provider action. If Google requires client_secret, restore the matching OAuth client secret in macOS Keychain; if it cannot be recovered, configure a dedicated OAuth client ID and matching secret, then reauthorize.'
|
|
80
|
+
: 'Call workspace_auth_login_prepare and open the returned local OAuth URL. The callback stores the refresh token in macOS Keychain.',
|
|
78
81
|
})),
|
|
79
82
|
safety: {
|
|
80
83
|
credentialMaterialReturned: false,
|
|
@@ -88,10 +91,10 @@ export function prepareWorkspaceAuthLogin(
|
|
|
88
91
|
controllerHomeOrInput: string | WorkspaceAuthLoginInput = {},
|
|
89
92
|
maybeInput: WorkspaceAuthLoginInput = {},
|
|
90
93
|
): Record<string, unknown> {
|
|
91
|
-
bootstrapManagedRuntimeEnv();
|
|
92
94
|
const controllerHome = typeof controllerHomeOrInput === 'string'
|
|
93
95
|
? controllerHomeOrInput
|
|
94
96
|
: process.env.FORGE_CONTROLLER_HOME?.trim() || process.cwd();
|
|
97
|
+
bootstrapManagedRuntimeEnv({ controllerHome });
|
|
95
98
|
const input = typeof controllerHomeOrInput === 'string' ? maybeInput : controllerHomeOrInput;
|
|
96
99
|
const service = normalizeService(input.service);
|
|
97
100
|
const redirectUri = input.redirectUri || process.env.FORGE_GOOGLE_REDIRECT_URI || 'http://127.0.0.1:8766/oauth/google/callback';
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { randomUUID } from 'crypto';
|
|
2
|
+
import { mkdirSync, renameSync, rmSync, writeFileSync } from 'fs';
|
|
3
|
+
import { dirname } from 'path';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* The single atomic text writer for Forge-managed service and release files.
|
|
7
|
+
* Create private parent directories, use a collision-resistant temporary file,
|
|
8
|
+
* preserve the caller-selected target mode, and remove abandoned temp files
|
|
9
|
+
* after a failed write or rename. An atomic rename is not an fsync guarantee.
|
|
10
|
+
*/
|
|
11
|
+
export function writeAtomicTextFile(path: string, content: string, mode = 0o600): void {
|
|
12
|
+
mkdirSync(dirname(path), { recursive: true, mode: 0o700 });
|
|
13
|
+
const temporary = `${path}.${process.pid}.${randomUUID()}.tmp`;
|
|
14
|
+
try {
|
|
15
|
+
writeFileSync(temporary, content, { encoding: 'utf8', mode, flag: 'wx' });
|
|
16
|
+
renameSync(temporary, path);
|
|
17
|
+
} catch (error) {
|
|
18
|
+
try { rmSync(temporary, { force: true }); } catch { /* preserve original write failure */ }
|
|
19
|
+
throw error;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
@@ -39,6 +39,8 @@ export interface BoundedChildRunOptions {
|
|
|
39
39
|
env?: NodeJS.ProcessEnv;
|
|
40
40
|
timeoutMs: number;
|
|
41
41
|
maxOutputBytes?: number;
|
|
42
|
+
/** Optional bounded stdin payload for request/response sidecars. */
|
|
43
|
+
input?: string | Buffer;
|
|
42
44
|
stdio?: 'capture' | 'inherit';
|
|
43
45
|
forwardSignals?: boolean;
|
|
44
46
|
onSpawn?: (pid: number) => void;
|
|
@@ -120,7 +122,7 @@ export async function runBoundedChild(
|
|
|
120
122
|
const maxOutputBytes = options.maxOutputBytes ?? DEFAULT_MAX_OUTPUT_BYTES;
|
|
121
123
|
const stdio: StdioOptions = options.stdio === 'inherit'
|
|
122
124
|
? ['ignore', 'inherit', 'inherit']
|
|
123
|
-
: ['ignore', 'pipe', 'pipe'];
|
|
125
|
+
: [options.input === undefined ? 'ignore' : 'pipe', 'pipe', 'pipe'];
|
|
124
126
|
let child: ChildProcess;
|
|
125
127
|
try {
|
|
126
128
|
child = spawn(command, [...args], {
|
|
@@ -147,6 +149,12 @@ export async function runBoundedChild(
|
|
|
147
149
|
|
|
148
150
|
const pid = child.pid;
|
|
149
151
|
if (pid) options.onSpawn?.(pid);
|
|
152
|
+
if (options.input !== undefined && child.stdin) {
|
|
153
|
+
// A canary or validation failure may close stdin before the parent writes.
|
|
154
|
+
// The child outcome is authoritative; a late EPIPE must not crash the host.
|
|
155
|
+
child.stdin.on('error', () => undefined);
|
|
156
|
+
child.stdin.end(options.input);
|
|
157
|
+
}
|
|
150
158
|
let stdout = '';
|
|
151
159
|
let stderr = '';
|
|
152
160
|
child.stdout?.on('data', (chunk) => { stdout = appendBounded(stdout, chunk, maxOutputBytes); });
|
|
@@ -16,11 +16,16 @@ export function readJsonFile<T>(path: string, fallback?: T): T {
|
|
|
16
16
|
}
|
|
17
17
|
}
|
|
18
18
|
|
|
19
|
-
export function writeJsonAtomic(path: string, value: unknown): void {
|
|
19
|
+
export function writeJsonAtomic(path: string, value: unknown, options?: { mode?: number }): void {
|
|
20
20
|
ensureParent(path);
|
|
21
21
|
const temporary = `${path}.${process.pid}.${randomUUID()}.tmp`;
|
|
22
|
-
|
|
23
|
-
|
|
22
|
+
try {
|
|
23
|
+
writeFileSync(temporary, `${JSON.stringify(value, null, 2)}\n`, { encoding: 'utf8', ...(options?.mode === undefined ? {} : { mode: options.mode }) });
|
|
24
|
+
renameSync(temporary, path);
|
|
25
|
+
} catch (error) {
|
|
26
|
+
rmSync(temporary, { force: true });
|
|
27
|
+
throw error;
|
|
28
|
+
}
|
|
24
29
|
}
|
|
25
30
|
|
|
26
31
|
export function appendJsonLine(path: string, value: unknown): void {
|
|
@@ -22,11 +22,30 @@ const RUNTIME_PRIVATE_ENV_PREFIXES = [
|
|
|
22
22
|
|
|
23
23
|
const RUNTIME_PRIVATE_ENV_KEYS = new Set([
|
|
24
24
|
'FORGE_BUILD_VERSION',
|
|
25
|
+
'FORGE_INSTANCE_ID',
|
|
25
26
|
'FORGE_MCP_INSTANCE_ID',
|
|
26
27
|
'FORGE_MCP_PUBLIC_ORIGIN',
|
|
27
28
|
'FORGE_STABLE_SUPERVISOR',
|
|
28
29
|
]);
|
|
29
30
|
|
|
31
|
+
/**
|
|
32
|
+
* Remove the hosting Runtime's private authority before starting a service or
|
|
33
|
+
* child. Callers may then add the exact contract they own. This prevents an
|
|
34
|
+
* ambient writer slot/claim from becoming an accidental second writer.
|
|
35
|
+
*/
|
|
36
|
+
export function runtimeAuthorityFreeEnvironment(
|
|
37
|
+
env: NodeJS.ProcessEnv = process.env,
|
|
38
|
+
): NodeJS.ProcessEnv {
|
|
39
|
+
const sanitized = { ...env };
|
|
40
|
+
for (const key of Object.keys(sanitized)) {
|
|
41
|
+
if (
|
|
42
|
+
RUNTIME_PRIVATE_ENV_KEYS.has(key)
|
|
43
|
+
|| RUNTIME_PRIVATE_ENV_PREFIXES.some((prefix) => key.startsWith(prefix))
|
|
44
|
+
) delete sanitized[key];
|
|
45
|
+
}
|
|
46
|
+
return sanitized;
|
|
47
|
+
}
|
|
48
|
+
|
|
30
49
|
function appendExecutableDirectory(pathEntries: string[], candidate: string | undefined): void {
|
|
31
50
|
if (!candidate || !isAbsolute(candidate) || pathEntries.includes(candidate)) return;
|
|
32
51
|
pathEntries.push(candidate);
|
|
@@ -70,15 +89,7 @@ export function repositoryChildProcessEnvironment(
|
|
|
70
89
|
env: NodeJS.ProcessEnv = process.env,
|
|
71
90
|
platform: NodeJS.Platform = process.platform,
|
|
72
91
|
): NodeJS.ProcessEnv {
|
|
73
|
-
const sanitized =
|
|
74
|
-
for (const key of Object.keys(sanitized)) {
|
|
75
|
-
if (
|
|
76
|
-
RUNTIME_PRIVATE_ENV_KEYS.has(key)
|
|
77
|
-
|| RUNTIME_PRIVATE_ENV_PREFIXES.some((prefix) => key.startsWith(prefix))
|
|
78
|
-
) {
|
|
79
|
-
delete sanitized[key];
|
|
80
|
-
}
|
|
81
|
-
}
|
|
92
|
+
const sanitized = runtimeAuthorityFreeEnvironment(env);
|
|
82
93
|
|
|
83
94
|
if (platform === 'win32') {
|
|
84
95
|
let inheritedPath: string | undefined;
|
|
@@ -222,9 +222,7 @@ export function artifactRef(input: {
|
|
|
222
222
|
...(typeof input.byteLength === 'number' ? { byteLength: input.byteLength } : {}),
|
|
223
223
|
...(input.repoId ? { repoId: input.repoId } : {}),
|
|
224
224
|
...(input.jobId ? { jobId: input.jobId } : {}),
|
|
225
|
-
next: input.
|
|
226
|
-
? `Call get_artifact with repo_id=${input.repoId} and artifact_id=${input.artifactId}.`
|
|
227
|
-
: `Call get_artifact with artifact_id=${input.artifactId}.`,
|
|
225
|
+
next: `Call get_artifact with artifact_id=${input.artifactId}.`,
|
|
228
226
|
};
|
|
229
227
|
}
|
|
230
228
|
|