@moretea-labs/forge 1.8.1 → 1.8.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (328) hide show
  1. package/AGENTS.md +5 -2
  2. package/CHANGELOG.md +20 -0
  3. package/README.en.md +24 -3
  4. package/README.md +10 -6
  5. package/README.zh-CN.md +5 -3
  6. package/THIRD_PARTY_NOTICES.md +1 -2
  7. package/adapters/chatgpt/browser-delivery-runtime.ts +5 -3
  8. package/adapters/chatgpt/provider-delivery.ts +1 -1
  9. package/adapters/chatgpt/work-conversation-binding-store.ts +20 -1
  10. package/adapters/computer/chatgpt-extension-target.ts +295 -50
  11. package/adapters/computer/chrome-extension/background.js +227 -71
  12. package/adapters/computer/chrome-extension/content.js +181 -157
  13. package/adapters/computer/chrome-extension/manifest.json +3 -1
  14. package/adapters/computer/desktop-operator-provider.ts +18 -6
  15. package/adapters/computer/interaction-target-authority.ts +39 -9
  16. package/adapters/mcp/access-mode.ts +18 -39
  17. package/adapters/mcp/auth.ts +2 -6
  18. package/adapters/mcp/instructions.ts +2 -2
  19. package/adapters/mcp/multi-repository.ts +7 -28
  20. package/adapters/mcp/runtime-gateway/context-adapter.ts +79 -40
  21. package/adapters/mcp/runtime-gateway/context-pack-sidecar.ts +7 -15
  22. package/adapters/mcp/runtime-gateway/execution-tools.ts +7 -13
  23. package/adapters/mcp/runtime-gateway/plugin-adapter.ts +16 -3
  24. package/adapters/mcp/runtime-gateway/process-tools.ts +3 -21
  25. package/adapters/mcp/runtime-gateway/router.ts +3 -5
  26. package/adapters/mcp/runtime-gateway/routing-policy.ts +17 -10
  27. package/adapters/mcp/runtime-gateway/runtime-observation-adapter.ts +1 -1
  28. package/adapters/mcp/runtime-gateway/runtime-tool-definitions.ts +14 -9
  29. package/adapters/mcp/runtime-gateway/runtime-tools.ts +1 -5
  30. package/adapters/mcp/runtime-gateway/scheduler-adapter.ts +36 -1
  31. package/adapters/mcp/runtime-gateway/status-inbox-adapter.ts +58 -4
  32. package/adapters/mcp/runtime-gateway/typescript-navigation-sidecar.ts +7 -3
  33. package/adapters/mcp/runtime-gateway/work-adapter.ts +16 -16
  34. package/adapters/mcp/runtime-gateway/work-input-wire-migration.ts +0 -17
  35. package/adapters/mcp/runtime-gateway/work-semantic-operations.ts +69 -12
  36. package/adapters/mcp/runtime-gateway/workflow-supervisor-adapter.ts +26 -2
  37. package/adapters/mcp/server.ts +24 -3
  38. package/adapters/mcp/setup.ts +4 -10
  39. package/adapters/mcp/tool-mapping/access-tools.ts +0 -6
  40. package/adapters/mcp/tool-mapping/legacy-tool-service.ts +672 -2935
  41. package/adapters/mcp/tool-mapping/post-finalize-work-attribution.ts +1 -1
  42. package/adapters/mcp/tool-mapping/repository-tools.ts +52 -86
  43. package/adapters/mcp/toolset-names.ts +11 -42
  44. package/adapters/mcp/toolset.ts +16 -90
  45. package/{src/cli → adapters}/mcp/transports/AGENTS.md +5 -5
  46. package/{src/cli → adapters}/mcp/transports/CLAUDE.md +5 -5
  47. package/adapters/mcp/transports/http-observation.ts +18 -6
  48. package/adapters/mcp/transports/http-post-lifecycle.ts +19 -0
  49. package/adapters/mcp/transports/http.ts +54 -14
  50. package/adapters/mcp/types.ts +0 -6
  51. package/assets/hooks/lib/session-state.sh +0 -38
  52. package/assets/hooks/post-bash.sh +1 -1
  53. package/assets/hooks/post-tool-observer.sh +0 -5
  54. package/assets/hooks/prompt-guard.sh +0 -55
  55. package/assets/partials/04-project-structure.partial.md +1 -1
  56. package/assets/partials/07-footer.partial.md +1 -1
  57. package/assets/partials-agents/02-operating-mode.partial.md +1 -1
  58. package/assets/partials-agents/08-deep-docs.partial.md +1 -1
  59. package/assets/reference-configs/agentic-development-flow.md +1 -1
  60. package/assets/reference-configs/external-tooling.md +0 -76
  61. package/assets/reference-configs/release-deploy.md +1 -1
  62. package/assets/templates/helpers/architecture-queue.sh +1 -1
  63. package/assets/templates/helpers/check-agent-tooling.sh +1 -327
  64. package/assets/templates/helpers/check-task-workflow.sh +1 -1
  65. package/assets/templates/helpers/ensure-task-workflow.sh +0 -14
  66. package/assets/templates/helpers/migrate-project-template.sh +2 -2
  67. package/assets/workflow-contract.v1.json +0 -2
  68. package/docs/README.md +5 -2
  69. package/docs/architecture/CURRENT.md +114 -30
  70. package/docs/architecture/decisions/20260904-ios-device-migration-baseline.md +42 -0
  71. package/docs/architecture/decisions/20260918-stable-candidate-release-lifecycle.md +15 -2
  72. package/docs/architecture/decisions/20260924-thin-semantic-working-context.md +4 -2
  73. package/docs/architecture/decisions/20261001-supervisor-turn-authority.md +109 -4
  74. package/docs/architecture/decisions/20261009-exact-code-context-discovery.md +19 -0
  75. package/docs/architecture/decisions/20261009-generated-xcode-cache-retention.md +37 -0
  76. package/docs/architecture/decisions/20261011-autonomous-continuation-convergence.md +597 -0
  77. package/docs/architecture/decisions/20261017-edit-session-finalization-reconciliation.md +17 -0
  78. package/docs/architecture/decisions/20261019-retire-host-skills.md +16 -0
  79. package/docs/architecture/diagrams/agentic-dev-plugin-architecture.html +1 -1
  80. package/docs/architecture/domains/public-surface.md +3 -5
  81. package/docs/architecture/domains/verification.md +5 -5
  82. package/docs/architecture/modules/controller-runtime/transport-lifecycle.md +2 -2
  83. package/docs/architecture/requests/2026-09-04-computer-plugin-workflow-taxonomy.md +4 -4
  84. package/docs/architecture/reviews/20261015-code-search-runtime-acceptance.md +75 -0
  85. package/docs/forge-plugin-management.md +14 -2
  86. package/docs/operations/controller-browser-plugin.md +23 -0
  87. package/docs/operations/features.md +6 -7
  88. package/docs/operations/features.zh-CN.md +1 -1
  89. package/docs/operations/github-repository.md +4 -4
  90. package/docs/operations/github-semantic-release-projection.md +20 -0
  91. package/docs/operations/homebrew.md +2 -2
  92. package/docs/operations/mcp-tool-exposure.md +13 -54
  93. package/docs/operations/runtime-performance-diagnostics.md +8 -0
  94. package/docs/operations/standalone-disaster-recovery.md +1 -1
  95. package/docs/tutorials/01-install-and-start.zh-CN.md +1 -1
  96. package/docs/tutorials/03-first-repository-task.md +2 -0
  97. package/docs/wiki/Computer-and-Plugins.md +78 -0
  98. package/docs/wiki/Computer-and-Plugins.zh-CN.md +88 -0
  99. package/docs/wiki/Home.md +16 -2
  100. package/docs/wiki/Implementation.md +24 -12
  101. package/docs/wiki/Installation.md +28 -32
  102. package/docs/wiki/Integrations.md +4 -0
  103. package/docs/wiki/Quick-Start.md +35 -22
  104. package/docs/wiki/Releases-and-Upgrades.md +15 -25
  105. package/docs/wiki/_Sidebar.md +5 -1
  106. package/package.json +1 -12
  107. package/packages/kernel/controller/infrastructure/controller-session-store.ts +63 -38
  108. package/packages/kernel/identity/infrastructure/activity-projection-store.ts +10 -0
  109. package/packages/kernel/scheduler/application/eligibility.ts +4 -1
  110. package/packages/kernel/scheduler/infrastructure/schedule-store.ts +13 -10
  111. package/packages/kernel/work/application/work-service.ts +1 -0
  112. package/packages/kernel/work/domain/repository-completion-receipt.ts +1 -1
  113. package/packages/kernel/work/domain/state-machine.ts +9 -2
  114. package/packages/kernel/work/infrastructure/work-contract-store.ts +28 -1
  115. package/packages/plugin-runtime/browser/provider-registry.ts +12 -36
  116. package/packages/plugin-runtime/computer/conversation-target.ts +17 -7
  117. package/scripts/assemble-template.ts +11 -72
  118. package/scripts/check-mcp-compatibility.ts +55 -74
  119. package/scripts/check-package-identity.mjs +0 -5
  120. package/scripts/check-runtime-architecture.mjs +305 -28
  121. package/scripts/init-project.sh +0 -46
  122. package/scripts/install-ios-hid-toolchain.sh +60 -0
  123. package/scripts/install-standalone-recovery.ts +1 -1
  124. package/scripts/lib/project-init-lib.sh +3 -3
  125. package/scripts/migrate-windows-wsl-controller-home.ts +2 -0
  126. package/scripts/open-source-audit-allowlist.txt +0 -1
  127. package/scripts/run-governed-gate.ts +2 -0
  128. package/scripts/smoke-ios-physical-device.ts +38 -10
  129. package/scripts/smoke-mcp-http-runtime.ts +7 -8
  130. package/scripts/smoke-mcp-tool-surface.ts +27 -41
  131. package/scripts/smoke-workflow-supervisor-chrome-adapter.ts +6 -3
  132. package/scripts/sync-generated-authority.mjs +0 -1
  133. package/src/cli/agent-jobs/executor-health.ts +1 -1
  134. package/src/cli/agent-jobs/integration.ts +2 -2
  135. package/src/cli/chatgpt-browser/file-policy.ts +2 -2
  136. package/src/cli/commands/doctor.ts +1 -143
  137. package/src/cli/commands/global-runtime.ts +3 -196
  138. package/src/cli/commands/init-hook.ts +6 -23
  139. package/src/cli/commands/init.ts +3 -252
  140. package/src/cli/commands/mcp.ts +0 -5
  141. package/src/cli/commands/prompt-guard-decision.ts +0 -2
  142. package/src/cli/commands/recovery.ts +2 -14
  143. package/src/cli/commands/repository.ts +17 -1
  144. package/src/cli/commands/setup-execution.ts +41 -0
  145. package/src/cli/controller/completion-orchestrator.ts +1 -1
  146. package/src/cli/controller/composite-operations.ts +1 -1
  147. package/src/cli/controller/context/instruction-context.ts +1 -1
  148. package/src/cli/controller/context/known-paths.ts +2 -2
  149. package/src/cli/controller/context/query-planning.ts +11 -4
  150. package/src/cli/controller/context/rule-resolution.ts +2 -2
  151. package/src/cli/controller/context/source-materializer.ts +2 -2
  152. package/src/cli/controller/context/structural-provider.ts +84 -0
  153. package/src/cli/controller/context/structural.ts +6 -6
  154. package/src/cli/controller/context/types.ts +8 -9
  155. package/src/cli/controller/context-pack.ts +97 -76
  156. package/src/cli/controller/operational-plan.ts +1 -1
  157. package/src/cli/controller/systemd-user.ts +4 -10
  158. package/src/cli/editing/edit-session.ts +17 -5
  159. package/src/cli/github/github.ts +4 -4
  160. package/src/cli/github/semantic-projection.ts +174 -0
  161. package/src/cli/hook/prompt-intents.ts +0 -9
  162. package/src/cli/index.ts +1 -43
  163. package/src/cli/local-bridge/connector-freshness.ts +1 -12
  164. package/src/cli/local-bridge/console-automations.ts +1 -1
  165. package/src/cli/local-bridge/console-view-models.ts +1 -1
  166. package/src/cli/local-bridge/facade-api.ts +0 -2
  167. package/src/cli/repositories/command-classifier.ts +0 -9
  168. package/src/cli/repositories/command-scope.ts +2 -2
  169. package/src/cli/repositories/locks.ts +20 -0
  170. package/src/cli/repositories/registry.ts +2 -1
  171. package/src/cli/repositories/safe-patch.ts +2 -12
  172. package/src/cli/repositories/structured-git.ts +39 -3
  173. package/src/cli/repository/inspector.ts +185 -343
  174. package/src/effects/process-runner.ts +17 -1
  175. package/src/runtime/context/generic-lsp-provider.ts +1 -1
  176. package/src/runtime/context/semantic-navigation-contract.ts +7 -0
  177. package/src/runtime/context/semantic-navigation.ts +1 -1
  178. package/src/runtime/control-plane/cleanup-artifact-retention.ts +4 -4
  179. package/src/runtime/control-plane/execution/work-delivery-service.ts +150 -31
  180. package/src/runtime/control-plane/execution/work-handle-authority.ts +12 -4
  181. package/src/runtime/control-plane/execution/work-handle-store.ts +53 -1
  182. package/src/runtime/control-plane/execution/work-operation-service.ts +20 -10
  183. package/src/runtime/control-plane/execution/work-preparation-service.ts +108 -4
  184. package/src/runtime/control-plane/execution/work-process-evidence.ts +2 -2
  185. package/src/runtime/control-plane/execution/work-terminal-cleanup.ts +28 -13
  186. package/src/runtime/control-plane/execution/work-validation-reconciler.ts +5 -1
  187. package/src/runtime/control-plane/execution/work-verification-snapshot.ts +1 -1
  188. package/src/runtime/control-plane/facade/capability-registry.ts +2 -0
  189. package/src/runtime/control-plane/facade/work-continuation.ts +1 -1
  190. package/src/runtime/control-plane/generated-cache-retention.ts +114 -63
  191. package/src/runtime/control-plane/global-scheduler/maintenance.ts +20 -8
  192. package/src/runtime/control-plane/global-scheduler/reconciliation.ts +1 -11
  193. package/src/runtime/control-plane/governance/external-effects.ts +1 -1
  194. package/src/runtime/control-plane/launcher/chatgpt-work-continuation.ts +1 -0
  195. package/src/runtime/control-plane/runtime-cleanup.ts +12 -93
  196. package/src/runtime/evidence/sensitive-output.ts +22 -2
  197. package/src/runtime/execution/jobs/child-reference.ts +11 -0
  198. package/src/runtime/execution/jobs/receipt-recovery.ts +1 -11
  199. package/src/runtime/execution/process-runtime/command-facade.ts +3 -3
  200. package/src/runtime/execution/process-runtime/runtime.ts +20 -16
  201. package/src/runtime/execution/thin-harness/execution-router.ts +16 -16
  202. package/src/runtime/execution/thin-harness/fast-executor.ts +2 -2
  203. package/src/runtime/execution/thin-harness/search-worker.ts +2 -2
  204. package/src/runtime/execution/workers/executor.ts +1 -2
  205. package/src/runtime/maintenance/cleanup.ts +41 -5
  206. package/src/runtime/plugins/action-application.ts +12 -1
  207. package/src/runtime/plugins/app-store-connect-adapter.ts +252 -4
  208. package/src/runtime/plugins/browser-adapter.ts +381 -313
  209. package/src/runtime/plugins/browser-macos-bridge.ts +114 -112
  210. package/src/runtime/plugins/browser-manifest-surface.ts +2 -1
  211. package/src/runtime/plugins/browser-registration.ts +2 -0
  212. package/src/runtime/plugins/browser-runtime.ts +26 -35
  213. package/src/runtime/plugins/computer-chatgpt-browser-adapter-installer.ts +11 -2
  214. package/src/runtime/plugins/computer-registration.ts +76 -9
  215. package/src/runtime/plugins/github-adapter.ts +30 -3
  216. package/src/runtime/plugins/gmail-adapter.ts +166 -1
  217. package/src/runtime/plugins/google-shared.ts +10 -5
  218. package/src/runtime/plugins/ios/remote-xpc-hid.ts +70 -30
  219. package/src/runtime/plugins/ios-adapter.ts +45 -40
  220. package/src/runtime/plugins/ios-agent-device.ts +54 -4
  221. package/src/runtime/plugins/ios-device-ownership.ts +103 -0
  222. package/src/runtime/plugins/ios-physical-device.ts +497 -79
  223. package/src/runtime/plugins/local-system-adapter.ts +1 -99
  224. package/src/runtime/plugins/store.ts +80 -7
  225. package/src/runtime/plugins/types.ts +4 -0
  226. package/src/runtime/projections/git-status-sampler.ts +2 -19
  227. package/src/runtime/recovery/actions.ts +1 -1
  228. package/src/runtime/recovery/lifecycle-inventory.ts +1 -11
  229. package/src/runtime/recovery/probe.ts +2 -2
  230. package/src/runtime/release/release-coordinator.ts +20 -4
  231. package/src/runtime/root/controller-progression-composition.ts +67 -5
  232. package/src/runtime/root/package-connector-service.ts +123 -11
  233. package/src/runtime/root/package-runtime-release.ts +6 -18
  234. package/src/runtime/root/package-runtime-service.ts +7 -13
  235. package/src/runtime/root/release-execution-canary.ts +18 -5
  236. package/src/runtime/root/release-manifest.ts +0 -34
  237. package/src/runtime/root/release-materialize.ts +0 -78
  238. package/src/runtime/root/runtime.ts +1 -2
  239. package/src/runtime/root/scheduled-controller-composition.ts +2 -1
  240. package/src/runtime/root/service.ts +90 -11
  241. package/src/runtime/root/types.ts +0 -6
  242. package/src/runtime/root/workflow-supervisor-composition.ts +207 -19
  243. package/src/runtime/root/workflow-supervisor-runtime.ts +365 -10
  244. package/src/runtime/safe-tooling/google-credential-store.ts +1 -11
  245. package/src/runtime/safe-tooling/ios-development.ts +22 -8
  246. package/src/runtime/safe-tooling/job-summary.ts +1 -1
  247. package/src/runtime/safe-tooling/workspace-auth.ts +4 -1
  248. package/src/runtime/shared/atomic-text-file.ts +21 -0
  249. package/src/runtime/shared/json-files.ts +8 -3
  250. package/src/runtime/standalone-recovery/core.ts +189 -174
  251. package/src/runtime/standalone-recovery/entry.ts +62 -30
  252. package/src/runtime/standalone-recovery/operation-lock.ts +11 -1
  253. package/src/runtime/workflow/schedules/chatgpt-automation-migration.ts +1 -0
  254. package/src/runtime/workflow/schedules/engine.ts +36 -14
  255. package/src/runtime/workflow/schedules/pending-activation.ts +11 -4
  256. package/src/runtime/workflow/schedules/work-continuation.ts +51 -6
  257. package/supervisor/client.ts +31 -14
  258. package/supervisor/control-plane.ts +210 -115
  259. package/supervisor/forge-validators.ts +88 -21
  260. package/supervisor/native-browser-adapter.ts +393 -28
  261. package/supervisor/native-messaging/host.ts +21 -2
  262. package/supervisor/protocol.ts +74 -26
  263. package/supervisor/server.ts +16 -8
  264. package/supervisor/store.ts +476 -57
  265. package/supervisor/types.ts +19 -13
  266. package/SKILL.md +0 -427
  267. package/adapters/computer/chatgpt-target-router.ts +0 -103
  268. package/adapters/mcp/runtime-gateway/automation-receipt-adapter.ts +0 -87
  269. package/adapters/mcp/runtime-gateway/work-validation-reconciler.ts +0 -1
  270. package/adapters/mcp/toolset-selection.ts +0 -41
  271. package/agents/openai.yaml +0 -4
  272. package/assets/skill-hooks.json +0 -41
  273. package/assets/skill-version.json +0 -189
  274. package/assets/skills/claude-review/SKILL.md +0 -231
  275. package/assets/skills/codex-review/SKILL.md +0 -103
  276. package/assets/templates/helpers/check-skill-version.ts +0 -193
  277. package/scripts/check-skill-version.ts +0 -5
  278. package/scripts/ensure-codegraph.sh +0 -16
  279. package/scripts/run-skill-hook.ts +0 -244
  280. package/scripts/sync-codex-installed-copies.sh +0 -182
  281. package/src/cli/commands/tools.ts +0 -167
  282. package/src/cli/mcp/access-mode.ts +0 -2
  283. package/src/cli/mcp/access-tools.ts +0 -2
  284. package/src/cli/mcp/audit.ts +0 -2
  285. package/src/cli/mcp/auth.ts +0 -2
  286. package/src/cli/mcp/instructions.ts +0 -2
  287. package/src/cli/mcp/legacy-context.ts +0 -2
  288. package/src/cli/mcp/legacy-tool-service.ts +0 -2
  289. package/src/cli/mcp/multi-repository.ts +0 -2
  290. package/src/cli/mcp/oauth.ts +0 -2
  291. package/src/cli/mcp/openai-secure-tunnel.ts +0 -2
  292. package/src/cli/mcp/paths.ts +0 -2
  293. package/src/cli/mcp/policy.ts +0 -2
  294. package/src/cli/mcp/post-finalize-work-attribution.ts +0 -2
  295. package/src/cli/mcp/proxy-env.ts +0 -2
  296. package/src/cli/mcp/readiness-projection.ts +0 -2
  297. package/src/cli/mcp/redaction.ts +0 -2
  298. package/src/cli/mcp/repo.ts +0 -2
  299. package/src/cli/mcp/repository-tools.ts +0 -2
  300. package/src/cli/mcp/server.ts +0 -2
  301. package/src/cli/mcp/setup.ts +0 -2
  302. package/src/cli/mcp/tool-capability-cache.ts +0 -2
  303. package/src/cli/mcp/tool-contract.ts +0 -2
  304. package/src/cli/mcp/tools.ts +0 -2
  305. package/src/cli/mcp/toolset-names.ts +0 -2
  306. package/src/cli/mcp/toolset-selection.ts +0 -2
  307. package/src/cli/mcp/toolset.ts +0 -2
  308. package/src/cli/mcp/transports/http.ts +0 -2
  309. package/src/cli/mcp/transports/session-registry.ts +0 -2
  310. package/src/cli/mcp/transports/stdio.ts +0 -2
  311. package/src/cli/mcp/types.ts +0 -2
  312. package/src/cli/mcp/umbrella-tools.ts +0 -2
  313. package/src/cli/tools/codegraph.ts +0 -695
  314. package/src/core/adoption/helper-wrapper-plan.ts +0 -159
  315. package/src/runtime/context/codegraph-cache-boundary.ts +0 -255
  316. package/src/runtime/context/codegraph-read-provider.ts +0 -611
  317. package/src/runtime/context/codegraph-sidecar.cjs +0 -248
  318. package/src/runtime/control-plane/codegraph-cache-retention.ts +0 -164
  319. package/src/runtime/gateway/mcp/execution-tools.ts +0 -2
  320. package/src/runtime/gateway/mcp/legacy-ios-tool-adapter.ts +0 -2
  321. package/src/runtime/gateway/mcp/persisted-check-process.ts +0 -2
  322. package/src/runtime/gateway/mcp/process-tools.ts +0 -2
  323. package/src/runtime/gateway/mcp/router.ts +0 -2
  324. package/src/runtime/gateway/mcp/runtime-tool-definitions.ts +0 -2
  325. package/src/runtime/gateway/mcp/runtime-tools.ts +0 -2
  326. package/src/runtime/gateway/mcp/work-validation-reconciler.ts +0 -2
  327. package/src/runtime/plugins/browser-provider-registry.ts +0 -2
  328. package/src/runtime/plugins/computer-chatgpt-macos-target.ts +0 -891
@@ -12,7 +12,7 @@ import { isTerminalSemanticWorkState } from '../facade/types';
12
12
  import { updateExecutionSession, type ExecutionSessionContext } from './session-store';
13
13
  import { currentPermissionSnapshotVersion, validateWorkHandle } from './validation';
14
14
  import { withWorkPrepareRequest } from './work-prepare-request-store';
15
- import { markWorkHandleFailed, newWorkId, readWorkHandle, writeWorkHandle, type WorkFinalizationStages, type WorkHandleState } from './work-handle-store';
15
+ import { markWorkHandleFailed, newWorkId, readWorkHandle, relocateWorkHandlePlacementAtomically, writeWorkHandle, type WorkFinalizationStages, type WorkHandleState } from './work-handle-store';
16
16
  import { createGoalDelegation } from '../governance/authorization';
17
17
  import { compactHandle, contractFor, findWorkHandle, gitHead, gitIsAncestor, identityFor, requireSession } from './work-execution-support';
18
18
 
@@ -42,6 +42,11 @@ function boundedStringArray(value: unknown, limit: number): string[] {
42
42
  return Array.isArray(value) ? value.map(String).slice(0, limit) : [];
43
43
  }
44
44
 
45
+ function requestedWorkPrepareIsolation(args: Record<string, unknown>): 'reuse' | 'new_worktree' | 'auto' | undefined {
46
+ if (!Object.prototype.hasOwnProperty.call(args, 'isolation')) return undefined;
47
+ return args.isolation === 'reuse' || args.isolation === 'new_worktree' || args.isolation === 'auto' ? args.isolation : 'auto';
48
+ }
49
+
45
50
  function workPrepareFingerprint(input: {
46
51
  repoId: string;
47
52
  requestedCheckoutId?: string;
@@ -112,7 +117,12 @@ function adoptExplicitSuccessorHead(
112
117
  if (!expectedPreviousHead || !adoptCandidateHead) {
113
118
  throw new Error('WORK_HANDLE_SUCCESSOR_ADOPTION_PAIR_REQUIRED: expected_previous_head and adopt_candidate_head must be supplied together');
114
119
  }
115
- if (existing.state !== 'prepared' && existing.state !== 'editing') {
120
+ // A failed validation attempt may need an explicit, audited successor
121
+ // adoption before it can retry against the current checkout. Keep its
122
+ // failed state: only a fresh valid check may restore execution authority.
123
+ const retryableValidationFailure = existing.state === 'failed'
124
+ && existing.finalization.validation === 'failed';
125
+ if (existing.state !== 'prepared' && existing.state !== 'editing' && !retryableValidationFailure) {
116
126
  throw new Error(`WORK_HANDLE_SUCCESSOR_ADOPTION_STATE_INVALID: ${existing.state}`);
117
127
  }
118
128
  if (existing.expectedHead !== expectedPreviousHead) {
@@ -150,7 +160,8 @@ function adoptExplicitSuccessorHead(
150
160
  }
151
161
  const candidate: WorkHandleState = {
152
162
  ...existing,
153
- deliveryBaseCommit: adoptCandidateHead,
163
+ // Successor adoption advances the Work candidate, not the delivery target.
164
+ // Preserve the canonical delivery base until authorized delivery or rebase.
154
165
  expectedHead: adoptCandidateHead,
155
166
  validationRun: undefined,
156
167
  validatedInputFingerprint: undefined,
@@ -161,6 +172,86 @@ function adoptExplicitSuccessorHead(
161
172
  return writeWorkHandle(ctx.controllerHome, candidate);
162
173
  }
163
174
 
175
+ function relocateExistingWorkToManagedCheckout(
176
+ ctx: McpExecutionContext,
177
+ args: Record<string, unknown>,
178
+ session: ExecutionSessionContext,
179
+ repository: ReturnType<typeof selectedRepository>,
180
+ existing: WorkHandleState,
181
+ ): Record<string, unknown> {
182
+ const prior = typeof args.expected_previous_head === 'string' ? args.expected_previous_head.trim() : '';
183
+ const candidate = typeof args.adopt_candidate_head === 'string' ? args.adopt_candidate_head.trim() : '';
184
+ const baseRef = typeof args.base_ref === 'string' ? args.base_ref.trim() : '';
185
+ if (!prior || !candidate || baseRef !== candidate || !/^[0-9a-f]{40}$/.test(candidate)) {
186
+ throw new Error('WORK_RELOCATION_EXACT_HEADS_REQUIRED: supply expected_previous_head and matching base_ref/adopt_candidate_head');
187
+ }
188
+ if (existing.principalId !== session.principalId) throw new Error('WORK_HANDLE_ACCESS_DENIED');
189
+ if (existing.expectedHead !== prior && !(existing.managedWorktree && existing.expectedHead === candidate)) {
190
+ throw new Error('WORK_RELOCATION_PREVIOUS_HEAD_MISMATCH');
191
+ }
192
+ if (existing.managedWorktree) {
193
+ if (existing.expectedHead !== candidate) throw new Error('WORK_RELOCATION_ALREADY_ISOLATED');
194
+ validateWorkHandle(ctx.controllerHome, existing, identityFor(ctx, args), 'cheap', 'inspect');
195
+ updateExecutionSession(ctx.controllerHome, identityFor(ctx, args), {
196
+ activeRepositoryId: existing.repositoryId, activeCheckoutId: existing.checkoutId,
197
+ activeWorkId: existing.workId, permissionSnapshotVersion: existing.permissionSnapshotVersion,
198
+ });
199
+ return { session: requireSession(ctx, args), work: compactHandle(existing), reused: true, relocated: true };
200
+ }
201
+ if (existing.state !== 'prepared' && existing.state !== 'editing') throw new Error('WORK_RELOCATION_STATE_INVALID');
202
+ if (existing.finalization.validation !== 'pending' || existing.finalization.commit !== 'pending' || existing.finalization.merge !== 'pending'
203
+ || existing.finalization.worktreeCleanup !== 'pending' || existing.finalization.branchCleanup !== 'pending'
204
+ || existing.cleanupReceipt || existing.validatedInputFingerprint || existing.validationRun) {
205
+ throw new Error('WORK_RELOCATION_FINALIZATION_IN_PROGRESS');
206
+ }
207
+ const contract = getWorkContract({ controllerHome: ctx.controllerHome, repoId: existing.repositoryId }, existing.workId);
208
+ if (!contract || contract.semanticState !== 'open' || contract.completionReceipt || contract.completionOutcome
209
+ || contract.checkoutId !== existing.checkoutId) throw new Error('WORK_RELOCATION_CONTRACT_MISMATCH');
210
+ if (existing.checkoutId !== repository.activeCheckoutId || existing.worktreePath !== repository.canonicalRoot
211
+ || existing.branch !== repositoryGitStatus(repository).branch) throw new Error('WORK_RELOCATION_SOURCE_MISMATCH');
212
+ if (!gitIsAncestor(existing.worktreePath, prior, candidate)) throw new Error('WORK_RELOCATION_NONLINEAR');
213
+ const changedPaths = gitPathSet(existing.worktreePath, ['diff', '--name-only', prior + '..' + candidate], 'WORK_RELOCATION_DIFF_UNAVAILABLE');
214
+ const dirtyPaths = currentDirtyPaths(existing.worktreePath);
215
+ const overlap = [...changedPaths].filter((path) => dirtyPaths.has(path));
216
+ if (overlap.length) throw new Error('WORK_RELOCATION_DIRTY_OVERLAP: ' + overlap.sort().join(','));
217
+ if (listRecoverableProcessRecords(ctx.controllerHome, existing.repositoryId).some((record) => record.workId === existing.workId)) {
218
+ throw new Error('WORK_RELOCATION_ACTIVE_PROCESS');
219
+ }
220
+ const requestId = typeof args.request_id === 'string' ? args.request_id.trim() : '';
221
+ if (!requestId) throw new Error('WORK_RELOCATION_REQUEST_ID_REQUIRED');
222
+ // A deterministic request identity makes physical worktree creation safe to
223
+ // resume after a process crash before the authoritative database transaction.
224
+ const workspace = ensureManagedWorkspace(ctx.controllerHome, repository, {
225
+ requestId: 'relocate:' + existing.workId + ':' + candidate,
226
+ title: 'Relocate existing Work to managed checkout',
227
+ associatedWorkId: existing.workId,
228
+ baseRef: candidate,
229
+ prepareDependencies: false,
230
+ });
231
+ if (!workspace.managed || !workspace.checkoutId || !workspace.root || !workspace.branch) {
232
+ throw new Error('WORK_RELOCATION_TARGET_NOT_MANAGED');
233
+ }
234
+ const selectedTarget = resolveRepositorySelection({
235
+ repoId: existing.repositoryId, checkoutId: workspace.checkoutId,
236
+ controllerHome: ctx.controllerHome, allowSoleRepository: false,
237
+ });
238
+ const targetStatus = repositoryGitStatus(selectedTarget);
239
+ if (!targetStatus.clean || targetStatus.head !== candidate || targetStatus.branch !== workspace.branch
240
+ || workspace.checkoutId === existing.checkoutId || selectedTarget.canonicalRoot !== workspace.root) {
241
+ throw new Error('WORK_RELOCATION_TARGET_CHANGED');
242
+ }
243
+ const refreshed = relocateWorkHandlePlacementAtomically(ctx.controllerHome, existing, {
244
+ checkoutId: workspace.checkoutId, root: workspace.root,
245
+ branch: workspace.branch, head: candidate,
246
+ });
247
+ updateExecutionSession(ctx.controllerHome, identityFor(ctx, args), {
248
+ activeRepositoryId: refreshed.repositoryId, activeCheckoutId: refreshed.checkoutId,
249
+ activeWorkId: refreshed.workId, permissionSnapshotVersion: refreshed.permissionSnapshotVersion,
250
+ });
251
+ return { session: requireSession(ctx, args), work: compactHandle(refreshed), relocated: true,
252
+ previousCheckoutId: existing.checkoutId, previousHead: prior, currentHead: candidate };
253
+ }
254
+
164
255
  export function prepareWork(ctx: McpExecutionContext, args: Record<string, unknown>): Record<string, unknown> {
165
256
  const session = requireSession(ctx, args);
166
257
  const repository = selectedRepository(ctx, session, args, true);
@@ -168,10 +259,23 @@ export function prepareWork(ctx: McpExecutionContext, args: Record<string, unkno
168
259
  updateExecutionSession(ctx.controllerHome, identityFor(ctx, args), { activeRepositoryId: repository.repoId, activeCheckoutId: repository.activeCheckoutId, permissionSnapshotVersion: currentPermissionSnapshotVersion(ctx.controllerHome, repository.repoId) });
169
260
  }
170
261
  const existingId = typeof args.work_id === 'string' ? args.work_id.trim() : '';
262
+ if (args.relocate_to_new_worktree === true && !existingId) throw new Error('WORK_RELOCATION_EXISTING_WORK_ID_REQUIRED');
263
+ const requestedIsolation = requestedWorkPrepareIsolation(args);
171
264
  if (existingId) {
172
265
  const existing = readWorkHandle(ctx.controllerHome, repository.repoId, existingId)
173
266
  ?? findWorkHandle(ctx, session, { ...args, work_id: existingId, repo_id: repository.repoId });
174
267
  if (existing.principalId !== session.principalId) throw new Error('WORK_HANDLE_ACCESS_DENIED');
268
+ if (args.relocate_to_new_worktree === true) {
269
+ if (requestedIsolation !== undefined) throw new Error('WORK_RELOCATION_ISOLATION_CONFLICT');
270
+ return relocateExistingWorkToManagedCheckout(ctx, args, session, repository, existing);
271
+ }
272
+ if (requestedIsolation !== undefined) {
273
+ const requestedWorkspaceMode = requestedIsolation === 'reuse' ? 'current' : 'isolated';
274
+ const existingWorkspaceMode = existing.managedWorktree ? 'isolated' : 'current';
275
+ if (requestedWorkspaceMode !== existingWorkspaceMode) {
276
+ throw new Error(`WORK_PREPARE_PLACEMENT_CONFLICT: ${existingId}; existing=${existingWorkspaceMode}; requested=${requestedWorkspaceMode}`);
277
+ }
278
+ }
175
279
  const adopted = adoptExplicitSuccessorHead(ctx, args, repository, existing);
176
280
  const active = adopted ?? existing;
177
281
  if (!adopted) validateWorkHandle(ctx.controllerHome, active, identityFor(ctx, args), 'cheap', 'inspect');
@@ -186,7 +290,7 @@ export function prepareWork(ctx: McpExecutionContext, args: Record<string, unkno
186
290
 
187
291
  const requestId = typeof args.request_id === 'string' ? args.request_id.trim() : '';
188
292
  if (!requestId) throw new Error('WORK_PREPARE_REQUEST_ID_REQUIRED: new work preparation requires request_id');
189
- const isolation = args.isolation === 'reuse' || args.isolation === 'new_worktree' || args.isolation === 'auto' ? args.isolation : 'auto';
293
+ const isolation = requestedWorkPrepareIsolation(args) ?? 'auto';
190
294
  const objective = String(args.objective ?? 'Controller-managed repository work').trim().slice(0, 2_000);
191
295
  const goalId = typeof args.goal_id === 'string' && args.goal_id.trim() ? args.goal_id.trim() : undefined;
192
296
  const acceptanceCriteria = boundedStringArray(args.acceptance_criteria, 20);
@@ -27,7 +27,7 @@ function isSuccessfulWorkRepositoryProcess(
27
27
  return record.workId === input.workId
28
28
  && record.checkoutId === input.checkoutId
29
29
  && record.origin?.surface === 'command'
30
- && record.origin.toolName === 'repository_command_execute'
30
+ && record.origin.toolName === 'execute_command'
31
31
  && record.origin.correlationId === input.workId
32
32
  && isManagedProcessTerminal(record)
33
33
  && record.terminalWritten === true
@@ -42,7 +42,7 @@ function isSuccessfulWorkRepositoryProcess(
42
42
  * Re-derive bounded completion evidence from the canonical durable Process store.
43
43
  *
44
44
  * This deliberately does not create a second evidence authority. A qualifying
45
- * record must be the terminal successful repository_command_execute Process for
45
+ * record must be the terminal successful execute_command Process for
46
46
  * the exact Work + checkout, and the command-origin correlation must still name
47
47
  * the same Work. Lightweight handles never enter listProcessRecords(), so they
48
48
  * cannot satisfy this contract.
@@ -170,6 +170,11 @@ function createVerifiedBundle(controllerHome: string, handle: WorkHandleState, t
170
170
  }
171
171
  const verified = git(targetRoot, ['bundle', 'verify', path], 60_000);
172
172
  if (!verified.ok) throw new Error(verified.stderr || 'git bundle verify failed');
173
+ const branchHead = git(targetRoot, ['rev-parse', '--verify', `refs/heads/${handle.branch}^{commit}`]);
174
+ const bundleHead = git(targetRoot, ['bundle', 'list-heads', path, `refs/heads/${handle.branch}`]);
175
+ if (!branchHead.ok || !bundleHead.ok || bundleHead.stdout !== `${branchHead.stdout} refs/heads/${handle.branch}`) {
176
+ throw new Error('BRANCH_BUNDLE_HEAD_MISMATCH: verified bundle does not preserve the current branch tip');
177
+ }
173
178
  return { path, sha256: hashText(readFileSync(path)) };
174
179
  }
175
180
 
@@ -489,9 +494,13 @@ function prepareManagedBranchPreservation(
489
494
  current: WorkHandleState,
490
495
  target: ReturnType<typeof getRepository>,
491
496
  targetBranch: string,
492
- ): { uniqueCommits: number; branchPreserved: boolean } {
497
+ ): { uniqueCommits: number; branchPreserved: boolean; branchHead?: string } {
493
498
  let uniqueCommits = 0;
499
+ let branchHead: string | undefined;
494
500
  if (branchExists(target.canonicalRoot, current.branch)) {
501
+ const observed = git(target.canonicalRoot, ['rev-parse', '--verify', `refs/heads/${current.branch}^{commit}`]);
502
+ if (!observed.ok || !observed.stdout) addBlocker(receipt, 'BRANCH_REVISION_UNKNOWN');
503
+ else branchHead = observed.stdout;
495
504
  if (!branchExists(target.canonicalRoot, targetBranch)) {
496
505
  addBlocker(receipt, `TARGET_BRANCH_MISSING: ${targetBranch}`);
497
506
  } else {
@@ -502,11 +511,12 @@ function prepareManagedBranchPreservation(
502
511
  }
503
512
  receipt.branchCleanup.uniqueCommits = uniqueCommits;
504
513
 
514
+ const retirement = receipt.preservation.bundleRetirement;
505
515
  let branchPreserved = Boolean(
506
- receipt.preservation.bundleRetirement?.status === 'not_needed'
507
- || receipt.preservation.bundleRetirement?.status === 'removed',
516
+ branchHead && retirement?.protectedRevision === branchHead
517
+ && (retirement.status === 'not_needed' || retirement.status === 'removed'),
508
518
  );
509
- if (receipt.preservation.bundlePath && !branchPreserved) {
519
+ if (branchHead && receipt.preservation.bundlePath && !branchPreserved) {
510
520
  try {
511
521
  const bundle = createVerifiedBundle(input.controllerHome, current, target.canonicalRoot);
512
522
  if (receipt.preservation.bundleSha256 && receipt.preservation.bundleSha256 !== bundle.sha256) {
@@ -519,7 +529,7 @@ function prepareManagedBranchPreservation(
519
529
  }
520
530
  }
521
531
  if (uniqueCommits > 0 && !branchPreserved && receipt.blockers.length === 0) {
522
- const proof = proveWorkPreservationContained(target.canonicalRoot, { ...current, cleanupReceipt: receipt }, targetBranch);
532
+ const proof = proveWorkPreservationContained(target.canonicalRoot, current, targetBranch, branchHead);
523
533
  if (proof.contained) {
524
534
  receipt.preservation.bundleRetirement = {
525
535
  status: 'not_needed',
@@ -547,7 +557,7 @@ function prepareManagedBranchPreservation(
547
557
  }
548
558
  }
549
559
  }
550
- return { uniqueCommits, branchPreserved };
560
+ return { uniqueCommits, branchPreserved, branchHead };
551
561
  }
552
562
 
553
563
  function applyManagedBranchCleanup(
@@ -559,6 +569,7 @@ function applyManagedBranchCleanup(
559
569
  receipt: WorkCleanupReceipt,
560
570
  uniqueCommits: number,
561
571
  branchPreserved: boolean,
572
+ expectedBranchHead: string | undefined,
562
573
  ): void {
563
574
  if (!deleteBranch) {
564
575
  receipt.branchCleanup.status = 'retained';
@@ -578,6 +589,10 @@ function applyManagedBranchCleanup(
578
589
  receipt.branchCleanup.status = 'retained';
579
590
  receipt.branchCleanup.reason = 'Unique commits are not archived.';
580
591
  addBlocker(receipt, `BRANCH_UNPRESERVED: ${current.branch}`);
592
+ } else if (!expectedBranchHead) {
593
+ receipt.branchCleanup.status = 'retained';
594
+ receipt.branchCleanup.reason = 'Exact branch revision is unavailable.';
595
+ addBlocker(receipt, 'BRANCH_REVISION_UNKNOWN');
581
596
  } else {
582
597
  // Branch deletion requires the canonical OwnedResource witness in addition
583
598
  // to Git relation checks. Repository/ref shape alone is not cleanup authority.
@@ -594,12 +609,10 @@ function applyManagedBranchCleanup(
594
609
  addBlocker(receipt, `OWNED_BRANCH_CLEANUP_FENCED: ${receipt.branchCleanup.reason}`);
595
610
  return;
596
611
  }
597
- // We already proved the exact branch relation against targetBranch above.
598
- // `git branch -d` instead consults the checkout's current HEAD, which may be
599
- // an older/stale source checkout and can falsely reject a branch that is
600
- // fully contained in the explicit target branch. After that target-branch
601
- // proof (or a verified archive for unique commits), delete the ref directly.
602
- const deleted = git(target.canonicalRoot, ['branch', '-D', current.branch]);
612
+ // Delete only the exact tip whose containment or bundle was proved above.
613
+ // A concurrent successor must retain its ref rather than inherit an older
614
+ // WorkHandle or preservation receipt's deletion authority.
615
+ const deleted = git(target.canonicalRoot, ['update-ref', '-d', `refs/heads/${current.branch}`, expectedBranchHead]);
603
616
  if (!deleted.ok && branchExists(target.canonicalRoot, current.branch)) {
604
617
  receipt.branchCleanup.status = 'failed';
605
618
  receipt.branchCleanup.reason = deleted.stderr || 'branch delete failed';
@@ -671,6 +684,7 @@ function reconcileCleanedManagedBranchRetirement(
671
684
  receipt,
672
685
  preservation.uniqueCommits,
673
686
  preservation.branchPreserved,
687
+ preservation.branchHead,
674
688
  );
675
689
  } else if (receipt.branchCleanup.status === 'pending') {
676
690
  receipt.branchCleanup.status = 'retained';
@@ -975,7 +989,7 @@ export async function cleanupTerminalWork(input: TerminalWorkCleanupInput): Prom
975
989
  receipt.worktree.status = 'already_removed';
976
990
  }
977
991
 
978
- const { uniqueCommits, branchPreserved } = prepareManagedBranchPreservation(
992
+ const { uniqueCommits, branchPreserved, branchHead } = prepareManagedBranchPreservation(
979
993
  input,
980
994
  receipt,
981
995
  current,
@@ -1049,6 +1063,7 @@ export async function cleanupTerminalWork(input: TerminalWorkCleanupInput): Prom
1049
1063
  receipt,
1050
1064
  uniqueCommits,
1051
1065
  branchPreserved,
1066
+ branchHead,
1052
1067
  );
1053
1068
 
1054
1069
  const pruned = git(target.canonicalRoot, ['worktree', 'prune']);
@@ -120,9 +120,13 @@ function settleInfrastructureFailure(
120
120
  handle: WorkHandleState,
121
121
  summary: string,
122
122
  ): WorkValidationReconciliation {
123
- const next = transitionWorkHandle(controllerHome, handle, 'failed', {
123
+ // Infrastructure/receipt uncertainty invalidates validation authority,
124
+ // not the underlying Work. Resume the pre-validation state so the same Work
125
+ // can repair and retry without opening a replacement lifecycle.
126
+ const next = transitionWorkHandle(controllerHome, handle, handle.validationRun?.resumeState ?? 'editing', {
124
127
  finalization: { ...handle.finalization, validation: 'failed', failureCode: undefined, lastError: summary },
125
128
  validationRun: undefined,
129
+ validatedInputFingerprint: undefined,
126
130
  failureReason: summary,
127
131
  });
128
132
  projectWorkValidationOutcome(controllerHome, next, 'infrastructure_failure', summary);
@@ -18,7 +18,7 @@ import {
18
18
  import { dirname, join, resolve, sep } from 'path';
19
19
  import { spawnSync } from 'child_process';
20
20
  import { repositoryControllerRoot } from '../../../cli/repositories/controller-home';
21
- import { globMatches, normalizeMcpRelativePath } from '../../../cli/mcp/paths';
21
+ import { globMatches, normalizeMcpRelativePath } from '../../../../adapters/mcp/paths';
22
22
  import { sanitizeFileComponent } from '../../shared/json-files';
23
23
  import { measureReclaimablePath, RUNTIME_LIFECYCLE_RETENTION_POLICY_VERSION } from '../lifecycle-retention-metrics';
24
24
 
@@ -647,6 +647,8 @@ export function getCoreCapabilityExecutionSchema(capabilityId: string): Record<s
647
647
  session_id: { type: 'string', minLength: 1, maxLength: 256 },
648
648
  work_id: { type: 'string', minLength: 1, maxLength: 256 },
649
649
  target_branch: { type: 'string', minLength: 1, maxLength: 512 },
650
+ complete_work: { type: 'boolean' },
651
+ allow_merge_commit: { type: 'boolean' },
650
652
  },
651
653
  },
652
654
  },
@@ -1,5 +1,5 @@
1
1
  import type { WorkContract, WorkReconciliationRecord } from './types';
2
- import { redactMcpText } from '../../../cli/mcp/redaction';
2
+ import { redactMcpText } from '../../../../adapters/mcp/redaction';
3
3
 
4
4
  export interface WorkContinuationSnapshot {
5
5
  schemaVersion: 1;