@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,693 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const utils_1 = require("../utils");
4
+ describe("E2E CRUD - replaceObjectBodyRegex", () => {
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("Basic Functionality Tests", () => {
23
+ it("should replace simple text patterns", async () => {
24
+ // Create task with simple text
25
+ const taskData = {
26
+ id: "T-simple-replace",
27
+ title: "Simple Replace Task",
28
+ status: "open",
29
+ body: "Hello World, welcome to the system",
30
+ };
31
+ await (0, utils_1.createObjectFile)(testEnv.projectRoot, "task", "T-simple-replace", (0, utils_1.createObjectContent)(taskData));
32
+ // Replace "World" with "Universe"
33
+ const result = await client.callTool("replace_object_body_regex", {
34
+ id: "T-simple-replace",
35
+ regex: "World",
36
+ replacement: "Universe",
37
+ });
38
+ expect(result.content[0].type).toBe("text");
39
+ const response = (0, utils_1.parseReplaceObjectBodyRegexResponse)(result.content[0].text);
40
+ expect(response.success).toBe(true);
41
+ expect(response.objectId).toBe("T-simple-replace");
42
+ expect(response.pattern).toBe("World");
43
+ // Verify file persistence
44
+ const file = await (0, utils_1.readObjectFile)(testEnv.projectRoot, "t/open/T-simple-replace.md");
45
+ expect(file.body).toBe("Hello Universe, welcome to the system");
46
+ });
47
+ it("should use backreferences for pattern reordering", async () => {
48
+ // Create task with name pattern
49
+ const taskData = {
50
+ id: "T-backreference",
51
+ title: "Backreference Test",
52
+ body: "Name: John Doe\nEmail: john.doe@example.com",
53
+ };
54
+ await (0, utils_1.createObjectFile)(testEnv.projectRoot, "task", "T-backreference", (0, utils_1.createObjectContent)(taskData));
55
+ // Reorder name using backreferences
56
+ const result = await client.callTool("replace_object_body_regex", {
57
+ id: "T-backreference",
58
+ regex: "Name: (\\w+) (\\w+)",
59
+ replacement: "Name: $2, $1",
60
+ });
61
+ const response = (0, utils_1.parseReplaceObjectBodyRegexResponse)(result.content[0].text);
62
+ expect(response.success).toBe(true);
63
+ // Verify file persistence
64
+ const file = await (0, utils_1.readObjectFile)(testEnv.projectRoot, "t/open/T-backreference.md");
65
+ expect(file.body).toBe("Name: Doe, John\nEmail: john.doe@example.com");
66
+ });
67
+ it("should work with multiline content", async () => {
68
+ // Create feature with multiline content
69
+ const featureData = {
70
+ id: "F-multiline",
71
+ title: "Multiline Content Feature",
72
+ body: `# Feature Description
73
+
74
+ ## Old Implementation
75
+ This is the old way
76
+ of doing things
77
+ across multiple lines
78
+
79
+ ## Other Section
80
+ Keep this unchanged`,
81
+ };
82
+ await (0, utils_1.createObjectFile)(testEnv.projectRoot, "feature", "F-multiline", (0, utils_1.createObjectContent)(featureData));
83
+ // Replace multiline section
84
+ const result = await client.callTool("replace_object_body_regex", {
85
+ id: "F-multiline",
86
+ regex: "## Old Implementation.*?(?=## Other Section)",
87
+ replacement: "## New Implementation\nThis is the new way\nof doing things\nbetter\n\n",
88
+ });
89
+ const response = (0, utils_1.parseReplaceObjectBodyRegexResponse)(result.content[0].text);
90
+ expect(response.success).toBe(true);
91
+ // Verify file persistence
92
+ const file = await (0, utils_1.readObjectFile)(testEnv.projectRoot, "f/F-multiline/F-multiline.md");
93
+ expect(file.body).toBe(`# Feature Description
94
+
95
+ ## New Implementation
96
+ This is the new way
97
+ of doing things
98
+ better
99
+
100
+ ## Other Section
101
+ Keep this unchanged`);
102
+ });
103
+ it("should work across different object types", async () => {
104
+ // First create the parent project for the epic
105
+ const parentProjectData = {
106
+ id: "P-test",
107
+ title: "Test Parent Project",
108
+ body: "Parent project body",
109
+ };
110
+ await (0, utils_1.createObjectFile)(testEnv.projectRoot, "project", "P-test", (0, utils_1.createObjectContent)(parentProjectData));
111
+ const objectTypes = [
112
+ {
113
+ type: "project",
114
+ id: "P-regex-test",
115
+ path: "p/P-regex-test/P-regex-test.md",
116
+ },
117
+ {
118
+ type: "epic",
119
+ id: "E-regex-test",
120
+ path: "p/P-test/e/E-regex-test/E-regex-test.md",
121
+ options: { projectId: "P-test" },
122
+ },
123
+ {
124
+ type: "feature",
125
+ id: "F-regex-test",
126
+ path: "f/F-regex-test/F-regex-test.md",
127
+ },
128
+ { type: "task", id: "T-regex-test", path: "t/open/T-regex-test.md" },
129
+ ];
130
+ for (const obj of objectTypes) {
131
+ const objectData = {
132
+ id: obj.id,
133
+ title: `${obj.type} Regex Test`,
134
+ body: `Old content for ${obj.type}`,
135
+ };
136
+ if (obj.type === "epic") {
137
+ // Epic needs parent project
138
+ objectData.parent = "P-test";
139
+ }
140
+ await (0, utils_1.createObjectFile)(testEnv.projectRoot, obj.type, obj.id, (0, utils_1.createObjectContent)(objectData), obj.options);
141
+ // Replace content
142
+ const result = await client.callTool("replace_object_body_regex", {
143
+ id: obj.id,
144
+ regex: `Old content for ${obj.type}`,
145
+ replacement: `New content for ${obj.type}`,
146
+ });
147
+ const response = (0, utils_1.parseReplaceObjectBodyRegexResponse)(result.content[0].text);
148
+ if (!response.success) {
149
+ console.log(`Failed for ${obj.type}:`, response.message);
150
+ console.log("Full result:", result.content[0].text);
151
+ }
152
+ expect(response.success).toBe(true);
153
+ // Verify file persistence
154
+ const file = await (0, utils_1.readObjectFile)(testEnv.projectRoot, obj.path);
155
+ expect(file.body).toBe(`New content for ${obj.type}`);
156
+ }
157
+ });
158
+ });
159
+ describe("Regex Feature Tests", () => {
160
+ it("should handle case-sensitive matching by default", async () => {
161
+ const taskData = {
162
+ id: "T-case-sensitive",
163
+ title: "Case Sensitive Test",
164
+ body: "Test content with Test and test variations",
165
+ };
166
+ await (0, utils_1.createObjectFile)(testEnv.projectRoot, "task", "T-case-sensitive", (0, utils_1.createObjectContent)(taskData));
167
+ // Only match "Test" (capital T)
168
+ const result = await client.callTool("replace_object_body_regex", {
169
+ id: "T-case-sensitive",
170
+ regex: "Test",
171
+ replacement: "Match",
172
+ allowMultipleOccurrences: true,
173
+ });
174
+ const response = (0, utils_1.parseReplaceObjectBodyRegexResponse)(result.content[0].text);
175
+ expect(response.success).toBe(true);
176
+ const file = await (0, utils_1.readObjectFile)(testEnv.projectRoot, "t/open/T-case-sensitive.md");
177
+ expect(file.body).toBe("Match content with Match and test variations");
178
+ });
179
+ it("should handle case-insensitive patterns with flag", async () => {
180
+ const taskData = {
181
+ id: "T-case-insensitive",
182
+ title: "Case Insensitive Test",
183
+ body: "Test content with TEST and test variations",
184
+ };
185
+ await (0, utils_1.createObjectFile)(testEnv.projectRoot, "task", "T-case-insensitive", (0, utils_1.createObjectContent)(taskData));
186
+ // Replace each case variation individually since (?i) flag might not be supported
187
+ // First replace "Test"
188
+ let result = await client.callTool("replace_object_body_regex", {
189
+ id: "T-case-insensitive",
190
+ regex: "Test",
191
+ replacement: "match",
192
+ });
193
+ let response = (0, utils_1.parseReplaceObjectBodyRegexResponse)(result.content[0].text);
194
+ expect(response.success).toBe(true);
195
+ // Then replace "TEST"
196
+ result = await client.callTool("replace_object_body_regex", {
197
+ id: "T-case-insensitive",
198
+ regex: "TEST",
199
+ replacement: "match",
200
+ });
201
+ response = (0, utils_1.parseReplaceObjectBodyRegexResponse)(result.content[0].text);
202
+ expect(response.success).toBe(true);
203
+ // Finally replace "test"
204
+ result = await client.callTool("replace_object_body_regex", {
205
+ id: "T-case-insensitive",
206
+ regex: "test",
207
+ replacement: "match",
208
+ });
209
+ response = (0, utils_1.parseReplaceObjectBodyRegexResponse)(result.content[0].text);
210
+ expect(response.success).toBe(true);
211
+ const file = await (0, utils_1.readObjectFile)(testEnv.projectRoot, "t/open/T-case-insensitive.md");
212
+ expect(file.body).toBe("match content with match and match variations");
213
+ });
214
+ it("should handle word boundaries", async () => {
215
+ const taskData = {
216
+ id: "T-word-boundaries",
217
+ title: "Word Boundaries Test",
218
+ body: "The cat category has catalog items",
219
+ };
220
+ await (0, utils_1.createObjectFile)(testEnv.projectRoot, "task", "T-word-boundaries", (0, utils_1.createObjectContent)(taskData));
221
+ // Only match whole word "cat"
222
+ const result = await client.callTool("replace_object_body_regex", {
223
+ id: "T-word-boundaries",
224
+ regex: "\\bcat\\b",
225
+ replacement: "dog",
226
+ });
227
+ const response = (0, utils_1.parseReplaceObjectBodyRegexResponse)(result.content[0].text);
228
+ expect(response.success).toBe(true);
229
+ const file = await (0, utils_1.readObjectFile)(testEnv.projectRoot, "t/open/T-word-boundaries.md");
230
+ expect(file.body).toBe("The dog category has catalog items");
231
+ });
232
+ it("should handle anchored patterns", async () => {
233
+ const taskData = {
234
+ id: "T-anchors",
235
+ title: "Anchors Test",
236
+ body: `Start of document
237
+ Middle content
238
+ End of document`,
239
+ };
240
+ await (0, utils_1.createObjectFile)(testEnv.projectRoot, "task", "T-anchors", (0, utils_1.createObjectContent)(taskData));
241
+ // Replace line starting with "Start" using a simpler pattern
242
+ const result = await client.callTool("replace_object_body_regex", {
243
+ id: "T-anchors",
244
+ regex: "Start of document",
245
+ replacement: "Beginning of document",
246
+ });
247
+ const response = (0, utils_1.parseReplaceObjectBodyRegexResponse)(result.content[0].text);
248
+ expect(response.success).toBe(true);
249
+ const file = await (0, utils_1.readObjectFile)(testEnv.projectRoot, "t/open/T-anchors.md");
250
+ expect(file.body).toBe(`Beginning of document
251
+ Middle content
252
+ End of document`);
253
+ });
254
+ it("should handle quantifiers", async () => {
255
+ const taskData = {
256
+ id: "T-quantifiers",
257
+ title: "Quantifiers Test",
258
+ body: "Version 1.2.3 and Version 10.20.30",
259
+ };
260
+ await (0, utils_1.createObjectFile)(testEnv.projectRoot, "task", "T-quantifiers", (0, utils_1.createObjectContent)(taskData));
261
+ // Match version patterns with quantifiers
262
+ const result = await client.callTool("replace_object_body_regex", {
263
+ id: "T-quantifiers",
264
+ regex: "Version \\d+\\.\\d+\\.\\d+",
265
+ replacement: "Release 2.0.0",
266
+ allowMultipleOccurrences: true,
267
+ });
268
+ const response = (0, utils_1.parseReplaceObjectBodyRegexResponse)(result.content[0].text);
269
+ expect(response.success).toBe(true);
270
+ const file = await (0, utils_1.readObjectFile)(testEnv.projectRoot, "t/open/T-quantifiers.md");
271
+ expect(file.body).toBe("Release 2.0.0 and Release 2.0.0");
272
+ });
273
+ it("should handle character classes", async () => {
274
+ const taskData = {
275
+ id: "T-char-classes",
276
+ title: "Character Classes Test",
277
+ body: "Phone: 123-456-7890, Phone: 987.654.3210, Phone: (555) 123-4567",
278
+ };
279
+ await (0, utils_1.createObjectFile)(testEnv.projectRoot, "task", "T-char-classes", (0, utils_1.createObjectContent)(taskData));
280
+ // Match phone numbers with various separators
281
+ const result = await client.callTool("replace_object_body_regex", {
282
+ id: "T-char-classes",
283
+ regex: "Phone: [\\d\\-\\.(\\) ]+",
284
+ replacement: "Phone: XXX-XXX-XXXX",
285
+ allowMultipleOccurrences: true,
286
+ });
287
+ const response = (0, utils_1.parseReplaceObjectBodyRegexResponse)(result.content[0].text);
288
+ expect(response.success).toBe(true);
289
+ const file = await (0, utils_1.readObjectFile)(testEnv.projectRoot, "t/open/T-char-classes.md");
290
+ expect(file.body).toBe("Phone: XXX-XXX-XXXX, Phone: XXX-XXX-XXXX, Phone: XXX-XXX-XXXX");
291
+ });
292
+ });
293
+ describe("Multiple Occurrences Handling", () => {
294
+ it("should reject multiple matches by default", async () => {
295
+ const taskData = {
296
+ id: "T-multiple-reject",
297
+ title: "Multiple Matches Reject",
298
+ body: "TODO: Fix bug 1\nTODO: Fix bug 2\nTODO: Fix bug 3",
299
+ };
300
+ await (0, utils_1.createObjectFile)(testEnv.projectRoot, "task", "T-multiple-reject", (0, utils_1.createObjectContent)(taskData));
301
+ // Attempt to replace all TODOs (should fail)
302
+ const result = await client.callTool("replace_object_body_regex", {
303
+ id: "T-multiple-reject",
304
+ regex: "TODO:",
305
+ replacement: "DONE:",
306
+ });
307
+ expect(result.content[0].type).toBe("text");
308
+ const response = (0, utils_1.parseReplaceObjectBodyRegexResponse)(result.content[0].text);
309
+ expect(response.success).toBe(false);
310
+ expect(response.message).toContain("Found 3 matches for pattern");
311
+ expect(response.message).toContain("allowMultipleOccurrences is false");
312
+ // Verify file unchanged
313
+ const file = await (0, utils_1.readObjectFile)(testEnv.projectRoot, "t/open/T-multiple-reject.md");
314
+ expect(file.body).toBe("TODO: Fix bug 1\nTODO: Fix bug 2\nTODO: Fix bug 3");
315
+ });
316
+ it("should replace all when allowMultipleOccurrences is true", async () => {
317
+ const taskData = {
318
+ id: "T-multiple-allow",
319
+ title: "Multiple Matches Allow",
320
+ body: "TODO: Fix bug 1\nTODO: Fix bug 2\nCompleted: Fix bug 3",
321
+ };
322
+ await (0, utils_1.createObjectFile)(testEnv.projectRoot, "task", "T-multiple-allow", (0, utils_1.createObjectContent)(taskData));
323
+ // Replace all TODOs with allowMultipleOccurrences
324
+ const result = await client.callTool("replace_object_body_regex", {
325
+ id: "T-multiple-allow",
326
+ regex: "TODO:",
327
+ replacement: "DONE:",
328
+ allowMultipleOccurrences: true,
329
+ });
330
+ const response = (0, utils_1.parseReplaceObjectBodyRegexResponse)(result.content[0].text);
331
+ expect(response.success).toBe(true);
332
+ // Verify file updated
333
+ const file = await (0, utils_1.readObjectFile)(testEnv.projectRoot, "t/open/T-multiple-allow.md");
334
+ expect(file.body).toBe("DONE: Fix bug 1\nDONE: Fix bug 2\nCompleted: Fix bug 3");
335
+ });
336
+ it("should handle no matches gracefully", async () => {
337
+ const taskData = {
338
+ id: "T-no-matches",
339
+ title: "No Matches Test",
340
+ body: "This content has no matching patterns",
341
+ };
342
+ await (0, utils_1.createObjectFile)(testEnv.projectRoot, "task", "T-no-matches", (0, utils_1.createObjectContent)(taskData));
343
+ // Search for non-existent pattern
344
+ const result = await client.callTool("replace_object_body_regex", {
345
+ id: "T-no-matches",
346
+ regex: "nonexistent",
347
+ replacement: "replacement",
348
+ });
349
+ const response = (0, utils_1.parseReplaceObjectBodyRegexResponse)(result.content[0].text);
350
+ expect(response.success).toBe(false);
351
+ expect(response.message).toContain("No matches found for pattern");
352
+ expect(response.pattern).toBe("nonexistent");
353
+ // Verify file unchanged
354
+ const file = await (0, utils_1.readObjectFile)(testEnv.projectRoot, "t/open/T-no-matches.md");
355
+ expect(file.body).toBe("This content has no matching patterns");
356
+ });
357
+ });
358
+ describe("Error Handling & Edge Cases", () => {
359
+ it("should handle non-existent object ID", async () => {
360
+ const result = await client.callTool("replace_object_body_regex", {
361
+ id: "T-nonexistent",
362
+ regex: "pattern",
363
+ replacement: "replacement",
364
+ });
365
+ expect(result.content[0].type).toBe("text");
366
+ expect(result.content[0].text).toBe("Error: Object with ID 'T-nonexistent' not found");
367
+ });
368
+ it("should handle empty body content", async () => {
369
+ const taskData = {
370
+ id: "T-empty-body",
371
+ title: "Empty Body Test",
372
+ body: "",
373
+ };
374
+ await (0, utils_1.createObjectFile)(testEnv.projectRoot, "task", "T-empty-body", (0, utils_1.createObjectContent)(taskData));
375
+ const result = await client.callTool("replace_object_body_regex", {
376
+ id: "T-empty-body",
377
+ regex: "pattern",
378
+ replacement: "replacement",
379
+ });
380
+ expect(result.content[0].text).toBe("Error: Object with ID 'T-empty-body' has no body content to replace");
381
+ });
382
+ it("should handle invalid regex patterns", async () => {
383
+ const taskData = {
384
+ id: "T-invalid-regex",
385
+ title: "Invalid Regex Test",
386
+ body: "Some content here",
387
+ };
388
+ await (0, utils_1.createObjectFile)(testEnv.projectRoot, "task", "T-invalid-regex", (0, utils_1.createObjectContent)(taskData));
389
+ const result = await client.callTool("replace_object_body_regex", {
390
+ id: "T-invalid-regex",
391
+ regex: "[invalid regex",
392
+ replacement: "replacement",
393
+ });
394
+ expect(result.content[0].text).toContain("Error replacing object body:");
395
+ expect(result.content[0].text).toContain("Invalid regex pattern");
396
+ });
397
+ it("should handle large body content", async () => {
398
+ // Create 10KB+ content
399
+ const largeContent = "A".repeat(5000) + "\n\nMIDDLE MARKER\n\n" + "B".repeat(5000);
400
+ const taskData = {
401
+ id: "T-large-body",
402
+ title: "Large Body Test",
403
+ body: largeContent,
404
+ };
405
+ await (0, utils_1.createObjectFile)(testEnv.projectRoot, "task", "T-large-body", (0, utils_1.createObjectContent)(taskData));
406
+ // Replace marker in the middle
407
+ const result = await client.callTool("replace_object_body_regex", {
408
+ id: "T-large-body",
409
+ regex: "MIDDLE MARKER",
410
+ replacement: "UPDATED MARKER",
411
+ });
412
+ const response = (0, utils_1.parseReplaceObjectBodyRegexResponse)(result.content[0].text);
413
+ expect(response.success).toBe(true);
414
+ // Verify large content was processed correctly
415
+ const file = await (0, utils_1.readObjectFile)(testEnv.projectRoot, "t/open/T-large-body.md");
416
+ expect(file.body).toContain("UPDATED MARKER");
417
+ expect(file.body.length).toBe(largeContent.length +
418
+ ("UPDATED MARKER".length - "MIDDLE MARKER".length));
419
+ });
420
+ it("should handle special characters and unicode", async () => {
421
+ const taskData = {
422
+ id: "T-special-chars",
423
+ title: "Special Characters Test",
424
+ body: `# Special Content 🚀
425
+
426
+ Code: const test = "value with 'quotes' and \\"double quotes\\"";
427
+ Math: α β γ δ ε
428
+ Arrows: → ← ↑ ↓
429
+ Symbols: & < > | \\ / * ? : " ' \` ~ ! @ # $ % ^ & * ( ) [ ] { }
430
+ Unicode: 你好世界`,
431
+ };
432
+ await (0, utils_1.createObjectFile)(testEnv.projectRoot, "task", "T-special-chars", (0, utils_1.createObjectContent)(taskData));
433
+ // Replace unicode content
434
+ const result = await client.callTool("replace_object_body_regex", {
435
+ id: "T-special-chars",
436
+ regex: "你好世界",
437
+ replacement: "Hello World",
438
+ });
439
+ const response = (0, utils_1.parseReplaceObjectBodyRegexResponse)(result.content[0].text);
440
+ expect(response.success).toBe(true);
441
+ const file = await (0, utils_1.readObjectFile)(testEnv.projectRoot, "t/open/T-special-chars.md");
442
+ expect(file.body).toContain("Hello World");
443
+ expect(file.body).not.toContain("你好世界");
444
+ });
445
+ it("should handle empty regex pattern", async () => {
446
+ const taskData = {
447
+ id: "T-empty-regex",
448
+ title: "Empty Regex Test",
449
+ body: "Some content",
450
+ };
451
+ await (0, utils_1.createObjectFile)(testEnv.projectRoot, "task", "T-empty-regex", (0, utils_1.createObjectContent)(taskData));
452
+ const result = await client.callTool("replace_object_body_regex", {
453
+ id: "T-empty-regex",
454
+ regex: "",
455
+ replacement: "replacement",
456
+ });
457
+ expect(result.content[0].text).toContain("Regex pattern cannot be empty");
458
+ });
459
+ });
460
+ describe("File System Persistence", () => {
461
+ it("should verify changes persist across file reads", async () => {
462
+ const taskData = {
463
+ id: "T-persistence",
464
+ title: "Persistence Test",
465
+ status: "open",
466
+ priority: "high",
467
+ body: "Original content for persistence testing",
468
+ };
469
+ await (0, utils_1.createObjectFile)(testEnv.projectRoot, "task", "T-persistence", (0, utils_1.createObjectContent)(taskData));
470
+ // Perform replacement
471
+ const result = await client.callTool("replace_object_body_regex", {
472
+ id: "T-persistence",
473
+ regex: "Original content",
474
+ replacement: "Updated content",
475
+ });
476
+ const response = (0, utils_1.parseReplaceObjectBodyRegexResponse)(result.content[0].text);
477
+ expect(response.success).toBe(true);
478
+ // Read file multiple times to verify persistence
479
+ for (let i = 0; i < 3; i++) {
480
+ const file = await (0, utils_1.readObjectFile)(testEnv.projectRoot, "t/open/T-persistence.md");
481
+ expect(file.body).toBe("Updated content for persistence testing");
482
+ expect(file.yaml.title).toBe("Persistence Test");
483
+ expect(file.yaml.status).toBe("open");
484
+ expect(file.yaml.priority).toBe("high");
485
+ }
486
+ });
487
+ it("should preserve YAML frontmatter during body updates", async () => {
488
+ const taskData = {
489
+ id: "T-yaml-preserve",
490
+ title: "YAML Preservation Test",
491
+ status: "open",
492
+ priority: "high",
493
+ prerequisites: ["T-dep-1", "T-dep-2"],
494
+ body: "Body content to be modified",
495
+ };
496
+ await (0, utils_1.createObjectFile)(testEnv.projectRoot, "task", "T-yaml-preserve", (0, utils_1.createObjectContent)(taskData));
497
+ // Update body content
498
+ const result = await client.callTool("replace_object_body_regex", {
499
+ id: "T-yaml-preserve",
500
+ regex: "Body content",
501
+ replacement: "Modified body content",
502
+ });
503
+ const response = (0, utils_1.parseReplaceObjectBodyRegexResponse)(result.content[0].text);
504
+ expect(response.success).toBe(true);
505
+ // Verify YAML metadata preserved (using open status so file is in t/open/ folder)
506
+ const file = await (0, utils_1.readObjectFile)(testEnv.projectRoot, "t/open/T-yaml-preserve.md");
507
+ expect(file.yaml.id).toBe("T-yaml-preserve");
508
+ expect(file.yaml.title).toBe("YAML Preservation Test");
509
+ expect(file.yaml.status).toBe("open");
510
+ expect(file.yaml.priority).toBe("high");
511
+ expect(file.yaml.prerequisites).toEqual(["T-dep-1", "T-dep-2"]);
512
+ expect(file.body).toBe("Modified body content to be modified");
513
+ });
514
+ it("should work with objects in hierarchy paths", async () => {
515
+ // Create project structure
516
+ const projectData = {
517
+ id: "P-hierarchy",
518
+ title: "Hierarchy Project",
519
+ body: "Project description",
520
+ };
521
+ await (0, utils_1.createObjectFile)(testEnv.projectRoot, "project", "P-hierarchy", (0, utils_1.createObjectContent)(projectData));
522
+ // Create epic in project
523
+ const epicData = {
524
+ id: "E-hierarchy",
525
+ title: "Hierarchy Epic",
526
+ parent: "P-hierarchy",
527
+ body: "Epic content for replacement",
528
+ };
529
+ await (0, utils_1.createObjectFile)(testEnv.projectRoot, "epic", "E-hierarchy", (0, utils_1.createObjectContent)(epicData), { projectId: "P-hierarchy" });
530
+ // Create feature in epic
531
+ const featureData = {
532
+ id: "F-hierarchy",
533
+ title: "Hierarchy Feature",
534
+ parent: "E-hierarchy",
535
+ body: "Feature content for replacement",
536
+ };
537
+ await (0, utils_1.createObjectFile)(testEnv.projectRoot, "feature", "F-hierarchy", (0, utils_1.createObjectContent)(featureData), { projectId: "P-hierarchy", epicId: "E-hierarchy" });
538
+ // Update feature content
539
+ const result = await client.callTool("replace_object_body_regex", {
540
+ id: "F-hierarchy",
541
+ regex: "Feature content",
542
+ replacement: "Updated feature content",
543
+ });
544
+ const response = (0, utils_1.parseReplaceObjectBodyRegexResponse)(result.content[0].text);
545
+ expect(response.success).toBe(true);
546
+ // Verify file in correct hierarchy path
547
+ const file = await (0, utils_1.readObjectFile)(testEnv.projectRoot, "p/P-hierarchy/e/E-hierarchy/f/F-hierarchy/F-hierarchy.md");
548
+ expect(file.body).toBe("Updated feature content for replacement");
549
+ });
550
+ });
551
+ describe("Integration Scenarios", () => {
552
+ it("should handle complex markdown content", async () => {
553
+ const complexMarkdown = `# Main Title
554
+
555
+ ## Section 1
556
+ Some content here with **bold** and *italic* text.
557
+
558
+ \`\`\`typescript
559
+ const example = "code block";
560
+ function test() {
561
+ return "old implementation";
562
+ }
563
+ \`\`\`
564
+
565
+ ### Subsection
566
+ - List item 1
567
+ - List item 2
568
+ - List item 3
569
+
570
+ | Column 1 | Column 2 |
571
+ |----------|----------|
572
+ | Value 1 | Value 2 |
573
+
574
+ > This is a blockquote with old information
575
+
576
+ ## Section 2
577
+ More content here.`;
578
+ const featureData = {
579
+ id: "F-complex-markdown",
580
+ title: "Complex Markdown Test",
581
+ body: complexMarkdown,
582
+ };
583
+ await (0, utils_1.createObjectFile)(testEnv.projectRoot, "feature", "F-complex-markdown", (0, utils_1.createObjectContent)(featureData));
584
+ // Update code block content - escape quotes properly
585
+ const result = await client.callTool("replace_object_body_regex", {
586
+ id: "F-complex-markdown",
587
+ regex: 'return "old implementation";',
588
+ replacement: 'return "new implementation";',
589
+ });
590
+ const response = (0, utils_1.parseReplaceObjectBodyRegexResponse)(result.content[0].text);
591
+ if (!response.success) {
592
+ console.log("Complex markdown failed:", response.message);
593
+ console.log("Full result:", result.content[0].text);
594
+ }
595
+ expect(response.success).toBe(true);
596
+ const file = await (0, utils_1.readObjectFile)(testEnv.projectRoot, "f/F-complex-markdown/F-complex-markdown.md");
597
+ expect(file.body).toContain('return "new implementation";');
598
+ expect(file.body).not.toContain('return "old implementation";');
599
+ expect(file.body).toContain("# Main Title");
600
+ expect(file.body).toContain("| Column 1 | Column 2 |");
601
+ });
602
+ it("should handle template placeholder replacements", async () => {
603
+ const templateContent = `# {{TITLE}} Implementation
604
+
605
+ ## Overview
606
+ This {{TYPE}} implements {{FEATURE_NAME}} functionality.
607
+
608
+ ## Configuration
609
+ - Environment: {{ENV}}
610
+ - Version: {{VERSION}}
611
+ - Database: {{DB_TYPE}}
612
+
613
+ ## Implementation Details
614
+ The {{FEATURE_NAME}} feature uses {{TECHNOLOGY}} to provide {{BENEFIT}}.`;
615
+ const taskData = {
616
+ id: "T-template",
617
+ title: "Template Replacement Test",
618
+ body: templateContent,
619
+ };
620
+ await (0, utils_1.createObjectFile)(testEnv.projectRoot, "task", "T-template", (0, utils_1.createObjectContent)(taskData));
621
+ // Replace all template variables
622
+ const replacements = [
623
+ { pattern: "\\{\\{TITLE\\}\\}", value: "Authentication" },
624
+ { pattern: "\\{\\{TYPE\\}\\}", value: "module" },
625
+ { pattern: "\\{\\{FEATURE_NAME\\}\\}", value: "user login" },
626
+ { pattern: "\\{\\{ENV\\}\\}", value: "production" },
627
+ { pattern: "\\{\\{VERSION\\}\\}", value: "2.0.0" },
628
+ { pattern: "\\{\\{DB_TYPE\\}\\}", value: "PostgreSQL" },
629
+ { pattern: "\\{\\{TECHNOLOGY\\}\\}", value: "JWT tokens" },
630
+ { pattern: "\\{\\{BENEFIT\\}\\}", value: "secure authentication" },
631
+ ];
632
+ for (const replacement of replacements) {
633
+ const result = await client.callTool("replace_object_body_regex", {
634
+ id: "T-template",
635
+ regex: replacement.pattern,
636
+ replacement: replacement.value,
637
+ allowMultipleOccurrences: true, // For template replacements, we want to replace all occurrences
638
+ });
639
+ const response = (0, utils_1.parseReplaceObjectBodyRegexResponse)(result.content[0].text);
640
+ if (!response.success) {
641
+ console.log(`Template replacement failed for ${replacement.pattern}:`, response.message);
642
+ console.log("Full result:", result.content[0].text);
643
+ }
644
+ expect(response.success).toBe(true);
645
+ }
646
+ // Verify all placeholders replaced
647
+ const file = await (0, utils_1.readObjectFile)(testEnv.projectRoot, "t/open/T-template.md");
648
+ expect(file.body).not.toContain("{{");
649
+ expect(file.body).not.toContain("}}");
650
+ expect(file.body).toContain("# Authentication Implementation");
651
+ expect(file.body).toContain("This module implements user login functionality");
652
+ expect(file.body).toContain("Version: 2.0.0");
653
+ expect(file.body).toContain("uses JWT tokens to provide secure authentication");
654
+ });
655
+ it("should handle cross-references and object IDs in content", async () => {
656
+ const contentWithRefs = `# Task Dependencies
657
+
658
+ This task depends on:
659
+ - P-auth-system (Authentication Project)
660
+ - E-user-management (User Management Epic)
661
+ - F-login-form (Login Form Feature)
662
+
663
+ ## Related Tasks
664
+ - T-create-models: Database model creation
665
+ - T-setup-routes: API route setup
666
+ - T-add-validation: Input validation
667
+
668
+ ## Status Updates
669
+ Updated T-old-task-id to completed status.
670
+ Blocked by F-payment-integration until resolved.`;
671
+ const taskData = {
672
+ id: "T-refs-test",
673
+ title: "Cross References Test",
674
+ body: contentWithRefs,
675
+ };
676
+ await (0, utils_1.createObjectFile)(testEnv.projectRoot, "task", "T-refs-test", (0, utils_1.createObjectContent)(taskData));
677
+ // Update old task reference
678
+ const result = await client.callTool("replace_object_body_regex", {
679
+ id: "T-refs-test",
680
+ regex: "T-old-task-id",
681
+ replacement: "T-new-task-id",
682
+ });
683
+ const response = (0, utils_1.parseReplaceObjectBodyRegexResponse)(result.content[0].text);
684
+ expect(response.success).toBe(true);
685
+ const file = await (0, utils_1.readObjectFile)(testEnv.projectRoot, "t/open/T-refs-test.md");
686
+ expect(file.body).toContain("T-new-task-id");
687
+ expect(file.body).not.toContain("T-old-task-id");
688
+ expect(file.body).toContain("P-auth-system");
689
+ expect(file.body).toContain("F-payment-integration");
690
+ });
691
+ });
692
+ });
693
+ //# sourceMappingURL=replaceObjectBodyRegex.e2e.test.js.map