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,138 @@
|
|
|
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
|
+
/**
|
|
7
|
+
* Extracts YAML frontmatter from a markdown file content.
|
|
8
|
+
* Returns the parsed key-value pairs or null if no frontmatter.
|
|
9
|
+
*/
|
|
10
|
+
export function extractFrontmatter(
|
|
11
|
+
content: string
|
|
12
|
+
): Record<string, string> | null {
|
|
13
|
+
const match = content.match(/^---\r?\n([\s\S]*?)\r?\n---/);
|
|
14
|
+
if (!match) return null;
|
|
15
|
+
|
|
16
|
+
const frontmatter: Record<string, string> = {};
|
|
17
|
+
const lines = match[1].split("\n");
|
|
18
|
+
|
|
19
|
+
for (const line of lines) {
|
|
20
|
+
const colonIdx = line.indexOf(":");
|
|
21
|
+
if (colonIdx > 0) {
|
|
22
|
+
const key = line.substring(0, colonIdx).trim();
|
|
23
|
+
const value = line.substring(colonIdx + 1).trim();
|
|
24
|
+
frontmatter[key] = value;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
return frontmatter;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Validates YAML frontmatter for a skill file.
|
|
33
|
+
*/
|
|
34
|
+
export function validateSkillFrontmatter(
|
|
35
|
+
content: string
|
|
36
|
+
): { valid: boolean; errors: string[] } {
|
|
37
|
+
const errors: string[] = [];
|
|
38
|
+
const fm = extractFrontmatter(content);
|
|
39
|
+
|
|
40
|
+
if (!fm) {
|
|
41
|
+
errors.push("Missing YAML frontmatter (must start with --- and end with ---)");
|
|
42
|
+
return { valid: false, errors };
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
if (!fm.name) {
|
|
46
|
+
errors.push("Missing required 'name' field in frontmatter");
|
|
47
|
+
} else if (fm.name.length > SKILL_NAME_MAX_LENGTH) {
|
|
48
|
+
errors.push(
|
|
49
|
+
`Skill name exceeds ${SKILL_NAME_MAX_LENGTH} chars: "${fm.name}" (${fm.name.length} chars)`
|
|
50
|
+
);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
if (!fm.description) {
|
|
54
|
+
errors.push("Missing required 'description' field in frontmatter");
|
|
55
|
+
} else if (fm.description.length > SKILL_DESCRIPTION_MAX_LENGTH) {
|
|
56
|
+
errors.push(
|
|
57
|
+
`Skill description exceeds ${SKILL_DESCRIPTION_MAX_LENGTH} chars (${fm.description.length} chars)`
|
|
58
|
+
);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
return { valid: errors.length === 0, errors };
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Validates JSON content.
|
|
66
|
+
*/
|
|
67
|
+
export function validateJSON(
|
|
68
|
+
content: string,
|
|
69
|
+
label: string
|
|
70
|
+
): { valid: boolean; errors: string[]; parsed: unknown } {
|
|
71
|
+
try {
|
|
72
|
+
const parsed: unknown = JSON.parse(content);
|
|
73
|
+
return { valid: true, errors: [], parsed };
|
|
74
|
+
} catch (err: unknown) {
|
|
75
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
76
|
+
return {
|
|
77
|
+
valid: false,
|
|
78
|
+
errors: [`Invalid JSON in ${label}: ${message}`],
|
|
79
|
+
parsed: null,
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Validates a CLAUDE.md file.
|
|
86
|
+
*/
|
|
87
|
+
export function validateClaudeMD(
|
|
88
|
+
content: string,
|
|
89
|
+
filePath: string
|
|
90
|
+
): { valid: boolean; errors: string[]; warnings: string[] } {
|
|
91
|
+
const errors: string[] = [];
|
|
92
|
+
const warnings: string[] = [];
|
|
93
|
+
|
|
94
|
+
const lines = content.split("\n");
|
|
95
|
+
|
|
96
|
+
if (lines.length > CLAUDEMD_MAX_LINES) {
|
|
97
|
+
warnings.push(
|
|
98
|
+
`${filePath}: CLAUDE.md has ${lines.length} lines (recommended max: ${CLAUDEMD_MAX_LINES})`
|
|
99
|
+
);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
if (!content.startsWith("#")) {
|
|
103
|
+
warnings.push(`${filePath}: CLAUDE.md should start with a heading`);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
if (content.length === 0) {
|
|
107
|
+
errors.push(`${filePath}: CLAUDE.md is empty`);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
return { valid: errors.length === 0, errors, warnings };
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Validates hook configuration object.
|
|
115
|
+
*/
|
|
116
|
+
export function validateHookConfig(
|
|
117
|
+
hook: Record<string, unknown>
|
|
118
|
+
): { valid: boolean; errors: string[] } {
|
|
119
|
+
const errors: string[] = [];
|
|
120
|
+
|
|
121
|
+
if (!hook.command || typeof hook.command !== "string") {
|
|
122
|
+
errors.push("Hook missing required 'command' field (string)");
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
if (hook.event && typeof hook.event !== "string") {
|
|
126
|
+
errors.push("Hook 'event' must be a string");
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
return { valid: errors.length === 0, errors };
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Estimates token count for a string.
|
|
134
|
+
* Uses a rough approximation of ~4 chars per token.
|
|
135
|
+
*/
|
|
136
|
+
export function estimateTokens(content: string): number {
|
|
137
|
+
return Math.ceil(content.length / 4);
|
|
138
|
+
}
|
|
@@ -0,0 +1,145 @@
|
|
|
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
|
+
import type { GeneratedFile } from "../types.js";
|
|
10
|
+
|
|
11
|
+
export interface WindsurfRuleTemplate {
|
|
12
|
+
name: string;
|
|
13
|
+
description: string;
|
|
14
|
+
content: string;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Converts CLAUDE.md content to Windsurf project-rules.md format.
|
|
19
|
+
*/
|
|
20
|
+
function convertToProjectRules(claudeMdContent: string): string {
|
|
21
|
+
const frontmatter = `---
|
|
22
|
+
trigger: always
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
> Note: Windsurf does not support enforcement hooks. The guardrails below rely on
|
|
26
|
+
> you following these rules. For automated enforcement, use Rebar with Claude Code
|
|
27
|
+
> or run \`npx rebar-mcp audit\` in your CI pipeline.
|
|
28
|
+
|
|
29
|
+
`;
|
|
30
|
+
return frontmatter + claudeMdContent;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Converts a rule template to Windsurf rule format.
|
|
35
|
+
*/
|
|
36
|
+
function convertToWindsurfRule(rule: WindsurfRuleTemplate): string {
|
|
37
|
+
const frontmatter = `---
|
|
38
|
+
trigger: manual
|
|
39
|
+
---
|
|
40
|
+
|
|
41
|
+
`;
|
|
42
|
+
return frontmatter + rule.content;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Generates Windsurf configuration files from CLAUDE.md and skills.
|
|
47
|
+
*/
|
|
48
|
+
export async function generateWindsurfConfig(
|
|
49
|
+
projectPath: string,
|
|
50
|
+
claudeMdContent: string,
|
|
51
|
+
rules: WindsurfRuleTemplate[]
|
|
52
|
+
): Promise<GeneratedFile[]> {
|
|
53
|
+
const files: GeneratedFile[] = [];
|
|
54
|
+
const rulesDir = path.join(projectPath, ".windsurf", "rules");
|
|
55
|
+
|
|
56
|
+
await ensureDir(rulesDir);
|
|
57
|
+
|
|
58
|
+
// Generate project-rules.md from CLAUDE.md
|
|
59
|
+
const projectRulesContent = convertToProjectRules(claudeMdContent);
|
|
60
|
+
const projectRulesPath = path.join(rulesDir, "project-rules.md");
|
|
61
|
+
await atomicWrite(projectRulesPath, projectRulesContent);
|
|
62
|
+
files.push({
|
|
63
|
+
path: ".windsurf/rules/project-rules.md",
|
|
64
|
+
content: projectRulesContent,
|
|
65
|
+
description: "Main project rules (from CLAUDE.md)",
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
// Convert rules
|
|
69
|
+
for (const rule of rules) {
|
|
70
|
+
const ruleContent = convertToWindsurfRule(rule);
|
|
71
|
+
const rulePath = path.join(rulesDir, `${rule.name}.md`);
|
|
72
|
+
await atomicWrite(rulePath, ruleContent);
|
|
73
|
+
files.push({
|
|
74
|
+
path: `.windsurf/rules/${rule.name}.md`,
|
|
75
|
+
content: ruleContent,
|
|
76
|
+
description: `${rule.name} rule`,
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
return files;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Default rules for Windsurf.
|
|
85
|
+
*/
|
|
86
|
+
export function getDefaultWindsurfRules(): WindsurfRuleTemplate[] {
|
|
87
|
+
return [
|
|
88
|
+
{
|
|
89
|
+
name: "code-review",
|
|
90
|
+
description: "Code review guidelines",
|
|
91
|
+
content: `# Code Review
|
|
92
|
+
|
|
93
|
+
When reviewing code changes:
|
|
94
|
+
|
|
95
|
+
1. **Security First**: Check for injection vulnerabilities, auth issues, data exposure
|
|
96
|
+
2. **Error Handling**: Ensure errors are properly caught and handled
|
|
97
|
+
3. **Type Safety**: Verify types are correct and 'any' is avoided
|
|
98
|
+
4. **Performance**: Watch for N+1 queries, memory leaks, unnecessary re-renders
|
|
99
|
+
5. **Tests**: Ensure tests exist and pass for changed code
|
|
100
|
+
`,
|
|
101
|
+
},
|
|
102
|
+
{
|
|
103
|
+
name: "test-writer",
|
|
104
|
+
description: "Test writing guidelines",
|
|
105
|
+
content: `# Test Writing
|
|
106
|
+
|
|
107
|
+
When writing tests:
|
|
108
|
+
|
|
109
|
+
1. Test behavior, not implementation
|
|
110
|
+
2. Use descriptive test names
|
|
111
|
+
3. Follow the Arrange-Act-Assert pattern
|
|
112
|
+
4. Mock external dependencies
|
|
113
|
+
5. Aim for edge cases, not just happy paths
|
|
114
|
+
`,
|
|
115
|
+
},
|
|
116
|
+
{
|
|
117
|
+
name: "security-scan",
|
|
118
|
+
description: "Security scanning guidelines",
|
|
119
|
+
content: `# Security Scan
|
|
120
|
+
|
|
121
|
+
Check for:
|
|
122
|
+
|
|
123
|
+
1. Hardcoded secrets (API keys, passwords)
|
|
124
|
+
2. SQL injection vulnerabilities
|
|
125
|
+
3. XSS in rendered HTML
|
|
126
|
+
4. Insecure direct object references
|
|
127
|
+
5. Missing authentication/authorization
|
|
128
|
+
`,
|
|
129
|
+
},
|
|
130
|
+
{
|
|
131
|
+
name: "documentation",
|
|
132
|
+
description: "Documentation guidelines",
|
|
133
|
+
content: `# Documentation
|
|
134
|
+
|
|
135
|
+
When documenting:
|
|
136
|
+
|
|
137
|
+
1. Document the WHY, not the WHAT
|
|
138
|
+
2. Keep documentation close to code
|
|
139
|
+
3. Update docs when changing code
|
|
140
|
+
4. Use examples liberally
|
|
141
|
+
5. Document public APIs thoroughly
|
|
142
|
+
`,
|
|
143
|
+
},
|
|
144
|
+
];
|
|
145
|
+
}
|