Skip to content

Commit f3a4af2

Browse files
authored
fix(wiki): resolve Algorithm directory case-insensitively (#1273)
Verified bug in our 5.1.0 wiki.ts:44 — still uses join(PAI_DIR, "Algorithm") while doctrine + actual directory is ALGORITHM. Applying equivalent fix to our source.
1 parent e2ae840 commit f3a4af2

1 file changed

Lines changed: 36 additions & 3 deletions

File tree

  • Releases/v5.0.0/.claude/PAI/PULSE/modules

Releases/v5.0.0/.claude/PAI/PULSE/modules/wiki.ts

Lines changed: 36 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,40 @@ const DOCUMENTATION_DIR = join(PAI_DIR, "DOCUMENTATION")
4141
const KNOWLEDGE_DIR = join(PAI_DIR, "MEMORY", "KNOWLEDGE")
4242
const BOOKMARKS_DIR = join(PAI_DIR, "MEMORY", "BOOKMARKS")
4343
const 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)
4578
const SKILLS_DIR = join(HOME, ".claude", "skills")
4679
const HOOKS_DIR = join(HOME, ".claude", "hooks")
4780
const 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

Comments
 (0)