@langadventurellc/task-trellis-mcp 0.1.0-rc.3 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (316) hide show
  1. package/README.md +357 -39
  2. package/dist/__tests__/e2e/configuration/activation.e2e.test.d.ts +2 -0
  3. package/dist/__tests__/e2e/configuration/activation.e2e.test.d.ts.map +1 -0
  4. package/dist/__tests__/e2e/configuration/activation.e2e.test.js +130 -0
  5. package/dist/__tests__/e2e/configuration/activation.e2e.test.js.map +1 -0
  6. package/dist/__tests__/e2e/configuration/commandLineArgs.e2e.test.d.ts +2 -0
  7. package/dist/__tests__/e2e/configuration/commandLineArgs.e2e.test.d.ts.map +1 -0
  8. package/dist/__tests__/e2e/configuration/commandLineArgs.e2e.test.js +125 -0
  9. package/dist/__tests__/e2e/configuration/commandLineArgs.e2e.test.js.map +1 -0
  10. package/dist/__tests__/e2e/configuration/directorySetup.e2e.test.d.ts +2 -0
  11. package/dist/__tests__/e2e/configuration/directorySetup.e2e.test.d.ts.map +1 -0
  12. package/dist/__tests__/e2e/configuration/directorySetup.e2e.test.js +262 -0
  13. package/dist/__tests__/e2e/configuration/directorySetup.e2e.test.js.map +1 -0
  14. package/dist/__tests__/e2e/configuration/invalidConfig.e2e.test.d.ts +2 -0
  15. package/dist/__tests__/e2e/configuration/invalidConfig.e2e.test.d.ts.map +1 -0
  16. package/dist/__tests__/e2e/configuration/invalidConfig.e2e.test.js +243 -0
  17. package/dist/__tests__/e2e/configuration/invalidConfig.e2e.test.js.map +1 -0
  18. package/dist/__tests__/e2e/configuration/preActivation.e2e.test.d.ts +2 -0
  19. package/dist/__tests__/e2e/configuration/preActivation.e2e.test.d.ts.map +1 -0
  20. package/dist/__tests__/e2e/configuration/preActivation.e2e.test.js +123 -0
  21. package/dist/__tests__/e2e/configuration/preActivation.e2e.test.js.map +1 -0
  22. package/dist/__tests__/e2e/crud/createObject.e2e.test.d.ts +2 -0
  23. package/dist/__tests__/e2e/crud/createObject.e2e.test.d.ts.map +1 -0
  24. package/dist/__tests__/e2e/crud/createObject.e2e.test.js +376 -0
  25. package/dist/__tests__/e2e/crud/createObject.e2e.test.js.map +1 -0
  26. package/dist/__tests__/e2e/crud/deleteObject.e2e.test.d.ts +2 -0
  27. package/dist/__tests__/e2e/crud/deleteObject.e2e.test.d.ts.map +1 -0
  28. package/dist/__tests__/e2e/crud/deleteObject.e2e.test.js +391 -0
  29. package/dist/__tests__/e2e/crud/deleteObject.e2e.test.js.map +1 -0
  30. package/dist/__tests__/e2e/crud/fileValidation.e2e.test.d.ts +2 -0
  31. package/dist/__tests__/e2e/crud/fileValidation.e2e.test.d.ts.map +1 -0
  32. package/dist/__tests__/e2e/crud/fileValidation.e2e.test.js +409 -0
  33. package/dist/__tests__/e2e/crud/fileValidation.e2e.test.js.map +1 -0
  34. package/dist/__tests__/e2e/crud/getObject.e2e.test.d.ts +2 -0
  35. package/dist/__tests__/e2e/crud/getObject.e2e.test.d.ts.map +1 -0
  36. package/dist/__tests__/e2e/crud/getObject.e2e.test.js +447 -0
  37. package/dist/__tests__/e2e/crud/getObject.e2e.test.js.map +1 -0
  38. package/dist/__tests__/e2e/crud/listObjects.e2e.test.d.ts +2 -0
  39. package/dist/__tests__/e2e/crud/listObjects.e2e.test.d.ts.map +1 -0
  40. package/dist/__tests__/e2e/crud/listObjects.e2e.test.js +593 -0
  41. package/dist/__tests__/e2e/crud/listObjects.e2e.test.js.map +1 -0
  42. package/dist/__tests__/e2e/crud/replaceObjectBodyRegex.e2e.test.d.ts +2 -0
  43. package/dist/__tests__/e2e/crud/replaceObjectBodyRegex.e2e.test.d.ts.map +1 -0
  44. package/dist/__tests__/e2e/crud/replaceObjectBodyRegex.e2e.test.js +693 -0
  45. package/dist/__tests__/e2e/crud/replaceObjectBodyRegex.e2e.test.js.map +1 -0
  46. package/dist/__tests__/e2e/crud/updateObject.e2e.test.d.ts +2 -0
  47. package/dist/__tests__/e2e/crud/updateObject.e2e.test.d.ts.map +1 -0
  48. package/dist/__tests__/e2e/crud/updateObject.e2e.test.js +662 -0
  49. package/dist/__tests__/e2e/crud/updateObject.e2e.test.js.map +1 -0
  50. package/dist/__tests__/e2e/infrastructure/client.e2e.test.d.ts +2 -0
  51. package/dist/__tests__/e2e/infrastructure/client.e2e.test.d.ts.map +1 -0
  52. package/dist/__tests__/e2e/infrastructure/client.e2e.test.js +68 -0
  53. package/dist/__tests__/e2e/infrastructure/client.e2e.test.js.map +1 -0
  54. package/dist/__tests__/e2e/infrastructure/server.e2e.test.d.ts +2 -0
  55. package/dist/__tests__/e2e/infrastructure/server.e2e.test.d.ts.map +1 -0
  56. package/dist/__tests__/e2e/infrastructure/server.e2e.test.js +37 -0
  57. package/dist/__tests__/e2e/infrastructure/server.e2e.test.js.map +1 -0
  58. package/dist/__tests__/e2e/utils/HierarchyOptions.d.ts +7 -0
  59. package/dist/__tests__/e2e/utils/HierarchyOptions.d.ts.map +1 -0
  60. package/dist/__tests__/e2e/utils/HierarchyOptions.js +3 -0
  61. package/dist/__tests__/e2e/utils/HierarchyOptions.js.map +1 -0
  62. package/dist/__tests__/e2e/utils/ObjectData.d.ts +17 -0
  63. package/dist/__tests__/e2e/utils/ObjectData.d.ts.map +1 -0
  64. package/dist/__tests__/e2e/utils/ObjectData.js +3 -0
  65. package/dist/__tests__/e2e/utils/ObjectData.js.map +1 -0
  66. package/dist/__tests__/e2e/utils/cleanup.d.ts +10 -0
  67. package/dist/__tests__/e2e/utils/cleanup.d.ts.map +1 -0
  68. package/dist/__tests__/e2e/utils/cleanup.js +99 -0
  69. package/dist/__tests__/e2e/utils/cleanup.js.map +1 -0
  70. package/dist/__tests__/e2e/utils/createObjectContent.d.ts +6 -0
  71. package/dist/__tests__/e2e/utils/createObjectContent.d.ts.map +1 -0
  72. package/dist/__tests__/e2e/utils/createObjectContent.js +34 -0
  73. package/dist/__tests__/e2e/utils/createObjectContent.js.map +1 -0
  74. package/dist/__tests__/e2e/utils/createObjectFile.d.ts +6 -0
  75. package/dist/__tests__/e2e/utils/createObjectFile.d.ts.map +1 -0
  76. package/dist/__tests__/e2e/utils/createObjectFile.js +88 -0
  77. package/dist/__tests__/e2e/utils/createObjectFile.js.map +1 -0
  78. package/dist/__tests__/e2e/utils/fileExists.d.ts +5 -0
  79. package/dist/__tests__/e2e/utils/fileExists.d.ts.map +1 -0
  80. package/dist/__tests__/e2e/utils/fileExists.js +52 -0
  81. package/dist/__tests__/e2e/utils/fileExists.js.map +1 -0
  82. package/dist/__tests__/e2e/utils/folderExists.d.ts +5 -0
  83. package/dist/__tests__/e2e/utils/folderExists.d.ts.map +1 -0
  84. package/dist/__tests__/e2e/utils/folderExists.js +52 -0
  85. package/dist/__tests__/e2e/utils/folderExists.js.map +1 -0
  86. package/dist/__tests__/e2e/utils/index.d.ts +15 -0
  87. package/dist/__tests__/e2e/utils/index.d.ts.map +1 -0
  88. package/dist/__tests__/e2e/utils/index.js +32 -0
  89. package/dist/__tests__/e2e/utils/index.js.map +1 -0
  90. package/dist/__tests__/e2e/utils/mcpTestClient.d.ts +13 -0
  91. package/dist/__tests__/e2e/utils/mcpTestClient.d.ts.map +1 -0
  92. package/dist/__tests__/e2e/utils/mcpTestClient.js +79 -0
  93. package/dist/__tests__/e2e/utils/mcpTestClient.js.map +1 -0
  94. package/dist/__tests__/e2e/utils/parseGetObjectResponse.d.ts +5 -0
  95. package/dist/__tests__/e2e/utils/parseGetObjectResponse.d.ts.map +1 -0
  96. package/dist/__tests__/e2e/utils/parseGetObjectResponse.js +15 -0
  97. package/dist/__tests__/e2e/utils/parseGetObjectResponse.js.map +1 -0
  98. package/dist/__tests__/e2e/utils/parseListObjectsResponse.d.ts +5 -0
  99. package/dist/__tests__/e2e/utils/parseListObjectsResponse.d.ts.map +1 -0
  100. package/dist/__tests__/e2e/utils/parseListObjectsResponse.js +15 -0
  101. package/dist/__tests__/e2e/utils/parseListObjectsResponse.js.map +1 -0
  102. package/dist/__tests__/e2e/utils/parseReplaceObjectBodyRegexResponse.d.ts +10 -0
  103. package/dist/__tests__/e2e/utils/parseReplaceObjectBodyRegexResponse.d.ts.map +1 -0
  104. package/dist/__tests__/e2e/utils/parseReplaceObjectBodyRegexResponse.js +40 -0
  105. package/dist/__tests__/e2e/utils/parseReplaceObjectBodyRegexResponse.js.map +1 -0
  106. package/dist/__tests__/e2e/utils/parseUpdateObjectResponse.d.ts +5 -0
  107. package/dist/__tests__/e2e/utils/parseUpdateObjectResponse.d.ts.map +1 -0
  108. package/dist/__tests__/e2e/utils/parseUpdateObjectResponse.js +15 -0
  109. package/dist/__tests__/e2e/utils/parseUpdateObjectResponse.js.map +1 -0
  110. package/dist/__tests__/e2e/utils/pathExists.d.ts +5 -0
  111. package/dist/__tests__/e2e/utils/pathExists.d.ts.map +1 -0
  112. package/dist/__tests__/e2e/utils/pathExists.js +50 -0
  113. package/dist/__tests__/e2e/utils/pathExists.js.map +1 -0
  114. package/dist/__tests__/e2e/utils/readObjectFile.d.ts +10 -0
  115. package/dist/__tests__/e2e/utils/readObjectFile.d.ts.map +1 -0
  116. package/dist/__tests__/e2e/utils/readObjectFile.js +54 -0
  117. package/dist/__tests__/e2e/utils/readObjectFile.js.map +1 -0
  118. package/dist/__tests__/e2e/utils/serverProcess.d.ts +11 -0
  119. package/dist/__tests__/e2e/utils/serverProcess.d.ts.map +1 -0
  120. package/dist/__tests__/e2e/utils/serverProcess.js +119 -0
  121. package/dist/__tests__/e2e/utils/serverProcess.js.map +1 -0
  122. package/dist/__tests__/e2e/utils/testEnvironment.d.ts +9 -0
  123. package/dist/__tests__/e2e/utils/testEnvironment.d.ts.map +1 -0
  124. package/dist/__tests__/e2e/utils/testEnvironment.js +74 -0
  125. package/dist/__tests__/e2e/utils/testEnvironment.js.map +1 -0
  126. package/dist/__tests__/e2e/workflow/appendLog.e2e.test.d.ts +2 -0
  127. package/dist/__tests__/e2e/workflow/appendLog.e2e.test.d.ts.map +1 -0
  128. package/dist/__tests__/e2e/workflow/appendLog.e2e.test.js +175 -0
  129. package/dist/__tests__/e2e/workflow/appendLog.e2e.test.js.map +1 -0
  130. package/dist/__tests__/e2e/workflow/claimTask.e2e.test.d.ts +2 -0
  131. package/dist/__tests__/e2e/workflow/claimTask.e2e.test.d.ts.map +1 -0
  132. package/dist/__tests__/e2e/workflow/claimTask.e2e.test.js +154 -0
  133. package/dist/__tests__/e2e/workflow/claimTask.e2e.test.js.map +1 -0
  134. package/dist/__tests__/e2e/workflow/completeTask.e2e.test.d.ts +2 -0
  135. package/dist/__tests__/e2e/workflow/completeTask.e2e.test.d.ts.map +1 -0
  136. package/dist/__tests__/e2e/workflow/completeTask.e2e.test.js +129 -0
  137. package/dist/__tests__/e2e/workflow/completeTask.e2e.test.js.map +1 -0
  138. package/dist/__tests__/e2e/workflow/prerequisites.e2e.test.d.ts +2 -0
  139. package/dist/__tests__/e2e/workflow/prerequisites.e2e.test.d.ts.map +1 -0
  140. package/dist/__tests__/e2e/workflow/prerequisites.e2e.test.js +547 -0
  141. package/dist/__tests__/e2e/workflow/prerequisites.e2e.test.js.map +1 -0
  142. package/dist/__tests__/e2e/workflow/pruneClosed.e2e.test.d.ts +2 -0
  143. package/dist/__tests__/e2e/workflow/pruneClosed.e2e.test.d.ts.map +1 -0
  144. package/dist/__tests__/e2e/workflow/pruneClosed.e2e.test.js +352 -0
  145. package/dist/__tests__/e2e/workflow/pruneClosed.e2e.test.js.map +1 -0
  146. package/dist/__tests__/e2e/workflow/taskLifecycle.e2e.test.d.ts +2 -0
  147. package/dist/__tests__/e2e/workflow/taskLifecycle.e2e.test.d.ts.map +1 -0
  148. package/dist/__tests__/e2e/workflow/taskLifecycle.e2e.test.js +385 -0
  149. package/dist/__tests__/e2e/workflow/taskLifecycle.e2e.test.js.map +1 -0
  150. package/dist/models/TrellisObject.d.ts +2 -0
  151. package/dist/models/TrellisObject.d.ts.map +1 -1
  152. package/dist/models/__tests__/isClaimable.test.js +8 -0
  153. package/dist/models/__tests__/isClaimable.test.js.map +1 -1
  154. package/dist/models/__tests__/isClosed.test.js +6 -0
  155. package/dist/models/__tests__/isClosed.test.js.map +1 -1
  156. package/dist/models/__tests__/isOpen.test.js +6 -0
  157. package/dist/models/__tests__/isOpen.test.js.map +1 -1
  158. package/dist/repositories/local/__tests__/getChildrenByFilePath.test.d.ts +2 -0
  159. package/dist/repositories/local/__tests__/getChildrenByFilePath.test.d.ts.map +1 -0
  160. package/dist/repositories/local/__tests__/getChildrenByFilePath.test.js +118 -0
  161. package/dist/repositories/local/__tests__/getChildrenByFilePath.test.js.map +1 -0
  162. package/dist/repositories/local/__tests__/getObjectByFilePath.test.js +13 -1
  163. package/dist/repositories/local/__tests__/getObjectByFilePath.test.js.map +1 -1
  164. package/dist/repositories/local/__tests__/getObjectById.test.js +2 -0
  165. package/dist/repositories/local/__tests__/getObjectById.test.js.map +1 -1
  166. package/dist/repositories/local/__tests__/getObjectFilePath.test.js +2 -0
  167. package/dist/repositories/local/__tests__/getObjectFilePath.test.js.map +1 -1
  168. package/dist/repositories/local/deleteObjectById.js +2 -2
  169. package/dist/repositories/local/deleteObjectById.js.map +1 -1
  170. package/dist/repositories/local/findMarkdownFiles.d.ts.map +1 -1
  171. package/dist/repositories/local/findMarkdownFiles.js +6 -1
  172. package/dist/repositories/local/findMarkdownFiles.js.map +1 -1
  173. package/dist/repositories/local/getChildrenByFilePath.d.ts +14 -0
  174. package/dist/repositories/local/getChildrenByFilePath.d.ts.map +1 -0
  175. package/dist/repositories/local/getChildrenByFilePath.js +93 -0
  176. package/dist/repositories/local/getChildrenByFilePath.js.map +1 -0
  177. package/dist/repositories/local/getObjectByFilePath.d.ts.map +1 -1
  178. package/dist/repositories/local/getObjectByFilePath.js +5 -1
  179. package/dist/repositories/local/getObjectByFilePath.js.map +1 -1
  180. package/dist/repositories/local/getObjectById.d.ts.map +1 -1
  181. package/dist/repositories/local/getObjectById.js +4 -1
  182. package/dist/repositories/local/getObjectById.js.map +1 -1
  183. package/dist/repositories/local/getObjects.js +1 -1
  184. package/dist/repositories/local/getObjects.js.map +1 -1
  185. package/dist/repositories/local/saveObject.d.ts +1 -0
  186. package/dist/repositories/local/saveObject.d.ts.map +1 -1
  187. package/dist/repositories/local/saveObject.js +46 -0
  188. package/dist/repositories/local/saveObject.js.map +1 -1
  189. package/dist/server.js +52 -17
  190. package/dist/server.js.map +1 -1
  191. package/dist/tools/__tests__/appendObjectLogTool.test.js +2 -0
  192. package/dist/tools/__tests__/appendObjectLogTool.test.js.map +1 -1
  193. package/dist/tools/__tests__/claimTaskTool.test.js +4 -0
  194. package/dist/tools/__tests__/claimTaskTool.test.js.map +1 -1
  195. package/dist/tools/__tests__/completeTaskTool.test.js +2 -0
  196. package/dist/tools/__tests__/completeTaskTool.test.js.map +1 -1
  197. package/dist/tools/__tests__/createObjectTool.test.js +18 -0
  198. package/dist/tools/__tests__/createObjectTool.test.js.map +1 -1
  199. package/dist/tools/__tests__/getObjectTool.test.js +4 -0
  200. package/dist/tools/__tests__/getObjectTool.test.js.map +1 -1
  201. package/dist/tools/__tests__/listObjectsTool.test.js +4 -0
  202. package/dist/tools/__tests__/listObjectsTool.test.js.map +1 -1
  203. package/dist/tools/__tests__/pruneClosedTool.test.d.ts +2 -0
  204. package/dist/tools/__tests__/pruneClosedTool.test.d.ts.map +1 -0
  205. package/dist/tools/__tests__/pruneClosedTool.test.js +171 -0
  206. package/dist/tools/__tests__/pruneClosedTool.test.js.map +1 -0
  207. package/dist/tools/__tests__/replaceObjectBodyRegexTool.test.d.ts +2 -0
  208. package/dist/tools/__tests__/replaceObjectBodyRegexTool.test.d.ts.map +1 -0
  209. package/dist/tools/__tests__/replaceObjectBodyRegexTool.test.js +258 -0
  210. package/dist/tools/__tests__/replaceObjectBodyRegexTool.test.js.map +1 -0
  211. package/dist/tools/__tests__/updateObjectTool.test.js +2 -0
  212. package/dist/tools/__tests__/updateObjectTool.test.js.map +1 -1
  213. package/dist/tools/activateTool.d.ts +1 -1
  214. package/dist/tools/activateTool.d.ts.map +1 -1
  215. package/dist/tools/activateTool.js +35 -1
  216. package/dist/tools/activateTool.js.map +1 -1
  217. package/dist/tools/appendObjectLogTool.d.ts +1 -1
  218. package/dist/tools/appendObjectLogTool.d.ts.map +1 -1
  219. package/dist/tools/appendObjectLogTool.js +27 -1
  220. package/dist/tools/appendObjectLogTool.js.map +1 -1
  221. package/dist/tools/claimTaskTool.d.ts +1 -1
  222. package/dist/tools/claimTaskTool.d.ts.map +1 -1
  223. package/dist/tools/claimTaskTool.js +34 -5
  224. package/dist/tools/claimTaskTool.js.map +1 -1
  225. package/dist/tools/completeTaskTool.d.ts +1 -1
  226. package/dist/tools/completeTaskTool.d.ts.map +1 -1
  227. package/dist/tools/completeTaskTool.js +30 -1
  228. package/dist/tools/completeTaskTool.js.map +1 -1
  229. package/dist/tools/createObjectTool.d.ts +1 -1
  230. package/dist/tools/createObjectTool.d.ts.map +1 -1
  231. package/dist/tools/createObjectTool.js +43 -2
  232. package/dist/tools/createObjectTool.js.map +1 -1
  233. package/dist/tools/deleteObjectTool.d.ts +1 -1
  234. package/dist/tools/deleteObjectTool.d.ts.map +1 -1
  235. package/dist/tools/deleteObjectTool.js +23 -1
  236. package/dist/tools/deleteObjectTool.js.map +1 -1
  237. package/dist/tools/getObjectTool.d.ts +1 -1
  238. package/dist/tools/getObjectTool.d.ts.map +1 -1
  239. package/dist/tools/getObjectTool.js +21 -1
  240. package/dist/tools/getObjectTool.js.map +1 -1
  241. package/dist/tools/index.d.ts +1 -0
  242. package/dist/tools/index.d.ts.map +1 -1
  243. package/dist/tools/index.js +4 -1
  244. package/dist/tools/index.js.map +1 -1
  245. package/dist/tools/listObjectsTool.d.ts +1 -1
  246. package/dist/tools/listObjectsTool.d.ts.map +1 -1
  247. package/dist/tools/listObjectsTool.js +37 -1
  248. package/dist/tools/listObjectsTool.js.map +1 -1
  249. package/dist/tools/pruneClosedTool.d.ts +3 -3
  250. package/dist/tools/pruneClosedTool.d.ts.map +1 -1
  251. package/dist/tools/pruneClosedTool.js +82 -11
  252. package/dist/tools/pruneClosedTool.js.map +1 -1
  253. package/dist/tools/replaceObjectBodyRegexTool.d.ts +35 -0
  254. package/dist/tools/replaceObjectBodyRegexTool.d.ts.map +1 -0
  255. package/dist/tools/replaceObjectBodyRegexTool.js +145 -0
  256. package/dist/tools/replaceObjectBodyRegexTool.js.map +1 -0
  257. package/dist/tools/updateObjectTool.d.ts +1 -1
  258. package/dist/tools/updateObjectTool.d.ts.map +1 -1
  259. package/dist/tools/updateObjectTool.js +35 -1
  260. package/dist/tools/updateObjectTool.js.map +1 -1
  261. package/dist/utils/MultipleMatchesError.d.ts +7 -0
  262. package/dist/utils/MultipleMatchesError.d.ts.map +1 -0
  263. package/dist/utils/MultipleMatchesError.js +15 -0
  264. package/dist/utils/MultipleMatchesError.js.map +1 -0
  265. package/dist/utils/ReplaceStringOptions.d.ts +12 -0
  266. package/dist/utils/ReplaceStringOptions.d.ts.map +1 -0
  267. package/dist/utils/ReplaceStringOptions.js +3 -0
  268. package/dist/utils/ReplaceStringOptions.js.map +1 -0
  269. package/dist/utils/__tests__/checkPrerequisitesComplete.test.js +2 -0
  270. package/dist/utils/__tests__/checkPrerequisitesComplete.test.js.map +1 -1
  271. package/dist/utils/__tests__/deserializeTrellisObject.test.js +48 -0
  272. package/dist/utils/__tests__/deserializeTrellisObject.test.js.map +1 -1
  273. package/dist/utils/__tests__/filterUnavailableObjects.test.js +11 -10
  274. package/dist/utils/__tests__/filterUnavailableObjects.test.js.map +1 -1
  275. package/dist/utils/__tests__/isRequiredForOtherObjects.test.js +2 -0
  276. package/dist/utils/__tests__/isRequiredForOtherObjects.test.js.map +1 -1
  277. package/dist/utils/__tests__/replaceStringWithRegex.test.d.ts +2 -0
  278. package/dist/utils/__tests__/replaceStringWithRegex.test.d.ts.map +1 -0
  279. package/dist/utils/__tests__/replaceStringWithRegex.test.js +281 -0
  280. package/dist/utils/__tests__/replaceStringWithRegex.test.js.map +1 -0
  281. package/dist/utils/__tests__/serializationRoundTrip.test.js +24 -0
  282. package/dist/utils/__tests__/serializationRoundTrip.test.js.map +1 -1
  283. package/dist/utils/__tests__/serializeTrellisObject.test.js +40 -0
  284. package/dist/utils/__tests__/serializeTrellisObject.test.js.map +1 -1
  285. package/dist/utils/__tests__/sortTrellisObjects.test.js +2 -0
  286. package/dist/utils/__tests__/sortTrellisObjects.test.js.map +1 -1
  287. package/dist/utils/checkPrerequisitesComplete.d.ts.map +1 -1
  288. package/dist/utils/checkPrerequisitesComplete.js +3 -4
  289. package/dist/utils/checkPrerequisitesComplete.js.map +1 -1
  290. package/dist/utils/deserializeTrellisObject.d.ts.map +1 -1
  291. package/dist/utils/deserializeTrellisObject.js +5 -0
  292. package/dist/utils/deserializeTrellisObject.js.map +1 -1
  293. package/dist/utils/filterUnavailableObjects.d.ts.map +1 -1
  294. package/dist/utils/filterUnavailableObjects.js +5 -6
  295. package/dist/utils/filterUnavailableObjects.js.map +1 -1
  296. package/dist/utils/index.d.ts +3 -0
  297. package/dist/utils/index.d.ts.map +1 -1
  298. package/dist/utils/index.js +5 -1
  299. package/dist/utils/index.js.map +1 -1
  300. package/dist/utils/isRequiredForOtherObjects.d.ts.map +1 -1
  301. package/dist/utils/isRequiredForOtherObjects.js +2 -4
  302. package/dist/utils/isRequiredForOtherObjects.js.map +1 -1
  303. package/dist/utils/replaceStringWithRegex.d.ts +45 -0
  304. package/dist/utils/replaceStringWithRegex.d.ts.map +1 -0
  305. package/dist/utils/replaceStringWithRegex.js +91 -0
  306. package/dist/utils/replaceStringWithRegex.js.map +1 -0
  307. package/dist/utils/serializeTrellisObject.d.ts.map +1 -1
  308. package/dist/utils/serializeTrellisObject.js +3 -0
  309. package/dist/utils/serializeTrellisObject.js.map +1 -1
  310. package/dist/validation/__tests__/validateObjectCreation.test.js +2 -0
  311. package/dist/validation/__tests__/validateObjectCreation.test.js.map +1 -1
  312. package/dist/validation/__tests__/validateParentExists.test.js +2 -0
  313. package/dist/validation/__tests__/validateParentExists.test.js.map +1 -1
  314. package/dist/validation/__tests__/validateStatusTransition.test.js +2 -0
  315. package/dist/validation/__tests__/validateStatusTransition.test.js.map +1 -1
  316. package/package.json +8 -3
@@ -0,0 +1,662 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const utils_1 = require("../utils");
4
+ describe("E2E CRUD - updateObject", () => {
5
+ let testEnv;
6
+ let client;
7
+ beforeEach(async () => {
8
+ testEnv = new utils_1.TestEnvironment();
9
+ testEnv.setup();
10
+ client = new utils_1.McpTestClient(testEnv.projectRoot);
11
+ await client.connect();
12
+ // Activate server in local mode
13
+ await client.callTool("activate", {
14
+ mode: "local",
15
+ projectRoot: testEnv.projectRoot,
16
+ });
17
+ }, 30000);
18
+ afterEach(async () => {
19
+ await client?.disconnect();
20
+ testEnv?.cleanup();
21
+ });
22
+ describe("Individual Field Updates", () => {
23
+ it("should update priority field and persist to file", async () => {
24
+ // Create initial task
25
+ const taskData = {
26
+ id: "T-priority-test",
27
+ title: "Priority Test Task",
28
+ status: "open",
29
+ priority: "low",
30
+ body: "Original body content",
31
+ };
32
+ await (0, utils_1.createObjectFile)(testEnv.projectRoot, "task", "T-priority-test", (0, utils_1.createObjectContent)(taskData));
33
+ // Update priority
34
+ const result = await client.callTool("update_object", {
35
+ id: "T-priority-test",
36
+ priority: "high",
37
+ });
38
+ expect(result.content[0].type).toBe("text");
39
+ const updatedObject = (0, utils_1.parseUpdateObjectResponse)(result.content[0].text);
40
+ expect(updatedObject.priority).toBe("high");
41
+ expect(updatedObject.title).toBe("Priority Test Task");
42
+ expect(updatedObject.body).toBe("Original body content");
43
+ // Verify file persistence
44
+ const file = await (0, utils_1.readObjectFile)(testEnv.projectRoot, "t/open/T-priority-test.md");
45
+ expect(file.yaml.priority).toBe("high");
46
+ expect(file.body).toBe("Original body content");
47
+ });
48
+ it("should update status field and persist to file", async () => {
49
+ // Create initial project
50
+ const projectData = {
51
+ id: "P-status-test",
52
+ title: "Status Test Project",
53
+ status: "draft",
54
+ priority: "medium",
55
+ };
56
+ await (0, utils_1.createObjectFile)(testEnv.projectRoot, "project", "P-status-test", (0, utils_1.createObjectContent)(projectData));
57
+ // Update status
58
+ const result = await client.callTool("update_object", {
59
+ id: "P-status-test",
60
+ status: "open",
61
+ });
62
+ const updatedObject = (0, utils_1.parseUpdateObjectResponse)(result.content[0].text);
63
+ expect(updatedObject.status).toBe("open");
64
+ // Verify file persistence
65
+ const file = await (0, utils_1.readObjectFile)(testEnv.projectRoot, "p/P-status-test/P-status-test.md");
66
+ expect(file.yaml.status).toBe("open");
67
+ });
68
+ it("should update body content", async () => {
69
+ // Create initial feature
70
+ const featureData = {
71
+ id: "F-body-test",
72
+ title: "Body Test Feature",
73
+ body: "Original description",
74
+ };
75
+ await (0, utils_1.createObjectFile)(testEnv.projectRoot, "feature", "F-body-test", (0, utils_1.createObjectContent)(featureData));
76
+ // Update body
77
+ const newBody = `# Updated Feature Description
78
+
79
+ ## Overview
80
+ This is the new body content with markdown formatting.
81
+
82
+ ## Details
83
+ - Point 1
84
+ - Point 2`;
85
+ const result = await client.callTool("update_object", {
86
+ id: "F-body-test",
87
+ body: newBody,
88
+ });
89
+ const updatedObject = (0, utils_1.parseUpdateObjectResponse)(result.content[0].text);
90
+ expect(updatedObject.body).toBe(newBody);
91
+ // Verify file persistence
92
+ const file = await (0, utils_1.readObjectFile)(testEnv.projectRoot, "f/F-body-test/F-body-test.md");
93
+ expect(file.body).toBe(newBody);
94
+ });
95
+ it("should update prerequisites array for tasks", async () => {
96
+ // Create prerequisite tasks
97
+ await (0, utils_1.createObjectFile)(testEnv.projectRoot, "task", "T-prereq-1", (0, utils_1.createObjectContent)({
98
+ id: "T-prereq-1",
99
+ title: "Prerequisite 1",
100
+ status: "done",
101
+ }));
102
+ await (0, utils_1.createObjectFile)(testEnv.projectRoot, "task", "T-prereq-2", (0, utils_1.createObjectContent)({
103
+ id: "T-prereq-2",
104
+ title: "Prerequisite 2",
105
+ status: "done",
106
+ }));
107
+ // Create main task
108
+ const taskData = {
109
+ id: "T-deps-test",
110
+ title: "Dependencies Test Task",
111
+ prerequisites: ["T-prereq-1"],
112
+ };
113
+ await (0, utils_1.createObjectFile)(testEnv.projectRoot, "task", "T-deps-test", (0, utils_1.createObjectContent)(taskData));
114
+ // Update prerequisites
115
+ const result = await client.callTool("update_object", {
116
+ id: "T-deps-test",
117
+ prerequisites: ["T-prereq-1", "T-prereq-2", "F-external-dep"],
118
+ });
119
+ const updatedObject = (0, utils_1.parseUpdateObjectResponse)(result.content[0].text);
120
+ expect(updatedObject.prerequisites).toEqual([
121
+ "T-prereq-1",
122
+ "T-prereq-2",
123
+ "F-external-dep",
124
+ ]);
125
+ // Verify file persistence
126
+ const file = await (0, utils_1.readObjectFile)(testEnv.projectRoot, "t/open/T-deps-test.md");
127
+ expect(file.yaml.prerequisites).toEqual([
128
+ "T-prereq-1",
129
+ "T-prereq-2",
130
+ "F-external-dep",
131
+ ]);
132
+ });
133
+ });
134
+ describe("Multiple Field Updates", () => {
135
+ it("should update multiple fields simultaneously", async () => {
136
+ // Create initial epic
137
+ const epicData = {
138
+ id: "E-multi-update",
139
+ title: "Multi Update Epic",
140
+ status: "draft",
141
+ priority: "low",
142
+ parent: "P-parent-project",
143
+ body: "Initial content",
144
+ };
145
+ await (0, utils_1.createObjectFile)(testEnv.projectRoot, "epic", "E-multi-update", (0, utils_1.createObjectContent)(epicData), { projectId: "P-parent-project" });
146
+ // Update multiple fields
147
+ const result = await client.callTool("update_object", {
148
+ id: "E-multi-update",
149
+ priority: "high",
150
+ status: "open",
151
+ body: "Completely new content with updated priority and status",
152
+ prerequisites: ["P-dep-1", "E-dep-2"],
153
+ });
154
+ const updatedObject = (0, utils_1.parseUpdateObjectResponse)(result.content[0].text);
155
+ expect(updatedObject.priority).toBe("high");
156
+ expect(updatedObject.status).toBe("open");
157
+ expect(updatedObject.body).toBe("Completely new content with updated priority and status");
158
+ expect(updatedObject.prerequisites).toEqual(["P-dep-1", "E-dep-2"]);
159
+ expect(updatedObject.title).toBe("Multi Update Epic"); // Unchanged
160
+ expect(updatedObject.parent).toBe("P-parent-project"); // Unchanged
161
+ // Verify file persistence
162
+ const file = await (0, utils_1.readObjectFile)(testEnv.projectRoot, "p/P-parent-project/e/E-multi-update/E-multi-update.md");
163
+ expect(file.yaml.priority).toBe("high");
164
+ expect(file.yaml.status).toBe("open");
165
+ expect(file.yaml.prerequisites).toEqual(["P-dep-1", "E-dep-2"]);
166
+ expect(file.body).toBe("Completely new content with updated priority and status");
167
+ });
168
+ it("should preserve unchanged fields during update", async () => {
169
+ // Create parent hierarchy first
170
+ await (0, utils_1.createObjectFile)(testEnv.projectRoot, "project", "P-project", (0, utils_1.createObjectContent)({
171
+ id: "P-project",
172
+ title: "Test Project",
173
+ }));
174
+ await (0, utils_1.createObjectFile)(testEnv.projectRoot, "epic", "E-parent-epic", (0, utils_1.createObjectContent)({
175
+ id: "E-parent-epic",
176
+ title: "Parent Epic",
177
+ parent: "P-project",
178
+ }), { projectId: "P-project" });
179
+ const featureData = {
180
+ id: "F-preserve-test",
181
+ title: "Preserve Test Feature",
182
+ status: "in-progress",
183
+ priority: "medium",
184
+ parent: "E-parent-epic",
185
+ prerequisites: ["F-dep-1", "T-dep-2"],
186
+ childrenIds: ["T-child-1", "T-child-2"],
187
+ affectedFiles: { "src/main.ts": "Added feature" },
188
+ log: ["Created feature", "Updated status"],
189
+ schema: "1.1",
190
+ body: "Detailed feature description",
191
+ };
192
+ // Create feature in hierarchy
193
+ await (0, utils_1.createObjectFile)(testEnv.projectRoot, "feature", "F-preserve-test", (0, utils_1.createObjectContent)(featureData), { projectId: "P-project", epicId: "E-parent-epic" });
194
+ // Create the expected child tasks
195
+ await (0, utils_1.createObjectFile)(testEnv.projectRoot, "task", "T-child-1", (0, utils_1.createObjectContent)({
196
+ id: "T-child-1",
197
+ title: "Child Task 1",
198
+ parent: "F-preserve-test",
199
+ }), {
200
+ projectId: "P-project",
201
+ epicId: "E-parent-epic",
202
+ featureId: "F-preserve-test",
203
+ status: "open",
204
+ });
205
+ await (0, utils_1.createObjectFile)(testEnv.projectRoot, "task", "T-child-2", (0, utils_1.createObjectContent)({
206
+ id: "T-child-2",
207
+ title: "Child Task 2",
208
+ parent: "F-preserve-test",
209
+ }), {
210
+ projectId: "P-project",
211
+ epicId: "E-parent-epic",
212
+ featureId: "F-preserve-test",
213
+ status: "open",
214
+ });
215
+ // Update only priority
216
+ const result = await client.callTool("update_object", {
217
+ id: "F-preserve-test",
218
+ priority: "high",
219
+ });
220
+ const updatedObject = (0, utils_1.parseUpdateObjectResponse)(result.content[0].text);
221
+ // Verify only priority changed
222
+ expect(updatedObject.priority).toBe("high");
223
+ // Verify all other fields preserved
224
+ expect(updatedObject.title).toBe("Preserve Test Feature");
225
+ expect(updatedObject.status).toBe("in-progress");
226
+ expect(updatedObject.parent).toBe("E-parent-epic");
227
+ expect(updatedObject.prerequisites).toEqual(["F-dep-1", "T-dep-2"]);
228
+ expect(updatedObject.childrenIds).toEqual(["T-child-1", "T-child-2"]);
229
+ expect(updatedObject.log).toEqual(["Created feature", "Updated status"]);
230
+ expect(updatedObject.body).toBe("Detailed feature description");
231
+ });
232
+ });
233
+ describe("Status Transition Validation", () => {
234
+ it("should allow status change to in-progress when prerequisites are complete", async () => {
235
+ // Create completed prerequisite
236
+ await (0, utils_1.createObjectFile)(testEnv.projectRoot, "task", "T-prereq-done", (0, utils_1.createObjectContent)({
237
+ id: "T-prereq-done",
238
+ title: "Completed Prerequisite",
239
+ status: "done",
240
+ }));
241
+ // Create task with prerequisite
242
+ await (0, utils_1.createObjectFile)(testEnv.projectRoot, "task", "T-can-progress", (0, utils_1.createObjectContent)({
243
+ id: "T-can-progress",
244
+ title: "Can Progress Task",
245
+ status: "open",
246
+ prerequisites: ["T-prereq-done"],
247
+ }));
248
+ // Update status to in-progress
249
+ const result = await client.callTool("update_object", {
250
+ id: "T-can-progress",
251
+ status: "in-progress",
252
+ });
253
+ expect(result.content[0].text).toContain("Successfully updated object");
254
+ const updatedObject = (0, utils_1.parseUpdateObjectResponse)(result.content[0].text);
255
+ expect(updatedObject.status).toBe("in-progress");
256
+ });
257
+ it("should reject status change to in-progress when prerequisites incomplete", async () => {
258
+ // Create incomplete prerequisite
259
+ await (0, utils_1.createObjectFile)(testEnv.projectRoot, "task", "T-prereq-incomplete", (0, utils_1.createObjectContent)({
260
+ id: "T-prereq-incomplete",
261
+ title: "Incomplete Prerequisite",
262
+ status: "open",
263
+ }));
264
+ // Create task with incomplete prerequisite
265
+ await (0, utils_1.createObjectFile)(testEnv.projectRoot, "task", "T-blocked", (0, utils_1.createObjectContent)({
266
+ id: "T-blocked",
267
+ title: "Blocked Task",
268
+ status: "open",
269
+ prerequisites: ["T-prereq-incomplete"],
270
+ }));
271
+ // Attempt to update status to in-progress
272
+ const result = await client.callTool("update_object", {
273
+ id: "T-blocked",
274
+ status: "in-progress",
275
+ });
276
+ expect(result.content[0].type).toBe("text");
277
+ expect(result.content[0].text).toBe("Error updating object: Cannot update status to 'in-progress' - prerequisites are not complete. Use force=true to override.");
278
+ // Verify file was not updated
279
+ const file = await (0, utils_1.readObjectFile)(testEnv.projectRoot, "t/open/T-blocked.md");
280
+ expect(file.yaml.status).toBe("open");
281
+ });
282
+ it("should reject status change to done when prerequisites incomplete", async () => {
283
+ // Create mixed prerequisites
284
+ await (0, utils_1.createObjectFile)(testEnv.projectRoot, "task", "T-prereq-done-2", (0, utils_1.createObjectContent)({
285
+ id: "T-prereq-done-2",
286
+ title: "Done Prerequisite",
287
+ status: "done",
288
+ }));
289
+ await (0, utils_1.createObjectFile)(testEnv.projectRoot, "task", "T-prereq-open", (0, utils_1.createObjectContent)({
290
+ id: "T-prereq-open",
291
+ title: "Open Prerequisite",
292
+ status: "open",
293
+ }));
294
+ // Create feature with mixed prerequisites
295
+ await (0, utils_1.createObjectFile)(testEnv.projectRoot, "feature", "F-blocked-done", (0, utils_1.createObjectContent)({
296
+ id: "F-blocked-done",
297
+ title: "Feature Blocked from Done",
298
+ status: "in-progress",
299
+ prerequisites: ["T-prereq-done-2", "T-prereq-open"],
300
+ }));
301
+ // Attempt to update status to done
302
+ const result = await client.callTool("update_object", {
303
+ id: "F-blocked-done",
304
+ status: "done",
305
+ });
306
+ expect(result.content[0].text).toBe("Error updating object: Cannot update status to 'done' - prerequisites are not complete. Use force=true to override.");
307
+ });
308
+ it("should allow force update bypassing validation", async () => {
309
+ // Create incomplete prerequisite
310
+ await (0, utils_1.createObjectFile)(testEnv.projectRoot, "task", "T-prereq-incomplete-2", (0, utils_1.createObjectContent)({
311
+ id: "T-prereq-incomplete-2",
312
+ title: "Incomplete Prerequisite 2",
313
+ status: "in-progress",
314
+ }));
315
+ // Create task with incomplete prerequisite
316
+ await (0, utils_1.createObjectFile)(testEnv.projectRoot, "task", "T-force-update", (0, utils_1.createObjectContent)({
317
+ id: "T-force-update",
318
+ title: "Force Update Task",
319
+ status: "open",
320
+ prerequisites: ["T-prereq-incomplete-2"],
321
+ }));
322
+ // Force update status to done
323
+ const result = await client.callTool("update_object", {
324
+ id: "T-force-update",
325
+ status: "done",
326
+ force: true,
327
+ });
328
+ expect(result.content[0].text).toContain("Successfully updated object");
329
+ const updatedObject = (0, utils_1.parseUpdateObjectResponse)(result.content[0].text);
330
+ expect(updatedObject.status).toBe("done");
331
+ // Verify file moved to closed folder
332
+ const file = await (0, utils_1.readObjectFile)(testEnv.projectRoot, "t/closed/T-force-update.md");
333
+ expect(file.yaml.status).toBe("done");
334
+ });
335
+ it("should allow status changes to draft without validation", async () => {
336
+ // Create task with incomplete prerequisites
337
+ await (0, utils_1.createObjectFile)(testEnv.projectRoot, "task", "T-to-draft", (0, utils_1.createObjectContent)({
338
+ id: "T-to-draft",
339
+ title: "To Draft Task",
340
+ status: "open",
341
+ prerequisites: ["T-nonexistent"],
342
+ }));
343
+ // Update to draft (no validation required)
344
+ const result = await client.callTool("update_object", {
345
+ id: "T-to-draft",
346
+ status: "draft",
347
+ });
348
+ expect(result.content[0].text).toContain("Successfully updated object");
349
+ const updatedObject = (0, utils_1.parseUpdateObjectResponse)(result.content[0].text);
350
+ expect(updatedObject.status).toBe("draft");
351
+ });
352
+ it("should allow status changes to wont-do without validation", async () => {
353
+ // Create task with incomplete prerequisites
354
+ await (0, utils_1.createObjectFile)(testEnv.projectRoot, "task", "T-to-wontdo", (0, utils_1.createObjectContent)({
355
+ id: "T-to-wontdo",
356
+ title: "To Wont-Do Task",
357
+ status: "open",
358
+ prerequisites: ["T-incomplete"],
359
+ }));
360
+ // Update to wont-do (no validation required)
361
+ const result = await client.callTool("update_object", {
362
+ id: "T-to-wontdo",
363
+ status: "wont-do",
364
+ });
365
+ expect(result.content[0].text).toContain("Successfully updated object");
366
+ const updatedObject = (0, utils_1.parseUpdateObjectResponse)(result.content[0].text);
367
+ expect(updatedObject.status).toBe("wont-do");
368
+ });
369
+ it("should consider wont-do prerequisites as complete", async () => {
370
+ // Create wont-do prerequisite
371
+ await (0, utils_1.createObjectFile)(testEnv.projectRoot, "task", "T-wontdo-prereq", (0, utils_1.createObjectContent)({
372
+ id: "T-wontdo-prereq",
373
+ title: "Wont-Do Prerequisite",
374
+ status: "wont-do",
375
+ }));
376
+ // Create task with wont-do prerequisite
377
+ await (0, utils_1.createObjectFile)(testEnv.projectRoot, "task", "T-with-wontdo", (0, utils_1.createObjectContent)({
378
+ id: "T-with-wontdo",
379
+ title: "Task with Wont-Do Prerequisite",
380
+ status: "open",
381
+ prerequisites: ["T-wontdo-prereq"],
382
+ }));
383
+ // Should allow progression since wont-do is considered complete
384
+ const result = await client.callTool("update_object", {
385
+ id: "T-with-wontdo",
386
+ status: "done",
387
+ });
388
+ expect(result.content[0].text).toContain("Successfully updated object");
389
+ const updatedObject = (0, utils_1.parseUpdateObjectResponse)(result.content[0].text);
390
+ expect(updatedObject.status).toBe("done");
391
+ });
392
+ });
393
+ describe("Error Handling", () => {
394
+ it("should handle non-existent object IDs", async () => {
395
+ const result = await client.callTool("update_object", {
396
+ id: "T-nonexistent",
397
+ priority: "high",
398
+ });
399
+ expect(result.content[0].type).toBe("text");
400
+ expect(result.content[0].text).toBe("Error: Object with ID 'T-nonexistent' not found");
401
+ });
402
+ it("should handle invalid priority values", async () => {
403
+ // Create test task
404
+ await (0, utils_1.createObjectFile)(testEnv.projectRoot, "task", "T-invalid-priority", (0, utils_1.createObjectContent)({
405
+ id: "T-invalid-priority",
406
+ title: "Invalid Priority Test",
407
+ }));
408
+ // Attempt update with invalid priority
409
+ const result = await client.callTool("update_object", {
410
+ id: "T-invalid-priority",
411
+ priority: "critical", // Invalid value
412
+ });
413
+ // The tool accepts any string but may fail on save or return as-is
414
+ // Check the actual behavior
415
+ const responseText = result.content[0].text;
416
+ if (responseText.startsWith("Successfully")) {
417
+ // If it accepts invalid values, verify it's stored
418
+ const updatedObject = (0, utils_1.parseUpdateObjectResponse)(responseText);
419
+ expect(updatedObject.priority).toBe("critical");
420
+ }
421
+ else {
422
+ // If it rejects invalid values
423
+ expect(responseText).toContain("Error");
424
+ }
425
+ });
426
+ it("should handle invalid status values", async () => {
427
+ // Create test project
428
+ await (0, utils_1.createObjectFile)(testEnv.projectRoot, "project", "P-invalid-status", (0, utils_1.createObjectContent)({
429
+ id: "P-invalid-status",
430
+ title: "Invalid Status Test",
431
+ }));
432
+ // Attempt update with invalid status
433
+ const result = await client.callTool("update_object", {
434
+ id: "P-invalid-status",
435
+ status: "completed", // Invalid value (should be "done")
436
+ });
437
+ const responseText = result.content[0].text;
438
+ if (responseText.startsWith("Successfully")) {
439
+ // If it accepts invalid values, verify it's stored
440
+ const updatedObject = (0, utils_1.parseUpdateObjectResponse)(responseText);
441
+ expect(updatedObject.status).toBe("completed");
442
+ }
443
+ else {
444
+ // If it rejects invalid values
445
+ expect(responseText).toContain("Error");
446
+ }
447
+ });
448
+ it("should handle malformed object IDs", async () => {
449
+ const malformedIds = [
450
+ "invalid-id",
451
+ "X-unknown-prefix",
452
+ "T_wrong_separator",
453
+ "",
454
+ "T-", // Missing slug
455
+ ];
456
+ for (const id of malformedIds) {
457
+ const result = await client.callTool("update_object", {
458
+ id,
459
+ priority: "high",
460
+ });
461
+ expect(result.content[0].type).toBe("text");
462
+ expect(result.content[0].text).toContain("Error");
463
+ }
464
+ });
465
+ it("should handle empty prerequisites array", async () => {
466
+ // Create task with prerequisites
467
+ await (0, utils_1.createObjectFile)(testEnv.projectRoot, "task", "T-clear-prereqs", (0, utils_1.createObjectContent)({
468
+ id: "T-clear-prereqs",
469
+ title: "Clear Prerequisites Test",
470
+ prerequisites: ["T-dep-1", "T-dep-2"],
471
+ }));
472
+ // Clear prerequisites
473
+ const result = await client.callTool("update_object", {
474
+ id: "T-clear-prereqs",
475
+ prerequisites: [],
476
+ });
477
+ expect(result.content[0].text).toContain("Successfully updated object");
478
+ const updatedObject = (0, utils_1.parseUpdateObjectResponse)(result.content[0].text);
479
+ expect(updatedObject.prerequisites).toEqual([]);
480
+ // Verify file persistence
481
+ const file = await (0, utils_1.readObjectFile)(testEnv.projectRoot, "t/open/T-clear-prereqs.md");
482
+ expect(file.yaml.prerequisites).toEqual([]);
483
+ });
484
+ it("should handle very long body content", async () => {
485
+ // Create test feature
486
+ await (0, utils_1.createObjectFile)(testEnv.projectRoot, "feature", "F-long-body", (0, utils_1.createObjectContent)({
487
+ id: "F-long-body",
488
+ title: "Long Body Test",
489
+ }));
490
+ // Create very long body content
491
+ const longBody = "A".repeat(10000) + "\n\n" + "B".repeat(10000);
492
+ const result = await client.callTool("update_object", {
493
+ id: "F-long-body",
494
+ body: longBody,
495
+ });
496
+ expect(result.content[0].text).toContain("Successfully updated object");
497
+ const updatedObject = (0, utils_1.parseUpdateObjectResponse)(result.content[0].text);
498
+ expect(updatedObject.body).toBe(longBody);
499
+ // Verify file persistence
500
+ const file = await (0, utils_1.readObjectFile)(testEnv.projectRoot, "f/F-long-body/F-long-body.md");
501
+ expect(file.body).toBe(longBody);
502
+ });
503
+ it("should handle special characters in body content", async () => {
504
+ // Create test epic
505
+ await (0, utils_1.createObjectFile)(testEnv.projectRoot, "epic", "E-special-chars", (0, utils_1.createObjectContent)({
506
+ id: "E-special-chars",
507
+ title: "Special Characters Test",
508
+ parent: "P-parent",
509
+ }), { projectId: "P-parent" });
510
+ // Body with special characters
511
+ const specialBody = `# Special Characters Test
512
+
513
+ ## Code blocks
514
+ \`\`\`typescript
515
+ const test = "value with 'quotes' and 'double quotes'";
516
+ \`\`\`
517
+
518
+ ## Special symbols
519
+ - Unicode: 🚀 ✅ ❌
520
+ - Math: α β γ δ ε
521
+ - Arrows: → ← ↑ ↓
522
+ - Other: & < > | \\ / * ? : " ' \` ~ ! @ # $ % ^ & * ( ) [ ] { }`;
523
+ const result = await client.callTool("update_object", {
524
+ id: "E-special-chars",
525
+ body: specialBody,
526
+ });
527
+ expect(result.content[0].text).toContain("Successfully updated object");
528
+ const updatedObject = (0, utils_1.parseUpdateObjectResponse)(result.content[0].text);
529
+ expect(updatedObject.body).toBe(specialBody);
530
+ // Verify file persistence
531
+ const file = await (0, utils_1.readObjectFile)(testEnv.projectRoot, "p/P-parent/e/E-special-chars/E-special-chars.md");
532
+ expect(file.body).toBe(specialBody);
533
+ });
534
+ });
535
+ describe("Complex Hierarchy Updates", () => {
536
+ it("should update objects in deep hierarchy", async () => {
537
+ // Create complete hierarchy
538
+ const projectId = "P-hierarchy";
539
+ const epicId = "E-hierarchy";
540
+ const featureId = "F-hierarchy";
541
+ const taskId = "T-hierarchy";
542
+ // Create project
543
+ await (0, utils_1.createObjectFile)(testEnv.projectRoot, "project", projectId, (0, utils_1.createObjectContent)({
544
+ id: projectId,
545
+ title: "Hierarchy Project",
546
+ childrenIds: [epicId],
547
+ }));
548
+ // Create epic
549
+ await (0, utils_1.createObjectFile)(testEnv.projectRoot, "epic", epicId, (0, utils_1.createObjectContent)({
550
+ id: epicId,
551
+ title: "Hierarchy Epic",
552
+ parent: projectId,
553
+ childrenIds: [featureId],
554
+ }), { projectId });
555
+ // Create feature
556
+ await (0, utils_1.createObjectFile)(testEnv.projectRoot, "feature", featureId, (0, utils_1.createObjectContent)({
557
+ id: featureId,
558
+ title: "Hierarchy Feature",
559
+ parent: epicId,
560
+ childrenIds: [taskId],
561
+ }), { projectId, epicId });
562
+ // Create task
563
+ await (0, utils_1.createObjectFile)(testEnv.projectRoot, "task", taskId, (0, utils_1.createObjectContent)({
564
+ id: taskId,
565
+ title: "Hierarchy Task",
566
+ parent: featureId,
567
+ status: "open",
568
+ }), { projectId, epicId, featureId, status: "open" });
569
+ // Update task in deep hierarchy
570
+ const result = await client.callTool("update_object", {
571
+ id: taskId,
572
+ priority: "high",
573
+ status: "done",
574
+ body: "Updated task in deep hierarchy",
575
+ });
576
+ expect(result.content[0].text).toContain("Successfully updated object");
577
+ const updatedObject = (0, utils_1.parseUpdateObjectResponse)(result.content[0].text);
578
+ expect(updatedObject.priority).toBe("high");
579
+ expect(updatedObject.status).toBe("done");
580
+ expect(updatedObject.parent).toBe(featureId);
581
+ // Verify file moved to closed folder
582
+ const file = await (0, utils_1.readObjectFile)(testEnv.projectRoot, `p/${projectId}/e/${epicId}/f/${featureId}/t/closed/${taskId}.md`);
583
+ expect(file.yaml.status).toBe("done");
584
+ expect(file.yaml.priority).toBe("high");
585
+ expect(file.body).toBe("Updated task in deep hierarchy");
586
+ });
587
+ it("should handle updates with cross-hierarchy prerequisites", async () => {
588
+ // Create objects in different hierarchies
589
+ await (0, utils_1.createObjectFile)(testEnv.projectRoot, "project", "P-proj-1", (0, utils_1.createObjectContent)({
590
+ id: "P-proj-1",
591
+ title: "Project 1",
592
+ status: "done",
593
+ }));
594
+ await (0, utils_1.createObjectFile)(testEnv.projectRoot, "feature", "F-feat-1", (0, utils_1.createObjectContent)({
595
+ id: "F-feat-1",
596
+ title: "Feature 1",
597
+ status: "done",
598
+ }));
599
+ await (0, utils_1.createObjectFile)(testEnv.projectRoot, "task", "T-cross-deps", (0, utils_1.createObjectContent)({
600
+ id: "T-cross-deps",
601
+ title: "Cross Dependencies Task",
602
+ status: "open",
603
+ prerequisites: [],
604
+ }));
605
+ // Update with cross-hierarchy prerequisites
606
+ const result = await client.callTool("update_object", {
607
+ id: "T-cross-deps",
608
+ prerequisites: ["P-proj-1", "F-feat-1", "E-external"],
609
+ status: "in-progress",
610
+ });
611
+ expect(result.content[0].text).toContain("Successfully updated object");
612
+ const updatedObject = (0, utils_1.parseUpdateObjectResponse)(result.content[0].text);
613
+ expect(updatedObject.prerequisites).toEqual([
614
+ "P-proj-1",
615
+ "F-feat-1",
616
+ "E-external",
617
+ ]);
618
+ expect(updatedObject.status).toBe("in-progress");
619
+ });
620
+ });
621
+ describe("Concurrent Updates", () => {
622
+ it("should handle sequential updates to same object", async () => {
623
+ // Create initial task
624
+ await (0, utils_1.createObjectFile)(testEnv.projectRoot, "task", "T-sequential", (0, utils_1.createObjectContent)({
625
+ id: "T-sequential",
626
+ title: "Sequential Updates Task",
627
+ priority: "low",
628
+ status: "draft",
629
+ body: "Initial",
630
+ }));
631
+ // First update
632
+ const result1 = await client.callTool("update_object", {
633
+ id: "T-sequential",
634
+ priority: "medium",
635
+ });
636
+ expect(result1.content[0].text).toContain("Successfully updated object");
637
+ // Second update
638
+ const result2 = await client.callTool("update_object", {
639
+ id: "T-sequential",
640
+ status: "open",
641
+ });
642
+ expect(result2.content[0].text).toContain("Successfully updated object");
643
+ // Third update
644
+ const result3 = await client.callTool("update_object", {
645
+ id: "T-sequential",
646
+ body: "Final content after multiple updates",
647
+ });
648
+ expect(result3.content[0].text).toContain("Successfully updated object");
649
+ // Verify final state
650
+ const finalObject = (0, utils_1.parseUpdateObjectResponse)(result3.content[0].text);
651
+ expect(finalObject.priority).toBe("medium");
652
+ expect(finalObject.status).toBe("open");
653
+ expect(finalObject.body).toBe("Final content after multiple updates");
654
+ // Verify file persistence
655
+ const file = await (0, utils_1.readObjectFile)(testEnv.projectRoot, "t/open/T-sequential.md");
656
+ expect(file.yaml.priority).toBe("medium");
657
+ expect(file.yaml.status).toBe("open");
658
+ expect(file.body).toBe("Final content after multiple updates");
659
+ });
660
+ });
661
+ });
662
+ //# sourceMappingURL=updateObject.e2e.test.js.map