@moretea-labs/forge 1.7.2 → 1.8.0

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 (685) hide show
  1. package/AGENTS.md +58 -62
  2. package/CHANGELOG.md +26 -0
  3. package/CLAUDE.md +42 -62
  4. package/README.md +2 -2
  5. package/SKILL.md +0 -1
  6. package/THIRD_PARTY_NOTICES.md +5 -2
  7. package/adapters/browser/index.ts +2 -0
  8. package/adapters/chatgpt/browser-delivery-host.ts +71 -0
  9. package/adapters/chatgpt/browser-delivery-runtime.ts +783 -0
  10. package/adapters/chatgpt/controller-binding-store.ts +55 -0
  11. package/adapters/chatgpt/controller-host.ts +119 -0
  12. package/adapters/chatgpt/controller-round-host.ts +78 -0
  13. package/adapters/chatgpt/controller-round-settlement-store.ts +45 -0
  14. package/adapters/chatgpt/provider-delivery.ts +113 -0
  15. package/adapters/chatgpt/work-conversation-binding-store.ts +192 -0
  16. package/adapters/chatgpt/wsl-bridge-delivery-host.ts +63 -0
  17. package/adapters/computer/desktop-operator-contract.ts +7 -0
  18. package/adapters/computer/desktop-operator-discovery.ts +201 -0
  19. package/adapters/computer/desktop-operator-negotiation.ts +174 -0
  20. package/adapters/computer/desktop-operator-provider.ts +312 -0
  21. package/adapters/computer/index.ts +1 -0
  22. package/adapters/computer/interaction-target-authority.ts +944 -0
  23. package/adapters/controller-process/binding-store.ts +34 -0
  24. package/adapters/controller-process/controller-host.ts +26 -0
  25. package/adapters/mcp/access-mode.ts +132 -0
  26. package/adapters/mcp/audit.ts +32 -0
  27. package/adapters/mcp/auth.ts +407 -0
  28. package/adapters/mcp/controller-round-compatibility.ts +184 -0
  29. package/adapters/mcp/frozen-client-semantic-compatibility.ts +292 -0
  30. package/adapters/mcp/instructions.ts +36 -0
  31. package/adapters/mcp/legacy-context.ts +18 -0
  32. package/adapters/mcp/multi-repository.ts +437 -0
  33. package/adapters/mcp/oauth.ts +391 -0
  34. package/adapters/mcp/paths.ts +140 -0
  35. package/adapters/mcp/policy.ts +232 -0
  36. package/adapters/mcp/proxy-env.ts +62 -0
  37. package/adapters/mcp/readiness-projection.ts +24 -0
  38. package/adapters/mcp/redaction.ts +21 -0
  39. package/adapters/mcp/repo.ts +24 -0
  40. package/adapters/mcp/runtime-gateway/artifact-adapter.ts +52 -0
  41. package/adapters/mcp/runtime-gateway/context-adapter.ts +829 -0
  42. package/adapters/mcp/runtime-gateway/controller-authority-adapter.ts +191 -0
  43. package/adapters/mcp/runtime-gateway/engineering-preconditions.ts +147 -0
  44. package/adapters/mcp/runtime-gateway/execution-control-adapter.ts +28 -0
  45. package/adapters/mcp/runtime-gateway/execution-tools.ts +207 -0
  46. package/adapters/mcp/runtime-gateway/filesystem-adapter.ts +38 -0
  47. package/adapters/mcp/runtime-gateway/gateway-execution-adapter.ts +411 -0
  48. package/adapters/mcp/runtime-gateway/legacy-ios-tool-adapter.ts +105 -0
  49. package/adapters/mcp/runtime-gateway/maintenance-adapter.ts +44 -0
  50. package/adapters/mcp/runtime-gateway/model-adapter.ts +63 -0
  51. package/adapters/mcp/runtime-gateway/persisted-check-process.ts +3 -0
  52. package/adapters/mcp/runtime-gateway/plugin-adapter.ts +308 -0
  53. package/adapters/mcp/runtime-gateway/process-tools.ts +289 -0
  54. package/adapters/mcp/runtime-gateway/protected-computer-adapter.ts +76 -0
  55. package/adapters/mcp/runtime-gateway/recovery-adapter.ts +268 -0
  56. package/adapters/mcp/runtime-gateway/recovery-client-adapter.ts +70 -0
  57. package/adapters/mcp/runtime-gateway/recovery-tool-contract.ts +99 -0
  58. package/adapters/mcp/runtime-gateway/repository-compat-adapter.ts +110 -0
  59. package/adapters/mcp/runtime-gateway/result-adapter.ts +108 -0
  60. package/adapters/mcp/runtime-gateway/router.ts +728 -0
  61. package/adapters/mcp/runtime-gateway/runtime-observation-adapter.ts +1251 -0
  62. package/adapters/mcp/runtime-gateway/runtime-tool-definitions.ts +634 -0
  63. package/adapters/mcp/runtime-gateway/runtime-tool-shared.ts +27 -0
  64. package/adapters/mcp/runtime-gateway/runtime-tools.ts +68 -0
  65. package/adapters/mcp/runtime-gateway/scheduler-adapter.ts +186 -0
  66. package/adapters/mcp/runtime-gateway/shared-adapter.ts +25 -0
  67. package/adapters/mcp/runtime-gateway/status-inbox-adapter.ts +870 -0
  68. package/adapters/mcp/runtime-gateway/work-adapter.ts +3186 -0
  69. package/adapters/mcp/runtime-gateway/work-compat-adapter.ts +502 -0
  70. package/adapters/mcp/runtime-gateway/work-validation-reconciler.ts +1 -0
  71. package/adapters/mcp/server.ts +1048 -0
  72. package/adapters/mcp/setup.ts +791 -0
  73. package/adapters/mcp/tool-capability-cache.ts +87 -0
  74. package/adapters/mcp/tool-mapping/access-tools.ts +387 -0
  75. package/adapters/mcp/tool-mapping/legacy-tool-service.ts +5265 -0
  76. package/adapters/mcp/tool-mapping/post-finalize-work-attribution.ts +150 -0
  77. package/adapters/mcp/tool-mapping/repository-tools.ts +1691 -0
  78. package/adapters/mcp/tool-mapping/tools.ts +9 -0
  79. package/adapters/mcp/tool-mapping/umbrella-tools.ts +117 -0
  80. package/adapters/mcp/toolset-names.ts +74 -0
  81. package/adapters/mcp/toolset-selection.ts +41 -0
  82. package/adapters/mcp/toolset.ts +336 -0
  83. package/adapters/mcp/transports/http.ts +1456 -0
  84. package/adapters/mcp/transports/session-registry.ts +513 -0
  85. package/adapters/mcp/transports/stdio.ts +8 -0
  86. package/adapters/mcp/tunnels/openai-secure-tunnel.ts +139 -0
  87. package/adapters/mcp/types.ts +41 -0
  88. package/assets/AGENTS.md +2 -16
  89. package/assets/CLAUDE.md +2 -16
  90. package/assets/hooks/AGENTS.md +3 -14
  91. package/assets/hooks/CLAUDE.md +3 -14
  92. package/assets/hooks/hook-input.sh +9 -2
  93. package/assets/hooks/lib/workflow-state.sh +28 -10
  94. package/assets/hooks/prompt-guard.sh +63 -37
  95. package/assets/hooks/security-sentinel.sh +2 -1
  96. package/assets/hooks/session-start-context.sh +7 -5
  97. package/assets/hooks/stop-orchestrator.sh +13 -3
  98. package/assets/initializer-question-pack.v4.json +11 -7
  99. package/assets/partials/05-workflow.partial.md +18 -73
  100. package/assets/partials/07-footer.partial.md +1 -1
  101. package/assets/partials-agents/02-operating-mode.partial.md +1 -2
  102. package/assets/partials-agents/04-task-protocol.partial.md +14 -59
  103. package/assets/partials-agents/06-quality-safety.partial.md +11 -16
  104. package/assets/partials-agents/08-deep-docs.partial.md +1 -2
  105. package/assets/plan-map.json +11 -11
  106. package/assets/plugin-registry.v1.json +9 -3
  107. package/assets/plugin-trust-policy.v1.json +6 -0
  108. package/assets/recovery/ForgeRecovery.ps1 +100 -0
  109. package/assets/recovery/forge-wsl-rescue +271 -0
  110. package/assets/reference-configs/development-protocol.md +11 -15
  111. package/assets/reference-configs/document-generation.md +1 -1
  112. package/assets/reference-configs/global-working-rules.md +9 -1
  113. package/assets/reference-configs/harness-overview.md +22 -112
  114. package/assets/reference-configs/hook-operations.md +1 -1
  115. package/assets/reference-configs/sprint-contracts.md +2 -2
  116. package/assets/skill-version.json +2 -2
  117. package/assets/templates/helpers/architecture-event.ts +3 -34
  118. package/assets/templates/helpers/architecture-queue.sh +61 -10
  119. package/assets/templates/helpers/archive-workflow.sh +90 -180
  120. package/assets/templates/helpers/capability-config.ts +8 -11
  121. package/assets/templates/helpers/capability-resolver.ts +37 -19
  122. package/assets/templates/helpers/capture-plan.sh +2 -2
  123. package/assets/templates/helpers/check-architecture-sync.sh +1 -9
  124. package/assets/templates/helpers/check-task-sync.sh +82 -11
  125. package/assets/templates/helpers/check-task-workflow.sh +1 -3
  126. package/assets/templates/helpers/context-contract-sync.sh +1 -12
  127. package/assets/templates/helpers/contract-worktree.sh +26 -24
  128. package/assets/templates/helpers/ensure-task-workflow.sh +6 -8
  129. package/assets/templates/helpers/inspect-project-state.ts +1 -1
  130. package/assets/templates/helpers/migrate-project-template.sh +1 -1
  131. package/assets/templates/helpers/migrate-workflow-docs.ts +53 -239
  132. package/assets/templates/helpers/new-plan.sh +2 -2
  133. package/assets/templates/helpers/plan-to-todo.sh +3 -31
  134. package/assets/templates/helpers/sprint-backlog.sh +1 -1
  135. package/assets/templates/helpers/switch-plan.sh +1 -1
  136. package/assets/templates/helpers/workflow-contract.ts +1 -0
  137. package/assets/workflow-contract.v1.json +63 -171
  138. package/assets/workflows/xiaohongshu/xiaohongshu.collect-metrics.v1.draft.json +118 -0
  139. package/assets/workflows/xiaohongshu/xiaohongshu.publish-image-note.v1.draft.json +316 -0
  140. package/assets/workflows/xiaohongshu/xiaohongshu.publish-long-text.v1.draft.json +324 -0
  141. package/docs/architecture/CURRENT.md +148 -13
  142. package/docs/architecture/EVOLUTION.md +13 -0
  143. package/docs/architecture/decisions/20260801-controller-home-sqlite-state.md +2 -1
  144. package/docs/architecture/decisions/20260831-independent-windows-wsl-host-rescue.md +59 -0
  145. package/docs/architecture/decisions/20260904-ios-device-migration-baseline.md +120 -0
  146. package/docs/architecture/decisions/20260904-repository-runtime-data-boundary.md +42 -0
  147. package/docs/architecture/decisions/20260907-assistant-learning-loop.md +35 -0
  148. package/docs/architecture/decisions/20260907-controller-round-transition-policy.md +296 -0
  149. package/docs/architecture/decisions/20260907-maintenance-diagnosis-bounded-read.md +39 -0
  150. package/docs/architecture/domains/verification.md +7 -0
  151. package/docs/architecture/domains/workflow-engine.md +1 -1
  152. package/docs/architecture/index.md +3 -3
  153. package/docs/architecture/modules/controller-runtime/transport-lifecycle.md +19 -8
  154. package/docs/architecture/requests/2026-09-04-computer-plugin-workflow-taxonomy.md +124 -0
  155. package/docs/forge-chatgpt-mcp-setup.md +5 -3
  156. package/docs/forge-plugin-management.md +20 -4
  157. package/docs/forge-runtime-self-healing-loop.md +2 -0
  158. package/docs/operations/benchmark-cross-version-freeze.md +38 -0
  159. package/docs/operations/controller-browser-plugin.md +3 -1
  160. package/docs/operations/homebrew.md +2 -2
  161. package/docs/operations/platform-support.md +16 -8
  162. package/docs/operations/platform-support.zh-CN.md +2 -2
  163. package/docs/operations/standalone-disaster-recovery.md +26 -1
  164. package/docs/operations/uu-remote-rescue.md +41 -0
  165. package/docs/operations/windows-wsl-host-rescue.md +133 -0
  166. package/docs/public-usage-guide.md +1 -1
  167. package/docs/public-usage-guide.zh-CN.md +1 -1
  168. package/docs/tutorials/01-install-and-start.md +1 -1
  169. package/docs/tutorials/01-install-and-start.zh-CN.md +1 -1
  170. package/docs/tutorials/02-connect-chatgpt.md +4 -4
  171. package/docs/tutorials/02-connect-chatgpt.zh-CN.md +4 -4
  172. package/docs/wiki/Implementation.md +1 -1
  173. package/package.json +23 -14
  174. package/packages/kernel/controller/api/index.ts +2 -0
  175. package/packages/kernel/controller/application/controller-round-service.ts +29 -0
  176. package/packages/kernel/controller/application/controller-service.ts +30 -0
  177. package/packages/kernel/controller/domain/controller-round-transition-policy.ts +308 -0
  178. package/packages/kernel/controller/domain/controller-round.ts +107 -0
  179. package/packages/kernel/controller/domain/execution-quality.ts +133 -0
  180. package/packages/kernel/controller/domain/types.ts +56 -0
  181. package/packages/kernel/controller/index.ts +1 -0
  182. package/packages/kernel/controller/infrastructure/controller-binding-store.ts +84 -0
  183. package/packages/kernel/controller/infrastructure/controller-round-store.ts +1384 -0
  184. package/packages/kernel/controller/infrastructure/controller-session-store.ts +578 -0
  185. package/packages/kernel/controller/ports/controller-host.ts +16 -0
  186. package/packages/kernel/goal/api/index.ts +1 -0
  187. package/packages/kernel/goal/domain/types.ts +40 -0
  188. package/packages/kernel/goal/index.ts +1 -0
  189. package/packages/kernel/identity/api/index.ts +5 -0
  190. package/packages/kernel/identity/application/identity-service.ts +67 -0
  191. package/packages/kernel/identity/domain/scope.ts +63 -0
  192. package/packages/kernel/identity/domain/semantic-sync.ts +81 -0
  193. package/packages/kernel/identity/domain/types.ts +44 -0
  194. package/packages/kernel/identity/domain/workspace.ts +56 -0
  195. package/packages/kernel/identity/index.ts +1 -0
  196. package/packages/kernel/identity/infrastructure/identity-store.ts +75 -0
  197. package/packages/kernel/memory/api/index.ts +5 -0
  198. package/packages/kernel/memory/application/experience-service.ts +118 -0
  199. package/packages/kernel/memory/application/outcome-service.ts +77 -0
  200. package/packages/kernel/memory/domain/experience.ts +103 -0
  201. package/packages/kernel/memory/domain/operational-prior.ts +92 -0
  202. package/packages/kernel/memory/index.ts +1 -0
  203. package/packages/kernel/progression/api/index.ts +2 -0
  204. package/packages/kernel/progression/application/projector.ts +211 -0
  205. package/packages/kernel/progression/domain/types.ts +116 -0
  206. package/packages/kernel/progression/index.ts +1 -0
  207. package/packages/kernel/scheduler/api/index.ts +6 -0
  208. package/packages/kernel/scheduler/application/continuation-service.ts +212 -0
  209. package/packages/kernel/scheduler/application/eligibility.ts +252 -0
  210. package/packages/kernel/scheduler/application/schedule-service.ts +24 -0
  211. package/packages/kernel/scheduler/application/settlement.ts +197 -0
  212. package/packages/kernel/scheduler/domain/continuation.ts +38 -0
  213. package/packages/kernel/scheduler/domain/schedule.ts +149 -0
  214. package/packages/kernel/scheduler/index.ts +1 -0
  215. package/packages/kernel/scheduler/infrastructure/continuation-dispatch-store.ts +38 -0
  216. package/packages/kernel/scheduler/infrastructure/schedule-store.ts +785 -0
  217. package/packages/kernel/work/api/index.ts +15 -0
  218. package/packages/kernel/work/application/work-service.ts +148 -0
  219. package/packages/kernel/work/domain/admission-policy.ts +34 -0
  220. package/packages/kernel/work/domain/check-receipt.ts +43 -0
  221. package/packages/kernel/work/domain/context-closure-receipt.ts +32 -0
  222. package/packages/kernel/work/domain/engineering-contracts.ts +157 -0
  223. package/packages/kernel/work/domain/engineering-design.ts +281 -0
  224. package/packages/kernel/work/domain/engineering-profile.ts +242 -0
  225. package/packages/kernel/work/domain/execution-concurrency.ts +254 -0
  226. package/packages/kernel/work/domain/execution-snapshot.ts +33 -0
  227. package/packages/kernel/work/domain/implementation-review.ts +510 -0
  228. package/packages/kernel/work/domain/project-engineering-contract.ts +202 -0
  229. package/packages/kernel/work/domain/repository-completion-receipt.ts +73 -0
  230. package/packages/kernel/work/domain/state-machine.ts +259 -0
  231. package/packages/kernel/work/domain/types.ts +528 -0
  232. package/packages/kernel/work/index.ts +1 -0
  233. package/packages/kernel/work/infrastructure/work-contract-store.ts +1876 -0
  234. package/packages/kernel/work/ports/work-contract-store.ts +18 -0
  235. package/packages/plugin-runtime/browser/index.ts +3 -0
  236. package/packages/plugin-runtime/browser/provider-registry.ts +110 -0
  237. package/packages/plugin-runtime/browser/runtime-contract.ts +150 -0
  238. package/packages/plugin-runtime/browser/session-authority.ts +61 -0
  239. package/packages/plugin-runtime/computer/index.ts +6 -0
  240. package/packages/plugin-runtime/computer/provider-error.ts +26 -0
  241. package/packages/plugin-runtime/computer/provider-registration.ts +52 -0
  242. package/packages/plugin-runtime/computer/provider-registry.ts +63 -0
  243. package/packages/plugin-runtime/computer/provider.ts +19 -0
  244. package/packages/plugin-runtime/computer/target-authority.ts +190 -0
  245. package/packages/plugin-runtime/computer/target-persistence.ts +54 -0
  246. package/packages/plugin-runtime/external/index.ts +1 -0
  247. package/packages/plugin-runtime/external/unix-jsonl-transport.ts +457 -0
  248. package/packages/plugin-runtime/index.ts +3 -0
  249. package/packages/protocols/browser/index.ts +1 -0
  250. package/packages/protocols/browser/session.ts +98 -0
  251. package/packages/protocols/computer/contract.ts +199 -0
  252. package/packages/protocols/computer/index.ts +1 -0
  253. package/packages/protocols/failure/contract.ts +158 -0
  254. package/packages/protocols/failure/index.ts +1 -0
  255. package/packages/protocols/handoff/index.ts +1 -0
  256. package/packages/protocols/handoff/status.ts +22 -0
  257. package/packages/protocols/mcp/execution-context.ts +11 -0
  258. package/packages/protocols/mcp/index.ts +2 -0
  259. package/packages/protocols/mcp/tool-contract.ts +42 -0
  260. package/packages/workflow-runtime/api/index.ts +2 -0
  261. package/packages/workflow-runtime/application/interpreter.ts +342 -0
  262. package/packages/workflow-runtime/domain/workflow-asset.ts +223 -0
  263. package/packages/workflow-runtime/index.ts +1 -0
  264. package/scripts/assemble-template.ts +1 -1
  265. package/scripts/benchmark-computer-hotpath.ts +255 -0
  266. package/scripts/benchmark-controller-round2.ts +54 -2
  267. package/scripts/benchmark-ios-agent-device.ts +3 -6
  268. package/scripts/benchmark-mcp-transport.ts +3 -4
  269. package/scripts/benchmark-operational-memory-activation.ts +235 -0
  270. package/scripts/benchmark-operational-shadow.ts +28 -0
  271. package/scripts/bootstrap-runtime-maintenance-recovery.sh +4 -1
  272. package/scripts/canary-chatgpt-provider-delivery.ts +97 -0
  273. package/scripts/canary-controller-semantic-wait.ts +195 -0
  274. package/scripts/canary-global-hook.sh +2 -2
  275. package/scripts/check-mcp-compatibility.ts +173 -7
  276. package/scripts/check-platform-support.mjs +28 -2
  277. package/scripts/check-public-docs.sh +1 -1
  278. package/scripts/check-release-readiness.sh +1 -1
  279. package/scripts/check-repository-hygiene.mjs +92 -0
  280. package/scripts/check-runtime-architecture.mjs +1206 -95
  281. package/scripts/check-source-duplication.mjs +9 -1
  282. package/scripts/check-tarball-install-smoke.sh +98 -15
  283. package/scripts/controller-ngrok-rotation.sh +5 -4
  284. package/scripts/create-project-dirs.sh +10 -74
  285. package/scripts/forge-local-recovery-helper.mjs +204 -0
  286. package/scripts/forge-uu-remote-rescue-helper.d.mts +31 -0
  287. package/scripts/forge-uu-remote-rescue-helper.mjs +409 -0
  288. package/scripts/forge-windows-host-recovery-helper.mjs +136 -0
  289. package/scripts/hook-shim.sh +2 -2
  290. package/scripts/init-project.sh +12 -70
  291. package/scripts/install-desktop-operator-registration.ts +4 -2
  292. package/scripts/install-independent-windows-wsl-recovery.ts +125 -0
  293. package/scripts/install-standalone-recovery.ts +122 -10
  294. package/scripts/install-uu-remote-rescue-registration.ts +74 -0
  295. package/scripts/install-windows-host-recovery-registration.ts +22 -0
  296. package/scripts/lib/controller-home-env.sh +6 -3
  297. package/scripts/lib/project-init-lib.sh +39 -582
  298. package/scripts/migrate-chatgpt-automation-schedules.ts +2 -2
  299. package/scripts/migrate-windows-wsl-controller-home.ts +306 -0
  300. package/scripts/open-source-audit-allowlist.txt +12 -1
  301. package/scripts/portability-bindings.mjs +70 -0
  302. package/scripts/run-bounded-command.mjs +55 -0
  303. package/scripts/run-bun-test-file.ts +22 -6
  304. package/scripts/run-governed-gate.ts +4 -1
  305. package/scripts/smoke-mcp-http-runtime.ts +1 -1
  306. package/scripts/smoke-runtime-recovery.ts +34 -1
  307. package/scripts/smoke-schedule-engine.ts +1 -1
  308. package/scripts/stage-runtime-release.ts +6 -1
  309. package/scripts/test-governance.ts +51 -2
  310. package/src/cli/agent-jobs/job-manager.ts +10 -1
  311. package/src/cli/chatgpt-browser/bind-server.ts +2 -1
  312. package/src/cli/chatgpt-browser/binding.ts +20 -10
  313. package/src/cli/chatgpt-browser/bridge-extension.ts +75 -0
  314. package/src/cli/chatgpt-browser/bridge-provider.ts +376 -11
  315. package/src/cli/chatgpt-browser/engine.ts +10 -11
  316. package/src/cli/chatgpt-browser/native-provider.ts +24 -83
  317. package/src/cli/chatgpt-browser/oracle-provider.ts +5 -3
  318. package/src/cli/chatgpt-browser/types.ts +1 -0
  319. package/src/cli/commands/bootstrap-control.ts +334 -0
  320. package/src/cli/commands/brain-assistant.ts +38 -0
  321. package/src/cli/commands/brain.ts +193 -40
  322. package/src/cli/commands/chatgpt.ts +127 -0
  323. package/src/cli/commands/computer.ts +437 -0
  324. package/src/cli/commands/doctor.ts +18 -1
  325. package/src/cli/commands/init-hook.ts +71 -61
  326. package/src/cli/commands/init.ts +3 -1
  327. package/src/cli/commands/mcp.ts +16 -10
  328. package/src/cli/commands/plugin.ts +38 -12
  329. package/src/cli/commands/recovery.ts +493 -80
  330. package/src/cli/commands/runtime.ts +9 -4
  331. package/src/cli/commands/setup-profile.ts +89 -39
  332. package/src/cli/commands/status.ts +2 -1
  333. package/src/cli/controller/check-runner.ts +487 -98
  334. package/src/cli/controller/context/types.ts +7 -1
  335. package/src/cli/controller/context-pack.ts +23 -3
  336. package/src/cli/controller/issue-store.ts +1 -1
  337. package/src/cli/controller/systemd-user.ts +110 -0
  338. package/src/cli/controller/types.ts +10 -70
  339. package/src/cli/controller/worklog.ts +67 -13
  340. package/src/cli/editing/edit-operation-contract.ts +92 -0
  341. package/src/cli/editing/edit-session.ts +289 -13
  342. package/src/cli/github/plugin.ts +17 -12
  343. package/src/cli/hook/route-registry.ts +3 -5
  344. package/src/cli/hook/runtime.ts +49 -3
  345. package/src/cli/index.ts +3 -0
  346. package/src/cli/local-bridge/connector-freshness.ts +2 -2
  347. package/src/cli/local-bridge/console-automations.ts +2 -2
  348. package/src/cli/local-bridge/facade-api.ts +41 -14
  349. package/src/cli/local-bridge/job-store.ts +1 -1
  350. package/src/cli/local-bridge/server.ts +24 -27
  351. package/src/cli/mcp/access-mode.ts +2 -132
  352. package/src/cli/mcp/access-tools.ts +2 -387
  353. package/src/cli/mcp/audit.ts +2 -32
  354. package/src/cli/mcp/auth.ts +2 -404
  355. package/src/cli/mcp/instructions.ts +2 -34
  356. package/src/cli/mcp/legacy-context.ts +2 -16
  357. package/src/cli/mcp/legacy-tool-service.ts +2 -5308
  358. package/src/cli/mcp/multi-repository.ts +2 -436
  359. package/src/cli/mcp/oauth.ts +2 -375
  360. package/src/cli/mcp/openai-secure-tunnel.ts +2 -0
  361. package/src/cli/mcp/paths.ts +2 -140
  362. package/src/cli/mcp/policy.ts +2 -232
  363. package/src/cli/mcp/post-finalize-work-attribution.ts +2 -150
  364. package/src/cli/mcp/proxy-env.ts +2 -62
  365. package/src/cli/mcp/readiness-projection.ts +2 -24
  366. package/src/cli/mcp/redaction.ts +2 -21
  367. package/src/cli/mcp/repo.ts +2 -24
  368. package/src/cli/mcp/repository-tools.ts +2 -1613
  369. package/src/cli/mcp/server.ts +2 -951
  370. package/src/cli/mcp/setup.ts +2 -737
  371. package/src/cli/mcp/tool-capability-cache.ts +2 -87
  372. package/src/cli/mcp/tool-contract.ts +2 -14
  373. package/src/cli/mcp/tools.ts +2 -9
  374. package/src/cli/mcp/toolset-names.ts +2 -70
  375. package/src/cli/mcp/toolset-selection.ts +2 -41
  376. package/src/cli/mcp/toolset.ts +2 -336
  377. package/src/cli/mcp/transports/AGENTS.md +1 -10
  378. package/src/cli/mcp/transports/CLAUDE.md +1 -10
  379. package/src/cli/mcp/transports/http.ts +2 -1414
  380. package/src/cli/mcp/transports/session-registry.ts +2 -490
  381. package/src/cli/mcp/transports/stdio.ts +2 -8
  382. package/src/cli/mcp/types.ts +2 -41
  383. package/src/cli/mcp/umbrella-tools.ts +2 -117
  384. package/src/cli/repositories/command-executor.ts +64 -18
  385. package/src/cli/repositories/command-scope.ts +117 -1
  386. package/src/cli/repositories/controller-home.ts +119 -1
  387. package/src/cli/repositories/identity.ts +13 -0
  388. package/src/cli/repositories/registry.ts +68 -49
  389. package/src/cli/repositories/repository-snapshot.ts +53 -7
  390. package/src/cli/repositories/runtime-storage.ts +27 -2
  391. package/src/cli/repositories/safe-patch.ts +34 -38
  392. package/src/cli/repositories/selected-path-actions.ts +22 -2
  393. package/src/cli/repositories/structured-git.ts +105 -25
  394. package/src/cli/runtime/helper-runner.ts +7 -0
  395. package/src/cli/runtime-invocation.ts +8 -1
  396. package/src/cli/tools/codegraph.ts +44 -25
  397. package/src/core/adoption/manifest-templates.ts +1 -1
  398. package/src/core/adoption/plan.ts +3 -26
  399. package/src/core/adoption/workflow-contract-plan.ts +17 -9
  400. package/src/effects/process-runner.ts +8 -14
  401. package/src/runtime/context/assistant-context.ts +154 -0
  402. package/src/runtime/context/assistant-work-context.ts +147 -0
  403. package/src/runtime/context/codegraph-cache-boundary.ts +255 -0
  404. package/src/runtime/context/codegraph-read-provider.ts +55 -22
  405. package/src/runtime/context/codegraph-sidecar.cjs +8 -1
  406. package/src/runtime/context/context-closure.ts +268 -0
  407. package/src/runtime/context/context-plane.ts +211 -0
  408. package/src/runtime/context/project-engineering-contract.ts +60 -0
  409. package/src/runtime/control-plane/bootstrap/capability-provider.ts +74 -0
  410. package/src/runtime/control-plane/bootstrap/control-api.ts +57 -0
  411. package/src/runtime/control-plane/bootstrap/index.ts +5 -0
  412. package/src/runtime/control-plane/bootstrap/state-machine.ts +141 -0
  413. package/src/runtime/control-plane/bootstrap/store.ts +21 -0
  414. package/src/runtime/control-plane/bootstrap/types.ts +87 -0
  415. package/src/runtime/control-plane/cleanup-artifact-retention.ts +328 -0
  416. package/src/runtime/control-plane/codegraph-cache-retention.ts +164 -0
  417. package/src/runtime/control-plane/concurrency/work-execution-concurrency.ts +320 -0
  418. package/src/runtime/control-plane/execution/content-equivalent-commit-authority.ts +169 -0
  419. package/src/runtime/control-plane/execution/controller-authority-recovery.ts +350 -0
  420. package/src/runtime/control-plane/execution/direct-canonical-work-reconciliation.ts +85 -0
  421. package/src/runtime/control-plane/execution/direct-edit-work-completion.ts +369 -99
  422. package/src/runtime/control-plane/execution/edit-validation-coordinator.ts +103 -15
  423. package/src/runtime/control-plane/execution/implementation-review-content.ts +95 -0
  424. package/src/runtime/control-plane/execution/repository-work-attribution.ts +2 -2
  425. package/src/runtime/control-plane/execution/retained-work-resume.ts +336 -6
  426. package/src/runtime/control-plane/execution/validation.ts +28 -3
  427. package/src/runtime/control-plane/execution/work-authority-reconciler.ts +116 -0
  428. package/src/runtime/control-plane/execution/work-completion-authority.ts +44 -2
  429. package/src/runtime/control-plane/execution/work-evidence-policy.ts +34 -3
  430. package/src/runtime/control-plane/execution/work-execution-support.ts +42 -22
  431. package/src/runtime/control-plane/execution/work-finalization-service.ts +1103 -166
  432. package/src/runtime/control-plane/execution/work-handle-authority.ts +219 -22
  433. package/src/runtime/control-plane/execution/work-handle-store.ts +77 -0
  434. package/src/runtime/control-plane/execution/work-head-settlement.ts +75 -0
  435. package/src/runtime/control-plane/execution/work-lifecycle-audit.ts +145 -23
  436. package/src/runtime/control-plane/execution/work-operation-service.ts +49 -13
  437. package/src/runtime/control-plane/execution/work-preparation-service.ts +31 -15
  438. package/src/runtime/control-plane/execution/work-remote-delivery.ts +1 -1
  439. package/src/runtime/control-plane/execution/work-task-receipt.ts +20 -1
  440. package/src/runtime/control-plane/execution/work-terminal-cleanup.ts +407 -76
  441. package/src/runtime/control-plane/execution/work-validation-reconciler.ts +88 -18
  442. package/src/runtime/control-plane/execution/work-verification-context.ts +1 -1
  443. package/src/runtime/control-plane/execution/work-verification-service.ts +258 -4
  444. package/src/runtime/control-plane/execution/work-verification-snapshot.ts +200 -15
  445. package/src/runtime/control-plane/facade/capability-registry.ts +21 -10
  446. package/src/runtime/control-plane/facade/controller-round-relay.ts +3 -1118
  447. package/src/runtime/control-plane/facade/controller-session-store.ts +2 -488
  448. package/src/runtime/control-plane/facade/goal-workloop-access.ts +6 -3
  449. package/src/runtime/control-plane/facade/goal-workloop.ts +972 -137
  450. package/src/runtime/control-plane/facade/handoff-inbox-application.ts +158 -0
  451. package/src/runtime/control-plane/facade/handoff-inbox-store.ts +10 -0
  452. package/src/runtime/control-plane/facade/index.ts +4 -2
  453. package/src/runtime/control-plane/facade/operation-digest.ts +22 -58
  454. package/src/runtime/control-plane/facade/plan-contract-store.ts +1004 -38
  455. package/src/runtime/control-plane/facade/repository-work-admission.ts +19 -1
  456. package/src/runtime/control-plane/facade/requirement-authority.ts +218 -0
  457. package/src/runtime/control-plane/facade/requirement-board.ts +6 -1
  458. package/src/runtime/control-plane/facade/rh-work-operation-contract.ts +48 -0
  459. package/src/runtime/control-plane/facade/semantic-admission.ts +8 -16
  460. package/src/runtime/control-plane/facade/suggested-actions.ts +4 -1
  461. package/src/runtime/control-plane/facade/types.ts +189 -532
  462. package/src/runtime/control-plane/facade/work-admission-policy.ts +84 -35
  463. package/src/runtime/control-plane/facade/work-contract-store.ts +2 -1043
  464. package/src/runtime/control-plane/facade/work-implementation-review.ts +2 -0
  465. package/src/runtime/control-plane/facade/work-state-machine.ts +2 -250
  466. package/src/runtime/control-plane/generated-cache-retention.ts +239 -18
  467. package/src/runtime/control-plane/global-scheduler/durable-admission.ts +12 -1
  468. package/src/runtime/control-plane/global-scheduler/maintenance.ts +76 -13
  469. package/src/runtime/control-plane/global-scheduler/periodic-cleanup-entry.ts +55 -0
  470. package/src/runtime/control-plane/global-scheduler/periodic-cleanup-process.ts +98 -0
  471. package/src/runtime/control-plane/global-scheduler/reconciliation.ts +1 -1
  472. package/src/runtime/control-plane/global-scheduler/scheduler-worker-entry.ts +10 -0
  473. package/src/runtime/control-plane/global-scheduler/scheduler.ts +173 -81
  474. package/src/runtime/control-plane/global-scheduler/worker-launch.ts +18 -6
  475. package/src/runtime/control-plane/launcher/chatgpt-round-continuation.ts +397 -0
  476. package/src/runtime/control-plane/launcher/chatgpt-work-binding-store.ts +2 -177
  477. package/src/runtime/control-plane/launcher/chatgpt-work-continuation.ts +301 -560
  478. package/src/runtime/control-plane/launcher/provider-mcp-bootstrap.ts +20 -4
  479. package/src/runtime/control-plane/launcher/thin-launcher.ts +50 -4
  480. package/src/runtime/control-plane/lifecycle-retention-metrics.ts +60 -0
  481. package/src/runtime/control-plane/persistence/experience-store.ts +169 -0
  482. package/src/runtime/control-plane/persistence/operational-prior-store.ts +348 -0
  483. package/src/runtime/control-plane/persistence/requirement-store.ts +30 -22
  484. package/src/runtime/control-plane/persistence/sqlite-store.ts +545 -76
  485. package/src/runtime/control-plane/persistence/workflow-content-store.ts +98 -0
  486. package/src/runtime/control-plane/persistence/workflow-registry-store.ts +186 -0
  487. package/src/runtime/control-plane/persistence/workflow-run-store.ts +123 -0
  488. package/src/runtime/control-plane/release-retention.ts +56 -16
  489. package/src/runtime/control-plane/repository-namespace-retention.ts +208 -0
  490. package/src/runtime/control-plane/routing/route-policy.ts +19 -0
  491. package/src/runtime/control-plane/runtime-cleanup.ts +574 -37
  492. package/src/runtime/control-plane/runtime-generation.ts +6 -0
  493. package/src/runtime/control-plane/workspace/semantic-sync-service.ts +465 -0
  494. package/src/runtime/control-plane/workspace/workspace-store.ts +80 -0
  495. package/src/runtime/diagnostics/incident-repair.ts +406 -0
  496. package/src/runtime/diagnostics/mcp-timing.ts +125 -6
  497. package/src/runtime/diagnostics/performance.ts +6 -14
  498. package/src/runtime/diagnostics/read-only-tool.ts +1 -1
  499. package/src/runtime/evidence/artifact-store.ts +65 -2
  500. package/src/runtime/evidence/operational-shadow.ts +38 -0
  501. package/src/runtime/evidence/process-check-receipt.ts +5 -43
  502. package/src/runtime/evidence/sensitive-output.ts +4 -4
  503. package/src/runtime/execution/jobs/receipt-recovery.ts +1 -1
  504. package/src/runtime/execution/jobs/store.ts +121 -2
  505. package/src/runtime/execution/managed-workspace.ts +55 -5
  506. package/src/runtime/execution/process-runtime/canary.ts +19 -5
  507. package/src/runtime/execution/process-runtime/check-classification.ts +48 -0
  508. package/src/runtime/execution/process-runtime/check-facade.ts +23 -9
  509. package/src/runtime/execution/process-runtime/check-receipt.ts +1 -1
  510. package/src/runtime/execution/process-runtime/check-result-retention.ts +132 -0
  511. package/src/runtime/execution/process-runtime/check-result.ts +73 -2
  512. package/src/runtime/execution/process-runtime/check-runner-sidecar.ts +42 -3
  513. package/src/runtime/execution/process-runtime/check-storage.ts +187 -0
  514. package/src/runtime/execution/process-runtime/command-facade.ts +38 -87
  515. package/src/runtime/execution/process-runtime/index.ts +1 -0
  516. package/src/runtime/execution/process-runtime/interactive-admission.ts +2 -1
  517. package/src/runtime/execution/process-runtime/lightweight-managed.ts +32 -1
  518. package/src/runtime/execution/process-runtime/persisted-check.ts +128 -21
  519. package/src/runtime/execution/process-runtime/resource-claims.ts +60 -3
  520. package/src/runtime/execution/process-runtime/runtime.ts +132 -15
  521. package/src/runtime/execution/process-runtime/types.ts +22 -0
  522. package/src/runtime/execution/workers/executor.ts +16 -13
  523. package/src/runtime/execution/workers/worker-entry.ts +1 -1
  524. package/src/runtime/gateway/mcp/execution-tools.ts +2 -207
  525. package/src/runtime/gateway/mcp/legacy-ios-tool-adapter.ts +2 -61
  526. package/src/runtime/gateway/mcp/persisted-check-process.ts +2 -3
  527. package/src/runtime/gateway/mcp/process-tools.ts +2 -289
  528. package/src/runtime/gateway/mcp/router.ts +2 -1125
  529. package/src/runtime/gateway/mcp/runtime-tool-definitions.ts +2 -565
  530. package/src/runtime/gateway/mcp/runtime-tools.ts +2 -6655
  531. package/src/runtime/gateway/mcp/work-validation-reconciler.ts +2 -1
  532. package/src/runtime/maintenance/cleanup.ts +38 -24
  533. package/src/runtime/platform/browser-product-discovery.ts +174 -0
  534. package/src/runtime/platform/computer-platform.ts +14 -0
  535. package/src/runtime/platform/executable-discovery.ts +54 -0
  536. package/src/runtime/platform/fetch-http-server.ts +90 -0
  537. package/src/runtime/platform/service-manager.ts +138 -0
  538. package/src/runtime/platform/windows-host-discovery.ts +118 -0
  539. package/src/runtime/platform/windows-recovery-deployment.ts +67 -0
  540. package/src/runtime/plugins/action-application.ts +135 -0
  541. package/src/runtime/plugins/app-store-connect-adapter.ts +9 -21
  542. package/src/runtime/plugins/browser-adapter.ts +140 -100
  543. package/src/runtime/plugins/browser-automation-service.ts +15 -36
  544. package/src/runtime/plugins/browser-macos-bridge.ts +69 -21
  545. package/src/runtime/plugins/browser-manifest-surface.ts +30 -6
  546. package/src/runtime/plugins/browser-native-session-service.ts +1 -1
  547. package/src/runtime/plugins/browser-provider-registry.ts +2 -109
  548. package/src/runtime/plugins/browser-registration.ts +16 -0
  549. package/src/runtime/plugins/browser-runtime-contract.ts +2 -154
  550. package/src/runtime/plugins/browser-runtime.ts +41 -9
  551. package/src/runtime/plugins/browser-session-authority.ts +101 -291
  552. package/src/runtime/plugins/browser-session-legacy-migration.ts +203 -0
  553. package/src/runtime/plugins/browser-session-store.ts +229 -36
  554. package/src/runtime/plugins/browser-session-types.ts +2 -98
  555. package/src/runtime/plugins/capability-authorization-grants.ts +17 -0
  556. package/src/runtime/plugins/catalog-trust.ts +82 -0
  557. package/src/runtime/plugins/computer-registration.ts +839 -0
  558. package/src/runtime/plugins/config-store.ts +119 -0
  559. package/src/runtime/plugins/desktop-operator-external-policy.ts +932 -0
  560. package/src/runtime/plugins/desktop-operator-registration.ts +111 -8
  561. package/src/runtime/plugins/errors.ts +8 -1
  562. package/src/runtime/plugins/external-adapter.ts +45 -322
  563. package/src/runtime/plugins/external-provider-policy.ts +48 -0
  564. package/src/runtime/plugins/external-registration.ts +9 -1
  565. package/src/runtime/plugins/external-unix-socket-probe.cjs +9 -3
  566. package/src/runtime/plugins/external-unix-socket.ts +64 -193
  567. package/src/runtime/plugins/first-party-external-registration.ts +163 -0
  568. package/src/runtime/plugins/first-party-registry.ts +3 -1
  569. package/src/runtime/plugins/github-adapter.ts +1 -2
  570. package/src/runtime/plugins/gmail-adapter.ts +6 -6
  571. package/src/runtime/plugins/google-calendar-adapter.ts +6 -6
  572. package/src/runtime/plugins/google-shared.ts +31 -46
  573. package/src/runtime/plugins/google-tasks-adapter.ts +6 -6
  574. package/src/runtime/plugins/ios-adapter.ts +1 -2
  575. package/src/runtime/plugins/local-system-adapter.ts +180 -0
  576. package/src/runtime/plugins/macos-capability-broker.ts +15 -105
  577. package/src/runtime/plugins/resend-adapter.ts +15 -24
  578. package/src/runtime/plugins/store.ts +493 -51
  579. package/src/runtime/plugins/types.ts +8 -1
  580. package/src/runtime/plugins/uu-remote-rescue-registration.ts +155 -0
  581. package/src/runtime/plugins/windows-host-recovery-install.ts +68 -0
  582. package/src/runtime/plugins/windows-host-recovery-registration.ts +85 -0
  583. package/src/runtime/plugins/xiaohongshu-publish.ts +86 -430
  584. package/src/runtime/projections/controller-context.ts +12 -6
  585. package/src/runtime/projections/git-status-sampler.ts +73 -22
  586. package/src/runtime/projections/materialized-view.ts +14 -8
  587. package/src/runtime/recovery/capability-action-application.ts +228 -0
  588. package/src/runtime/recovery/index.ts +3 -0
  589. package/src/runtime/recovery/lifecycle-inventory.ts +338 -0
  590. package/src/runtime/recovery/local-jobs-repair.ts +14 -14
  591. package/src/runtime/recovery/maintenance-executor.ts +358 -76
  592. package/src/runtime/recovery/quarantine-retention.ts +256 -0
  593. package/src/runtime/release/identity.ts +6 -0
  594. package/src/runtime/resources/leases/store.ts +1 -1
  595. package/src/runtime/root/active-execution-power-assertion.ts +139 -0
  596. package/src/runtime/root/assistant-learning-loop.ts +45 -0
  597. package/src/runtime/root/browser-session-composition.ts +59 -0
  598. package/src/runtime/root/computer-composition.ts +191 -0
  599. package/src/runtime/root/computer-target-composition.ts +16 -0
  600. package/src/runtime/root/computer-target-persistence.ts +39 -0
  601. package/src/runtime/root/controller-round-composition.ts +107 -0
  602. package/src/runtime/root/controller-services.ts +2 -0
  603. package/src/runtime/root/entry.ts +4 -3
  604. package/src/runtime/root/gateway-adapter.ts +3 -3
  605. package/src/runtime/root/local-bridge.ts +5 -2
  606. package/src/runtime/root/mcp-transport.ts +5 -5
  607. package/src/runtime/root/package-connector-service.ts +108 -56
  608. package/src/runtime/root/package-runtime-release.ts +85 -18
  609. package/src/runtime/root/package-runtime-service.ts +60 -97
  610. package/src/runtime/root/release-execution-canary.ts +71 -0
  611. package/src/runtime/root/release-loader.ts +68 -0
  612. package/src/runtime/root/release-manifest.ts +106 -2
  613. package/src/runtime/root/release-materialize.ts +103 -4
  614. package/src/runtime/root/release-store.ts +31 -2
  615. package/src/runtime/root/runtime.ts +240 -25
  616. package/src/runtime/root/scheduled-controller-composition.ts +51 -0
  617. package/src/runtime/root/scheduler.ts +12 -4
  618. package/src/runtime/root/service-runner.ts +1 -1
  619. package/src/runtime/root/service.ts +41 -16
  620. package/src/runtime/root/status.ts +1 -0
  621. package/src/runtime/root/types.ts +24 -1
  622. package/src/runtime/shared/local-bridge-surface.ts +1 -1
  623. package/src/runtime/shared/process-environment.ts +19 -4
  624. package/src/runtime/shared/storage-capacity.ts +68 -0
  625. package/src/runtime/standalone-recovery/controller-home-migration.ts +1116 -0
  626. package/src/runtime/standalone-recovery/core.ts +984 -230
  627. package/src/runtime/standalone-recovery/entry.ts +182 -51
  628. package/src/runtime/standalone-recovery/independent-host-rescue.ts +172 -0
  629. package/src/runtime/standalone-recovery/installer.ts +212 -104
  630. package/src/runtime/standalone-recovery/mcp-server.ts +243 -0
  631. package/src/runtime/standalone-recovery/mutation-identity-contract.ts +21 -0
  632. package/src/runtime/standalone-recovery/operation-lock.ts +160 -0
  633. package/src/runtime/standalone-recovery/performance.ts +135 -0
  634. package/src/runtime/standalone-recovery/release.ts +5 -0
  635. package/src/runtime/watchdog/workflow-watchdog.ts +1 -1
  636. package/src/runtime/workflow/schedules/chatgpt-automation-migration.ts +1 -1
  637. package/src/runtime/workflow/schedules/engine.ts +191 -343
  638. package/src/runtime/workflow/schedules/pending-activation.ts +1 -1
  639. package/src/runtime/workflow/schedules/settlement.ts +2 -191
  640. package/src/runtime/workflow/schedules/store.ts +2 -607
  641. package/src/runtime/workflow/schedules/types.ts +2 -127
  642. package/src/runtime/workflow/schedules/work-continuation.ts +180 -15
  643. package/src/runtime/workflows/first-party/xiaohongshu.ts +122 -0
  644. package/src/runtime/workflows/runtime.ts +486 -0
  645. package/src/testing/test-governance.ts +90 -29
  646. package/assets/templates/helpers/archive-architecture-request.sh +0 -244
  647. package/docs/architecture/history/README.md +0 -7
  648. package/docs/architecture/history/chatgpt-handoff-facade.md +0 -397
  649. package/docs/architecture/history/global-hook-runtime.md +0 -166
  650. package/docs/architecture/history/ios-semantic-automation-provider-v2.md +0 -170
  651. package/docs/architecture/requests/archive/2026/20260528-154740-ai-hooks-ai-hooks-hook-input-sh.md +0 -59
  652. package/docs/architecture/requests/archive/2026/20260528-154816-assets-hooks-assets-hooks-hook-input-sh.md +0 -59
  653. package/docs/architecture/requests/archive/2026/20260528-161851-ai-harness-workflow-contract-json-ai-harness-workflow-contract-json.md +0 -59
  654. package/docs/architecture/requests/archive/2026/20260528-161853-scripts-check-task-workflow-sh-scripts-check-task-workflow-sh.md +0 -59
  655. package/docs/architecture/requests/archive/2026/20260528-161911-assets-workflow-contract-v1-json-assets-workflow-contract-v1-json.md +0 -59
  656. package/docs/architecture/requests/archive/2026/20260528-222416-ai-hooks-ai-hooks-hook-input-sh.md +0 -59
  657. package/docs/architecture/requests/archive/2026/20260528-222444-ai-hooks-ai-hooks-pre-edit-guard-sh.md +0 -59
  658. package/docs/architecture/requests/archive/2026/20260528-222457-ai-hooks-ai-hooks-pre-edit-guard-sh.md +0 -59
  659. package/docs/architecture/requests/archive/2026/20260528-222648-ai-hooks-ai-hooks-pre-edit-guard-sh.md +0 -59
  660. package/docs/architecture/requests/archive/2026/20260528-222705-ai-hooks-ai-hooks-worktree-guard-sh.md +0 -59
  661. package/docs/architecture/requests/archive/2026/20260528-222726-ai-hooks-ai-hooks-prompt-guard-sh.md +0 -59
  662. package/docs/architecture/requests/archive/2026/20260528-222727-ai-hooks-ai-hooks-prompt-guard-sh.md +0 -59
  663. package/docs/architecture/requests/archive/2026/20260528-224736-ai-hooks-ai-hooks-hook-input-sh.md +0 -59
  664. package/docs/architecture/requests/archive/2026/20260528-233259-ai-hooks-ai-hooks-prompt-guard-sh.md +0 -59
  665. package/docs/architecture/requests/archive/2026/20260528-233335-assets-hooks-assets-hooks-prompt-guard-sh.md +0 -59
  666. package/docs/architecture/requests/archive/2026/20260528-233456-ai-hooks-ai-hooks-prompt-guard-sh.md +0 -59
  667. package/docs/architecture/requests/archive/2026/20260528-233457-assets-hooks-assets-hooks-prompt-guard-sh.md +0 -59
  668. package/docs/architecture/requests/archive/2026/20260528-233637-ai-hooks-ai-hooks-prompt-guard-sh.md +0 -59
  669. package/docs/architecture/requests/archive/2026/20260528-233638-assets-hooks-assets-hooks-prompt-guard-sh.md +0 -59
  670. package/docs/architecture/requests/archive/2026/20260529-000322-root-package-json.md +0 -59
  671. package/docs/architecture/requests/archive/2026/20260529-004238-ai-hooks-ai-hooks-lib-workflow-state-sh.md +0 -59
  672. package/docs/architecture/requests/archive/2026/20260529-020654-ai-harness-policy-json-ai-harness-policy-json.md +0 -63
  673. package/docs/architecture/requests/archive/2026/20260529-094236-ai-hooks-ai-hooks-prompt-guard-sh.md +0 -60
  674. package/docs/architecture/requests/archive/2026/20260529-094323-assets-hooks-assets-hooks-prompt-guard-sh.md +0 -60
  675. package/docs/architecture/requests/archive/2026/20260529-094331-ai-hooks-ai-hooks-prompt-guard-sh.md +0 -60
  676. package/docs/architecture/requests/archive/2026/20260529-094339-assets-hooks-assets-hooks-prompt-guard-sh.md +0 -60
  677. package/docs/architecture/requests/archive/2026/20260529-094430-assets-hooks-assets-hooks-session-start-context-sh.md +0 -60
  678. package/docs/architecture/requests/archive/2026/20260529-094446-ai-hooks-ai-hooks-session-start-context-sh.md +0 -60
  679. package/docs/architecture/requests/archive/2026/20260613-002040-runtime-harness-hook-adapters.md +0 -68
  680. package/docs/architecture/requests/archive/2026/root.md +0 -68
  681. package/docs/architecture/requests/archive/2026/runtime-harness-hook-adapters.md +0 -76
  682. package/docs/architecture/requests/archive/2026/verification-evals-checks.md +0 -68
  683. package/docs/architecture/requests/archive/2026/workflow-engine-contract-assets.md +0 -69
  684. package/scripts/archive-architecture-request.sh +0 -4
  685. package/scripts/run-skill-evals.ts +0 -1022
@@ -0,0 +1,2 @@
1
+ /** @deprecated Kernel V2 compatibility shim. Canonical authority is packages/kernel/work/domain/implementation-review. */
2
+ export * from '../../../../packages/kernel/work/domain/implementation-review';
@@ -1,250 +1,2 @@
1
- import {
2
- isDirectEditWorkCompletionReceipt,
3
- isReadOnlyReviewCompletionReceipt,
4
- isRemoteEffectCompletionReceipt,
5
- isRepositoryCompletionReceipt,
6
- type DispatchState,
7
- type EvidenceRef,
8
- type EvidenceState,
9
- type SuggestedNextAction,
10
- type WorkContract,
11
- type WorkContractStatus,
12
- type WorkPhase,
13
- type WorkPhaseEvidence,
14
- type WorkPhaseEvidenceMap,
15
- } from './types';
16
-
17
- export function phaseIndex(phase: WorkPhase): number {
18
- return ['implementation', 'verification', 'delivery', 'cleanup'].indexOf(phase);
19
- }
20
-
21
- export function transitionPhaseEvidence(
22
- current: Pick<WorkContract, 'phaseEvidence' | 'evidenceRefs'>,
23
- targetPhase: WorkPhase,
24
- input: {
25
- status: WorkContractStatus;
26
- summary: string;
27
- evidenceRefs?: EvidenceRef[];
28
- recordedAt: string;
29
- source?: WorkPhaseEvidence['source'];
30
- },
31
- ): WorkPhaseEvidenceMap {
32
- const targetIndex = phaseIndex(targetPhase);
33
- const evidenceRefs = (input.evidenceRefs ?? current.evidenceRefs).slice(0, 20);
34
- const source = input.source ?? 'recorded';
35
- const phaseEvidence = { ...current.phaseEvidence };
36
- for (const phase of ['implementation', 'verification', 'delivery', 'cleanup'] as WorkPhase[]) {
37
- const index = phaseIndex(phase);
38
- if (index < targetIndex) {
39
- phaseEvidence[phase] = {
40
- state: ['satisfied', 'skipped'].includes(phaseEvidence[phase].state) ? phaseEvidence[phase].state : 'satisfied',
41
- source,
42
- summary: `Advanced to ${targetPhase}: ${input.summary}`.slice(0, 1_000),
43
- evidenceRefs,
44
- recordedAt: input.recordedAt,
45
- };
46
- } else if (index > targetIndex) {
47
- phaseEvidence[phase] = {
48
- state: 'pending',
49
- source,
50
- summary: `Waiting for Work phase ${phase}.`,
51
- evidenceRefs: [],
52
- recordedAt: input.recordedAt,
53
- };
54
- }
55
- }
56
- phaseEvidence[targetPhase] = {
57
- state: input.status === 'failed'
58
- ? 'failed'
59
- : input.status === 'cancelled'
60
- ? 'skipped'
61
- : input.status === 'blocked' || input.status === 'ready'
62
- ? 'blocked'
63
- : 'active',
64
- source,
65
- summary: input.summary.trim().slice(0, 1_000) || `Work entered ${targetPhase}.`,
66
- evidenceRefs,
67
- recordedAt: input.recordedAt,
68
- };
69
- return phaseEvidence;
70
- }
71
-
72
- export function validateWorkSemantics(contract: WorkContract): WorkContract {
73
- if (!contract.objective.trim()) throw new Error('WORK_OBJECTIVE_REQUIRED');
74
- if (contract.status === 'completed' && !contract.completionReceipt) {
75
- throw new Error('WORK_COMPLETION_RECEIPT_REQUIRED');
76
- }
77
- const currentPhaseIndex = phaseIndex(contract.phase);
78
- for (const phase of ['implementation', 'verification', 'delivery', 'cleanup'] as WorkPhase[]) {
79
- const checkpoint = contract.phaseEvidence?.[phase];
80
- if (!checkpoint) throw new Error(`WORK_PHASE_EVIDENCE_REQUIRED: ${phase}`);
81
- const index = phaseIndex(phase);
82
- if (index < currentPhaseIndex && !['satisfied', 'skipped'].includes(checkpoint.state)) {
83
- throw new Error(`WORK_PHASE_EVIDENCE_PREVIOUS_NOT_SATISFIED: ${phase}`);
84
- }
85
- if (index === currentPhaseIndex && checkpoint.state === 'pending') {
86
- throw new Error(`WORK_PHASE_EVIDENCE_REQUIRED: ${phase}`);
87
- }
88
- if (index > currentPhaseIndex && checkpoint.state !== 'pending') {
89
- throw new Error(`WORK_PHASE_EVIDENCE_FUTURE_NOT_PENDING: ${phase}`);
90
- }
91
- }
92
- if (contract.completionReceipt) {
93
- const receipt = contract.completionReceipt;
94
- if (receipt.workId !== contract.workId) throw new Error('WORK_COMPLETION_RECEIPT_IDENTITY_MISMATCH');
95
- if (isRepositoryCompletionReceipt(receipt)) {
96
- if (!receipt.targetBranch.trim() || !receipt.targetRevision.trim()) throw new Error('WORK_COMPLETION_RECEIPT_TARGET_REQUIRED');
97
- if (receipt.delivery.status !== 'integrated' || !receipt.delivery.reachable) throw new Error('WORK_COMPLETION_RECEIPT_DELIVERY_NOT_PROVEN');
98
- if (!['complete', 'maintenance_warning'].includes(receipt.cleanup.status) || receipt.cleanup.blockers.length > 0) throw new Error('WORK_COMPLETION_RECEIPT_CLEANUP_NOT_PROVEN');
99
- } else if (isDirectEditWorkCompletionReceipt(receipt)) {
100
- const directEditAuthorityCount = Number(Boolean(receipt.editSessionId?.trim())) + Number(Boolean(receipt.reconciliationId?.trim()));
101
- if (directEditAuthorityCount !== 1) throw new Error('WORK_COMPLETION_RECEIPT_DIRECT_EDIT_AUTHORITY_REQUIRED');
102
- if (!receipt.targetBranch.trim() || !receipt.targetRevision.trim()) throw new Error('WORK_COMPLETION_RECEIPT_TARGET_REQUIRED');
103
- if (receipt.delivery.status !== 'integrated' || !receipt.delivery.reachable) throw new Error('WORK_COMPLETION_RECEIPT_DELIVERY_NOT_PROVEN');
104
- if (!['complete', 'maintenance_warning'].includes(receipt.cleanup.status) || receipt.cleanup.blockers.length > 0) throw new Error('WORK_COMPLETION_RECEIPT_CLEANUP_NOT_PROVEN');
105
- if (!['repository_change', 'completed_no_change'].includes(contract.workKind)) throw new Error('WORK_COMPLETION_RECEIPT_DIRECT_EDIT_KIND_REQUIRED');
106
- const expectedOutcome = contract.workKind === 'completed_no_change' ? 'completed_no_change' : 'completed_changed';
107
- if (contract.completionOutcome !== expectedOutcome) throw new Error('WORK_COMPLETION_RECEIPT_DIRECT_EDIT_OUTCOME_REQUIRED');
108
- } else if (isReadOnlyReviewCompletionReceipt(receipt)) {
109
- if (contract.workKind !== 'read_only_review') throw new Error('WORK_COMPLETION_RECEIPT_READ_ONLY_REVIEW_KIND_REQUIRED');
110
- if (contract.completionOutcome !== 'completed_no_change') throw new Error('WORK_COMPLETION_RECEIPT_READ_ONLY_REVIEW_OUTCOME_REQUIRED');
111
- if (!receipt.baseRevision.trim() || receipt.baseRevision !== receipt.sourceRevision) throw new Error('WORK_COMPLETION_RECEIPT_READ_ONLY_REVIEW_SOURCE_REQUIRED');
112
- if (contract.baseRevision && receipt.baseRevision !== contract.baseRevision) throw new Error('WORK_COMPLETION_RECEIPT_READ_ONLY_REVIEW_BASE_MISMATCH');
113
- if (receipt.workspaceChangedPaths.length !== 0) throw new Error('WORK_COMPLETION_RECEIPT_READ_ONLY_REVIEW_WORKSPACE_CHANGED');
114
- const reviewEvidence = contract.readOnlyReviewEvidence;
115
- if (!reviewEvidence || reviewEvidence.sourceRevision !== receipt.sourceRevision) throw new Error('WORK_COMPLETION_RECEIPT_READ_ONLY_REVIEW_EVIDENCE_REQUIRED');
116
- if (reviewEvidence.findings.length !== 0 || receipt.findingCount !== 0 || receipt.inspectedPaths.length === 0) throw new Error('WORK_COMPLETION_RECEIPT_READ_ONLY_REVIEW_CLEAN_SCOPE_REQUIRED');
117
- const evidencePaths = [...new Set(reviewEvidence.inspectedPaths)].sort();
118
- const receiptPaths = [...new Set(receipt.inspectedPaths)].sort();
119
- if (evidencePaths.length !== receiptPaths.length || evidencePaths.some((path, index) => path !== receiptPaths[index])) {
120
- throw new Error('WORK_COMPLETION_RECEIPT_READ_ONLY_REVIEW_SCOPE_MISMATCH');
121
- }
122
- if (reviewEvidence.workspaceFingerprint && receipt.workspaceFingerprint && reviewEvidence.workspaceFingerprint !== receipt.workspaceFingerprint) {
123
- throw new Error('WORK_COMPLETION_RECEIPT_READ_ONLY_REVIEW_WORKSPACE_MISMATCH');
124
- }
125
- } else if (isRemoteEffectCompletionReceipt(receipt)) {
126
- if (contract.workKind !== 'remote_effect') throw new Error('WORK_COMPLETION_RECEIPT_REMOTE_EFFECT_KIND_REQUIRED');
127
- if (contract.completionOutcome !== 'completed_remote') throw new Error('WORK_COMPLETION_RECEIPT_REMOTE_EFFECT_OUTCOME_REQUIRED');
128
- const authority = receipt.authority ?? 'plugin_action';
129
- if (!receipt.actionId.trim() || !receipt.requestId.trim() || !receipt.semanticKey.trim() || !receipt.resultDigest.trim()) {
130
- throw new Error('WORK_COMPLETION_RECEIPT_REMOTE_EFFECT_IDENTITY_REQUIRED');
131
- }
132
- if (authority === 'plugin_action' && !receipt.pluginId?.trim()) {
133
- throw new Error('WORK_COMPLETION_RECEIPT_REMOTE_EFFECT_PLUGIN_IDENTITY_REQUIRED');
134
- }
135
- if (authority === 'repository_process' && !receipt.processId?.trim()) {
136
- throw new Error('WORK_COMPLETION_RECEIPT_REMOTE_EFFECT_PROCESS_IDENTITY_REQUIRED');
137
- }
138
- } else {
139
- if (contract.workKind !== 'local_effect') throw new Error('WORK_COMPLETION_RECEIPT_LOCAL_EFFECT_KIND_REQUIRED');
140
- if (contract.completionOutcome !== 'completed_local') throw new Error('WORK_COMPLETION_RECEIPT_LOCAL_EFFECT_OUTCOME_REQUIRED');
141
- if (!receipt.operation.trim() || !receipt.target.id.trim()) throw new Error('WORK_COMPLETION_RECEIPT_LOCAL_EFFECT_TARGET_REQUIRED');
142
- }
143
- if (contract.status !== 'completed') throw new Error('WORK_COMPLETION_RECEIPT_REQUIRES_COMPLETED_WORK');
144
- for (const phase of ['implementation', 'verification', 'delivery', 'cleanup'] as WorkPhase[]) {
145
- if (!['satisfied', 'skipped'].includes(contract.phaseEvidence[phase].state)) {
146
- throw new Error(`WORK_COMPLETION_PHASE_NOT_SATISFIED: ${phase}`);
147
- }
148
- }
149
- for (const phase of ['delivery', 'cleanup'] as WorkPhase[]) {
150
- if (contract.phaseEvidence[phase].receiptId !== receipt.receiptId) {
151
- throw new Error(`WORK_COMPLETION_PHASE_RECEIPT_MISMATCH: ${phase}`);
152
- }
153
- }
154
- }
155
- const outcome = contract.completionOutcome;
156
- if (!outcome) return contract;
157
- if (contract.status !== 'completed' || !contract.completionReceipt) {
158
- throw new Error(`WORK_SEMANTICS_INVALID: ${outcome} requires a completed Work receipt`);
159
- }
160
- if (contract.dispatchState !== 'terminal') {
161
- throw new Error(`WORK_SEMANTICS_INVALID: ${outcome} requires terminal dispatch`);
162
- }
163
- if (contract.evidenceState !== 'valid') {
164
- throw new Error(`WORK_SEMANTICS_INVALID: ${outcome} requires valid evidence`);
165
- }
166
- if (outcome === 'completed_changed' && contract.workKind !== 'repository_change') {
167
- throw new Error('WORK_SEMANTICS_INVALID: completed_changed requires repository_change WorkKind');
168
- }
169
- if (outcome === 'completed_no_change' && !['completed_no_change', 'read_only_review'].includes(contract.workKind)) {
170
- throw new Error('WORK_SEMANTICS_INVALID: completed_no_change requires completed_no_change or read_only_review WorkKind');
171
- }
172
- if (outcome === 'completed_no_change' && contract.workKind === 'read_only_review' && contract.completionReceipt?.source !== 'read_only_review') {
173
- throw new Error('WORK_SEMANTICS_INVALID: read_only_review completed_no_change requires a read_only_review completion receipt');
174
- }
175
- if (outcome === 'completed_local' && contract.workKind !== 'local_effect') {
176
- throw new Error('WORK_SEMANTICS_INVALID: completed_local requires local_effect WorkKind');
177
- }
178
- if (outcome === 'completed_local' && contract.completionReceipt?.source !== 'local_effect') {
179
- throw new Error('WORK_SEMANTICS_INVALID: completed_local requires a local_effect completion receipt');
180
- }
181
- if (outcome === 'completed_remote' && contract.workKind !== 'remote_effect') {
182
- throw new Error('WORK_SEMANTICS_INVALID: completed_remote requires remote_effect WorkKind');
183
- }
184
- if (outcome === 'completed_remote' && contract.completionReceipt?.source !== 'remote_effect') {
185
- throw new Error('WORK_SEMANTICS_INVALID: completed_remote requires a remote_effect completion receipt');
186
- }
187
- if (outcome === 'superseded' && contract.workKind !== 'superseded') {
188
- throw new Error('WORK_SEMANTICS_INVALID: superseded requires superseded WorkKind');
189
- }
190
- return contract;
191
- }
192
-
193
- const DISPATCH_TRANSITIONS: Readonly<Record<DispatchState, readonly DispatchState[]>> = {
194
- not_dispatched: ['not_dispatched', 'claimed', 'launching', 'running', 'blocked', 'terminal'],
195
- claimed: ['claimed', 'launching', 'running', 'blocked', 'terminal'],
196
- launching: ['launching', 'running', 'blocked', 'terminal'],
197
- running: ['running', 'blocked', 'terminal'],
198
- blocked: ['blocked', 'claimed', 'launching', 'running', 'terminal'],
199
- terminal: ['terminal'],
200
- };
201
-
202
- const EVIDENCE_TRANSITIONS: Readonly<Record<EvidenceState, readonly EvidenceState[]>> = {
203
- none: ['none', 'partial', 'valid', 'failed'],
204
- partial: ['partial', 'valid', 'stale', 'contradictory', 'failed'],
205
- valid: ['valid', 'stale', 'contradictory', 'failed'],
206
- stale: ['stale', 'partial', 'valid', 'contradictory', 'failed'],
207
- contradictory: ['contradictory', 'partial', 'valid', 'failed'],
208
- failed: ['failed', 'partial', 'valid', 'contradictory'],
209
- };
210
-
211
- export function validateWorkSemanticTransition(
212
- current: WorkContract,
213
- next: WorkContract,
214
- options: { allowRetainedCancelledResume?: boolean } = {},
215
- ): WorkContract {
216
- const retryingFailedWork = current.status === 'failed'
217
- && !current.completionOutcome
218
- && ['claimed', 'launching', 'running', 'blocked'].includes(next.dispatchState);
219
- const resumingRetainedCancelledWork = options.allowRetainedCancelledResume === true
220
- && current.status === 'cancelled'
221
- && current.dispatchState === 'terminal'
222
- && current.phase === 'cleanup'
223
- && current.phaseEvidence.cleanup.state === 'skipped'
224
- && !current.completionReceipt
225
- && !current.completionOutcome
226
- && next.status === 'running'
227
- && next.dispatchState === 'running'
228
- && next.phase === 'implementation';
229
- if (!retryingFailedWork && !resumingRetainedCancelledWork && !DISPATCH_TRANSITIONS[current.dispatchState].includes(next.dispatchState)) {
230
- throw new Error(`WORK_SEMANTICS_TRANSITION_INVALID: dispatch ${current.dispatchState} -> ${next.dispatchState}`);
231
- }
232
- if (!EVIDENCE_TRANSITIONS[current.evidenceState].includes(next.evidenceState)) {
233
- throw new Error(`WORK_SEMANTICS_TRANSITION_INVALID: evidence ${current.evidenceState} -> ${next.evidenceState}`);
234
- }
235
- if (current.completionOutcome && current.completionOutcome !== next.completionOutcome) {
236
- throw new Error(`WORK_SEMANTICS_TRANSITION_INVALID: completion outcome ${current.completionOutcome} is immutable`);
237
- }
238
- if ((current.lifecycleRole ?? 'primary') !== (next.lifecycleRole ?? 'primary')) {
239
- throw new Error('WORK_SEMANTICS_TRANSITION_INVALID: lifecycleRole is immutable');
240
- }
241
- if (current.parentWorkId !== next.parentWorkId) {
242
- throw new Error('WORK_SEMANTICS_TRANSITION_INVALID: parentWorkId is immutable');
243
- }
244
- return next;
245
- }
246
-
247
- export function suggestedActionsForStatus(status: WorkContractStatus, actions: readonly SuggestedNextAction[]): SuggestedNextAction[] {
248
- if (status === 'completed' || status === 'cancelled') return [];
249
- return actions.slice(0, 8);
250
- }
1
+ /** @deprecated Kernel V2 compatibility shim. Canonical authority is packages/kernel/work/domain/state-machine. */
2
+ export * from '../../../../packages/kernel/work/domain/state-machine';
@@ -8,10 +8,16 @@ import {
8
8
  } from 'fs';
9
9
  import { homedir } from 'os';
10
10
  import { basename, join, relative, resolve, sep } from 'path';
11
+ import { repositoryControllerRoot } from '../../cli/repositories/controller-home';
11
12
 
12
13
  const DEFAULT_GENERATED_CACHE_GRACE_MS = 6 * 60 * 60_000;
14
+ const DEFAULT_BROWSER_UPLOAD_GRACE_MS = 24 * 60 * 60_000;
15
+ const DEFAULT_BROWSER_SCREENSHOT_GRACE_MS = 7 * 24 * 60 * 60_000;
16
+ const DEFAULT_BROWSER_ARTIFACT_ACTIVE_GRACE_MS = 60 * 60_000;
13
17
  const DEFAULT_SCAN_BUDGET = 1_000;
14
18
  const DEFAULT_REMOVAL_BUDGET = 8;
19
+ const DEFAULT_BROWSER_ARTIFACT_SCAN_BUDGET = 1_000;
20
+ const DEFAULT_BROWSER_ARTIFACT_REMOVAL_BUDGET = 16;
15
21
 
16
22
  export interface GeneratedCacheRetentionOptions {
17
23
  nowMs?: number;
@@ -31,6 +37,41 @@ export interface GeneratedCacheRetentionReport {
31
37
  budgetExhausted: boolean;
32
38
  }
33
39
 
40
+ export type BrowserDisposableArtifactKind = 'screenshots' | 'downloads' | 'diagnostics';
41
+
42
+ export interface BrowserArtifactRetentionOptions {
43
+ nowMs?: number;
44
+ activeGraceMs?: number;
45
+ graceMs?: number;
46
+ maxEntries?: number;
47
+ maxRemovals?: number;
48
+ maxCountPerClass?: number;
49
+ maxBytesPerClass?: number;
50
+ }
51
+
52
+ export interface BrowserArtifactClassRetentionReport {
53
+ inspected: number;
54
+ eligible: number;
55
+ removedCount: number;
56
+ removedBytes: number;
57
+ retainedCount: number;
58
+ totalBytesBefore: number;
59
+ totalBytesAfter: number;
60
+ overCapacity: boolean;
61
+ blockers: string[];
62
+ }
63
+
64
+ export interface BrowserArtifactRetentionReport {
65
+ policyVersion: 'browser-disposable-artifact-retention-v1';
66
+ inspected: number;
67
+ removedPaths: string[];
68
+ removedBytes: number;
69
+ skippedByReason: Record<string, number>;
70
+ errors: string[];
71
+ budgetExhausted: boolean;
72
+ classes: Record<BrowserDisposableArtifactKind, BrowserArtifactClassRetentionReport>;
73
+ }
74
+
34
75
  export interface XCTestDeviceCleanupReport {
35
76
  attempted: boolean;
36
77
  removedDevices: number;
@@ -40,7 +81,13 @@ export interface XCTestDeviceCleanupReport {
40
81
 
41
82
  interface Candidate {
42
83
  path: string;
43
- kind: 'forge_ios_derived_data' | 'harness_derived_data' | 'repo_harness_derived_data' | 'tmp_derived_data';
84
+ kind:
85
+ | 'forge_ios_derived_data'
86
+ | 'harness_derived_data'
87
+ | 'repo_harness_derived_data'
88
+ | 'tmp_derived_data'
89
+ | 'forge_browser_upload'
90
+ | 'forge_browser_screenshot';
44
91
  }
45
92
 
46
93
  function increment(counts: Record<string, number>, reason: string): void {
@@ -71,9 +118,14 @@ function collectProcessCommands(): string[] {
71
118
  }
72
119
 
73
120
  function commandReferencesPath(commands: readonly string[], repoRoot: string, path: string): boolean {
74
- const absolute = canonical(path);
75
- const rel = relative(resolve(repoRoot), absolute).replace(/\\/g, '/');
76
- return commands.some((command) => command.includes(absolute) || (rel && command.includes(rel)));
121
+ const rawAbsolute = resolve(path);
122
+ const canonicalAbsolute = canonical(path);
123
+ const rawRelative = relative(resolve(repoRoot), rawAbsolute).replace(/\\/g, '/');
124
+ const canonicalRelative = relative(canonical(repoRoot), canonicalAbsolute).replace(/\\/g, '/');
125
+ return commands.some((command) => command.includes(rawAbsolute)
126
+ || command.includes(canonicalAbsolute)
127
+ || (rawRelative && command.includes(rawRelative))
128
+ || (canonicalRelative && command.includes(canonicalRelative)));
77
129
  }
78
130
 
79
131
  function containsTrackedFiles(repoRoot: string, path: string): boolean {
@@ -106,6 +158,19 @@ function directChildDirectories(root: string, predicate: (name: string) => boole
106
158
  return found;
107
159
  }
108
160
 
161
+ function directChildFiles(root: string, budget: { remaining: number }): string[] {
162
+ if (!existsSync(root) || budget.remaining <= 0) return [];
163
+ const found: string[] = [];
164
+ let entries;
165
+ try { entries = readdirSync(root, { withFileTypes: true }); } catch { return found; }
166
+ for (const entry of entries) {
167
+ if (budget.remaining <= 0) break;
168
+ budget.remaining -= 1;
169
+ if (entry.isFile()) found.push(join(root, entry.name));
170
+ }
171
+ return found;
172
+ }
173
+
109
174
  function nestedDerivedDataDirectories(root: string, maxDepth: number, budget: { remaining: number }): string[] {
110
175
  if (!existsSync(root) || budget.remaining <= 0) return [];
111
176
  const found: string[] = [];
@@ -135,6 +200,15 @@ function discoverCandidates(repoRoot: string, maxEntries: number): { candidates:
135
200
  const initial = budget.remaining;
136
201
  const candidates: Candidate[] = [];
137
202
 
203
+ // Browser artifacts are direct children of small, explicitly owned roots.
204
+ // Scan them before recursively walking potentially high-cardinality cache
205
+ // trees so cache history cannot starve their retention policy.
206
+ for (const path of directChildFiles(join(root, '.forge', 'browser', 'uploads'), budget)) {
207
+ candidates.push({ path, kind: 'forge_browser_upload' });
208
+ }
209
+ for (const path of directChildFiles(join(root, '.forge', 'browser', 'screenshots'), budget)) {
210
+ candidates.push({ path, kind: 'forge_browser_screenshot' });
211
+ }
138
212
  for (const path of directChildDirectories(join(root, '.forge', 'ios', 'DerivedData'), () => true, budget)) {
139
213
  candidates.push({ path, kind: 'forge_ios_derived_data' });
140
214
  }
@@ -147,7 +221,6 @@ function discoverCandidates(repoRoot: string, maxEntries: number): { candidates:
147
221
  for (const path of nestedDerivedDataDirectories(join(root, '.tmp'), 6, budget)) {
148
222
  candidates.push({ path, kind: 'tmp_derived_data' });
149
223
  }
150
-
151
224
  return {
152
225
  candidates: candidates.filter((candidate, index, values) => values.findIndex((item) => resolve(item.path) === resolve(candidate.path)) === index),
153
226
  inspected: initial - budget.remaining,
@@ -155,17 +228,36 @@ function discoverCandidates(repoRoot: string, maxEntries: number): { candidates:
155
228
  };
156
229
  }
157
230
 
231
+ function retentionGraceMs(candidate: Candidate, explicitGraceMs: number | undefined): number {
232
+ if (explicitGraceMs !== undefined) return Math.max(60_000, Math.floor(explicitGraceMs));
233
+ if (candidate.kind === 'forge_browser_upload') return DEFAULT_BROWSER_UPLOAD_GRACE_MS;
234
+ if (candidate.kind === 'forge_browser_screenshot') return DEFAULT_BROWSER_SCREENSHOT_GRACE_MS;
235
+ return DEFAULT_GENERATED_CACHE_GRACE_MS;
236
+ }
237
+
238
+ function candidateOwnedRoot(repoRoot: string, candidate: Candidate): string {
239
+ switch (candidate.kind) {
240
+ case 'forge_ios_derived_data': return join(repoRoot, '.forge', 'ios', 'DerivedData');
241
+ case 'harness_derived_data': return join(repoRoot, '.ai', 'harness');
242
+ case 'repo_harness_derived_data': return join(repoRoot, '.repo-harness');
243
+ case 'tmp_derived_data': return join(repoRoot, '.tmp');
244
+ case 'forge_browser_upload': return join(repoRoot, '.forge', 'browser', 'uploads');
245
+ case 'forge_browser_screenshot': return join(repoRoot, '.forge', 'browser', 'screenshots');
246
+ }
247
+ }
248
+
158
249
  /**
159
- * Reclaim only rebuildable Xcode DerivedData under Forge/repo-harness-owned
160
- * namespaces. Result bundles, logs, edit-session metadata, and all tracked files
161
- * are deliberately outside this cleanup surface.
250
+ * Reclaim only rebuildable DerivedData and bounded browser artifacts under
251
+ * Forge-owned namespaces. Browser uploads are temporary staging (24 hours);
252
+ * screenshots remain review evidence for seven days. Result bundles, logs,
253
+ * profiles, downloads, edit-session metadata, and all tracked files remain
254
+ * deliberately outside this cleanup surface.
162
255
  */
163
256
  export function cleanupGeneratedRepositoryCaches(
164
257
  repoRoot: string,
165
258
  options: GeneratedCacheRetentionOptions = {},
166
259
  ): GeneratedCacheRetentionReport {
167
260
  const nowMs = options.nowMs ?? Date.now();
168
- const graceMs = Math.max(60_000, Math.floor(options.graceMs ?? DEFAULT_GENERATED_CACHE_GRACE_MS));
169
261
  const maxEntries = Math.max(1, Math.floor(options.maxEntries ?? DEFAULT_SCAN_BUDGET));
170
262
  let remainingRemovals = Math.max(1, Math.floor(options.maxRemovals ?? DEFAULT_REMOVAL_BUDGET));
171
263
  const commands = options.processCommands ?? collectProcessCommands();
@@ -181,21 +273,16 @@ export function cleanupGeneratedRepositoryCaches(
181
273
  };
182
274
 
183
275
  for (const candidate of discovered.candidates) {
184
- const ownedRoot = candidate.kind === 'forge_ios_derived_data'
185
- ? join(repoRoot, '.forge', 'ios', 'DerivedData')
186
- : candidate.kind === 'harness_derived_data'
187
- ? join(repoRoot, '.ai', 'harness')
188
- : candidate.kind === 'repo_harness_derived_data'
189
- ? join(repoRoot, '.repo-harness')
190
- : join(repoRoot, '.tmp');
276
+ const ownedRoot = candidateOwnedRoot(repoRoot, candidate);
277
+ const fileCandidate = candidate.kind === 'forge_browser_upload' || candidate.kind === 'forge_browser_screenshot';
191
278
  try {
192
279
  const stat = lstatSync(candidate.path);
193
- if (!stat.isDirectory() || stat.isSymbolicLink() || !pathInside(ownedRoot, candidate.path)) {
280
+ if ((fileCandidate ? !stat.isFile() : !stat.isDirectory()) || stat.isSymbolicLink() || !pathInside(ownedRoot, candidate.path)) {
194
281
  increment(report.skippedByReason, 'ownership_unproven');
195
282
  report.retainedPaths.push(relative(repoRoot, candidate.path));
196
283
  continue;
197
284
  }
198
- if (nowMs - stat.mtimeMs < graceMs) {
285
+ if (nowMs - stat.mtimeMs < retentionGraceMs(candidate, options.graceMs)) {
199
286
  increment(report.skippedByReason, 'retention_grace');
200
287
  continue;
201
288
  }
@@ -226,6 +313,140 @@ export function cleanupGeneratedRepositoryCaches(
226
313
  return report;
227
314
  }
228
315
 
316
+ function emptyBrowserArtifactClassReport(): BrowserArtifactClassRetentionReport {
317
+ return {
318
+ inspected: 0,
319
+ eligible: 0,
320
+ removedCount: 0,
321
+ removedBytes: 0,
322
+ retainedCount: 0,
323
+ totalBytesBefore: 0,
324
+ totalBytesAfter: 0,
325
+ overCapacity: false,
326
+ blockers: [],
327
+ };
328
+ }
329
+
330
+ function browserArtifactPolicy(kind: BrowserDisposableArtifactKind): { graceMs: number; maxCount: number; maxBytes: number } {
331
+ switch (kind) {
332
+ case 'screenshots': return { graceMs: 7 * 24 * 60 * 60_000, maxCount: 500, maxBytes: 512 * 1024 * 1024 };
333
+ case 'downloads': return { graceMs: 7 * 24 * 60 * 60_000, maxCount: 200, maxBytes: 2 * 1024 * 1024 * 1024 };
334
+ case 'diagnostics': return { graceMs: 24 * 60 * 60_000, maxCount: 200, maxBytes: 256 * 1024 * 1024 };
335
+ }
336
+ }
337
+
338
+ /**
339
+ * Bound disposable Browser provider artifacts below the Controller Home repository
340
+ * namespace. Session/profile authority is deliberately excluded: this cleanup is
341
+ * only for screenshots, downloads and diagnostics that can disappear without
342
+ * changing provider-effect or ControllerRound semantics.
343
+ */
344
+ export function cleanupControllerHomeBrowserArtifacts(
345
+ controllerHome: string,
346
+ repoId: string,
347
+ options: BrowserArtifactRetentionOptions = {},
348
+ ): BrowserArtifactRetentionReport {
349
+ const nowMs = options.nowMs ?? Date.now();
350
+ const activeGraceMs = Math.max(60_000, Math.floor(options.activeGraceMs ?? DEFAULT_BROWSER_ARTIFACT_ACTIVE_GRACE_MS));
351
+ let remainingScan = Math.max(1, Math.floor(options.maxEntries ?? DEFAULT_BROWSER_ARTIFACT_SCAN_BUDGET));
352
+ let remainingRemovals = Math.max(0, Math.floor(options.maxRemovals ?? DEFAULT_BROWSER_ARTIFACT_REMOVAL_BUDGET));
353
+ const browserRoot = join(repositoryControllerRoot(controllerHome, repoId), 'browser');
354
+ const report: BrowserArtifactRetentionReport = {
355
+ policyVersion: 'browser-disposable-artifact-retention-v1',
356
+ inspected: 0,
357
+ removedPaths: [],
358
+ removedBytes: 0,
359
+ skippedByReason: {},
360
+ errors: [],
361
+ budgetExhausted: false,
362
+ classes: {
363
+ screenshots: emptyBrowserArtifactClassReport(),
364
+ downloads: emptyBrowserArtifactClassReport(),
365
+ diagnostics: emptyBrowserArtifactClassReport(),
366
+ },
367
+ };
368
+
369
+ for (const kind of ['screenshots', 'downloads', 'diagnostics'] as const) {
370
+ const classReport = report.classes[kind];
371
+ const root = join(browserRoot, kind);
372
+ const defaults = browserArtifactPolicy(kind);
373
+ const graceMs = Math.max(activeGraceMs, Math.floor(options.graceMs ?? defaults.graceMs));
374
+ const maxCount = Math.max(1, Math.floor(options.maxCountPerClass ?? defaults.maxCount));
375
+ const maxBytes = Math.max(1, Math.floor(options.maxBytesPerClass ?? defaults.maxBytes));
376
+ if (!existsSync(root) || remainingScan <= 0) continue;
377
+
378
+ let entries;
379
+ try { entries = readdirSync(root, { withFileTypes: true }); } catch (error) {
380
+ report.errors.push(`${kind}:scan: ${error instanceof Error ? error.message : String(error)}`);
381
+ continue;
382
+ }
383
+ const candidates: Array<{ path: string; mtimeMs: number; size: number; ageMs: number }> = [];
384
+ for (const entry of entries) {
385
+ if (remainingScan <= 0) {
386
+ report.budgetExhausted = true;
387
+ increment(report.skippedByReason, 'scan_budget_exhausted');
388
+ break;
389
+ }
390
+ remainingScan -= 1;
391
+ report.inspected += 1;
392
+ classReport.inspected += 1;
393
+ const path = join(root, String(entry.name));
394
+ try {
395
+ const stat = lstatSync(path);
396
+ if (!entry.isFile() || !stat.isFile() || stat.isSymbolicLink() || !pathInside(root, path)) {
397
+ increment(report.skippedByReason, 'ownership_unproven');
398
+ classReport.blockers.push(`ownership_unproven:${String(entry.name)}`);
399
+ continue;
400
+ }
401
+ const size = Math.max(0, stat.size);
402
+ candidates.push({ path, mtimeMs: stat.mtimeMs, size, ageMs: Math.max(0, nowMs - stat.mtimeMs) });
403
+ classReport.totalBytesBefore += size;
404
+ } catch (error) {
405
+ report.errors.push(`${kind}:${String(entry.name)}: ${error instanceof Error ? error.message : String(error)}`);
406
+ }
407
+ }
408
+
409
+ candidates.sort((left, right) => left.mtimeMs - right.mtimeMs || left.path.localeCompare(right.path));
410
+ let projectedCount = candidates.length;
411
+ let projectedBytes = classReport.totalBytesBefore;
412
+ for (const candidate of candidates) {
413
+ const ttlExpired = candidate.ageMs >= graceMs;
414
+ const countPressure = projectedCount > maxCount;
415
+ const bytePressure = projectedBytes > maxBytes;
416
+ if (!ttlExpired && !countPressure && !bytePressure) continue;
417
+ if (candidate.ageMs < activeGraceMs) {
418
+ increment(report.skippedByReason, 'active_grace');
419
+ classReport.blockers.push(`active_grace:${basename(candidate.path)}`);
420
+ continue;
421
+ }
422
+ classReport.eligible += 1;
423
+ if (remainingRemovals <= 0) {
424
+ report.budgetExhausted = true;
425
+ increment(report.skippedByReason, 'cleanup_budget_exhausted');
426
+ continue;
427
+ }
428
+ try {
429
+ rmSync(candidate.path, { force: true });
430
+ remainingRemovals -= 1;
431
+ projectedCount -= 1;
432
+ projectedBytes = Math.max(0, projectedBytes - candidate.size);
433
+ classReport.removedCount += 1;
434
+ classReport.removedBytes += candidate.size;
435
+ report.removedBytes += candidate.size;
436
+ report.removedPaths.push(relative(browserRoot, candidate.path).replace(/\\/g, '/'));
437
+ } catch (error) {
438
+ report.errors.push(`${kind}:${basename(candidate.path)}: ${error instanceof Error ? error.message : String(error)}`);
439
+ }
440
+ }
441
+ classReport.retainedCount = projectedCount;
442
+ classReport.totalBytesAfter = projectedBytes;
443
+ classReport.overCapacity = projectedCount > maxCount || projectedBytes > maxBytes;
444
+ if (classReport.overCapacity) classReport.blockers.push('capacity_remains_above_limit');
445
+ }
446
+
447
+ return report;
448
+ }
449
+
229
450
  /**
230
451
  * XCTest's private device set is separate from the user's normal CoreSimulator
231
452
  * devices. When Forge is idle, delete only that dedicated set through simctl so
@@ -3,9 +3,19 @@ import {
3
3
  markExecutionJobSchedulerObserved,
4
4
  } from '../../execution/jobs/store';
5
5
  import { tickSchedules } from '../../workflow/schedules/engine';
6
+ import type { ExecutionJob } from '../../execution/jobs/types';
6
7
 
7
8
  const SCHEDULE_TICK_INTERVAL_MS = 30_000;
8
9
 
10
+ export function schedulerDurableAdmissionRequiresPolicy(input: {
11
+ activeJobs: readonly ExecutionJob[];
12
+ nowMs: number;
13
+ lastScheduleTickAt: number;
14
+ }): boolean {
15
+ return input.activeJobs.length > 0
16
+ || input.nowMs - input.lastScheduleTickAt >= SCHEDULE_TICK_INTERVAL_MS;
17
+ }
18
+
9
19
  export interface SchedulerDurableAdmissionDependencies {
10
20
  listActiveJobs: typeof listActiveExecutionJobs;
11
21
  markSchedulerObserved: typeof markExecutionJobSchedulerObserved;
@@ -23,13 +33,14 @@ export async function runSchedulerDurableAdmission(input: {
23
33
  repositoryIds: readonly string[];
24
34
  nowMs: number;
25
35
  lastScheduleTickAt: number;
36
+ activeJobs?: readonly ExecutionJob[];
26
37
  }, dependencies: SchedulerDurableAdmissionDependencies = DEFAULT_DEPENDENCIES): Promise<{
27
38
  scheduleTicked: boolean;
28
39
  }> {
29
40
  // Observation closes the admission phase for durable Jobs and starts their
30
41
  // independent queue budget. Each Job owns its own atomic state transition,
31
42
  // so this intentionally remains outside the global dispatch reservation lock.
32
- for (const job of dependencies.listActiveJobs(input.controllerHome)) {
43
+ for (const job of input.activeJobs ?? dependencies.listActiveJobs(input.controllerHome)) {
33
44
  if (job.status === 'running' || job.timings?.schedulerObservedAt) continue;
34
45
  try {
35
46
  dependencies.markSchedulerObserved(input.controllerHome, job.repoId, job.jobId);