1- import type { Bridge , Rule , ProjectConfig } from './types.js' ;
1+ import type { DirectoryBridge , Rule , ProjectConfig , ScopeMetadata } from './types.js' ;
22import { filterRules , groupByScope , formatScopeHeading } from '../core/helpers.js' ;
3+ import { scopeToFilename } from '../core/scope-filename.js' ;
4+
5+ const GENERATED_COMMENT = '<!-- Generated by dev-workflows. Do not edit manually. -->' ;
6+
7+ function buildFrontmatter ( metadata ?: ScopeMetadata ) : string {
8+ if ( ! metadata ?. paths || metadata . paths . length === 0 ) {
9+ return '' ;
10+ }
311
4- function buildMarkdown ( rules : Rule [ ] ) : string {
512 const lines : string [ ] = [
6- '# Project Rules' ,
13+ '---' ,
14+ 'paths:' ,
715 ] ;
16+ for ( const p of metadata . paths ) {
17+ lines . push ( ` - "${ p } "` ) ;
18+ }
19+ lines . push ( '---' ) ;
820
9- const filtered = filterRules ( rules ) ;
10- const grouped = groupByScope ( filtered ) ;
11-
12- for ( const [ scope , scopeRules ] of grouped ) {
13- lines . push ( '' , `## ${ formatScopeHeading ( scope ) } ` ) ;
14- lines . push ( '' ) ;
15- for ( const rule of scopeRules ) {
16- const contentLines = rule . content . split ( '\n' ) ;
17- const first = contentLines [ 0 ] ;
18- if ( first !== undefined ) {
19- lines . push ( `- ${ first } ` ) ;
20- }
21- for ( let i = 1 ; i < contentLines . length ; i ++ ) {
22- const line = contentLines [ i ] ;
23- if ( line !== undefined ) {
24- lines . push ( ` ${ line } ` ) ;
25- }
21+ return lines . join ( '\n' ) ;
22+ }
23+
24+ function buildScopeMarkdown ( scope : string , rules : Rule [ ] ) : string {
25+ const lines : string [ ] = [ ] ;
26+
27+ // Get metadata from the first rule in the scope (all rules in a scope share metadata)
28+ const metadata = rules [ 0 ] ?. metadata ;
29+ const frontmatter = buildFrontmatter ( metadata ) ;
30+
31+ if ( frontmatter ) {
32+ lines . push ( frontmatter ) ;
33+ }
34+
35+ lines . push ( GENERATED_COMMENT ) ;
36+ lines . push ( `# ${ formatScopeHeading ( scope ) } ` ) ;
37+ lines . push ( '' ) ;
38+
39+ for ( const rule of rules ) {
40+ const contentLines = rule . content . split ( '\n' ) ;
41+ const first = contentLines [ 0 ] ;
42+ if ( first !== undefined ) {
43+ lines . push ( `- ${ first } ` ) ;
44+ }
45+ for ( let i = 1 ; i < contentLines . length ; i ++ ) {
46+ const line = contentLines [ i ] ;
47+ if ( line !== undefined ) {
48+ lines . push ( ` ${ line } ` ) ;
2649 }
2750 }
2851 }
@@ -31,14 +54,25 @@ function buildMarkdown(rules: Rule[]): string {
3154 return lines . join ( '\n' ) ;
3255}
3356
34- export const claudeBridge : Bridge = {
57+ export const claudeBridge : DirectoryBridge = {
3558 id : 'claude' ,
36- outputPaths : [ 'CLAUDE.md' ] ,
37- usesMarkers : true ,
59+ kind : 'directory' ,
60+ outputDir : '.claude/rules' ,
61+ filePrefix : 'dwf-' ,
62+ fileExtension : '.md' ,
3863
3964 compile ( rules : Rule [ ] , _config : ProjectConfig ) : Map < string , string > {
4065 const output = new Map < string , string > ( ) ;
41- output . set ( 'CLAUDE.md' , buildMarkdown ( rules ) ) ;
66+
67+ const filtered = filterRules ( rules ) ;
68+ const grouped = groupByScope ( filtered ) ;
69+
70+ for ( const [ scope , scopeRules ] of grouped ) {
71+ const filename = scopeToFilename ( scope , 'dwf-' , '.md' ) ;
72+ const key = `.claude/rules/${ filename } ` ;
73+ output . set ( key , buildScopeMarkdown ( scope , scopeRules ) ) ;
74+ }
75+
4276 return output ;
4377 } ,
4478} ;
0 commit comments