11import { lstat , readFile , readdir } from 'node:fs/promises' ;
2- import { basename , join , relative } from 'node:path' ;
2+ import { join , relative } from 'node:path' ;
33import type { Command } from 'commander' ;
44import { parse } from 'yaml' ;
55import { readConfig , readRules } from '../core/parser.js' ;
@@ -14,7 +14,6 @@ import { getBridgeOutputPaths, isDirectoryBridge } from '../bridges/types.js';
1414import { fileExists } from '../utils/fs.js' ;
1515import { resolveContext } from '../core/resolve-context.js' ;
1616import { isValidScope } from '../core/schema.js' ;
17- import { buildCanonicalOutputs } from '../core/canonical.js' ;
1817import { detectLegacyFiles } from '../core/cleanup.js' ;
1918import * as ui from '../utils/ui.js' ;
2019
@@ -268,12 +267,6 @@ export async function checkHashSync(cwd: string, rules: Rule[]): Promise<CheckRe
268267 } ;
269268}
270269
271- function normalizeComparableContent ( content : string ) : string {
272- const frontmatterPattern = / ^ - - - \r ? \n [ \s \S ] * ?\r ? \n - - - \r ? \n ? / ;
273- const withoutFrontmatter = content . replace ( frontmatterPattern , '' ) ;
274- return withoutFrontmatter . replaceAll ( '\r\n' , '\n' ) . trimEnd ( ) ;
275- }
276-
277270function extractFrontmatter ( content : string ) : string | null {
278271 const match = content . match ( / ^ - - - \r ? \n ( [ \s \S ] * ?) \r ? \n - - - (?: \r ? \n | $ ) / ) ;
279272 if ( ! match ) {
@@ -282,112 +275,6 @@ function extractFrontmatter(content: string): string | null {
282275 return match [ 1 ] ?? null ;
283276}
284277
285- export async function checkCanonicalExists ( cwd : string ) : Promise < CheckResult > {
286- const canonicalDir = join ( cwd , '.agents' , 'rules' , 'devw' ) ;
287-
288- let entries : string [ ] ;
289- try {
290- entries = await readdir ( canonicalDir ) ;
291- } catch {
292- return {
293- passed : false ,
294- message : '.agents/rules/devw not found — run "devw compile"' ,
295- } ;
296- }
297-
298- const canonicalFiles = entries . filter ( ( entry ) => entry . startsWith ( 'dwf-' ) && entry . endsWith ( '.md' ) ) ;
299- if ( canonicalFiles . length === 0 ) {
300- return {
301- passed : false ,
302- message : '.agents/rules/devw has no canonical files — run "devw compile"' ,
303- } ;
304- }
305-
306- return {
307- passed : true ,
308- message : `Canonical files exist (${ String ( canonicalFiles . length ) } file${ canonicalFiles . length === 1 ? '' : 's' } )` ,
309- } ;
310- }
311-
312- export async function checkCanonicalSync ( cwd : string , rules : Rule [ ] , config : ProjectConfig ) : Promise < CheckResult > {
313- const directoryBridges = getConfiguredDirectoryBridges ( config ) ;
314-
315- if ( directoryBridges . length === 0 ) {
316- return {
317- passed : true ,
318- message : 'Canonical sync skipped (no directory tools configured)' ,
319- skipped : true ,
320- } ;
321- }
322-
323- const canonicalOutputs = buildCanonicalOutputs ( rules ) ;
324- if ( canonicalOutputs . size === 0 ) {
325- return {
326- passed : true ,
327- message : 'Canonical sync skipped (no active scope outputs)' ,
328- skipped : true ,
329- } ;
330- }
331-
332- const mismatches : string [ ] = [ ] ;
333- let compared = 0 ;
334-
335- for ( const bridge of directoryBridges ) {
336- const expectedNativeFiles = new Set < string > ( ) ;
337-
338- for ( const [ canonicalPath , canonicalContent ] of canonicalOutputs ) {
339- const canonicalFilename = basename ( canonicalPath ) ;
340- const scopeName = canonicalFilename . slice ( 'dwf-' . length , canonicalFilename . length - '.md' . length ) ;
341- const nativeFilename = `${ bridge . filePrefix } ${ scopeName } ${ bridge . fileExtension } ` ;
342- expectedNativeFiles . add ( nativeFilename ) ;
343-
344- const nativePath = join ( cwd , bridge . outputDir , nativeFilename ) ;
345- if ( ! ( await fileExists ( nativePath ) ) ) {
346- mismatches . push ( `${ bridge . id } : missing ${ nativeFilename } ` ) ;
347- continue ;
348- }
349-
350- const nativeRaw = await readFile ( nativePath , 'utf-8' ) ;
351- const normalizedNative = normalizeComparableContent ( nativeRaw ) ;
352- const normalizedCanonical = normalizeComparableContent ( canonicalContent ) ;
353-
354- compared += 1 ;
355- if ( normalizedNative !== normalizedCanonical ) {
356- mismatches . push ( `${ bridge . id } : modified ${ nativeFilename } ` ) ;
357- }
358- }
359-
360- const bridgeDir = join ( cwd , bridge . outputDir ) ;
361- let entries : string [ ] = [ ] ;
362- try {
363- entries = await readdir ( bridgeDir ) ;
364- } catch {
365- entries = [ ] ;
366- }
367-
368- for ( const entry of entries ) {
369- if ( ! entry . startsWith ( bridge . filePrefix ) || ! entry . endsWith ( bridge . fileExtension ) ) {
370- continue ;
371- }
372- if ( ! expectedNativeFiles . has ( entry ) ) {
373- mismatches . push ( `${ bridge . id } : unexpected ${ entry } ` ) ;
374- }
375- }
376- }
377-
378- if ( mismatches . length > 0 ) {
379- return {
380- passed : false ,
381- message : `Canonical/native mismatch: ${ mismatches . join ( ', ' ) } ` ,
382- } ;
383- }
384-
385- return {
386- passed : true ,
387- message : `Canonical and native files are in sync (${ String ( compared ) } files compared)` ,
388- } ;
389- }
390-
391278export async function checkLegacyMigration ( cwd : string ) : Promise < CheckResult > {
392279 const legacyFiles = await detectLegacyFiles ( cwd ) ;
393280 if ( legacyFiles . length === 0 ) {
@@ -570,17 +457,7 @@ export async function runDoctor(): Promise<void> {
570457 const hashResult = await checkHashSync ( effectiveCwd , rules ) ;
571458 results . push ( hashResult ) ;
572459
573- // Check 11: Canonical output exists (skip if no rules)
574- if ( rules . length > 0 ) {
575- const canonicalExistsResult = await checkCanonicalExists ( effectiveCwd ) ;
576- results . push ( canonicalExistsResult ) ;
577-
578- // Check 12: Canonical and native outputs are synchronized
579- const canonicalSyncResult = await checkCanonicalSync ( effectiveCwd , rules , config ) ;
580- results . push ( canonicalSyncResult ) ;
581- }
582-
583- // Check 13: Legacy migration has no pending files
460+ // Check 11: Legacy migration has no pending files
584461 const legacyResult = await checkLegacyMigration ( effectiveCwd ) ;
585462 results . push ( legacyResult ) ;
586463
0 commit comments