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.
- package/.claude/agents/template-writer.md +43 -0
- package/.claude/agents/test-runner.md +47 -0
- package/.claude/mcp.json +9 -0
- package/.claude/settings.json +29 -0
- package/.claude/skills/ /SKILL.md +21 -0
- package/.claude/skills/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/SKILL.md +21 -0
- package/.claude/skills/bmmibwetxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/SKILL.md +21 -0
- package/.claude/skills/bmmibwjgvxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/SKILL.md +21 -0
- package/.claude/skills/bmmibwsesxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/SKILL.md +21 -0
- package/.claude/skills/bmmibwxufxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/SKILL.md +21 -0
- package/.claude/skills/bmmibx3r9xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/SKILL.md +21 -0
- package/.claude/skills/bmmji0lrkxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/SKILL.md +21 -0
- package/.claude/skills/bmmjiniphxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/SKILL.md +21 -0
- package/.claude/skills/bmmjio86zxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/SKILL.md +21 -0
- package/.claude/skills/bmmjiolfbxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/SKILL.md +21 -0
- package/.claude/skills/bmmjit1lvxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/SKILL.md +21 -0
- package/.claude/skills/bmmjita1qxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/SKILL.md +21 -0
- package/.claude/skills/bnd-mmibweu3/SKILL.md +21 -0
- package/.claude/skills/bnd-mmibwjh4/SKILL.md +21 -0
- package/.claude/skills/bnd-mmibwsey/SKILL.md +21 -0
- package/.claude/skills/bnd-mmibwxup/SKILL.md +21 -0
- package/.claude/skills/bnd-mmibx3rg/SKILL.md +21 -0
- package/.claude/skills/bnd-mmji0lrp/SKILL.md +21 -0
- package/.claude/skills/bnd-mmjinipm/SKILL.md +21 -0
- package/.claude/skills/bnd-mmjio875/SKILL.md +21 -0
- package/.claude/skills/bnd-mmjiolfg/SKILL.md +21 -0
- package/.claude/skills/bnd-mmjit1m3/SKILL.md +21 -0
- package/.claude/skills/bnd-mmjita1x/SKILL.md +21 -0
- package/.claude/skills/coercion-test/SKILL.md +50 -0
- package/.claude/skills/large-skill/SKILL.md +21 -0
- package/.claude/skills/long-desc-skill/SKILL.md +21 -0
- package/.claude/skills/mcp-dev/SKILL.md +61 -0
- package/.claude/skills/nl-mmibweus/SKILL.md +25 -0
- package/.claude/skills/nl-mmibwjhf/SKILL.md +25 -0
- package/.claude/skills/nl-mmibwsf7/SKILL.md +25 -0
- package/.claude/skills/nl-mmibwxvq/SKILL.md +25 -0
- package/.claude/skills/nl-mmibx3rt/SKILL.md +25 -0
- package/.claude/skills/nl-mmji0lrz/SKILL.md +25 -0
- package/.claude/skills/nl-mmjinipx/SKILL.md +25 -0
- package/.claude/skills/nl-mmjio87f/SKILL.md +25 -0
- package/.claude/skills/nl-mmjiolfs/SKILL.md +25 -0
- package/.claude/skills/nl-mmjit1mc/SKILL.md +25 -0
- package/.claude/skills/nl-mmjita26/SKILL.md +25 -0
- package/.claude/skills/rapid-1/SKILL.md +21 -0
- package/.claude/skills/rapid-2/SKILL.md +21 -0
- package/.claude/skills/rapid-3/SKILL.md +21 -0
- package/.claude/skills/rapid-4/SKILL.md +21 -0
- package/.claude/skills/rapid-5/SKILL.md +21 -0
- package/.claude/skills/test/", /"malicious/": /"true/SKILL.md" +69 -0
- package/.claude/skills/test-emoji-/360/237/230/200-skill/SKILL.md +69 -0
- package/.claude/skills/test-skill/SKILL.md +69 -0
- package/.claude/skills/test; rm -rf /; skill/SKILL.md +69 -0
- package/.claude/skills/test<script>alert(1)</script>skill/SKILL.md +69 -0
- package/.claudeignore +5 -0
- package/.mcp.json +3 -0
- package/CHANGELOG.md +29 -0
- package/CLAUDE.md +76 -0
- package/LICENSE +21 -0
- package/README.md +149 -0
- package/ROADMAP.md +526 -0
- package/ccboot-PRD-v1.0.docx.md +732 -0
- package/ccboot-v1.2.0-enforcement-spec.md +1272 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +674 -0
- package/dist/cli.js.map +1 -0
- package/dist/constants.d.ts +25 -0
- package/dist/constants.d.ts.map +1 -0
- package/dist/constants.js +118 -0
- package/dist/constants.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +47 -0
- package/dist/index.js.map +1 -0
- package/dist/schemas/common.d.ts +62 -0
- package/dist/schemas/common.d.ts.map +1 -0
- package/dist/schemas/common.js +15 -0
- package/dist/schemas/common.js.map +1 -0
- package/dist/schemas/scaffolding.d.ts +277 -0
- package/dist/schemas/scaffolding.d.ts.map +1 -0
- package/dist/schemas/scaffolding.js +133 -0
- package/dist/schemas/scaffolding.js.map +1 -0
- package/dist/services/claudemd-generator.d.ts +16 -0
- package/dist/services/claudemd-generator.d.ts.map +1 -0
- package/dist/services/claudemd-generator.js +426 -0
- package/dist/services/claudemd-generator.js.map +1 -0
- package/dist/services/codex-generator.d.ts +6 -0
- package/dist/services/codex-generator.d.ts.map +1 -0
- package/dist/services/codex-generator.js +35 -0
- package/dist/services/codex-generator.js.map +1 -0
- package/dist/services/cursor-generator.d.ts +15 -0
- package/dist/services/cursor-generator.d.ts.map +1 -0
- package/dist/services/cursor-generator.js +134 -0
- package/dist/services/cursor-generator.js.map +1 -0
- package/dist/services/file-ops.d.ts +48 -0
- package/dist/services/file-ops.d.ts.map +1 -0
- package/dist/services/file-ops.js +153 -0
- package/dist/services/file-ops.js.map +1 -0
- package/dist/services/output-formatter.d.ts +57 -0
- package/dist/services/output-formatter.d.ts.map +1 -0
- package/dist/services/output-formatter.js +88 -0
- package/dist/services/output-formatter.js.map +1 -0
- package/dist/services/platform-detect.d.ts +14 -0
- package/dist/services/platform-detect.d.ts.map +1 -0
- package/dist/services/platform-detect.js +63 -0
- package/dist/services/platform-detect.js.map +1 -0
- package/dist/services/project-analyzer.d.ts +71 -0
- package/dist/services/project-analyzer.d.ts.map +1 -0
- package/dist/services/project-analyzer.js +595 -0
- package/dist/services/project-analyzer.js.map +1 -0
- package/dist/services/rules-engine.d.ts +41 -0
- package/dist/services/rules-engine.d.ts.map +1 -0
- package/dist/services/rules-engine.js +304 -0
- package/dist/services/rules-engine.js.map +1 -0
- package/dist/services/strictness.d.ts +37 -0
- package/dist/services/strictness.d.ts.map +1 -0
- package/dist/services/strictness.js +182 -0
- package/dist/services/strictness.js.map +1 -0
- package/dist/services/template-engine.d.ts +16 -0
- package/dist/services/template-engine.d.ts.map +1 -0
- package/dist/services/template-engine.js +85 -0
- package/dist/services/template-engine.js.map +1 -0
- package/dist/services/validation.d.ts +41 -0
- package/dist/services/validation.d.ts.map +1 -0
- package/dist/services/validation.js +104 -0
- package/dist/services/validation.js.map +1 -0
- package/dist/services/windsurf-generator.d.ts +15 -0
- package/dist/services/windsurf-generator.d.ts.map +1 -0
- package/dist/services/windsurf-generator.js +127 -0
- package/dist/services/windsurf-generator.js.map +1 -0
- package/dist/tests/enforcement.test.d.ts +2 -0
- package/dist/tests/enforcement.test.d.ts.map +1 -0
- package/dist/tests/enforcement.test.js +541 -0
- package/dist/tests/enforcement.test.js.map +1 -0
- package/dist/tests/enterprise.test.d.ts +2 -0
- package/dist/tests/enterprise.test.d.ts.map +1 -0
- package/dist/tests/enterprise.test.js +353 -0
- package/dist/tests/enterprise.test.js.map +1 -0
- package/dist/tests/fuzzing.test.d.ts +2 -0
- package/dist/tests/fuzzing.test.d.ts.map +1 -0
- package/dist/tests/fuzzing.test.js +596 -0
- package/dist/tests/fuzzing.test.js.map +1 -0
- package/dist/tests/knowledge.test.d.ts +2 -0
- package/dist/tests/knowledge.test.d.ts.map +1 -0
- package/dist/tests/knowledge.test.js +292 -0
- package/dist/tests/knowledge.test.js.map +1 -0
- package/dist/tests/management.test.d.ts +2 -0
- package/dist/tests/management.test.d.ts.map +1 -0
- package/dist/tests/management.test.js +338 -0
- package/dist/tests/management.test.js.map +1 -0
- package/dist/tests/scaffolding.test.d.ts +2 -0
- package/dist/tests/scaffolding.test.d.ts.map +1 -0
- package/dist/tests/scaffolding.test.js +419 -0
- package/dist/tests/scaffolding.test.js.map +1 -0
- package/dist/tests/test-utils.d.ts +76 -0
- package/dist/tests/test-utils.d.ts.map +1 -0
- package/dist/tests/test-utils.js +171 -0
- package/dist/tests/test-utils.js.map +1 -0
- package/dist/tests/tool-harness.d.ts +18 -0
- package/dist/tests/tool-harness.d.ts.map +1 -0
- package/dist/tests/tool-harness.js +51 -0
- package/dist/tests/tool-harness.js.map +1 -0
- package/dist/tools/enterprise.d.ts +8 -0
- package/dist/tools/enterprise.d.ts.map +1 -0
- package/dist/tools/enterprise.js +571 -0
- package/dist/tools/enterprise.js.map +1 -0
- package/dist/tools/knowledge.d.ts +7 -0
- package/dist/tools/knowledge.d.ts.map +1 -0
- package/dist/tools/knowledge.js +120 -0
- package/dist/tools/knowledge.js.map +1 -0
- package/dist/tools/management.d.ts +10 -0
- package/dist/tools/management.d.ts.map +1 -0
- package/dist/tools/management.js +1541 -0
- package/dist/tools/management.js.map +1 -0
- package/dist/tools/scaffolding.d.ts +8 -0
- package/dist/tools/scaffolding.d.ts.map +1 -0
- package/dist/tools/scaffolding.js +736 -0
- package/dist/tools/scaffolding.js.map +1 -0
- package/dist/types.d.ts +54 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +5 -0
- package/dist/types.js.map +1 -0
- package/landing/app/layout.tsx +30 -0
- package/landing/app/page.tsx +944 -0
- package/landing/next-env.d.ts +6 -0
- package/landing/next.config.js +6 -0
- package/landing/package-lock.json +896 -0
- package/landing/package.json +20 -0
- package/landing/tsconfig.json +40 -0
- package/package.json +49 -0
- package/rebar-v2.0.0-platform-spec.md +1567 -0
- package/server.json +20 -0
- package/src/cli.ts +735 -0
- package/src/constants.ts +131 -0
- package/src/index.ts +54 -0
- package/src/schemas/common.ts +22 -0
- package/src/schemas/scaffolding.ts +161 -0
- package/src/services/claudemd-generator.ts +481 -0
- package/src/services/codex-generator.ts +44 -0
- package/src/services/cursor-generator.ts +153 -0
- package/src/services/file-ops.ts +172 -0
- package/src/services/platform-detect.ts +80 -0
- package/src/services/project-analyzer.ts +690 -0
- package/src/services/rules-engine.ts +353 -0
- package/src/services/strictness.ts +202 -0
- package/src/services/template-engine.ts +119 -0
- package/src/services/validation.ts +138 -0
- package/src/services/windsurf-generator.ts +145 -0
- package/src/tests/enforcement.test.ts +794 -0
- package/src/tests/enterprise.test.ts +483 -0
- package/src/tests/fuzzing.test.ts +690 -0
- package/src/tests/knowledge.test.ts +371 -0
- package/src/tests/management.test.ts +451 -0
- package/src/tests/scaffolding.test.ts +575 -0
- package/src/tests/test-utils.ts +206 -0
- package/src/tests/tool-harness.ts +70 -0
- package/src/tools/enterprise.ts +666 -0
- package/src/tools/knowledge.ts +162 -0
- package/src/tools/management.ts +1706 -0
- package/src/tools/scaffolding.ts +909 -0
- package/src/types.ts +93 -0
- package/supabase/.temp/cli-latest +1 -0
- package/supabase/.temp/gotrue-version +1 -0
- package/supabase/.temp/pooler-url +1 -0
- package/supabase/.temp/postgres-version +1 -0
- package/supabase/.temp/project-ref +1 -0
- package/supabase/.temp/rest-version +1 -0
- package/supabase/.temp/storage-migration +1 -0
- package/supabase/.temp/storage-version +1 -0
- package/templates/agents/explore.md +41 -0
- package/templates/agents/plan.md +73 -0
- package/templates/agents/security-auditor.md +77 -0
- package/templates/agents/test-runner.md +60 -0
- package/templates/claudemd/fastapi.md +49 -0
- package/templates/claudemd/monorepo.md +48 -0
- package/templates/claudemd/nextjs.md +52 -0
- package/templates/claudemd/react-spa.md +50 -0
- package/templates/claudemd/springboot.md +50 -0
- package/templates/hooks/danger-blocker.json +11 -0
- package/templates/hooks/format-on-write.json +17 -0
- package/templates/hooks/lint-on-write.json +16 -0
- package/templates/hooks/secret-detector.json +11 -0
- package/templates/skills/code-review.md +68 -0
- package/templates/skills/documentation.md +62 -0
- package/templates/skills/performance-audit.md +80 -0
- package/templates/skills/security-scan.md +66 -0
- package/templates/skills/test-writer.md +56 -0
- package/tsconfig.json +19 -0
|
@@ -0,0 +1,292 @@
|
|
|
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 { createTestDir, createMockProject, readTestFile, testFileExists, assertToolSuccess, assertToolError, getToolResultText, parseToolResultJson, } from "./test-utils.js";
|
|
8
|
+
import { initializeTools, invokeTool } from "./tool-harness.js";
|
|
9
|
+
// Initialize tools before all tests
|
|
10
|
+
before(() => {
|
|
11
|
+
initializeTools();
|
|
12
|
+
});
|
|
13
|
+
describe("rebar_create_knowledge", () => {
|
|
14
|
+
it("should create a knowledge document in the correct category directory", async () => {
|
|
15
|
+
const { path: testDir, cleanup } = await createTestDir();
|
|
16
|
+
try {
|
|
17
|
+
const originalCwd = process.cwd();
|
|
18
|
+
process.chdir(testDir);
|
|
19
|
+
try {
|
|
20
|
+
await createMockProject(testDir);
|
|
21
|
+
const result = await invokeTool("rebar_create_knowledge", {
|
|
22
|
+
title: "API Design Guidelines",
|
|
23
|
+
category: "api",
|
|
24
|
+
content: "## REST Conventions\n\nUse proper HTTP methods.",
|
|
25
|
+
tags: ["api", "rest", "conventions"],
|
|
26
|
+
});
|
|
27
|
+
assertToolSuccess(result);
|
|
28
|
+
assert.ok(await testFileExists(testDir, ".claude/docs/api/api-design-guidelines.md"), "Knowledge doc should be created in api category");
|
|
29
|
+
const doc = await readTestFile(testDir, ".claude/docs/api/api-design-guidelines.md");
|
|
30
|
+
assert.ok(doc, "Document should have content");
|
|
31
|
+
assert.ok(doc.includes("title: API Design Guidelines"), "Should have title in frontmatter");
|
|
32
|
+
assert.ok(doc.includes("category: api"), "Should have category in frontmatter");
|
|
33
|
+
assert.ok(doc.includes("tags: [api, rest, conventions]"), "Should have tags");
|
|
34
|
+
assert.ok(doc.includes("## REST Conventions"), "Should include content");
|
|
35
|
+
}
|
|
36
|
+
finally {
|
|
37
|
+
process.chdir(originalCwd);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
finally {
|
|
41
|
+
await cleanup();
|
|
42
|
+
}
|
|
43
|
+
});
|
|
44
|
+
it("should fail if document with same title already exists", async () => {
|
|
45
|
+
const { path: testDir, cleanup } = await createTestDir();
|
|
46
|
+
try {
|
|
47
|
+
const originalCwd = process.cwd();
|
|
48
|
+
process.chdir(testDir);
|
|
49
|
+
try {
|
|
50
|
+
await createMockProject(testDir);
|
|
51
|
+
// Create first document
|
|
52
|
+
await invokeTool("rebar_create_knowledge", {
|
|
53
|
+
title: "Duplicate Doc",
|
|
54
|
+
category: "runbook",
|
|
55
|
+
content: "First version",
|
|
56
|
+
});
|
|
57
|
+
// Try to create duplicate
|
|
58
|
+
const result = await invokeTool("rebar_create_knowledge", {
|
|
59
|
+
title: "Duplicate Doc",
|
|
60
|
+
category: "runbook",
|
|
61
|
+
content: "Second version",
|
|
62
|
+
});
|
|
63
|
+
assertToolError(result);
|
|
64
|
+
const text = getToolResultText(result);
|
|
65
|
+
assert.ok(text.includes("already exists"), "Should mention already exists");
|
|
66
|
+
}
|
|
67
|
+
finally {
|
|
68
|
+
process.chdir(originalCwd);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
finally {
|
|
72
|
+
await cleanup();
|
|
73
|
+
}
|
|
74
|
+
});
|
|
75
|
+
it("should support dry_run mode", async () => {
|
|
76
|
+
const { path: testDir, cleanup } = await createTestDir();
|
|
77
|
+
try {
|
|
78
|
+
const originalCwd = process.cwd();
|
|
79
|
+
process.chdir(testDir);
|
|
80
|
+
try {
|
|
81
|
+
await createMockProject(testDir);
|
|
82
|
+
const result = await invokeTool("rebar_create_knowledge", {
|
|
83
|
+
title: "Dry Run Doc",
|
|
84
|
+
category: "schema",
|
|
85
|
+
content: "Schema definition",
|
|
86
|
+
dry_run: true,
|
|
87
|
+
output_format: "json",
|
|
88
|
+
});
|
|
89
|
+
assertToolSuccess(result);
|
|
90
|
+
const parsed = parseToolResultJson(result);
|
|
91
|
+
assert.strictEqual(parsed.dry_run, true);
|
|
92
|
+
// File should not exist
|
|
93
|
+
assert.ok(!(await testFileExists(testDir, ".claude/docs/schema/dry-run-doc.md")), "Document should NOT be created in dry-run");
|
|
94
|
+
}
|
|
95
|
+
finally {
|
|
96
|
+
process.chdir(originalCwd);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
finally {
|
|
100
|
+
await cleanup();
|
|
101
|
+
}
|
|
102
|
+
});
|
|
103
|
+
it("should create docs in all supported categories", async () => {
|
|
104
|
+
const { path: testDir, cleanup } = await createTestDir();
|
|
105
|
+
try {
|
|
106
|
+
const originalCwd = process.cwd();
|
|
107
|
+
process.chdir(testDir);
|
|
108
|
+
try {
|
|
109
|
+
await createMockProject(testDir);
|
|
110
|
+
const categories = ["adr", "runbook", "api", "schema", "style"];
|
|
111
|
+
for (const category of categories) {
|
|
112
|
+
const result = await invokeTool("rebar_create_knowledge", {
|
|
113
|
+
title: `Test ${category} doc`,
|
|
114
|
+
category,
|
|
115
|
+
content: `Content for ${category}`,
|
|
116
|
+
});
|
|
117
|
+
assertToolSuccess(result);
|
|
118
|
+
assert.ok(await testFileExists(testDir, `.claude/docs/${category}/test-${category}-doc.md`), `Document should be created in ${category} category`);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
finally {
|
|
122
|
+
process.chdir(originalCwd);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
finally {
|
|
126
|
+
await cleanup();
|
|
127
|
+
}
|
|
128
|
+
});
|
|
129
|
+
});
|
|
130
|
+
describe("rebar_create_adr", () => {
|
|
131
|
+
it("should create an ADR with proper numbering", async () => {
|
|
132
|
+
const { path: testDir, cleanup } = await createTestDir();
|
|
133
|
+
try {
|
|
134
|
+
const originalCwd = process.cwd();
|
|
135
|
+
process.chdir(testDir);
|
|
136
|
+
try {
|
|
137
|
+
await createMockProject(testDir);
|
|
138
|
+
const result = await invokeTool("rebar_create_adr", {
|
|
139
|
+
title: "Use PostgreSQL for persistence",
|
|
140
|
+
status: "accepted",
|
|
141
|
+
context: "We need a reliable RDBMS for our application data.",
|
|
142
|
+
decision: "Use PostgreSQL with Prisma ORM.",
|
|
143
|
+
consequences: "Need to manage migrations. Get ACID compliance.",
|
|
144
|
+
});
|
|
145
|
+
assertToolSuccess(result);
|
|
146
|
+
// Should be numbered 0001
|
|
147
|
+
assert.ok(await testFileExists(testDir, ".claude/docs/adr/0001-use-postgresql-for-persistence.md"), "ADR should be created with 0001 prefix");
|
|
148
|
+
const adr = await readTestFile(testDir, ".claude/docs/adr/0001-use-postgresql-for-persistence.md");
|
|
149
|
+
assert.ok(adr, "ADR should have content");
|
|
150
|
+
assert.ok(adr.includes("# ADR 0001:"), "Should have ADR number in title");
|
|
151
|
+
assert.ok(adr.includes("**Status:** accepted"), "Should have status");
|
|
152
|
+
assert.ok(adr.includes("## Context"), "Should have Context section");
|
|
153
|
+
assert.ok(adr.includes("## Decision"), "Should have Decision section");
|
|
154
|
+
assert.ok(adr.includes("## Consequences"), "Should have Consequences section");
|
|
155
|
+
}
|
|
156
|
+
finally {
|
|
157
|
+
process.chdir(originalCwd);
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
finally {
|
|
161
|
+
await cleanup();
|
|
162
|
+
}
|
|
163
|
+
});
|
|
164
|
+
it("should auto-increment ADR numbers", async () => {
|
|
165
|
+
const { path: testDir, cleanup } = await createTestDir();
|
|
166
|
+
try {
|
|
167
|
+
const originalCwd = process.cwd();
|
|
168
|
+
process.chdir(testDir);
|
|
169
|
+
try {
|
|
170
|
+
await createMockProject(testDir);
|
|
171
|
+
// Create first ADR
|
|
172
|
+
await invokeTool("rebar_create_adr", {
|
|
173
|
+
title: "First Decision",
|
|
174
|
+
status: "accepted",
|
|
175
|
+
context: "Context 1",
|
|
176
|
+
decision: "Decision 1",
|
|
177
|
+
consequences: "Consequences 1",
|
|
178
|
+
});
|
|
179
|
+
// Create second ADR
|
|
180
|
+
const result = await invokeTool("rebar_create_adr", {
|
|
181
|
+
title: "Second Decision",
|
|
182
|
+
status: "proposed",
|
|
183
|
+
context: "Context 2",
|
|
184
|
+
decision: "Decision 2",
|
|
185
|
+
consequences: "Consequences 2",
|
|
186
|
+
});
|
|
187
|
+
assertToolSuccess(result);
|
|
188
|
+
// Should be numbered 0002
|
|
189
|
+
assert.ok(await testFileExists(testDir, ".claude/docs/adr/0002-second-decision.md"), "Second ADR should be 0002");
|
|
190
|
+
}
|
|
191
|
+
finally {
|
|
192
|
+
process.chdir(originalCwd);
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
finally {
|
|
196
|
+
await cleanup();
|
|
197
|
+
}
|
|
198
|
+
});
|
|
199
|
+
it("should support all status types", async () => {
|
|
200
|
+
const { path: testDir, cleanup } = await createTestDir();
|
|
201
|
+
try {
|
|
202
|
+
const originalCwd = process.cwd();
|
|
203
|
+
process.chdir(testDir);
|
|
204
|
+
try {
|
|
205
|
+
await createMockProject(testDir);
|
|
206
|
+
const statuses = ["proposed", "accepted", "deprecated"];
|
|
207
|
+
for (let i = 0; i < statuses.length; i++) {
|
|
208
|
+
const status = statuses[i];
|
|
209
|
+
const result = await invokeTool("rebar_create_adr", {
|
|
210
|
+
title: `ADR with ${status} status`,
|
|
211
|
+
status,
|
|
212
|
+
context: "Test context",
|
|
213
|
+
decision: "Test decision",
|
|
214
|
+
consequences: "Test consequences",
|
|
215
|
+
});
|
|
216
|
+
assertToolSuccess(result);
|
|
217
|
+
const num = String(i + 1).padStart(4, "0");
|
|
218
|
+
const adr = await readTestFile(testDir, `.claude/docs/adr/${num}-adr-with-${status}-status.md`);
|
|
219
|
+
assert.ok(adr?.includes(`**Status:** ${status}`), `Should have ${status} status`);
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
finally {
|
|
223
|
+
process.chdir(originalCwd);
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
finally {
|
|
227
|
+
await cleanup();
|
|
228
|
+
}
|
|
229
|
+
});
|
|
230
|
+
it("should support dry_run mode", async () => {
|
|
231
|
+
const { path: testDir, cleanup } = await createTestDir();
|
|
232
|
+
try {
|
|
233
|
+
const originalCwd = process.cwd();
|
|
234
|
+
process.chdir(testDir);
|
|
235
|
+
try {
|
|
236
|
+
await createMockProject(testDir);
|
|
237
|
+
const result = await invokeTool("rebar_create_adr", {
|
|
238
|
+
title: "Dry Run ADR",
|
|
239
|
+
status: "proposed",
|
|
240
|
+
context: "Test",
|
|
241
|
+
decision: "Test",
|
|
242
|
+
consequences: "Test",
|
|
243
|
+
dry_run: true,
|
|
244
|
+
output_format: "json",
|
|
245
|
+
});
|
|
246
|
+
assertToolSuccess(result);
|
|
247
|
+
const parsed = parseToolResultJson(result);
|
|
248
|
+
assert.strictEqual(parsed.dry_run, true);
|
|
249
|
+
// File should not exist
|
|
250
|
+
assert.ok(!(await testFileExists(testDir, ".claude/docs/adr/0001-dry-run-adr.md")), "ADR should NOT be created in dry-run");
|
|
251
|
+
}
|
|
252
|
+
finally {
|
|
253
|
+
process.chdir(originalCwd);
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
finally {
|
|
257
|
+
await cleanup();
|
|
258
|
+
}
|
|
259
|
+
});
|
|
260
|
+
it("should return JSON output when requested", async () => {
|
|
261
|
+
const { path: testDir, cleanup } = await createTestDir();
|
|
262
|
+
try {
|
|
263
|
+
const originalCwd = process.cwd();
|
|
264
|
+
process.chdir(testDir);
|
|
265
|
+
try {
|
|
266
|
+
await createMockProject(testDir);
|
|
267
|
+
const result = await invokeTool("rebar_create_adr", {
|
|
268
|
+
title: "JSON Output Test",
|
|
269
|
+
status: "accepted",
|
|
270
|
+
context: "Test",
|
|
271
|
+
decision: "Test",
|
|
272
|
+
consequences: "Test",
|
|
273
|
+
output_format: "json",
|
|
274
|
+
});
|
|
275
|
+
assertToolSuccess(result);
|
|
276
|
+
const parsed = parseToolResultJson(result);
|
|
277
|
+
assert.strictEqual(parsed.success, true);
|
|
278
|
+
assert.strictEqual(parsed.operation, "create_adr");
|
|
279
|
+
const data = parsed.data;
|
|
280
|
+
assert.strictEqual(data.number, "0001");
|
|
281
|
+
assert.strictEqual(data.status, "accepted");
|
|
282
|
+
}
|
|
283
|
+
finally {
|
|
284
|
+
process.chdir(originalCwd);
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
finally {
|
|
288
|
+
await cleanup();
|
|
289
|
+
}
|
|
290
|
+
});
|
|
291
|
+
});
|
|
292
|
+
//# sourceMappingURL=knowledge.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"knowledge.test.js","sourceRoot":"","sources":["../../src/tests/knowledge.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"management.test.d.ts","sourceRoot":"","sources":["../../src/tests/management.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,338 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Integration tests for management tools
|
|
3
|
+
* rebar_list_artifacts, rebar_validate_config, rebar_audit_context
|
|
4
|
+
*/
|
|
5
|
+
import { describe, it, before } from "node:test";
|
|
6
|
+
import * as assert from "node:assert";
|
|
7
|
+
import * as fs from "node:fs/promises";
|
|
8
|
+
import * as path from "node:path";
|
|
9
|
+
import { createTestDir, createMockProject, readTestFile, assertToolSuccess, getToolResultText, parseToolResultJson, createMinimalClaudeMd, createMinimalSkill, } from "./test-utils.js";
|
|
10
|
+
import { initializeTools, invokeTool } from "./tool-harness.js";
|
|
11
|
+
// Initialize tools before all tests
|
|
12
|
+
before(() => {
|
|
13
|
+
initializeTools();
|
|
14
|
+
});
|
|
15
|
+
describe("rebar_list_artifacts", () => {
|
|
16
|
+
// TODO: This test is flaky due to file system timing issues in temp directories
|
|
17
|
+
// The tool returns empty artifacts even though files exist - needs investigation
|
|
18
|
+
it.skip("should list all artifacts in a configured project", async () => {
|
|
19
|
+
const { path: testDir, cleanup } = await createTestDir();
|
|
20
|
+
try {
|
|
21
|
+
await createMockProject(testDir, {
|
|
22
|
+
existingClaudeMd: createMinimalClaudeMd(),
|
|
23
|
+
existingSettings: { permissions: { allow: [] } },
|
|
24
|
+
});
|
|
25
|
+
// Create a skill
|
|
26
|
+
const skillDir = path.join(testDir, ".claude/skills/test-skill");
|
|
27
|
+
await fs.mkdir(skillDir, { recursive: true });
|
|
28
|
+
await fs.writeFile(path.join(skillDir, "SKILL.md"), createMinimalSkill("test-skill", "A test skill"));
|
|
29
|
+
// Use JSON output for more reliable assertions
|
|
30
|
+
const result = await invokeTool("rebar_list_artifacts", {
|
|
31
|
+
project_path: testDir,
|
|
32
|
+
output_format: "json",
|
|
33
|
+
});
|
|
34
|
+
assertToolSuccess(result);
|
|
35
|
+
const parsed = parseToolResultJson(result);
|
|
36
|
+
// Detailed debugging
|
|
37
|
+
const debugInfo = `
|
|
38
|
+
Full response: ${JSON.stringify(parsed, null, 2)}
|
|
39
|
+
Project path: ${testDir}
|
|
40
|
+
Data keys: ${Object.keys(parsed.data || {}).join(", ")}
|
|
41
|
+
`;
|
|
42
|
+
assert.strictEqual(parsed.success, true, `Tool should succeed. ${debugInfo}`);
|
|
43
|
+
const data = parsed.data;
|
|
44
|
+
const artifacts = data.artifacts || [];
|
|
45
|
+
// Check we found the expected artifacts
|
|
46
|
+
const types = artifacts.map(a => a.type);
|
|
47
|
+
assert.ok(types.includes("claudemd"), `Should find CLAUDE.md. ${debugInfo}`);
|
|
48
|
+
assert.ok(types.includes("skill"), `Should find skill. Found types: ${types.join(", ")}`);
|
|
49
|
+
assert.ok(types.includes("settings"), `Should find settings. Found types: ${types.join(", ")}`);
|
|
50
|
+
}
|
|
51
|
+
finally {
|
|
52
|
+
await cleanup();
|
|
53
|
+
}
|
|
54
|
+
});
|
|
55
|
+
it("should filter by artifact type", async () => {
|
|
56
|
+
const { path: testDir, cleanup } = await createTestDir();
|
|
57
|
+
try {
|
|
58
|
+
await createMockProject(testDir, {
|
|
59
|
+
existingClaudeMd: createMinimalClaudeMd(),
|
|
60
|
+
existingSettings: { permissions: { allow: [] } },
|
|
61
|
+
});
|
|
62
|
+
// Create a skill
|
|
63
|
+
const skillDir = path.join(testDir, ".claude/skills/filter-test");
|
|
64
|
+
await fs.mkdir(skillDir, { recursive: true });
|
|
65
|
+
await fs.writeFile(path.join(skillDir, "SKILL.md"), createMinimalSkill("filter-test", "Filter test skill"));
|
|
66
|
+
const result = await invokeTool("rebar_list_artifacts", {
|
|
67
|
+
project_path: testDir,
|
|
68
|
+
type_filter: "skill",
|
|
69
|
+
});
|
|
70
|
+
assertToolSuccess(result);
|
|
71
|
+
const text = getToolResultText(result);
|
|
72
|
+
assert.ok(text.includes("SKILL"), "Should list skills");
|
|
73
|
+
assert.ok(!text.includes("CLAUDEMD"), "Should NOT list CLAUDE.md when filtering");
|
|
74
|
+
}
|
|
75
|
+
finally {
|
|
76
|
+
await cleanup();
|
|
77
|
+
}
|
|
78
|
+
});
|
|
79
|
+
it("should show 'no artifacts' message for empty project", async () => {
|
|
80
|
+
const { path: testDir, cleanup } = await createTestDir();
|
|
81
|
+
try {
|
|
82
|
+
// Create minimal project without Claude artifacts
|
|
83
|
+
await fs.mkdir(testDir, { recursive: true });
|
|
84
|
+
await fs.writeFile(path.join(testDir, "package.json"), JSON.stringify({ name: "empty-project" }));
|
|
85
|
+
const result = await invokeTool("rebar_list_artifacts", {
|
|
86
|
+
project_path: testDir,
|
|
87
|
+
});
|
|
88
|
+
assertToolSuccess(result);
|
|
89
|
+
const text = getToolResultText(result);
|
|
90
|
+
assert.ok(text.includes("No Claude Code artifacts") || text.includes("artifacts: []"), "Should indicate no artifacts found");
|
|
91
|
+
}
|
|
92
|
+
finally {
|
|
93
|
+
await cleanup();
|
|
94
|
+
}
|
|
95
|
+
});
|
|
96
|
+
it("should return JSON output when requested", async () => {
|
|
97
|
+
const { path: testDir, cleanup } = await createTestDir();
|
|
98
|
+
try {
|
|
99
|
+
await createMockProject(testDir, {
|
|
100
|
+
existingClaudeMd: createMinimalClaudeMd(),
|
|
101
|
+
});
|
|
102
|
+
const result = await invokeTool("rebar_list_artifacts", {
|
|
103
|
+
project_path: testDir,
|
|
104
|
+
output_format: "json",
|
|
105
|
+
});
|
|
106
|
+
assertToolSuccess(result);
|
|
107
|
+
const parsed = parseToolResultJson(result);
|
|
108
|
+
assert.strictEqual(parsed.success, true);
|
|
109
|
+
assert.strictEqual(parsed.operation, "list_artifacts");
|
|
110
|
+
const data = parsed.data;
|
|
111
|
+
assert.ok(Array.isArray(data.artifacts), "Should have artifacts array");
|
|
112
|
+
}
|
|
113
|
+
finally {
|
|
114
|
+
await cleanup();
|
|
115
|
+
}
|
|
116
|
+
});
|
|
117
|
+
});
|
|
118
|
+
describe("rebar_validate_config", () => {
|
|
119
|
+
it("should pass validation for well-structured config", async () => {
|
|
120
|
+
const { path: testDir, cleanup } = await createTestDir();
|
|
121
|
+
try {
|
|
122
|
+
await createMockProject(testDir, {
|
|
123
|
+
existingClaudeMd: createMinimalClaudeMd(),
|
|
124
|
+
existingSettings: {
|
|
125
|
+
permissions: { allow: [], deny: [] },
|
|
126
|
+
hooks: {
|
|
127
|
+
PreToolCall: [
|
|
128
|
+
{ command: "echo test", description: "Test hook" },
|
|
129
|
+
],
|
|
130
|
+
},
|
|
131
|
+
},
|
|
132
|
+
});
|
|
133
|
+
const result = await invokeTool("rebar_validate_config", {
|
|
134
|
+
project_path: testDir,
|
|
135
|
+
});
|
|
136
|
+
assertToolSuccess(result);
|
|
137
|
+
const text = getToolResultText(result);
|
|
138
|
+
assert.ok(text.includes("PASSED") || text.includes("valid"), "Should pass validation");
|
|
139
|
+
}
|
|
140
|
+
finally {
|
|
141
|
+
await cleanup();
|
|
142
|
+
}
|
|
143
|
+
});
|
|
144
|
+
it("should report errors for missing CLAUDE.md", async () => {
|
|
145
|
+
const { path: testDir, cleanup } = await createTestDir();
|
|
146
|
+
try {
|
|
147
|
+
await createMockProject(testDir);
|
|
148
|
+
// Don't create CLAUDE.md
|
|
149
|
+
const result = await invokeTool("rebar_validate_config", {
|
|
150
|
+
project_path: testDir,
|
|
151
|
+
});
|
|
152
|
+
assertToolSuccess(result); // Tool succeeds but reports errors
|
|
153
|
+
const text = getToolResultText(result);
|
|
154
|
+
assert.ok(text.includes("No CLAUDE.md") || text.includes("error"), "Should report missing CLAUDE.md");
|
|
155
|
+
}
|
|
156
|
+
finally {
|
|
157
|
+
await cleanup();
|
|
158
|
+
}
|
|
159
|
+
});
|
|
160
|
+
it("should report errors for invalid JSON in settings", async () => {
|
|
161
|
+
const { path: testDir, cleanup } = await createTestDir();
|
|
162
|
+
try {
|
|
163
|
+
await createMockProject(testDir, {
|
|
164
|
+
existingClaudeMd: createMinimalClaudeMd(),
|
|
165
|
+
});
|
|
166
|
+
// Create invalid JSON settings
|
|
167
|
+
await fs.mkdir(path.join(testDir, ".claude"), { recursive: true });
|
|
168
|
+
await fs.writeFile(path.join(testDir, ".claude/settings.json"), "{ invalid json }");
|
|
169
|
+
const result = await invokeTool("rebar_validate_config", {
|
|
170
|
+
project_path: testDir,
|
|
171
|
+
});
|
|
172
|
+
assertToolSuccess(result);
|
|
173
|
+
const text = getToolResultText(result);
|
|
174
|
+
assert.ok(text.includes("FAILED") || text.includes("error") || text.includes("invalid"), "Should report JSON error");
|
|
175
|
+
}
|
|
176
|
+
finally {
|
|
177
|
+
await cleanup();
|
|
178
|
+
}
|
|
179
|
+
});
|
|
180
|
+
it("should return isError=true in CI mode when validation fails", async () => {
|
|
181
|
+
const { path: testDir, cleanup } = await createTestDir();
|
|
182
|
+
try {
|
|
183
|
+
await createMockProject(testDir);
|
|
184
|
+
// No CLAUDE.md = validation error
|
|
185
|
+
const result = await invokeTool("rebar_validate_config", {
|
|
186
|
+
project_path: testDir,
|
|
187
|
+
ci_mode: true,
|
|
188
|
+
});
|
|
189
|
+
// In CI mode with errors, should return isError: true
|
|
190
|
+
assert.ok(result.isError, "Should return isError=true in CI mode with failures");
|
|
191
|
+
// Should be JSON output
|
|
192
|
+
const parsed = parseToolResultJson(result);
|
|
193
|
+
assert.strictEqual(parsed.success, false, "success should be false");
|
|
194
|
+
assert.ok(parsed.ci_mode || parsed.data?.ci_mode, "Should include ci_mode flag");
|
|
195
|
+
}
|
|
196
|
+
finally {
|
|
197
|
+
await cleanup();
|
|
198
|
+
}
|
|
199
|
+
});
|
|
200
|
+
it("should not return isError in CI mode when validation passes", async () => {
|
|
201
|
+
const { path: testDir, cleanup } = await createTestDir();
|
|
202
|
+
try {
|
|
203
|
+
await createMockProject(testDir, {
|
|
204
|
+
existingClaudeMd: createMinimalClaudeMd(),
|
|
205
|
+
});
|
|
206
|
+
const result = await invokeTool("rebar_validate_config", {
|
|
207
|
+
project_path: testDir,
|
|
208
|
+
ci_mode: true,
|
|
209
|
+
});
|
|
210
|
+
// In CI mode without errors, should NOT have isError
|
|
211
|
+
assert.ok(!result.isError, "Should NOT return isError when validation passes");
|
|
212
|
+
}
|
|
213
|
+
finally {
|
|
214
|
+
await cleanup();
|
|
215
|
+
}
|
|
216
|
+
});
|
|
217
|
+
it("should auto-fix trailing commas in JSON when fix_mode is auto_fix", async () => {
|
|
218
|
+
const { path: testDir, cleanup } = await createTestDir();
|
|
219
|
+
try {
|
|
220
|
+
await createMockProject(testDir, {
|
|
221
|
+
existingClaudeMd: createMinimalClaudeMd(),
|
|
222
|
+
});
|
|
223
|
+
// Create settings with trailing comma (fixable)
|
|
224
|
+
await fs.mkdir(path.join(testDir, ".claude"), { recursive: true });
|
|
225
|
+
await fs.writeFile(path.join(testDir, ".claude/settings.json"), '{ "permissions": { "allow": [], }, }');
|
|
226
|
+
const result = await invokeTool("rebar_validate_config", {
|
|
227
|
+
project_path: testDir,
|
|
228
|
+
fix_mode: "auto_fix",
|
|
229
|
+
});
|
|
230
|
+
assertToolSuccess(result);
|
|
231
|
+
const text = getToolResultText(result);
|
|
232
|
+
assert.ok(text.includes("Fixed") || text.includes("fix"), "Should indicate fix was applied");
|
|
233
|
+
// Verify file was fixed
|
|
234
|
+
const settings = await readTestFile(testDir, ".claude/settings.json");
|
|
235
|
+
assert.ok(settings, "Settings file should exist");
|
|
236
|
+
// Should be parseable now
|
|
237
|
+
assert.doesNotThrow(() => JSON.parse(settings), "Fixed JSON should be valid");
|
|
238
|
+
}
|
|
239
|
+
finally {
|
|
240
|
+
await cleanup();
|
|
241
|
+
}
|
|
242
|
+
});
|
|
243
|
+
});
|
|
244
|
+
describe("rebar_audit_context", () => {
|
|
245
|
+
it("should report context budget for configured project", async () => {
|
|
246
|
+
const { path: testDir, cleanup } = await createTestDir();
|
|
247
|
+
try {
|
|
248
|
+
await createMockProject(testDir, {
|
|
249
|
+
existingClaudeMd: createMinimalClaudeMd(),
|
|
250
|
+
});
|
|
251
|
+
const result = await invokeTool("rebar_audit_context", {
|
|
252
|
+
project_path: testDir,
|
|
253
|
+
});
|
|
254
|
+
assertToolSuccess(result);
|
|
255
|
+
const text = getToolResultText(result);
|
|
256
|
+
assert.ok(text.includes("Context Budget"), "Should show Context Budget header");
|
|
257
|
+
assert.ok(text.includes("CLAUDE.md"), "Should show CLAUDE.md tokens");
|
|
258
|
+
assert.ok(text.includes("tokens"), "Should show token counts");
|
|
259
|
+
assert.ok(text.includes("%"), "Should show percentage");
|
|
260
|
+
}
|
|
261
|
+
finally {
|
|
262
|
+
await cleanup();
|
|
263
|
+
}
|
|
264
|
+
});
|
|
265
|
+
it("should warn about large skills", async () => {
|
|
266
|
+
const { path: testDir, cleanup } = await createTestDir();
|
|
267
|
+
try {
|
|
268
|
+
await createMockProject(testDir, {
|
|
269
|
+
existingClaudeMd: createMinimalClaudeMd(),
|
|
270
|
+
});
|
|
271
|
+
// Create a large skill (> 500 tokens)
|
|
272
|
+
const skillDir = path.join(testDir, ".claude/skills/large-skill");
|
|
273
|
+
await fs.mkdir(skillDir, { recursive: true });
|
|
274
|
+
// Generate content that's roughly 600+ tokens
|
|
275
|
+
const largeContent = createMinimalSkill("large-skill", "A very large skill") +
|
|
276
|
+
"\n" +
|
|
277
|
+
"Instructions: ".repeat(200) +
|
|
278
|
+
"\nThis skill does many things.\n".repeat(100);
|
|
279
|
+
await fs.writeFile(path.join(skillDir, "SKILL.md"), largeContent);
|
|
280
|
+
const result = await invokeTool("rebar_audit_context", {
|
|
281
|
+
project_path: testDir,
|
|
282
|
+
});
|
|
283
|
+
assertToolSuccess(result);
|
|
284
|
+
const text = getToolResultText(result);
|
|
285
|
+
// Should warn about large skill
|
|
286
|
+
assert.ok(text.includes("large-skill") && (text.includes("⚠") || text.includes("warning")), "Should warn about large skill");
|
|
287
|
+
}
|
|
288
|
+
finally {
|
|
289
|
+
await cleanup();
|
|
290
|
+
}
|
|
291
|
+
});
|
|
292
|
+
it("should return JSON output when requested", async () => {
|
|
293
|
+
const { path: testDir, cleanup } = await createTestDir();
|
|
294
|
+
try {
|
|
295
|
+
await createMockProject(testDir, {
|
|
296
|
+
existingClaudeMd: createMinimalClaudeMd(),
|
|
297
|
+
});
|
|
298
|
+
const result = await invokeTool("rebar_audit_context", {
|
|
299
|
+
project_path: testDir,
|
|
300
|
+
output_format: "json",
|
|
301
|
+
});
|
|
302
|
+
assertToolSuccess(result);
|
|
303
|
+
const parsed = parseToolResultJson(result);
|
|
304
|
+
assert.strictEqual(parsed.success, true);
|
|
305
|
+
assert.strictEqual(parsed.operation, "audit_context");
|
|
306
|
+
const data = parsed.data;
|
|
307
|
+
assert.ok(data.tokens, "Should have tokens breakdown");
|
|
308
|
+
assert.ok(data.budget, "Should have budget info");
|
|
309
|
+
const tokens = data.tokens;
|
|
310
|
+
assert.ok(typeof tokens.claudemd === "number", "Should have claudemd token count");
|
|
311
|
+
assert.ok(typeof tokens.total === "number", "Should have total token count");
|
|
312
|
+
}
|
|
313
|
+
finally {
|
|
314
|
+
await cleanup();
|
|
315
|
+
}
|
|
316
|
+
});
|
|
317
|
+
it("should report healthy budget for minimal config", async () => {
|
|
318
|
+
const { path: testDir, cleanup } = await createTestDir();
|
|
319
|
+
try {
|
|
320
|
+
await createMockProject(testDir, {
|
|
321
|
+
existingClaudeMd: createMinimalClaudeMd(),
|
|
322
|
+
});
|
|
323
|
+
const result = await invokeTool("rebar_audit_context", {
|
|
324
|
+
project_path: testDir,
|
|
325
|
+
output_format: "json",
|
|
326
|
+
});
|
|
327
|
+
assertToolSuccess(result);
|
|
328
|
+
const parsed = parseToolResultJson(result);
|
|
329
|
+
const data = parsed.data;
|
|
330
|
+
const budget = data.budget;
|
|
331
|
+
assert.ok(budget.healthy === true, "Minimal config should be healthy");
|
|
332
|
+
}
|
|
333
|
+
finally {
|
|
334
|
+
await cleanup();
|
|
335
|
+
}
|
|
336
|
+
});
|
|
337
|
+
});
|
|
338
|
+
//# sourceMappingURL=management.test.js.map
|