@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,5 +1,5 @@
|
|
|
1
|
-
import { cpSync, lstatSync, mkdirSync,
|
|
2
|
-
import {
|
|
1
|
+
import { cpSync, lstatSync, mkdirSync, readlinkSync, rmSync } from 'fs';
|
|
2
|
+
import { join, resolve } from 'path';
|
|
3
3
|
import type {
|
|
4
4
|
ComputerSurfaceProviderBinding,
|
|
5
5
|
ComputerSurfaceTarget,
|
|
@@ -12,13 +12,24 @@ import {
|
|
|
12
12
|
cleanupLegacyBrowserSessionJson,
|
|
13
13
|
readLegacyBrowserSessionMigrationEntries,
|
|
14
14
|
} from './browser-session-legacy-migration';
|
|
15
|
-
import { writeJsonAtomic } from '../shared/json-files';
|
|
16
15
|
import { AssistantPluginError } from './errors';
|
|
17
16
|
|
|
18
17
|
const BROWSER_STATE_ROOT = '.forge/browser';
|
|
19
18
|
const BROWSER_SESSION_COMPATIBILITY_NAMESPACE = 'browser.session.v1';
|
|
20
19
|
const BROWSER_SESSION_COMPUTER_MIGRATION_ID = 'browser-session-authority-v1-to-computer-surface-v1';
|
|
21
20
|
|
|
21
|
+
function requireBrowserSessionExecutionContext() {
|
|
22
|
+
const context = currentRuntimeBrowserSessionExecutionContext();
|
|
23
|
+
if (!context) {
|
|
24
|
+
throw new AssistantPluginError(
|
|
25
|
+
'PLUGIN_BROWSER_SESSION_CONTEXT_REQUIRED',
|
|
26
|
+
'Browser session identity is owned by the Computer target authority and requires an explicit Controller execution context.',
|
|
27
|
+
{ retryable: false },
|
|
28
|
+
);
|
|
29
|
+
}
|
|
30
|
+
return context;
|
|
31
|
+
}
|
|
32
|
+
|
|
22
33
|
function unique(values: readonly string[]): string[] {
|
|
23
34
|
return [...new Set(values.map((value) => value.trim()).filter(Boolean))];
|
|
24
35
|
}
|
|
@@ -109,9 +120,9 @@ function surfaceInput(
|
|
|
109
120
|
* Browser actions never read or write Browser-owned durable session state.
|
|
110
121
|
*/
|
|
111
122
|
export function ensureBrowserSessionsMigratedToComputer(repoRoot: string): number {
|
|
112
|
-
const context =
|
|
113
|
-
if (!context) return 0;
|
|
123
|
+
const context = requireBrowserSessionExecutionContext();
|
|
114
124
|
const computer = runtimeComputerInteractionTargetAuthority();
|
|
125
|
+
if (!context.repoId) return 0;
|
|
115
126
|
if (computer.compatibilityMigrationMarker(context.controllerHome, BROWSER_SESSION_COMPUTER_MIGRATION_ID, context.repoId)) {
|
|
116
127
|
cleanupLegacyBrowserSessionJson(context.controllerHome, context.repoId, repoRoot);
|
|
117
128
|
return 0;
|
|
@@ -146,8 +157,10 @@ export function ensureBrowserSessionsMigratedToComputer(repoRoot: string): numbe
|
|
|
146
157
|
}
|
|
147
158
|
|
|
148
159
|
/** Move legacy provider files out of the repository and retire the old path after migration. */
|
|
149
|
-
export function ensureBrowserStateInControllerHome(controllerHome: string, repoId: string, repoRoot: string): string {
|
|
150
|
-
const targetRoot =
|
|
160
|
+
export function ensureBrowserStateInControllerHome(controllerHome: string, repoId: string | undefined, repoRoot: string): string {
|
|
161
|
+
const targetRoot = repoId
|
|
162
|
+
? join(controllerHome, 'repositories', repoId, 'browser')
|
|
163
|
+
: join(controllerHome, 'browser');
|
|
151
164
|
const compatibilityParent = join(repoRoot, '.forge');
|
|
152
165
|
const compatibilityRoot = join(compatibilityParent, 'browser');
|
|
153
166
|
mkdirSync(targetRoot, { recursive: true });
|
|
@@ -178,50 +191,25 @@ export function ensureBrowserStateInControllerHome(controllerHome: string, repoI
|
|
|
178
191
|
/**
|
|
179
192
|
* Browser semantic identity belongs to Computer SurfaceTarget authority. Provider
|
|
180
193
|
* working state (profiles, screenshots, downloads, diagnostics) remains
|
|
181
|
-
* repository-scoped under Controller Home.
|
|
182
|
-
*
|
|
194
|
+
* repository-scoped under Controller Home. Session identity has no standalone
|
|
195
|
+
* repository-local fallback; callers must supply Controller execution context.
|
|
183
196
|
*/
|
|
184
197
|
export function browserStateDir(
|
|
185
198
|
repoRoot: string,
|
|
186
199
|
name: 'sessions' | 'screenshots' | 'profiles' | 'downloads' | 'diagnostics',
|
|
187
200
|
): string {
|
|
188
201
|
const context = currentRuntimeBrowserSessionExecutionContext();
|
|
202
|
+
if (name === 'sessions') {
|
|
203
|
+
const sessionContext = context ?? requireBrowserSessionExecutionContext();
|
|
204
|
+
return join(ensureBrowserStateInControllerHome(sessionContext.controllerHome, sessionContext.repoId, repoRoot), name);
|
|
205
|
+
}
|
|
189
206
|
return context
|
|
190
207
|
? join(ensureBrowserStateInControllerHome(context.controllerHome, context.repoId, repoRoot), name)
|
|
191
208
|
: join(repoRoot, BROWSER_STATE_ROOT, name);
|
|
192
209
|
}
|
|
193
210
|
|
|
194
|
-
function sessionPath(repoRoot: string, sessionId: string): string {
|
|
195
|
-
return join(browserStateDir(repoRoot, 'sessions'), `${sessionId.replace(/[^a-zA-Z0-9_-]/g, '_')}.json`);
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
function readLegacyBrowserSessionJson(path: string): BrowserSessionState | undefined {
|
|
199
|
-
let raw: string;
|
|
200
|
-
try {
|
|
201
|
-
raw = readFileSync(path, 'utf-8');
|
|
202
|
-
} catch (error) {
|
|
203
|
-
if ((error as NodeJS.ErrnoException)?.code === 'ENOENT') return undefined;
|
|
204
|
-
throw new AssistantPluginError('PLUGIN_BROWSER_SESSION_STATE_READ_FAILED', 'Saved browser session metadata could not be read.', {
|
|
205
|
-
retryable: true,
|
|
206
|
-
details: { fileName: basename(path), cause: error instanceof Error ? error.message : String(error) },
|
|
207
|
-
});
|
|
208
|
-
}
|
|
209
|
-
try {
|
|
210
|
-
return JSON.parse(raw) as BrowserSessionState;
|
|
211
|
-
} catch (error) {
|
|
212
|
-
throw new AssistantPluginError('PLUGIN_BROWSER_SESSION_STATE_CORRUPT', 'Saved browser session metadata is malformed; refusing to treat corrupt state as a missing session.', {
|
|
213
|
-
retryable: false,
|
|
214
|
-
details: { fileName: basename(path), cause: error instanceof Error ? error.message : String(error) },
|
|
215
|
-
});
|
|
216
|
-
}
|
|
217
|
-
}
|
|
218
|
-
|
|
219
211
|
export function saveBrowserSession(repoRoot: string, session: BrowserSessionState): BrowserSessionState {
|
|
220
|
-
const context =
|
|
221
|
-
if (!context) {
|
|
222
|
-
writeJsonAtomic(sessionPath(repoRoot, session.sessionId), session);
|
|
223
|
-
return session;
|
|
224
|
-
}
|
|
212
|
+
const context = requireBrowserSessionExecutionContext();
|
|
225
213
|
ensureBrowserSessionsMigratedToComputer(repoRoot);
|
|
226
214
|
const computer = runtimeComputerInteractionTargetAuthority();
|
|
227
215
|
const binding = surfaceProviderBinding(session);
|
|
@@ -235,7 +223,8 @@ export function saveBrowserSession(repoRoot: string, session: BrowserSessionStat
|
|
|
235
223
|
if (!existing) {
|
|
236
224
|
existing = computer.upsertSurface(context.controllerHome, surfaceInput(session, {
|
|
237
225
|
aliases: [session.sessionId],
|
|
238
|
-
repositoryIds: [context.repoId],
|
|
226
|
+
repositoryIds: context.repoId ? [context.repoId] : [],
|
|
227
|
+
visibility: context.repoId ? undefined : 'controller',
|
|
239
228
|
includeCompatibility: false,
|
|
240
229
|
reactivate: true,
|
|
241
230
|
})).target;
|
|
@@ -248,7 +237,8 @@ export function saveBrowserSession(repoRoot: string, session: BrowserSessionStat
|
|
|
248
237
|
if (normalized.browser?.sessionResume) normalized.browser.sessionResume.sessionId = canonicalSessionId;
|
|
249
238
|
const saved = computer.upsertSurface(context.controllerHome, surfaceInput(normalized, {
|
|
250
239
|
aliases: [session.sessionId, canonicalSessionId],
|
|
251
|
-
repositoryIds: [context.repoId],
|
|
240
|
+
repositoryIds: context.repoId ? [context.repoId] : [],
|
|
241
|
+
visibility: context.repoId ? undefined : 'controller',
|
|
252
242
|
reactivate: true,
|
|
253
243
|
}));
|
|
254
244
|
return browserSessionFromSurface(saved.target) ?? normalized;
|
|
@@ -256,49 +246,29 @@ export function saveBrowserSession(repoRoot: string, session: BrowserSessionStat
|
|
|
256
246
|
|
|
257
247
|
export function findBrowserSession(repoRoot: string, sessionId?: string): BrowserSessionState | undefined {
|
|
258
248
|
if (!sessionId) return undefined;
|
|
259
|
-
const context =
|
|
260
|
-
if (!context) return readLegacyBrowserSessionJson(sessionPath(repoRoot, sessionId));
|
|
249
|
+
const context = requireBrowserSessionExecutionContext();
|
|
261
250
|
ensureBrowserSessionsMigratedToComputer(repoRoot);
|
|
262
251
|
const target = runtimeComputerInteractionTargetAuthority().findSurfaceByAlias(context.controllerHome, sessionId, context.repoId);
|
|
263
|
-
|
|
252
|
+
if (!target || (!context.repoId && target.visibility !== 'controller')) return undefined;
|
|
253
|
+
return browserSessionFromSurface(target);
|
|
264
254
|
}
|
|
265
255
|
|
|
266
256
|
export function listSavedBrowserSessions(repoRoot: string): BrowserSessionState[] {
|
|
267
|
-
const context =
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
}
|
|
275
|
-
const root = browserStateDir(repoRoot, 'sessions');
|
|
276
|
-
let names: string[];
|
|
277
|
-
try {
|
|
278
|
-
names = readdirSync(root);
|
|
279
|
-
} catch (error) {
|
|
280
|
-
if ((error as NodeJS.ErrnoException)?.code === 'ENOENT') return [];
|
|
281
|
-
throw new AssistantPluginError('PLUGIN_BROWSER_SESSION_STATE_READ_FAILED', 'Saved browser session directory could not be read.', {
|
|
282
|
-
retryable: true,
|
|
283
|
-
details: { cause: error instanceof Error ? error.message : String(error) },
|
|
284
|
-
});
|
|
285
|
-
}
|
|
286
|
-
return names
|
|
287
|
-
.filter((name) => name.endsWith('.json'))
|
|
288
|
-
.map((name) => readLegacyBrowserSessionJson(join(root, name)))
|
|
289
|
-
.filter((session): session is BrowserSessionState => Boolean(session));
|
|
257
|
+
const context = requireBrowserSessionExecutionContext();
|
|
258
|
+
ensureBrowserSessionsMigratedToComputer(repoRoot);
|
|
259
|
+
return runtimeComputerInteractionTargetAuthority().listAllSurfaces(context.controllerHome, { repoId: context.repoId })
|
|
260
|
+
.filter((target) => Boolean(context.repoId) || target.visibility === 'controller')
|
|
261
|
+
.map(browserSessionFromSurface)
|
|
262
|
+
.filter((session): session is BrowserSessionState => Boolean(session))
|
|
263
|
+
.sort((left, right) => right.updatedAt.localeCompare(left.updatedAt) || left.sessionId.localeCompare(right.sessionId));
|
|
290
264
|
}
|
|
291
265
|
|
|
292
266
|
export function removeBrowserSession(repoRoot: string, sessionId: string): void {
|
|
293
|
-
const context =
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
if (target) computer.tombstoneSurface(context.controllerHome, target.targetId);
|
|
299
|
-
return;
|
|
300
|
-
}
|
|
301
|
-
rmSync(sessionPath(repoRoot, sessionId), { force: true });
|
|
267
|
+
const context = requireBrowserSessionExecutionContext();
|
|
268
|
+
ensureBrowserSessionsMigratedToComputer(repoRoot);
|
|
269
|
+
const computer = runtimeComputerInteractionTargetAuthority();
|
|
270
|
+
const target = computer.findSurfaceByAlias(context.controllerHome, sessionId, context.repoId);
|
|
271
|
+
if (target && (context.repoId || target.visibility === 'controller')) computer.tombstoneSurface(context.controllerHome, target.targetId);
|
|
302
272
|
}
|
|
303
273
|
|
|
304
274
|
export function loadBrowserSession(repoRoot: string, sessionId?: string): BrowserSessionState | undefined {
|
|
@@ -1,5 +1,13 @@
|
|
|
1
|
+
import {
|
|
2
|
+
findActiveCanonicalGrant,
|
|
3
|
+
listCanonicalGrants,
|
|
4
|
+
reconcileCanonicalGrants,
|
|
5
|
+
recordCanonicalGrant,
|
|
6
|
+
revokeCanonicalGrant,
|
|
7
|
+
type Grant,
|
|
8
|
+
} from '../../../packages/kernel/identity/api/index';
|
|
1
9
|
import { randomUUID } from 'crypto';
|
|
2
|
-
import { existsSync,
|
|
10
|
+
import { existsSync, renameSync } from 'fs';
|
|
3
11
|
import { join } from 'path';
|
|
4
12
|
import { controllerSystemRoot } from '../../cli/repositories/controller-home';
|
|
5
13
|
import { ControllerLockContentionError, withControllerLock } from '../../cli/repositories/locks';
|
|
@@ -31,7 +39,7 @@ export interface PluginCapabilityAuthorizationGrant {
|
|
|
31
39
|
schemaVersion: 1;
|
|
32
40
|
grantId: string;
|
|
33
41
|
ownerScope: string;
|
|
34
|
-
repoId
|
|
42
|
+
repoId?: string;
|
|
35
43
|
pluginId: string;
|
|
36
44
|
capabilityId: string;
|
|
37
45
|
target: AssistantPluginAuthorizationTarget;
|
|
@@ -51,7 +59,7 @@ interface PluginCapabilityAuthorizationGrantStore {
|
|
|
51
59
|
|
|
52
60
|
export interface PluginCapabilityAuthorizationQuery {
|
|
53
61
|
ownerScope: string;
|
|
54
|
-
repoId
|
|
62
|
+
repoId?: string;
|
|
55
63
|
pluginId: string;
|
|
56
64
|
capabilityId: string;
|
|
57
65
|
target: AssistantPluginAuthorizationTarget;
|
|
@@ -73,12 +81,19 @@ export interface RevokePluginCapabilityAuthorizationInput {
|
|
|
73
81
|
now?: Date;
|
|
74
82
|
}
|
|
75
83
|
|
|
76
|
-
|
|
77
|
-
readonly
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
84
|
+
export interface ReconcilePluginCapabilityAuthorizationsInput {
|
|
85
|
+
retiredOwnerScopes?: readonly string[];
|
|
86
|
+
now?: Date;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
export interface ReconcilePluginCapabilityAuthorizationsResult {
|
|
90
|
+
removedRetiredOwner: number;
|
|
91
|
+
removedRevoked: number;
|
|
92
|
+
removedExpired: number;
|
|
93
|
+
removedTotal: number;
|
|
94
|
+
remaining: number;
|
|
95
|
+
changed: boolean;
|
|
96
|
+
}
|
|
82
97
|
|
|
83
98
|
const GENERIC_PLUGIN_AUTHORIZATION_ACTORS = new Set(['', 'anonymous', 'plugin_action_execute']);
|
|
84
99
|
|
|
@@ -156,7 +171,10 @@ function validatePersistedGrant(value: unknown, index: number): PluginCapability
|
|
|
156
171
|
schemaVersion: 1,
|
|
157
172
|
grantId: string('grantId'),
|
|
158
173
|
ownerScope: string('ownerScope'),
|
|
159
|
-
repoId
|
|
174
|
+
// Pre-canonical plugin grants could omit repoId for controller/account targets.
|
|
175
|
+
// Normalize that omission once during the one-way migration; authorization
|
|
176
|
+
// against the canonical Grant store is exact after this point.
|
|
177
|
+
repoId: typeof record.repoId === 'string' && record.repoId.trim() ? record.repoId.trim() : 'controller:global',
|
|
160
178
|
pluginId: string('pluginId'),
|
|
161
179
|
capabilityId: string('capabilityId'),
|
|
162
180
|
target: normalizeTarget({
|
|
@@ -180,6 +198,41 @@ export function pluginCapabilityAuthorizationGrantStorePath(controllerHome: stri
|
|
|
180
198
|
return join(controllerSystemRoot(controllerHome), 'plugin-capability-authorizations', 'grants.json');
|
|
181
199
|
}
|
|
182
200
|
|
|
201
|
+
function legacyPluginGrantMigrationMarkerPath(controllerHome: string): string {
|
|
202
|
+
return join(controllerSystemRoot(controllerHome), 'plugin-capability-authorizations', 'migration.json');
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
/**
|
|
206
|
+
* Durable proof that this Controller Home already ran the one-way migration, so
|
|
207
|
+
* authorization reads stop consulting the legacy file at all.
|
|
208
|
+
*/
|
|
209
|
+
interface LegacyPluginGrantMigrationMarker {
|
|
210
|
+
schemaVersion: 1;
|
|
211
|
+
migratedAt: string;
|
|
212
|
+
legacyGrantCount: number;
|
|
213
|
+
canonicalGrantCount: number;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
function readLegacyPluginGrantMigrationMarker(controllerHome: string): LegacyPluginGrantMigrationMarker | undefined {
|
|
217
|
+
const path = legacyPluginGrantMigrationMarkerPath(controllerHome);
|
|
218
|
+
if (!existsSync(path)) return undefined;
|
|
219
|
+
try {
|
|
220
|
+
const raw = readJsonFile<Record<string, unknown>>(path);
|
|
221
|
+
if (raw?.schemaVersion !== 1
|
|
222
|
+
|| typeof raw.migratedAt !== 'string'
|
|
223
|
+
|| typeof raw.legacyGrantCount !== 'number'
|
|
224
|
+
|| typeof raw.canonicalGrantCount !== 'number') {
|
|
225
|
+
throw new Error('migration marker schema is invalid');
|
|
226
|
+
}
|
|
227
|
+
return raw as unknown as LegacyPluginGrantMigrationMarker;
|
|
228
|
+
} catch (error) {
|
|
229
|
+
throw new PluginCapabilityAuthorizationGrantError(
|
|
230
|
+
'PLUGIN_CAPABILITY_GRANT_STORE_CORRUPT',
|
|
231
|
+
`Plugin capability authorization migration marker is corrupt: ${error instanceof Error ? error.message : String(error)}`,
|
|
232
|
+
);
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
|
|
183
236
|
function loadStore(controllerHome: string): PluginCapabilityAuthorizationGrantStore {
|
|
184
237
|
const path = pluginCapabilityAuthorizationGrantStorePath(controllerHome);
|
|
185
238
|
if (!existsSync(path)) return { schemaVersion: 1, grants: [] };
|
|
@@ -197,21 +250,123 @@ function loadStore(controllerHome: string): PluginCapabilityAuthorizationGrantSt
|
|
|
197
250
|
}
|
|
198
251
|
}
|
|
199
252
|
|
|
200
|
-
function
|
|
201
|
-
const
|
|
202
|
-
|
|
203
|
-
|
|
253
|
+
function pluginMetadataFromCanonicalGrant(grant: Grant): { pluginId: string; capabilityId: string } | undefined {
|
|
254
|
+
const constraints = grant.constraints;
|
|
255
|
+
if (!constraints || constraints.kind !== 'plugin_capability_authorization') return undefined;
|
|
256
|
+
const pluginId = typeof constraints.pluginId === 'string' ? constraints.pluginId.trim() : '';
|
|
257
|
+
const capabilityId = typeof constraints.capabilityId === 'string' ? constraints.capabilityId.trim() : '';
|
|
258
|
+
return pluginId && capabilityId ? { pluginId, capabilityId } : undefined;
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
function pluginGrantFromCanonical(
|
|
262
|
+
grant: Grant,
|
|
263
|
+
fallback?: { pluginId: string; capabilityId: string; repoId?: string; target?: AssistantPluginAuthorizationTarget },
|
|
264
|
+
): PluginCapabilityAuthorizationGrant | undefined {
|
|
265
|
+
const metadata = pluginMetadataFromCanonicalGrant(grant)
|
|
266
|
+
?? (fallback ? { pluginId: fallback.pluginId, capabilityId: fallback.capabilityId } : undefined);
|
|
267
|
+
if (!metadata || !grant.target) return undefined;
|
|
268
|
+
if (grant.riskCeiling === 'destructive') return undefined;
|
|
269
|
+
const ownerScope = grant.ownerScope?.trim() || grant.principalId.trim();
|
|
270
|
+
if (!ownerScope) return undefined;
|
|
271
|
+
const target: AssistantPluginAuthorizationTarget = {
|
|
272
|
+
kind: grant.target.kind,
|
|
273
|
+
id: grant.target.id,
|
|
274
|
+
...(grant.target.identityFingerprint ? { identityFingerprint: grant.target.identityFingerprint } : fallback?.target?.identityFingerprint ? { identityFingerprint: fallback.target.identityFingerprint } : {}),
|
|
275
|
+
};
|
|
276
|
+
return {
|
|
277
|
+
schemaVersion: 1,
|
|
278
|
+
grantId: grant.grantId,
|
|
279
|
+
ownerScope,
|
|
280
|
+
repoId: grant.target.repoId ?? fallback?.repoId ?? 'controller:global',
|
|
281
|
+
pluginId: metadata.pluginId,
|
|
282
|
+
capabilityId: metadata.capabilityId,
|
|
283
|
+
target,
|
|
284
|
+
scopes: [...(grant.scopes ?? [])],
|
|
285
|
+
riskCeiling: grant.riskCeiling ?? 'readonly',
|
|
286
|
+
createdAt: grant.createdAt,
|
|
287
|
+
updatedAt: grant.updatedAt,
|
|
288
|
+
expiresAt: grant.expiresAt,
|
|
289
|
+
...(grant.revokedAt ? { revokedAt: grant.revokedAt } : {}),
|
|
290
|
+
...(grant.revokedReason ? { revokedReason: grant.revokedReason } : {}),
|
|
291
|
+
};
|
|
204
292
|
}
|
|
205
293
|
|
|
206
|
-
function
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
294
|
+
function recordCanonicalPluginGrant(
|
|
295
|
+
controllerHome: string,
|
|
296
|
+
grant: PluginCapabilityAuthorizationGrant,
|
|
297
|
+
now?: Date,
|
|
298
|
+
): PluginCapabilityAuthorizationGrant {
|
|
299
|
+
const expiresInMinutes = Math.max(1, Math.ceil((Date.parse(grant.expiresAt) - (now ?? new Date()).getTime()) / 60_000));
|
|
300
|
+
const canonical = recordCanonicalGrant(controllerHome, {
|
|
301
|
+
grantId: grant.grantId,
|
|
302
|
+
principalId: grant.ownerScope,
|
|
303
|
+
ownerScope: grant.ownerScope,
|
|
304
|
+
capabilities: [`${grant.pluginId}:${grant.capabilityId}`, grant.capabilityId],
|
|
305
|
+
target: {
|
|
306
|
+
kind: grant.target.kind,
|
|
307
|
+
id: grant.target.id,
|
|
308
|
+
repoId: grant.repoId,
|
|
309
|
+
...(grant.target.identityFingerprint ? { identityFingerprint: grant.target.identityFingerprint } : {}),
|
|
310
|
+
},
|
|
311
|
+
scopes: grant.scopes,
|
|
312
|
+
riskCeiling: grant.riskCeiling,
|
|
313
|
+
constraints: { kind: 'plugin_capability_authorization', pluginId: grant.pluginId, capabilityId: grant.capabilityId },
|
|
314
|
+
expiresInMinutes,
|
|
315
|
+
now,
|
|
316
|
+
});
|
|
317
|
+
return pluginGrantFromCanonical(canonical, grant)!;
|
|
210
318
|
}
|
|
211
319
|
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
320
|
+
/**
|
|
321
|
+
* One-way migration input. The legacy plugin grant file is read-only history:
|
|
322
|
+
* every still-authorizable legacy grant is copied into the canonical Grant
|
|
323
|
+
* authority exactly once, and this module never writes the legacy file again.
|
|
324
|
+
* A corrupt migration input still fails closed so un-migrated grants cannot be
|
|
325
|
+
* silently dropped.
|
|
326
|
+
*
|
|
327
|
+
* Removal trigger: once a released Runtime baseline has shipped with the
|
|
328
|
+
* `migration.json` marker (so every install has migrated at least once), delete
|
|
329
|
+
* this migration, `loadStore`/`validatePersistedGrant`, the legacy path getter
|
|
330
|
+
* and the PLUGIN_CAPABILITY_GRANT_STORE_CORRUPT error code in the same slice.
|
|
331
|
+
* The archived `grants.json.migrated-*` file is recoverable history, not input.
|
|
332
|
+
*/
|
|
333
|
+
function migrateLegacyPluginCapabilityGrants(controllerHome: string, at = new Date()): void {
|
|
334
|
+
if (readLegacyPluginGrantMigrationMarker(controllerHome)) return;
|
|
335
|
+
const legacyGrants = loadStore(controllerHome).grants;
|
|
336
|
+
const canonicalById = new Map(listCanonicalGrants(controllerHome).map((grant) => [grant.grantId, grant]));
|
|
337
|
+
const atMs = at.getTime();
|
|
338
|
+
for (const grant of legacyGrants) {
|
|
339
|
+
if (grant.revokedAt) continue;
|
|
340
|
+
if (Date.parse(grant.expiresAt) <= atMs) continue;
|
|
341
|
+
const existing = canonicalById.get(grant.grantId);
|
|
342
|
+
if (existing) {
|
|
343
|
+
// A canonical row written before plugin metadata existed cannot be projected
|
|
344
|
+
// back into a plugin grant. Repair it in place instead of leaving a live grant
|
|
345
|
+
// that neither list nor by-id resolution can see.
|
|
346
|
+
if (existing.revokedAt || pluginMetadataFromCanonicalGrant(existing)) continue;
|
|
347
|
+
recordCanonicalPluginGrant(controllerHome, grant, new Date(grant.createdAt));
|
|
348
|
+
continue;
|
|
349
|
+
}
|
|
350
|
+
recordCanonicalPluginGrant(controllerHome, grant, new Date(grant.createdAt));
|
|
351
|
+
canonicalById.set(grant.grantId, { grantId: grant.grantId } as Grant);
|
|
352
|
+
}
|
|
353
|
+
// The migration is complete for this Controller Home: prove it durably, then
|
|
354
|
+
// move the legacy file aside so no authorization read can ever depend on it
|
|
355
|
+
// again. The archive is recoverable; a failed rename leaves an inert file.
|
|
356
|
+
writeJsonAtomic(legacyPluginGrantMigrationMarkerPath(controllerHome), {
|
|
357
|
+
schemaVersion: 1,
|
|
358
|
+
migratedAt: at.toISOString(),
|
|
359
|
+
legacyGrantCount: legacyGrants.length,
|
|
360
|
+
canonicalGrantCount: listCanonicalGrants(controllerHome).length,
|
|
361
|
+
} satisfies LegacyPluginGrantMigrationMarker);
|
|
362
|
+
const legacyPath = pluginCapabilityAuthorizationGrantStorePath(controllerHome);
|
|
363
|
+
if (existsSync(legacyPath)) {
|
|
364
|
+
try {
|
|
365
|
+
renameSync(legacyPath, `${legacyPath}.migrated-${at.getTime()}`);
|
|
366
|
+
} catch {
|
|
367
|
+
// Inert history; the marker already prevents any further legacy read.
|
|
368
|
+
}
|
|
369
|
+
}
|
|
215
370
|
}
|
|
216
371
|
|
|
217
372
|
export function findActivePluginCapabilityAuthorization(
|
|
@@ -220,22 +375,21 @@ export function findActivePluginCapabilityAuthorization(
|
|
|
220
375
|
): PluginCapabilityAuthorizationGrant | undefined {
|
|
221
376
|
if (query.risk === 'destructive') return undefined;
|
|
222
377
|
const ownerScope = required(query.ownerScope, 'ownerScope');
|
|
223
|
-
const repoId =
|
|
378
|
+
const repoId = (query.repoId?.trim()) || 'controller:global';
|
|
224
379
|
const pluginId = required(query.pluginId, 'pluginId');
|
|
225
380
|
const capabilityId = required(query.capabilityId, 'capabilityId');
|
|
226
381
|
const target = normalizeTarget(query.target);
|
|
227
382
|
const scopes = normalizeScopes(query.scopes);
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
.sort((left, right) => Date.parse(right.updatedAt) - Date.parse(left.updatedAt))[0];
|
|
383
|
+
migrateLegacyPluginCapabilityGrants(controllerHome, query.at ?? new Date());
|
|
384
|
+
const canonical = findActiveCanonicalGrant(controllerHome, {
|
|
385
|
+
ownerScope,
|
|
386
|
+
capability: `${pluginId}:${capabilityId}`,
|
|
387
|
+
target: { kind: target.kind, id: target.id, repoId, ...(target.identityFingerprint ? { identityFingerprint: target.identityFingerprint } : {}) },
|
|
388
|
+
scopes,
|
|
389
|
+
risk: query.risk,
|
|
390
|
+
at: query.at,
|
|
391
|
+
});
|
|
392
|
+
return canonical ? pluginGrantFromCanonical(canonical, { pluginId, capabilityId, repoId, target }) : undefined;
|
|
239
393
|
}
|
|
240
394
|
|
|
241
395
|
/**
|
|
@@ -250,9 +404,12 @@ export function findActivePluginCapabilityAuthorizationById(
|
|
|
250
404
|
): PluginCapabilityAuthorizationGrant | undefined {
|
|
251
405
|
const normalizedGrantId = required(grantId, 'grantId');
|
|
252
406
|
const atMs = at.getTime();
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
407
|
+
migrateLegacyPluginCapabilityGrants(controllerHome, at);
|
|
408
|
+
const canonical = listCanonicalGrants(controllerHome).find((entry) => entry.grantId === normalizedGrantId);
|
|
409
|
+
if (canonical && !canonical.revokedAt && Date.parse(canonical.expiresAt) > atMs) {
|
|
410
|
+
return pluginGrantFromCanonical(canonical);
|
|
411
|
+
}
|
|
412
|
+
return undefined;
|
|
256
413
|
}
|
|
257
414
|
|
|
258
415
|
export function recordPluginCapabilityAuthorization(
|
|
@@ -267,7 +424,7 @@ export function recordPluginCapabilityAuthorization(
|
|
|
267
424
|
}
|
|
268
425
|
const now = input.now ?? new Date();
|
|
269
426
|
const ownerScope = required(input.ownerScope, 'ownerScope');
|
|
270
|
-
const repoId =
|
|
427
|
+
const repoId = (input.repoId?.trim()) || 'controller:global';
|
|
271
428
|
const pluginId = required(input.pluginId, 'pluginId');
|
|
272
429
|
const capabilityId = required(input.capabilityId, 'capabilityId');
|
|
273
430
|
const target = normalizeTarget(input.target);
|
|
@@ -278,6 +435,7 @@ export function recordPluginCapabilityAuthorization(
|
|
|
278
435
|
}
|
|
279
436
|
const expiresInMinutes = Math.min(Math.max(1, Math.trunc(rawMinutes)), MAX_PLUGIN_CAPABILITY_GRANT_MINUTES);
|
|
280
437
|
const timestamp = now.toISOString();
|
|
438
|
+
migrateLegacyPluginCapabilityGrants(controllerHome, now);
|
|
281
439
|
const grant: PluginCapabilityAuthorizationGrant = {
|
|
282
440
|
schemaVersion: 1,
|
|
283
441
|
grantId: `plugin-grant-${randomUUID()}`,
|
|
@@ -298,16 +456,19 @@ export function recordPluginCapabilityAuthorization(
|
|
|
298
456
|
{ scope: 'global', resource: 'plugin-capability-authorization-grants' },
|
|
299
457
|
`plugin-capability-grant:${ownerScope}`,
|
|
300
458
|
() => {
|
|
301
|
-
const
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
459
|
+
const canonicalGrant = recordCanonicalGrant(controllerHome, {
|
|
460
|
+
grantId: grant.grantId,
|
|
461
|
+
principalId: grant.ownerScope,
|
|
462
|
+
ownerScope: grant.ownerScope,
|
|
463
|
+
capabilities: [`${grant.pluginId}:${grant.capabilityId}`, grant.capabilityId],
|
|
464
|
+
target: { kind: grant.target.kind, id: grant.target.id, repoId: grant.repoId, ...(grant.target.identityFingerprint ? { identityFingerprint: grant.target.identityFingerprint } : {}) },
|
|
465
|
+
scopes: grant.scopes,
|
|
466
|
+
riskCeiling: grant.riskCeiling,
|
|
467
|
+
constraints: { kind: 'plugin_capability_authorization', pluginId: grant.pluginId, capabilityId: grant.capabilityId },
|
|
468
|
+
expiresInMinutes,
|
|
469
|
+
now,
|
|
470
|
+
});
|
|
471
|
+
return pluginGrantFromCanonical(canonicalGrant, grant)!;
|
|
311
472
|
},
|
|
312
473
|
5_000,
|
|
313
474
|
);
|
|
@@ -333,22 +494,56 @@ export function revokePluginCapabilityAuthorization(
|
|
|
333
494
|
{ scope: 'global', resource: 'plugin-capability-authorization-grants' },
|
|
334
495
|
`plugin-capability-revoke:${ownerScope}`,
|
|
335
496
|
() => {
|
|
336
|
-
const
|
|
337
|
-
|
|
338
|
-
if (index < 0) throw new PluginCapabilityAuthorizationGrantError('PLUGIN_CAPABILITY_GRANT_NOT_FOUND', `Grant ${grantId} was not found.`);
|
|
339
|
-
const current = store.grants[index]!;
|
|
497
|
+
const current = findActivePluginCapabilityAuthorizationById(controllerHome, grantId, now);
|
|
498
|
+
if (!current) throw new PluginCapabilityAuthorizationGrantError('PLUGIN_CAPABILITY_GRANT_NOT_FOUND', `Grant ${grantId} was not found.`);
|
|
340
499
|
if (current.ownerScope !== ownerScope) {
|
|
341
500
|
throw new PluginCapabilityAuthorizationGrantError('PLUGIN_CAPABILITY_GRANT_OWNER_MISMATCH', `Grant ${grantId} belongs to another owner scope.`);
|
|
342
501
|
}
|
|
343
|
-
const
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
502
|
+
const canonical = revokeCanonicalGrant(controllerHome, { grantId, ownerScope, reason, now });
|
|
503
|
+
return pluginGrantFromCanonical(canonical, current)!;
|
|
504
|
+
},
|
|
505
|
+
5_000,
|
|
506
|
+
);
|
|
507
|
+
} catch (error) {
|
|
508
|
+
if (error instanceof ControllerLockContentionError) {
|
|
509
|
+
throw new PluginCapabilityAuthorizationGrantError('PLUGIN_CAPABILITY_GRANT_STORE_BUSY', error.message);
|
|
510
|
+
}
|
|
511
|
+
throw error;
|
|
512
|
+
}
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
export function reconcilePluginCapabilityAuthorizations(
|
|
516
|
+
controllerHome: string,
|
|
517
|
+
input: ReconcilePluginCapabilityAuthorizationsInput = {},
|
|
518
|
+
): ReconcilePluginCapabilityAuthorizationsResult {
|
|
519
|
+
const retiredOwnerScopes = new Set(
|
|
520
|
+
(input.retiredOwnerScopes ?? [])
|
|
521
|
+
.map((ownerScope) => required(ownerScope, 'retiredOwnerScopes[]')),
|
|
522
|
+
);
|
|
523
|
+
const nowMs = (input.now ?? new Date()).getTime();
|
|
524
|
+
try {
|
|
525
|
+
return withControllerLock(
|
|
526
|
+
controllerHome,
|
|
527
|
+
{ scope: 'global', resource: 'plugin-capability-authorization-grants' },
|
|
528
|
+
'plugin-capability-reconcile',
|
|
529
|
+
() => {
|
|
530
|
+
void nowMs;
|
|
531
|
+
migrateLegacyPluginCapabilityGrants(controllerHome, input.now ?? new Date());
|
|
532
|
+
const canonical = reconcileCanonicalGrants(controllerHome, {
|
|
533
|
+
retiredOwnerScopes: [...retiredOwnerScopes],
|
|
534
|
+
now: input.now,
|
|
535
|
+
});
|
|
536
|
+
const grants = listCanonicalGrants(controllerHome)
|
|
537
|
+
.map((grant) => pluginGrantFromCanonical(grant))
|
|
538
|
+
.filter((grant): grant is PluginCapabilityAuthorizationGrant => Boolean(grant));
|
|
539
|
+
return {
|
|
540
|
+
removedRetiredOwner: canonical.removedRetiredOwner,
|
|
541
|
+
removedRevoked: canonical.removedRevoked,
|
|
542
|
+
removedExpired: canonical.removedExpired,
|
|
543
|
+
removedTotal: canonical.removedTotal,
|
|
544
|
+
remaining: grants.length,
|
|
545
|
+
changed: canonical.changed,
|
|
348
546
|
};
|
|
349
|
-
store.grants[index] = revoked;
|
|
350
|
-
saveStore(controllerHome, store);
|
|
351
|
-
return revoked;
|
|
352
547
|
},
|
|
353
548
|
5_000,
|
|
354
549
|
);
|
|
@@ -364,8 +559,9 @@ export function listPluginCapabilityAuthorizations(
|
|
|
364
559
|
controllerHome: string,
|
|
365
560
|
ownerScope?: string,
|
|
366
561
|
): PluginCapabilityAuthorizationGrant[] {
|
|
562
|
+
migrateLegacyPluginCapabilityGrants(controllerHome);
|
|
367
563
|
const normalizedOwner = ownerScope?.trim();
|
|
368
|
-
return
|
|
369
|
-
.
|
|
370
|
-
.
|
|
564
|
+
return listCanonicalGrants(controllerHome, normalizedOwner ? { ownerScope: normalizedOwner } : undefined)
|
|
565
|
+
.map((grant) => pluginGrantFromCanonical(grant))
|
|
566
|
+
.filter((grant): grant is PluginCapabilityAuthorizationGrant => Boolean(grant));
|
|
371
567
|
}
|