fix(windsurf): include YAML frontmatter when generating rule files#1470
fix(windsurf): include YAML frontmatter when generating rule files#1470dyoshikawa merged 1 commit intomainfrom
Conversation
There was a problem hiding this comment.
Pull request overview
Adds Windsurf-required YAML frontmatter to generated .windsurf/rules/*.md files so Windsurf can correctly interpret rule metadata during its rule loading pipeline.
Changes:
- Generate Windsurf rule file content via
stringifyFrontmatter(), emittingtitle,trigger, and optionalglobs. - Introduce
buildWindsurfFrontmatter()to derive Windsurf frontmatter from Rulesync rule metadata. - Update unit tests to assert the new frontmatter output, including a glob-triggered example.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
| src/features/rules/windsurf-rule.ts | Builds and serializes Windsurf YAML frontmatter into generated rule file content. |
| src/features/rules/windsurf-rule.test.ts | Updates assertions to match the new frontmatter-bearing output and adds a glob-trigger test. |
| const hasSpecificGlobs = Boolean(globs && globs.length > 0 && !globs.includes("**/*")); | ||
|
|
||
| return { | ||
| title: description ?? relativeFilePath.replace(/\.md$/, ""), | ||
| trigger: hasSpecificGlobs ? "glob" : "always_on", | ||
| ...(hasSpecificGlobs && { globs }), |
There was a problem hiding this comment.
hasSpecificGlobs treats any occurrence of "/*" as meaning "no specific globs". That misclassifies cases like ["**/*", "src/**/*.ts"] (should still be trigger: glob) and also treats "*" as specific even though it’s a wildcard used elsewhere in the codebase. Consider computing specificity as “at least one glob that isn’t "/" or ""” (and treat mixed wildcard+specific as specific).
| const windsurfFrontmatter = this.buildWindsurfFrontmatter({ | ||
| relativeFilePath: rulesyncRule.getRelativeFilePath(), | ||
| description: rulesyncRule.getFrontmatter().description, | ||
| globs: rulesyncRule.getFrontmatter().globs, | ||
| }); | ||
|
|
||
| return new WindsurfRule({ | ||
| ...toolRuleParams, | ||
| fileContent: stringifyFrontmatter(rulesyncRule.getBody(), windsurfFrontmatter), | ||
| }); |
There was a problem hiding this comment.
fromRulesyncRule() now writes Windsurf YAML frontmatter into fileContent, but WindsurfRule.fromFile() doesn’t parse/strip that frontmatter. As a result, reading a generated .windsurf/rules/*.md file will keep the frontmatter in the body and toRulesyncRuleDefault() will round-trip it into the Rulesync rule body (and you also lose the ability to map title/trigger/globs back into Rulesync metadata). Consider updating fromFile() to parseFrontmatter() and populate description/globs from the parsed Windsurf frontmatter, storing only the markdown body as fileContent.
Motivation
title,trigger,globs) in.windsurf/rules/*.mdfiles, but generated files previously contained only the rule body.Description
stringifyFrontmatterand adding aWindsurfRuleFrontmattershape.buildWindsurfFrontmatter()to derivetitlefrom rulesyncdescription(fallback to filename), settriggertoglobwhen specific globs exist otherwisealways_on, and includeglobsonly forglobtriggers.WindsurfRule.fromRulesyncRule()to build tool params, compose Windsurf frontmatter, and setfileContenttostringifyFrontmatter(body, windsurfFrontmatter).src/features/rules/windsurf-rule.test.tsto assert the new frontmatter output and add coverage for glob-triggered rules.Testing
pnpm vitest run src/features/rules/windsurf-rule.test.tsand they passed (38 passed).pnpm cicheck, which completed formatting, linting, typechecks and the full test suite successfully (all automated checks passed; full test run completed without failures).Codex Task