@scardis/omnifocus-mcp 0.1.0 → 0.1.2

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 (223) hide show
  1. package/dist/schemas/shapes.d.ts +3 -33
  2. package/dist/schemas/shapes.d.ts.map +1 -1
  3. package/dist/schemas/shapes.js +3 -5
  4. package/dist/schemas/shapes.js.map +1 -1
  5. package/dist/server.js +3 -5
  6. package/dist/server.js.map +1 -1
  7. package/dist/tools/createTask.d.ts +1 -11
  8. package/dist/tools/createTask.d.ts.map +1 -1
  9. package/dist/tools/editTask.d.ts +1 -11
  10. package/dist/tools/editTask.d.ts.map +1 -1
  11. package/dist/tools/index.d.ts +2 -22
  12. package/dist/tools/index.d.ts.map +1 -1
  13. package/package.json +7 -1
  14. package/src/snippets/edit_task.js +4 -6
  15. package/.claude/commands/opsx/apply.md +0 -152
  16. package/.claude/commands/opsx/archive.md +0 -157
  17. package/.claude/commands/opsx/bulk-archive.md +0 -242
  18. package/.claude/commands/opsx/continue.md +0 -114
  19. package/.claude/commands/opsx/explore.md +0 -173
  20. package/.claude/commands/opsx/ff.md +0 -97
  21. package/.claude/commands/opsx/new.md +0 -69
  22. package/.claude/commands/opsx/onboard.md +0 -550
  23. package/.claude/commands/opsx/propose.md +0 -106
  24. package/.claude/commands/opsx/sync.md +0 -134
  25. package/.claude/commands/opsx/verify.md +0 -164
  26. package/.claude/skills/openspec-apply-change/SKILL.md +0 -156
  27. package/.claude/skills/openspec-archive-change/SKILL.md +0 -114
  28. package/.claude/skills/openspec-bulk-archive-change/SKILL.md +0 -246
  29. package/.claude/skills/openspec-continue-change/SKILL.md +0 -118
  30. package/.claude/skills/openspec-explore/SKILL.md +0 -288
  31. package/.claude/skills/openspec-ff-change/SKILL.md +0 -101
  32. package/.claude/skills/openspec-new-change/SKILL.md +0 -74
  33. package/.claude/skills/openspec-onboard/SKILL.md +0 -554
  34. package/.claude/skills/openspec-propose/SKILL.md +0 -110
  35. package/.claude/skills/openspec-sync-specs/SKILL.md +0 -138
  36. package/.claude/skills/openspec-verify-change/SKILL.md +0 -168
  37. package/CONTRIBUTING.md +0 -83
  38. package/openspec/changes/archive/2026-04-09-bootstrap-omnifocus-mcp/.openspec.yaml +0 -2
  39. package/openspec/changes/archive/2026-04-09-bootstrap-omnifocus-mcp/design.md +0 -162
  40. package/openspec/changes/archive/2026-04-09-bootstrap-omnifocus-mcp/proposal.md +0 -49
  41. package/openspec/changes/archive/2026-04-09-bootstrap-omnifocus-mcp/specs/attachments/spec.md +0 -9
  42. package/openspec/changes/archive/2026-04-09-bootstrap-omnifocus-mcp/specs/batch-operations/spec.md +0 -9
  43. package/openspec/changes/archive/2026-04-09-bootstrap-omnifocus-mcp/specs/database-inspection/spec.md +0 -9
  44. package/openspec/changes/archive/2026-04-09-bootstrap-omnifocus-mcp/specs/execution-runtime/spec.md +0 -69
  45. package/openspec/changes/archive/2026-04-09-bootstrap-omnifocus-mcp/specs/folder-management/spec.md +0 -25
  46. package/openspec/changes/archive/2026-04-09-bootstrap-omnifocus-mcp/specs/forecast/spec.md +0 -9
  47. package/openspec/changes/archive/2026-04-09-bootstrap-omnifocus-mcp/specs/identity-resolution/spec.md +0 -45
  48. package/openspec/changes/archive/2026-04-09-bootstrap-omnifocus-mcp/specs/perspective-management/spec.md +0 -9
  49. package/openspec/changes/archive/2026-04-09-bootstrap-omnifocus-mcp/specs/project-management/spec.md +0 -25
  50. package/openspec/changes/archive/2026-04-09-bootstrap-omnifocus-mcp/specs/recurrence/spec.md +0 -9
  51. package/openspec/changes/archive/2026-04-09-bootstrap-omnifocus-mcp/specs/settings/spec.md +0 -9
  52. package/openspec/changes/archive/2026-04-09-bootstrap-omnifocus-mcp/specs/tag-management/spec.md +0 -25
  53. package/openspec/changes/archive/2026-04-09-bootstrap-omnifocus-mcp/specs/task-management/spec.md +0 -29
  54. package/openspec/changes/archive/2026-04-09-bootstrap-omnifocus-mcp/specs/url-automation/spec.md +0 -9
  55. package/openspec/changes/archive/2026-04-09-bootstrap-omnifocus-mcp/specs/window-state/spec.md +0 -9
  56. package/openspec/changes/archive/2026-04-09-bootstrap-omnifocus-mcp/tasks.md +0 -84
  57. package/openspec/changes/archive/2026-04-09-folder-crud/.openspec.yaml +0 -2
  58. package/openspec/changes/archive/2026-04-09-folder-crud/design.md +0 -58
  59. package/openspec/changes/archive/2026-04-09-folder-crud/proposal.md +0 -28
  60. package/openspec/changes/archive/2026-04-09-folder-crud/specs/folder-write/spec.md +0 -45
  61. package/openspec/changes/archive/2026-04-09-folder-crud/tasks.md +0 -41
  62. package/openspec/changes/archive/2026-04-09-folder-tag-list-filtering/.openspec.yaml +0 -2
  63. package/openspec/changes/archive/2026-04-09-folder-tag-list-filtering/design.md +0 -38
  64. package/openspec/changes/archive/2026-04-09-folder-tag-list-filtering/proposal.md +0 -30
  65. package/openspec/changes/archive/2026-04-09-folder-tag-list-filtering/specs/folder-management/spec.md +0 -21
  66. package/openspec/changes/archive/2026-04-09-folder-tag-list-filtering/specs/tag-management/spec.md +0 -21
  67. package/openspec/changes/archive/2026-04-09-folder-tag-list-filtering/tasks.md +0 -35
  68. package/openspec/changes/archive/2026-04-09-move-operations/.openspec.yaml +0 -2
  69. package/openspec/changes/archive/2026-04-09-move-operations/design.md +0 -43
  70. package/openspec/changes/archive/2026-04-09-move-operations/proposal.md +0 -25
  71. package/openspec/changes/archive/2026-04-09-move-operations/specs/move-operations/spec.md +0 -41
  72. package/openspec/changes/archive/2026-04-09-move-operations/tasks.md +0 -40
  73. package/openspec/changes/archive/2026-04-09-project-crud/.openspec.yaml +0 -2
  74. package/openspec/changes/archive/2026-04-09-project-crud/design.md +0 -60
  75. package/openspec/changes/archive/2026-04-09-project-crud/proposal.md +0 -29
  76. package/openspec/changes/archive/2026-04-09-project-crud/specs/project-write/spec.md +0 -74
  77. package/openspec/changes/archive/2026-04-09-project-crud/tasks.md +0 -48
  78. package/openspec/changes/archive/2026-04-09-project-filtering/.openspec.yaml +0 -2
  79. package/openspec/changes/archive/2026-04-09-project-filtering/design.md +0 -52
  80. package/openspec/changes/archive/2026-04-09-project-filtering/proposal.md +0 -26
  81. package/openspec/changes/archive/2026-04-09-project-filtering/specs/project-filtering/spec.md +0 -66
  82. package/openspec/changes/archive/2026-04-09-project-filtering/specs/project-management/spec.md +0 -13
  83. package/openspec/changes/archive/2026-04-09-project-filtering/tasks.md +0 -41
  84. package/openspec/changes/archive/2026-04-09-tag-crud/.openspec.yaml +0 -2
  85. package/openspec/changes/archive/2026-04-09-tag-crud/design.md +0 -45
  86. package/openspec/changes/archive/2026-04-09-tag-crud/proposal.md +0 -28
  87. package/openspec/changes/archive/2026-04-09-tag-crud/specs/tag-write/spec.md +0 -49
  88. package/openspec/changes/archive/2026-04-09-tag-crud/tasks.md +0 -41
  89. package/openspec/changes/archive/2026-04-09-task-crud/.openspec.yaml +0 -2
  90. package/openspec/changes/archive/2026-04-09-task-crud/design.md +0 -62
  91. package/openspec/changes/archive/2026-04-09-task-crud/proposal.md +0 -29
  92. package/openspec/changes/archive/2026-04-09-task-crud/specs/task-management/spec.md +0 -17
  93. package/openspec/changes/archive/2026-04-09-task-crud/specs/task-write/spec.md +0 -89
  94. package/openspec/changes/archive/2026-04-09-task-crud/tasks.md +0 -55
  95. package/openspec/changes/archive/2026-04-09-task-filtering/.openspec.yaml +0 -2
  96. package/openspec/changes/archive/2026-04-09-task-filtering/design.md +0 -61
  97. package/openspec/changes/archive/2026-04-09-task-filtering/proposal.md +0 -26
  98. package/openspec/changes/archive/2026-04-09-task-filtering/specs/task-filtering/spec.md +0 -63
  99. package/openspec/changes/archive/2026-04-09-task-filtering/specs/task-management/spec.md +0 -17
  100. package/openspec/changes/archive/2026-04-09-task-filtering/tasks.md +0 -42
  101. package/openspec/changes/archive/2026-04-10-planned-date/.openspec.yaml +0 -2
  102. package/openspec/changes/archive/2026-04-10-planned-date/design.md +0 -27
  103. package/openspec/changes/archive/2026-04-10-planned-date/proposal.md +0 -29
  104. package/openspec/changes/archive/2026-04-10-planned-date/specs/task-management/spec.md +0 -29
  105. package/openspec/changes/archive/2026-04-10-planned-date/specs/task-write/spec.md +0 -69
  106. package/openspec/changes/archive/2026-04-10-planned-date/tasks.md +0 -26
  107. package/openspec/changes/archive/2026-04-10-task-recurrence/.openspec.yaml +0 -2
  108. package/openspec/changes/archive/2026-04-10-task-recurrence/design.md +0 -81
  109. package/openspec/changes/archive/2026-04-10-task-recurrence/proposal.md +0 -28
  110. package/openspec/changes/archive/2026-04-10-task-recurrence/specs/recurrence/spec.md +0 -47
  111. package/openspec/changes/archive/2026-04-10-task-recurrence/specs/task-management/spec.md +0 -25
  112. package/openspec/changes/archive/2026-04-10-task-recurrence/specs/task-write/spec.md +0 -61
  113. package/openspec/changes/archive/2026-04-10-task-recurrence/tasks.md +0 -39
  114. package/openspec/config.yaml +0 -20
  115. package/openspec/specs/attachments/spec.md +0 -15
  116. package/openspec/specs/batch-operations/spec.md +0 -15
  117. package/openspec/specs/database-inspection/spec.md +0 -15
  118. package/openspec/specs/execution-runtime/spec.md +0 -75
  119. package/openspec/specs/folder-management/spec.md +0 -39
  120. package/openspec/specs/folder-write/spec.md +0 -45
  121. package/openspec/specs/forecast/spec.md +0 -15
  122. package/openspec/specs/identity-resolution/spec.md +0 -51
  123. package/openspec/specs/move-operations/spec.md +0 -41
  124. package/openspec/specs/perspective-management/spec.md +0 -15
  125. package/openspec/specs/project-filtering/spec.md +0 -72
  126. package/openspec/specs/project-management/spec.md +0 -31
  127. package/openspec/specs/project-write/spec.md +0 -79
  128. package/openspec/specs/recurrence/spec.md +0 -51
  129. package/openspec/specs/settings/spec.md +0 -15
  130. package/openspec/specs/tag-management/spec.md +0 -39
  131. package/openspec/specs/tag-write/spec.md +0 -49
  132. package/openspec/specs/task-filtering/spec.md +0 -63
  133. package/openspec/specs/task-management/spec.md +0 -51
  134. package/openspec/specs/task-write/spec.md +0 -115
  135. package/openspec/specs/url-automation/spec.md +0 -15
  136. package/openspec/specs/window-state/spec.md +0 -15
  137. package/scripts/cleanup-fixtures.ts +0 -89
  138. package/server.json +0 -21
  139. package/src/runtime/bridge.ts +0 -97
  140. package/src/runtime/index.ts +0 -4
  141. package/src/runtime/jxaShim.ts +0 -55
  142. package/src/runtime/resultProtocol.ts +0 -62
  143. package/src/runtime/snippetLoader.ts +0 -79
  144. package/src/schemas/enums.ts +0 -32
  145. package/src/schemas/index.ts +0 -38
  146. package/src/schemas/shapes.ts +0 -267
  147. package/src/server.ts +0 -58
  148. package/src/tools/completeProject.ts +0 -21
  149. package/src/tools/completeTask.ts +0 -23
  150. package/src/tools/createFolder.ts +0 -20
  151. package/src/tools/createProject.ts +0 -20
  152. package/src/tools/createTag.ts +0 -20
  153. package/src/tools/createTask.ts +0 -20
  154. package/src/tools/deleteFolder.ts +0 -24
  155. package/src/tools/deleteProject.ts +0 -24
  156. package/src/tools/deleteTag.ts +0 -24
  157. package/src/tools/deleteTask.ts +0 -26
  158. package/src/tools/dropProject.ts +0 -21
  159. package/src/tools/dropTask.ts +0 -23
  160. package/src/tools/editFolder.ts +0 -19
  161. package/src/tools/editProject.ts +0 -20
  162. package/src/tools/editTag.ts +0 -20
  163. package/src/tools/editTask.ts +0 -20
  164. package/src/tools/getFolder.ts +0 -24
  165. package/src/tools/getProject.ts +0 -24
  166. package/src/tools/getTag.ts +0 -24
  167. package/src/tools/getTask.ts +0 -24
  168. package/src/tools/index.ts +0 -85
  169. package/src/tools/listFolders.ts +0 -32
  170. package/src/tools/listProjects.ts +0 -32
  171. package/src/tools/listTags.ts +0 -32
  172. package/src/tools/listTasks.ts +0 -56
  173. package/src/tools/moveProject.ts +0 -20
  174. package/src/tools/moveTask.ts +0 -20
  175. package/src/tools/resolveName.ts +0 -37
  176. package/test/integration/.gitkeep +0 -0
  177. package/test/integration/completeProject.int.test.ts +0 -25
  178. package/test/integration/completeTask.int.test.ts +0 -30
  179. package/test/integration/createFolder.int.test.ts +0 -50
  180. package/test/integration/createProject.int.test.ts +0 -49
  181. package/test/integration/createTag.int.test.ts +0 -52
  182. package/test/integration/createTask.int.test.ts +0 -55
  183. package/test/integration/deleteFolder.int.test.ts +0 -64
  184. package/test/integration/deleteProject.int.test.ts +0 -31
  185. package/test/integration/deleteTag.int.test.ts +0 -61
  186. package/test/integration/deleteTask.int.test.ts +0 -36
  187. package/test/integration/dropProject.int.test.ts +0 -24
  188. package/test/integration/dropTask.int.test.ts +0 -29
  189. package/test/integration/editFolder.int.test.ts +0 -43
  190. package/test/integration/editProject.int.test.ts +0 -39
  191. package/test/integration/editTag.int.test.ts +0 -43
  192. package/test/integration/editTask.int.test.ts +0 -56
  193. package/test/integration/fixtures.ts +0 -219
  194. package/test/integration/getTask.int.test.ts +0 -64
  195. package/test/integration/listFoldersFiltered.int.test.ts +0 -98
  196. package/test/integration/listProjects.int.test.ts +0 -73
  197. package/test/integration/listProjectsFiltered.int.test.ts +0 -96
  198. package/test/integration/listTagsFiltered.int.test.ts +0 -54
  199. package/test/integration/listTasksFiltered.int.test.ts +0 -141
  200. package/test/integration/moveProject.int.test.ts +0 -57
  201. package/test/integration/moveTask.int.test.ts +0 -61
  202. package/test/integration/plannedDate.int.test.ts +0 -72
  203. package/test/integration/preflight.ts +0 -60
  204. package/test/integration/resolveName.int.test.ts +0 -86
  205. package/test/integration/taskRecurrence.int.test.ts +0 -106
  206. package/test/unit/.gitkeep +0 -0
  207. package/test/unit/bridge.injection.test.ts +0 -66
  208. package/test/unit/resultProtocol.test.ts +0 -71
  209. package/test/unit/schemas.createFolder.test.ts +0 -38
  210. package/test/unit/schemas.createProject.test.ts +0 -115
  211. package/test/unit/schemas.createTask.test.ts +0 -87
  212. package/test/unit/schemas.editTag.test.ts +0 -64
  213. package/test/unit/schemas.folderTagFiltering.test.ts +0 -42
  214. package/test/unit/schemas.listProjects.test.ts +0 -44
  215. package/test/unit/schemas.moveOperations.test.ts +0 -60
  216. package/test/unit/schemas.recurrence.test.ts +0 -120
  217. package/test/unit/schemas.test.ts +0 -126
  218. package/test/unit/snippetLoader.test.ts +0 -56
  219. package/test/unit/tools.deleteTask.test.ts +0 -19
  220. package/test/unit/tools.listTasks.test.ts +0 -126
  221. package/tsconfig.json +0 -19
  222. package/vitest.config.ts +0 -8
  223. package/vitest.integration.config.ts +0 -18
@@ -1,120 +0,0 @@
1
- import { describe, it, expect } from "vitest";
2
- import { RepetitionRuleInput, CreateTaskInput, EditTaskInput } from "../../src/schemas/index.js";
3
-
4
- describe("RepetitionRuleInput schema", () => {
5
- it("accepts daily repetition", () => {
6
- expect(() =>
7
- RepetitionRuleInput.parse({ frequency: "daily", interval: 1, method: "fixed" })
8
- ).not.toThrow();
9
- });
10
-
11
- it("accepts weekly repetition with daysOfWeek", () => {
12
- expect(() =>
13
- RepetitionRuleInput.parse({
14
- frequency: "weekly",
15
- interval: 2,
16
- daysOfWeek: ["monday", "wednesday", "friday"],
17
- method: "start",
18
- })
19
- ).not.toThrow();
20
- });
21
-
22
- it("accepts monthly repetition", () => {
23
- expect(() =>
24
- RepetitionRuleInput.parse({ frequency: "monthly", interval: 1, method: "dueDate" })
25
- ).not.toThrow();
26
- });
27
-
28
- it("accepts yearly repetition", () => {
29
- expect(() =>
30
- RepetitionRuleInput.parse({ frequency: "yearly", interval: 1, method: "fixed" })
31
- ).not.toThrow();
32
- });
33
-
34
- it("defaults interval to 1 when omitted", () => {
35
- const result = RepetitionRuleInput.parse({ frequency: "daily", method: "fixed" });
36
- expect(result.interval).toBe(1);
37
- });
38
-
39
- it("rejects daysOfWeek on non-weekly frequency", () => {
40
- expect(() =>
41
- RepetitionRuleInput.parse({
42
- frequency: "daily",
43
- interval: 1,
44
- daysOfWeek: ["monday"],
45
- method: "fixed",
46
- })
47
- ).toThrow();
48
- });
49
-
50
- it("rejects daysOfWeek on monthly frequency", () => {
51
- expect(() =>
52
- RepetitionRuleInput.parse({
53
- frequency: "monthly",
54
- interval: 1,
55
- daysOfWeek: ["tuesday"],
56
- method: "fixed",
57
- })
58
- ).toThrow();
59
- });
60
-
61
- it("rejects interval of zero", () => {
62
- expect(() =>
63
- RepetitionRuleInput.parse({ frequency: "daily", interval: 0, method: "fixed" })
64
- ).toThrow();
65
- });
66
-
67
- it("rejects negative interval", () => {
68
- expect(() =>
69
- RepetitionRuleInput.parse({ frequency: "weekly", interval: -1, method: "fixed" })
70
- ).toThrow();
71
- });
72
-
73
- it("rejects invalid frequency", () => {
74
- expect(() =>
75
- RepetitionRuleInput.parse({ frequency: "hourly", interval: 1, method: "fixed" })
76
- ).toThrow();
77
- });
78
-
79
- it("rejects invalid method", () => {
80
- expect(() =>
81
- RepetitionRuleInput.parse({ frequency: "daily", interval: 1, method: "completion" })
82
- ).toThrow();
83
- });
84
- });
85
-
86
- describe("CreateTaskInput with repetitionRule", () => {
87
- it("accepts task without repetitionRule (backward compat)", () => {
88
- expect(() => CreateTaskInput.parse({ name: "Buy milk" })).not.toThrow();
89
- });
90
-
91
- it("accepts task with repetitionRule", () => {
92
- expect(() =>
93
- CreateTaskInput.parse({
94
- name: "Stand-up",
95
- repetitionRule: { frequency: "daily", interval: 1, method: "fixed" },
96
- })
97
- ).not.toThrow();
98
- });
99
- });
100
-
101
- describe("EditTaskInput with repetitionRule", () => {
102
- it("accepts edit without repetitionRule (leave unchanged)", () => {
103
- expect(() => EditTaskInput.parse({ id: "abc", flagged: true })).not.toThrow();
104
- });
105
-
106
- it("accepts edit with repetitionRule object (set rule)", () => {
107
- expect(() =>
108
- EditTaskInput.parse({
109
- id: "abc",
110
- repetitionRule: { frequency: "weekly", interval: 1, method: "start" },
111
- })
112
- ).not.toThrow();
113
- });
114
-
115
- it("accepts edit with repetitionRule null (clear rule)", () => {
116
- expect(() =>
117
- EditTaskInput.parse({ id: "abc", repetitionRule: null })
118
- ).not.toThrow();
119
- });
120
- });
@@ -1,126 +0,0 @@
1
- import { describe, it, expect } from "vitest";
2
- import {
3
- ProjectType,
4
- ProjectStatus,
5
- TaskStatus,
6
- FolderStatus,
7
- TagStatus,
8
- TaskSummary,
9
- TaskDetail,
10
- ProjectSummary,
11
- FolderSummary,
12
- TagSummary,
13
- } from "../../src/schemas/index.js";
14
-
15
- describe("ProjectType enum", () => {
16
- it("accepts valid values", () => {
17
- expect(ProjectType.parse("parallel")).toBe("parallel");
18
- expect(ProjectType.parse("sequential")).toBe("sequential");
19
- expect(ProjectType.parse("singleActions")).toBe("singleActions");
20
- });
21
-
22
- it("rejects boolean (the sequential-as-boolean regression)", () => {
23
- expect(() => ProjectType.parse(true)).toThrow();
24
- expect(() => ProjectType.parse(false)).toThrow();
25
- });
26
-
27
- it("rejects string 'true' (the sequential-as-string regression)", () => {
28
- expect(() => ProjectType.parse("true")).toThrow();
29
- expect(() => ProjectType.parse("false")).toThrow();
30
- });
31
- });
32
-
33
- describe("ProjectSummary schema", () => {
34
- const valid = {
35
- id: "abc123",
36
- name: "My Project",
37
- folderPath: "Work ▸ Projects",
38
- folderId: "folder1",
39
- status: "active",
40
- type: "parallel",
41
- flagged: false,
42
- };
43
-
44
- it("parses a valid summary", () => {
45
- expect(() => ProjectSummary.parse(valid)).not.toThrow();
46
- });
47
-
48
- it("rejects empty id", () => {
49
- expect(() => ProjectSummary.parse({ ...valid, id: "" })).toThrow();
50
- });
51
-
52
- it("rejects invalid status", () => {
53
- expect(() =>
54
- ProjectSummary.parse({ ...valid, status: "unknown" })
55
- ).toThrow();
56
- });
57
- });
58
-
59
- describe("TaskSummary schema", () => {
60
- const valid = {
61
- id: "t1",
62
- name: "Buy milk",
63
- status: "available",
64
- flagged: false,
65
- containerId: "p1",
66
- containerType: "project",
67
- dueDate: null,
68
- tagIds: [],
69
- };
70
-
71
- it("parses a valid task summary", () => {
72
- expect(() => TaskSummary.parse(valid)).not.toThrow();
73
- });
74
-
75
- it("rejects items-as-string on TaskDetail (the batch_remove_items regression)", () => {
76
- // The regression: passing a serialised JSON string where an array is expected
77
- const detailBase = {
78
- id: "t1", name: "Buy milk", note: "", status: "available",
79
- flagged: false, deferDate: null, dueDate: null, completionDate: null,
80
- estimatedMinutes: null, containerId: "p1", containerType: "project",
81
- };
82
- expect(() =>
83
- TaskDetail.parse({ ...detailBase, tagIds: '["abc"]' })
84
- ).toThrow();
85
- });
86
- });
87
-
88
- describe("FolderSummary schema", () => {
89
- it("parses valid folder summary with null parent", () => {
90
- expect(() =>
91
- FolderSummary.parse({
92
- id: "f1",
93
- name: "Work",
94
- path: "Work",
95
- parentId: null,
96
- status: "active",
97
- })
98
- ).not.toThrow();
99
- });
100
-
101
- it("rejects invalid status", () => {
102
- expect(() =>
103
- FolderSummary.parse({
104
- id: "f1",
105
- name: "Work",
106
- path: "Work",
107
- parentId: null,
108
- status: "onHold", // folders only have active/dropped
109
- })
110
- ).toThrow();
111
- });
112
- });
113
-
114
- describe("TagSummary schema", () => {
115
- it("parses valid tag summary with onHold status", () => {
116
- expect(() =>
117
- TagSummary.parse({
118
- id: "t1",
119
- name: "Waiting",
120
- path: "Waiting",
121
- parentId: null,
122
- status: "onHold",
123
- })
124
- ).not.toThrow();
125
- });
126
- });
@@ -1,56 +0,0 @@
1
- import { describe, it, expect, beforeEach, afterEach } from "vitest";
2
- import { writeFileSync, mkdirSync, rmSync } from "fs";
3
- import { join } from "path";
4
- import { tmpdir } from "os";
5
-
6
- // We test the loader logic directly by pointing it at temp fixture files.
7
- // The real loader uses __dirname-relative paths; we test the core validation
8
- // logic by importing the internals.
9
-
10
- describe("snippet __ARGS__ validation", () => {
11
- // Test the validation logic inline (mirrors snippetLoader.ts exactly)
12
- function validate(content: string, name: string): void {
13
- const matches = content.split("__ARGS__").length - 1;
14
- if (matches === 0) {
15
- throw new Error(`Snippet "${name}" contains no __ARGS__ placeholder.`);
16
- }
17
- if (matches > 1) {
18
- throw new Error(
19
- `Snippet "${name}" contains ${matches} __ARGS__ placeholders. Exactly one is required.`
20
- );
21
- }
22
- }
23
-
24
- it("accepts snippet with exactly one __ARGS__", () => {
25
- expect(() =>
26
- validate("const args = __ARGS__; return args;", "valid")
27
- ).not.toThrow();
28
- });
29
-
30
- it("rejects snippet with zero __ARGS__", () => {
31
- expect(() =>
32
- validate("const x = 1; return x;", "no-placeholder")
33
- ).toThrow(/no __ARGS__ placeholder/);
34
- });
35
-
36
- it("rejects snippet with two __ARGS__", () => {
37
- expect(() =>
38
- validate("const a = __ARGS__; const b = __ARGS__;", "two-placeholders")
39
- ).toThrow(/2 __ARGS__ placeholders/);
40
- });
41
-
42
- it("all real snippets contain exactly one __ARGS__", async () => {
43
- const { readdirSync, readFileSync } = await import("fs");
44
- const { join: pathJoin } = await import("path");
45
- const { fileURLToPath } = await import("url");
46
- const { dirname } = await import("path");
47
- const __dirname = dirname(fileURLToPath(import.meta.url));
48
- const snippetsDir = pathJoin(__dirname, "../../src/snippets");
49
- const files = readdirSync(snippetsDir).filter((f) => f.endsWith(".js"));
50
- expect(files.length).toBeGreaterThan(0);
51
- for (const file of files) {
52
- const content = readFileSync(pathJoin(snippetsDir, file), "utf-8");
53
- expect(() => validate(content, file), `${file}`).not.toThrow();
54
- }
55
- });
56
- });
@@ -1,19 +0,0 @@
1
- import { describe, it, expect } from "vitest";
2
- import { deleteTaskTool } from "../../src/tools/deleteTask.js";
3
-
4
- describe("deleteTask tool description", () => {
5
- it("contains confirmation language", () => {
6
- const desc = deleteTaskTool.description.toLowerCase();
7
- expect(desc).toMatch(/confirm/);
8
- });
9
-
10
- it("mentions permanent deletion", () => {
11
- const desc = deleteTaskTool.description.toLowerCase();
12
- expect(desc).toMatch(/permanent/);
13
- });
14
-
15
- it("warns about subtasks", () => {
16
- const desc = deleteTaskTool.description.toLowerCase();
17
- expect(desc).toMatch(/subtask/);
18
- });
19
- });
@@ -1,126 +0,0 @@
1
- import { describe, it, expect } from "vitest";
2
- import { listTasksSchema } from "../../src/tools/listTasks.js";
3
- import { ListTasksFilter } from "../../src/schemas/index.js";
4
-
5
- describe("listTasks input validation", () => {
6
- it("accepts projectId scope", () => {
7
- expect(() =>
8
- listTasksSchema.parse({ scope: { projectId: "abc" } })
9
- ).not.toThrow();
10
- });
11
-
12
- it("accepts folderId scope", () => {
13
- expect(() =>
14
- listTasksSchema.parse({ scope: { folderId: "f1" } })
15
- ).not.toThrow();
16
- });
17
-
18
- it("accepts inbox scope", () => {
19
- expect(() =>
20
- listTasksSchema.parse({ scope: { inbox: true } })
21
- ).not.toThrow();
22
- });
23
-
24
- it("accepts all scope", () => {
25
- expect(() =>
26
- listTasksSchema.parse({ scope: { all: true } })
27
- ).not.toThrow();
28
- });
29
-
30
- it("rejects scope with both projectId and inbox (mutual exclusivity)", () => {
31
- expect(() =>
32
- listTasksSchema.parse({ scope: { projectId: "abc", inbox: true } })
33
- ).toThrow();
34
- });
35
-
36
- it("rejects scope with both folderId and all", () => {
37
- expect(() =>
38
- listTasksSchema.parse({ scope: { folderId: "f1", all: true } })
39
- ).toThrow();
40
- });
41
-
42
- it("rejects empty scope object (no discriminator)", () => {
43
- expect(() => listTasksSchema.parse({ scope: {} })).toThrow();
44
- });
45
-
46
- it("rejects missing scope", () => {
47
- expect(() => listTasksSchema.parse({})).toThrow();
48
- });
49
-
50
- it("rejects empty projectId string", () => {
51
- expect(() =>
52
- listTasksSchema.parse({ scope: { projectId: "" } })
53
- ).toThrow();
54
- });
55
-
56
- it("accepts filter with flagged", () => {
57
- expect(() =>
58
- listTasksSchema.parse({ scope: { all: true }, filter: { flagged: true } })
59
- ).not.toThrow();
60
- });
61
-
62
- it("accepts filter with status array", () => {
63
- expect(() =>
64
- listTasksSchema.parse({ scope: { all: true }, filter: { status: ["overdue", "dueSoon"] } })
65
- ).not.toThrow();
66
- });
67
-
68
- it("accepts filter with tagId", () => {
69
- expect(() =>
70
- listTasksSchema.parse({ scope: { all: true }, filter: { tagId: "tag123" } })
71
- ).not.toThrow();
72
- });
73
-
74
- it("accepts filter with dueBeforeDate", () => {
75
- expect(() =>
76
- listTasksSchema.parse({ scope: { all: true }, filter: { dueBeforeDate: "2026-04-09T23:59:59.000Z" } })
77
- ).not.toThrow();
78
- });
79
-
80
- it("accepts limit", () => {
81
- expect(() =>
82
- listTasksSchema.parse({ scope: { all: true }, limit: 50 })
83
- ).not.toThrow();
84
- });
85
-
86
- it("rejects non-positive limit", () => {
87
- expect(() =>
88
- listTasksSchema.parse({ scope: { all: true }, limit: 0 })
89
- ).toThrow();
90
- });
91
- });
92
-
93
- describe("ListTasksFilter schema", () => {
94
- it("accepts empty filter object", () => {
95
- expect(() => ListTasksFilter.parse({})).not.toThrow();
96
- });
97
-
98
- it("accepts all valid filter fields", () => {
99
- expect(() =>
100
- ListTasksFilter.parse({
101
- flagged: true,
102
- status: ["available", "overdue"],
103
- tagId: "tag123",
104
- dueBeforeDate: "2026-04-09T23:59:59.000Z",
105
- })
106
- ).not.toThrow();
107
- });
108
-
109
- it("rejects invalid status enum in array", () => {
110
- expect(() =>
111
- ListTasksFilter.parse({ status: ["available", "flying"] })
112
- ).toThrow();
113
- });
114
-
115
- it("rejects non-ISO dueBeforeDate", () => {
116
- expect(() =>
117
- ListTasksFilter.parse({ dueBeforeDate: "April 9, 2026" })
118
- ).toThrow();
119
- });
120
-
121
- it("rejects flagged: false (must be literal true or absent)", () => {
122
- expect(() =>
123
- ListTasksFilter.parse({ flagged: false })
124
- ).toThrow();
125
- });
126
- });
package/tsconfig.json DELETED
@@ -1,19 +0,0 @@
1
- {
2
- "compilerOptions": {
3
- "target": "ES2022",
4
- "module": "ESNext",
5
- "moduleResolution": "bundler",
6
- "lib": ["ES2022"],
7
- "outDir": "dist",
8
- "rootDir": "src",
9
- "strict": true,
10
- "sourceMap": true,
11
- "declaration": true,
12
- "declarationMap": true,
13
- "esModuleInterop": true,
14
- "skipLibCheck": true,
15
- "resolveJsonModule": true
16
- },
17
- "include": ["src/**/*"],
18
- "exclude": ["node_modules", "dist", "test"]
19
- }
package/vitest.config.ts DELETED
@@ -1,8 +0,0 @@
1
- import { defineConfig } from "vitest/config";
2
-
3
- export default defineConfig({
4
- test: {
5
- include: ["test/unit/**/*.test.ts"],
6
- environment: "node",
7
- },
8
- });
@@ -1,18 +0,0 @@
1
- import { defineConfig } from "vitest/config";
2
-
3
- export default defineConfig({
4
- test: {
5
- include: ["test/integration/**/*.int.test.ts"],
6
- environment: "node",
7
- pool: "forks",
8
- poolOptions: {
9
- forks: {
10
- maxForks: 1,
11
- minForks: 1,
12
- },
13
- },
14
- globalSetup: ["./test/integration/preflight.ts"],
15
- testTimeout: 60_000,
16
- hookTimeout: 60_000,
17
- },
18
- });