@moretea-labs/forge 1.6.0 → 1.7.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +4 -0
- package/CHANGELOG.md +39 -0
- package/CLAUDE.md +4 -0
- package/README.md +2 -2
- package/README.zh-CN.md +1 -1
- package/SKILL.md +2 -2
- package/THIRD_PARTY_NOTICES.md +1 -1
- package/agents/openai.yaml +1 -1
- package/assets/hooks/hook-input.sh +11 -8
- package/assets/hooks/lib/session-state.sh +10 -7
- package/assets/hooks/lib/workflow-state.sh +13 -177
- package/assets/hooks/post-tool-observer.sh +8 -2
- package/assets/hooks/prompt-guard.sh +5 -81
- package/assets/hooks/session-start-context.sh +56 -1
- package/assets/partials/05-workflow.partial.md +1 -1
- package/assets/partials-agents/02-operating-mode.partial.md +2 -0
- package/assets/partials-agents/03-orchestration.partial.md +1 -1
- package/assets/plugin-registry.v1.json +3 -3
- package/assets/reference-configs/document-generation.md +1 -1
- package/assets/reference-configs/harness-overview.md +1 -1
- package/assets/reference-configs/sprint-contracts.md +3 -3
- package/assets/skill-version.json +2 -2
- package/assets/templates/contract.template.md +2 -7
- package/assets/templates/helpers/capture-plan.sh +2 -2
- package/assets/templates/helpers/check-architecture-sync.sh +17 -0
- package/assets/templates/helpers/check-task-workflow.sh +4 -4
- package/assets/templates/helpers/contract-worktree.sh +1 -21
- package/assets/templates/helpers/ensure-task-workflow.sh +11 -36
- package/assets/templates/helpers/inspect-project-state.ts +8 -6
- package/assets/templates/helpers/migrate-project-template.sh +22 -45
- package/assets/templates/helpers/migrate-workflow-docs.ts +9 -7
- package/assets/templates/helpers/new-plan.sh +1 -1
- package/assets/templates/helpers/plan-to-todo.sh +12 -37
- package/assets/templates/helpers/ship-worktrees.sh +2 -29
- package/assets/templates/helpers/verify-contract.sh +1 -111
- package/assets/templates/helpers/verify-sprint.sh +3 -180
- package/assets/templates/helpers/workflow-contract.ts +5 -1
- package/assets/templates/plan.template.md +1 -1
- package/assets/templates/review.template.md +9 -34
- package/assets/workflow-contract.v1.json +10 -19
- package/docs/README.md +10 -10
- package/docs/architecture/CURRENT.md +178 -0
- package/docs/architecture/EVOLUTION.md +42 -0
- package/docs/architecture/current/README.md +4 -156
- package/docs/architecture/decisions/20260803-release-identity-binding-and-exit-policy.md +2 -2
- package/docs/architecture/decisions/20260823-immediate-controller-relay.md +53 -0
- package/docs/architecture/decisions/20260826-browser-runtime-v2.md +73 -0
- package/docs/architecture/history/README.md +7 -0
- package/docs/architecture/{chatgpt-handoff-facade.md → history/chatgpt-handoff-facade.md} +4 -0
- package/docs/architecture/{global-hook-runtime.md → history/global-hook-runtime.md} +7 -3
- package/docs/architecture/{ios-semantic-automation-provider-v2.md → history/ios-semantic-automation-provider-v2.md} +6 -2
- package/docs/architecture/history.md +3 -34
- package/docs/architecture/index.md +15 -98
- package/docs/architecture/modules/controller-runtime/transport-lifecycle.md +1 -1
- package/docs/architecture/reviews/2026-08-22-semantic-harness-convergence-acceptance.md +39 -0
- package/docs/architecture/versions/1.6.md +38 -0
- package/docs/architecture/versions/1.7.md +41 -0
- package/docs/forge-chatgpt-browser-engine.md +2 -2
- package/docs/forge-chatgpt-mcp-setup.md +4 -28
- package/docs/forge-chatgpt-supervised-automation.md +3 -3
- package/docs/forge-github-issue-launcher.md +1 -1
- package/docs/forge-plugin-management.md +1 -1
- package/docs/forge-runtime-self-healing-loop.md +1 -1
- package/docs/operations/controller-browser-plugin.md +26 -6
- package/docs/operations/controller-performance-and-502.md +143 -0
- package/docs/operations/controller-reliability-runbook.md +1 -1
- package/docs/operations/features.md +2 -2
- package/docs/operations/github-repository.md +1 -1
- package/docs/operations/homebrew.md +2 -2
- package/docs/operations/mcp-tool-exposure.md +5 -3
- package/docs/wiki/Architecture.md +6 -6
- package/docs/wiki/Implementation.md +2 -2
- package/docs/wiki/Integrations.md +2 -2
- package/docs/wiki/Work-Lifecycle.md +1 -1
- package/package.json +33 -11
- package/scripts/activate-source-baseline.ts +17 -13
- package/scripts/architecture-event.ts +2 -820
- package/scripts/architecture-queue.sh +2 -645
- package/scripts/archive-architecture-request.sh +2 -242
- package/scripts/archive-workflow.sh +1 -291
- package/scripts/benchmark-background-check-overlap.ts +228 -0
- package/scripts/benchmark-mcp-host.sh +117 -0
- package/scripts/benchmark-mcp-transport.ts +170 -0
- package/scripts/benchmark-quality-harness.ts +146 -0
- package/scripts/benchmark-route-session-concurrency.ts +207 -6
- package/scripts/benchmark-thin-harness-mcp-e2e.ts +7 -1
- package/scripts/benchmark-typescript-navigation.ts +186 -0
- package/scripts/benchmark-work-efficiency.ts +334 -0
- package/scripts/capability-config.ts +2 -392
- package/scripts/capability-resolver.ts +2 -503
- package/scripts/capture-plan.sh +1 -332
- package/scripts/check-agent-tooling.sh +2 -1558
- package/scripts/check-architecture-sync.sh +2 -371
- package/scripts/check-brain-manifest.sh +2 -253
- package/scripts/check-context-files.sh +2 -47
- package/scripts/check-deploy-sql-order.sh +2 -115
- package/scripts/check-mcp-compatibility.ts +14 -0
- package/scripts/check-runtime-architecture.mjs +349 -79
- package/scripts/check-skill-version.ts +3 -191
- package/scripts/check-source-duplication.mjs +61 -0
- package/scripts/check-stable-baseline.ts +92 -0
- package/scripts/check-task-sync.sh +2 -63
- package/scripts/check-task-workflow.sh +2 -1000
- package/scripts/codex-handoff-resume.sh +2 -267
- package/scripts/context-contract-sync.sh +2 -514
- package/scripts/contract-run.ts +2 -463
- package/scripts/contract-worktree.sh +1 -722
- package/scripts/ensure-task-workflow.sh +1 -1225
- package/scripts/host-temporary-cloud-mcp-e2e.sh +265 -0
- package/scripts/inspect-project-state.ts +4 -279
- package/scripts/install-standalone-recovery.ts +24 -0
- package/scripts/lib/project-init-lib.sh +22 -46
- package/scripts/lib/run-forge-helper.sh +19 -0
- package/scripts/lib/run-forge-helper.ts +26 -0
- package/scripts/migrate-project-template.sh +1 -1189
- package/scripts/migrate-workflow-docs.ts +4 -412
- package/scripts/new-plan.sh +1 -180
- package/scripts/new-spec.sh +1 -47
- package/scripts/new-sprint.sh +1 -46
- package/scripts/plan-to-todo.sh +1 -796
- package/scripts/prepare-codex-handoff.sh +2 -201
- package/scripts/prepare-handoff.sh +1 -78
- package/scripts/refresh-current-status.sh +2 -467
- package/scripts/run-governed-gate.ts +5 -1
- package/scripts/select-agent-context-blocks.sh +2 -64
- package/scripts/ship-worktrees.sh +1 -558
- package/scripts/smoke-ios-physical-device.ts +4 -2
- package/scripts/smoke-runtime-recovery.ts +1 -35
- package/scripts/smoke-schedule-engine.ts +1 -20
- package/scripts/sprint-backlog.sh +1 -834
- package/scripts/stage-runtime-release.ts +2 -1
- package/scripts/summarize-failures.sh +2 -123
- package/scripts/switch-plan.sh +1 -150
- package/scripts/sync-brain-docs.sh +2 -379
- package/scripts/sync-generated-authority.mjs +175 -0
- package/scripts/verify-contract.sh +2 -703
- package/scripts/verify-forge-runtime.sh +0 -1
- package/scripts/verify-sprint.sh +1 -677
- package/scripts/workflow-contract.ts +4 -205
- package/scripts/workstream-sync.sh +2 -261
- package/src/cli/agent-jobs/executor-health.ts +1 -1
- package/src/cli/commands/init-hook.ts +3 -3
- package/src/cli/commands/mcp.ts +9 -5
- package/src/cli/commands/plugin.ts +12 -3
- package/src/cli/commands/recovery.ts +25 -3
- package/src/cli/commands/runtime.ts +55 -3
- package/src/cli/commands/security.ts +12 -1
- package/src/cli/commands/setup-profile.ts +31 -21
- package/src/cli/controller/check-runner.ts +113 -5
- package/src/cli/controller/composite-result.ts +1 -1
- package/src/cli/controller/context/focus.ts +51 -0
- package/src/cli/controller/context/instruction-context.ts +114 -0
- package/src/cli/controller/context/known-paths.ts +76 -0
- package/src/cli/controller/context/query-planning.ts +110 -0
- package/src/cli/controller/context/rule-resolution.ts +532 -0
- package/src/cli/controller/context/source-materializer.ts +278 -0
- package/src/cli/controller/context/structural.ts +16 -0
- package/src/cli/controller/context/types.ts +286 -0
- package/src/cli/controller/context-pack.ts +828 -487
- package/src/cli/controller/launch-agents.ts +77 -2
- package/src/cli/controller/operational-plan.ts +2 -2
- package/src/cli/controller/work-mode.ts +6 -4
- package/src/cli/editing/edit-session.ts +60 -7
- package/src/cli/github/contracts.ts +16 -0
- package/src/cli/github/github.ts +135 -16
- package/src/cli/github/session.ts +2 -1
- package/src/cli/installer/managed-entries.ts +15 -1
- package/src/cli/local-bridge/console-automations.ts +54 -78
- package/src/cli/local-bridge/console-view-models.ts +1 -35
- package/src/cli/local-bridge/facade-api.ts +37 -264
- package/src/cli/local-bridge/frontend/src/App.tsx +3 -3
- package/src/cli/local-bridge/frontend/src/features/automations/AutomationsView.tsx +23 -13
- package/src/cli/local-bridge/frontend/src/features/capabilities/CapabilitiesView.tsx +37 -4
- package/src/cli/local-bridge/frontend/src/features/overview/OverviewView.tsx +6 -4
- package/src/cli/local-bridge/frontend/src/lib/api.ts +1 -6
- package/src/cli/local-bridge/frontend/src/lib/routes.ts +1 -1
- package/src/cli/local-bridge/frontend/src/shell/Sidebar.tsx +2 -2
- package/src/cli/local-bridge/frontend/src/styles.css +1 -1
- package/src/cli/local-bridge/frontend/src/types.ts +5 -8
- package/src/cli/local-bridge/job-store.ts +1 -490
- package/src/cli/local-bridge/server.ts +2 -515
- package/src/cli/local-bridge/ui-dist/app.css +1 -1
- package/src/cli/local-bridge/ui-dist/app.js +3703 -3757
- package/src/cli/mcp/auth.ts +5 -5
- package/src/cli/mcp/instructions.ts +3 -2
- package/src/cli/mcp/legacy-tool-service.ts +10 -222
- package/src/cli/mcp/multi-repository.ts +16 -5
- package/src/cli/mcp/oauth.ts +175 -26
- package/src/cli/mcp/post-finalize-work-attribution.ts +150 -0
- package/src/cli/mcp/repository-tools.ts +282 -146
- package/src/cli/mcp/server.ts +586 -116
- package/src/cli/mcp/tool-capability-cache.ts +1 -1
- package/src/cli/mcp/tool-contract.ts +14 -0
- package/src/cli/mcp/toolset-selection.ts +1 -1
- package/src/cli/mcp/toolset.ts +44 -7
- package/src/cli/mcp/transports/http.ts +124 -14
- package/src/cli/mcp/transports/session-registry.ts +43 -5
- package/src/cli/mcp/types.ts +3 -3
- package/src/cli/repositories/command-classifier.ts +103 -21
- package/src/cli/repositories/command-executor.ts +78 -526
- package/src/cli/repositories/command-process.ts +108 -0
- package/src/cli/repositories/command-scope.ts +99 -41
- package/src/cli/repositories/controller-home.ts +7 -8
- package/src/cli/repositories/git-command-executor.ts +2 -0
- package/src/cli/repositories/locks.ts +53 -16
- package/src/cli/repositories/repository-snapshot.ts +124 -0
- package/src/cli/repositories/selected-path-actions.ts +17 -9
- package/src/cli/repositories/structured-git.ts +118 -6
- package/src/cli/repository/inspector.ts +563 -65
- package/src/cli/repository/session-cache.ts +58 -17
- package/src/cli/v81-entry.ts +1 -4
- package/src/effects/fs-transaction.ts +85 -17
- package/src/runtime/context/codegraph-read-provider.ts +233 -2
- package/src/runtime/context/codegraph-sidecar.cjs +74 -40
- package/src/runtime/context/generic-lsp-provider.ts +355 -0
- package/src/runtime/context/lsp-client.ts +283 -0
- package/src/runtime/context/semantic-navigation-contract.ts +61 -0
- package/src/runtime/context/semantic-navigation.ts +223 -0
- package/src/runtime/context/swift-navigation.ts +565 -0
- package/src/runtime/context/typescript-navigation.ts +226 -0
- package/src/runtime/control-plane/dispatch-priority.ts +28 -0
- package/src/runtime/control-plane/execution/direct-edit-work-completion.ts +48 -16
- package/src/runtime/control-plane/execution/edit-validation-coordinator.ts +86 -24
- package/src/runtime/control-plane/execution/repository-work-attribution.ts +106 -0
- package/src/runtime/control-plane/execution/retained-work-resume.ts +203 -0
- package/src/runtime/control-plane/execution/session-store.ts +18 -0
- package/src/runtime/control-plane/execution/verification-evidence.ts +58 -3
- package/src/runtime/control-plane/execution/work-completion-authority.ts +58 -0
- package/src/runtime/control-plane/execution/work-evidence-policy.ts +200 -0
- package/src/runtime/control-plane/execution/work-execution-support.ts +386 -0
- package/src/runtime/control-plane/execution/work-finalization-service.ts +1913 -0
- package/src/runtime/control-plane/execution/work-handle-authority.ts +96 -0
- package/src/runtime/control-plane/execution/work-handle-store.ts +27 -2
- package/src/runtime/control-plane/execution/work-lifecycle-audit.ts +258 -0
- package/src/runtime/control-plane/execution/work-operation-service.ts +468 -0
- package/src/runtime/control-plane/execution/work-path-scope.ts +37 -0
- package/src/runtime/control-plane/execution/work-preparation-service.ts +479 -0
- package/src/runtime/control-plane/execution/work-process-evidence.ts +129 -0
- package/src/runtime/control-plane/execution/work-remote-delivery.ts +215 -0
- package/src/runtime/control-plane/execution/work-task-receipt.ts +22 -18
- package/src/runtime/control-plane/execution/work-terminal-cleanup.ts +156 -11
- package/src/runtime/control-plane/execution/work-validation-reconciler.ts +22 -14
- package/src/runtime/control-plane/execution/work-verification-context.ts +56 -0
- package/src/runtime/control-plane/execution/work-verification-service.ts +388 -0
- package/src/runtime/control-plane/execution/work-verification-snapshot.ts +90 -9
- package/src/runtime/control-plane/facade/capability-registry.ts +129 -25
- package/src/runtime/control-plane/facade/controller-round-relay.ts +1118 -0
- package/src/runtime/control-plane/facade/controller-session-store.ts +302 -12
- package/src/runtime/control-plane/facade/goal-workloop-access.ts +17 -1
- package/src/runtime/control-plane/facade/goal-workloop.ts +928 -190
- package/src/runtime/control-plane/facade/index.ts +3 -0
- package/src/runtime/control-plane/facade/plan-contract-store.ts +275 -42
- package/src/runtime/control-plane/facade/repository-work-admission.ts +147 -0
- package/src/runtime/control-plane/facade/requirement-authority.ts +83 -0
- package/src/runtime/control-plane/facade/semantic-admission.ts +205 -0
- package/src/runtime/control-plane/facade/suggested-actions.ts +5 -1
- package/src/runtime/control-plane/facade/types.ts +90 -10
- package/src/runtime/control-plane/facade/work-contract-store.ts +157 -261
- package/src/runtime/control-plane/facade/work-state-machine.ts +250 -0
- package/src/runtime/control-plane/generated-cache-retention.ts +271 -0
- package/src/runtime/control-plane/global-scheduler/config.ts +44 -0
- package/src/runtime/control-plane/global-scheduler/dispatch-capacity.ts +80 -0
- package/src/runtime/control-plane/global-scheduler/durable-admission.ts +46 -0
- package/src/runtime/control-plane/global-scheduler/maintenance.ts +152 -0
- package/src/runtime/control-plane/global-scheduler/projection-refresh.ts +84 -0
- package/src/runtime/control-plane/global-scheduler/reconciliation.ts +3 -3
- package/src/runtime/control-plane/global-scheduler/scheduler.ts +278 -543
- package/src/runtime/control-plane/global-scheduler/source-scan.ts +59 -0
- package/src/runtime/control-plane/global-scheduler/state.ts +88 -0
- package/src/runtime/control-plane/global-scheduler/worker-attachment.ts +57 -0
- package/src/runtime/control-plane/global-scheduler/worker-exit-decision.ts +38 -0
- package/src/runtime/control-plane/global-scheduler/worker-exit-reconciler.ts +175 -0
- package/src/runtime/control-plane/global-scheduler/worker-launch.ts +111 -0
- package/src/runtime/control-plane/global-scheduler/worker-lifecycle-store.ts +64 -0
- package/src/runtime/control-plane/global-scheduler/worker-lifecycle.ts +150 -0
- package/src/runtime/control-plane/global-scheduler/worker-process.ts +119 -0
- package/src/runtime/control-plane/global-scheduler/worker-stderr.ts +60 -0
- package/src/runtime/control-plane/launcher/chatgpt-work-binding-store.ts +63 -0
- package/src/runtime/control-plane/launcher/chatgpt-work-continuation.ts +365 -117
- package/src/runtime/control-plane/launcher/launch-reservation-store.ts +89 -0
- package/src/runtime/control-plane/launcher/thin-launcher.ts +244 -11
- package/src/runtime/control-plane/persistence/controller-home-migration.ts +487 -0
- package/src/runtime/control-plane/persistence/requirement-store.ts +0 -12
- package/src/runtime/control-plane/persistence/sqlite-store.ts +33 -2
- package/src/runtime/control-plane/release-retention.ts +62 -2
- package/src/runtime/control-plane/repo-actor/registry.ts +4 -2
- package/src/runtime/control-plane/routing/route-policy.ts +24 -21
- package/src/runtime/control-plane/routing/workspace-admission.ts +70 -0
- package/src/runtime/control-plane/runtime-status-client.ts +0 -2
- package/src/runtime/diagnostics/mcp-timing.ts +13 -0
- package/src/runtime/diagnostics/mcp-transport-benchmark.ts +129 -0
- package/src/runtime/diagnostics/performance.ts +24 -1
- package/src/runtime/evidence/event-ledger.ts +1 -1
- package/src/runtime/evidence/process-check-execution.ts +18 -0
- package/src/runtime/execution/jobs/child-reference.ts +6 -2
- package/src/runtime/execution/jobs/store.ts +58 -4
- package/src/runtime/execution/jobs/types.ts +1 -1
- package/src/runtime/execution/managed-workspace.ts +203 -1
- package/src/runtime/execution/process-runtime/check-facade.ts +51 -4
- package/src/runtime/execution/process-runtime/check-result.ts +88 -0
- package/src/runtime/execution/process-runtime/check-runner-sidecar.ts +7 -1
- package/src/runtime/execution/process-runtime/check-scheduling.ts +114 -0
- package/src/runtime/execution/process-runtime/command-facade.ts +367 -40
- package/src/runtime/execution/process-runtime/gc.ts +38 -6
- package/src/runtime/execution/process-runtime/lightweight-managed.ts +1201 -0
- package/src/runtime/execution/process-runtime/persisted-check.ts +51 -5
- package/src/runtime/execution/process-runtime/resource-claims.ts +10 -6
- package/src/runtime/execution/process-runtime/runtime.ts +53 -3
- package/src/runtime/execution/process-runtime/store.ts +1 -0
- package/src/runtime/execution/process-runtime/types.ts +4 -12
- package/src/runtime/execution/thin-harness/async-process.ts +12 -2
- package/src/runtime/execution/thin-harness/search-worker.ts +54 -5
- package/src/runtime/execution/work-activity.ts +21 -0
- package/src/runtime/execution/workers/executor.ts +18 -61
- package/src/runtime/gateway/mcp/execution-tools.ts +35 -1852
- package/src/runtime/gateway/mcp/legacy-ios-tool-adapter.ts +61 -0
- package/src/runtime/gateway/mcp/process-tools.ts +83 -37
- package/src/runtime/gateway/mcp/router.ts +186 -84
- package/src/runtime/gateway/mcp/runtime-tool-definitions.ts +565 -0
- package/src/runtime/gateway/mcp/runtime-tools.ts +2378 -1947
- package/src/runtime/plugins/app-store-connect-adapter.ts +216 -47
- package/src/runtime/plugins/browser-adapter.ts +2662 -829
- package/src/runtime/plugins/browser-automation-service.ts +10 -0
- package/src/runtime/plugins/browser-handoff-host.ts +2 -25
- package/src/runtime/plugins/browser-handoff.ts +110 -5
- package/src/runtime/plugins/browser-macos-bridge.ts +701 -63
- package/src/runtime/plugins/browser-manifest-surface.ts +603 -0
- package/src/runtime/plugins/browser-native-session-service.ts +222 -0
- package/src/runtime/plugins/browser-node-bridge.ts +6 -34
- package/src/runtime/plugins/browser-provider-registry.ts +109 -0
- package/src/runtime/plugins/browser-runtime-contract.ts +154 -0
- package/src/runtime/plugins/browser-runtime.ts +193 -0
- package/src/runtime/plugins/browser-session-authority.ts +332 -0
- package/src/runtime/plugins/browser-session-store.ts +121 -0
- package/src/runtime/plugins/browser-session-types.ts +98 -0
- package/src/runtime/plugins/capability-authorization-grants.ts +354 -0
- package/src/runtime/plugins/desktop-operator-registration.ts +10 -4
- package/src/runtime/plugins/external-adapter.ts +358 -3
- package/src/runtime/plugins/external-unix-socket.ts +7 -1
- package/src/runtime/plugins/first-party-registry.ts +2 -0
- package/src/runtime/plugins/github-adapter.ts +125 -0
- package/src/runtime/plugins/ios/agent-device-provider.ts +1 -1
- package/src/runtime/plugins/ios/agent-device-typed-provider.ts +52 -9
- package/src/runtime/plugins/ios/remote-xpc-hid.ts +1171 -0
- package/src/runtime/plugins/ios-adapter.ts +106 -16
- package/src/runtime/plugins/ios-agent-device.ts +234 -64
- package/src/runtime/plugins/ios-physical-device.ts +1143 -392
- package/src/runtime/plugins/lightweight-action.ts +153 -0
- package/src/runtime/plugins/local-system-adapter.ts +123 -6
- package/src/runtime/plugins/macos-capability-broker.ts +47 -9
- package/src/runtime/plugins/plugin-action-sidecar.ts +59 -0
- package/src/runtime/plugins/plugin-management-adapter.ts +49 -8
- package/src/runtime/plugins/resend-adapter.ts +1 -1
- package/src/runtime/plugins/store.ts +330 -33
- package/src/runtime/plugins/types.ts +38 -3
- package/src/runtime/plugins/xiaohongshu-publish.ts +515 -0
- package/src/runtime/projections/git-status-sampler.ts +16 -16
- package/src/runtime/projections/materialized-view.ts +28 -10
- package/src/runtime/recovery/maintenance-executor.ts +426 -25
- package/src/runtime/root/mcp-transport.ts +180 -10
- package/src/runtime/root/package-connector-service.ts +230 -10
- package/src/runtime/root/package-runtime-release.ts +143 -17
- package/src/runtime/root/package-runtime-service.ts +461 -22
- package/src/runtime/root/release-manifest.ts +144 -18
- package/src/runtime/root/release-materialize.ts +125 -32
- package/src/runtime/root/release-store.ts +48 -11
- package/src/runtime/root/runtime.ts +23 -5
- package/src/runtime/root/service.ts +100 -29
- package/src/runtime/root/types.ts +12 -0
- package/src/runtime/safe-tooling/ios-development.ts +321 -63
- package/src/runtime/shared/trusted-executable.ts +62 -0
- package/src/runtime/shared/trusted-node-executable.ts +48 -0
- package/src/runtime/standalone-recovery/core.ts +1079 -240
- package/src/runtime/standalone-recovery/entry.ts +100 -24
- package/src/runtime/standalone-recovery/installer.ts +20 -4
- package/src/runtime/standalone-recovery/service-labels.ts +2 -0
- package/src/runtime/standalone-recovery/watchdog-heartbeat.ts +160 -0
- package/src/runtime/workflow/schedules/browser-probe.ts +81 -3
- package/src/runtime/workflow/schedules/engine.ts +364 -202
- package/src/runtime/workflow/schedules/github-issue-watch.ts +158 -0
- package/src/runtime/workflow/schedules/settlement.ts +64 -17
- package/src/runtime/workflow/schedules/store.ts +209 -19
- package/src/runtime/workflow/schedules/types.ts +2 -4
- package/src/runtime/workflow/schedules/work-continuation.ts +26 -13
- package/src/testing/test-governance.ts +8 -40
- package/assets/reference-configs/heartbeat-triage.md +0 -57
- package/assets/templates/helpers/harness-trace-grade.sh +0 -150
- package/assets/templates/helpers/heartbeat-triage.sh +0 -361
- package/assets/templates/helpers/maintenance-triage.sh +0 -167
- package/docs/architecture/current/approved-target-architecture.zh-CN.md +0 -1501
- package/docs/architecture/current/architecture-invariants.md +0 -331
- package/docs/architecture/current/automation-and-schedule-engine.md +0 -459
- package/docs/architecture/current/codegraph-context-provider.md +0 -238
- package/docs/architecture/current/control-plane-authority-inventory.md +0 -94
- package/docs/architecture/current/controller-repository-decoupling.md +0 -148
- package/docs/architecture/current/dispatch-and-agent-strategy.md +0 -373
- package/docs/architecture/current/entity-model.md +0 -612
- package/docs/architecture/current/external-plugin-governance.md +0 -396
- package/docs/architecture/current/failure-recovery.md +0 -447
- package/docs/architecture/current/governance.md +0 -213
- package/docs/architecture/current/human-interaction-plane.md +0 -87
- package/docs/architecture/current/implementation-status.md +0 -128
- package/docs/architecture/current/job-and-run-lifecycle.md +0 -413
- package/docs/architecture/current/legacy-governance.md +0 -58
- package/docs/architecture/current/local-workspace-target-grants.md +0 -70
- package/docs/architecture/current/migration-roadmap.md +0 -105
- package/docs/architecture/current/multi-repository-execution.md +0 -371
- package/docs/architecture/current/operations-runbook.md +0 -45
- package/docs/architecture/current/peer-supercontroller-runtime.md +0 -32
- package/docs/architecture/current/personal-assistant-plugin-baseline.md +0 -206
- package/docs/architecture/current/repository-access-modes.md +0 -102
- package/docs/architecture/current/route-policy.md +0 -15
- package/docs/architecture/current/route-session-concurrency.md +0 -85
- package/docs/architecture/current/runtime-architecture-simplification.md +0 -214
- package/docs/architecture/current/runtime-directory-map.md +0 -49
- package/docs/architecture/current/runtime-health-and-resource-lifecycle.md +0 -85
- package/docs/architecture/current/scheduler-and-resource-claims.md +0 -422
- package/docs/architecture/current/session-aware-execution-and-authorization.md +0 -77
- package/docs/architecture/current/system-overview.md +0 -169
- package/docs/architecture/current/target-requirements-traceability.md +0 -202
- package/docs/architecture/current/thin-harness-governance-policy.md +0 -32
- package/docs/architecture/current/thin-harness-v1.md +0 -321
- package/docs/architecture/current/verification-and-release-gates.md +0 -391
- package/docs/forge-autonomous-goal-loop.md +0 -9
- package/docs/forge-provider-configuration.md +0 -7
- package/docs/operations/chatgpt-personal-assistant-runtime.md +0 -93
- package/docs/operations/gmail-assistant-routines.md +0 -186
- package/docs/operations/personal-assistant-operator-guide.md +0 -61
- package/docs/operations/provider-configuration.md +0 -31
- package/scripts/harness-trace-grade.sh +0 -150
- package/scripts/heartbeat-triage.sh +0 -361
- package/scripts/maintenance-triage.sh +0 -167
- package/src/cli/local-bridge/frontend/src/features/settings/SettingsView.tsx +0 -2
- package/src/cli/repositories/goal-registry.ts +0 -239
- package/src/runtime/assistant/action-proposals.ts +0 -279
- package/src/runtime/assistant/intent.ts +0 -395
- package/src/runtime/assistant/model-provider.ts +0 -460
- package/src/runtime/assistant/openapi.ts +0 -223
- package/src/runtime/assistant/policy.ts +0 -89
- package/src/runtime/assistant/readiness.ts +0 -258
- package/src/runtime/assistant/routine-runtime.ts +0 -477
- package/src/runtime/assistant/schedule-binding.ts +0 -171
- package/src/runtime/assistant/standing-grants.ts +0 -375
- package/src/runtime/assistant/store.ts +0 -243
- package/src/runtime/assistant/types.ts +0 -135
- package/src/runtime/control-plane/goal-loop/config-facade.ts +0 -700
- package/src/runtime/control-plane/goal-loop/config-store.ts +0 -570
- package/src/runtime/control-plane/goal-loop/config-types.ts +0 -213
- package/src/runtime/control-plane/goal-loop/executor-router.ts +0 -109
- package/src/runtime/control-plane/goal-loop/failure-taxonomy.ts +0 -149
- package/src/runtime/control-plane/goal-loop/goal-contract-store.ts +0 -304
- package/src/runtime/control-plane/goal-loop/goal-loop-engine.ts +0 -1001
- package/src/runtime/control-plane/goal-loop/handoff-packet.ts +0 -160
- package/src/runtime/control-plane/goal-loop/index.ts +0 -13
- package/src/runtime/control-plane/goal-loop/local-tools.ts +0 -290
- package/src/runtime/control-plane/goal-loop/policy-gates.ts +0 -203
- package/src/runtime/control-plane/goal-loop/provider-dispatch.ts +0 -93
- package/src/runtime/control-plane/goal-loop/provider-registry.ts +0 -545
- package/src/runtime/control-plane/goal-loop/types.ts +0 -378
- package/src/runtime/control-plane/startup-recovery.ts +0 -198
- package/src/runtime/gateway/mcp/resource-policy.ts +0 -186
- package/src/runtime/personal-assistant/gmail-triage-manager.ts +0 -231
- package/src/runtime/personal-assistant/reporting-runtime.ts +0 -344
- package/src/runtime/personal-assistant/triage-runtime.ts +0 -748
- package/src/runtime/workflow/findings/store.ts +0 -204
- package/src/runtime/workflow/findings/types.ts +0 -58
- package/src/runtime/workflow/portfolio/engine.ts +0 -20
- package/src/runtime/workflow/portfolio/store.ts +0 -185
- package/src/runtime/workflow/portfolio/types.ts +0 -29
|
@@ -12,16 +12,17 @@ import {
|
|
|
12
12
|
writeControlPlaneRecordWithinTransaction,
|
|
13
13
|
} from '../persistence/sqlite-store';
|
|
14
14
|
import { assertWorkAdmissionAllowed } from './work-admission-policy';
|
|
15
|
+
import { phaseIndex, suggestedActionsForStatus, transitionPhaseEvidence, validateWorkSemanticTransition, validateWorkSemantics } from './work-state-machine';
|
|
15
16
|
import {
|
|
16
17
|
type EvidenceRef,
|
|
17
18
|
type CompletionOutcome,
|
|
18
19
|
type DispatchState,
|
|
19
20
|
type EvidenceState,
|
|
20
21
|
type PolicyDecision,
|
|
21
|
-
type SubmittedWorkOperation,
|
|
22
22
|
type SuggestedNextAction,
|
|
23
23
|
type VerificationRecord,
|
|
24
24
|
type WorkReconciliationRecord,
|
|
25
|
+
type SubmittedWorkOperation,
|
|
25
26
|
type WorkContract,
|
|
26
27
|
type WorkContractStatus,
|
|
27
28
|
type WorkRisk,
|
|
@@ -32,7 +33,6 @@ import {
|
|
|
32
33
|
type WorkPhaseEvidenceState,
|
|
33
34
|
type WorkContractStore,
|
|
34
35
|
isDirectEditWorkCompletionReceipt,
|
|
35
|
-
isRemoteEffectCompletionReceipt,
|
|
36
36
|
isRepositoryCompletionReceipt,
|
|
37
37
|
isTerminalWorkContractStatus,
|
|
38
38
|
} from './types';
|
|
@@ -173,10 +173,6 @@ function inferredEvidenceState(status: WorkContractStatus): EvidenceState {
|
|
|
173
173
|
return 'none';
|
|
174
174
|
}
|
|
175
175
|
|
|
176
|
-
function phaseIndex(phase: WorkPhase): number {
|
|
177
|
-
return ['implementation', 'verification', 'delivery', 'cleanup'].indexOf(phase);
|
|
178
|
-
}
|
|
179
|
-
|
|
180
176
|
function legacyPhaseEvidence(
|
|
181
177
|
contract: Pick<WorkContract, 'phase' | 'status' | 'evidenceRefs' | 'completionReceipt' | 'updatedAt'>,
|
|
182
178
|
source: WorkPhaseEvidence['source'] = 'legacy_inferred',
|
|
@@ -207,191 +203,6 @@ function legacyPhaseEvidence(
|
|
|
207
203
|
})) as WorkPhaseEvidenceMap;
|
|
208
204
|
}
|
|
209
205
|
|
|
210
|
-
function transitionPhaseEvidence(
|
|
211
|
-
current: Pick<WorkContract, 'phaseEvidence' | 'evidenceRefs'>,
|
|
212
|
-
targetPhase: WorkPhase,
|
|
213
|
-
input: {
|
|
214
|
-
status: WorkContractStatus;
|
|
215
|
-
summary: string;
|
|
216
|
-
evidenceRefs?: EvidenceRef[];
|
|
217
|
-
recordedAt: string;
|
|
218
|
-
source?: WorkPhaseEvidence['source'];
|
|
219
|
-
},
|
|
220
|
-
): WorkPhaseEvidenceMap {
|
|
221
|
-
const targetIndex = phaseIndex(targetPhase);
|
|
222
|
-
const evidenceRefs = (input.evidenceRefs ?? current.evidenceRefs).slice(0, 20);
|
|
223
|
-
const source = input.source ?? 'recorded';
|
|
224
|
-
const phaseEvidence = { ...current.phaseEvidence };
|
|
225
|
-
for (const phase of ['implementation', 'verification', 'delivery', 'cleanup'] as WorkPhase[]) {
|
|
226
|
-
const index = phaseIndex(phase);
|
|
227
|
-
if (index < targetIndex) {
|
|
228
|
-
phaseEvidence[phase] = {
|
|
229
|
-
state: ['satisfied', 'skipped'].includes(phaseEvidence[phase].state) ? phaseEvidence[phase].state : 'satisfied',
|
|
230
|
-
source,
|
|
231
|
-
summary: `Advanced to ${targetPhase}: ${input.summary}`.slice(0, 1_000),
|
|
232
|
-
evidenceRefs,
|
|
233
|
-
recordedAt: input.recordedAt,
|
|
234
|
-
};
|
|
235
|
-
} else if (index > targetIndex) {
|
|
236
|
-
phaseEvidence[phase] = {
|
|
237
|
-
state: 'pending',
|
|
238
|
-
source,
|
|
239
|
-
summary: `Waiting for Work phase ${phase}.`,
|
|
240
|
-
evidenceRefs: [],
|
|
241
|
-
recordedAt: input.recordedAt,
|
|
242
|
-
};
|
|
243
|
-
}
|
|
244
|
-
}
|
|
245
|
-
phaseEvidence[targetPhase] = {
|
|
246
|
-
state: input.status === 'failed'
|
|
247
|
-
? 'failed'
|
|
248
|
-
: input.status === 'cancelled'
|
|
249
|
-
? 'skipped'
|
|
250
|
-
: input.status === 'blocked' || input.status === 'ready'
|
|
251
|
-
? 'blocked'
|
|
252
|
-
: 'active',
|
|
253
|
-
source,
|
|
254
|
-
summary: input.summary.trim().slice(0, 1_000) || `Work entered ${targetPhase}.`,
|
|
255
|
-
evidenceRefs,
|
|
256
|
-
recordedAt: input.recordedAt,
|
|
257
|
-
};
|
|
258
|
-
return phaseEvidence;
|
|
259
|
-
}
|
|
260
|
-
|
|
261
|
-
function validateWorkSemantics(contract: WorkContract): WorkContract {
|
|
262
|
-
if (!contract.objective.trim()) throw new Error('WORK_OBJECTIVE_REQUIRED');
|
|
263
|
-
if (contract.status === 'completed' && !contract.completionReceipt) {
|
|
264
|
-
throw new Error('WORK_COMPLETION_RECEIPT_REQUIRED');
|
|
265
|
-
}
|
|
266
|
-
const currentPhaseIndex = phaseIndex(contract.phase);
|
|
267
|
-
for (const phase of ['implementation', 'verification', 'delivery', 'cleanup'] as WorkPhase[]) {
|
|
268
|
-
const checkpoint = contract.phaseEvidence?.[phase];
|
|
269
|
-
if (!checkpoint) throw new Error(`WORK_PHASE_EVIDENCE_REQUIRED: ${phase}`);
|
|
270
|
-
const index = phaseIndex(phase);
|
|
271
|
-
if (index < currentPhaseIndex && !['satisfied', 'skipped'].includes(checkpoint.state)) {
|
|
272
|
-
throw new Error(`WORK_PHASE_EVIDENCE_PREVIOUS_NOT_SATISFIED: ${phase}`);
|
|
273
|
-
}
|
|
274
|
-
if (index === currentPhaseIndex && checkpoint.state === 'pending') {
|
|
275
|
-
throw new Error(`WORK_PHASE_EVIDENCE_REQUIRED: ${phase}`);
|
|
276
|
-
}
|
|
277
|
-
if (index > currentPhaseIndex && checkpoint.state !== 'pending') {
|
|
278
|
-
throw new Error(`WORK_PHASE_EVIDENCE_FUTURE_NOT_PENDING: ${phase}`);
|
|
279
|
-
}
|
|
280
|
-
}
|
|
281
|
-
if (contract.completionReceipt) {
|
|
282
|
-
const receipt = contract.completionReceipt;
|
|
283
|
-
if (receipt.workId !== contract.workId) throw new Error('WORK_COMPLETION_RECEIPT_IDENTITY_MISMATCH');
|
|
284
|
-
if (isRepositoryCompletionReceipt(receipt)) {
|
|
285
|
-
if (!receipt.targetBranch.trim() || !receipt.targetRevision.trim()) throw new Error('WORK_COMPLETION_RECEIPT_TARGET_REQUIRED');
|
|
286
|
-
if (receipt.delivery.status !== 'integrated' || !receipt.delivery.reachable) throw new Error('WORK_COMPLETION_RECEIPT_DELIVERY_NOT_PROVEN');
|
|
287
|
-
if (!['complete', 'maintenance_warning'].includes(receipt.cleanup.status) || receipt.cleanup.blockers.length > 0) throw new Error('WORK_COMPLETION_RECEIPT_CLEANUP_NOT_PROVEN');
|
|
288
|
-
} else if (isDirectEditWorkCompletionReceipt(receipt)) {
|
|
289
|
-
const directEditAuthorityCount = Number(Boolean(receipt.editSessionId?.trim())) + Number(Boolean(receipt.reconciliationId?.trim()));
|
|
290
|
-
if (directEditAuthorityCount !== 1) throw new Error('WORK_COMPLETION_RECEIPT_DIRECT_EDIT_AUTHORITY_REQUIRED');
|
|
291
|
-
if (!receipt.targetBranch.trim() || !receipt.targetRevision.trim()) throw new Error('WORK_COMPLETION_RECEIPT_TARGET_REQUIRED');
|
|
292
|
-
if (receipt.delivery.status !== 'integrated' || !receipt.delivery.reachable) throw new Error('WORK_COMPLETION_RECEIPT_DELIVERY_NOT_PROVEN');
|
|
293
|
-
if (!['complete', 'maintenance_warning'].includes(receipt.cleanup.status) || receipt.cleanup.blockers.length > 0) throw new Error('WORK_COMPLETION_RECEIPT_CLEANUP_NOT_PROVEN');
|
|
294
|
-
if (!['repository_change', 'completed_no_change'].includes(contract.workKind)) throw new Error('WORK_COMPLETION_RECEIPT_DIRECT_EDIT_KIND_REQUIRED');
|
|
295
|
-
const expectedOutcome = contract.workKind === 'completed_no_change' ? 'completed_no_change' : 'completed_changed';
|
|
296
|
-
if (contract.completionOutcome !== expectedOutcome) throw new Error('WORK_COMPLETION_RECEIPT_DIRECT_EDIT_OUTCOME_REQUIRED');
|
|
297
|
-
} else if (isRemoteEffectCompletionReceipt(receipt)) {
|
|
298
|
-
if (contract.workKind !== 'remote_effect') throw new Error('WORK_COMPLETION_RECEIPT_REMOTE_EFFECT_KIND_REQUIRED');
|
|
299
|
-
if (contract.completionOutcome !== 'completed_remote') throw new Error('WORK_COMPLETION_RECEIPT_REMOTE_EFFECT_OUTCOME_REQUIRED');
|
|
300
|
-
if (!receipt.pluginId.trim() || !receipt.actionId.trim() || !receipt.requestId.trim() || !receipt.semanticKey.trim() || !receipt.resultDigest.trim()) {
|
|
301
|
-
throw new Error('WORK_COMPLETION_RECEIPT_REMOTE_EFFECT_IDENTITY_REQUIRED');
|
|
302
|
-
}
|
|
303
|
-
} else {
|
|
304
|
-
if (contract.workKind !== 'local_effect') throw new Error('WORK_COMPLETION_RECEIPT_LOCAL_EFFECT_KIND_REQUIRED');
|
|
305
|
-
if (contract.completionOutcome !== 'completed_local') throw new Error('WORK_COMPLETION_RECEIPT_LOCAL_EFFECT_OUTCOME_REQUIRED');
|
|
306
|
-
if (!receipt.operation.trim() || !receipt.target.id.trim()) throw new Error('WORK_COMPLETION_RECEIPT_LOCAL_EFFECT_TARGET_REQUIRED');
|
|
307
|
-
}
|
|
308
|
-
if (contract.status !== 'completed') throw new Error('WORK_COMPLETION_RECEIPT_REQUIRES_COMPLETED_WORK');
|
|
309
|
-
for (const phase of ['implementation', 'verification', 'delivery', 'cleanup'] as WorkPhase[]) {
|
|
310
|
-
if (!['satisfied', 'skipped'].includes(contract.phaseEvidence[phase].state)) {
|
|
311
|
-
throw new Error(`WORK_COMPLETION_PHASE_NOT_SATISFIED: ${phase}`);
|
|
312
|
-
}
|
|
313
|
-
}
|
|
314
|
-
for (const phase of ['delivery', 'cleanup'] as WorkPhase[]) {
|
|
315
|
-
if (contract.phaseEvidence[phase].receiptId !== receipt.receiptId) {
|
|
316
|
-
throw new Error(`WORK_COMPLETION_PHASE_RECEIPT_MISMATCH: ${phase}`);
|
|
317
|
-
}
|
|
318
|
-
}
|
|
319
|
-
}
|
|
320
|
-
const outcome = contract.completionOutcome;
|
|
321
|
-
if (!outcome) return contract;
|
|
322
|
-
if (contract.status !== 'completed' || !contract.completionReceipt) {
|
|
323
|
-
throw new Error(`WORK_SEMANTICS_INVALID: ${outcome} requires a completed Work receipt`);
|
|
324
|
-
}
|
|
325
|
-
if (contract.dispatchState !== 'terminal') {
|
|
326
|
-
throw new Error(`WORK_SEMANTICS_INVALID: ${outcome} requires terminal dispatch`);
|
|
327
|
-
}
|
|
328
|
-
if (contract.evidenceState !== 'valid') {
|
|
329
|
-
throw new Error(`WORK_SEMANTICS_INVALID: ${outcome} requires valid evidence`);
|
|
330
|
-
}
|
|
331
|
-
if (outcome === 'completed_changed' && contract.workKind !== 'repository_change') {
|
|
332
|
-
throw new Error('WORK_SEMANTICS_INVALID: completed_changed requires repository_change WorkKind');
|
|
333
|
-
}
|
|
334
|
-
if (outcome === 'completed_no_change' && contract.workKind !== 'completed_no_change') {
|
|
335
|
-
throw new Error('WORK_SEMANTICS_INVALID: completed_no_change requires completed_no_change WorkKind');
|
|
336
|
-
}
|
|
337
|
-
if (outcome === 'completed_local' && contract.workKind !== 'local_effect') {
|
|
338
|
-
throw new Error('WORK_SEMANTICS_INVALID: completed_local requires local_effect WorkKind');
|
|
339
|
-
}
|
|
340
|
-
if (outcome === 'completed_local' && contract.completionReceipt?.source !== 'local_effect') {
|
|
341
|
-
throw new Error('WORK_SEMANTICS_INVALID: completed_local requires a local_effect completion receipt');
|
|
342
|
-
}
|
|
343
|
-
if (outcome === 'completed_remote' && contract.workKind !== 'remote_effect') {
|
|
344
|
-
throw new Error('WORK_SEMANTICS_INVALID: completed_remote requires remote_effect WorkKind');
|
|
345
|
-
}
|
|
346
|
-
if (outcome === 'completed_remote' && contract.completionReceipt?.source !== 'remote_effect') {
|
|
347
|
-
throw new Error('WORK_SEMANTICS_INVALID: completed_remote requires a remote_effect completion receipt');
|
|
348
|
-
}
|
|
349
|
-
if (outcome === 'superseded' && contract.workKind !== 'superseded') {
|
|
350
|
-
throw new Error('WORK_SEMANTICS_INVALID: superseded requires superseded WorkKind');
|
|
351
|
-
}
|
|
352
|
-
return contract;
|
|
353
|
-
}
|
|
354
|
-
|
|
355
|
-
const DISPATCH_TRANSITIONS: Readonly<Record<DispatchState, readonly DispatchState[]>> = {
|
|
356
|
-
not_dispatched: ['not_dispatched', 'claimed', 'launching', 'running', 'blocked', 'terminal'],
|
|
357
|
-
claimed: ['claimed', 'launching', 'running', 'blocked', 'terminal'],
|
|
358
|
-
launching: ['launching', 'running', 'blocked', 'terminal'],
|
|
359
|
-
running: ['running', 'blocked', 'terminal'],
|
|
360
|
-
blocked: ['blocked', 'claimed', 'launching', 'running', 'terminal'],
|
|
361
|
-
terminal: ['terminal'],
|
|
362
|
-
};
|
|
363
|
-
|
|
364
|
-
const EVIDENCE_TRANSITIONS: Readonly<Record<EvidenceState, readonly EvidenceState[]>> = {
|
|
365
|
-
none: ['none', 'partial', 'valid', 'failed'],
|
|
366
|
-
partial: ['partial', 'valid', 'stale', 'contradictory', 'failed'],
|
|
367
|
-
valid: ['valid', 'stale', 'contradictory', 'failed'],
|
|
368
|
-
stale: ['stale', 'partial', 'valid', 'contradictory', 'failed'],
|
|
369
|
-
contradictory: ['contradictory', 'partial', 'valid', 'failed'],
|
|
370
|
-
failed: ['failed', 'partial', 'valid', 'contradictory'],
|
|
371
|
-
};
|
|
372
|
-
|
|
373
|
-
function validateWorkSemanticTransition(current: WorkContract, next: WorkContract): WorkContract {
|
|
374
|
-
const retryingFailedWork = current.status === 'failed'
|
|
375
|
-
&& !current.completionOutcome
|
|
376
|
-
&& ['claimed', 'launching', 'running', 'blocked'].includes(next.dispatchState);
|
|
377
|
-
if (!retryingFailedWork && !DISPATCH_TRANSITIONS[current.dispatchState].includes(next.dispatchState)) {
|
|
378
|
-
throw new Error(`WORK_SEMANTICS_TRANSITION_INVALID: dispatch ${current.dispatchState} -> ${next.dispatchState}`);
|
|
379
|
-
}
|
|
380
|
-
if (!EVIDENCE_TRANSITIONS[current.evidenceState].includes(next.evidenceState)) {
|
|
381
|
-
throw new Error(`WORK_SEMANTICS_TRANSITION_INVALID: evidence ${current.evidenceState} -> ${next.evidenceState}`);
|
|
382
|
-
}
|
|
383
|
-
if (current.completionOutcome && current.completionOutcome !== next.completionOutcome) {
|
|
384
|
-
throw new Error(`WORK_SEMANTICS_TRANSITION_INVALID: completion outcome ${current.completionOutcome} is immutable`);
|
|
385
|
-
}
|
|
386
|
-
if ((current.lifecycleRole ?? 'primary') !== (next.lifecycleRole ?? 'primary')) {
|
|
387
|
-
throw new Error('WORK_SEMANTICS_TRANSITION_INVALID: lifecycleRole is immutable');
|
|
388
|
-
}
|
|
389
|
-
if (current.parentWorkId !== next.parentWorkId) {
|
|
390
|
-
throw new Error('WORK_SEMANTICS_TRANSITION_INVALID: parentWorkId is immutable');
|
|
391
|
-
}
|
|
392
|
-
return next;
|
|
393
|
-
}
|
|
394
|
-
|
|
395
206
|
function sqliteBacked(options: WorkContractStoreOptions): options is WorkContractStoreOptions & { controllerHome: string; repoId: string } {
|
|
396
207
|
// A caller-provided root is a test/portable compatibility store. Runtime
|
|
397
208
|
// controller state always carries controllerHome + repoId and is SQLite.
|
|
@@ -429,6 +240,7 @@ function normalizeWorkContractStore(store: WorkContractStore): WorkContractStore
|
|
|
429
240
|
workKind: legacy.workKind ?? 'repository_change',
|
|
430
241
|
dispatchState: legacy.dispatchState ?? inferredDispatchState(status),
|
|
431
242
|
evidenceState: legacy.evidenceState ?? inferredEvidenceState(status),
|
|
243
|
+
suggestedNextActions: suggestedActionsForStatus(status, legacy.suggestedNextActions ?? []),
|
|
432
244
|
reconciliations: legacy.reconciliations ?? [],
|
|
433
245
|
driver: (legacy.driver as unknown as { preferred?: string } | undefined)?.preferred === 'codex_worker'
|
|
434
246
|
? { ...legacy.driver, preferred: 'external_controller', allowWorker: false }
|
|
@@ -541,7 +353,7 @@ export function createWorkContract(options: WorkContractStoreOptions, input: Cre
|
|
|
541
353
|
if (input.status === 'completed' || input.completionReceipt || input.completionOutcome) {
|
|
542
354
|
throw new Error('WORK_COMPLETION_REQUIRES_RECORD_API');
|
|
543
355
|
}
|
|
544
|
-
|
|
356
|
+
const create = (): WorkContract => {
|
|
545
357
|
const at = input.createdAt ?? input.updatedAt ?? nowIso(options);
|
|
546
358
|
const workId = sanitizeFileComponent(input.workId);
|
|
547
359
|
const contract: WorkContract = validateWorkSemantics({
|
|
@@ -585,6 +397,12 @@ export function createWorkContract(options: WorkContractStoreOptions, input: Cre
|
|
|
585
397
|
planStepId: input.planStepId,
|
|
586
398
|
planSourceRevision: input.planSourceRevision,
|
|
587
399
|
scopeSummary: input.scopeSummary?.slice(0, 1_000),
|
|
400
|
+
scopeEvidence: input.scopeEvidence ? {
|
|
401
|
+
initialLikelyPaths: [...new Set(input.scopeEvidence.initialLikelyPaths)].slice(0, 100),
|
|
402
|
+
inspectedPaths: [...new Set(input.scopeEvidence.inspectedPaths)].slice(0, 500),
|
|
403
|
+
actualChangedPaths: [...new Set(input.scopeEvidence.actualChangedPaths)].slice(0, 500),
|
|
404
|
+
recordedAt: input.scopeEvidence.recordedAt,
|
|
405
|
+
} : undefined,
|
|
588
406
|
allowedPaths: (input.allowedPaths ?? []).slice(0, 50),
|
|
589
407
|
forbiddenPaths: (input.forbiddenPaths ?? []).slice(0, 50),
|
|
590
408
|
checks: (input.checks ?? []).slice(0, 30),
|
|
@@ -618,6 +436,23 @@ export function createWorkContract(options: WorkContractStoreOptions, input: Cre
|
|
|
618
436
|
submittedOperation: input.submittedOperation,
|
|
619
437
|
});
|
|
620
438
|
|
|
439
|
+
if (sqliteBacked(options)) {
|
|
440
|
+
withControlPlaneTransaction(options.controllerHome, (database) => {
|
|
441
|
+
if (readControlPlaneRecordWithinTransaction<WorkContract>(database, 'work_contract', options.repoId, contract.workId)) {
|
|
442
|
+
throw new Error(`work contract already exists: ${contract.workId}`);
|
|
443
|
+
}
|
|
444
|
+
writeControlPlaneRecordWithinTransaction(database, {
|
|
445
|
+
namespace: 'work_contract',
|
|
446
|
+
scope: options.repoId,
|
|
447
|
+
key: contract.workId,
|
|
448
|
+
schemaVersion: 2,
|
|
449
|
+
value: contract,
|
|
450
|
+
action: 'work_contract_created',
|
|
451
|
+
expectedRevision: null,
|
|
452
|
+
});
|
|
453
|
+
});
|
|
454
|
+
return contract;
|
|
455
|
+
}
|
|
621
456
|
const store = readWorkContractStore(options);
|
|
622
457
|
if (store.contracts.some((existing) => existing.workId === contract.workId)) {
|
|
623
458
|
throw new Error(`work contract already exists: ${contract.workId}`);
|
|
@@ -629,7 +464,8 @@ export function createWorkContract(options: WorkContractStoreOptions, input: Cre
|
|
|
629
464
|
};
|
|
630
465
|
writeWorkContractStore(options, nextStore);
|
|
631
466
|
return contract;
|
|
632
|
-
}
|
|
467
|
+
};
|
|
468
|
+
return create();
|
|
633
469
|
}
|
|
634
470
|
|
|
635
471
|
interface WorkRequestIndexRecord {
|
|
@@ -647,26 +483,6 @@ function workRequestIndexPath(controllerHome: string, requestId: string): string
|
|
|
647
483
|
return join(root, `${hash}.json`);
|
|
648
484
|
}
|
|
649
485
|
|
|
650
|
-
export interface AcceptSubmittedWorkInput {
|
|
651
|
-
requestId: string;
|
|
652
|
-
repoId: string;
|
|
653
|
-
parentWorkId?: string;
|
|
654
|
-
semanticKey: string;
|
|
655
|
-
operation: SubmittedWorkOperation;
|
|
656
|
-
objective?: string;
|
|
657
|
-
mode?: WorkContract['mode'];
|
|
658
|
-
requestedBy?: WorkContract['requestedBy'];
|
|
659
|
-
principalId?: string;
|
|
660
|
-
controllerInstanceId?: string;
|
|
661
|
-
workKind?: WorkKind;
|
|
662
|
-
risk?: WorkRisk;
|
|
663
|
-
allowedPaths?: string[];
|
|
664
|
-
forbiddenPaths?: string[];
|
|
665
|
-
checks?: string[];
|
|
666
|
-
acceptanceCriteria?: string[];
|
|
667
|
-
constraints?: WorkContract['constraints'];
|
|
668
|
-
}
|
|
669
|
-
|
|
670
486
|
export function getWorkContractByRequestId(
|
|
671
487
|
controllerHome: string,
|
|
672
488
|
requestId: string,
|
|
@@ -687,8 +503,8 @@ export function getWorkContractByRequestId(
|
|
|
687
503
|
}
|
|
688
504
|
|
|
689
505
|
/**
|
|
690
|
-
*
|
|
691
|
-
*
|
|
506
|
+
* Create or reuse the execution-child Work used by typed callers. This is not
|
|
507
|
+
* a generic MCP submission authority and never creates an ExecutionJob.
|
|
692
508
|
*/
|
|
693
509
|
export function acceptSubmittedWorkContract(
|
|
694
510
|
controllerHome: string,
|
|
@@ -696,20 +512,12 @@ export function acceptSubmittedWorkContract(
|
|
|
696
512
|
options: WorkContractStoreOptions = {},
|
|
697
513
|
): { contract: WorkContract; deduplicated: boolean } {
|
|
698
514
|
const home = ensureControllerHome(controllerHome);
|
|
699
|
-
const
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
if (!
|
|
705
|
-
throw new Error('INVALID_ARGUMENT: work_submit requires a semantic operation key');
|
|
706
|
-
}
|
|
707
|
-
if (!input.repoId.trim()) {
|
|
708
|
-
throw new Error('INVALID_ARGUMENT: work_submit is missing required argument(s): repo_id');
|
|
709
|
-
}
|
|
710
|
-
if (!input.operation?.name?.trim()) {
|
|
711
|
-
throw new Error('INVALID_ARGUMENT: work_submit is missing required argument(s): operation');
|
|
712
|
-
}
|
|
515
|
+
const requestId = input.requestId.trim();
|
|
516
|
+
const semanticKey = input.semanticKey.trim();
|
|
517
|
+
if (!requestId) throw new Error('INVALID_ARGUMENT: typed execution is missing request_id');
|
|
518
|
+
if (!semanticKey) throw new Error('INVALID_ARGUMENT: typed execution requires a semantic operation key');
|
|
519
|
+
if (!input.repoId.trim()) throw new Error('INVALID_ARGUMENT: typed execution is missing repo_id');
|
|
520
|
+
if (!input.operation?.name?.trim()) throw new Error('INVALID_ARGUMENT: typed execution is missing operation');
|
|
713
521
|
const parentWorkId = input.parentWorkId?.trim() || undefined;
|
|
714
522
|
if (parentWorkId) {
|
|
715
523
|
const parent = getWorkContract({ controllerHome: home, repoId: input.repoId, now: options.now }, parentWorkId);
|
|
@@ -717,25 +525,17 @@ export function acceptSubmittedWorkContract(
|
|
|
717
525
|
if (isTerminalWorkContractStatus(parent.status)) throw new Error(`PARENT_WORK_TERMINAL: ${parentWorkId}:${parent.status}`);
|
|
718
526
|
if ((parent.lifecycleRole ?? 'primary') !== 'primary') throw new Error(`PARENT_WORK_NOT_PRIMARY: ${parentWorkId}`);
|
|
719
527
|
}
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
const recordPath = workRequestIndexPath(home, normalizedRequestId);
|
|
528
|
+
const lockId = createHash('sha256').update(requestId).digest('hex').slice(0, 24);
|
|
529
|
+
return withControllerLock(home, { scope: 'global', resource: `work-request-${lockId}` }, `accept-work:${requestId}`, () => {
|
|
530
|
+
const recordPath = workRequestIndexPath(home, requestId);
|
|
724
531
|
if (existsSync(recordPath)) {
|
|
725
532
|
const record = readJsonFile<WorkRequestIndexRecord>(recordPath);
|
|
726
|
-
if (record.repoId !== input.repoId) {
|
|
727
|
-
|
|
728
|
-
}
|
|
729
|
-
if (record.semanticKey !== normalizedSemanticKey) {
|
|
730
|
-
throw new Error(`REQUEST_ID_CONFLICT: ${normalizedRequestId} already belongs to ${record.semanticKey}`);
|
|
731
|
-
}
|
|
533
|
+
if (record.repoId !== input.repoId) throw new Error(`REQUEST_ID_REPO_CONFLICT: ${requestId} already belongs to repository ${record.repoId}`);
|
|
534
|
+
if (record.semanticKey !== semanticKey) throw new Error(`REQUEST_ID_CONFLICT: ${requestId} already belongs to ${record.semanticKey}`);
|
|
732
535
|
const existing = getWorkContract({ controllerHome: home, repoId: record.repoId, now: options.now }, record.workId);
|
|
733
|
-
if (!existing) {
|
|
734
|
-
throw new Error(`WORK_ACCEPTANCE_LOST: request ${normalizedRequestId} is indexed without a readable WorkContract`);
|
|
735
|
-
}
|
|
536
|
+
if (!existing) throw new Error(`WORK_ACCEPTANCE_LOST: request ${requestId} is indexed without a readable WorkContract`);
|
|
736
537
|
return { contract: existing, deduplicated: true };
|
|
737
538
|
}
|
|
738
|
-
|
|
739
539
|
const contract = createWorkContract({ controllerHome: home, repoId: input.repoId, now: options.now }, {
|
|
740
540
|
workId: `WORK-${Date.now()}-${randomUUID().slice(0, 8)}`,
|
|
741
541
|
repoId: input.repoId,
|
|
@@ -744,7 +544,7 @@ export function acceptSubmittedWorkContract(
|
|
|
744
544
|
mode: input.mode ?? 'direct_control',
|
|
745
545
|
lifecycleRole: 'execution_child',
|
|
746
546
|
parentWorkId,
|
|
747
|
-
objective: (input.objective ?? `
|
|
547
|
+
objective: (input.objective ?? `Typed operation ${input.operation.name}`).slice(0, 2_000),
|
|
748
548
|
acceptanceCriteria: input.acceptanceCriteria ?? [],
|
|
749
549
|
workKind: input.workKind,
|
|
750
550
|
risk: input.risk,
|
|
@@ -754,13 +554,9 @@ export function acceptSubmittedWorkContract(
|
|
|
754
554
|
checks: input.checks ?? [],
|
|
755
555
|
requestedBy: input.requestedBy ?? 'chatgpt',
|
|
756
556
|
status: 'open',
|
|
757
|
-
requestId
|
|
557
|
+
requestId,
|
|
758
558
|
submittedOperation: input.operation,
|
|
759
|
-
driver: {
|
|
760
|
-
preferred: 'external_controller',
|
|
761
|
-
allowWorker: false,
|
|
762
|
-
allowDirectEdit: input.operation.mode === 'readonly' || input.operation.mode === 'mutating',
|
|
763
|
-
},
|
|
559
|
+
driver: { preferred: 'external_controller', allowWorker: false, allowDirectEdit: input.operation.mode === 'readonly' || input.operation.mode === 'mutating' },
|
|
764
560
|
suggestedNextActions: [{
|
|
765
561
|
label: 'Claim controller ownership',
|
|
766
562
|
tool: 'rh_work',
|
|
@@ -770,15 +566,7 @@ export function acceptSubmittedWorkContract(
|
|
|
770
566
|
reason: 'Claim this Work before launching an external SuperController or Process Runtime command.',
|
|
771
567
|
}],
|
|
772
568
|
});
|
|
773
|
-
|
|
774
|
-
writeJsonAtomic(recordPath, {
|
|
775
|
-
requestId: normalizedRequestId,
|
|
776
|
-
repoId: input.repoId,
|
|
777
|
-
workId: contract.workId,
|
|
778
|
-
semanticKey: normalizedSemanticKey,
|
|
779
|
-
createdAt: contract.createdAt,
|
|
780
|
-
} satisfies WorkRequestIndexRecord);
|
|
781
|
-
|
|
569
|
+
writeJsonAtomic(recordPath, { requestId, repoId: input.repoId, workId: contract.workId, semanticKey, createdAt: contract.createdAt } satisfies WorkRequestIndexRecord);
|
|
782
570
|
return { contract, deduplicated: false };
|
|
783
571
|
});
|
|
784
572
|
}
|
|
@@ -809,6 +597,8 @@ function wasPausedByRuntimeReconciliation(contract: WorkContract): boolean {
|
|
|
809
597
|
|
|
810
598
|
function hasReviewableWorkOutput(contract: WorkContract): boolean {
|
|
811
599
|
if (contract.checkRefs.length > 0 || contract.handoffRefs.length > 0) return true;
|
|
600
|
+
if ((contract.scopeEvidence?.inspectedPaths.length ?? 0) > 0) return true;
|
|
601
|
+
if ((contract.readOnlyReviewEvidence?.inspectedPaths.length ?? 0) > 0 || (contract.readOnlyReviewEvidence?.findings.length ?? 0) > 0) return true;
|
|
812
602
|
return contract.evidenceRefs.some((evidence) =>
|
|
813
603
|
Boolean(evidence.artifactId || evidence.evidenceId)
|
|
814
604
|
|| !SYSTEM_ONLY_EVIDENCE_TITLES.has(evidence.title));
|
|
@@ -965,6 +755,7 @@ function updateWorkContractInternal(
|
|
|
965
755
|
patch: Partial<Omit<WorkContract, 'schemaVersion' | 'workId' | 'repoId' | 'createdAt'>>,
|
|
966
756
|
allowCompletionWrite: boolean,
|
|
967
757
|
allowPhaseWrite = false,
|
|
758
|
+
allowRetainedCancelledResume = false,
|
|
968
759
|
): WorkContract {
|
|
969
760
|
return withWorkContractStoreWrite(options, () => {
|
|
970
761
|
const sanitizedId = sanitizeFileComponent(workId);
|
|
@@ -1022,13 +813,13 @@ function updateWorkContractInternal(
|
|
|
1022
813
|
completionOutcome: patch.completionOutcome ?? current.completionOutcome,
|
|
1023
814
|
evidenceRefs: (patch.evidenceRefs ?? current.evidenceRefs).slice(0, current.evidencePolicy.maxEvidenceRefs),
|
|
1024
815
|
handoffRefs: (patch.handoffRefs ?? current.handoffRefs).slice(0, 20),
|
|
1025
|
-
suggestedNextActions: (patch.suggestedNextActions ?? current.suggestedNextActions)
|
|
816
|
+
suggestedNextActions: suggestedActionsForStatus(patch.status ?? current.status, patch.suggestedNextActions ?? current.suggestedNextActions),
|
|
1026
817
|
policyDecisions: (patch.policyDecisions ?? current.policyDecisions).slice(0, 20),
|
|
1027
818
|
checkRefs: (patch.checkRefs ?? current.checkRefs).slice(0, 50),
|
|
1028
819
|
reconciliations: (patch.reconciliations ?? current.reconciliations ?? []).slice(0, 20),
|
|
1029
820
|
objective: (patch.objective ?? current.objective).slice(0, 2_000),
|
|
1030
821
|
continuationPrompt: (patch.continuationPrompt ?? current.continuationPrompt)?.slice(0, 2_000),
|
|
1031
|
-
}));
|
|
822
|
+
}), { allowRetainedCancelledResume });
|
|
1032
823
|
const contracts = [...store.contracts];
|
|
1033
824
|
contracts[index] = next;
|
|
1034
825
|
writeWorkContractStore(options, { schemaVersion: 2, updatedAt: at, contracts });
|
|
@@ -1044,6 +835,83 @@ export function updateWorkContract(
|
|
|
1044
835
|
return updateWorkContractInternal(options, workId, patch, false);
|
|
1045
836
|
}
|
|
1046
837
|
|
|
838
|
+
/**
|
|
839
|
+
* Reopen one explicitly retained cancelled repository Work after the facade has
|
|
840
|
+
* reauthenticated the same principal and revalidated physical Work ownership.
|
|
841
|
+
* Generic mutation APIs intentionally cannot perform terminal -> running.
|
|
842
|
+
*/
|
|
843
|
+
export function resumeRetainedCancelledWorkContract(
|
|
844
|
+
options: WorkContractStoreOptions,
|
|
845
|
+
workId: string,
|
|
846
|
+
input: {
|
|
847
|
+
principalId: string;
|
|
848
|
+
controllerInstanceId: string;
|
|
849
|
+
summary: string;
|
|
850
|
+
checkoutId?: string;
|
|
851
|
+
worktreeRef?: string;
|
|
852
|
+
},
|
|
853
|
+
): WorkContract {
|
|
854
|
+
const current = getWorkContract(options, workId);
|
|
855
|
+
if (!current) throw new Error(`work contract not found: ${workId}`);
|
|
856
|
+
if (current.status !== 'cancelled' || current.dispatchState !== 'terminal' || current.phase !== 'cleanup') {
|
|
857
|
+
throw new Error(`WORK_CANCELLED_RESUME_STATUS_INVALID: ${workId}`);
|
|
858
|
+
}
|
|
859
|
+
if (current.workKind !== 'repository_change') throw new Error(`WORK_CANCELLED_RESUME_KIND_INVALID: ${workId}`);
|
|
860
|
+
if (current.completionReceipt || current.completionOutcome) throw new Error(`WORK_CANCELLED_RESUME_COMPLETION_CONFLICT: ${workId}`);
|
|
861
|
+
if (current.phaseEvidence.cleanup.state !== 'skipped' || current.phaseEvidence.cleanup.source !== 'recorded') {
|
|
862
|
+
throw new Error(`WORK_CANCELLED_RESUME_HISTORY_AMBIGUOUS: ${workId}`);
|
|
863
|
+
}
|
|
864
|
+
const originalPrincipal = current.principalId?.trim();
|
|
865
|
+
if (!originalPrincipal || originalPrincipal !== input.principalId.trim()) {
|
|
866
|
+
throw new Error(`WORK_CANCELLED_RESUME_PRINCIPAL_MISMATCH: ${workId}`);
|
|
867
|
+
}
|
|
868
|
+
const at = nowIso(options);
|
|
869
|
+
const evidenceRefs = [...current.evidenceRefs, {
|
|
870
|
+
title: 'explicit current-user Work reauthorization',
|
|
871
|
+
summary: input.summary.trim().slice(0, 1_000),
|
|
872
|
+
detailLevel: 'summary' as const,
|
|
873
|
+
}].slice(-current.evidencePolicy.maxEvidenceRefs);
|
|
874
|
+
const phaseEvidence = transitionPhaseEvidence({ ...current, evidenceRefs }, 'implementation', {
|
|
875
|
+
status: 'running',
|
|
876
|
+
summary: input.summary,
|
|
877
|
+
evidenceRefs,
|
|
878
|
+
recordedAt: at,
|
|
879
|
+
source: 'recorded',
|
|
880
|
+
});
|
|
881
|
+
return updateWorkContractInternal(options, workId, {
|
|
882
|
+
status: 'running',
|
|
883
|
+
phase: 'implementation',
|
|
884
|
+
phaseEvidence,
|
|
885
|
+
dispatchState: 'running',
|
|
886
|
+
evidenceRefs,
|
|
887
|
+
checkoutId: input.checkoutId ?? current.checkoutId,
|
|
888
|
+
worktreeRef: input.worktreeRef ?? current.worktreeRef,
|
|
889
|
+
controllerInstanceId: input.controllerInstanceId,
|
|
890
|
+
continuationPrompt: input.summary,
|
|
891
|
+
}, false, true, true);
|
|
892
|
+
}
|
|
893
|
+
|
|
894
|
+
/** Merge non-authoritative discovery/change evidence without changing policy fences. */
|
|
895
|
+
export function recordWorkScopeEvidence(
|
|
896
|
+
options: WorkContractStoreOptions,
|
|
897
|
+
workId: string,
|
|
898
|
+
input: { initialLikelyPaths?: string[]; inspectedPaths?: string[]; actualChangedPaths?: string[] },
|
|
899
|
+
): WorkContract {
|
|
900
|
+
const current = getWorkContract(options, workId);
|
|
901
|
+
if (!current) throw new Error(`work contract not found: ${workId}`);
|
|
902
|
+
const previous = current.scopeEvidence ?? {
|
|
903
|
+
initialLikelyPaths: [], inspectedPaths: [], actualChangedPaths: [], recordedAt: current.createdAt,
|
|
904
|
+
};
|
|
905
|
+
return updateWorkContract(options, workId, {
|
|
906
|
+
scopeEvidence: {
|
|
907
|
+
initialLikelyPaths: [...new Set([...previous.initialLikelyPaths, ...(input.initialLikelyPaths ?? [])])].slice(0, 100),
|
|
908
|
+
inspectedPaths: [...new Set([...previous.inspectedPaths, ...(input.inspectedPaths ?? [])])].slice(0, 500),
|
|
909
|
+
actualChangedPaths: [...new Set([...previous.actualChangedPaths, ...(input.actualChangedPaths ?? [])])].slice(0, 500),
|
|
910
|
+
recordedAt: nowIso(options),
|
|
911
|
+
},
|
|
912
|
+
});
|
|
913
|
+
}
|
|
914
|
+
|
|
1047
915
|
export function transitionWorkContractPhase(
|
|
1048
916
|
options: WorkContractStoreOptions,
|
|
1049
917
|
workId: string,
|
|
@@ -1126,6 +994,9 @@ export function recordWorkCompletionReceipt(
|
|
|
1126
994
|
return current;
|
|
1127
995
|
}
|
|
1128
996
|
const recordedAt = receipt.recordedAt;
|
|
997
|
+
const receiptChangedPaths = isRepositoryCompletionReceipt(receipt) || isDirectEditWorkCompletionReceipt(receipt)
|
|
998
|
+
? receipt.changedPaths
|
|
999
|
+
: [];
|
|
1129
1000
|
const phaseEvidence = Object.fromEntries((['implementation', 'verification', 'delivery', 'cleanup'] as WorkPhase[]).map((phase) => [phase, {
|
|
1130
1001
|
state: 'satisfied',
|
|
1131
1002
|
source: 'recorded',
|
|
@@ -1143,5 +1014,30 @@ export function recordWorkCompletionReceipt(
|
|
|
1143
1014
|
completionOutcome,
|
|
1144
1015
|
...(completionWorkKind ? { workKind: completionWorkKind } : {}),
|
|
1145
1016
|
completionReceipt: receipt,
|
|
1017
|
+
scopeEvidence: {
|
|
1018
|
+
initialLikelyPaths: current.scopeEvidence?.initialLikelyPaths ?? current.allowedPaths,
|
|
1019
|
+
inspectedPaths: current.scopeEvidence?.inspectedPaths ?? [],
|
|
1020
|
+
actualChangedPaths: [...new Set(receiptChangedPaths)].slice(0, 500),
|
|
1021
|
+
recordedAt,
|
|
1022
|
+
},
|
|
1146
1023
|
}, true, true);
|
|
1147
1024
|
}
|
|
1025
|
+
export interface AcceptSubmittedWorkInput {
|
|
1026
|
+
requestId: string;
|
|
1027
|
+
repoId: string;
|
|
1028
|
+
parentWorkId?: string;
|
|
1029
|
+
semanticKey: string;
|
|
1030
|
+
operation: SubmittedWorkOperation;
|
|
1031
|
+
objective?: string;
|
|
1032
|
+
mode?: WorkContract['mode'];
|
|
1033
|
+
requestedBy?: WorkContract['requestedBy'];
|
|
1034
|
+
principalId?: string;
|
|
1035
|
+
controllerInstanceId?: string;
|
|
1036
|
+
workKind?: WorkKind;
|
|
1037
|
+
risk?: WorkRisk;
|
|
1038
|
+
allowedPaths?: string[];
|
|
1039
|
+
forbiddenPaths?: string[];
|
|
1040
|
+
checks?: string[];
|
|
1041
|
+
acceptanceCriteria?: string[];
|
|
1042
|
+
constraints?: WorkContract['constraints'];
|
|
1043
|
+
}
|