@moretea-labs/forge 1.8.0 → 1.8.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +70 -7
- package/CHANGELOG.md +14 -0
- package/CLAUDE.md +17 -2
- package/CONTRIBUTING.md +3 -2
- package/THIRD_PARTY_NOTICES.md +1 -1
- package/adapters/chatgpt/browser-delivery-host.ts +7 -1
- package/adapters/chatgpt/browser-delivery-runtime.ts +529 -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 +228 -1
- package/adapters/chatgpt/work-conversation-binding-store.ts +79 -53
- package/adapters/computer/chatgpt-extension-target.ts +463 -0
- package/adapters/computer/chatgpt-target-router.ts +103 -0
- package/adapters/computer/chrome-extension/background.js +385 -0
- package/adapters/computer/chrome-extension/content.js +378 -0
- package/adapters/computer/chrome-extension/core.js +24 -0
- package/adapters/computer/chrome-extension/manifest.json +30 -0
- package/adapters/computer/desktop-operator-discovery.ts +11 -31
- package/adapters/computer/interaction-target-authority.ts +142 -18
- package/adapters/mcp/auth.ts +0 -1
- package/adapters/mcp/instructions.ts +5 -4
- package/adapters/mcp/multi-repository.ts +3 -19
- package/adapters/mcp/oauth.ts +73 -0
- package/adapters/mcp/paths.ts +4 -1
- package/adapters/mcp/runtime-gateway/automation-receipt-adapter.ts +87 -0
- 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 +411 -73
- package/adapters/mcp/runtime-gateway/context-pack-sidecar.ts +91 -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 +8 -42
- package/adapters/mcp/runtime-gateway/gateway-execution-adapter.ts +2 -1
- package/adapters/mcp/runtime-gateway/plugin-adapter.ts +117 -45
- package/adapters/mcp/runtime-gateway/process-tools.ts +190 -22
- 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 +18 -504
- package/adapters/mcp/runtime-gateway/routing-policy.ts +499 -0
- package/adapters/mcp/runtime-gateway/runtime-observation-adapter.ts +14 -65
- package/adapters/mcp/runtime-gateway/runtime-readiness-observation.ts +218 -0
- package/adapters/mcp/runtime-gateway/runtime-tool-definitions.ts +113 -173
- package/adapters/mcp/runtime-gateway/runtime-tools.ts +15 -5
- package/adapters/mcp/runtime-gateway/scheduler-adapter.ts +1 -0
- package/adapters/mcp/runtime-gateway/shared-adapter.ts +20 -0
- package/adapters/mcp/runtime-gateway/status-inbox-adapter.ts +358 -266
- package/adapters/mcp/runtime-gateway/typescript-navigation-sidecar.ts +136 -0
- package/adapters/mcp/runtime-gateway/work-adapter.ts +261 -3122
- 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 +246 -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 +263 -0
- package/adapters/mcp/runtime-gateway/work-workflow-operations.ts +113 -0
- package/adapters/mcp/runtime-gateway/workflow-supervisor-adapter.ts +156 -0
- package/adapters/mcp/server.ts +67 -23
- package/adapters/mcp/setup.ts +1 -3
- package/adapters/mcp/tool-mapping/legacy-tool-service.ts +44 -170
- package/adapters/mcp/tool-mapping/post-finalize-work-attribution.ts +4 -9
- package/adapters/mcp/tool-mapping/repository-tools.ts +133 -142
- package/adapters/mcp/toolset-names.ts +5 -0
- package/adapters/mcp/toolset.ts +6 -5
- package/adapters/mcp/transports/http-observation.ts +365 -0
- package/adapters/mcp/transports/http.ts +154 -677
- 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/assets/plugin-registry.v1.json +6 -4
- package/assets/reference-configs/agentic-development-flow.md +25 -0
- package/assets/reference-configs/global-working-rules.md +19 -0
- package/assets/skill-version.json +2 -2
- package/docs/architecture/CURRENT.md +111 -41
- 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/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 +221 -0
- package/docs/architecture/decisions/20260919-autonomous-work-liveness.md +62 -0
- package/docs/architecture/decisions/20260924-thin-semantic-working-context.md +72 -0
- package/docs/architecture/decisions/20261001-supervisor-turn-authority.md +237 -0
- package/docs/architecture/decisions/20261005-forge-v3-desktop-client-boundary.md +77 -0
- package/docs/architecture/domains/verification.md +1 -0
- package/docs/architecture/domains/workflow-engine.md +6 -0
- package/docs/architecture/modules/controller-runtime/transport-lifecycle.md +1 -1
- package/docs/forge-plugin-management.md +2 -2
- package/docs/operations/controller-performance-and-502.md +17 -0
- package/docs/operations/controller-reliability-runbook.md +2 -2
- package/docs/operations/features.md +1 -1
- package/docs/operations/features.zh-CN.md +1 -1
- package/docs/operations/homebrew.md +2 -2
- package/docs/operations/mcp-tool-exposure.md +2 -0
- package/docs/operations/releasing.md +2 -0
- package/docs/operations/standalone-disaster-recovery.md +14 -6
- package/docs/wiki/Implementation.md +1 -1
- package/package.json +25 -14
- 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 +297 -71
- 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 +77 -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/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 +153 -133
- package/packages/kernel/work/api/index.ts +3 -2
- package/packages/kernel/work/application/work-service.ts +17 -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 +25 -63
- package/packages/kernel/work/domain/types.ts +57 -51
- package/packages/kernel/work/infrastructure/work-contract-store.ts +819 -728
- package/packages/kernel/work/ports/work-contract-store.ts +5 -2
- 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 +143 -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/canary-controller-semantic-wait.ts +12 -24
- package/scripts/check-mcp-compatibility.ts +48 -136
- package/scripts/check-runtime-architecture.mjs +622 -217
- package/scripts/forge-local-recovery-helper.mjs +93 -15
- package/scripts/lib/project-init-lib.sh +3 -0
- package/scripts/open-source-audit-allowlist.txt +1 -2
- package/scripts/run-bounded-command.mjs +5 -0
- package/scripts/run-governed-gate.ts +0 -1
- package/scripts/run-mobile-monitor-bridge.ts +0 -1
- package/scripts/smoke-control-plane-failure-domain.ts +94 -0
- package/scripts/smoke-mcp-http-runtime.ts +5 -0
- 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 +92 -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/verify-forge-runtime.sh +2 -1
- package/src/cli/agent-jobs/executor-health.ts +11 -34
- package/src/cli/agent-jobs/integration.ts +18 -49
- package/src/cli/agent-jobs/job-manager.ts +7 -3
- 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/recovery.ts +135 -121
- package/src/cli/commands/runtime.ts +3 -3
- 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 +4 -43
- package/src/cli/controller/completion-target.ts +3 -72
- package/src/cli/controller/context/source-materializer.ts +81 -100
- package/src/cli/controller/context-pack.ts +10 -8
- 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 +24 -51
- 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 +39 -1
- package/src/cli/editing/edit-session.ts +1 -7
- package/src/cli/local-bridge/console-automations.ts +18 -13
- package/src/cli/local-bridge/console-view-models.ts +3 -12
- package/src/cli/local-bridge/facade-api.ts +64 -191
- 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-executor.ts +29 -23
- package/src/cli/repositories/command-scope.ts +35 -16
- 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/registry.ts +77 -11
- package/src/cli/repositories/structured-git.ts +62 -2
- package/src/cli/repository/session-cache.ts +92 -6
- 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/semantic-navigation-contract.ts +9 -0
- package/src/runtime/context/semantic-navigation.ts +6 -34
- 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 +212 -9
- 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 +497 -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 +188 -109
- package/src/runtime/control-plane/execution/work-handle-store.ts +19 -43
- 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 +43 -27
- package/src/runtime/control-plane/execution/work-preparation-service.ts +126 -266
- 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 +173 -186
- package/src/runtime/control-plane/execution/work-validation-reconciler.ts +28 -84
- package/src/runtime/control-plane/execution/work-verification-service.ts +406 -50
- package/src/runtime/control-plane/execution/work-verification-snapshot.ts +5 -1
- package/src/runtime/control-plane/facade/capability-registry.ts +362 -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 +8 -8
- package/src/runtime/control-plane/generated-cache-retention.ts +97 -1
- 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 +239 -112
- package/src/runtime/control-plane/global-scheduler/reconciliation.ts +2 -1
- 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/launcher/chatgpt-round-continuation.ts +63 -300
- package/src/runtime/control-plane/launcher/chatgpt-work-continuation.ts +28 -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 +290 -21
- 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/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 +79 -27
- 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 +35 -2
- package/src/runtime/execution/process-runtime/store.ts +30 -2
- package/src/runtime/execution/process-runtime/types.ts +6 -1
- package/src/runtime/execution/workers/executor.ts +2 -6
- 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 +85 -28
- package/src/runtime/plugins/app-store-connect-adapter.ts +38 -14
- package/src/runtime/plugins/browser-adapter.ts +757 -34
- package/src/runtime/plugins/browser-automation-service.ts +23 -3
- package/src/runtime/plugins/browser-macos-bridge.ts +321 -29
- package/src/runtime/plugins/browser-manifest-surface.ts +45 -11
- package/src/runtime/plugins/browser-native-session-service.ts +63 -13
- package/src/runtime/plugins/browser-registration.ts +16 -0
- package/src/runtime/plugins/browser-runtime.ts +14 -1
- 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 +219 -0
- package/src/runtime/plugins/computer-chatgpt-macos-target.ts +891 -0
- package/src/runtime/plugins/computer-registration.ts +222 -11
- 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/gmail-adapter.ts +23 -2
- package/src/runtime/plugins/google-calendar-adapter.ts +2 -2
- package/src/runtime/plugins/google-shared.ts +14 -7
- package/src/runtime/plugins/google-tasks-adapter.ts +2 -2
- package/src/runtime/plugins/ios-adapter.ts +1 -1
- package/src/runtime/plugins/lightweight-action.ts +208 -2
- package/src/runtime/plugins/local-system-adapter.ts +12 -2
- 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 +602 -428
- package/src/runtime/plugins/types.ts +20 -0
- package/src/runtime/plugins/xiaohongshu-publish.ts +16 -0
- package/src/runtime/projections/invalidation.ts +7 -3
- package/src/runtime/projections/materialized-view.ts +80 -36
- package/src/runtime/recovery/actions.ts +3 -3
- package/src/runtime/recovery/capability-action-application.ts +46 -45
- package/src/runtime/recovery/lifecycle-inventory.ts +29 -29
- package/src/runtime/recovery/maintenance-executor.ts +374 -123
- package/src/runtime/recovery/store.ts +29 -11
- package/src/runtime/release/release-coordinator.ts +296 -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 +192 -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 +105 -19
- package/src/runtime/root/package-runtime-release.ts +117 -18
- package/src/runtime/root/package-runtime-service.ts +17 -11
- package/src/runtime/root/release-execution-canary.ts +44 -12
- package/src/runtime/root/release-loader.ts +90 -8
- package/src/runtime/root/release-manifest.ts +80 -6
- package/src/runtime/root/release-materialize.ts +372 -28
- package/src/runtime/root/release-store.ts +395 -36
- package/src/runtime/root/runtime-lane.ts +191 -0
- package/src/runtime/root/runtime.ts +159 -27
- package/src/runtime/root/scheduled-controller-composition.ts +28 -3
- package/src/runtime/root/service-runner.ts +2 -2
- package/src/runtime/root/service.ts +36 -33
- package/src/runtime/root/status.ts +48 -0
- package/src/runtime/root/types.ts +32 -3
- package/src/runtime/root/workflow-supervisor-composition.ts +493 -0
- package/src/runtime/root/workflow-supervisor-runtime.ts +209 -0
- package/src/runtime/root/write-fence.ts +50 -2
- package/src/runtime/safe-tooling/google-credential-store.ts +76 -21
- package/src/runtime/safe-tooling/google-oauth-broker.ts +25 -7
- package/src/runtime/safe-tooling/workspace-auth.ts +1 -1
- package/src/runtime/shared/bounded-child-supervisor.ts +9 -1
- 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 +3702 -342
- package/src/runtime/standalone-recovery/entry.ts +469 -39
- 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 +1 -1
- 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 +10 -3
- package/src/runtime/workflow/schedules/engine.ts +138 -172
- package/src/runtime/workflow/schedules/work-continuation.ts +44 -5
- 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 +201 -0
- package/supervisor/control-plane.ts +868 -0
- package/supervisor/entry.ts +15 -0
- package/supervisor/forge-validators.ts +80 -0
- package/supervisor/index.ts +5 -0
- package/supervisor/native-browser-adapter.ts +786 -0
- package/supervisor/native-messaging/host.ts +39 -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 +202 -0
- package/supervisor/server.ts +404 -0
- package/supervisor/store.ts +1451 -0
- package/supervisor/tsconfig.json +8 -0
- package/supervisor/types.ts +255 -0
- 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/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-tarball-install-smoke.sh +0 -150
- 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/stage-runtime-release.ts +0 -44
- 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/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
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
import type { CallToolResult } from '../../../packages/protocols/mcp/tool-contract';
|
|
2
|
+
import { getWorkContract } from '../../../packages/kernel/work/api/index';
|
|
3
|
+
import {
|
|
4
|
+
recordControllerExperience,
|
|
5
|
+
recordControllerOutcome,
|
|
6
|
+
type ControllerExperienceDraft,
|
|
7
|
+
type ControllerOutcomeObservationDraft,
|
|
8
|
+
} from '../../../src/runtime/context/assistant-work-context';
|
|
9
|
+
import { parseControllerLearningSignalDrafts } from '../../../src/runtime/context/automatic-learning';
|
|
10
|
+
import { persistDirectControllerLearning, recordDirectControllerLearningFeedback, type DirectControllerLearningFeedbackDraft } from '../../../src/runtime/context/direct-controller-learning';
|
|
11
|
+
import { buildFacadeResult } from '../../../src/runtime/control-plane/facade';
|
|
12
|
+
import type { MultiRepositoryMcpToolContext } from '../multi-repository';
|
|
13
|
+
import { result } from './result-adapter';
|
|
14
|
+
|
|
15
|
+
type RepositoryIdentity = { repoId: string; activeCheckoutId: string };
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* rh_work learning dispatch is advisory. Generic learning needs no Work; Work-specific
|
|
19
|
+
* outcome/experience writes are bound to exact Work provenance and canonical evidence.
|
|
20
|
+
* ControllerSession/ControllerRound state never grants write authority here.
|
|
21
|
+
*/
|
|
22
|
+
export function callRhWorkLearningOperation(
|
|
23
|
+
ctx: MultiRepositoryMcpToolContext,
|
|
24
|
+
repository: RepositoryIdentity,
|
|
25
|
+
operation: string,
|
|
26
|
+
args: Record<string, unknown>,
|
|
27
|
+
): CallToolResult | undefined {
|
|
28
|
+
if (!['learning_record', 'learning_feedback', 'outcome_record', 'experience_record'].includes(operation)) return undefined;
|
|
29
|
+
const store = { controllerHome: ctx.controllerHome, repoId: repository.repoId };
|
|
30
|
+
try {
|
|
31
|
+
if (operation === 'learning_feedback') {
|
|
32
|
+
if (!Array.isArray(args.learning_feedback) || args.learning_feedback.length === 0 || args.learning_feedback.length > 32) {
|
|
33
|
+
throw new Error('COGNITION_DIRECT_FEEDBACK_ITEMS_REQUIRED');
|
|
34
|
+
}
|
|
35
|
+
const feedback = args.learning_feedback.map((entry, index) => {
|
|
36
|
+
if (!entry || typeof entry !== 'object' || Array.isArray(entry)) throw new Error(`COGNITION_DIRECT_FEEDBACK_ITEM_INVALID: ${index}`);
|
|
37
|
+
const item = entry as Record<string, unknown>;
|
|
38
|
+
const decision = String(item.decision ?? '').trim();
|
|
39
|
+
const memoryAddress = String(item.memory_address ?? '').trim();
|
|
40
|
+
const reason = String(item.reason ?? '').trim();
|
|
41
|
+
const rejectionKind = typeof item.rejection_kind === 'string' ? item.rejection_kind.trim() : undefined;
|
|
42
|
+
if (!memoryAddress || !['used', 'rejected'].includes(decision)) throw new Error(`COGNITION_DIRECT_FEEDBACK_ITEM_INVALID: ${index}`);
|
|
43
|
+
if (decision === 'rejected' && !['irrelevant', 'stale', 'contradicted'].includes(rejectionKind ?? '')) {
|
|
44
|
+
throw new Error(`COGNITION_DIRECT_FEEDBACK_REJECTION_KIND_REQUIRED: ${index}`);
|
|
45
|
+
}
|
|
46
|
+
if (decision === 'used' && rejectionKind) throw new Error(`COGNITION_DIRECT_FEEDBACK_REJECTION_KIND_UNEXPECTED: ${index}`);
|
|
47
|
+
return {
|
|
48
|
+
memoryAddress,
|
|
49
|
+
decision,
|
|
50
|
+
reason,
|
|
51
|
+
...(rejectionKind ? { rejectionKind } : {}),
|
|
52
|
+
} as DirectControllerLearningFeedbackDraft;
|
|
53
|
+
});
|
|
54
|
+
const recorded = recordDirectControllerLearningFeedback({
|
|
55
|
+
controllerHome: ctx.controllerHome,
|
|
56
|
+
repository,
|
|
57
|
+
feedback,
|
|
58
|
+
principalId: ctx.principalId,
|
|
59
|
+
sessionId: ctx.sessionId,
|
|
60
|
+
controllerInstanceId: ctx.controllerInstanceId,
|
|
61
|
+
workId: typeof args.work_id === 'string' && args.work_id.trim() ? args.work_id.trim() : undefined,
|
|
62
|
+
});
|
|
63
|
+
return result(buildFacadeResult({
|
|
64
|
+
summary: `Recorded ${recorded.observationIds.length} lifecycle-free Cognitive usage feedback observation(s).`,
|
|
65
|
+
data: {
|
|
66
|
+
recorded: true,
|
|
67
|
+
observationIds: recorded.observationIds,
|
|
68
|
+
scopes: recorded.scopes,
|
|
69
|
+
authorityBoundary: 'Usage feedback adjusts advisory retrieval utility only; it grants no execution, lifecycle, or semantic authority.',
|
|
70
|
+
},
|
|
71
|
+
}) as unknown as Record<string, unknown>);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
if (operation === 'learning_record') {
|
|
75
|
+
const signals = parseControllerLearningSignalDrafts(args.learning_signals);
|
|
76
|
+
if (signals.length === 0) throw new Error('COGNITION_DIRECT_LEARNING_SIGNALS_REQUIRED');
|
|
77
|
+
const learning = persistDirectControllerLearning({
|
|
78
|
+
controllerHome: ctx.controllerHome,
|
|
79
|
+
repository,
|
|
80
|
+
signals,
|
|
81
|
+
principalId: ctx.principalId,
|
|
82
|
+
sessionId: ctx.sessionId,
|
|
83
|
+
controllerInstanceId: ctx.controllerInstanceId,
|
|
84
|
+
controllerType: ctx.controllerType,
|
|
85
|
+
workId: typeof args.work_id === 'string' && args.work_id.trim() ? args.work_id.trim() : undefined,
|
|
86
|
+
});
|
|
87
|
+
return result(buildFacadeResult({
|
|
88
|
+
summary: `Recorded ${learning.storedMemoryIds.length} model-authored advisory learning item(s) without creating Work lifecycle.`,
|
|
89
|
+
data: {
|
|
90
|
+
recorded: true,
|
|
91
|
+
storedMemoryIds: learning.storedMemoryIds,
|
|
92
|
+
associatedEdgeCount: learning.associatedEdgeCount,
|
|
93
|
+
consolidatedMemoryIds: learning.consolidatedMemoryIds,
|
|
94
|
+
scopes: learning.scopes,
|
|
95
|
+
authorityBoundary: 'Cognitive advisory memory only; it never grants execution or lifecycle authority.',
|
|
96
|
+
},
|
|
97
|
+
}) as unknown as Record<string, unknown>);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
const workId = String(args.work_id ?? '').trim();
|
|
101
|
+
if (!workId) throw new Error('LEARNING_LOOP_WORK_ID_REQUIRED');
|
|
102
|
+
const work = getWorkContract(store, workId);
|
|
103
|
+
if (!work) throw new Error(`WORK_NOT_FOUND: ${workId}`);
|
|
104
|
+
const identity = { workId };
|
|
105
|
+
|
|
106
|
+
if (operation === 'outcome_record') {
|
|
107
|
+
if (!args.outcome_observation || typeof args.outcome_observation !== 'object' || Array.isArray(args.outcome_observation)) {
|
|
108
|
+
throw new Error('OUTCOME_OBSERVATION_REQUIRED');
|
|
109
|
+
}
|
|
110
|
+
const outcome = recordControllerOutcome({
|
|
111
|
+
controllerHome: ctx.controllerHome,
|
|
112
|
+
repoId: repository.repoId,
|
|
113
|
+
identity,
|
|
114
|
+
draft: args.outcome_observation as ControllerOutcomeObservationDraft,
|
|
115
|
+
});
|
|
116
|
+
return result(buildFacadeResult({
|
|
117
|
+
summary: `OutcomeObservation ${outcome.id} recorded from canonical Work evidence.`,
|
|
118
|
+
data: { outcome },
|
|
119
|
+
}) as unknown as Record<string, unknown>);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
if (!args.experience_draft || typeof args.experience_draft !== 'object' || Array.isArray(args.experience_draft)) {
|
|
123
|
+
throw new Error('EXPERIENCE_DRAFT_REQUIRED');
|
|
124
|
+
}
|
|
125
|
+
const experience = recordControllerExperience({
|
|
126
|
+
controllerHome: ctx.controllerHome,
|
|
127
|
+
repoId: repository.repoId,
|
|
128
|
+
identity,
|
|
129
|
+
draft: args.experience_draft as ControllerExperienceDraft,
|
|
130
|
+
qualityAdjustmentFingerprint: typeof args.quality_adjustment_fingerprint === 'string'
|
|
131
|
+
? args.quality_adjustment_fingerprint.trim() || undefined
|
|
132
|
+
: undefined,
|
|
133
|
+
});
|
|
134
|
+
return result(buildFacadeResult({
|
|
135
|
+
summary: `Experience ${experience.id} recorded from canonical Work evidence for later advisory reuse.`,
|
|
136
|
+
data: { experience },
|
|
137
|
+
}) as unknown as Record<string, unknown>);
|
|
138
|
+
} catch (error) {
|
|
139
|
+
return result(buildFacadeResult({
|
|
140
|
+
status: 'blocked',
|
|
141
|
+
summary: error instanceof Error ? error.message : 'Learning record failed.',
|
|
142
|
+
data: { recorded: false },
|
|
143
|
+
}) as unknown as Record<string, unknown>, true);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import type { CallToolResult } from '../../../packages/protocols/mcp/tool-contract';
|
|
2
|
+
import {
|
|
3
|
+
listWorkContracts,
|
|
4
|
+
workSemanticView,
|
|
5
|
+
type WorkContractStoreOptions,
|
|
6
|
+
} from '../../../packages/kernel/work/api/index';
|
|
7
|
+
import { buildFacadeResult } from '../../../src/runtime/control-plane/facade';
|
|
8
|
+
import { result } from './result-adapter';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Bounded read-only collection projection for current and recent terminal semantic Work.
|
|
12
|
+
* Collection reads are separate from the semantic start/get/revise/complete
|
|
13
|
+
* mutation adapter so listing can never widen or gate semantic completion.
|
|
14
|
+
*/
|
|
15
|
+
export function callRhWorkListProjection(
|
|
16
|
+
store: WorkContractStoreOptions,
|
|
17
|
+
operation: string,
|
|
18
|
+
args: Record<string, unknown>,
|
|
19
|
+
): CallToolResult | undefined {
|
|
20
|
+
if (operation !== 'list') return undefined;
|
|
21
|
+
const limit = Math.max(1, Math.min(Math.trunc(typeof args.limit === 'number' ? args.limit : 50), 100));
|
|
22
|
+
const historyLimit = Math.min(limit, 50);
|
|
23
|
+
const works = listWorkContracts({ ...store, state: 'active', limit });
|
|
24
|
+
const recentHistory = [
|
|
25
|
+
...listWorkContracts({ ...store, state: 'completed', limit: historyLimit }),
|
|
26
|
+
...listWorkContracts({ ...store, state: 'cancelled', limit: historyLimit }),
|
|
27
|
+
]
|
|
28
|
+
.sort((left, right) => right.updatedAt.localeCompare(left.updatedAt))
|
|
29
|
+
.slice(0, historyLimit);
|
|
30
|
+
return result(buildFacadeResult({
|
|
31
|
+
summary: `${works.length} current and ${recentHistory.length} recent terminal semantic Work(s) in this repository.`,
|
|
32
|
+
data: {
|
|
33
|
+
works: works.map(workSemanticView),
|
|
34
|
+
recentHistory: recentHistory.map(workSemanticView),
|
|
35
|
+
bounded: true,
|
|
36
|
+
},
|
|
37
|
+
}) as unknown as Record<string, unknown>);
|
|
38
|
+
}
|
|
@@ -0,0 +1,382 @@
|
|
|
1
|
+
import type { CallToolResult } from '../../../packages/protocols/mcp/tool-contract';
|
|
2
|
+
import type { MultiRepositoryMcpToolContext } from '../multi-repository';
|
|
3
|
+
import {
|
|
4
|
+
admitPlanContractAsync,
|
|
5
|
+
createPlanSemanticContext,
|
|
6
|
+
buildFacadeResult,
|
|
7
|
+
getPlanContract,
|
|
8
|
+
listPlanContracts,
|
|
9
|
+
normalizeCheckIds,
|
|
10
|
+
resolvePlanAdmission,
|
|
11
|
+
summarizePlanContract,
|
|
12
|
+
planSemanticView,
|
|
13
|
+
revisePlanSemanticContext,
|
|
14
|
+
listPlanSemanticRevisionRecords,
|
|
15
|
+
type CheckDefinitionLike,
|
|
16
|
+
type PlanContractStoreOptions,
|
|
17
|
+
} from '../../../src/runtime/control-plane/facade';
|
|
18
|
+
import { readRequirement } from '../../../src/runtime/control-plane/persistence/requirement-store';
|
|
19
|
+
import { listRepositories } from '../../../src/cli/repositories/registry';
|
|
20
|
+
import { SEMANTIC_SCOPE_KEY } from '../../../src/cli/repositories/controller-home';
|
|
21
|
+
import { result } from './result-adapter';
|
|
22
|
+
|
|
23
|
+
const RH_WORK_LIGHTWEIGHT_PLAN_OPERATIONS = new Set([
|
|
24
|
+
'plan_list',
|
|
25
|
+
'plan_get',
|
|
26
|
+
'plan_revise',
|
|
27
|
+
]);
|
|
28
|
+
|
|
29
|
+
export function isRhWorkLightweightPlanOperation(operation: string): boolean {
|
|
30
|
+
return RH_WORK_LIGHTWEIGHT_PLAN_OPERATIONS.has(operation);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export async function callRhWorkPlanOperation(
|
|
34
|
+
store: PlanContractStoreOptions,
|
|
35
|
+
operation: string,
|
|
36
|
+
args: Record<string, unknown>,
|
|
37
|
+
): Promise<CallToolResult | undefined> {
|
|
38
|
+
if (!isRhWorkLightweightPlanOperation(operation)) return undefined;
|
|
39
|
+
|
|
40
|
+
if (operation === 'plan_list') {
|
|
41
|
+
const plans = listPlanContracts({ ...store, status: 'active', limit: typeof args.limit === 'number' ? args.limit : 20 });
|
|
42
|
+
const facade = buildFacadeResult({
|
|
43
|
+
summary: `${plans.length} current semantic Plan(s) in this repository.`,
|
|
44
|
+
data: { plans: plans.map(planSemanticView), bounded: true },
|
|
45
|
+
});
|
|
46
|
+
return result(facade as unknown as Record<string, unknown>);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
if (operation === 'plan_get') {
|
|
50
|
+
const plan = getPlanContract(store, String(args.plan_id ?? ''));
|
|
51
|
+
const facade = plan
|
|
52
|
+
? buildFacadeResult({
|
|
53
|
+
summary: `Plan ${plan.planId} current head retrieved at semantic revision ${planSemanticView(plan).revision}.`,
|
|
54
|
+
data: {
|
|
55
|
+
plan: planSemanticView(plan),
|
|
56
|
+
...(args.detail_level === 'detail' ? { revisionHistory: listPlanSemanticRevisionRecords(store, plan.planId) } : {}),
|
|
57
|
+
},
|
|
58
|
+
detailLevel: args.detail_level === 'detail' ? 'detail' : 'summary',
|
|
59
|
+
})
|
|
60
|
+
: buildFacadeResult({
|
|
61
|
+
status: 'not_found',
|
|
62
|
+
summary: `PlanContract ${String(args.plan_id ?? '')} not found.`,
|
|
63
|
+
data: { planId: String(args.plan_id ?? '') },
|
|
64
|
+
});
|
|
65
|
+
return result(facade as unknown as Record<string, unknown>, !plan);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
try {
|
|
69
|
+
if (operation === 'plan_revise') {
|
|
70
|
+
const planId = String(args.plan_id ?? '').trim();
|
|
71
|
+
const expectedRevision = Number(args.expected_revision);
|
|
72
|
+
const plan = revisePlanSemanticContext(store, planId, {
|
|
73
|
+
expectedRevision,
|
|
74
|
+
...(typeof args.superseded_by === 'string' ? { supersededBy: args.superseded_by } : {}),
|
|
75
|
+
...(typeof args.requirement_revision === 'number' ? { requirementBasisRevision: args.requirement_revision } : {}),
|
|
76
|
+
...(typeof args.source_revision === 'string' ? { sourceBasisRevision: args.source_revision } : {}),
|
|
77
|
+
...(typeof args.objective === 'string' ? { goal: args.objective } : {}),
|
|
78
|
+
...(Array.isArray(args.non_goals) ? { nonGoals: args.non_goals.map(String) } : {}),
|
|
79
|
+
...(Array.isArray(args.assumptions) ? { assumptions: args.assumptions.map(String) } : {}),
|
|
80
|
+
...(Array.isArray(args.resolved_decisions) ? { resolvedDecisions: args.resolved_decisions.map(String) } : {}),
|
|
81
|
+
...(Array.isArray(args.stop_conditions) ? { stopConditions: args.stop_conditions.map(String) } : {}),
|
|
82
|
+
...(Array.isArray(args.replan_conditions) ? { replanConditions: args.replan_conditions.map(String) } : {}),
|
|
83
|
+
...(args.integration_strategy === null || typeof args.integration_strategy === 'string' ? { integrationStrategy: args.integration_strategy as string | null } : {}),
|
|
84
|
+
...(Array.isArray(args.plan_items) ? { items: args.plan_items
|
|
85
|
+
.filter((entry): entry is Record<string, unknown> => Boolean(entry) && typeof entry === 'object' && !Array.isArray(entry))
|
|
86
|
+
.map((entry) => ({
|
|
87
|
+
id: String(entry.id ?? ''),
|
|
88
|
+
objective: String(entry.objective ?? ''),
|
|
89
|
+
dependencies: Array.isArray(entry.dependencies) ? entry.dependencies.map(String) : [],
|
|
90
|
+
})) } : {}),
|
|
91
|
+
});
|
|
92
|
+
return result(buildFacadeResult({
|
|
93
|
+
summary: `Plan ${plan.planId} revised atomically to semantic revision ${planSemanticView(plan).revision}; source basis remains provenance metadata and no approval/execution transition was implied.`,
|
|
94
|
+
data: { plan: planSemanticView(plan), expectedRevision },
|
|
95
|
+
}) as unknown as Record<string, unknown>);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
return undefined;
|
|
99
|
+
} catch (error) {
|
|
100
|
+
const currentPlanId = String(args.plan_id ?? '').trim();
|
|
101
|
+
const currentPlan = operation === 'plan_revise' && currentPlanId ? getPlanContract(store, currentPlanId) : undefined;
|
|
102
|
+
const facade = buildFacadeResult({
|
|
103
|
+
status: 'blocked',
|
|
104
|
+
summary: error instanceof Error ? error.message : 'PlanContract operation failed.',
|
|
105
|
+
data: {
|
|
106
|
+
operation,
|
|
107
|
+
executionStarted: false,
|
|
108
|
+
...(currentPlan ? { currentPlan: planSemanticView(currentPlan) } : {}),
|
|
109
|
+
},
|
|
110
|
+
});
|
|
111
|
+
return result(facade as unknown as Record<string, unknown>, true);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
function planObligationDispositionsFromArgs(value: unknown) {
|
|
116
|
+
if (!Array.isArray(value)) return undefined;
|
|
117
|
+
return value
|
|
118
|
+
.filter((entry): entry is Record<string, unknown> => Boolean(entry) && typeof entry === 'object' && !Array.isArray(entry))
|
|
119
|
+
.map((entry) => ({
|
|
120
|
+
predecessorPlanId: String(entry.predecessor_plan_id ?? ''),
|
|
121
|
+
obligationId: String(entry.obligation_id ?? ''),
|
|
122
|
+
disposition: String(entry.disposition ?? '') as 'keep' | 'change' | 'defer' | 'drop',
|
|
123
|
+
successorRefs: Array.isArray(entry.successor_refs) ? entry.successor_refs.map(String) : [],
|
|
124
|
+
rationale: typeof entry.rationale === 'string' ? entry.rationale : undefined,
|
|
125
|
+
}));
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
export interface RhWorkPlanCreateContext {
|
|
129
|
+
controllerHome: string;
|
|
130
|
+
/** Node-local placement provenance; absent when the Plan belongs to the ForgeInstance. */
|
|
131
|
+
repoId?: string;
|
|
132
|
+
checks: readonly CheckDefinitionLike[];
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* A Plan is authored semantic context: it can belong to the ForgeInstance with
|
|
137
|
+
* no repository and no source revision. When no repository target is available
|
|
138
|
+
* or explicitly requested, create it in the semantic scope; otherwise return
|
|
139
|
+
* undefined so the normal repository-bound path stays authoritative.
|
|
140
|
+
*/
|
|
141
|
+
export async function callRhWorkPlanCreateWithoutRepository(
|
|
142
|
+
ctx: MultiRepositoryMcpToolContext,
|
|
143
|
+
operation: string,
|
|
144
|
+
args: Record<string, unknown>,
|
|
145
|
+
): Promise<CallToolResult | undefined> {
|
|
146
|
+
if (operation !== 'plan_create') return undefined;
|
|
147
|
+
const explicitRepoId = typeof args.repo_id === 'string' ? args.repo_id.trim() : '';
|
|
148
|
+
if (explicitRepoId || ctx.explicitRepository) return undefined;
|
|
149
|
+
const enabled = listRepositories(ctx.controllerHome).filter((record) => record.enabled && !record.removedAt);
|
|
150
|
+
// Zero repositories means "ForgeInstance-scoped Plan". One means the sole
|
|
151
|
+
// repository stays authoritative; several keep the explicit disambiguation
|
|
152
|
+
// error instead of silently creating an unscoped Plan.
|
|
153
|
+
if (enabled.length !== 0) return undefined;
|
|
154
|
+
return callRhWorkPlanCreateOperation(
|
|
155
|
+
{ controllerHome: ctx.controllerHome, scopeKey: SEMANTIC_SCOPE_KEY },
|
|
156
|
+
operation,
|
|
157
|
+
args,
|
|
158
|
+
{ controllerHome: ctx.controllerHome, checks: [] },
|
|
159
|
+
);
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
export async function callRhWorkPlanCreateOperation(
|
|
163
|
+
store: PlanContractStoreOptions,
|
|
164
|
+
operation: string,
|
|
165
|
+
args: Record<string, unknown>,
|
|
166
|
+
context: RhWorkPlanCreateContext,
|
|
167
|
+
): Promise<CallToolResult | undefined> {
|
|
168
|
+
if (operation !== 'plan_create') return undefined;
|
|
169
|
+
|
|
170
|
+
if (!Array.isArray(args.plan_steps)) {
|
|
171
|
+
try {
|
|
172
|
+
const plan = createPlanSemanticContext(store, {
|
|
173
|
+
planId: String(args.plan_id ?? ''),
|
|
174
|
+
repoId: context.repoId,
|
|
175
|
+
requirementId: typeof args.requirement_id === 'string' && args.requirement_id.trim() ? args.requirement_id.trim() : undefined,
|
|
176
|
+
requirementBasisRevision: typeof args.requirement_revision === 'number' ? args.requirement_revision : undefined,
|
|
177
|
+
scopeKey: typeof args.scope_key === 'string' ? args.scope_key : undefined,
|
|
178
|
+
sourceBasisRevision: typeof args.source_revision === 'string' ? args.source_revision : undefined,
|
|
179
|
+
goal: String(args.objective ?? ''),
|
|
180
|
+
nonGoals: Array.isArray(args.non_goals) ? args.non_goals.map(String) : undefined,
|
|
181
|
+
assumptions: Array.isArray(args.assumptions) ? args.assumptions.map(String) : undefined,
|
|
182
|
+
resolvedDecisions: Array.isArray(args.resolved_decisions) ? args.resolved_decisions.map(String) : undefined,
|
|
183
|
+
stopConditions: Array.isArray(args.stop_conditions) ? args.stop_conditions.map(String) : undefined,
|
|
184
|
+
replanConditions: Array.isArray(args.replan_conditions) ? args.replan_conditions.map(String) : undefined,
|
|
185
|
+
integrationStrategy: typeof args.integration_strategy === 'string' ? args.integration_strategy : undefined,
|
|
186
|
+
items: Array.isArray(args.plan_items)
|
|
187
|
+
? args.plan_items
|
|
188
|
+
.filter((entry): entry is Record<string, unknown> => Boolean(entry) && typeof entry === 'object' && !Array.isArray(entry))
|
|
189
|
+
.map((entry) => ({
|
|
190
|
+
id: String(entry.id ?? ''),
|
|
191
|
+
objective: String(entry.objective ?? ''),
|
|
192
|
+
dependencies: Array.isArray(entry.dependencies) ? entry.dependencies.map(String) : [],
|
|
193
|
+
}))
|
|
194
|
+
: [],
|
|
195
|
+
});
|
|
196
|
+
return result(buildFacadeResult({
|
|
197
|
+
summary: `Plan ${plan.planId} created at semantic revision 1. Plan items are descriptive working memory; no approval, PlanStep, path/check, scheduling, Work, or acceptance authority was created.`,
|
|
198
|
+
data: { plan: planSemanticView(plan), planContractCreated: true, executionStarted: false },
|
|
199
|
+
}) as unknown as Record<string, unknown>);
|
|
200
|
+
} catch (error) {
|
|
201
|
+
return result(buildFacadeResult({
|
|
202
|
+
status: 'blocked',
|
|
203
|
+
summary: error instanceof Error ? error.message : 'Semantic Plan creation failed.',
|
|
204
|
+
data: { planContractCreated: false, executionStarted: false },
|
|
205
|
+
}) as unknown as Record<string, unknown>, true);
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
try {
|
|
210
|
+
// Frozen-client compatibility only. Current model-facing schema no longer exposes plan_steps.
|
|
211
|
+
const rawSteps = args.plan_steps;
|
|
212
|
+
const requestedPlanId = String(args.plan_id ?? '').trim();
|
|
213
|
+
const requestedRequirementId = typeof args.requirement_id === 'string' && args.requirement_id.trim() ? args.requirement_id.trim() : undefined;
|
|
214
|
+
const requestedPlanRelation: 'extend' | 'parallel' | undefined = args.plan_relation === 'extend' || args.plan_relation === 'parallel'
|
|
215
|
+
? args.plan_relation
|
|
216
|
+
: undefined;
|
|
217
|
+
const relatedPlanId = typeof args.related_plan_id === 'string' && args.related_plan_id.trim() ? args.related_plan_id.trim() : undefined;
|
|
218
|
+
if (requestedRequirementId && !readRequirement({ controllerHome: context.controllerHome }, requestedRequirementId)) {
|
|
219
|
+
const facade = buildFacadeResult({
|
|
220
|
+
status: 'failed',
|
|
221
|
+
summary: `PLAN_REQUIREMENT_NOT_FOUND: ${requestedRequirementId}. Plan was not persisted; create or reconcile the Requirement authority first.`,
|
|
222
|
+
data: { executionStarted: false, planContractCreated: false, admissionDecision: 'missing_requirement', requirementId: requestedRequirementId },
|
|
223
|
+
});
|
|
224
|
+
return result(facade as unknown as Record<string, unknown>, true);
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
const admissionInput = {
|
|
228
|
+
requirementId: requestedRequirementId,
|
|
229
|
+
scopeKey: String(args.scope_key ?? ''),
|
|
230
|
+
planRelation: requestedPlanRelation,
|
|
231
|
+
relatedPlanId,
|
|
232
|
+
};
|
|
233
|
+
const renderPlanAdmission = (admission: ReturnType<typeof resolvePlanAdmission>): CallToolResult | undefined => {
|
|
234
|
+
if (admission.admissionDecision === 'create_new') return undefined;
|
|
235
|
+
if (admission.reason === 'exact_scope_authority' && admission.plan) {
|
|
236
|
+
const exactDraftRepair = admission.plan.status === 'draft' && requestedPlanId === admission.plan.planId;
|
|
237
|
+
const facade = buildFacadeResult({
|
|
238
|
+
summary: exactDraftRepair
|
|
239
|
+
? `PLAN_DRAFT_REPAIR_REQUIRED: draft Plan ${admission.plan.planId} already owns scope ${admission.normalizedScopeKey}; preserve that authority and amend it through rh_work repair.`
|
|
240
|
+
: `PLAN_AUTHORITY_REUSED: active Plan ${admission.plan.planId} already owns scope ${admission.normalizedScopeKey}; no duplicate draft was created.`,
|
|
241
|
+
data: {
|
|
242
|
+
plan: summarizePlanContract(admission.plan),
|
|
243
|
+
executionStarted: false,
|
|
244
|
+
planContractCreated: false,
|
|
245
|
+
admissionDecision: 'reuse_existing',
|
|
246
|
+
resolutionRequired: false,
|
|
247
|
+
...(exactDraftRepair ? { repairRequired: true } : {}),
|
|
248
|
+
},
|
|
249
|
+
suggestedNextActions: exactDraftRepair
|
|
250
|
+
? [{
|
|
251
|
+
label: 'Repair this exact draft Plan',
|
|
252
|
+
tool: 'rh_work',
|
|
253
|
+
operation: 'repair',
|
|
254
|
+
payload: {
|
|
255
|
+
plan_id: admission.plan.planId,
|
|
256
|
+
repair_operation: 'repair',
|
|
257
|
+
dry_run: false,
|
|
258
|
+
scope_key: args.scope_key,
|
|
259
|
+
source_revision: args.source_revision,
|
|
260
|
+
objective: args.objective,
|
|
261
|
+
plan_steps: args.plan_steps,
|
|
262
|
+
non_goals: args.non_goals,
|
|
263
|
+
assumptions: args.assumptions,
|
|
264
|
+
resolved_decisions: args.resolved_decisions,
|
|
265
|
+
stop_conditions: args.stop_conditions,
|
|
266
|
+
replan_conditions: args.replan_conditions,
|
|
267
|
+
integration_strategy: args.integration_strategy,
|
|
268
|
+
},
|
|
269
|
+
risk: 'workspace_write',
|
|
270
|
+
confidence: 'high',
|
|
271
|
+
}]
|
|
272
|
+
: [{ label: 'Read active Plan', tool: 'rh_work', operation: 'plan_get', payload: { plan_id: admission.plan.planId }, risk: 'readonly', confidence: 'high' }],
|
|
273
|
+
});
|
|
274
|
+
return result(facade as unknown as Record<string, unknown>);
|
|
275
|
+
}
|
|
276
|
+
if (admission.reason === 'extension_target_required') {
|
|
277
|
+
const facade = buildFacadeResult({
|
|
278
|
+
summary: `PLAN_EXTENSION_TARGET_REQUIRED: select related_plan_id from the active Plan slices for Requirement ${requestedRequirementId}.`,
|
|
279
|
+
data: { executionStarted: false, planContractCreated: false, admissionDecision: 'resolution_required', resolutionRequired: true, candidates: admission.candidates.map(summarizePlanContract) },
|
|
280
|
+
});
|
|
281
|
+
return result(facade as unknown as Record<string, unknown>);
|
|
282
|
+
}
|
|
283
|
+
if (admission.reason === 'extend_existing' && admission.plan) {
|
|
284
|
+
// plan_create + plan_relation=extend revises the explicitly related stable
|
|
285
|
+
// Plan identity in place and advances its semantic head. Preflight continues
|
|
286
|
+
// into atomic admission; compatibility must not create a sibling revision Plan.
|
|
287
|
+
return undefined;
|
|
288
|
+
}
|
|
289
|
+
throw new Error(`PLAN_ADMISSION_RESULT_INVALID: ${admission.admissionDecision}:${admission.reason}`);
|
|
290
|
+
};
|
|
291
|
+
|
|
292
|
+
const plans = listPlanContracts({ ...store, status: 'all', limit: 100 });
|
|
293
|
+
const preflightAdmission = resolvePlanAdmission(plans, admissionInput);
|
|
294
|
+
const preflightResult = renderPlanAdmission(preflightAdmission);
|
|
295
|
+
if (preflightResult) return preflightResult;
|
|
296
|
+
|
|
297
|
+
const requestedPlanCheckIds = rawSteps
|
|
298
|
+
.filter((step): step is Record<string, unknown> => Boolean(step) && typeof step === 'object' && !Array.isArray(step))
|
|
299
|
+
.flatMap((step) => Array.isArray(step.check_ids) ? step.check_ids.map(String) : []);
|
|
300
|
+
const normalizedPlanChecks = normalizeCheckIds(requestedPlanCheckIds, context.checks);
|
|
301
|
+
if (normalizedPlanChecks.invalidCheckIds.length > 0) {
|
|
302
|
+
const facade = buildFacadeResult({
|
|
303
|
+
status: 'failed',
|
|
304
|
+
summary: `PLAN_CHECKS_INVALID: ${normalizedPlanChecks.invalidCheckIds.join(', ')}. Plan was not persisted; select replacement IDs from registeredCheckIds in this response, then request readiness only for the checks you choose.`,
|
|
305
|
+
data: {
|
|
306
|
+
executionStarted: false,
|
|
307
|
+
planContractCreated: false,
|
|
308
|
+
admissionDecision: 'invalid_checks',
|
|
309
|
+
normalizedChecks: normalizedPlanChecks,
|
|
310
|
+
registeredCheckIds: context.checks.map((check) => check.id).slice(0, 80),
|
|
311
|
+
},
|
|
312
|
+
suggestedNextActions: [],
|
|
313
|
+
});
|
|
314
|
+
return result(facade as unknown as Record<string, unknown>, true);
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
const admitted = await admitPlanContractAsync(store, {
|
|
318
|
+
planId: String(args.plan_id ?? ''),
|
|
319
|
+
repoId: context.repoId,
|
|
320
|
+
requirementId: requestedRequirementId,
|
|
321
|
+
scopeKey: String(args.scope_key ?? ''),
|
|
322
|
+
planRelation: requestedPlanRelation,
|
|
323
|
+
relatedPlanId,
|
|
324
|
+
sourceRevision: String(args.source_revision ?? ''),
|
|
325
|
+
goal: String(args.objective ?? ''),
|
|
326
|
+
nonGoals: Array.isArray(args.non_goals) ? args.non_goals.map(String) : undefined,
|
|
327
|
+
assumptions: Array.isArray(args.assumptions) ? args.assumptions.map(String) : undefined,
|
|
328
|
+
resolvedDecisions: Array.isArray(args.resolved_decisions) ? args.resolved_decisions.map(String) : undefined,
|
|
329
|
+
stopConditions: Array.isArray(args.stop_conditions) ? args.stop_conditions.map(String) : undefined,
|
|
330
|
+
replanConditions: Array.isArray(args.replan_conditions) ? args.replan_conditions.map(String) : undefined,
|
|
331
|
+
integrationStrategy: typeof args.integration_strategy === 'string' ? args.integration_strategy : undefined,
|
|
332
|
+
obligationDispositions: planObligationDispositionsFromArgs(args.obligation_dispositions),
|
|
333
|
+
steps: rawSteps.filter((step): step is Record<string, unknown> => Boolean(step) && typeof step === 'object' && !Array.isArray(step)).map((step) => ({
|
|
334
|
+
id: String(step.id ?? ''),
|
|
335
|
+
objective: String(step.objective ?? ''),
|
|
336
|
+
dependencies: Array.isArray(step.dependencies) ? step.dependencies.map(String) : [],
|
|
337
|
+
authoritativeFiles: Array.isArray(step.authoritative_files) ? step.authoritative_files.map(String) : [],
|
|
338
|
+
allowedPaths: Array.isArray(step.allowed_paths) ? step.allowed_paths.map(String) : [],
|
|
339
|
+
forbiddenPaths: Array.isArray(step.forbidden_paths) ? step.forbidden_paths.map(String) : [],
|
|
340
|
+
checks: Array.isArray(step.check_ids) ? step.check_ids.map(String) : [],
|
|
341
|
+
acceptanceCriteria: Array.isArray(step.acceptance_criteria) ? step.acceptance_criteria.map(String) : [],
|
|
342
|
+
})),
|
|
343
|
+
});
|
|
344
|
+
if (admitted.reason === 'extend_existing' && admitted.plan) {
|
|
345
|
+
const plan = admitted.plan;
|
|
346
|
+
const requestedLabel = requestedPlanId && requestedPlanId !== plan.planId
|
|
347
|
+
? ` Requested compatibility plan_id ${requestedPlanId} was retained only as revision audit metadata.`
|
|
348
|
+
: '';
|
|
349
|
+
const facade = buildFacadeResult({
|
|
350
|
+
summary: `PLAN_REVISION_REUSED_AUTHORITY: Plan ${plan.planId} was revised in place; no successor PlanContract was created.${requestedLabel}`,
|
|
351
|
+
data: {
|
|
352
|
+
plan: summarizePlanContract(plan),
|
|
353
|
+
executionStarted: false,
|
|
354
|
+
planContractCreated: false,
|
|
355
|
+
admissionDecision: 'reuse_existing',
|
|
356
|
+
resolutionRequired: false,
|
|
357
|
+
},
|
|
358
|
+
// Plan approval is a retired ceremony no-op; the projection must not steer
|
|
359
|
+
// the model back into it. Reading the current revision is the honest action.
|
|
360
|
+
suggestedNextActions: [{ label: 'Read current Plan revision', tool: 'rh_work', operation: 'plan_get', payload: { plan_id: plan.planId }, risk: 'readonly', confidence: 'high' }],
|
|
361
|
+
});
|
|
362
|
+
return result(facade as unknown as Record<string, unknown>);
|
|
363
|
+
}
|
|
364
|
+
const racedAdmissionResult = renderPlanAdmission(admitted);
|
|
365
|
+
if (racedAdmissionResult) return racedAdmissionResult;
|
|
366
|
+
if (!admitted.plan) throw new Error('PLAN_ADMISSION_CREATE_MISSING_PLAN');
|
|
367
|
+
const plan = admitted.plan;
|
|
368
|
+
const facade = buildFacadeResult({
|
|
369
|
+
summary: `PlanContract ${plan.planId} created as draft after atomic authority admission; no execution was started.`,
|
|
370
|
+
data: { plan: summarizePlanContract(plan), executionStarted: false, planContractCreated: true, admissionDecision: 'create_new' },
|
|
371
|
+
suggestedNextActions: [{ label: 'Read current Plan revision', tool: 'rh_work', operation: 'plan_get', payload: { plan_id: plan.planId }, risk: 'readonly', confidence: 'high' }],
|
|
372
|
+
});
|
|
373
|
+
return result(facade as unknown as Record<string, unknown>);
|
|
374
|
+
} catch (error) {
|
|
375
|
+
const facade = buildFacadeResult({
|
|
376
|
+
status: 'blocked',
|
|
377
|
+
summary: error instanceof Error ? error.message : 'PlanContract operation failed.',
|
|
378
|
+
data: { operation, executionStarted: false },
|
|
379
|
+
});
|
|
380
|
+
return result(facade as unknown as Record<string, unknown>, true);
|
|
381
|
+
}
|
|
382
|
+
}
|