vgxness 1.20.4 → 1.20.6

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 (375) hide show
  1. package/dist/adapters/claude/agent-renderer.js +82 -0
  2. package/dist/{mcp → adapters/claude/install}/claude-code-agent-config.js +64 -9
  3. package/dist/{mcp → adapters/claude/install}/claude-code-config.js +28 -6
  4. package/dist/{mcp → adapters/claude/install}/claude-code-project-memory.js +35 -5
  5. package/dist/{mcp → adapters/claude/install}/claude-code-scope.js +12 -3
  6. package/dist/{mcp → adapters/claude/install}/claude-code-user-config.js +26 -5
  7. package/dist/{mcp → adapters/claude/install}/claude-code-user-memory.js +47 -7
  8. package/dist/{mcp → adapters/claude/install}/client-install-claude-code-contract.js +45 -8
  9. package/dist/{mcp → adapters/claude/install}/client-install-claude-code.js +98 -14
  10. package/dist/adapters/json/agent-renderer.js +104 -0
  11. package/dist/adapters/opencode/agent-renderer.js +113 -0
  12. package/dist/{mcp → adapters/opencode/install}/client-install-opencode-contract.js +2 -2
  13. package/dist/{mcp → adapters/opencode/install}/client-install-opencode.js +1 -1
  14. package/dist/{mcp → adapters/opencode/install}/opencode-default-agent-config.js +2 -2
  15. package/dist/{mcp → adapters/opencode/install}/opencode-handoff-preview.js +60 -7
  16. package/dist/{mcp → adapters/opencode/install}/opencode-visibility.js +1 -1
  17. package/dist/adapters/provider-renderer.js +6 -0
  18. package/dist/agents/agent-activation-service.js +1 -263
  19. package/dist/agents/agent-lookup-contexts.js +1 -28
  20. package/dist/agents/agent-registry-service.js +1 -81
  21. package/dist/agents/agent-resolver.js +1 -287
  22. package/dist/agents/agent-seed-service.js +1 -157
  23. package/dist/agents/agent-seed-upgrade-service.js +1 -231
  24. package/dist/agents/agent-selector-resolver.js +1 -28
  25. package/dist/agents/boot-upgrade.js +1 -59
  26. package/dist/agents/canonical-agent-manifest.js +1 -245
  27. package/dist/agents/canonical-agent-projection.js +1 -236
  28. package/dist/agents/manager-profile-overlay-service.js +1 -60
  29. package/dist/agents/profile-model-routing.js +1 -30
  30. package/dist/agents/renderers/claude-renderer.js +1 -82
  31. package/dist/agents/renderers/index.js +1 -14
  32. package/dist/agents/renderers/json-renderer.js +1 -104
  33. package/dist/agents/renderers/opencode-renderer.js +1 -113
  34. package/dist/agents/renderers/provider-adapter.js +1 -6
  35. package/dist/agents/repositories/agent-seed-history.js +1 -128
  36. package/dist/agents/repositories/agents.js +1 -200
  37. package/dist/agents/repositories/manager-profile-overlays.js +1 -90
  38. package/dist/agents/schema.js +1 -1
  39. package/dist/application/agents/agent-activation-service.js +261 -0
  40. package/dist/application/agents/agent-lookup-contexts.js +28 -0
  41. package/dist/application/agents/agent-registry-service.js +81 -0
  42. package/dist/application/agents/agent-resolver.js +287 -0
  43. package/dist/application/agents/agent-seed-service.js +157 -0
  44. package/dist/application/agents/agent-seed-upgrade-service.js +231 -0
  45. package/dist/application/agents/agent-selector-resolver.js +28 -0
  46. package/dist/application/agents/boot-upgrade.js +59 -0
  47. package/dist/application/agents/canonical-agent-projection.js +236 -0
  48. package/dist/application/agents/manager-profile-overlay-service.js +68 -0
  49. package/dist/application/agents/profile-model-routing.js +30 -0
  50. package/dist/application/agents/renderers/claude-renderer.js +1 -0
  51. package/dist/application/agents/renderers/index.js +14 -0
  52. package/dist/application/agents/renderers/json-renderer.js +1 -0
  53. package/dist/application/agents/renderers/opencode-renderer.js +1 -0
  54. package/dist/application/agents/renderers/provider-adapter.js +1 -0
  55. package/dist/application/memory/active-work-preview.js +75 -0
  56. package/dist/application/memory/agent-memory-capture-service.js +498 -0
  57. package/dist/application/memory/import/dry-run-planner.js +58 -0
  58. package/dist/application/memory/import/index.js +3 -0
  59. package/dist/application/memory/import/observation-writer.js +226 -0
  60. package/dist/application/memory/import/package.js +179 -0
  61. package/dist/application/memory/memory-service.js +202 -0
  62. package/dist/application/memory/search.js +11 -0
  63. package/dist/{mcp → application/provider-setup}/provider-change-plan.js +74 -13
  64. package/dist/{mcp → application/provider-setup}/provider-doctor.js +201 -31
  65. package/dist/{mcp → application/provider-setup}/provider-health-types.js +1 -1
  66. package/dist/{mcp → application/provider-setup}/provider-status.js +170 -33
  67. package/dist/application/runs/execution-planning.js +180 -0
  68. package/dist/application/runs/operation-execution.js +1 -0
  69. package/dist/application/runs/operation-retry.js +129 -0
  70. package/dist/application/runs/resume-after-approval-result.js +88 -0
  71. package/dist/application/runs/run-insights.js +270 -0
  72. package/dist/application/runs/run-service.js +1480 -0
  73. package/dist/application/runs/run-snapshot-export-service.js +31 -0
  74. package/dist/application/runs/sandbox-process-execution.js +244 -0
  75. package/dist/application/runs/sandbox-worktree-planning.js +59 -0
  76. package/dist/application/runs/task-scoped-command-grant-service.js +224 -0
  77. package/dist/application/sdd/artifact-portability-service.js +137 -0
  78. package/dist/application/sdd/cockpit-read-model.js +195 -0
  79. package/dist/application/sdd/sdd-continuation-plan.js +265 -0
  80. package/dist/application/sdd/sdd-workflow-service.js +892 -0
  81. package/dist/application/skills/boot-seed.js +42 -0
  82. package/dist/application/skills/personal-skills.js +41 -0
  83. package/dist/application/skills/skill-export-service.js +34 -0
  84. package/dist/application/skills/skill-index-service.js +126 -0
  85. package/dist/application/skills/skill-payload.js +186 -0
  86. package/dist/application/skills/skill-registry-service.js +648 -0
  87. package/dist/application/skills/skill-resolver.js +368 -0
  88. package/dist/application/skills/skill-seed-service.js +242 -0
  89. package/dist/application/skills/skill-status-service.js +147 -0
  90. package/dist/cli/bun-bin.js +0 -0
  91. package/dist/cli/cli-flags.js +1 -387
  92. package/dist/cli/cli-help.js +1 -173
  93. package/dist/cli/cli-helpers.js +1 -77
  94. package/dist/cli/cli-types.js +1 -1
  95. package/dist/cli/commands/agent-skill-dispatcher.js +1 -700
  96. package/dist/cli/commands/index.js +1 -9
  97. package/dist/cli/commands/interactive-entrypoint-dispatcher.js +1 -14
  98. package/dist/cli/commands/mcp-dispatcher.js +1 -232
  99. package/dist/cli/commands/memory-sdd-dispatcher.js +1 -367
  100. package/dist/cli/commands/run-permission-dispatcher.js +1 -455
  101. package/dist/cli/commands/setup-dispatcher.js +1 -496
  102. package/dist/cli/commands/status-dispatcher.js +1 -130
  103. package/dist/cli/commands/verification-dispatcher.js +1 -47
  104. package/dist/cli/commands/workflow-dispatcher.js +1 -566
  105. package/dist/cli/dispatcher.js +1 -247
  106. package/dist/cli/doctor-renderer.js +1 -26
  107. package/dist/cli/home-tui-app.js +1 -411
  108. package/dist/cli/home-tui-controller.js +1 -314
  109. package/dist/cli/mcp-start-path.js +1 -21
  110. package/dist/cli/product-resume-renderer.js +1 -32
  111. package/dist/cli/product-status-renderer.js +1 -81
  112. package/dist/cli/sdd-renderer.js +1 -247
  113. package/dist/cli/setup-plan-renderer.js +1 -79
  114. package/dist/cli/setup-status-renderer.js +1 -50
  115. package/dist/cli/setup-tui-app.js +1 -130
  116. package/dist/cli/setup-tui-controller.js +1 -89
  117. package/dist/cli/tui/focus-reducer.js +1 -0
  118. package/dist/cli/tui/focus-types.js +1 -0
  119. package/dist/cli/tui/ink/app-shell.js +1 -0
  120. package/dist/cli/tui/ink/components.js +1 -38
  121. package/dist/cli/tui/ink/help-overlay.js +1 -0
  122. package/dist/cli/tui/ink/state-components.js +1 -0
  123. package/dist/cli/tui/ink/theme.js +1 -36
  124. package/dist/cli/tui/key-intents.js +1 -0
  125. package/dist/cli/tui/keymap.js +1 -20
  126. package/dist/cli/tui/navigation.js +1 -10
  127. package/dist/cli/tui/screen-registry.js +1 -0
  128. package/dist/cli/tui/terminal-capabilities.js +1 -12
  129. package/dist/cli/tui/tui-types.js +1 -1
  130. package/dist/cli/tui/visual/badges.js +1 -19
  131. package/dist/cli/tui/visual/footer.js +1 -27
  132. package/dist/cli/tui/visual/index.js +1 -3
  133. package/dist/cli/tui/visual/viewport.js +1 -11
  134. package/dist/cli/tui-render-helpers.js +1 -200
  135. package/dist/cli/verification-plan-renderer.js +1 -25
  136. package/dist/cli/verification-report-renderer.js +1 -19
  137. package/dist/domain/agents/canonical-agent-manifest.js +355 -0
  138. package/dist/domain/agents/schema.js +1 -0
  139. package/dist/domain/memory/active-work-topics.js +64 -0
  140. package/dist/domain/memory/memory-capture-schema.js +1 -0
  141. package/dist/domain/memory/schema.js +1 -0
  142. package/dist/domain/runs/schema.js +5 -0
  143. package/dist/domain/sdd/cockpit-types.js +1 -0
  144. package/dist/domain/sdd/schema.js +111 -0
  145. package/dist/domain/skills/schema.js +1 -0
  146. package/dist/governance/risk-classifier.js +2 -0
  147. package/dist/interfaces/cli/bun-bin.js +46 -0
  148. package/dist/interfaces/cli/cli-flags.js +391 -0
  149. package/dist/interfaces/cli/cli-help.js +173 -0
  150. package/dist/interfaces/cli/cli-helpers.js +77 -0
  151. package/dist/interfaces/cli/cli-types.js +1 -0
  152. package/dist/interfaces/cli/commands/agent-skill-dispatcher.js +700 -0
  153. package/dist/interfaces/cli/commands/index.js +9 -0
  154. package/dist/interfaces/cli/commands/interactive-entrypoint-dispatcher.js +14 -0
  155. package/dist/interfaces/cli/commands/mcp-dispatcher.js +252 -0
  156. package/dist/interfaces/cli/commands/memory-sdd-dispatcher.js +367 -0
  157. package/dist/interfaces/cli/commands/run-permission-dispatcher.js +460 -0
  158. package/dist/interfaces/cli/commands/setup-dispatcher.js +496 -0
  159. package/dist/interfaces/cli/commands/status-dispatcher.js +130 -0
  160. package/dist/interfaces/cli/commands/verification-dispatcher.js +47 -0
  161. package/dist/interfaces/cli/commands/workflow-dispatcher.js +566 -0
  162. package/dist/interfaces/cli/dispatcher.js +247 -0
  163. package/dist/interfaces/cli/doctor-renderer.js +26 -0
  164. package/dist/interfaces/cli/home-tui-app.js +462 -0
  165. package/dist/interfaces/cli/home-tui-controller.js +341 -0
  166. package/dist/interfaces/cli/index.js +27 -0
  167. package/dist/interfaces/cli/mcp-start-path.js +21 -0
  168. package/dist/interfaces/cli/product-resume-renderer.js +32 -0
  169. package/dist/interfaces/cli/product-status-renderer.js +81 -0
  170. package/dist/interfaces/cli/sdd-renderer.js +247 -0
  171. package/dist/interfaces/cli/setup-plan-renderer.js +79 -0
  172. package/dist/interfaces/cli/setup-status-renderer.js +50 -0
  173. package/dist/interfaces/cli/setup-tui-app.js +135 -0
  174. package/dist/interfaces/cli/setup-tui-controller.js +89 -0
  175. package/dist/interfaces/cli/tui/focus-reducer.js +60 -0
  176. package/dist/interfaces/cli/tui/focus-types.js +10 -0
  177. package/dist/interfaces/cli/tui/ink/app-shell.js +16 -0
  178. package/dist/interfaces/cli/tui/ink/components.js +38 -0
  179. package/dist/interfaces/cli/tui/ink/help-overlay.js +6 -0
  180. package/dist/interfaces/cli/tui/ink/state-components.js +22 -0
  181. package/dist/interfaces/cli/tui/ink/theme.js +36 -0
  182. package/dist/interfaces/cli/tui/key-intents.js +33 -0
  183. package/dist/interfaces/cli/tui/keymap.js +20 -0
  184. package/dist/interfaces/cli/tui/navigation.js +10 -0
  185. package/dist/interfaces/cli/tui/screen-registry.js +43 -0
  186. package/dist/interfaces/cli/tui/terminal-capabilities.js +12 -0
  187. package/dist/interfaces/cli/tui/tui-types.js +1 -0
  188. package/dist/interfaces/cli/tui/visual/badges.js +19 -0
  189. package/dist/interfaces/cli/tui/visual/footer.js +27 -0
  190. package/dist/interfaces/cli/tui/visual/index.js +3 -0
  191. package/dist/interfaces/cli/tui/visual/viewport.js +11 -0
  192. package/dist/interfaces/cli/tui-render-helpers.js +200 -0
  193. package/dist/interfaces/cli/verification-plan-renderer.js +25 -0
  194. package/dist/interfaces/cli/verification-report-renderer.js +19 -0
  195. package/dist/interfaces/mcp/contracts/agents.js +1 -0
  196. package/dist/interfaces/mcp/contracts/context.js +1 -0
  197. package/dist/interfaces/mcp/contracts/governance.js +1 -0
  198. package/dist/interfaces/mcp/contracts/index.js +1 -0
  199. package/dist/interfaces/mcp/contracts/memory.js +1 -0
  200. package/dist/interfaces/mcp/contracts/providers.js +1 -0
  201. package/dist/interfaces/mcp/contracts/runs.js +1 -0
  202. package/dist/interfaces/mcp/contracts/sdd.js +1 -0
  203. package/dist/interfaces/mcp/contracts/sessions.js +1 -0
  204. package/dist/interfaces/mcp/contracts/skills.js +1 -0
  205. package/dist/interfaces/mcp/contracts/verification.js +1 -0
  206. package/dist/interfaces/mcp/control-plane/handlers/agents.js +38 -0
  207. package/dist/interfaces/mcp/control-plane/handlers/context.js +12 -0
  208. package/dist/interfaces/mcp/control-plane/handlers/memory.js +95 -0
  209. package/dist/interfaces/mcp/control-plane/handlers/providers.js +19 -0
  210. package/dist/interfaces/mcp/control-plane/handlers/runs.js +134 -0
  211. package/dist/interfaces/mcp/control-plane/handlers/sdd.js +225 -0
  212. package/dist/interfaces/mcp/control-plane/handlers/sessions.js +39 -0
  213. package/dist/interfaces/mcp/control-plane/handlers/skills.js +82 -0
  214. package/dist/interfaces/mcp/control-plane/handlers/verification.js +11 -0
  215. package/dist/interfaces/mcp/control-plane/types.js +1 -0
  216. package/dist/interfaces/mcp/control-plane.js +235 -0
  217. package/dist/interfaces/mcp/schema.js +174 -0
  218. package/dist/interfaces/mcp/schemas/common.js +121 -0
  219. package/dist/interfaces/mcp/schemas/inputs/agents.js +69 -0
  220. package/dist/interfaces/mcp/schemas/inputs/context.js +32 -0
  221. package/dist/interfaces/mcp/schemas/inputs/governance.js +23 -0
  222. package/dist/interfaces/mcp/schemas/inputs/index.js +10 -0
  223. package/dist/interfaces/mcp/schemas/inputs/memory.js +50 -0
  224. package/dist/interfaces/mcp/schemas/inputs/providers.js +35 -0
  225. package/dist/interfaces/mcp/schemas/inputs/runs.js +146 -0
  226. package/dist/interfaces/mcp/schemas/inputs/sdd.js +102 -0
  227. package/dist/interfaces/mcp/schemas/inputs/sessions.js +32 -0
  228. package/dist/interfaces/mcp/schemas/inputs/skills.js +231 -0
  229. package/dist/interfaces/mcp/schemas/inputs/verification.js +9 -0
  230. package/dist/interfaces/mcp/schemas/outputs/index.js +2 -0
  231. package/dist/interfaces/mcp/schemas/outputs/providers.js +28 -0
  232. package/dist/interfaces/mcp/schemas/outputs/sdd.js +166 -0
  233. package/dist/interfaces/mcp/stdio-server.js +116 -0
  234. package/dist/interfaces/mcp/validation/agents.js +189 -0
  235. package/dist/interfaces/mcp/validation/common.js +415 -0
  236. package/dist/interfaces/mcp/validation/governance.js +50 -0
  237. package/dist/interfaces/mcp/validation/memory.js +133 -0
  238. package/dist/interfaces/mcp/validation/providers.js +94 -0
  239. package/dist/interfaces/mcp/validation/runs.js +514 -0
  240. package/dist/interfaces/mcp/validation/sdd.js +247 -0
  241. package/dist/interfaces/mcp/validation/sessions.js +51 -0
  242. package/dist/interfaces/mcp/validation/skills.js +685 -0
  243. package/dist/interfaces/mcp/validation/verification.js +24 -0
  244. package/dist/interfaces/mcp/validation.js +149 -0
  245. package/dist/mcp/control-plane-snapshot-service.js +65 -2
  246. package/dist/mcp/control-plane.js +1 -646
  247. package/dist/mcp/doctor.js +1 -1
  248. package/dist/mcp/index.js +17 -17
  249. package/dist/mcp/schema.js +1 -1072
  250. package/dist/mcp/stdio-server.js +1 -116
  251. package/dist/mcp/validation.js +1 -2239
  252. package/dist/memory/active-work-preview.js +1 -75
  253. package/dist/memory/active-work-topics.js +1 -64
  254. package/dist/memory/agent-memory-capture-service.js +1 -497
  255. package/dist/memory/import/dry-run-planner.js +1 -58
  256. package/dist/memory/import/index.js +1 -3
  257. package/dist/memory/import/observation-writer.js +1 -226
  258. package/dist/memory/import/package.js +1 -179
  259. package/dist/memory/memory-capture-schema.js +1 -1
  260. package/dist/memory/memory-service.js +1 -201
  261. package/dist/memory/repositories/artifacts.js +1 -67
  262. package/dist/memory/repositories/observations.js +1 -217
  263. package/dist/memory/repositories/sessions.js +1 -125
  264. package/dist/memory/repositories/traces.js +1 -78
  265. package/dist/memory/schema.js +1 -1
  266. package/dist/memory/search.js +1 -11
  267. package/dist/memory/sqlite/database.js +1 -228
  268. package/dist/memory/storage-paths.js +1 -72
  269. package/dist/payload/context-budget-policy.js +10 -0
  270. package/dist/payload/context-budget-service.js +26 -0
  271. package/dist/payload/payload-diagnostics.js +50 -0
  272. package/dist/permissions/explicit-request-authorization.js +126 -0
  273. package/dist/permissions/policy-evaluator.js +54 -14
  274. package/dist/runs/execution-planning.js +1 -178
  275. package/dist/runs/operation-execution.js +1 -1
  276. package/dist/runs/operation-retry.js +1 -129
  277. package/dist/runs/repositories/runs.js +1 -676
  278. package/dist/runs/repositories/task-scoped-command-grants.js +1 -462
  279. package/dist/runs/resume-after-approval-result.js +1 -84
  280. package/dist/runs/run-insights.js +1 -270
  281. package/dist/runs/run-service.js +1 -1439
  282. package/dist/runs/run-snapshot-export-service.js +1 -31
  283. package/dist/runs/sandbox-process-execution.js +1 -240
  284. package/dist/runs/sandbox-worktree-planning.js +1 -59
  285. package/dist/runs/schema.js +1 -5
  286. package/dist/runs/task-scoped-command-grant-service.js +1 -216
  287. package/dist/sdd/artifact-portability-service.js +1 -137
  288. package/dist/sdd/cockpit-read-model.js +1 -195
  289. package/dist/sdd/cockpit-types.js +1 -1
  290. package/dist/sdd/schema.js +1 -111
  291. package/dist/sdd/sdd-continuation-plan.js +1 -265
  292. package/dist/sdd/sdd-workflow-service.js +1 -822
  293. package/dist/setup/providers/claude-setup-adapter.js +11 -4
  294. package/dist/setup/providers/opencode-setup-adapter.js +10 -7
  295. package/dist/setup/setup-plan.js +20 -7
  296. package/dist/skills/boot-seed.js +1 -42
  297. package/dist/skills/personal-skills.js +1 -41
  298. package/dist/skills/repositories/skill-evaluation-requests.js +1 -190
  299. package/dist/skills/repositories/skill-evaluation-scenarios.js +1 -305
  300. package/dist/skills/repositories/skill-improvement-proposals.js +1 -355
  301. package/dist/skills/repositories/skills.js +1 -1077
  302. package/dist/skills/schema.js +1 -1
  303. package/dist/skills/skill-export-service.js +1 -34
  304. package/dist/skills/skill-index-service.js +1 -126
  305. package/dist/skills/skill-payload.js +1 -186
  306. package/dist/skills/skill-registry-service.js +1 -644
  307. package/dist/skills/skill-resolver.js +1 -368
  308. package/dist/skills/skill-seed-service.js +1 -242
  309. package/dist/skills/skill-status-service.js +1 -147
  310. package/dist/storage/agents/repositories/agent-seed-history.js +128 -0
  311. package/dist/storage/agents/repositories/agents.js +200 -0
  312. package/dist/storage/agents/repositories/manager-profile-overlays.js +90 -0
  313. package/dist/storage/memory/repositories/artifacts.js +67 -0
  314. package/dist/storage/memory/repositories/observations.js +217 -0
  315. package/dist/storage/memory/repositories/sessions.js +125 -0
  316. package/dist/storage/memory/repositories/traces.js +78 -0
  317. package/dist/storage/memory/sqlite/database.js +228 -0
  318. package/dist/storage/memory/storage-paths.js +72 -0
  319. package/dist/storage/runs/repositories/runs.js +676 -0
  320. package/dist/storage/runs/repositories/task-scoped-command-grants.js +464 -0
  321. package/dist/storage/skills/repositories/skill-evaluation-requests.js +190 -0
  322. package/dist/storage/skills/repositories/skill-evaluation-scenarios.js +305 -0
  323. package/dist/storage/skills/repositories/skill-improvement-proposals.js +355 -0
  324. package/dist/storage/skills/repositories/skills.js +1084 -0
  325. package/docs/architecture.md +2 -2
  326. package/docs/glossary.md +1 -1
  327. package/docs/mcp.md +1 -1
  328. package/docs/module-boundaries.md +114 -0
  329. package/docs/prd.md +1 -1
  330. package/docs/project-health-audit-v1.10.x.md +1 -1
  331. package/docs/providers.md +2 -2
  332. package/docs/safety.md +3 -3
  333. package/docs/sdd/archive/2026-06-26-ambitious-structure-reorganization/apply-progress.md +122 -0
  334. package/docs/sdd/archive/2026-06-26-ambitious-structure-reorganization/archive-report.md +61 -0
  335. package/docs/sdd/archive/2026-06-26-ambitious-structure-reorganization/design.md +66 -0
  336. package/docs/sdd/archive/2026-06-26-ambitious-structure-reorganization/proposal.md +79 -0
  337. package/docs/sdd/archive/2026-06-26-ambitious-structure-reorganization/spec.md +67 -0
  338. package/docs/sdd/archive/2026-06-26-ambitious-structure-reorganization/tasks.md +63 -0
  339. package/docs/sdd/archive/2026-06-26-ambitious-structure-reorganization/verify-report.md +71 -0
  340. package/docs/sdd/archive/2026-06-26-legacy-facade-cleanup/apply-progress.md +68 -0
  341. package/docs/sdd/archive/2026-06-26-legacy-facade-cleanup/archive-report.md +61 -0
  342. package/docs/sdd/archive/2026-06-26-legacy-facade-cleanup/design.md +43 -0
  343. package/docs/sdd/archive/2026-06-26-legacy-facade-cleanup/proposal.md +61 -0
  344. package/docs/sdd/archive/2026-06-26-legacy-facade-cleanup/spec.md +31 -0
  345. package/docs/sdd/archive/2026-06-26-legacy-facade-cleanup/tasks.md +27 -0
  346. package/docs/sdd/archive/2026-06-26-legacy-facade-cleanup/verify-report.md +58 -0
  347. package/docs/sdd/archive/2026-06-26-provider-install-adapter-boundary/apply-progress.md +65 -0
  348. package/docs/sdd/archive/2026-06-26-provider-install-adapter-boundary/archive-report.md +53 -0
  349. package/docs/sdd/archive/2026-06-26-provider-install-adapter-boundary/design.md +64 -0
  350. package/docs/sdd/archive/2026-06-26-provider-install-adapter-boundary/proposal.md +62 -0
  351. package/docs/sdd/archive/2026-06-26-provider-install-adapter-boundary/spec.md +51 -0
  352. package/docs/sdd/archive/2026-06-26-provider-install-adapter-boundary/tasks.md +50 -0
  353. package/docs/sdd/archive/2026-06-26-provider-install-adapter-boundary/verify-report.md +66 -0
  354. package/docs/storage.md +2 -2
  355. package/package.json +2 -2
  356. /package/dist/{mcp → adapters/claude/install}/claude-code-cli.js +0 -0
  357. /package/dist/{memory → storage/memory}/sqlite/migrations/001_initial.sql +0 -0
  358. /package/dist/{memory → storage/memory}/sqlite/migrations/002_observation_revisions.sql +0 -0
  359. /package/dist/{memory → storage/memory}/sqlite/migrations/003_agent_registry.sql +0 -0
  360. /package/dist/{memory → storage/memory}/sqlite/migrations/004_run_runtime.sql +0 -0
  361. /package/dist/{memory → storage/memory}/sqlite/migrations/005_run_approvals.sql +0 -0
  362. /package/dist/{memory → storage/memory}/sqlite/migrations/006_run_operation_attempts.sql +0 -0
  363. /package/dist/{memory → storage/memory}/sqlite/migrations/007_abandoned_operation_attempts.sql +0 -0
  364. /package/dist/{memory → storage/memory}/sqlite/migrations/008_run_execution_plan_events.sql +0 -0
  365. /package/dist/{memory → storage/memory}/sqlite/migrations/009_multiple_operation_attempts.sql +0 -0
  366. /package/dist/{memory → storage/memory}/sqlite/migrations/010_skill_registry.sql +0 -0
  367. /package/dist/{memory → storage/memory}/sqlite/migrations/011_skill_usage_resolution_outcomes.sql +0 -0
  368. /package/dist/{memory → storage/memory}/sqlite/migrations/012_skill_improvement_proposals.sql +0 -0
  369. /package/dist/{memory → storage/memory}/sqlite/migrations/013_skill_evaluation_scenarios.sql +0 -0
  370. /package/dist/{memory → storage/memory}/sqlite/migrations/014_manager_profile_overlays.sql +0 -0
  371. /package/dist/{memory → storage/memory}/sqlite/migrations/015_artifact_metadata.sql +0 -0
  372. /package/dist/{memory → storage/memory}/sqlite/migrations/016_agent_seed_history.sql +0 -0
  373. /package/dist/{memory → storage/memory}/sqlite/migrations/017_intent_signal_skill_targets.sql +0 -0
  374. /package/dist/{memory → storage/memory}/sqlite/migrations/018_skill_system_v2.sql +0 -0
  375. /package/dist/{memory → storage/memory}/sqlite/migrations/019_task_scoped_command_grants.sql +0 -0
@@ -3,6 +3,7 @@ import { dirname, isAbsolute, resolve, sep } from 'node:path';
3
3
  import { classifyOperationRisk } from '../governance/risk-classifier.js';
4
4
  import { isSddPhase, sddPhases } from '../sdd/schema.js';
5
5
  import { commandAllowlistIds } from '../workflows/command-allowlist-adapter.js';
6
+ import { evaluateExplicitRequestAuthorization } from './explicit-request-authorization.js';
6
7
  export { isRiskyPermissionCategory, permissionCategories, riskyPermissionCategories } from './schema.js';
7
8
  export const permissionDecisions = ['allow', 'ask', 'deny'];
8
9
  export const permissionModes = ['allow', 'audit', 'require-preflight', 'deny'];
@@ -21,8 +22,8 @@ export const defaultPermissionPolicy = {
21
22
  { category: 'network', decision: 'ask', reason: 'Network access is external and requires approval by default.' },
22
23
  { category: 'git', decision: 'ask', reason: 'Git operations can affect review state or remotes.' },
23
24
  { category: 'git-write', decision: 'ask', reason: 'Git writes can affect review state or remotes.' },
24
- { category: 'memory', decision: 'ask', reason: 'Memory changes are durable and should be explicit.' },
25
- { category: 'memory-write', decision: 'ask', reason: 'Memory writes are durable and should be explicit.' },
25
+ { category: 'memory', decision: 'ask', reason: 'Memory reads/writes are durable and audited; ordinary qualifying memory writes may proceed without duplicate confirmation.' },
26
+ { category: 'memory-write', decision: 'ask', reason: 'Memory writes are durable and audited; ordinary qualifying memory writes may proceed without duplicate confirmation.' },
26
27
  { category: 'external-directory', decision: 'deny', reason: 'External directory access is denied unless a future sandbox grants it explicitly.' },
27
28
  { category: 'provider-tool', decision: 'ask', reason: 'Provider-specific tools stay opaque and require approval by default.' },
28
29
  { category: 'secrets', decision: 'deny', reason: 'Secret access is privileged and denied by default.' },
@@ -41,8 +42,8 @@ const planningPhaseModes = {
41
42
  network: 'require-preflight',
42
43
  git: 'require-preflight',
43
44
  'git-write': 'require-preflight',
44
- memory: 'require-preflight',
45
- 'memory-write': 'require-preflight',
45
+ memory: 'audit',
46
+ 'memory-write': 'audit',
46
47
  'external-directory': 'deny',
47
48
  'provider-tool': 'audit',
48
49
  secrets: 'deny',
@@ -69,7 +70,14 @@ export const sddPhasePermissionMatrix = Object.fromEntries(sddPhases.map((phase)
69
70
  if (phase === 'archive')
70
71
  return [
71
72
  phase,
72
- { ...verifyPhaseModes, git: 'require-preflight', 'git-write': 'require-preflight', memory: 'require-preflight', 'memory-write': 'require-preflight' },
73
+ {
74
+ ...verifyPhaseModes,
75
+ edit: 'require-preflight',
76
+ git: 'require-preflight',
77
+ 'git-write': 'require-preflight',
78
+ memory: 'audit',
79
+ 'memory-write': 'audit',
80
+ },
73
81
  ];
74
82
  return [phase, planningPhaseModes];
75
83
  }));
@@ -85,30 +93,30 @@ const filesystemCategories = new Set([
85
93
  export function evaluatePermission(request, policy = defaultPermissionPolicy) {
86
94
  const risk = classifyOperationRisk(request);
87
95
  if (request.category === 'secrets')
88
- return result(request, 'deny', 'secret_access', 'Secret access is denied by default.', {}, risk);
96
+ return withExplicitRequestAuthorization(request, result(request, 'deny', 'secret_access', 'Secret access is denied by default.', {}, risk), risk);
89
97
  if (request.category === 'external-directory') {
90
- return result(request, 'deny', 'workspace_boundary', 'External directory access is denied by the foundation policy.', {}, risk);
98
+ return withExplicitRequestAuthorization(request, result(request, 'deny', 'workspace_boundary', 'External directory access is denied by the foundation policy.', {}, risk), risk);
91
99
  }
92
100
  const hardRisk = hardRiskDecision(request, risk);
93
101
  if (hardRisk !== undefined)
94
- return hardRisk;
102
+ return withExplicitRequestAuthorization(request, hardRisk, risk);
95
103
  const workspaceEscape = workspaceEscapeDecision(request);
96
104
  if (workspaceEscape !== undefined)
97
- return workspaceEscape;
105
+ return withExplicitRequestAuthorization(request, workspaceEscape, risk);
98
106
  const verifyAllowlistedCommand = verifyAllowlistedCommandDecision(request, risk);
99
107
  if (verifyAllowlistedCommand !== undefined)
100
108
  return verifyAllowlistedCommand;
101
109
  const sddPhaseDecision = phaseMatrixDecision(request);
102
110
  if (sddPhaseDecision !== undefined && sddPhaseDecision.mode !== 'allow' && sddPhaseDecision.mode !== 'audit')
103
- return sddPhaseDecision;
111
+ return withExplicitRequestAuthorization(request, sddPhaseDecision, risk);
104
112
  const explicitValidation = explicitValidationDecision(request, risk);
105
113
  if (explicitValidation !== undefined)
106
- return explicitValidation;
114
+ return withExplicitRequestAuthorization(request, explicitValidation, risk);
107
115
  if (sddPhaseDecision !== undefined)
108
116
  return sddPhaseDecision;
109
117
  const boundary = workspaceBoundaryDecision(request);
110
118
  if (boundary !== undefined)
111
- return boundary;
119
+ return withExplicitRequestAuthorization(request, boundary, risk);
112
120
  const agentDecision = request.agent?.permissions[request.category];
113
121
  const baseRule = policy.rules.find((rule) => rule.category === request.category);
114
122
  const baseDecision = agentDecision ?? baseRule?.decision ?? 'ask';
@@ -118,7 +126,7 @@ export function evaluatePermission(request, policy = defaultPermissionPolicy) {
118
126
  : (baseRule?.reason ?? `No explicit rule exists for ${request.category}; ask by default.`);
119
127
  const flagRisk = riskDecision(request);
120
128
  if (flagRisk !== undefined && isLessRestrictive(baseDecision, flagRisk.decision)) {
121
- return result(request, flagRisk.decision, flagRisk.reason, flagRisk.message, {}, risk);
129
+ return withExplicitRequestAuthorization(request, result(request, flagRisk.decision, flagRisk.reason, flagRisk.message, {}, risk), risk);
122
130
  }
123
131
  if (risk.defaultDecision === 'audit' && baseDecision !== 'deny') {
124
132
  return result(request, 'allow', risk.reasonCodes.includes('provider_readonly_audit') ? 'provider_readonly_audit' : risk.reasonCodes.includes('allowlisted_verification') ? 'allowlisted_command' : baseReason, baseMessage, {
@@ -127,7 +135,39 @@ export function evaluatePermission(request, policy = defaultPermissionPolicy) {
127
135
  warnings: risk.reasonCodes.includes('provider_readonly_audit') ? ['provider-readonly-audit-only'] : ['audit-only'],
128
136
  }, risk);
129
137
  }
130
- return result(request, baseDecision, baseReason, baseMessage, {}, risk);
138
+ return withExplicitRequestAuthorization(request, result(request, baseDecision, baseReason, baseMessage, {}, risk), risk);
139
+ }
140
+ function withExplicitRequestAuthorization(request, decision, risk) {
141
+ if (request.explicitRequest === undefined)
142
+ return decision;
143
+ const explicit = evaluateExplicitRequestAuthorization({ request, risk, evaluatedAt: new Date().toISOString() });
144
+ if (decision.decision !== 'ask') {
145
+ return { ...decision, explicitRequestAudit: explicit.audit, auditEvidence: [...(decision.auditEvidence ?? []), `explicitRequest:${explicit.audit.matchStatus}`] };
146
+ }
147
+ if (explicit.decision === 'allow') {
148
+ return {
149
+ ...decision,
150
+ decision: 'allow',
151
+ reason: 'explicit_request_authorization',
152
+ message: 'Explicit human request authorizes this exact one-off operation.',
153
+ explicitRequestAudit: explicit.audit,
154
+ authorizationMode: 'explicit-request',
155
+ auditEvidence: [...(decision.auditEvidence ?? []), 'explicitRequest:exact-match'],
156
+ };
157
+ }
158
+ if (explicit.decision === 'deny') {
159
+ return {
160
+ ...decision,
161
+ decision: 'deny',
162
+ reason: explicit.audit.reasonCodes.includes('sdd_human_acceptance_required') ? 'sdd_phase_policy' : 'risk_tier_policy',
163
+ message: explicit.audit.reasonCodes.includes('sdd_human_acceptance_required')
164
+ ? 'SDD artifact acceptance is human-only and cannot be inferred from explicit-request preflight.'
165
+ : 'Explicit request contains a hard-stop condition and cannot authorize this operation.',
166
+ explicitRequestAudit: explicit.audit,
167
+ auditEvidence: [...(decision.auditEvidence ?? []), `explicitRequest:${explicit.audit.matchStatus}`],
168
+ };
169
+ }
170
+ return { ...decision, explicitRequestAudit: explicit.audit, auditEvidence: [...(decision.auditEvidence ?? []), `explicitRequest:${explicit.audit.matchStatus}`] };
131
171
  }
132
172
  export function isPathInsideWorkspace(workspaceRoot, targetPath) {
133
173
  const root = resolve(workspaceRoot);
@@ -1,178 +1 @@
1
- import { existsSync } from 'node:fs';
2
- import { join } from 'node:path';
3
- import { recommendWorkspaceStrategy } from '../workspace-strategy/index.js';
4
- import { planWorktreeSandbox } from './sandbox-worktree-planning.js';
5
- const filesystemCategories = new Set(['read', 'edit', 'external-directory']);
6
- export function planExecutionIsolation(input) {
7
- const { operation, decision } = input;
8
- const strategy = selectStrategy(operation, decision);
9
- const sandbox = worktreeSandboxPlan(operation, strategy, input.gitBoundaryInspector);
10
- const realpathHardeningRequired = requiresRealpathHardening(operation);
11
- const requiredApprovals = approvalRequirements(operation, decision);
12
- const requiredConditions = conditionRequirements(operation, decision, realpathHardeningRequired, sandbox);
13
- const limitations = planLimitations(operation, decision, strategy, sandbox);
14
- return {
15
- strategy,
16
- pathConstraints: pathConstraints(operation),
17
- ...(sandbox === undefined ? {} : { sandbox }),
18
- realpathHardeningRequired,
19
- requiredApprovals,
20
- requiredConditions,
21
- limitations,
22
- executable: decision.decision === 'allow' && sandbox?.decision !== 'rejected',
23
- executesProvider: false,
24
- createsWorktree: false,
25
- };
26
- }
27
- export function recommendWorkspaceStrategyForExecution(input) {
28
- return recommendWorkspaceStrategy(workspaceStrategyInputForExecution(input));
29
- }
30
- export function workspaceStrategyInputForExecution(input) {
31
- const categories = workspaceStrategyCategories(input.operation, input.decision);
32
- const mutationSignal = hasWorkspaceMutationSignal(input.operation, categories);
33
- return {
34
- categories,
35
- intentSignals: workspaceStrategyIntentSignals(input.operation, input.decision),
36
- risk: workspaceStrategyRisk(input.decision),
37
- readOnly: isReadOnlyWorkspaceOperation(input.operation, input.decision),
38
- expectedWrites: mutationSignal,
39
- mutatesRepository: mutationSignal,
40
- destructive: input.operation.destructive === true,
41
- external: input.operation.external === true || input.operation.category === 'external-directory',
42
- privileged: input.operation.privileged === true,
43
- ambiguous: input.operation.ambiguous === true,
44
- changeSize: workspaceStrategyChangeSize(input.decision),
45
- ...(mutationSignal ? { workspace: { checkout: 'unknown' } } : {}),
46
- };
47
- }
48
- function selectStrategy(operation, decision) {
49
- if (operation.sandboxStrategy === 'worktree')
50
- return 'worktree';
51
- if (decision.decision === 'deny') {
52
- return operation.category === 'external-directory' || operation.external === true ? 'process-sandbox' : 'workspace';
53
- }
54
- if (operation.category === 'shell' || operation.category === 'network' || operation.category === 'provider-tool' || operation.privileged === true) {
55
- return 'process-sandbox';
56
- }
57
- if (operation.category === 'edit' || operation.category === 'git' || operation.destructive === true) {
58
- return 'worktree';
59
- }
60
- return 'workspace';
61
- }
62
- function pathConstraints(operation) {
63
- return {
64
- ...(operation.workspaceRoot === undefined ? {} : { workspaceRoot: operation.workspaceRoot }),
65
- ...(operation.targetPath === undefined ? {} : { targetPath: operation.targetPath }),
66
- enforceWorkspaceBoundary: operation.category !== 'external-directory',
67
- allowExternalPaths: false,
68
- };
69
- }
70
- function requiresRealpathHardening(operation) {
71
- return filesystemCategories.has(operation.category) || operation.workspaceRoot !== undefined || operation.targetPath !== undefined;
72
- }
73
- function approvalRequirements(operation, decision) {
74
- const approvals = [];
75
- if (decision.decision === 'ask')
76
- approvals.push(`human-approval:${decision.reason}`);
77
- if (operation.destructive === true)
78
- approvals.push('destructive-operation-approval');
79
- if (operation.external === true || operation.category === 'external-directory')
80
- approvals.push('external-access-approval');
81
- if (operation.privileged === true)
82
- approvals.push('privileged-operation-approval');
83
- if (operation.ambiguous === true)
84
- approvals.push('clarify-ambiguous-operation');
85
- return [...new Set(approvals)];
86
- }
87
- function conditionRequirements(operation, decision, realpathHardeningRequired, sandbox) {
88
- const conditions = ['permission-decision-recorded'];
89
- if (decision.decision === 'deny')
90
- conditions.push('blocked-by-policy-before-execution');
91
- if (sandbox?.decision === 'rejected')
92
- conditions.push(`blocked-by-sandbox-planning:${sandbox.reason ?? 'unknown'}`);
93
- if (decision.decision === 'ask')
94
- conditions.push('approved-before-execution');
95
- if (realpathHardeningRequired)
96
- conditions.push('resolve-realpath-and-recheck-workspace-boundary-before-execution');
97
- if (operation.category === 'edit' || operation.category === 'git' || operation.destructive === true)
98
- conditions.push('isolated-worktree-or-equivalent-before-mutation');
99
- if (operation.category === 'shell' || operation.category === 'network' || operation.category === 'provider-tool')
100
- conditions.push('sandboxed-process-or-equivalent-before-provider-execution');
101
- return conditions;
102
- }
103
- function planLimitations(operation, decision, strategy, sandbox) {
104
- const limitations = ['planning-only: this preflight records an execution plan only; no command, provider tool, worktree, sandbox, directory, or filesystem mutation was performed'];
105
- if (strategy === 'worktree')
106
- limitations.push('worktree is only the planned isolation target; no worktree was created and mutations still require a separate executor or manual worktree');
107
- if (strategy === 'process-sandbox')
108
- limitations.push('process-sandbox is only the planned isolation target; no sandbox was launched and execution still requires a separate executor');
109
- if (decision.decision === 'deny')
110
- limitations.push(`permission policy denies execution: ${decision.reason}`);
111
- if (sandbox?.decision === 'rejected')
112
- limitations.push(`sandbox planning rejects execution: ${sandbox.audit.validationSummary}`);
113
- if (operation.category === 'external-directory')
114
- limitations.push('external directory execution remains denied by default even when a stronger future sandbox is selected');
115
- return limitations;
116
- }
117
- function worktreeSandboxPlan(operation, strategy, gitBoundaryInspector) {
118
- if (strategy !== 'worktree')
119
- return undefined;
120
- if (operation.workspaceRoot === undefined || operation.targetPath === undefined)
121
- return undefined;
122
- return planWorktreeSandbox({
123
- workspaceRoot: operation.workspaceRoot,
124
- targetPath: operation.targetPath,
125
- gitBoundaryInspector: gitBoundaryInspector ?? defaultGitBoundaryInspector,
126
- });
127
- }
128
- const defaultGitBoundaryInspector = ({ workspaceRoot }) => {
129
- if (existsSync(join(workspaceRoot, '.git'))) {
130
- return { status: 'compatible', reason: 'workspace git metadata is present' };
131
- }
132
- return { status: 'compatible', reason: 'workspace has no git metadata to conflict with a planned worktree boundary' };
133
- };
134
- function workspaceStrategyCategories(operation, decision) {
135
- const categories = [operation.category];
136
- if (decision.riskReasonCodes?.includes('git_write') === true && !categories.includes('git-write'))
137
- categories.push('git-write');
138
- return categories;
139
- }
140
- function workspaceStrategyIntentSignals(operation, decision) {
141
- return [
142
- `permission:${decision.reason}`,
143
- ...(decision.riskReasonCodes ?? []).map((code) => `risk:${code}`),
144
- ...(operation.workflow === undefined ? [] : [`workflow:${operation.workflow}`]),
145
- ...(operation.phase === undefined ? [] : [`phase:${operation.phase}`]),
146
- ];
147
- }
148
- function workspaceStrategyRisk(decision) {
149
- if (decision.riskTier === 0)
150
- return 'none';
151
- if (decision.riskTier === 1)
152
- return 'low';
153
- if (decision.riskTier === 2)
154
- return 'medium';
155
- if (decision.riskTier === 3)
156
- return 'high';
157
- if (decision.riskTier === 4)
158
- return 'critical';
159
- return 'unknown';
160
- }
161
- function workspaceStrategyChangeSize(decision) {
162
- if (decision.riskReasonCodes?.some((code) => code === 'architecture_change' || code === 'cross_surface_change' || code === 'governance_change') === true)
163
- return 'large';
164
- if (decision.riskTier === 2)
165
- return 'medium';
166
- if (decision.riskTier === 1)
167
- return 'small';
168
- return 'unknown';
169
- }
170
- function isReadOnlyWorkspaceOperation(operation, decision) {
171
- return decision.riskTier === 0 || operation.category === 'read' || (operation.category === 'git' && decision.riskReasonCodes?.includes('git_write') !== true);
172
- }
173
- function hasWorkspaceMutationSignal(operation, categories) {
174
- if (operation.destructive === true || operation.privileged === true || operation.external === true || operation.ambiguous === true)
175
- return true;
176
- return categories.some((category) => workspaceMutationCategories.has(category));
177
- }
178
- const workspaceMutationCategories = new Set(['edit', 'implementation-edit', 'spec-write', 'design-write', 'task-write', 'git-write']);
1
+ export * from '../application/runs/execution-planning.js';
@@ -1 +1 @@
1
- export {};
1
+ export * from '../application/runs/operation-execution.js';
@@ -1,129 +1 @@
1
- const defaultRetryPolicy = { mode: 'never' };
2
- const operationRetryPolicyModes = [
3
- 'never',
4
- 'after-abandoned',
5
- 'after-failure',
6
- 'after-failure-or-abandoned',
7
- ];
8
- const allowedRetryableStatuses = ['failed', 'abandoned'];
9
- export function defaultOperationRetryPolicy() {
10
- return defaultRetryPolicy;
11
- }
12
- export function parseOperationRetryPolicy(input) {
13
- if (input === undefined) {
14
- return { ok: true, policy: defaultRetryPolicy };
15
- }
16
- if (!isRecord(input) || Array.isArray(input)) {
17
- return { ok: false, errors: ['Retry policy must be an object'] };
18
- }
19
- const allowedKeys = new Set(['mode', 'retryableStatuses']);
20
- const unknownKeys = Object.keys(input).filter((key) => !allowedKeys.has(key));
21
- const errors = unknownKeys.map((key) => `Unknown retry policy field: ${key}`);
22
- const mode = input.mode;
23
- if (!isOperationRetryPolicyMode(mode)) {
24
- errors.push('Retry policy mode must be one of: never, after-abandoned, after-failure, after-failure-or-abandoned');
25
- }
26
- if ('retryableStatuses' in input) {
27
- const retryableStatuses = input.retryableStatuses;
28
- if (!Array.isArray(retryableStatuses)) {
29
- errors.push('Retry policy retryableStatuses must be an array');
30
- }
31
- else {
32
- const invalidStatuses = retryableStatuses.filter((status) => !isAllowedRetryableStatus(status));
33
- if (invalidStatuses.length > 0) {
34
- errors.push(`Retry policy retryableStatuses contains invalid retryable status: ${invalidStatuses.map(String).join(', ')}`);
35
- }
36
- if (new Set(retryableStatuses).size !== retryableStatuses.length) {
37
- errors.push('Retry policy retryableStatuses must not contain duplicates');
38
- }
39
- if (isOperationRetryPolicyMode(mode) && invalidStatuses.length === 0) {
40
- const expectedStatuses = retryableStatusesFor({ mode });
41
- if (!sameStatuses(retryableStatuses, expectedStatuses)) {
42
- errors.push(`Retry policy retryableStatuses must match mode ${mode}: ${expectedStatuses.length === 0 ? '[]' : expectedStatuses.join(', ')}`);
43
- }
44
- }
45
- }
46
- }
47
- if (errors.length > 0 || !isOperationRetryPolicyMode(mode)) {
48
- return { ok: false, errors };
49
- }
50
- return { ok: true, policy: { mode } };
51
- }
52
- export function evaluateOperationRetry(input) {
53
- const policy = input.policy ?? defaultRetryPolicy;
54
- const retryableStatuses = retryableStatusesFor(policy);
55
- const attempts = [...input.attempts].sort(compareAttempts);
56
- const activeAttempt = attempts.find((attempt) => attempt.status === 'reserved');
57
- if (activeAttempt !== undefined) {
58
- const latestAttempt = attempts.at(-1);
59
- return {
60
- allowed: false,
61
- policy,
62
- reasonCode: 'active_attempt_reserved',
63
- reason: `Retry blocked because attempt ${activeAttempt.id} is still reserved`,
64
- evaluatedAttemptCount: attempts.length,
65
- retryableStatuses,
66
- activeAttempt,
67
- ...(latestAttempt === undefined ? {} : { latestAttempt }),
68
- };
69
- }
70
- const latestAttempt = attempts.at(-1);
71
- if (latestAttempt === undefined) {
72
- return {
73
- allowed: true,
74
- policy,
75
- reasonCode: 'initial_attempt_allowed',
76
- reason: 'No previous operation attempt exists for this approval',
77
- evaluatedAttemptCount: 0,
78
- retryableStatuses,
79
- };
80
- }
81
- if (latestAttempt.status === 'succeeded') {
82
- return block(policy, retryableStatuses, attempts.length, latestAttempt, 'already_succeeded', `Retry blocked because latest attempt ${latestAttempt.id} already succeeded`);
83
- }
84
- if (policy.mode === 'never') {
85
- return block(policy, retryableStatuses, attempts.length, latestAttempt, 'retry_disabled', `Retry blocked by policy never after ${latestAttempt.status}`);
86
- }
87
- if (retryableStatuses.includes(latestAttempt.status)) {
88
- return {
89
- allowed: true,
90
- policy,
91
- reasonCode: 'status_allowed_by_policy',
92
- reason: `Retry allowed by policy ${policy.mode} after ${latestAttempt.status}`,
93
- evaluatedAttemptCount: attempts.length,
94
- retryableStatuses,
95
- latestAttempt,
96
- };
97
- }
98
- return block(policy, retryableStatuses, attempts.length, latestAttempt, 'status_not_allowed_by_policy', `Retry blocked by policy ${policy.mode} after ${latestAttempt.status}`);
99
- }
100
- function block(policy, retryableStatuses, evaluatedAttemptCount, latestAttempt, reasonCode, reason) {
101
- return { allowed: false, policy, reasonCode, reason, evaluatedAttemptCount, retryableStatuses, latestAttempt };
102
- }
103
- function retryableStatusesFor(policy) {
104
- switch (policy.mode) {
105
- case 'after-abandoned':
106
- return ['abandoned'];
107
- case 'after-failure':
108
- return ['failed'];
109
- case 'after-failure-or-abandoned':
110
- return ['failed', 'abandoned'];
111
- case 'never':
112
- return [];
113
- }
114
- }
115
- function isRecord(value) {
116
- return typeof value === 'object' && value !== null;
117
- }
118
- function isOperationRetryPolicyMode(value) {
119
- return typeof value === 'string' && operationRetryPolicyModes.includes(value);
120
- }
121
- function isAllowedRetryableStatus(value) {
122
- return typeof value === 'string' && allowedRetryableStatuses.includes(value);
123
- }
124
- function sameStatuses(actual, expected) {
125
- return actual.length === expected.length && actual.every((status) => expected.includes(status));
126
- }
127
- function compareAttempts(a, b) {
128
- return a.attemptSequence - b.attemptSequence || a.reservedAt.localeCompare(b.reservedAt) || a.id.localeCompare(b.id);
129
- }
1
+ export * from '../application/runs/operation-retry.js';