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,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Lightweight template engine with variable substitution and conditionals.
|
|
3
|
+
* Uses {{variable}} syntax and {{#if condition}}...{{/if}} blocks.
|
|
4
|
+
*/
|
|
5
|
+
import type { TemplateVariables } from "../types.js";
|
|
6
|
+
/**
|
|
7
|
+
* Renders a template string with the given variables.
|
|
8
|
+
*
|
|
9
|
+
* Supports:
|
|
10
|
+
* - {{variable_name}} — replaced with the variable's value
|
|
11
|
+
* - {{#if variable_name}}...{{/if}} — conditional blocks
|
|
12
|
+
* - {{#unless variable_name}}...{{/unless}} — inverse conditional blocks
|
|
13
|
+
* - {{#each variable_name}}...{{/each}} — iteration over arrays
|
|
14
|
+
*/
|
|
15
|
+
export declare function renderTemplate(template: string, variables: TemplateVariables): string;
|
|
16
|
+
//# sourceMappingURL=template-engine.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"template-engine.d.ts","sourceRoot":"","sources":["../../src/services/template-engine.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAErD;;;;;;;;GAQG;AACH,wBAAgB,cAAc,CAC5B,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,iBAAiB,GAC3B,MAAM,CAgBR"}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Renders a template string with the given variables.
|
|
3
|
+
*
|
|
4
|
+
* Supports:
|
|
5
|
+
* - {{variable_name}} — replaced with the variable's value
|
|
6
|
+
* - {{#if variable_name}}...{{/if}} — conditional blocks
|
|
7
|
+
* - {{#unless variable_name}}...{{/unless}} — inverse conditional blocks
|
|
8
|
+
* - {{#each variable_name}}...{{/each}} — iteration over arrays
|
|
9
|
+
*/
|
|
10
|
+
export function renderTemplate(template, variables) {
|
|
11
|
+
let result = template;
|
|
12
|
+
// Process {{#each variable}}...{{/each}} blocks
|
|
13
|
+
result = processEachBlocks(result, variables);
|
|
14
|
+
// Process {{#if variable}}...{{/if}} blocks (supports nesting)
|
|
15
|
+
result = processConditionalBlocks(result, variables);
|
|
16
|
+
// Process {{#unless variable}}...{{/unless}} blocks
|
|
17
|
+
result = processUnlessBlocks(result, variables);
|
|
18
|
+
// Replace {{variable}} placeholders
|
|
19
|
+
result = replaceVariables(result, variables);
|
|
20
|
+
return result;
|
|
21
|
+
}
|
|
22
|
+
function processEachBlocks(template, variables) {
|
|
23
|
+
const eachRegex = /\{\{#each\s+(\w+)\}\}([\s\S]*?)\{\{\/each\}\}/g;
|
|
24
|
+
return template.replace(eachRegex, (_match, varName, body) => {
|
|
25
|
+
const value = variables[varName];
|
|
26
|
+
if (!Array.isArray(value) || value.length === 0) {
|
|
27
|
+
return "";
|
|
28
|
+
}
|
|
29
|
+
return value
|
|
30
|
+
.map((item) => body.replace(/\{\{this\}\}/g, item))
|
|
31
|
+
.join("");
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
function processConditionalBlocks(template, variables) {
|
|
35
|
+
// Process innermost {{#if}}...{{/if}} first to handle nesting
|
|
36
|
+
let result = template;
|
|
37
|
+
let iterations = 0;
|
|
38
|
+
const maxIterations = 50;
|
|
39
|
+
while (result.includes("{{#if ") && iterations < maxIterations) {
|
|
40
|
+
const prev = result;
|
|
41
|
+
result = result.replace(/\{\{#if\s+(\w+)\}\}([\s\S]*?)\{\{\/if\}\}/, (_match, varName, body) => {
|
|
42
|
+
const value = variables[varName];
|
|
43
|
+
if (isTruthy(value)) {
|
|
44
|
+
return body;
|
|
45
|
+
}
|
|
46
|
+
return "";
|
|
47
|
+
});
|
|
48
|
+
if (result === prev)
|
|
49
|
+
break;
|
|
50
|
+
iterations++;
|
|
51
|
+
}
|
|
52
|
+
return result;
|
|
53
|
+
}
|
|
54
|
+
function processUnlessBlocks(template, variables) {
|
|
55
|
+
const unlessRegex = /\{\{#unless\s+(\w+)\}\}([\s\S]*?)\{\{\/unless\}\}/g;
|
|
56
|
+
return template.replace(unlessRegex, (_match, varName, body) => {
|
|
57
|
+
const value = variables[varName];
|
|
58
|
+
if (!isTruthy(value)) {
|
|
59
|
+
return body;
|
|
60
|
+
}
|
|
61
|
+
return "";
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
function replaceVariables(template, variables) {
|
|
65
|
+
return template.replace(/\{\{(\w+)\}\}/g, (_match, varName) => {
|
|
66
|
+
const value = variables[varName];
|
|
67
|
+
if (value === undefined) {
|
|
68
|
+
return `{{${varName}}}`;
|
|
69
|
+
}
|
|
70
|
+
if (Array.isArray(value)) {
|
|
71
|
+
return value.join(", ");
|
|
72
|
+
}
|
|
73
|
+
return String(value);
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
function isTruthy(value) {
|
|
77
|
+
if (value === undefined || value === false || value === "") {
|
|
78
|
+
return false;
|
|
79
|
+
}
|
|
80
|
+
if (Array.isArray(value) && value.length === 0) {
|
|
81
|
+
return false;
|
|
82
|
+
}
|
|
83
|
+
return true;
|
|
84
|
+
}
|
|
85
|
+
//# sourceMappingURL=template-engine.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"template-engine.js","sourceRoot":"","sources":["../../src/services/template-engine.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Extracts YAML frontmatter from a markdown file content.
|
|
3
|
+
* Returns the parsed key-value pairs or null if no frontmatter.
|
|
4
|
+
*/
|
|
5
|
+
export declare function extractFrontmatter(content: string): Record<string, string> | null;
|
|
6
|
+
/**
|
|
7
|
+
* Validates YAML frontmatter for a skill file.
|
|
8
|
+
*/
|
|
9
|
+
export declare function validateSkillFrontmatter(content: string): {
|
|
10
|
+
valid: boolean;
|
|
11
|
+
errors: string[];
|
|
12
|
+
};
|
|
13
|
+
/**
|
|
14
|
+
* Validates JSON content.
|
|
15
|
+
*/
|
|
16
|
+
export declare function validateJSON(content: string, label: string): {
|
|
17
|
+
valid: boolean;
|
|
18
|
+
errors: string[];
|
|
19
|
+
parsed: unknown;
|
|
20
|
+
};
|
|
21
|
+
/**
|
|
22
|
+
* Validates a CLAUDE.md file.
|
|
23
|
+
*/
|
|
24
|
+
export declare function validateClaudeMD(content: string, filePath: string): {
|
|
25
|
+
valid: boolean;
|
|
26
|
+
errors: string[];
|
|
27
|
+
warnings: string[];
|
|
28
|
+
};
|
|
29
|
+
/**
|
|
30
|
+
* Validates hook configuration object.
|
|
31
|
+
*/
|
|
32
|
+
export declare function validateHookConfig(hook: Record<string, unknown>): {
|
|
33
|
+
valid: boolean;
|
|
34
|
+
errors: string[];
|
|
35
|
+
};
|
|
36
|
+
/**
|
|
37
|
+
* Estimates token count for a string.
|
|
38
|
+
* Uses a rough approximation of ~4 chars per token.
|
|
39
|
+
*/
|
|
40
|
+
export declare function estimateTokens(content: string): number;
|
|
41
|
+
//# sourceMappingURL=validation.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validation.d.ts","sourceRoot":"","sources":["../../src/services/validation.ts"],"names":[],"mappings":"AAKA;;;GAGG;AACH,wBAAgB,kBAAkB,CAChC,OAAO,EAAE,MAAM,GACd,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI,CAiB/B;AAED;;GAEG;AACH,wBAAgB,wBAAwB,CACtC,OAAO,EAAE,MAAM,GACd;IAAE,KAAK,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE,MAAM,EAAE,CAAA;CAAE,CA0BtC;AAED;;GAEG;AACH,wBAAgB,YAAY,CAC1B,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,MAAM,GACZ;IAAE,KAAK,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE,MAAM,EAAE,CAAC;IAAC,MAAM,EAAE,OAAO,CAAA;CAAE,CAYvD;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAC9B,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,MAAM,GACf;IAAE,KAAK,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE,MAAM,EAAE,CAAC;IAAC,QAAQ,EAAE,MAAM,EAAE,CAAA;CAAE,CAqB1D;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAChC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC5B;IAAE,KAAK,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE,MAAM,EAAE,CAAA;CAAE,CAYtC;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAEtD"}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Validation service for Claude Code configuration artifacts
|
|
3
|
+
*/
|
|
4
|
+
import { SKILL_NAME_MAX_LENGTH, SKILL_DESCRIPTION_MAX_LENGTH, CLAUDEMD_MAX_LINES } from "../constants.js";
|
|
5
|
+
/**
|
|
6
|
+
* Extracts YAML frontmatter from a markdown file content.
|
|
7
|
+
* Returns the parsed key-value pairs or null if no frontmatter.
|
|
8
|
+
*/
|
|
9
|
+
export function extractFrontmatter(content) {
|
|
10
|
+
const match = content.match(/^---\r?\n([\s\S]*?)\r?\n---/);
|
|
11
|
+
if (!match)
|
|
12
|
+
return null;
|
|
13
|
+
const frontmatter = {};
|
|
14
|
+
const lines = match[1].split("\n");
|
|
15
|
+
for (const line of lines) {
|
|
16
|
+
const colonIdx = line.indexOf(":");
|
|
17
|
+
if (colonIdx > 0) {
|
|
18
|
+
const key = line.substring(0, colonIdx).trim();
|
|
19
|
+
const value = line.substring(colonIdx + 1).trim();
|
|
20
|
+
frontmatter[key] = value;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
return frontmatter;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Validates YAML frontmatter for a skill file.
|
|
27
|
+
*/
|
|
28
|
+
export function validateSkillFrontmatter(content) {
|
|
29
|
+
const errors = [];
|
|
30
|
+
const fm = extractFrontmatter(content);
|
|
31
|
+
if (!fm) {
|
|
32
|
+
errors.push("Missing YAML frontmatter (must start with --- and end with ---)");
|
|
33
|
+
return { valid: false, errors };
|
|
34
|
+
}
|
|
35
|
+
if (!fm.name) {
|
|
36
|
+
errors.push("Missing required 'name' field in frontmatter");
|
|
37
|
+
}
|
|
38
|
+
else if (fm.name.length > SKILL_NAME_MAX_LENGTH) {
|
|
39
|
+
errors.push(`Skill name exceeds ${SKILL_NAME_MAX_LENGTH} chars: "${fm.name}" (${fm.name.length} chars)`);
|
|
40
|
+
}
|
|
41
|
+
if (!fm.description) {
|
|
42
|
+
errors.push("Missing required 'description' field in frontmatter");
|
|
43
|
+
}
|
|
44
|
+
else if (fm.description.length > SKILL_DESCRIPTION_MAX_LENGTH) {
|
|
45
|
+
errors.push(`Skill description exceeds ${SKILL_DESCRIPTION_MAX_LENGTH} chars (${fm.description.length} chars)`);
|
|
46
|
+
}
|
|
47
|
+
return { valid: errors.length === 0, errors };
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Validates JSON content.
|
|
51
|
+
*/
|
|
52
|
+
export function validateJSON(content, label) {
|
|
53
|
+
try {
|
|
54
|
+
const parsed = JSON.parse(content);
|
|
55
|
+
return { valid: true, errors: [], parsed };
|
|
56
|
+
}
|
|
57
|
+
catch (err) {
|
|
58
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
59
|
+
return {
|
|
60
|
+
valid: false,
|
|
61
|
+
errors: [`Invalid JSON in ${label}: ${message}`],
|
|
62
|
+
parsed: null,
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Validates a CLAUDE.md file.
|
|
68
|
+
*/
|
|
69
|
+
export function validateClaudeMD(content, filePath) {
|
|
70
|
+
const errors = [];
|
|
71
|
+
const warnings = [];
|
|
72
|
+
const lines = content.split("\n");
|
|
73
|
+
if (lines.length > CLAUDEMD_MAX_LINES) {
|
|
74
|
+
warnings.push(`${filePath}: CLAUDE.md has ${lines.length} lines (recommended max: ${CLAUDEMD_MAX_LINES})`);
|
|
75
|
+
}
|
|
76
|
+
if (!content.startsWith("#")) {
|
|
77
|
+
warnings.push(`${filePath}: CLAUDE.md should start with a heading`);
|
|
78
|
+
}
|
|
79
|
+
if (content.length === 0) {
|
|
80
|
+
errors.push(`${filePath}: CLAUDE.md is empty`);
|
|
81
|
+
}
|
|
82
|
+
return { valid: errors.length === 0, errors, warnings };
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Validates hook configuration object.
|
|
86
|
+
*/
|
|
87
|
+
export function validateHookConfig(hook) {
|
|
88
|
+
const errors = [];
|
|
89
|
+
if (!hook.command || typeof hook.command !== "string") {
|
|
90
|
+
errors.push("Hook missing required 'command' field (string)");
|
|
91
|
+
}
|
|
92
|
+
if (hook.event && typeof hook.event !== "string") {
|
|
93
|
+
errors.push("Hook 'event' must be a string");
|
|
94
|
+
}
|
|
95
|
+
return { valid: errors.length === 0, errors };
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Estimates token count for a string.
|
|
99
|
+
* Uses a rough approximation of ~4 chars per token.
|
|
100
|
+
*/
|
|
101
|
+
export function estimateTokens(content) {
|
|
102
|
+
return Math.ceil(content.length / 4);
|
|
103
|
+
}
|
|
104
|
+
//# sourceMappingURL=validation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validation.js","sourceRoot":"","sources":["../../src/services/validation.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { GeneratedFile } from "../types.js";
|
|
2
|
+
export interface WindsurfRuleTemplate {
|
|
3
|
+
name: string;
|
|
4
|
+
description: string;
|
|
5
|
+
content: string;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Generates Windsurf configuration files from CLAUDE.md and skills.
|
|
9
|
+
*/
|
|
10
|
+
export declare function generateWindsurfConfig(projectPath: string, claudeMdContent: string, rules: WindsurfRuleTemplate[]): Promise<GeneratedFile[]>;
|
|
11
|
+
/**
|
|
12
|
+
* Default rules for Windsurf.
|
|
13
|
+
*/
|
|
14
|
+
export declare function getDefaultWindsurfRules(): WindsurfRuleTemplate[];
|
|
15
|
+
//# sourceMappingURL=windsurf-generator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"windsurf-generator.d.ts","sourceRoot":"","sources":["../../src/services/windsurf-generator.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAEjD,MAAM,WAAW,oBAAoB;IACnC,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;CACjB;AA8BD;;GAEG;AACH,wBAAsB,sBAAsB,CAC1C,WAAW,EAAE,MAAM,EACnB,eAAe,EAAE,MAAM,EACvB,KAAK,EAAE,oBAAoB,EAAE,GAC5B,OAAO,CAAC,aAAa,EAAE,CAAC,CA6B1B;AAED;;GAEG;AACH,wBAAgB,uBAAuB,IAAI,oBAAoB,EAAE,CA2DhE"}
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Windsurf configuration generator.
|
|
3
|
+
*
|
|
4
|
+
* Windsurf uses .windsurf/rules/*.md files similar to Cursor,
|
|
5
|
+
* but with a simpler frontmatter format using 'trigger: always'.
|
|
6
|
+
*/
|
|
7
|
+
import * as path from "node:path";
|
|
8
|
+
import { ensureDir, atomicWrite } from "./file-ops.js";
|
|
9
|
+
/**
|
|
10
|
+
* Converts CLAUDE.md content to Windsurf project-rules.md format.
|
|
11
|
+
*/
|
|
12
|
+
function convertToProjectRules(claudeMdContent) {
|
|
13
|
+
const frontmatter = `---
|
|
14
|
+
trigger: always
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
> Note: Windsurf does not support enforcement hooks. The guardrails below rely on
|
|
18
|
+
> you following these rules. For automated enforcement, use Rebar with Claude Code
|
|
19
|
+
> or run \`npx rebar-mcp audit\` in your CI pipeline.
|
|
20
|
+
|
|
21
|
+
`;
|
|
22
|
+
return frontmatter + claudeMdContent;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Converts a rule template to Windsurf rule format.
|
|
26
|
+
*/
|
|
27
|
+
function convertToWindsurfRule(rule) {
|
|
28
|
+
const frontmatter = `---
|
|
29
|
+
trigger: manual
|
|
30
|
+
---
|
|
31
|
+
|
|
32
|
+
`;
|
|
33
|
+
return frontmatter + rule.content;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Generates Windsurf configuration files from CLAUDE.md and skills.
|
|
37
|
+
*/
|
|
38
|
+
export async function generateWindsurfConfig(projectPath, claudeMdContent, rules) {
|
|
39
|
+
const files = [];
|
|
40
|
+
const rulesDir = path.join(projectPath, ".windsurf", "rules");
|
|
41
|
+
await ensureDir(rulesDir);
|
|
42
|
+
// Generate project-rules.md from CLAUDE.md
|
|
43
|
+
const projectRulesContent = convertToProjectRules(claudeMdContent);
|
|
44
|
+
const projectRulesPath = path.join(rulesDir, "project-rules.md");
|
|
45
|
+
await atomicWrite(projectRulesPath, projectRulesContent);
|
|
46
|
+
files.push({
|
|
47
|
+
path: ".windsurf/rules/project-rules.md",
|
|
48
|
+
content: projectRulesContent,
|
|
49
|
+
description: "Main project rules (from CLAUDE.md)",
|
|
50
|
+
});
|
|
51
|
+
// Convert rules
|
|
52
|
+
for (const rule of rules) {
|
|
53
|
+
const ruleContent = convertToWindsurfRule(rule);
|
|
54
|
+
const rulePath = path.join(rulesDir, `${rule.name}.md`);
|
|
55
|
+
await atomicWrite(rulePath, ruleContent);
|
|
56
|
+
files.push({
|
|
57
|
+
path: `.windsurf/rules/${rule.name}.md`,
|
|
58
|
+
content: ruleContent,
|
|
59
|
+
description: `${rule.name} rule`,
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
return files;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Default rules for Windsurf.
|
|
66
|
+
*/
|
|
67
|
+
export function getDefaultWindsurfRules() {
|
|
68
|
+
return [
|
|
69
|
+
{
|
|
70
|
+
name: "code-review",
|
|
71
|
+
description: "Code review guidelines",
|
|
72
|
+
content: `# Code Review
|
|
73
|
+
|
|
74
|
+
When reviewing code changes:
|
|
75
|
+
|
|
76
|
+
1. **Security First**: Check for injection vulnerabilities, auth issues, data exposure
|
|
77
|
+
2. **Error Handling**: Ensure errors are properly caught and handled
|
|
78
|
+
3. **Type Safety**: Verify types are correct and 'any' is avoided
|
|
79
|
+
4. **Performance**: Watch for N+1 queries, memory leaks, unnecessary re-renders
|
|
80
|
+
5. **Tests**: Ensure tests exist and pass for changed code
|
|
81
|
+
`,
|
|
82
|
+
},
|
|
83
|
+
{
|
|
84
|
+
name: "test-writer",
|
|
85
|
+
description: "Test writing guidelines",
|
|
86
|
+
content: `# Test Writing
|
|
87
|
+
|
|
88
|
+
When writing tests:
|
|
89
|
+
|
|
90
|
+
1. Test behavior, not implementation
|
|
91
|
+
2. Use descriptive test names
|
|
92
|
+
3. Follow the Arrange-Act-Assert pattern
|
|
93
|
+
4. Mock external dependencies
|
|
94
|
+
5. Aim for edge cases, not just happy paths
|
|
95
|
+
`,
|
|
96
|
+
},
|
|
97
|
+
{
|
|
98
|
+
name: "security-scan",
|
|
99
|
+
description: "Security scanning guidelines",
|
|
100
|
+
content: `# Security Scan
|
|
101
|
+
|
|
102
|
+
Check for:
|
|
103
|
+
|
|
104
|
+
1. Hardcoded secrets (API keys, passwords)
|
|
105
|
+
2. SQL injection vulnerabilities
|
|
106
|
+
3. XSS in rendered HTML
|
|
107
|
+
4. Insecure direct object references
|
|
108
|
+
5. Missing authentication/authorization
|
|
109
|
+
`,
|
|
110
|
+
},
|
|
111
|
+
{
|
|
112
|
+
name: "documentation",
|
|
113
|
+
description: "Documentation guidelines",
|
|
114
|
+
content: `# Documentation
|
|
115
|
+
|
|
116
|
+
When documenting:
|
|
117
|
+
|
|
118
|
+
1. Document the WHY, not the WHAT
|
|
119
|
+
2. Keep documentation close to code
|
|
120
|
+
3. Update docs when changing code
|
|
121
|
+
4. Use examples liberally
|
|
122
|
+
5. Document public APIs thoroughly
|
|
123
|
+
`,
|
|
124
|
+
},
|
|
125
|
+
];
|
|
126
|
+
}
|
|
127
|
+
//# sourceMappingURL=windsurf-generator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"windsurf-generator.js","sourceRoot":"","sources":["../../src/services/windsurf-generator.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAClC,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AASvD;;GAEG;AACH,SAAS,qBAAqB,CAAC,eAAuB;IACpD,MAAM,WAAW,GAAG;;;;;;;;CAQrB,CAAC;IACA,OAAO,WAAW,GAAG,eAAe,CAAC;AACvC,CAAC;AAED;;GAEG;AACH,SAAS,qBAAqB,CAAC,IAA0B;IACvD,MAAM,WAAW,GAAG;;;;CAIrB,CAAC;IACA,OAAO,WAAW,GAAG,IAAI,CAAC,OAAO,CAAC;AACpC,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,sBAAsB,CAC1C,WAAmB,EACnB,eAAuB,EACvB,KAA6B;IAE7B,MAAM,KAAK,GAAoB,EAAE,CAAC;IAClC,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,WAAW,EAAE,OAAO,CAAC,CAAC;IAE9D,MAAM,SAAS,CAAC,QAAQ,CAAC,CAAC;IAE1B,2CAA2C;IAC3C,MAAM,mBAAmB,GAAG,qBAAqB,CAAC,eAAe,CAAC,CAAC;IACnE,MAAM,gBAAgB,GAAG,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,kBAAkB,CAAC,CAAC;IACjE,MAAM,WAAW,CAAC,gBAAgB,EAAE,mBAAmB,CAAC,CAAC;IACzD,KAAK,CAAC,IAAI,CAAC;QACT,IAAI,EAAE,kCAAkC;QACxC,OAAO,EAAE,mBAAmB;QAC5B,WAAW,EAAE,qCAAqC;KACnD,CAAC,CAAC;IAEH,gBAAgB;IAChB,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,WAAW,GAAG,qBAAqB,CAAC,IAAI,CAAC,CAAC;QAChD,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,GAAG,IAAI,CAAC,IAAI,KAAK,CAAC,CAAC;QACxD,MAAM,WAAW,CAAC,QAAQ,EAAE,WAAW,CAAC,CAAC;QACzC,KAAK,CAAC,IAAI,CAAC;YACT,IAAI,EAAE,mBAAmB,IAAI,CAAC,IAAI,KAAK;YACvC,OAAO,EAAE,WAAW;YACpB,WAAW,EAAE,GAAG,IAAI,CAAC,IAAI,OAAO;SACjC,CAAC,CAAC;IACL,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,uBAAuB;IACrC,OAAO;QACL;YACE,IAAI,EAAE,aAAa;YACnB,WAAW,EAAE,wBAAwB;YACrC,OAAO,EAAE;;;;;;;;;CASd;SACI;QACD;YACE,IAAI,EAAE,aAAa;YACnB,WAAW,EAAE,yBAAyB;YACtC,OAAO,EAAE;;;;;;;;;CASd;SACI;QACD;YACE,IAAI,EAAE,eAAe;YACrB,WAAW,EAAE,8BAA8B;YAC3C,OAAO,EAAE;;;;;;;;;CASd;SACI;QACD;YACE,IAAI,EAAE,eAAe;YACrB,WAAW,EAAE,0BAA0B;YACvC,OAAO,EAAE;;;;;;;;;CASd;SACI;KACF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"enforcement.test.d.ts","sourceRoot":"","sources":["../../src/tests/enforcement.test.ts"],"names":[],"mappings":""}
|