@@ -41,7 +41,40 @@ const DOCUMENTATION_DIR = join(PAI_DIR, "DOCUMENTATION")
4141const KNOWLEDGE_DIR = join ( PAI_DIR , "MEMORY" , "KNOWLEDGE" )
4242const BOOKMARKS_DIR = join ( PAI_DIR , "MEMORY" , "BOOKMARKS" )
4343const BOOKMARKS_CSV = join ( BOOKMARKS_DIR , "bookmarks.csv" )
44- const ALGORITHM_DIR = join ( PAI_DIR , "Algorithm" )
44+ // Resolve the Algorithm directory case-insensitively. The v6.3.0 doctrine uses
45+ // `ALGORITHM/` (all-caps) while older defaults used `Algorithm/` — on Linux
46+ // (case-sensitive FS), a string-equality mismatch silently empties the Wiki's
47+ // Algorithm view. Scan PAI_DIR once at module init.
48+ function resolveAlgorithmDir ( paiDir : string ) : string | null {
49+ if ( ! existsSync ( paiDir ) ) return null
50+ const entries = readdirSync ( paiDir , { withFileTypes : true } )
51+ const exact = entries . find (
52+ ( e ) => e . name === "Algorithm" && ( e . isDirectory ( ) || e . isSymbolicLink ( ) ) ,
53+ )
54+ if ( exact ) return join ( paiDir , exact . name )
55+ const variants = entries . filter (
56+ ( e ) =>
57+ e . name . toLowerCase ( ) === "algorithm" &&
58+ ( e . isDirectory ( ) || e . isSymbolicLink ( ) ) ,
59+ )
60+ if ( variants . length > 0 ) {
61+ // Deterministic tie-break: prefer `ALGORITHM` (v6.3.0 doctrine spelling),
62+ // else raw byte-order (locale-independent, stable across Node versions).
63+ // readdirSync order is FS-implementation-defined; never trust it.
64+ variants . sort ( ( a , b ) => {
65+ if ( a . name === "ALGORITHM" ) return - 1
66+ if ( b . name === "ALGORITHM" ) return 1
67+ return a . name < b . name ? - 1 : a . name > b . name ? 1 : 0
68+ } )
69+ return join ( paiDir , variants [ 0 ] . name )
70+ }
71+ console . warn (
72+ `[wiki] PAI Algorithm directory not found in ${ paiDir } — Algorithm view will be empty` ,
73+ )
74+ return null
75+ }
76+
77+ const ALGORITHM_DIR : string | null = resolveAlgorithmDir ( PAI_DIR )
4578const SKILLS_DIR = join ( HOME , ".claude" , "skills" )
4679const HOOKS_DIR = join ( HOME , ".claude" , "hooks" )
4780const SETTINGS_PATH = join ( HOME , ".claude" , "settings.json" )
@@ -177,7 +210,7 @@ function systemDocMetadata(filePath: string): { slug: string; group: string } |
177210 return { slug : `${ group } __${ bareSlug } ` , group }
178211 }
179212
180- if ( filePath . startsWith ( ALGORITHM_DIR ) ) {
213+ if ( ALGORITHM_DIR != null && filePath . startsWith ( ALGORITHM_DIR ) ) {
181214 const filename = basename ( filePath )
182215 return {
183216 slug : `Algorithm__${ stripMarkdownExtension ( filename ) } ` ,
@@ -528,7 +561,7 @@ function indexSystemDocs(): void {
528561 indexSystemDoc ( filePath )
529562 }
530563
531- if ( ! existsSync ( ALGORITHM_DIR ) ) return
564+ if ( ALGORITHM_DIR == null || ! existsSync ( ALGORITHM_DIR ) ) return
532565
533566 try {
534567 const algorithmFiles = readdirSync ( ALGORITHM_DIR , { withFileTypes : true } )
0 commit comments