@langadventurellc/task-trellis-mcp 1.0.1 → 1.1.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 (207) hide show
  1. package/README.md +47 -67
  2. package/dist/__tests__/e2e/crud/createObject.e2e.test.js +64 -12
  3. package/dist/__tests__/e2e/crud/createObject.e2e.test.js.map +1 -1
  4. package/dist/__tests__/e2e/crud/listObjects.e2e.test.js +260 -90
  5. package/dist/__tests__/e2e/crud/listObjects.e2e.test.js.map +1 -1
  6. package/dist/__tests__/e2e/utils/extractObjectIds.d.ts +5 -0
  7. package/dist/__tests__/e2e/utils/extractObjectIds.d.ts.map +1 -0
  8. package/dist/__tests__/e2e/utils/extractObjectIds.js +12 -0
  9. package/dist/__tests__/e2e/utils/extractObjectIds.js.map +1 -0
  10. package/dist/__tests__/e2e/utils/index.d.ts +1 -0
  11. package/dist/__tests__/e2e/utils/index.d.ts.map +1 -1
  12. package/dist/__tests__/e2e/utils/index.js +3 -1
  13. package/dist/__tests__/e2e/utils/index.js.map +1 -1
  14. package/dist/__tests__/e2e/utils/mcpTestClient.d.ts +2 -1
  15. package/dist/__tests__/e2e/utils/mcpTestClient.d.ts.map +1 -1
  16. package/dist/__tests__/e2e/utils/mcpTestClient.js +14 -8
  17. package/dist/__tests__/e2e/utils/mcpTestClient.js.map +1 -1
  18. package/dist/__tests__/e2e/utils/parseListObjectsResponse.d.ts +3 -1
  19. package/dist/__tests__/e2e/utils/parseListObjectsResponse.d.ts.map +1 -1
  20. package/dist/__tests__/e2e/utils/parseListObjectsResponse.js +1 -0
  21. package/dist/__tests__/e2e/utils/parseListObjectsResponse.js.map +1 -1
  22. package/dist/__tests__/e2e/workflow/appendModifiedFiles.e2e.test.d.ts +2 -0
  23. package/dist/__tests__/e2e/workflow/appendModifiedFiles.e2e.test.d.ts.map +1 -0
  24. package/dist/__tests__/e2e/workflow/appendModifiedFiles.e2e.test.js +597 -0
  25. package/dist/__tests__/e2e/workflow/appendModifiedFiles.e2e.test.js.map +1 -0
  26. package/dist/__tests__/e2e/workflow/claimTask.e2e.test.js +189 -0
  27. package/dist/__tests__/e2e/workflow/claimTask.e2e.test.js.map +1 -1
  28. package/dist/__tests__/e2e/workflow/completeTask.e2e.test.js +446 -0
  29. package/dist/__tests__/e2e/workflow/completeTask.e2e.test.js.map +1 -1
  30. package/dist/__tests__/e2e/workflow/taskLifecycle.e2e.test.js +3 -7
  31. package/dist/__tests__/e2e/workflow/taskLifecycle.e2e.test.js.map +1 -1
  32. package/dist/configuration/ServerConfig.d.ts +1 -0
  33. package/dist/configuration/ServerConfig.d.ts.map +1 -1
  34. package/dist/models/TrellisObjectSummary.d.ts +16 -0
  35. package/dist/models/TrellisObjectSummary.d.ts.map +1 -0
  36. package/dist/models/TrellisObjectSummary.js +3 -0
  37. package/dist/models/TrellisObjectSummary.js.map +1 -0
  38. package/dist/models/index.d.ts +1 -0
  39. package/dist/models/index.d.ts.map +1 -1
  40. package/dist/models/index.js.map +1 -1
  41. package/dist/repositories/local/__tests__/getObjectFilePath.test.js +9 -6
  42. package/dist/repositories/local/__tests__/getObjectFilePath.test.js.map +1 -1
  43. package/dist/repositories/local/__tests__/getObjects.test.js +40 -10
  44. package/dist/repositories/local/__tests__/getObjects.test.js.map +1 -1
  45. package/dist/repositories/local/getObjectFilePath.d.ts.map +1 -1
  46. package/dist/repositories/local/getObjectFilePath.js +8 -4
  47. package/dist/repositories/local/getObjectFilePath.js.map +1 -1
  48. package/dist/repositories/local/getObjects.d.ts.map +1 -1
  49. package/dist/repositories/local/getObjects.js +6 -1
  50. package/dist/repositories/local/getObjects.js.map +1 -1
  51. package/dist/server.js +23 -9
  52. package/dist/server.js.map +1 -1
  53. package/dist/services/TaskTrellisService.d.ts +87 -0
  54. package/dist/services/TaskTrellisService.d.ts.map +1 -0
  55. package/dist/services/TaskTrellisService.js +3 -0
  56. package/dist/services/TaskTrellisService.js.map +1 -0
  57. package/dist/services/local/LocalTaskTrellisService.d.ts +61 -0
  58. package/dist/services/local/LocalTaskTrellisService.d.ts.map +1 -0
  59. package/dist/services/local/LocalTaskTrellisService.js +77 -0
  60. package/dist/services/local/LocalTaskTrellisService.js.map +1 -0
  61. package/dist/services/local/__tests__/appendAffectedFiles.test.d.ts +2 -0
  62. package/dist/services/local/__tests__/appendAffectedFiles.test.d.ts.map +1 -0
  63. package/dist/services/local/__tests__/appendAffectedFiles.test.js +202 -0
  64. package/dist/services/local/__tests__/appendAffectedFiles.test.js.map +1 -0
  65. package/dist/services/local/__tests__/appendModifiedFiles.test.d.ts +2 -0
  66. package/dist/services/local/__tests__/appendModifiedFiles.test.d.ts.map +1 -0
  67. package/dist/services/local/__tests__/appendModifiedFiles.test.js +161 -0
  68. package/dist/services/local/__tests__/appendModifiedFiles.test.js.map +1 -0
  69. package/dist/services/local/__tests__/appendObjectLog.test.d.ts +2 -0
  70. package/dist/services/local/__tests__/appendObjectLog.test.d.ts.map +1 -0
  71. package/dist/services/local/__tests__/appendObjectLog.test.js +104 -0
  72. package/dist/services/local/__tests__/appendObjectLog.test.js.map +1 -0
  73. package/dist/services/local/__tests__/claimTask.test.d.ts +2 -0
  74. package/dist/services/local/__tests__/claimTask.test.d.ts.map +1 -0
  75. package/dist/services/local/__tests__/claimTask.test.js +463 -0
  76. package/dist/services/local/__tests__/claimTask.test.js.map +1 -0
  77. package/dist/services/local/__tests__/completeTask.test.d.ts +2 -0
  78. package/dist/services/local/__tests__/completeTask.test.d.ts.map +1 -0
  79. package/dist/services/local/__tests__/completeTask.test.js +468 -0
  80. package/dist/services/local/__tests__/completeTask.test.js.map +1 -0
  81. package/dist/services/local/__tests__/createObject.test.d.ts +2 -0
  82. package/dist/services/local/__tests__/createObject.test.d.ts.map +1 -0
  83. package/dist/services/local/__tests__/createObject.test.js +332 -0
  84. package/dist/services/local/__tests__/createObject.test.js.map +1 -0
  85. package/dist/services/local/__tests__/listObjects.test.d.ts +2 -0
  86. package/dist/services/local/__tests__/listObjects.test.d.ts.map +1 -0
  87. package/dist/services/local/__tests__/listObjects.test.js +226 -0
  88. package/dist/services/local/__tests__/listObjects.test.js.map +1 -0
  89. package/dist/services/local/__tests__/pruneClosed.test.d.ts +2 -0
  90. package/dist/services/local/__tests__/pruneClosed.test.d.ts.map +1 -0
  91. package/dist/services/local/__tests__/pruneClosed.test.js +213 -0
  92. package/dist/services/local/__tests__/pruneClosed.test.js.map +1 -0
  93. package/dist/services/local/__tests__/replaceObjectBodyRegex.test.d.ts +2 -0
  94. package/dist/services/local/__tests__/replaceObjectBodyRegex.test.d.ts.map +1 -0
  95. package/dist/services/local/__tests__/replaceObjectBodyRegex.test.js +283 -0
  96. package/dist/services/local/__tests__/replaceObjectBodyRegex.test.js.map +1 -0
  97. package/dist/services/local/__tests__/updateObject.test.d.ts +2 -0
  98. package/dist/services/local/__tests__/updateObject.test.d.ts.map +1 -0
  99. package/dist/services/local/__tests__/updateObject.test.js +314 -0
  100. package/dist/services/local/__tests__/updateObject.test.js.map +1 -0
  101. package/dist/services/local/appendAffectedFiles.d.ts +12 -0
  102. package/dist/services/local/appendAffectedFiles.d.ts.map +1 -0
  103. package/dist/services/local/appendAffectedFiles.js +34 -0
  104. package/dist/services/local/appendAffectedFiles.js.map +1 -0
  105. package/dist/services/local/appendModifiedFiles.d.ts +15 -0
  106. package/dist/services/local/appendModifiedFiles.d.ts.map +1 -0
  107. package/dist/services/local/appendModifiedFiles.js +39 -0
  108. package/dist/services/local/appendModifiedFiles.js.map +1 -0
  109. package/dist/services/local/appendObjectLog.d.ts +8 -0
  110. package/dist/services/local/appendObjectLog.d.ts.map +1 -0
  111. package/dist/services/local/appendObjectLog.js +45 -0
  112. package/dist/services/local/appendObjectLog.js.map +1 -0
  113. package/dist/services/local/claimTask.d.ts +8 -0
  114. package/dist/services/local/claimTask.d.ts.map +1 -0
  115. package/dist/services/local/claimTask.js +118 -0
  116. package/dist/services/local/claimTask.js.map +1 -0
  117. package/dist/services/local/completeTask.d.ts +9 -0
  118. package/dist/services/local/completeTask.d.ts.map +1 -0
  119. package/dist/services/local/completeTask.js +74 -0
  120. package/dist/services/local/completeTask.js.map +1 -0
  121. package/dist/services/local/createObject.d.ts +9 -0
  122. package/dist/services/local/createObject.d.ts.map +1 -0
  123. package/dist/services/local/createObject.js +44 -0
  124. package/dist/services/local/createObject.js.map +1 -0
  125. package/dist/services/local/listObjects.d.ts +9 -0
  126. package/dist/services/local/listObjects.d.ts.map +1 -0
  127. package/dist/services/local/listObjects.js +43 -0
  128. package/dist/services/local/listObjects.js.map +1 -0
  129. package/dist/services/local/pruneClosed.d.ts +8 -0
  130. package/dist/services/local/pruneClosed.d.ts.map +1 -0
  131. package/dist/services/local/pruneClosed.js +55 -0
  132. package/dist/services/local/pruneClosed.js.map +1 -0
  133. package/dist/services/local/replaceObjectBodyRegex.d.ts +8 -0
  134. package/dist/services/local/replaceObjectBodyRegex.d.ts.map +1 -0
  135. package/dist/services/local/replaceObjectBodyRegex.js +85 -0
  136. package/dist/services/local/replaceObjectBodyRegex.js.map +1 -0
  137. package/dist/services/local/updateObject.d.ts +9 -0
  138. package/dist/services/local/updateObject.d.ts.map +1 -0
  139. package/dist/services/local/updateObject.js +53 -0
  140. package/dist/services/local/updateObject.js.map +1 -0
  141. package/dist/tools/__tests__/appendModifiedFilesTool.test.d.ts +2 -0
  142. package/dist/tools/__tests__/appendModifiedFilesTool.test.d.ts.map +1 -0
  143. package/dist/tools/__tests__/appendModifiedFilesTool.test.js +177 -0
  144. package/dist/tools/__tests__/appendModifiedFilesTool.test.js.map +1 -0
  145. package/dist/tools/__tests__/appendObjectLogTool.test.js +33 -101
  146. package/dist/tools/__tests__/appendObjectLogTool.test.js.map +1 -1
  147. package/dist/tools/__tests__/claimTaskTool.test.js +98 -311
  148. package/dist/tools/__tests__/claimTaskTool.test.js.map +1 -1
  149. package/dist/tools/__tests__/completeTaskTool.test.js +134 -184
  150. package/dist/tools/__tests__/completeTaskTool.test.js.map +1 -1
  151. package/dist/tools/__tests__/createObjectTool.test.js +61 -325
  152. package/dist/tools/__tests__/createObjectTool.test.js.map +1 -1
  153. package/dist/tools/__tests__/listObjectsTool.test.js +70 -109
  154. package/dist/tools/__tests__/listObjectsTool.test.js.map +1 -1
  155. package/dist/tools/__tests__/pruneClosedTool.test.js +87 -146
  156. package/dist/tools/__tests__/pruneClosedTool.test.js.map +1 -1
  157. package/dist/tools/__tests__/replaceObjectBodyRegexTool.test.js +56 -225
  158. package/dist/tools/__tests__/replaceObjectBodyRegexTool.test.js.map +1 -1
  159. package/dist/tools/__tests__/updateObjectTool.test.js +48 -166
  160. package/dist/tools/__tests__/updateObjectTool.test.js.map +1 -1
  161. package/dist/tools/appendModifiedFilesTool.d.ts +30 -0
  162. package/dist/tools/appendModifiedFilesTool.d.ts.map +1 -0
  163. package/dist/tools/appendModifiedFilesTool.js +55 -0
  164. package/dist/tools/appendModifiedFilesTool.js.map +1 -0
  165. package/dist/tools/appendObjectLogTool.d.ts +4 -3
  166. package/dist/tools/appendObjectLogTool.d.ts.map +1 -1
  167. package/dist/tools/appendObjectLogTool.js +2 -40
  168. package/dist/tools/appendObjectLogTool.js.map +1 -1
  169. package/dist/tools/claimTaskTool.d.ts +4 -3
  170. package/dist/tools/claimTaskTool.d.ts.map +1 -1
  171. package/dist/tools/claimTaskTool.js +2 -80
  172. package/dist/tools/claimTaskTool.js.map +1 -1
  173. package/dist/tools/completeTaskTool.d.ts +5 -3
  174. package/dist/tools/completeTaskTool.d.ts.map +1 -1
  175. package/dist/tools/completeTaskTool.js +3 -29
  176. package/dist/tools/completeTaskTool.js.map +1 -1
  177. package/dist/tools/createObjectTool.d.ts +7 -6
  178. package/dist/tools/createObjectTool.d.ts.map +1 -1
  179. package/dist/tools/createObjectTool.js +11 -44
  180. package/dist/tools/createObjectTool.js.map +1 -1
  181. package/dist/tools/index.d.ts +1 -0
  182. package/dist/tools/index.d.ts.map +1 -1
  183. package/dist/tools/index.js +4 -1
  184. package/dist/tools/index.js.map +1 -1
  185. package/dist/tools/listObjectsTool.d.ts +5 -4
  186. package/dist/tools/listObjectsTool.d.ts.map +1 -1
  187. package/dist/tools/listObjectsTool.js +5 -13
  188. package/dist/tools/listObjectsTool.js.map +1 -1
  189. package/dist/tools/pruneClosedTool.d.ts +4 -3
  190. package/dist/tools/pruneClosedTool.d.ts.map +1 -1
  191. package/dist/tools/pruneClosedTool.js +2 -51
  192. package/dist/tools/pruneClosedTool.js.map +1 -1
  193. package/dist/tools/replaceObjectBodyRegexTool.d.ts +4 -3
  194. package/dist/tools/replaceObjectBodyRegexTool.d.ts.map +1 -1
  195. package/dist/tools/replaceObjectBodyRegexTool.js +2 -80
  196. package/dist/tools/replaceObjectBodyRegexTool.js.map +1 -1
  197. package/dist/tools/updateObjectTool.d.ts +5 -4
  198. package/dist/tools/updateObjectTool.d.ts.map +1 -1
  199. package/dist/tools/updateObjectTool.js +3 -49
  200. package/dist/tools/updateObjectTool.js.map +1 -1
  201. package/dist/validation/__tests__/validateParentType.test.js +5 -5
  202. package/dist/validation/__tests__/validateParentType.test.js.map +1 -1
  203. package/dist/validation/validateParentType.d.ts +1 -1
  204. package/dist/validation/validateParentType.d.ts.map +1 -1
  205. package/dist/validation/validateParentType.js +2 -5
  206. package/dist/validation/validateParentType.js.map +1 -1
  207. package/package.json +1 -1
@@ -84,37 +84,33 @@ describe("E2E CRUD - listObjects", () => {
84
84
  const result = await client.callTool("list_objects", {
85
85
  type: "project",
86
86
  });
87
- const objects = (0, utils_1.parseListObjectsResponse)(result.content[0].text);
87
+ const objects = (0, utils_1.extractObjectIds)(result.content[0].text);
88
88
  expect(objects).toHaveLength(1);
89
- expect(objects[0].id).toBe("P-test-project");
90
- expect(objects[0].type).toBe("project");
89
+ expect(objects[0]).toBe("P-test-project");
91
90
  });
92
91
  it("should list only tasks when type=task", async () => {
93
92
  const result = await client.callTool("list_objects", {
94
93
  type: "task",
95
94
  });
96
- const objects = (0, utils_1.parseListObjectsResponse)(result.content[0].text);
95
+ const objects = (0, utils_1.extractObjectIds)(result.content[0].text);
97
96
  expect(objects).toHaveLength(1);
98
- expect(objects[0].id).toBe("T-test-task");
99
- expect(objects[0].type).toBe("task");
97
+ expect(objects[0]).toBe("T-test-task");
100
98
  });
101
99
  it("should list only epics when type=epic", async () => {
102
100
  const result = await client.callTool("list_objects", {
103
101
  type: "epic",
104
102
  });
105
- const objects = (0, utils_1.parseListObjectsResponse)(result.content[0].text);
103
+ const objects = (0, utils_1.extractObjectIds)(result.content[0].text);
106
104
  expect(objects).toHaveLength(1);
107
- expect(objects[0].id).toBe("E-test-epic");
108
- expect(objects[0].type).toBe("epic");
105
+ expect(objects[0]).toBe("E-test-epic");
109
106
  });
110
107
  it("should list only features when type=feature", async () => {
111
108
  const result = await client.callTool("list_objects", {
112
109
  type: "feature",
113
110
  });
114
- const objects = (0, utils_1.parseListObjectsResponse)(result.content[0].text);
111
+ const objects = (0, utils_1.extractObjectIds)(result.content[0].text);
115
112
  expect(objects).toHaveLength(1);
116
- expect(objects[0].id).toBe("F-test-feature");
117
- expect(objects[0].type).toBe("feature");
113
+ expect(objects[0]).toBe("F-test-feature");
118
114
  });
119
115
  it("should return empty array when no objects of specified type exist", async () => {
120
116
  // Test with a scope that doesn't exist to get empty results
@@ -122,7 +118,7 @@ describe("E2E CRUD - listObjects", () => {
122
118
  type: "task",
123
119
  scope: "E-nonexistent-epic",
124
120
  });
125
- const objects = (0, utils_1.parseListObjectsResponse)(result.content[0].text);
121
+ const objects = (0, utils_1.extractObjectIds)(result.content[0].text);
126
122
  expect(objects).toEqual([]);
127
123
  });
128
124
  });
@@ -145,37 +141,231 @@ describe("E2E CRUD - listObjects", () => {
145
141
  type: "task",
146
142
  status: "in-progress",
147
143
  });
148
- const objects = (0, utils_1.parseListObjectsResponse)(result.content[0].text);
144
+ const objects = (0, utils_1.extractObjectIds)(result.content[0].text);
149
145
  expect(objects).toHaveLength(1);
150
- expect(objects[0].status).toBe("in-progress");
151
146
  });
152
147
  it("should exclude closed tasks by default", async () => {
153
148
  const result = await client.callTool("list_objects", {
154
149
  type: "task",
155
150
  });
156
- const objects = (0, utils_1.parseListObjectsResponse)(result.content[0].text);
157
- const closedTasks = objects.filter((o) => o.status === "done" || o.status === "wont-do");
158
- expect(closedTasks).toHaveLength(0);
151
+ const objects = (0, utils_1.extractObjectIds)(result.content[0].text);
152
+ // Note: Can't filter by status since only IDs are returned
153
+ // Expect only open objects to be returned by default (3 in this case)
154
+ expect(objects).toHaveLength(3);
159
155
  });
160
156
  it("should include closed tasks when includeClosed=true", async () => {
161
157
  const result = await client.callTool("list_objects", {
162
158
  type: "task",
163
159
  includeClosed: true,
164
160
  });
165
- const objects = (0, utils_1.parseListObjectsResponse)(result.content[0].text);
161
+ const objects = (0, utils_1.extractObjectIds)(result.content[0].text);
166
162
  expect(objects).toHaveLength(5);
167
- const closedTasks = objects.filter((o) => o.status === "done" || o.status === "wont-do");
168
- expect(closedTasks).toHaveLength(2);
163
+ // Note: Can't test individual object status since only IDs are returned
169
164
  });
170
165
  it("should filter open tasks correctly", async () => {
171
166
  const result = await client.callTool("list_objects", {
172
167
  type: "task",
173
168
  status: "open",
174
169
  });
175
- const objects = (0, utils_1.parseListObjectsResponse)(result.content[0].text);
170
+ const objects = (0, utils_1.extractObjectIds)(result.content[0].text);
176
171
  expect(objects).toHaveLength(1);
177
- expect(objects[0].status).toBe("open");
178
- expect(objects[0].id).toBe("T-open-task");
172
+ expect(objects[0]).toBe("T-open-task");
173
+ });
174
+ });
175
+ describe("includeClosed Flag with Different Object Types", () => {
176
+ beforeEach(async () => {
177
+ // Create projects with different statuses
178
+ const projectStatuses = [
179
+ { status: "open", folder: "open" },
180
+ { status: "done", folder: "closed" },
181
+ { status: "wont-do", folder: "closed" },
182
+ ];
183
+ for (const config of projectStatuses) {
184
+ await (0, utils_1.createObjectFile)(testEnv.projectRoot, "project", `P-${config.status}-project`, (0, utils_1.createObjectContent)({
185
+ id: `P-${config.status}-project`,
186
+ title: `${config.status} Project`,
187
+ status: config.status,
188
+ }));
189
+ }
190
+ // Create a project first for epics to belong to
191
+ await (0, utils_1.createObjectFile)(testEnv.projectRoot, "project", "P-epic-container", (0, utils_1.createObjectContent)({
192
+ id: "P-epic-container",
193
+ title: "Epic Container Project",
194
+ status: "open",
195
+ }));
196
+ // Create epics with different statuses within the project
197
+ const epicStatuses = [
198
+ { status: "open", folder: "open" },
199
+ { status: "in-progress", folder: "open" },
200
+ { status: "done", folder: "closed" },
201
+ { status: "wont-do", folder: "closed" },
202
+ ];
203
+ for (const config of epicStatuses) {
204
+ await (0, utils_1.createObjectFile)(testEnv.projectRoot, "epic", `E-${config.status}-epic`, (0, utils_1.createObjectContent)({
205
+ id: `E-${config.status}-epic`,
206
+ title: `${config.status} Epic`,
207
+ status: config.status,
208
+ parent: "P-epic-container",
209
+ }), { projectId: "P-epic-container" });
210
+ }
211
+ // Create features with different statuses
212
+ const featureStatuses = [
213
+ { status: "draft", folder: "open" },
214
+ { status: "open", folder: "open" },
215
+ { status: "done", folder: "closed" },
216
+ { status: "wont-do", folder: "closed" },
217
+ ];
218
+ for (const config of featureStatuses) {
219
+ await (0, utils_1.createObjectFile)(testEnv.projectRoot, "feature", `F-${config.status}-feature`, (0, utils_1.createObjectContent)({
220
+ id: `F-${config.status}-feature`,
221
+ title: `${config.status} Feature`,
222
+ status: config.status,
223
+ }));
224
+ }
225
+ // Create tasks with different statuses (already covered in other tests, but adding for completeness)
226
+ const taskStatuses = [
227
+ { status: "draft", folder: "open" },
228
+ { status: "open", folder: "open" },
229
+ { status: "in-progress", folder: "open" },
230
+ { status: "done", folder: "closed" },
231
+ { status: "wont-do", folder: "closed" },
232
+ ];
233
+ for (const config of taskStatuses) {
234
+ await (0, utils_1.createObjectFile)(testEnv.projectRoot, "task", `T-${config.status}-includeclosed`, (0, utils_1.createObjectContent)({
235
+ id: `T-${config.status}-includeclosed`,
236
+ title: `${config.status} Task`,
237
+ status: config.status,
238
+ }), { status: config.folder });
239
+ }
240
+ });
241
+ it("should exclude closed projects by default", async () => {
242
+ const result = await client.callTool("list_objects", {
243
+ type: "project",
244
+ });
245
+ const objects = (0, utils_1.extractObjectIds)(result.content[0].text);
246
+ // Filter to only the objects we created in this test (excluding the epic container)
247
+ const testObjects = objects.filter((id) => id.includes("-project") && !id.includes("epic-container"));
248
+ expect(testObjects).toHaveLength(1);
249
+ expect(testObjects).toContain("P-open-project");
250
+ expect(testObjects).not.toContain("P-done-project");
251
+ expect(testObjects).not.toContain("P-wont-do-project");
252
+ });
253
+ it("should include closed projects when includeClosed=true", async () => {
254
+ const result = await client.callTool("list_objects", {
255
+ type: "project",
256
+ includeClosed: true,
257
+ });
258
+ const objects = (0, utils_1.extractObjectIds)(result.content[0].text);
259
+ // Filter to only the objects we created in this test (excluding the epic container)
260
+ const testObjects = objects.filter((id) => id.includes("-project") && !id.includes("epic-container"));
261
+ expect(testObjects).toHaveLength(3);
262
+ expect(testObjects).toContain("P-open-project");
263
+ expect(testObjects).toContain("P-done-project");
264
+ expect(testObjects).toContain("P-wont-do-project");
265
+ });
266
+ it("should exclude closed epics by default", async () => {
267
+ const result = await client.callTool("list_objects", {
268
+ type: "epic",
269
+ });
270
+ const objects = (0, utils_1.extractObjectIds)(result.content[0].text);
271
+ expect(objects).toHaveLength(2);
272
+ expect(objects).toContain("E-open-epic");
273
+ expect(objects).toContain("E-in-progress-epic");
274
+ expect(objects).not.toContain("E-done-epic");
275
+ expect(objects).not.toContain("E-wont-do-epic");
276
+ });
277
+ it("should include closed epics when includeClosed=true", async () => {
278
+ const result = await client.callTool("list_objects", {
279
+ type: "epic",
280
+ includeClosed: true,
281
+ });
282
+ const objects = (0, utils_1.extractObjectIds)(result.content[0].text);
283
+ expect(objects).toHaveLength(4);
284
+ expect(objects).toContain("E-open-epic");
285
+ expect(objects).toContain("E-in-progress-epic");
286
+ expect(objects).toContain("E-done-epic");
287
+ expect(objects).toContain("E-wont-do-epic");
288
+ });
289
+ it("should exclude closed features by default", async () => {
290
+ const result = await client.callTool("list_objects", {
291
+ type: "feature",
292
+ });
293
+ const objects = (0, utils_1.extractObjectIds)(result.content[0].text);
294
+ expect(objects).toHaveLength(2);
295
+ expect(objects).toContain("F-draft-feature");
296
+ expect(objects).toContain("F-open-feature");
297
+ expect(objects).not.toContain("F-done-feature");
298
+ expect(objects).not.toContain("F-wont-do-feature");
299
+ });
300
+ it("should include closed features when includeClosed=true", async () => {
301
+ const result = await client.callTool("list_objects", {
302
+ type: "feature",
303
+ includeClosed: true,
304
+ });
305
+ const objects = (0, utils_1.extractObjectIds)(result.content[0].text);
306
+ expect(objects).toHaveLength(4);
307
+ expect(objects).toContain("F-draft-feature");
308
+ expect(objects).toContain("F-open-feature");
309
+ expect(objects).toContain("F-done-feature");
310
+ expect(objects).toContain("F-wont-do-feature");
311
+ });
312
+ it("should exclude closed tasks by default", async () => {
313
+ const result = await client.callTool("list_objects", {
314
+ type: "task",
315
+ });
316
+ const objects = (0, utils_1.extractObjectIds)(result.content[0].text);
317
+ // Filter to only the objects we created in this test
318
+ const testObjects = objects.filter((id) => id.includes("includeclosed"));
319
+ expect(testObjects).toHaveLength(3);
320
+ expect(testObjects).toContain("T-draft-includeclosed");
321
+ expect(testObjects).toContain("T-open-includeclosed");
322
+ expect(testObjects).toContain("T-in-progress-includeclosed");
323
+ expect(testObjects).not.toContain("T-done-includeclosed");
324
+ expect(testObjects).not.toContain("T-wont-do-includeclosed");
325
+ });
326
+ it("should include closed tasks when includeClosed=true", async () => {
327
+ const result = await client.callTool("list_objects", {
328
+ type: "task",
329
+ includeClosed: true,
330
+ });
331
+ const objects = (0, utils_1.extractObjectIds)(result.content[0].text);
332
+ // Filter to only the objects we created in this test
333
+ const testObjects = objects.filter((id) => id.includes("includeclosed"));
334
+ expect(testObjects).toHaveLength(5);
335
+ expect(testObjects).toContain("T-draft-includeclosed");
336
+ expect(testObjects).toContain("T-open-includeclosed");
337
+ expect(testObjects).toContain("T-in-progress-includeclosed");
338
+ expect(testObjects).toContain("T-done-includeclosed");
339
+ expect(testObjects).toContain("T-wont-do-includeclosed");
340
+ });
341
+ it("should work with includeClosed and status filters for projects", async () => {
342
+ const result = await client.callTool("list_objects", {
343
+ type: "project",
344
+ status: "done",
345
+ includeClosed: true,
346
+ });
347
+ const objects = (0, utils_1.extractObjectIds)(result.content[0].text);
348
+ expect(objects).toHaveLength(1);
349
+ expect(objects).toContain("P-done-project");
350
+ });
351
+ it("should work with includeClosed and status filters for epics", async () => {
352
+ const result = await client.callTool("list_objects", {
353
+ type: "epic",
354
+ status: "wont-do",
355
+ includeClosed: true,
356
+ });
357
+ const objects = (0, utils_1.extractObjectIds)(result.content[0].text);
358
+ expect(objects).toHaveLength(1);
359
+ expect(objects).toContain("E-wont-do-epic");
360
+ });
361
+ it("should return empty array when status filter requires closed objects but includeClosed=false", async () => {
362
+ const result = await client.callTool("list_objects", {
363
+ type: "feature",
364
+ status: "done",
365
+ includeClosed: false,
366
+ });
367
+ const objects = (0, utils_1.extractObjectIds)(result.content[0].text);
368
+ expect(objects).toEqual([]);
179
369
  });
180
370
  });
181
371
  describe("Priority Filtering", () => {
@@ -194,41 +384,39 @@ describe("E2E CRUD - listObjects", () => {
194
384
  type: "feature",
195
385
  priority: "high",
196
386
  });
197
- const objects = (0, utils_1.parseListObjectsResponse)(result.content[0].text);
387
+ const objects = (0, utils_1.extractObjectIds)(result.content[0].text);
198
388
  expect(objects).toHaveLength(1);
199
- expect(objects[0].priority).toBe("high");
200
- expect(objects[0].id).toBe("F-high-priority");
389
+ expect(objects[0]).toBe("F-high-priority");
201
390
  });
202
391
  it("should filter objects by medium priority", async () => {
203
392
  const result = await client.callTool("list_objects", {
204
393
  type: "feature",
205
394
  priority: "medium",
206
395
  });
207
- const objects = (0, utils_1.parseListObjectsResponse)(result.content[0].text);
396
+ const objects = (0, utils_1.extractObjectIds)(result.content[0].text);
208
397
  expect(objects).toHaveLength(1);
209
- expect(objects[0].priority).toBe("medium");
210
- expect(objects[0].id).toBe("F-medium-priority");
398
+ expect(objects[0]).toBe("F-medium-priority");
211
399
  });
212
400
  it("should filter objects by low priority", async () => {
213
401
  const result = await client.callTool("list_objects", {
214
402
  type: "feature",
215
403
  priority: "low",
216
404
  });
217
- const objects = (0, utils_1.parseListObjectsResponse)(result.content[0].text);
405
+ const objects = (0, utils_1.extractObjectIds)(result.content[0].text);
218
406
  expect(objects).toHaveLength(1);
219
- expect(objects[0].priority).toBe("low");
220
- expect(objects[0].id).toBe("F-low-priority");
407
+ expect(objects[0]).toBe("F-low-priority");
221
408
  });
222
409
  it("should return all priorities when no filter specified", async () => {
223
410
  const result = await client.callTool("list_objects", {
224
411
  type: "feature",
225
412
  });
226
- const objects = (0, utils_1.parseListObjectsResponse)(result.content[0].text);
413
+ const objects = (0, utils_1.extractObjectIds)(result.content[0].text);
227
414
  expect(objects).toHaveLength(3);
228
- const priorities = objects.map((o) => o.priority);
229
- expect(priorities).toContain("high");
230
- expect(priorities).toContain("medium");
231
- expect(priorities).toContain("low");
415
+ // Note: Can't test individual priorities since only IDs are returned
416
+ // Just verify we have all the expected feature IDs
417
+ expect(objects).toContain("F-high-priority");
418
+ expect(objects).toContain("F-medium-priority");
419
+ expect(objects).toContain("F-low-priority");
232
420
  });
233
421
  });
234
422
  describe("Scope Filtering", () => {
@@ -266,35 +454,35 @@ describe("E2E CRUD - listObjects", () => {
266
454
  type: "epic",
267
455
  scope: "P-parent",
268
456
  });
269
- const objects = (0, utils_1.parseListObjectsResponse)(result.content[0].text);
457
+ const objects = (0, utils_1.extractObjectIds)(result.content[0].text);
270
458
  expect(objects).toHaveLength(2);
271
- expect(objects.map((o) => o.id)).toContain("E-child-1");
272
- expect(objects.map((o) => o.id)).toContain("E-child-2");
459
+ expect(objects).toContain("E-child-1");
460
+ expect(objects).toContain("E-child-2");
273
461
  });
274
462
  it("should list objects within epic scope", async () => {
275
463
  const result = await client.callTool("list_objects", {
276
464
  type: "feature",
277
465
  scope: "E-child-1",
278
466
  });
279
- const objects = (0, utils_1.parseListObjectsResponse)(result.content[0].text);
467
+ const objects = (0, utils_1.extractObjectIds)(result.content[0].text);
280
468
  expect(objects).toHaveLength(1);
281
- expect(objects[0].id).toBe("F-grandchild-1");
469
+ expect(objects[0]).toBe("F-grandchild-1");
282
470
  });
283
471
  it("should not include objects outside of scope", async () => {
284
472
  const result = await client.callTool("list_objects", {
285
473
  type: "feature",
286
474
  scope: "P-parent",
287
475
  });
288
- const objects = (0, utils_1.parseListObjectsResponse)(result.content[0].text);
289
- expect(objects.map((o) => o.id)).toContain("F-grandchild-1");
290
- expect(objects.map((o) => o.id)).not.toContain("F-standalone");
476
+ const objects = (0, utils_1.extractObjectIds)(result.content[0].text);
477
+ expect(objects).toContain("F-grandchild-1");
478
+ expect(objects).not.toContain("F-standalone");
291
479
  });
292
480
  it("should return empty array for non-existent scope", async () => {
293
481
  const result = await client.callTool("list_objects", {
294
482
  type: "task",
295
483
  scope: "P-nonexistent",
296
484
  });
297
- const objects = (0, utils_1.parseListObjectsResponse)(result.content[0].text);
485
+ const objects = (0, utils_1.extractObjectIds)(result.content[0].text);
298
486
  expect(objects).toEqual([]);
299
487
  });
300
488
  });
@@ -360,9 +548,9 @@ describe("E2E CRUD - listObjects", () => {
360
548
  priority: "high",
361
549
  scope: "P-complex",
362
550
  });
363
- const objects = (0, utils_1.parseListObjectsResponse)(result.content[0].text);
551
+ const objects = (0, utils_1.extractObjectIds)(result.content[0].text);
364
552
  expect(objects).toHaveLength(1);
365
- expect(objects[0].id).toBe("T-high-open");
553
+ expect(objects[0]).toBe("T-high-open");
366
554
  });
367
555
  it("should combine includeClosed with other filters", async () => {
368
556
  const result = await client.callTool("list_objects", {
@@ -371,10 +559,10 @@ describe("E2E CRUD - listObjects", () => {
371
559
  scope: "P-complex",
372
560
  includeClosed: true,
373
561
  });
374
- const objects = (0, utils_1.parseListObjectsResponse)(result.content[0].text);
562
+ const objects = (0, utils_1.extractObjectIds)(result.content[0].text);
375
563
  expect(objects).toHaveLength(2);
376
- expect(objects.map((o) => o.id)).toContain("T-high-open");
377
- expect(objects.map((o) => o.id)).toContain("T-high-done");
564
+ expect(objects).toContain("T-high-open");
565
+ expect(objects).toContain("T-high-done");
378
566
  });
379
567
  it("should return empty when combined filters match nothing", async () => {
380
568
  const result = await client.callTool("list_objects", {
@@ -383,7 +571,7 @@ describe("E2E CRUD - listObjects", () => {
383
571
  priority: "high",
384
572
  scope: "P-complex",
385
573
  });
386
- const objects = (0, utils_1.parseListObjectsResponse)(result.content[0].text);
574
+ const objects = (0, utils_1.extractObjectIds)(result.content[0].text);
387
575
  expect(objects).toEqual([]);
388
576
  });
389
577
  it("should combine status and priority filters", async () => {
@@ -393,9 +581,9 @@ describe("E2E CRUD - listObjects", () => {
393
581
  priority: "medium",
394
582
  scope: "P-complex",
395
583
  });
396
- const objects = (0, utils_1.parseListObjectsResponse)(result.content[0].text);
584
+ const objects = (0, utils_1.extractObjectIds)(result.content[0].text);
397
585
  expect(objects).toHaveLength(1);
398
- expect(objects[0].id).toBe("T-medium-progress");
586
+ expect(objects[0]).toBe("T-medium-progress");
399
587
  });
400
588
  });
401
589
  describe("Object Structure Validation", () => {
@@ -421,23 +609,10 @@ describe("E2E CRUD - listObjects", () => {
421
609
  const result = await client.callTool("list_objects", {
422
610
  type: "project",
423
611
  });
424
- const objects = (0, utils_1.parseListObjectsResponse)(result.content[0].text);
612
+ const objects = (0, utils_1.extractObjectIds)(result.content[0].text);
425
613
  expect(objects).toHaveLength(1);
426
- const project = objects[0];
427
- expect(project).toMatchObject({
428
- id: "P-detailed",
429
- type: "project",
430
- title: "Detailed Project",
431
- status: "open",
432
- priority: "high",
433
- prerequisites: ["P-dep1", "P-dep2"],
434
- log: ["Created", "Updated"],
435
- schema: "1.1",
436
- childrenIds: ["E-child"],
437
- body: "Project description",
438
- });
439
- // Verify no parent field for projects
440
- expect(project.parent).toBeUndefined();
614
+ // Note: Only object IDs are returned, not full objects
615
+ expect(objects[0]).toBe("P-detailed");
441
616
  });
442
617
  it("should handle objects with minimal fields", async () => {
443
618
  await (0, utils_1.createObjectFile)(testEnv.projectRoot, "task", "T-minimal", (0, utils_1.createObjectContent)({
@@ -447,14 +622,10 @@ describe("E2E CRUD - listObjects", () => {
447
622
  const result = await client.callTool("list_objects", {
448
623
  type: "task",
449
624
  });
450
- const objects = (0, utils_1.parseListObjectsResponse)(result.content[0].text);
451
- const task = objects[0];
452
- expect(task.id).toBe("T-minimal");
453
- expect(task.title).toBe("Minimal Task");
454
- expect(task.status).toBe("open");
455
- expect(task.priority).toBe("medium");
456
- expect(task.prerequisites).toEqual([]);
457
- expect(task.body).toBe("");
625
+ const objects = (0, utils_1.extractObjectIds)(result.content[0].text);
626
+ // Note: Only object IDs are returned, not full objects
627
+ expect(objects[0]).toBe("T-minimal");
628
+ // Note: Only IDs returned, cannot test object properties
458
629
  });
459
630
  it("should preserve object hierarchy relationships", async () => {
460
631
  await (0, utils_1.createObjectFile)(testEnv.projectRoot, "project", "P-hierarchy", (0, utils_1.createObjectContent)({
@@ -485,9 +656,9 @@ describe("E2E CRUD - listObjects", () => {
485
656
  type: "task",
486
657
  scope: "P-hierarchy",
487
658
  });
488
- const objects = (0, utils_1.parseListObjectsResponse)(result.content[0].text);
659
+ const objects = (0, utils_1.extractObjectIds)(result.content[0].text);
489
660
  expect(objects).toHaveLength(1);
490
- expect(objects[0].parent).toBe("F-hierarchy");
661
+ // Note: Only object IDs are returned, not full objects with parent property
491
662
  });
492
663
  });
493
664
  describe("Large Dataset Handling", () => {
@@ -511,15 +682,14 @@ describe("E2E CRUD - listObjects", () => {
511
682
  includeClosed: true,
512
683
  });
513
684
  const duration = Date.now() - startTime;
514
- const objects = (0, utils_1.parseListObjectsResponse)(result.content[0].text);
685
+ const objects = (0, utils_1.extractObjectIds)(result.content[0].text);
515
686
  expect(objects).toHaveLength(NUM_OBJECTS);
516
687
  // Performance check - should complete within reasonable time
517
688
  expect(duration).toBeLessThan(3000);
518
689
  // Verify all objects have correct structure
519
- objects.forEach((obj) => {
520
- expect(obj.id).toMatch(/^T-bulk-\d{3}$/);
521
- expect(obj.type).toBe("task");
522
- expect(obj.title).toMatch(/^Bulk Task \d+$/);
690
+ // Note: Only IDs returned, cannot test object properties
691
+ objects.forEach((id) => {
692
+ expect(id).toMatch(/^T-bulk-\d{3}$/);
523
693
  });
524
694
  });
525
695
  it("should filter large datasets correctly", async () => {
@@ -536,9 +706,9 @@ describe("E2E CRUD - listObjects", () => {
536
706
  type: "feature",
537
707
  priority: "high",
538
708
  });
539
- const objects = (0, utils_1.parseListObjectsResponse)(result.content[0].text);
709
+ const objects = (0, utils_1.extractObjectIds)(result.content[0].text);
710
+ // Note: Only IDs returned, cannot test object properties - just verify count
540
711
  expect(objects).toHaveLength(5);
541
- expect(objects.every((o) => o.priority === "high")).toBe(true);
542
712
  });
543
713
  });
544
714
  describe("Error Handling", () => {
@@ -576,7 +746,7 @@ describe("E2E CRUD - listObjects", () => {
576
746
  const result = await client.callTool("list_objects", {
577
747
  type: "task",
578
748
  });
579
- const objects = (0, utils_1.parseListObjectsResponse)(result.content[0].text);
749
+ const objects = (0, utils_1.extractObjectIds)(result.content[0].text);
580
750
  // Should return empty array or only valid objects
581
751
  expect(Array.isArray(objects)).toBe(true);
582
752
  });
@@ -584,7 +754,7 @@ describe("E2E CRUD - listObjects", () => {
584
754
  const result = await client.callTool("list_objects", {
585
755
  type: "task",
586
756
  });
587
- const objects = (0, utils_1.parseListObjectsResponse)(result.content[0].text);
757
+ const objects = (0, utils_1.extractObjectIds)(result.content[0].text);
588
758
  expect(Array.isArray(objects)).toBe(true);
589
759
  expect(objects).toEqual([]);
590
760
  });