rebar-mcp 2.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 (248) hide show
  1. package/.claude/agents/template-writer.md +43 -0
  2. package/.claude/agents/test-runner.md +47 -0
  3. package/.claude/mcp.json +9 -0
  4. package/.claude/settings.json +29 -0
  5. package/.claude/skills/ /SKILL.md +21 -0
  6. package/.claude/skills/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/SKILL.md +21 -0
  7. package/.claude/skills/bmmibwetxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/SKILL.md +21 -0
  8. package/.claude/skills/bmmibwjgvxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/SKILL.md +21 -0
  9. package/.claude/skills/bmmibwsesxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/SKILL.md +21 -0
  10. package/.claude/skills/bmmibwxufxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/SKILL.md +21 -0
  11. package/.claude/skills/bmmibx3r9xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/SKILL.md +21 -0
  12. package/.claude/skills/bmmji0lrkxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/SKILL.md +21 -0
  13. package/.claude/skills/bmmjiniphxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/SKILL.md +21 -0
  14. package/.claude/skills/bmmjio86zxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/SKILL.md +21 -0
  15. package/.claude/skills/bmmjiolfbxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/SKILL.md +21 -0
  16. package/.claude/skills/bmmjit1lvxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/SKILL.md +21 -0
  17. package/.claude/skills/bmmjita1qxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/SKILL.md +21 -0
  18. package/.claude/skills/bnd-mmibweu3/SKILL.md +21 -0
  19. package/.claude/skills/bnd-mmibwjh4/SKILL.md +21 -0
  20. package/.claude/skills/bnd-mmibwsey/SKILL.md +21 -0
  21. package/.claude/skills/bnd-mmibwxup/SKILL.md +21 -0
  22. package/.claude/skills/bnd-mmibx3rg/SKILL.md +21 -0
  23. package/.claude/skills/bnd-mmji0lrp/SKILL.md +21 -0
  24. package/.claude/skills/bnd-mmjinipm/SKILL.md +21 -0
  25. package/.claude/skills/bnd-mmjio875/SKILL.md +21 -0
  26. package/.claude/skills/bnd-mmjiolfg/SKILL.md +21 -0
  27. package/.claude/skills/bnd-mmjit1m3/SKILL.md +21 -0
  28. package/.claude/skills/bnd-mmjita1x/SKILL.md +21 -0
  29. package/.claude/skills/coercion-test/SKILL.md +50 -0
  30. package/.claude/skills/large-skill/SKILL.md +21 -0
  31. package/.claude/skills/long-desc-skill/SKILL.md +21 -0
  32. package/.claude/skills/mcp-dev/SKILL.md +61 -0
  33. package/.claude/skills/nl-mmibweus/SKILL.md +25 -0
  34. package/.claude/skills/nl-mmibwjhf/SKILL.md +25 -0
  35. package/.claude/skills/nl-mmibwsf7/SKILL.md +25 -0
  36. package/.claude/skills/nl-mmibwxvq/SKILL.md +25 -0
  37. package/.claude/skills/nl-mmibx3rt/SKILL.md +25 -0
  38. package/.claude/skills/nl-mmji0lrz/SKILL.md +25 -0
  39. package/.claude/skills/nl-mmjinipx/SKILL.md +25 -0
  40. package/.claude/skills/nl-mmjio87f/SKILL.md +25 -0
  41. package/.claude/skills/nl-mmjiolfs/SKILL.md +25 -0
  42. package/.claude/skills/nl-mmjit1mc/SKILL.md +25 -0
  43. package/.claude/skills/nl-mmjita26/SKILL.md +25 -0
  44. package/.claude/skills/rapid-1/SKILL.md +21 -0
  45. package/.claude/skills/rapid-2/SKILL.md +21 -0
  46. package/.claude/skills/rapid-3/SKILL.md +21 -0
  47. package/.claude/skills/rapid-4/SKILL.md +21 -0
  48. package/.claude/skills/rapid-5/SKILL.md +21 -0
  49. package/.claude/skills/test/", /"malicious/": /"true/SKILL.md" +69 -0
  50. package/.claude/skills/test-emoji-/360/237/230/200-skill/SKILL.md +69 -0
  51. package/.claude/skills/test-skill/SKILL.md +69 -0
  52. package/.claude/skills/test; rm -rf /; skill/SKILL.md +69 -0
  53. package/.claude/skills/test<script>alert(1)</script>skill/SKILL.md +69 -0
  54. package/.claudeignore +5 -0
  55. package/.mcp.json +3 -0
  56. package/CHANGELOG.md +29 -0
  57. package/CLAUDE.md +76 -0
  58. package/LICENSE +21 -0
  59. package/README.md +149 -0
  60. package/ROADMAP.md +526 -0
  61. package/ccboot-PRD-v1.0.docx.md +732 -0
  62. package/ccboot-v1.2.0-enforcement-spec.md +1272 -0
  63. package/dist/cli.d.ts +3 -0
  64. package/dist/cli.d.ts.map +1 -0
  65. package/dist/cli.js +674 -0
  66. package/dist/cli.js.map +1 -0
  67. package/dist/constants.d.ts +25 -0
  68. package/dist/constants.d.ts.map +1 -0
  69. package/dist/constants.js +118 -0
  70. package/dist/constants.js.map +1 -0
  71. package/dist/index.d.ts +3 -0
  72. package/dist/index.d.ts.map +1 -0
  73. package/dist/index.js +47 -0
  74. package/dist/index.js.map +1 -0
  75. package/dist/schemas/common.d.ts +62 -0
  76. package/dist/schemas/common.d.ts.map +1 -0
  77. package/dist/schemas/common.js +15 -0
  78. package/dist/schemas/common.js.map +1 -0
  79. package/dist/schemas/scaffolding.d.ts +277 -0
  80. package/dist/schemas/scaffolding.d.ts.map +1 -0
  81. package/dist/schemas/scaffolding.js +133 -0
  82. package/dist/schemas/scaffolding.js.map +1 -0
  83. package/dist/services/claudemd-generator.d.ts +16 -0
  84. package/dist/services/claudemd-generator.d.ts.map +1 -0
  85. package/dist/services/claudemd-generator.js +426 -0
  86. package/dist/services/claudemd-generator.js.map +1 -0
  87. package/dist/services/codex-generator.d.ts +6 -0
  88. package/dist/services/codex-generator.d.ts.map +1 -0
  89. package/dist/services/codex-generator.js +35 -0
  90. package/dist/services/codex-generator.js.map +1 -0
  91. package/dist/services/cursor-generator.d.ts +15 -0
  92. package/dist/services/cursor-generator.d.ts.map +1 -0
  93. package/dist/services/cursor-generator.js +134 -0
  94. package/dist/services/cursor-generator.js.map +1 -0
  95. package/dist/services/file-ops.d.ts +48 -0
  96. package/dist/services/file-ops.d.ts.map +1 -0
  97. package/dist/services/file-ops.js +153 -0
  98. package/dist/services/file-ops.js.map +1 -0
  99. package/dist/services/output-formatter.d.ts +57 -0
  100. package/dist/services/output-formatter.d.ts.map +1 -0
  101. package/dist/services/output-formatter.js +88 -0
  102. package/dist/services/output-formatter.js.map +1 -0
  103. package/dist/services/platform-detect.d.ts +14 -0
  104. package/dist/services/platform-detect.d.ts.map +1 -0
  105. package/dist/services/platform-detect.js +63 -0
  106. package/dist/services/platform-detect.js.map +1 -0
  107. package/dist/services/project-analyzer.d.ts +71 -0
  108. package/dist/services/project-analyzer.d.ts.map +1 -0
  109. package/dist/services/project-analyzer.js +595 -0
  110. package/dist/services/project-analyzer.js.map +1 -0
  111. package/dist/services/rules-engine.d.ts +41 -0
  112. package/dist/services/rules-engine.d.ts.map +1 -0
  113. package/dist/services/rules-engine.js +304 -0
  114. package/dist/services/rules-engine.js.map +1 -0
  115. package/dist/services/strictness.d.ts +37 -0
  116. package/dist/services/strictness.d.ts.map +1 -0
  117. package/dist/services/strictness.js +182 -0
  118. package/dist/services/strictness.js.map +1 -0
  119. package/dist/services/template-engine.d.ts +16 -0
  120. package/dist/services/template-engine.d.ts.map +1 -0
  121. package/dist/services/template-engine.js +85 -0
  122. package/dist/services/template-engine.js.map +1 -0
  123. package/dist/services/validation.d.ts +41 -0
  124. package/dist/services/validation.d.ts.map +1 -0
  125. package/dist/services/validation.js +104 -0
  126. package/dist/services/validation.js.map +1 -0
  127. package/dist/services/windsurf-generator.d.ts +15 -0
  128. package/dist/services/windsurf-generator.d.ts.map +1 -0
  129. package/dist/services/windsurf-generator.js +127 -0
  130. package/dist/services/windsurf-generator.js.map +1 -0
  131. package/dist/tests/enforcement.test.d.ts +2 -0
  132. package/dist/tests/enforcement.test.d.ts.map +1 -0
  133. package/dist/tests/enforcement.test.js +541 -0
  134. package/dist/tests/enforcement.test.js.map +1 -0
  135. package/dist/tests/enterprise.test.d.ts +2 -0
  136. package/dist/tests/enterprise.test.d.ts.map +1 -0
  137. package/dist/tests/enterprise.test.js +353 -0
  138. package/dist/tests/enterprise.test.js.map +1 -0
  139. package/dist/tests/fuzzing.test.d.ts +2 -0
  140. package/dist/tests/fuzzing.test.d.ts.map +1 -0
  141. package/dist/tests/fuzzing.test.js +596 -0
  142. package/dist/tests/fuzzing.test.js.map +1 -0
  143. package/dist/tests/knowledge.test.d.ts +2 -0
  144. package/dist/tests/knowledge.test.d.ts.map +1 -0
  145. package/dist/tests/knowledge.test.js +292 -0
  146. package/dist/tests/knowledge.test.js.map +1 -0
  147. package/dist/tests/management.test.d.ts +2 -0
  148. package/dist/tests/management.test.d.ts.map +1 -0
  149. package/dist/tests/management.test.js +338 -0
  150. package/dist/tests/management.test.js.map +1 -0
  151. package/dist/tests/scaffolding.test.d.ts +2 -0
  152. package/dist/tests/scaffolding.test.d.ts.map +1 -0
  153. package/dist/tests/scaffolding.test.js +419 -0
  154. package/dist/tests/scaffolding.test.js.map +1 -0
  155. package/dist/tests/test-utils.d.ts +76 -0
  156. package/dist/tests/test-utils.d.ts.map +1 -0
  157. package/dist/tests/test-utils.js +171 -0
  158. package/dist/tests/test-utils.js.map +1 -0
  159. package/dist/tests/tool-harness.d.ts +18 -0
  160. package/dist/tests/tool-harness.d.ts.map +1 -0
  161. package/dist/tests/tool-harness.js +51 -0
  162. package/dist/tests/tool-harness.js.map +1 -0
  163. package/dist/tools/enterprise.d.ts +8 -0
  164. package/dist/tools/enterprise.d.ts.map +1 -0
  165. package/dist/tools/enterprise.js +571 -0
  166. package/dist/tools/enterprise.js.map +1 -0
  167. package/dist/tools/knowledge.d.ts +7 -0
  168. package/dist/tools/knowledge.d.ts.map +1 -0
  169. package/dist/tools/knowledge.js +120 -0
  170. package/dist/tools/knowledge.js.map +1 -0
  171. package/dist/tools/management.d.ts +10 -0
  172. package/dist/tools/management.d.ts.map +1 -0
  173. package/dist/tools/management.js +1541 -0
  174. package/dist/tools/management.js.map +1 -0
  175. package/dist/tools/scaffolding.d.ts +8 -0
  176. package/dist/tools/scaffolding.d.ts.map +1 -0
  177. package/dist/tools/scaffolding.js +736 -0
  178. package/dist/tools/scaffolding.js.map +1 -0
  179. package/dist/types.d.ts +54 -0
  180. package/dist/types.d.ts.map +1 -0
  181. package/dist/types.js +5 -0
  182. package/dist/types.js.map +1 -0
  183. package/landing/app/layout.tsx +30 -0
  184. package/landing/app/page.tsx +944 -0
  185. package/landing/next-env.d.ts +6 -0
  186. package/landing/next.config.js +6 -0
  187. package/landing/package-lock.json +896 -0
  188. package/landing/package.json +20 -0
  189. package/landing/tsconfig.json +40 -0
  190. package/package.json +49 -0
  191. package/rebar-v2.0.0-platform-spec.md +1567 -0
  192. package/server.json +20 -0
  193. package/src/cli.ts +735 -0
  194. package/src/constants.ts +131 -0
  195. package/src/index.ts +54 -0
  196. package/src/schemas/common.ts +22 -0
  197. package/src/schemas/scaffolding.ts +161 -0
  198. package/src/services/claudemd-generator.ts +481 -0
  199. package/src/services/codex-generator.ts +44 -0
  200. package/src/services/cursor-generator.ts +153 -0
  201. package/src/services/file-ops.ts +172 -0
  202. package/src/services/platform-detect.ts +80 -0
  203. package/src/services/project-analyzer.ts +690 -0
  204. package/src/services/rules-engine.ts +353 -0
  205. package/src/services/strictness.ts +202 -0
  206. package/src/services/template-engine.ts +119 -0
  207. package/src/services/validation.ts +138 -0
  208. package/src/services/windsurf-generator.ts +145 -0
  209. package/src/tests/enforcement.test.ts +794 -0
  210. package/src/tests/enterprise.test.ts +483 -0
  211. package/src/tests/fuzzing.test.ts +690 -0
  212. package/src/tests/knowledge.test.ts +371 -0
  213. package/src/tests/management.test.ts +451 -0
  214. package/src/tests/scaffolding.test.ts +575 -0
  215. package/src/tests/test-utils.ts +206 -0
  216. package/src/tests/tool-harness.ts +70 -0
  217. package/src/tools/enterprise.ts +666 -0
  218. package/src/tools/knowledge.ts +162 -0
  219. package/src/tools/management.ts +1706 -0
  220. package/src/tools/scaffolding.ts +909 -0
  221. package/src/types.ts +93 -0
  222. package/supabase/.temp/cli-latest +1 -0
  223. package/supabase/.temp/gotrue-version +1 -0
  224. package/supabase/.temp/pooler-url +1 -0
  225. package/supabase/.temp/postgres-version +1 -0
  226. package/supabase/.temp/project-ref +1 -0
  227. package/supabase/.temp/rest-version +1 -0
  228. package/supabase/.temp/storage-migration +1 -0
  229. package/supabase/.temp/storage-version +1 -0
  230. package/templates/agents/explore.md +41 -0
  231. package/templates/agents/plan.md +73 -0
  232. package/templates/agents/security-auditor.md +77 -0
  233. package/templates/agents/test-runner.md +60 -0
  234. package/templates/claudemd/fastapi.md +49 -0
  235. package/templates/claudemd/monorepo.md +48 -0
  236. package/templates/claudemd/nextjs.md +52 -0
  237. package/templates/claudemd/react-spa.md +50 -0
  238. package/templates/claudemd/springboot.md +50 -0
  239. package/templates/hooks/danger-blocker.json +11 -0
  240. package/templates/hooks/format-on-write.json +17 -0
  241. package/templates/hooks/lint-on-write.json +16 -0
  242. package/templates/hooks/secret-detector.json +11 -0
  243. package/templates/skills/code-review.md +68 -0
  244. package/templates/skills/documentation.md +62 -0
  245. package/templates/skills/performance-audit.md +80 -0
  246. package/templates/skills/security-scan.md +66 -0
  247. package/templates/skills/test-writer.md +56 -0
  248. package/tsconfig.json +19 -0
@@ -0,0 +1,371 @@
1
+ /**
2
+ * Integration tests for Rebar knowledge tools
3
+ * rebar_create_knowledge, rebar_create_adr
4
+ */
5
+ import { describe, it, before } from "node:test";
6
+ import * as assert from "node:assert";
7
+ import {
8
+ createTestDir,
9
+ createMockProject,
10
+ readTestFile,
11
+ testFileExists,
12
+ assertToolSuccess,
13
+ assertToolError,
14
+ getToolResultText,
15
+ parseToolResultJson,
16
+ } from "./test-utils.js";
17
+ import { initializeTools, invokeTool } from "./tool-harness.js";
18
+
19
+ // Initialize tools before all tests
20
+ before(() => {
21
+ initializeTools();
22
+ });
23
+
24
+ describe("rebar_create_knowledge", () => {
25
+ it("should create a knowledge document in the correct category directory", async () => {
26
+ const { path: testDir, cleanup } = await createTestDir();
27
+
28
+ try {
29
+ const originalCwd = process.cwd();
30
+ process.chdir(testDir);
31
+
32
+ try {
33
+ await createMockProject(testDir);
34
+
35
+ const result = await invokeTool("rebar_create_knowledge", {
36
+ title: "API Design Guidelines",
37
+ category: "api",
38
+ content: "## REST Conventions\n\nUse proper HTTP methods.",
39
+ tags: ["api", "rest", "conventions"],
40
+ });
41
+
42
+ assertToolSuccess(result);
43
+
44
+ assert.ok(
45
+ await testFileExists(testDir, ".claude/docs/api/api-design-guidelines.md"),
46
+ "Knowledge doc should be created in api category"
47
+ );
48
+
49
+ const doc = await readTestFile(
50
+ testDir,
51
+ ".claude/docs/api/api-design-guidelines.md"
52
+ );
53
+ assert.ok(doc, "Document should have content");
54
+ assert.ok(doc.includes("title: API Design Guidelines"), "Should have title in frontmatter");
55
+ assert.ok(doc.includes("category: api"), "Should have category in frontmatter");
56
+ assert.ok(doc.includes("tags: [api, rest, conventions]"), "Should have tags");
57
+ assert.ok(doc.includes("## REST Conventions"), "Should include content");
58
+ } finally {
59
+ process.chdir(originalCwd);
60
+ }
61
+ } finally {
62
+ await cleanup();
63
+ }
64
+ });
65
+
66
+ it("should fail if document with same title already exists", async () => {
67
+ const { path: testDir, cleanup } = await createTestDir();
68
+
69
+ try {
70
+ const originalCwd = process.cwd();
71
+ process.chdir(testDir);
72
+
73
+ try {
74
+ await createMockProject(testDir);
75
+
76
+ // Create first document
77
+ await invokeTool("rebar_create_knowledge", {
78
+ title: "Duplicate Doc",
79
+ category: "runbook",
80
+ content: "First version",
81
+ });
82
+
83
+ // Try to create duplicate
84
+ const result = await invokeTool("rebar_create_knowledge", {
85
+ title: "Duplicate Doc",
86
+ category: "runbook",
87
+ content: "Second version",
88
+ });
89
+
90
+ assertToolError(result);
91
+ const text = getToolResultText(result);
92
+ assert.ok(text.includes("already exists"), "Should mention already exists");
93
+ } finally {
94
+ process.chdir(originalCwd);
95
+ }
96
+ } finally {
97
+ await cleanup();
98
+ }
99
+ });
100
+
101
+ it("should support dry_run mode", async () => {
102
+ const { path: testDir, cleanup } = await createTestDir();
103
+
104
+ try {
105
+ const originalCwd = process.cwd();
106
+ process.chdir(testDir);
107
+
108
+ try {
109
+ await createMockProject(testDir);
110
+
111
+ const result = await invokeTool("rebar_create_knowledge", {
112
+ title: "Dry Run Doc",
113
+ category: "schema",
114
+ content: "Schema definition",
115
+ dry_run: true,
116
+ output_format: "json",
117
+ });
118
+
119
+ assertToolSuccess(result);
120
+
121
+ const parsed = parseToolResultJson<Record<string, unknown>>(result);
122
+ assert.strictEqual(parsed.dry_run, true);
123
+
124
+ // File should not exist
125
+ assert.ok(
126
+ !(await testFileExists(testDir, ".claude/docs/schema/dry-run-doc.md")),
127
+ "Document should NOT be created in dry-run"
128
+ );
129
+ } finally {
130
+ process.chdir(originalCwd);
131
+ }
132
+ } finally {
133
+ await cleanup();
134
+ }
135
+ });
136
+
137
+ it("should create docs in all supported categories", async () => {
138
+ const { path: testDir, cleanup } = await createTestDir();
139
+
140
+ try {
141
+ const originalCwd = process.cwd();
142
+ process.chdir(testDir);
143
+
144
+ try {
145
+ await createMockProject(testDir);
146
+
147
+ const categories = ["adr", "runbook", "api", "schema", "style"] as const;
148
+
149
+ for (const category of categories) {
150
+ const result = await invokeTool("rebar_create_knowledge", {
151
+ title: `Test ${category} doc`,
152
+ category,
153
+ content: `Content for ${category}`,
154
+ });
155
+
156
+ assertToolSuccess(result);
157
+ assert.ok(
158
+ await testFileExists(testDir, `.claude/docs/${category}/test-${category}-doc.md`),
159
+ `Document should be created in ${category} category`
160
+ );
161
+ }
162
+ } finally {
163
+ process.chdir(originalCwd);
164
+ }
165
+ } finally {
166
+ await cleanup();
167
+ }
168
+ });
169
+ });
170
+
171
+ describe("rebar_create_adr", () => {
172
+ it("should create an ADR with proper numbering", async () => {
173
+ const { path: testDir, cleanup } = await createTestDir();
174
+
175
+ try {
176
+ const originalCwd = process.cwd();
177
+ process.chdir(testDir);
178
+
179
+ try {
180
+ await createMockProject(testDir);
181
+
182
+ const result = await invokeTool("rebar_create_adr", {
183
+ title: "Use PostgreSQL for persistence",
184
+ status: "accepted",
185
+ context: "We need a reliable RDBMS for our application data.",
186
+ decision: "Use PostgreSQL with Prisma ORM.",
187
+ consequences: "Need to manage migrations. Get ACID compliance.",
188
+ });
189
+
190
+ assertToolSuccess(result);
191
+
192
+ // Should be numbered 0001
193
+ assert.ok(
194
+ await testFileExists(testDir, ".claude/docs/adr/0001-use-postgresql-for-persistence.md"),
195
+ "ADR should be created with 0001 prefix"
196
+ );
197
+
198
+ const adr = await readTestFile(
199
+ testDir,
200
+ ".claude/docs/adr/0001-use-postgresql-for-persistence.md"
201
+ );
202
+ assert.ok(adr, "ADR should have content");
203
+ assert.ok(adr.includes("# ADR 0001:"), "Should have ADR number in title");
204
+ assert.ok(adr.includes("**Status:** accepted"), "Should have status");
205
+ assert.ok(adr.includes("## Context"), "Should have Context section");
206
+ assert.ok(adr.includes("## Decision"), "Should have Decision section");
207
+ assert.ok(adr.includes("## Consequences"), "Should have Consequences section");
208
+ } finally {
209
+ process.chdir(originalCwd);
210
+ }
211
+ } finally {
212
+ await cleanup();
213
+ }
214
+ });
215
+
216
+ it("should auto-increment ADR numbers", async () => {
217
+ const { path: testDir, cleanup } = await createTestDir();
218
+
219
+ try {
220
+ const originalCwd = process.cwd();
221
+ process.chdir(testDir);
222
+
223
+ try {
224
+ await createMockProject(testDir);
225
+
226
+ // Create first ADR
227
+ await invokeTool("rebar_create_adr", {
228
+ title: "First Decision",
229
+ status: "accepted",
230
+ context: "Context 1",
231
+ decision: "Decision 1",
232
+ consequences: "Consequences 1",
233
+ });
234
+
235
+ // Create second ADR
236
+ const result = await invokeTool("rebar_create_adr", {
237
+ title: "Second Decision",
238
+ status: "proposed",
239
+ context: "Context 2",
240
+ decision: "Decision 2",
241
+ consequences: "Consequences 2",
242
+ });
243
+
244
+ assertToolSuccess(result);
245
+
246
+ // Should be numbered 0002
247
+ assert.ok(
248
+ await testFileExists(testDir, ".claude/docs/adr/0002-second-decision.md"),
249
+ "Second ADR should be 0002"
250
+ );
251
+ } finally {
252
+ process.chdir(originalCwd);
253
+ }
254
+ } finally {
255
+ await cleanup();
256
+ }
257
+ });
258
+
259
+ it("should support all status types", async () => {
260
+ const { path: testDir, cleanup } = await createTestDir();
261
+
262
+ try {
263
+ const originalCwd = process.cwd();
264
+ process.chdir(testDir);
265
+
266
+ try {
267
+ await createMockProject(testDir);
268
+
269
+ const statuses = ["proposed", "accepted", "deprecated"] as const;
270
+
271
+ for (let i = 0; i < statuses.length; i++) {
272
+ const status = statuses[i];
273
+ const result = await invokeTool("rebar_create_adr", {
274
+ title: `ADR with ${status} status`,
275
+ status,
276
+ context: "Test context",
277
+ decision: "Test decision",
278
+ consequences: "Test consequences",
279
+ });
280
+
281
+ assertToolSuccess(result);
282
+
283
+ const num = String(i + 1).padStart(4, "0");
284
+ const adr = await readTestFile(
285
+ testDir,
286
+ `.claude/docs/adr/${num}-adr-with-${status}-status.md`
287
+ );
288
+ assert.ok(adr?.includes(`**Status:** ${status}`), `Should have ${status} status`);
289
+ }
290
+ } finally {
291
+ process.chdir(originalCwd);
292
+ }
293
+ } finally {
294
+ await cleanup();
295
+ }
296
+ });
297
+
298
+ it("should support dry_run mode", async () => {
299
+ const { path: testDir, cleanup } = await createTestDir();
300
+
301
+ try {
302
+ const originalCwd = process.cwd();
303
+ process.chdir(testDir);
304
+
305
+ try {
306
+ await createMockProject(testDir);
307
+
308
+ const result = await invokeTool("rebar_create_adr", {
309
+ title: "Dry Run ADR",
310
+ status: "proposed",
311
+ context: "Test",
312
+ decision: "Test",
313
+ consequences: "Test",
314
+ dry_run: true,
315
+ output_format: "json",
316
+ });
317
+
318
+ assertToolSuccess(result);
319
+
320
+ const parsed = parseToolResultJson<Record<string, unknown>>(result);
321
+ assert.strictEqual(parsed.dry_run, true);
322
+
323
+ // File should not exist
324
+ assert.ok(
325
+ !(await testFileExists(testDir, ".claude/docs/adr/0001-dry-run-adr.md")),
326
+ "ADR should NOT be created in dry-run"
327
+ );
328
+ } finally {
329
+ process.chdir(originalCwd);
330
+ }
331
+ } finally {
332
+ await cleanup();
333
+ }
334
+ });
335
+
336
+ it("should return JSON output when requested", async () => {
337
+ const { path: testDir, cleanup } = await createTestDir();
338
+
339
+ try {
340
+ const originalCwd = process.cwd();
341
+ process.chdir(testDir);
342
+
343
+ try {
344
+ await createMockProject(testDir);
345
+
346
+ const result = await invokeTool("rebar_create_adr", {
347
+ title: "JSON Output Test",
348
+ status: "accepted",
349
+ context: "Test",
350
+ decision: "Test",
351
+ consequences: "Test",
352
+ output_format: "json",
353
+ });
354
+
355
+ assertToolSuccess(result);
356
+
357
+ const parsed = parseToolResultJson<Record<string, unknown>>(result);
358
+ assert.strictEqual(parsed.success, true);
359
+ assert.strictEqual(parsed.operation, "create_adr");
360
+
361
+ const data = parsed.data as Record<string, unknown>;
362
+ assert.strictEqual(data.number, "0001");
363
+ assert.strictEqual(data.status, "accepted");
364
+ } finally {
365
+ process.chdir(originalCwd);
366
+ }
367
+ } finally {
368
+ await cleanup();
369
+ }
370
+ });
371
+ });