@planweave-ai/runtime 0.1.2 → 0.1.7

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 (325) hide show
  1. package/dist/autoRun/claudeCodeIntegration.d.ts.map +1 -1
  2. package/dist/autoRun/claudeCodeIntegration.js +4 -2
  3. package/dist/autoRun/claudeCodeIntegration.js.map +1 -1
  4. package/dist/autoRun/codexExecutor.d.ts +2 -0
  5. package/dist/autoRun/codexExecutor.d.ts.map +1 -1
  6. package/dist/autoRun/codexExecutor.js +10 -2
  7. package/dist/autoRun/codexExecutor.js.map +1 -1
  8. package/dist/autoRun/codexIntegration.d.ts.map +1 -1
  9. package/dist/autoRun/codexIntegration.js +4 -2
  10. package/dist/autoRun/codexIntegration.js.map +1 -1
  11. package/dist/autoRun/executorIntegration.d.ts +1 -0
  12. package/dist/autoRun/executorIntegration.d.ts.map +1 -1
  13. package/dist/autoRun/executorIntegration.js.map +1 -1
  14. package/dist/autoRun/localReviewExecutor.d.ts +2 -0
  15. package/dist/autoRun/localReviewExecutor.d.ts.map +1 -1
  16. package/dist/autoRun/localReviewExecutor.js +9 -2
  17. package/dist/autoRun/localReviewExecutor.js.map +1 -1
  18. package/dist/autoRun/localReviewIntegration.d.ts.map +1 -1
  19. package/dist/autoRun/localReviewIntegration.js +4 -2
  20. package/dist/autoRun/localReviewIntegration.js.map +1 -1
  21. package/dist/autoRun/opencodeExecutor.d.ts +2 -0
  22. package/dist/autoRun/opencodeExecutor.d.ts.map +1 -1
  23. package/dist/autoRun/opencodeExecutor.js +9 -2
  24. package/dist/autoRun/opencodeExecutor.js.map +1 -1
  25. package/dist/autoRun/opencodeIntegration.d.ts.map +1 -1
  26. package/dist/autoRun/opencodeIntegration.js +4 -2
  27. package/dist/autoRun/opencodeIntegration.js.map +1 -1
  28. package/dist/autoRun/piIntegration.d.ts.map +1 -1
  29. package/dist/autoRun/piIntegration.js +4 -2
  30. package/dist/autoRun/piIntegration.js.map +1 -1
  31. package/dist/autoRun/terminalAgentExecutor.d.ts +2 -0
  32. package/dist/autoRun/terminalAgentExecutor.d.ts.map +1 -1
  33. package/dist/autoRun/terminalAgentExecutor.js +9 -2
  34. package/dist/autoRun/terminalAgentExecutor.js.map +1 -1
  35. package/dist/autoRun/tmuxExecutor.d.ts +3 -0
  36. package/dist/autoRun/tmuxExecutor.d.ts.map +1 -1
  37. package/dist/autoRun/tmuxExecutor.js +19 -3
  38. package/dist/autoRun/tmuxExecutor.js.map +1 -1
  39. package/dist/desktop/canvasApi.d.ts.map +1 -1
  40. package/dist/desktop/canvasApi.js +45 -22
  41. package/dist/desktop/canvasApi.js.map +1 -1
  42. package/dist/desktop/canvasGraphApi.d.ts.map +1 -1
  43. package/dist/desktop/canvasGraphApi.js +24 -33
  44. package/dist/desktop/canvasGraphApi.js.map +1 -1
  45. package/dist/desktop/canvasSelectionApi.d.ts +2 -0
  46. package/dist/desktop/canvasSelectionApi.d.ts.map +1 -0
  47. package/dist/desktop/canvasSelectionApi.js +18 -0
  48. package/dist/desktop/canvasSelectionApi.js.map +1 -0
  49. package/dist/desktop/canvasSelectionStore.d.ts +6 -0
  50. package/dist/desktop/canvasSelectionStore.d.ts.map +1 -0
  51. package/dist/desktop/canvasSelectionStore.js +88 -0
  52. package/dist/desktop/canvasSelectionStore.js.map +1 -0
  53. package/dist/desktop/fileSyncApi.d.ts.map +1 -1
  54. package/dist/desktop/fileSyncApi.js +77 -16
  55. package/dist/desktop/fileSyncApi.js.map +1 -1
  56. package/dist/desktop/graph/editModel.d.ts +18 -6
  57. package/dist/desktop/graph/editModel.d.ts.map +1 -1
  58. package/dist/desktop/graph/editModel.js +157 -69
  59. package/dist/desktop/graph/editModel.js.map +1 -1
  60. package/dist/desktop/graph/projectProjectionModel.d.ts.map +1 -1
  61. package/dist/desktop/graph/projectProjectionModel.js +255 -77
  62. package/dist/desktop/graph/projectProjectionModel.js.map +1 -1
  63. package/dist/desktop/graph/readModel.d.ts.map +1 -1
  64. package/dist/desktop/graph/readModel.js +33 -59
  65. package/dist/desktop/graph/readModel.js.map +1 -1
  66. package/dist/desktop/graph/resultsFileIndex.d.ts +6 -0
  67. package/dist/desktop/graph/resultsFileIndex.d.ts.map +1 -1
  68. package/dist/desktop/graph/resultsFileIndex.js +83 -50
  69. package/dist/desktop/graph/resultsFileIndex.js.map +1 -1
  70. package/dist/desktop/graph/searchIndexModel.d.ts +10 -1
  71. package/dist/desktop/graph/searchIndexModel.d.ts.map +1 -1
  72. package/dist/desktop/graph/searchIndexModel.js +143 -81
  73. package/dist/desktop/graph/searchIndexModel.js.map +1 -1
  74. package/dist/desktop/graph/statisticsIndexModel.d.ts.map +1 -1
  75. package/dist/desktop/graph/statisticsIndexModel.js +35 -103
  76. package/dist/desktop/graph/statisticsIndexModel.js.map +1 -1
  77. package/dist/desktop/graph/todoModel.d.ts +6 -17
  78. package/dist/desktop/graph/todoModel.d.ts.map +1 -1
  79. package/dist/desktop/graph/todoModel.js +30 -102
  80. package/dist/desktop/graph/todoModel.js.map +1 -1
  81. package/dist/desktop/graphApi.d.ts +1 -1
  82. package/dist/desktop/graphApi.d.ts.map +1 -1
  83. package/dist/desktop/graphApi.js +1 -1
  84. package/dist/desktop/graphApi.js.map +1 -1
  85. package/dist/desktop/index.d.ts +4 -1
  86. package/dist/desktop/index.d.ts.map +1 -1
  87. package/dist/desktop/index.js +3 -1
  88. package/dist/desktop/index.js.map +1 -1
  89. package/dist/desktop/layoutApi.d.ts +5 -6
  90. package/dist/desktop/layoutApi.d.ts.map +1 -1
  91. package/dist/desktop/layoutApi.js +31 -185
  92. package/dist/desktop/layoutApi.js.map +1 -1
  93. package/dist/desktop/layoutStore.d.ts +10 -0
  94. package/dist/desktop/layoutStore.d.ts.map +1 -0
  95. package/dist/desktop/layoutStore.js +158 -0
  96. package/dist/desktop/layoutStore.js.map +1 -0
  97. package/dist/desktop/projectGraphEditApi.d.ts +12 -0
  98. package/dist/desktop/projectGraphEditApi.d.ts.map +1 -0
  99. package/dist/desktop/projectGraphEditApi.js +32 -0
  100. package/dist/desktop/projectGraphEditApi.js.map +1 -0
  101. package/dist/desktop/reviewPipelineApi.d.ts.map +1 -1
  102. package/dist/desktop/reviewPipelineApi.js +28 -28
  103. package/dist/desktop/reviewPipelineApi.js.map +1 -1
  104. package/dist/desktop/runApi.d.ts.map +1 -1
  105. package/dist/desktop/runApi.js +4 -3
  106. package/dist/desktop/runApi.js.map +1 -1
  107. package/dist/desktop/types/bridgeTypes.d.ts +12 -4
  108. package/dist/desktop/types/bridgeTypes.d.ts.map +1 -1
  109. package/dist/desktop/types/graphTypes.d.ts +12 -0
  110. package/dist/desktop/types/graphTypes.d.ts.map +1 -1
  111. package/dist/errors.d.ts +13 -0
  112. package/dist/errors.d.ts.map +1 -0
  113. package/dist/errors.js +24 -0
  114. package/dist/errors.js.map +1 -0
  115. package/dist/graph/fieldEditMutation.d.ts +2 -0
  116. package/dist/graph/fieldEditMutation.d.ts.map +1 -1
  117. package/dist/graph/fieldEditMutation.js +18 -0
  118. package/dist/graph/fieldEditMutation.js.map +1 -1
  119. package/dist/index.d.ts +11 -6
  120. package/dist/index.d.ts.map +1 -1
  121. package/dist/index.js +9 -6
  122. package/dist/index.js.map +1 -1
  123. package/dist/package/loadPackage.d.ts.map +1 -1
  124. package/dist/package/loadPackage.js +4 -0
  125. package/dist/package/loadPackage.js.map +1 -1
  126. package/dist/package/manifestEdit.d.ts.map +1 -1
  127. package/dist/package/manifestEdit.js +112 -31
  128. package/dist/package/manifestEdit.js.map +1 -1
  129. package/dist/paths.d.ts.map +1 -1
  130. package/dist/paths.js +2 -10
  131. package/dist/paths.js.map +1 -1
  132. package/dist/plangraph/adapters.d.ts +3 -0
  133. package/dist/plangraph/adapters.d.ts.map +1 -0
  134. package/dist/plangraph/adapters.js +13 -0
  135. package/dist/plangraph/adapters.js.map +1 -0
  136. package/dist/plangraph/commands.d.ts +191 -0
  137. package/dist/plangraph/commands.d.ts.map +1 -0
  138. package/dist/plangraph/commands.js +4 -0
  139. package/dist/plangraph/commands.js.map +1 -0
  140. package/dist/plangraph/domain/buildPlanGraph.d.ts +14 -0
  141. package/dist/plangraph/domain/buildPlanGraph.d.ts.map +1 -0
  142. package/dist/plangraph/domain/buildPlanGraph.js +91 -0
  143. package/dist/plangraph/domain/buildPlanGraph.js.map +1 -0
  144. package/dist/plangraph/domain/selectors.d.ts +11 -0
  145. package/dist/plangraph/domain/selectors.d.ts.map +1 -0
  146. package/dist/plangraph/domain/selectors.js +54 -0
  147. package/dist/plangraph/domain/selectors.js.map +1 -0
  148. package/dist/plangraph/domain/types.d.ts +56 -0
  149. package/dist/plangraph/domain/types.d.ts.map +1 -0
  150. package/dist/plangraph/domain/types.js +2 -0
  151. package/dist/plangraph/domain/types.js.map +1 -0
  152. package/dist/plangraph/executeCommand.d.ts +19 -0
  153. package/dist/plangraph/executeCommand.d.ts.map +1 -0
  154. package/dist/plangraph/executeCommand.js +809 -0
  155. package/dist/plangraph/executeCommand.js.map +1 -0
  156. package/dist/plangraph/hash.d.ts +4 -0
  157. package/dist/plangraph/hash.d.ts.map +1 -0
  158. package/dist/plangraph/hash.js +21 -0
  159. package/dist/plangraph/hash.js.map +1 -0
  160. package/dist/plangraph/index.d.ts +15 -0
  161. package/dist/plangraph/index.d.ts.map +1 -0
  162. package/dist/plangraph/index.js +9 -0
  163. package/dist/plangraph/index.js.map +1 -0
  164. package/dist/plangraph/packageRepository.d.ts +19 -0
  165. package/dist/plangraph/packageRepository.d.ts.map +1 -0
  166. package/dist/plangraph/packageRepository.js +114 -0
  167. package/dist/plangraph/packageRepository.js.map +1 -0
  168. package/dist/plangraph/ports.d.ts +73 -0
  169. package/dist/plangraph/ports.d.ts.map +1 -0
  170. package/dist/plangraph/ports.js +2 -0
  171. package/dist/plangraph/ports.js.map +1 -0
  172. package/dist/plangraph/projectGraphCommand.d.ts +16 -0
  173. package/dist/plangraph/projectGraphCommand.d.ts.map +1 -0
  174. package/dist/plangraph/projectGraphCommand.js +203 -0
  175. package/dist/plangraph/projectGraphCommand.js.map +1 -0
  176. package/dist/plangraph/projections/agentContextProjection.d.ts +8 -0
  177. package/dist/plangraph/projections/agentContextProjection.d.ts.map +1 -0
  178. package/dist/plangraph/projections/agentContextProjection.js +50 -0
  179. package/dist/plangraph/projections/agentContextProjection.js.map +1 -0
  180. package/dist/plangraph/projections/canvasMapProjection.d.ts +13 -0
  181. package/dist/plangraph/projections/canvasMapProjection.d.ts.map +1 -0
  182. package/dist/plangraph/projections/canvasMapProjection.js +40 -0
  183. package/dist/plangraph/projections/canvasMapProjection.js.map +1 -0
  184. package/dist/plangraph/projections/graphViewProjection.d.ts +16 -0
  185. package/dist/plangraph/projections/graphViewProjection.d.ts.map +1 -0
  186. package/dist/plangraph/projections/graphViewProjection.js +125 -0
  187. package/dist/plangraph/projections/graphViewProjection.js.map +1 -0
  188. package/dist/plangraph/projections/index.d.ts +10 -0
  189. package/dist/plangraph/projections/index.d.ts.map +1 -0
  190. package/dist/plangraph/projections/index.js +6 -0
  191. package/dist/plangraph/projections/index.js.map +1 -0
  192. package/dist/plangraph/projections/reviewProjection.d.ts +25 -0
  193. package/dist/plangraph/projections/reviewProjection.d.ts.map +1 -0
  194. package/dist/plangraph/projections/reviewProjection.js +27 -0
  195. package/dist/plangraph/projections/reviewProjection.js.map +1 -0
  196. package/dist/plangraph/projections/statisticsProjection.d.ts +15 -0
  197. package/dist/plangraph/projections/statisticsProjection.d.ts.map +1 -0
  198. package/dist/plangraph/projections/statisticsProjection.js +113 -0
  199. package/dist/plangraph/projections/statisticsProjection.js.map +1 -0
  200. package/dist/plangraph/projections/todoProjection.d.ts +43 -0
  201. package/dist/plangraph/projections/todoProjection.d.ts.map +1 -0
  202. package/dist/plangraph/projections/todoProjection.js +97 -0
  203. package/dist/plangraph/projections/todoProjection.js.map +1 -0
  204. package/dist/plangraph/sqliteIndex.d.ts +11 -0
  205. package/dist/plangraph/sqliteIndex.d.ts.map +1 -0
  206. package/dist/plangraph/sqliteIndex.js +655 -0
  207. package/dist/plangraph/sqliteIndex.js.map +1 -0
  208. package/dist/project.d.ts +1 -0
  209. package/dist/project.d.ts.map +1 -1
  210. package/dist/project.js +11 -0
  211. package/dist/project.js.map +1 -1
  212. package/dist/projectGraph/canvasWorkspaceRecovery.d.ts +40 -0
  213. package/dist/projectGraph/canvasWorkspaceRecovery.d.ts.map +1 -0
  214. package/dist/projectGraph/canvasWorkspaceRecovery.js +213 -0
  215. package/dist/projectGraph/canvasWorkspaceRecovery.js.map +1 -0
  216. package/dist/projectGraph/compileProjectGraph.d.ts.map +1 -1
  217. package/dist/projectGraph/compileProjectGraph.js +110 -50
  218. package/dist/projectGraph/compileProjectGraph.js.map +1 -1
  219. package/dist/projectGraph/index.d.ts +1 -1
  220. package/dist/projectGraph/index.d.ts.map +1 -1
  221. package/dist/projectGraph/index.js +1 -1
  222. package/dist/projectGraph/index.js.map +1 -1
  223. package/dist/projectGraph/schema.d.ts +1 -0
  224. package/dist/projectGraph/schema.d.ts.map +1 -1
  225. package/dist/projectGraph/schema.js +4 -4
  226. package/dist/projectGraph/schema.js.map +1 -1
  227. package/dist/projectGraph/types.d.ts +5 -0
  228. package/dist/projectGraph/types.d.ts.map +1 -1
  229. package/dist/schema/manifest.d.ts +4 -3
  230. package/dist/schema/manifest.d.ts.map +1 -1
  231. package/dist/schema/manifest.js +14 -12
  232. package/dist/schema/manifest.js.map +1 -1
  233. package/dist/schemaDocs/index.d.ts +7 -0
  234. package/dist/schemaDocs/index.d.ts.map +1 -0
  235. package/dist/schemaDocs/index.js +10 -0
  236. package/dist/schemaDocs/index.js.map +1 -0
  237. package/dist/schemaDocs/manifest.d.ts +3 -0
  238. package/dist/schemaDocs/manifest.d.ts.map +1 -0
  239. package/dist/schemaDocs/manifest.js +111 -0
  240. package/dist/schemaDocs/manifest.js.map +1 -0
  241. package/dist/schemaDocs/project.d.ts +3 -0
  242. package/dist/schemaDocs/project.d.ts.map +1 -0
  243. package/dist/schemaDocs/project.js +39 -0
  244. package/dist/schemaDocs/project.js.map +1 -0
  245. package/dist/schemaDocs/types.d.ts +11 -0
  246. package/dist/schemaDocs/types.d.ts.map +1 -0
  247. package/dist/schemaDocs/types.js +2 -0
  248. package/dist/schemaDocs/types.js.map +1 -0
  249. package/dist/taskManager/autoRun.d.ts +1 -0
  250. package/dist/taskManager/autoRun.d.ts.map +1 -1
  251. package/dist/taskManager/autoRun.js +2 -2
  252. package/dist/taskManager/autoRun.js.map +1 -1
  253. package/dist/taskManager/doctor.d.ts.map +1 -1
  254. package/dist/taskManager/doctor.js.map +1 -1
  255. package/dist/taskManager/index.d.ts +1 -0
  256. package/dist/taskManager/index.d.ts.map +1 -1
  257. package/dist/taskManager/index.js +1 -0
  258. package/dist/taskManager/index.js.map +1 -1
  259. package/dist/taskManager/projectDoctor.d.ts +6 -0
  260. package/dist/taskManager/projectDoctor.d.ts.map +1 -0
  261. package/dist/taskManager/projectDoctor.js +192 -0
  262. package/dist/taskManager/projectDoctor.js.map +1 -0
  263. package/dist/taskManager/projectDoctorCanvas.d.ts +14 -0
  264. package/dist/taskManager/projectDoctorCanvas.d.ts.map +1 -0
  265. package/dist/taskManager/projectDoctorCanvas.js +181 -0
  266. package/dist/taskManager/projectDoctorCanvas.js.map +1 -0
  267. package/dist/taskManager/promptRenderer.d.ts.map +1 -1
  268. package/dist/taskManager/promptRenderer.js +10 -0
  269. package/dist/taskManager/promptRenderer.js.map +1 -1
  270. package/dist/taskManager/reviewHook.d.ts +17 -0
  271. package/dist/taskManager/reviewHook.d.ts.map +1 -1
  272. package/dist/taskManager/reviewHook.js +113 -25
  273. package/dist/taskManager/reviewHook.js.map +1 -1
  274. package/dist/types/autoRun.d.ts +125 -0
  275. package/dist/types/autoRun.d.ts.map +1 -0
  276. package/dist/types/autoRun.js +2 -0
  277. package/dist/types/autoRun.js.map +1 -0
  278. package/dist/types/executor.d.ts +118 -0
  279. package/dist/types/executor.d.ts.map +1 -0
  280. package/dist/types/executor.js +17 -0
  281. package/dist/types/executor.js.map +1 -0
  282. package/dist/types/graph.d.ts +100 -0
  283. package/dist/types/graph.d.ts.map +1 -0
  284. package/dist/types/graph.js +2 -0
  285. package/dist/types/graph.js.map +1 -0
  286. package/dist/types/manifest.d.ts +86 -0
  287. package/dist/types/manifest.d.ts.map +1 -0
  288. package/dist/types/manifest.js +6 -0
  289. package/dist/types/manifest.js.map +1 -0
  290. package/dist/types/packageFiles.d.ts +26 -0
  291. package/dist/types/packageFiles.d.ts.map +1 -0
  292. package/dist/types/packageFiles.js +2 -0
  293. package/dist/types/packageFiles.js.map +1 -0
  294. package/dist/types/results.d.ts +24 -0
  295. package/dist/types/results.d.ts.map +1 -0
  296. package/dist/types/results.js +4 -0
  297. package/dist/types/results.js.map +1 -0
  298. package/dist/types/state.d.ts +38 -0
  299. package/dist/types/state.d.ts.map +1 -0
  300. package/dist/types/state.js +5 -0
  301. package/dist/types/state.js.map +1 -0
  302. package/dist/types/taskManager.d.ts +259 -0
  303. package/dist/types/taskManager.d.ts.map +1 -0
  304. package/dist/types/taskManager.js +2 -0
  305. package/dist/types/taskManager.js.map +1 -0
  306. package/dist/types/validation.d.ts +11 -0
  307. package/dist/types/validation.d.ts.map +1 -0
  308. package/dist/types/validation.js +2 -0
  309. package/dist/types/validation.js.map +1 -0
  310. package/dist/types/workspace.d.ts +55 -0
  311. package/dist/types/workspace.d.ts.map +1 -0
  312. package/dist/types/workspace.js +2 -0
  313. package/dist/types/workspace.js.map +1 -0
  314. package/dist/types.d.ts +10 -775
  315. package/dist/types.d.ts.map +1 -1
  316. package/dist/types.js +10 -10
  317. package/dist/types.js.map +1 -1
  318. package/dist/validatePackage.d.ts.map +1 -1
  319. package/dist/validatePackage.js +1 -1
  320. package/dist/validatePackage.js.map +1 -1
  321. package/dist/validation/desktopLayoutValidation.d.ts +6 -0
  322. package/dist/validation/desktopLayoutValidation.d.ts.map +1 -0
  323. package/dist/validation/desktopLayoutValidation.js +154 -0
  324. package/dist/validation/desktopLayoutValidation.js.map +1 -0
  325. package/package.json +2 -2
@@ -0,0 +1,809 @@
1
+ import { buildPlanPackageManifestChangeMutation, buildPlanPackageGraphMutation, writePromptSideEffects } from "../graph/mutation.js";
2
+ import { buildPlanPackageBlockFieldEditMutation, buildPlanPackageTaskFieldEditMutation } from "../graph/fieldEditMutation.js";
3
+ import { parseBlockRef } from "../graph/compileTaskGraph.js";
4
+ import { defaultPlanGraphCommandDependencies } from "./adapters.js";
5
+ import { stableJson } from "./hash.js";
6
+ import { applyProjectGraphHistoryCommand, executeProjectGraphCommand, isProjectGraphCommand } from "./projectGraphCommand.js";
7
+ import { emptyAffectedRefs } from "./commands.js";
8
+ function diagnostic(code, message, path) {
9
+ return { code, message, path };
10
+ }
11
+ function fail(options) {
12
+ return {
13
+ ok: false,
14
+ command: options.command,
15
+ graphVersion: options.graphVersion,
16
+ packageFingerprint: options.packageFingerprint,
17
+ affected: emptyAffectedRefs(),
18
+ changedPaths: [],
19
+ diagnostics: options.diagnostics
20
+ };
21
+ }
22
+ function sameEdge(left, right) {
23
+ return left.from === right.from && left.to === right.to && left.type === right.type;
24
+ }
25
+ function taskFromManifest(manifest, taskId) {
26
+ return manifest.nodes.find((node) => node.type === "task" && node.id === taskId);
27
+ }
28
+ function blockFromManifest(manifest, blockRef) {
29
+ const { taskId, blockId } = parseBlockRef(blockRef);
30
+ const task = taskFromManifest(manifest, taskId);
31
+ const block = task?.blocks.find((candidate) => candidate.id === blockId);
32
+ return task && block ? { task, block } : undefined;
33
+ }
34
+ function promptMarkdown(loaded, packagePath) {
35
+ return loaded.promptMarkdownByPath.get(packagePath);
36
+ }
37
+ function readTaskSnapshot(loaded, taskId) {
38
+ const task = taskFromManifest(loaded.manifest, taskId);
39
+ if (!task) {
40
+ return diagnostic("task_missing", `Task '${taskId}' does not exist.`, taskId);
41
+ }
42
+ const insertIndex = loaded.manifest.nodes.findIndex((node) => node.type === "task" && node.id === taskId);
43
+ const taskPromptMarkdown = promptMarkdown(loaded, task.prompt);
44
+ if (taskPromptMarkdown === undefined) {
45
+ return diagnostic("prompt_missing", `Prompt '${task.prompt}' is not indexed.`, task.prompt);
46
+ }
47
+ const blockPromptMarkdown = [];
48
+ for (const block of task.blocks) {
49
+ const markdown = promptMarkdown(loaded, block.prompt);
50
+ if (markdown === undefined) {
51
+ return diagnostic("prompt_missing", `Prompt '${block.prompt}' is not indexed.`, block.prompt);
52
+ }
53
+ blockPromptMarkdown.push({ blockId: block.id, markdown });
54
+ }
55
+ return {
56
+ task: structuredClone(task),
57
+ taskPromptMarkdown,
58
+ blockPromptMarkdown,
59
+ insertIndex: insertIndex >= 0 ? insertIndex : null,
60
+ affectedTaskEdges: loaded.manifest.edges.filter((edge) => edge.from === taskId || edge.to === taskId).map((edge) => structuredClone(edge))
61
+ };
62
+ }
63
+ function readBlockSnapshot(loaded, blockRef) {
64
+ const current = blockFromManifest(loaded.manifest, blockRef);
65
+ if (!current) {
66
+ return diagnostic("block_missing", `Block '${blockRef}' does not exist.`, blockRef);
67
+ }
68
+ const { blockId } = parseBlockRef(blockRef);
69
+ const insertIndex = current.task.blocks.findIndex((candidate) => candidate.id === blockId);
70
+ const markdown = promptMarkdown(loaded, current.block.prompt);
71
+ if (markdown === undefined) {
72
+ return diagnostic("prompt_missing", `Prompt '${current.block.prompt}' is not indexed.`, current.block.prompt);
73
+ }
74
+ return {
75
+ taskId: current.task.id,
76
+ block: structuredClone(current.block),
77
+ promptMarkdown: markdown,
78
+ insertIndex: insertIndex >= 0 ? insertIndex : null,
79
+ affectedDependsOn: current.task.blocks
80
+ .filter((block) => block.depends_on.includes(blockId))
81
+ .map((block) => ({
82
+ blockRef: `${current.task.id}#${block.id}`,
83
+ dependsOn: [...block.depends_on]
84
+ }))
85
+ };
86
+ }
87
+ function commandPromptHash(loaded, command) {
88
+ if (command.type === "updateTaskPrompt" || (command.type === "updateTaskFields" && command.fields.promptMarkdown !== undefined)) {
89
+ return loaded.graph.tasks.get(command.taskId)?.promptRef.contentHash;
90
+ }
91
+ if (command.type === "updateBlockPrompt" || (command.type === "updateBlockFields" && command.fields.promptMarkdown !== undefined)) {
92
+ return loaded.graph.blocks.get(command.blockRef)?.promptRef.contentHash;
93
+ }
94
+ return undefined;
95
+ }
96
+ function commandBasePromptHash(command) {
97
+ if (command.type === "updateTaskPrompt" || command.type === "updateBlockPrompt") {
98
+ return command.basePromptHash;
99
+ }
100
+ if (command.type === "updateTaskFields" || command.type === "updateBlockFields") {
101
+ return command.fields.basePromptHash;
102
+ }
103
+ return undefined;
104
+ }
105
+ function commandPromptTarget(command) {
106
+ if (command.type === "updateTaskPrompt" || (command.type === "updateTaskFields" && command.fields.promptMarkdown !== undefined)) {
107
+ return command.taskId;
108
+ }
109
+ if (command.type === "updateBlockPrompt" || (command.type === "updateBlockFields" && command.fields.promptMarkdown !== undefined)) {
110
+ return command.blockRef;
111
+ }
112
+ return null;
113
+ }
114
+ function validateBaseVersion(loaded, command) {
115
+ if (!command.baseGraphVersion || command.baseGraphVersion === loaded.graph.graphVersion) {
116
+ return null;
117
+ }
118
+ const promptTarget = commandPromptTarget(command);
119
+ if (promptTarget) {
120
+ const currentPromptHash = commandPromptHash(loaded, command);
121
+ const basePromptHash = commandBasePromptHash(command);
122
+ if (basePromptHash && currentPromptHash === basePromptHash) {
123
+ return null;
124
+ }
125
+ return diagnostic("graph_version_conflict", "Prompt changed after the command base graph version; refusing to overwrite newer prompt content.", promptTarget);
126
+ }
127
+ return diagnostic("graph_version_conflict", "Plan graph changed after the command base graph version; re-read the graph before applying this structural command.");
128
+ }
129
+ function validateDependencyCommand(manifest, command) {
130
+ if (command.type !== "addTaskDependency" && command.type !== "removeTaskDependency" && command.type !== "reconnectTaskDependency") {
131
+ return null;
132
+ }
133
+ const fromTaskIds = command.type === "reconnectTaskDependency" ? [command.fromTaskId, command.newFromTaskId ?? command.fromTaskId] : [command.fromTaskId];
134
+ const toTaskIds = command.type === "reconnectTaskDependency" ? [command.oldToTaskId, command.newToTaskId] : [command.toTaskId];
135
+ for (const fromTaskId of fromTaskIds) {
136
+ if (!taskFromManifest(manifest, fromTaskId)) {
137
+ return diagnostic("task_missing", `Task '${fromTaskId}' does not exist.`, fromTaskId);
138
+ }
139
+ }
140
+ for (const toTaskId of toTaskIds) {
141
+ if (!taskFromManifest(manifest, toTaskId)) {
142
+ return diagnostic("task_missing", `Task '${toTaskId}' does not exist.`, toTaskId);
143
+ }
144
+ }
145
+ return null;
146
+ }
147
+ function dependencyEdge(fromTaskId, toTaskId) {
148
+ return { from: fromTaskId, to: toTaskId, type: "depends_on" };
149
+ }
150
+ function reconnectDependencyMutation(manifest, command) {
151
+ const oldEdge = dependencyEdge(command.fromTaskId, command.oldToTaskId);
152
+ const newEdge = dependencyEdge(command.newFromTaskId ?? command.fromTaskId, command.newToTaskId);
153
+ if (sameEdge(oldEdge, newEdge)) {
154
+ return buildPlanPackageManifestChangeMutation(manifest, manifest, { affectedTasks: [command.fromTaskId] });
155
+ }
156
+ if (!manifest.edges.some((edge) => sameEdge(edge, oldEdge))) {
157
+ return diagnostic("edge_missing", "Task dependency edge does not exist.", "edges");
158
+ }
159
+ if (manifest.edges.some((edge) => sameEdge(edge, newEdge))) {
160
+ return diagnostic("edge_duplicate", "Task dependency edge already exists.", "edges");
161
+ }
162
+ return buildPlanPackageManifestChangeMutation(manifest, {
163
+ ...manifest,
164
+ edges: [...manifest.edges.filter((edge) => !sameEdge(edge, oldEdge)), newEdge]
165
+ });
166
+ }
167
+ function mutationForCommand(loaded, command) {
168
+ const baseVersionDiagnostic = validateBaseVersion(loaded, command);
169
+ if (baseVersionDiagnostic) {
170
+ return baseVersionDiagnostic;
171
+ }
172
+ const dependencyDiagnostic = validateDependencyCommand(loaded.manifest, command);
173
+ if (dependencyDiagnostic) {
174
+ return dependencyDiagnostic;
175
+ }
176
+ if (command.type === "addTaskDependency") {
177
+ const edge = dependencyEdge(command.fromTaskId, command.toTaskId);
178
+ if (loaded.manifest.edges.some((candidate) => sameEdge(candidate, edge))) {
179
+ return diagnostic("edge_duplicate", "Task dependency edge already exists.", "edges");
180
+ }
181
+ return buildPlanPackageGraphMutation(loaded.manifest, { kind: "addEdge", edge });
182
+ }
183
+ if (command.type === "removeTaskDependency") {
184
+ const edge = dependencyEdge(command.fromTaskId, command.toTaskId);
185
+ if (!loaded.manifest.edges.some((candidate) => sameEdge(candidate, edge))) {
186
+ return diagnostic("edge_missing", "Task dependency edge does not exist.", "edges");
187
+ }
188
+ return buildPlanPackageGraphMutation(loaded.manifest, { kind: "removeEdge", edge });
189
+ }
190
+ if (command.type === "reconnectTaskDependency") {
191
+ return reconnectDependencyMutation(loaded.manifest, command);
192
+ }
193
+ if (command.type === "updateTaskPrompt") {
194
+ return buildPlanPackageTaskFieldEditMutation(loaded.manifest, {
195
+ taskId: command.taskId,
196
+ promptMarkdown: command.promptMarkdown
197
+ });
198
+ }
199
+ if (command.type === "updateBlockPrompt") {
200
+ return buildPlanPackageBlockFieldEditMutation(loaded.manifest, {
201
+ blockRef: command.blockRef,
202
+ promptMarkdown: command.promptMarkdown
203
+ });
204
+ }
205
+ if (command.type === "updateTaskFields") {
206
+ return buildPlanPackageTaskFieldEditMutation(loaded.manifest, {
207
+ taskId: command.taskId,
208
+ title: command.fields.title,
209
+ promptMarkdown: command.fields.promptMarkdown,
210
+ executor: command.fields.executor,
211
+ acceptance: command.fields.acceptance
212
+ });
213
+ }
214
+ if (command.type === "updateBlockFields") {
215
+ return buildPlanPackageBlockFieldEditMutation(loaded.manifest, {
216
+ blockRef: command.blockRef,
217
+ title: command.fields.title,
218
+ promptMarkdown: command.fields.promptMarkdown,
219
+ executor: command.fields.executor,
220
+ dependsOn: command.fields.dependsOn,
221
+ parallelSafe: command.fields.parallelSafe,
222
+ parallelLocks: command.fields.parallelLocks,
223
+ reviewRequired: command.fields.reviewRequired,
224
+ maxFeedbackCycles: command.fields.maxFeedbackCycles,
225
+ reviewHook: command.fields.reviewHook
226
+ });
227
+ }
228
+ if (command.type === "addTask" || command.type === "restoreTask") {
229
+ if (taskFromManifest(loaded.manifest, command.snapshot.task.id)) {
230
+ return diagnostic("task_duplicate", `Task '${command.snapshot.task.id}' already exists.`, command.snapshot.task.id);
231
+ }
232
+ const addTaskMutation = buildPlanPackageGraphMutation(loaded.manifest, {
233
+ kind: "addTaskNode",
234
+ node: command.snapshot.task,
235
+ taskPromptMarkdown: command.snapshot.taskPromptMarkdown,
236
+ blockPromptMarkdown: command.snapshot.blockPromptMarkdown
237
+ });
238
+ if (command.type !== "restoreTask") {
239
+ return addTaskMutation;
240
+ }
241
+ const insertIndex = command.snapshot.insertIndex === null
242
+ ? loaded.manifest.nodes.length
243
+ : Math.max(0, Math.min(command.snapshot.insertIndex, loaded.manifest.nodes.length));
244
+ const existingEdges = new Set(loaded.manifest.edges.map((edge) => `${edge.type}:${edge.from}:${edge.to}`));
245
+ const restoredEdges = command.snapshot.affectedTaskEdges.filter((edge) => !existingEdges.has(`${edge.type}:${edge.from}:${edge.to}`));
246
+ return buildPlanPackageManifestChangeMutation(loaded.manifest, {
247
+ ...loaded.manifest,
248
+ nodes: [
249
+ ...loaded.manifest.nodes.slice(0, insertIndex),
250
+ command.snapshot.task,
251
+ ...loaded.manifest.nodes.slice(insertIndex)
252
+ ],
253
+ edges: [...loaded.manifest.edges, ...restoredEdges]
254
+ }, { affectedTasks: [...addTaskMutation.affectedTasks, command.snapshot.task.id], sideEffects: addTaskMutation.sideEffects });
255
+ }
256
+ if (command.type === "removeTask") {
257
+ if (!taskFromManifest(loaded.manifest, command.taskId)) {
258
+ return diagnostic("task_missing", `Task '${command.taskId}' does not exist.`, command.taskId);
259
+ }
260
+ return buildPlanPackageGraphMutation(loaded.manifest, {
261
+ kind: "removeNode",
262
+ nodeId: command.taskId,
263
+ removeTaskDirectory: true
264
+ });
265
+ }
266
+ if (command.type === "addBlock" || command.type === "restoreBlock") {
267
+ const task = taskFromManifest(loaded.manifest, command.snapshot.taskId);
268
+ if (!task) {
269
+ return diagnostic("task_missing", `Task '${command.snapshot.taskId}' does not exist.`, command.snapshot.taskId);
270
+ }
271
+ if (task.blocks.some((block) => block.id === command.snapshot.block.id)) {
272
+ return diagnostic("block_duplicate", `Block '${command.snapshot.taskId}#${command.snapshot.block.id}' already exists.`, command.snapshot.block.id);
273
+ }
274
+ if (command.type === "restoreBlock") {
275
+ const insertIndex = command.snapshot.insertIndex === null
276
+ ? task.blocks.length
277
+ : Math.max(0, Math.min(command.snapshot.insertIndex, task.blocks.length));
278
+ const blocksWithRestoredBlock = [
279
+ ...task.blocks.slice(0, insertIndex),
280
+ command.snapshot.block,
281
+ ...task.blocks.slice(insertIndex)
282
+ ];
283
+ const nextTask = {
284
+ ...task,
285
+ blocks: blocksWithRestoredBlock.map((block) => {
286
+ const ref = `${task.id}#${block.id}`;
287
+ const affected = command.snapshot.affectedDependsOn.find((item) => item.blockRef === ref);
288
+ return affected ? { ...block, depends_on: [...affected.dependsOn] } : block;
289
+ })
290
+ };
291
+ return buildPlanPackageManifestChangeMutation(loaded.manifest, {
292
+ ...loaded.manifest,
293
+ nodes: loaded.manifest.nodes.map((node) => (node.type === "task" && node.id === task.id ? nextTask : node))
294
+ }, { affectedTasks: [task.id], sideEffects: writePromptSideEffects(command.snapshot.block.prompt, command.snapshot.promptMarkdown) });
295
+ }
296
+ return buildPlanPackageGraphMutation(loaded.manifest, {
297
+ kind: "addBlock",
298
+ taskId: command.snapshot.taskId,
299
+ block: command.snapshot.block,
300
+ promptMarkdown: command.snapshot.promptMarkdown
301
+ });
302
+ }
303
+ if (command.type === "removeBlock") {
304
+ if (!blockFromManifest(loaded.manifest, command.blockRef)) {
305
+ return diagnostic("block_missing", `Block '${command.blockRef}' does not exist.`, command.blockRef);
306
+ }
307
+ return buildPlanPackageGraphMutation(loaded.manifest, { kind: "removeBlock", blockRef: command.blockRef });
308
+ }
309
+ if (command.type === "updateReviewPipeline") {
310
+ const task = taskFromManifest(loaded.manifest, command.taskId);
311
+ if (!task) {
312
+ return diagnostic("task_missing", `Task '${command.taskId}' does not exist.`, command.taskId);
313
+ }
314
+ const reviewPromptPaths = new Set(command.reviewBlocks.map((block) => block.prompt));
315
+ const removedPrompts = task.blocks
316
+ .filter((block) => block.type === "review" && !reviewPromptPaths.has(block.prompt))
317
+ .map((block) => ({ kind: "removePrompt", packagePath: block.prompt }));
318
+ const promptMarkdownByBlockId = new Map(command.promptMarkdownByBlockId.map((item) => [item.blockId, item.markdown]));
319
+ const sideEffects = [
320
+ ...removedPrompts,
321
+ ...command.reviewBlocks.flatMap((block) => writePromptSideEffects(block.prompt, promptMarkdownByBlockId.get(block.id) ?? ""))
322
+ ];
323
+ const nextTask = {
324
+ ...task,
325
+ blocks: [...task.blocks.filter((block) => block.type !== "review"), ...command.reviewBlocks]
326
+ };
327
+ return buildPlanPackageManifestChangeMutation(loaded.manifest, {
328
+ ...loaded.manifest,
329
+ review: { ...command.packageDefaults },
330
+ nodes: loaded.manifest.nodes.map((node) => (node.type === "task" && node.id === command.taskId ? nextTask : node))
331
+ }, { affectedTasks: [command.taskId], sideEffects });
332
+ }
333
+ return diagnostic("layout_command_not_handled", "PlanGraph layout commands are defined here but still written by the existing layout API.");
334
+ }
335
+ function inverseForCommand(loaded, command) {
336
+ if (command.type === "addTaskDependency") {
337
+ return { type: "removeTaskDependency", fromTaskId: command.fromTaskId, toTaskId: command.toTaskId };
338
+ }
339
+ if (command.type === "removeTaskDependency") {
340
+ return { type: "addTaskDependency", fromTaskId: command.fromTaskId, toTaskId: command.toTaskId };
341
+ }
342
+ if (command.type === "reconnectTaskDependency") {
343
+ return {
344
+ type: "reconnectTaskDependency",
345
+ fromTaskId: command.newFromTaskId ?? command.fromTaskId,
346
+ oldToTaskId: command.newToTaskId,
347
+ newFromTaskId: command.fromTaskId,
348
+ newToTaskId: command.oldToTaskId
349
+ };
350
+ }
351
+ if (command.type === "updateTaskPrompt") {
352
+ const task = taskFromManifest(loaded.manifest, command.taskId);
353
+ const markdown = task ? promptMarkdown(loaded, task.prompt) : undefined;
354
+ return markdown === undefined
355
+ ? diagnostic("prompt_missing", `Prompt for task '${command.taskId}' is not indexed.`, command.taskId)
356
+ : {
357
+ type: "updateTaskPrompt",
358
+ taskId: command.taskId,
359
+ promptMarkdown: markdown
360
+ };
361
+ }
362
+ if (command.type === "updateBlockPrompt") {
363
+ const current = blockFromManifest(loaded.manifest, command.blockRef);
364
+ const markdown = current ? promptMarkdown(loaded, current.block.prompt) : undefined;
365
+ return markdown === undefined
366
+ ? diagnostic("prompt_missing", `Prompt for block '${command.blockRef}' is not indexed.`, command.blockRef)
367
+ : {
368
+ type: "updateBlockPrompt",
369
+ blockRef: command.blockRef,
370
+ promptMarkdown: markdown
371
+ };
372
+ }
373
+ if (command.type === "updateTaskFields") {
374
+ const task = taskFromManifest(loaded.manifest, command.taskId);
375
+ if (!task) {
376
+ return diagnostic("task_missing", `Task '${command.taskId}' does not exist.`, command.taskId);
377
+ }
378
+ const fields = {};
379
+ if (command.fields.title !== undefined) {
380
+ fields.title = task.title;
381
+ }
382
+ if (command.fields.promptMarkdown !== undefined) {
383
+ const markdown = promptMarkdown(loaded, task.prompt);
384
+ if (markdown === undefined) {
385
+ return diagnostic("prompt_missing", `Prompt for task '${command.taskId}' is not indexed.`, command.taskId);
386
+ }
387
+ fields.promptMarkdown = markdown;
388
+ }
389
+ if (command.fields.executor !== undefined) {
390
+ fields.executor = task.executor ?? null;
391
+ }
392
+ if (command.fields.acceptance !== undefined) {
393
+ fields.acceptance = [...task.acceptance];
394
+ }
395
+ const inverse = { type: "updateTaskFields", taskId: command.taskId, fields };
396
+ if (command.fields.executor === undefined) {
397
+ return inverse;
398
+ }
399
+ const blockExecutorRestores = task.blocks
400
+ .filter((block) => block.executor !== undefined)
401
+ .map((block) => ({
402
+ type: "updateBlockFields",
403
+ blockRef: `${task.id}#${block.id}`,
404
+ fields: { executor: block.executor ?? null }
405
+ }));
406
+ return blockExecutorRestores.length === 0 ? inverse : [inverse, ...blockExecutorRestores];
407
+ }
408
+ if (command.type === "updateBlockFields") {
409
+ const current = blockFromManifest(loaded.manifest, command.blockRef);
410
+ if (!current) {
411
+ return diagnostic("block_missing", `Block '${command.blockRef}' does not exist.`, command.blockRef);
412
+ }
413
+ const fields = {};
414
+ if (command.fields.title !== undefined) {
415
+ fields.title = current.block.title;
416
+ }
417
+ if (command.fields.promptMarkdown !== undefined) {
418
+ const markdown = promptMarkdown(loaded, current.block.prompt);
419
+ if (markdown === undefined) {
420
+ return diagnostic("prompt_missing", `Prompt for block '${command.blockRef}' is not indexed.`, command.blockRef);
421
+ }
422
+ fields.promptMarkdown = markdown;
423
+ }
424
+ if (command.fields.executor !== undefined) {
425
+ fields.executor = current.block.executor ?? null;
426
+ }
427
+ if (command.fields.dependsOn !== undefined) {
428
+ fields.dependsOn = [...current.block.depends_on];
429
+ }
430
+ if (current.block.type === "implementation") {
431
+ if (command.fields.parallelSafe !== undefined) {
432
+ fields.parallelSafe = current.block.parallel.safe;
433
+ }
434
+ if (command.fields.parallelLocks !== undefined) {
435
+ fields.parallelLocks = [...current.block.parallel.locks];
436
+ }
437
+ }
438
+ else {
439
+ if (command.fields.reviewRequired !== undefined) {
440
+ fields.reviewRequired = current.block.review.required;
441
+ }
442
+ if (command.fields.maxFeedbackCycles !== undefined) {
443
+ fields.maxFeedbackCycles = current.block.review.maxFeedbackCycles;
444
+ }
445
+ if (command.fields.reviewHook !== undefined) {
446
+ fields.reviewHook = current.block.review.hook;
447
+ }
448
+ }
449
+ return { type: "updateBlockFields", blockRef: command.blockRef, fields };
450
+ }
451
+ if (command.type === "addTask" || command.type === "restoreTask") {
452
+ return { type: "removeTask", taskId: command.snapshot.task.id };
453
+ }
454
+ if (command.type === "removeTask") {
455
+ return snapshotOrDiagnostic(readTaskSnapshot(loaded, command.taskId), (snapshot) => ({
456
+ type: "restoreTask",
457
+ snapshot: { ...snapshot, layoutNode: command.layoutNode ?? snapshot.layoutNode ?? null }
458
+ }));
459
+ }
460
+ if (command.type === "addBlock" || command.type === "restoreBlock") {
461
+ return { type: "removeBlock", blockRef: `${command.snapshot.taskId}#${command.snapshot.block.id}` };
462
+ }
463
+ if (command.type === "removeBlock") {
464
+ return snapshotOrDiagnostic(readBlockSnapshot(loaded, command.blockRef), (snapshot) => ({ type: "restoreBlock", snapshot }));
465
+ }
466
+ if (command.type === "updateReviewPipeline") {
467
+ const task = taskFromManifest(loaded.manifest, command.taskId);
468
+ if (!task) {
469
+ return diagnostic("task_missing", `Task '${command.taskId}' does not exist.`, command.taskId);
470
+ }
471
+ const promptMarkdownByBlockId = [];
472
+ for (const block of task.blocks) {
473
+ if (block.type !== "review") {
474
+ continue;
475
+ }
476
+ const markdown = promptMarkdown(loaded, block.prompt);
477
+ if (markdown === undefined) {
478
+ return diagnostic("prompt_missing", `Prompt for block '${command.taskId}#${block.id}' is not indexed.`, block.prompt);
479
+ }
480
+ promptMarkdownByBlockId.push({ blockId: block.id, markdown });
481
+ }
482
+ return {
483
+ type: "updateReviewPipeline",
484
+ taskId: command.taskId,
485
+ packageDefaults: { ...loaded.manifest.review },
486
+ reviewBlocks: task.blocks.filter((block) => block.type === "review").map((block) => structuredClone(block)),
487
+ promptMarkdownByBlockId
488
+ };
489
+ }
490
+ return diagnostic("layout_command_not_handled", "PlanGraph layout commands are not undoable here.");
491
+ }
492
+ function snapshotOrDiagnostic(value, build) {
493
+ return isPlanGraphCommandDiagnostic(value) ? value : build(value);
494
+ }
495
+ function isPlanGraphCommandDiagnostic(value) {
496
+ return value !== null && typeof value === "object" && "code" in value && "message" in value;
497
+ }
498
+ function commandTouchedRefs(command, loaded) {
499
+ if (command.type === "addTaskDependency" || command.type === "removeTaskDependency") {
500
+ return { tasks: [command.fromTaskId], blocks: [] };
501
+ }
502
+ if (command.type === "reconnectTaskDependency") {
503
+ return { tasks: [command.fromTaskId, command.newFromTaskId ?? command.fromTaskId], blocks: [] };
504
+ }
505
+ if (command.type === "updateTaskPrompt" || command.type === "updateTaskFields" || command.type === "removeTask") {
506
+ return { tasks: [command.taskId], blocks: [] };
507
+ }
508
+ if (command.type === "updateBlockPrompt" || command.type === "updateBlockFields" || command.type === "removeBlock") {
509
+ const { taskId, blockId } = parseBlockRef(command.blockRef);
510
+ const task = taskFromManifest(loaded.manifest, taskId);
511
+ const dependentBlocks = task?.blocks
512
+ .filter((block) => block.depends_on.includes(blockId))
513
+ .map((block) => `${taskId}#${block.id}`) ?? [];
514
+ return { tasks: [taskId], blocks: [command.blockRef, ...dependentBlocks] };
515
+ }
516
+ if (command.type === "addTask" || command.type === "restoreTask") {
517
+ return { tasks: [command.snapshot.task.id], blocks: command.snapshot.task.blocks.map((block) => `${command.snapshot.task.id}#${block.id}`) };
518
+ }
519
+ if (command.type === "addBlock" || command.type === "restoreBlock") {
520
+ return {
521
+ tasks: [command.snapshot.taskId],
522
+ blocks: [`${command.snapshot.taskId}#${command.snapshot.block.id}`, ...command.snapshot.affectedDependsOn.map((item) => item.blockRef)]
523
+ };
524
+ }
525
+ if (command.type === "updateReviewPipeline") {
526
+ return {
527
+ tasks: [command.taskId],
528
+ blocks: command.reviewBlocks.map((block) => `${command.taskId}#${block.id}`)
529
+ };
530
+ }
531
+ return { tasks: [], blocks: [] };
532
+ }
533
+ function affectedRefs(command, mutation, loaded) {
534
+ const touched = commandTouchedRefs(command, loaded);
535
+ const prompts = mutation.sideEffects
536
+ .filter((sideEffect) => sideEffect.kind === "writePrompt" || sideEffect.kind === "removePrompt")
537
+ .map((sideEffect) => sideEffect.packagePath);
538
+ return {
539
+ canvases: [],
540
+ tasks: [...new Set([...mutation.affectedTasks, ...touched.tasks])],
541
+ blocks: [...new Set(touched.blocks)],
542
+ prompts: [...new Set(prompts)],
543
+ packageFiles: [...new Set([...(mutation.nextManifest ? ["manifest.json"] : []), ...prompts])]
544
+ };
545
+ }
546
+ function changedPaths(repository, loaded, affected) {
547
+ return affected.packageFiles.map((path) => repository.packageFilePath(loaded, path));
548
+ }
549
+ function isNoopMutation(loaded, mutation) {
550
+ return mutation.sideEffects.length === 0 && JSON.stringify(mutation.nextManifest) === JSON.stringify(loaded.manifest);
551
+ }
552
+ function isDiagnostic(value) {
553
+ return isPlanGraphCommandDiagnostic(value);
554
+ }
555
+ async function executeLayoutCommand(options, dependencies) {
556
+ const command = options.command;
557
+ if (command.type !== "updateLayout") {
558
+ throw new Error("executeLayoutCommand requires an updateLayout command.");
559
+ }
560
+ const recordOperation = options.recordOperation ?? true;
561
+ const loaded = await dependencies.repository.load(options.projectRoot);
562
+ let previousLayout;
563
+ try {
564
+ previousLayout = await dependencies.layoutStore.read(options.projectRoot, command.layoutScope);
565
+ }
566
+ catch (caught) {
567
+ return fail({
568
+ command,
569
+ diagnostics: [diagnostic("layout_read_failed", caught instanceof Error ? caught.message : String(caught), command.layoutScope)],
570
+ graphVersion: loaded.graph.graphVersion,
571
+ packageFingerprint: loaded.graph.packageFingerprint
572
+ });
573
+ }
574
+ const inverse = {
575
+ type: "updateLayout",
576
+ layoutScope: command.layoutScope,
577
+ layout: previousLayout
578
+ };
579
+ if (stableJson(previousLayout) === stableJson(command.layout)) {
580
+ return {
581
+ ok: true,
582
+ workspaceRef: loaded.workspace,
583
+ graphVersion: loaded.graph.graphVersion,
584
+ packageFingerprint: loaded.graph.packageFingerprint,
585
+ command,
586
+ inverse,
587
+ affected: emptyAffectedRefs(),
588
+ changedPaths: [],
589
+ diagnostics: []
590
+ };
591
+ }
592
+ try {
593
+ await dependencies.layoutStore.write(options.projectRoot, command.layoutScope, command.layout);
594
+ }
595
+ catch (caught) {
596
+ return fail({
597
+ command,
598
+ diagnostics: [diagnostic("layout_write_failed", caught instanceof Error ? caught.message : String(caught), command.layoutScope)],
599
+ graphVersion: loaded.graph.graphVersion,
600
+ packageFingerprint: loaded.graph.packageFingerprint
601
+ });
602
+ }
603
+ const store = await dependencies.createIndexStore({ projectRoot: options.projectRoot, indexPath: options.indexPath });
604
+ const affected = {
605
+ ...emptyAffectedRefs(),
606
+ packageFiles: command.layoutScope === "desktop" ? ["desktop/layout.json"] : ["desktop/canvases.json"]
607
+ };
608
+ const result = {
609
+ ok: true,
610
+ workspaceRef: loaded.workspace,
611
+ graphVersion: loaded.graph.graphVersion,
612
+ packageFingerprint: loaded.graph.packageFingerprint,
613
+ command,
614
+ inverse,
615
+ affected,
616
+ changedPaths: affected.packageFiles,
617
+ diagnostics: []
618
+ };
619
+ if (recordOperation) {
620
+ result.operationId = await store.log.append({
621
+ workspaceRef: loaded.workspace,
622
+ graphVersionBefore: loaded.graph.graphVersion,
623
+ graphVersionAfter: loaded.graph.graphVersion,
624
+ command,
625
+ inverse,
626
+ affected
627
+ });
628
+ }
629
+ return result;
630
+ }
631
+ export async function executePlanGraphCommand(options) {
632
+ const dependencies = {
633
+ ...defaultPlanGraphCommandDependencies,
634
+ ...options.dependencies
635
+ };
636
+ if (isProjectGraphCommand(options.command)) {
637
+ return executeProjectGraphCommand({
638
+ projectRoot: options.projectRoot,
639
+ command: options.command,
640
+ indexPath: options.indexPath,
641
+ recordOperation: options.recordOperation
642
+ }, dependencies);
643
+ }
644
+ if (options.command.type === "updateLayout") {
645
+ return executeLayoutCommand(options, dependencies);
646
+ }
647
+ const recordOperation = options.recordOperation ?? true;
648
+ const loaded = await dependencies.repository.load(options.projectRoot);
649
+ const inverse = inverseForCommand(loaded, options.command);
650
+ if (isDiagnostic(inverse)) {
651
+ return fail({
652
+ command: options.command,
653
+ diagnostics: [inverse],
654
+ graphVersion: loaded.graph.graphVersion,
655
+ packageFingerprint: loaded.graph.packageFingerprint
656
+ });
657
+ }
658
+ let mutation;
659
+ try {
660
+ mutation = mutationForCommand(loaded, options.command);
661
+ }
662
+ catch (caught) {
663
+ return fail({
664
+ command: options.command,
665
+ diagnostics: [
666
+ diagnostic("command_validation_failed", caught instanceof Error ? caught.message : String(caught))
667
+ ],
668
+ graphVersion: loaded.graph.graphVersion,
669
+ packageFingerprint: loaded.graph.packageFingerprint
670
+ });
671
+ }
672
+ if (isDiagnostic(mutation)) {
673
+ return fail({
674
+ command: options.command,
675
+ diagnostics: [mutation],
676
+ graphVersion: loaded.graph.graphVersion,
677
+ packageFingerprint: loaded.graph.packageFingerprint
678
+ });
679
+ }
680
+ if (isNoopMutation(loaded, mutation)) {
681
+ return {
682
+ ok: true,
683
+ workspaceRef: loaded.workspace,
684
+ graphVersion: loaded.graph.graphVersion,
685
+ packageFingerprint: loaded.graph.packageFingerprint,
686
+ command: options.command,
687
+ inverse,
688
+ affected: emptyAffectedRefs(),
689
+ changedPaths: [],
690
+ diagnostics: []
691
+ };
692
+ }
693
+ const commitDiagnostics = await dependencies.repository.commit({ projectRoot: options.projectRoot, mutation });
694
+ if (commitDiagnostics.length > 0) {
695
+ return fail({
696
+ command: options.command,
697
+ diagnostics: commitDiagnostics,
698
+ graphVersion: loaded.graph.graphVersion,
699
+ packageFingerprint: loaded.graph.packageFingerprint
700
+ });
701
+ }
702
+ const store = await dependencies.createIndexStore({ projectRoot: options.projectRoot, indexPath: options.indexPath });
703
+ const graph = await store.rebuild();
704
+ const affected = affectedRefs(options.command, mutation, loaded);
705
+ const result = {
706
+ ok: true,
707
+ workspaceRef: loaded.workspace,
708
+ graphVersion: graph.graphVersion,
709
+ packageFingerprint: graph.packageFingerprint,
710
+ command: options.command,
711
+ inverse,
712
+ affected,
713
+ changedPaths: changedPaths(dependencies.repository, loaded, affected),
714
+ diagnostics: []
715
+ };
716
+ if (recordOperation) {
717
+ result.operationId = await store.log.append({
718
+ workspaceRef: loaded.workspace,
719
+ graphVersionBefore: loaded.graph.graphVersion,
720
+ graphVersionAfter: graph.graphVersion,
721
+ command: options.command,
722
+ inverse,
723
+ affected
724
+ });
725
+ }
726
+ return result;
727
+ }
728
+ async function applyHistoryCommand(options, command, expectedGraphVersion, workspaceRef) {
729
+ const dependencies = {
730
+ ...defaultPlanGraphCommandDependencies,
731
+ ...options.dependencies
732
+ };
733
+ if (!Array.isArray(command) && isProjectGraphCommand(command)) {
734
+ return applyProjectGraphHistoryCommand({ indexPath: options.indexPath }, dependencies, command, expectedGraphVersion, workspaceRef);
735
+ }
736
+ const loaded = await dependencies.repository.load(workspaceRef);
737
+ if (loaded.graph.graphVersion !== expectedGraphVersion) {
738
+ return fail({
739
+ command: Array.isArray(command) ? command[0] ?? { type: "updateLayout", layoutScope: "desktop", layout: null } : command,
740
+ diagnostics: [
741
+ diagnostic("graph_version_conflict", "Plan graph changed after this history entry was recorded; refusing to apply stale undo/redo.")
742
+ ],
743
+ graphVersion: loaded.graph.graphVersion,
744
+ packageFingerprint: loaded.graph.packageFingerprint
745
+ });
746
+ }
747
+ const commands = Array.isArray(command) ? command : [command];
748
+ let latest = null;
749
+ for (const item of commands) {
750
+ latest = await executePlanGraphCommand({
751
+ ...options,
752
+ projectRoot: workspaceRef,
753
+ command: commandForHistoryReplay(item),
754
+ recordOperation: false,
755
+ dependencies
756
+ });
757
+ if (!latest.ok) {
758
+ return latest;
759
+ }
760
+ }
761
+ if (!latest) {
762
+ return fail({ command: { type: "updateLayout", layoutScope: "desktop", layout: null }, diagnostics: [diagnostic("history_empty", "No command to apply.")] });
763
+ }
764
+ return latest;
765
+ }
766
+ function commandForHistoryReplay(command) {
767
+ const replayCommand = structuredClone(command);
768
+ delete replayCommand.baseGraphVersion;
769
+ if (replayCommand.type === "updateTaskPrompt" || replayCommand.type === "updateBlockPrompt") {
770
+ delete replayCommand.basePromptHash;
771
+ }
772
+ if (replayCommand.type === "updateTaskFields" || replayCommand.type === "updateBlockFields") {
773
+ delete replayCommand.fields.basePromptHash;
774
+ }
775
+ return replayCommand;
776
+ }
777
+ export async function undoPlanGraphCommand(options) {
778
+ const dependencies = {
779
+ ...defaultPlanGraphCommandDependencies,
780
+ ...options.dependencies
781
+ };
782
+ const store = await dependencies.createIndexStore(options);
783
+ const entry = await store.log.latestUndoable();
784
+ if (!entry) {
785
+ return fail({ command: { type: "updateLayout", layoutScope: "desktop", layout: null }, diagnostics: [diagnostic("history_empty", "No command to undo.")] });
786
+ }
787
+ const result = await applyHistoryCommand(options, entry.inverse, entry.graphVersionAfter, entry.workspaceRef);
788
+ if (result.ok) {
789
+ await store.log.markUndone(entry.id);
790
+ }
791
+ return result;
792
+ }
793
+ export async function redoPlanGraphCommand(options) {
794
+ const dependencies = {
795
+ ...defaultPlanGraphCommandDependencies,
796
+ ...options.dependencies
797
+ };
798
+ const store = await dependencies.createIndexStore(options);
799
+ const entry = await store.log.latestRedoable();
800
+ if (!entry) {
801
+ return fail({ command: { type: "updateLayout", layoutScope: "desktop", layout: null }, diagnostics: [diagnostic("history_empty", "No command to redo.")] });
802
+ }
803
+ const result = await applyHistoryCommand(options, entry.command, entry.graphVersionBefore, entry.workspaceRef);
804
+ if (result.ok) {
805
+ await store.log.markRedone(entry.id);
806
+ }
807
+ return result;
808
+ }
809
+ //# sourceMappingURL=executeCommand.js.map