Skip to content

Bug: hardcoded mixed-case path segments break on Linux/case-sensitive filesystems #1278

@sinloft

Description

@sinloft

Summary

PAI ships with hardcoded path strings like PAI/Pulse, PAI/Algorithm, and PAI/Tools, but the actual directories on disk are PAI/PULSE, PAI/ALGORITHM, and PAI/TOOLS. On macOS (HFS+/APFS case-insensitive by default) this is invisible. On Linux, WSL, or any case-sensitive filesystem, these paths silently fail — files are not found, modules do not load, and the dashboard returns 404.

Environment

Any Linux install (LXC container, WSL, native). Confirmed on a Proxmox LXC running Debian.

Affected files

PAI/Pulse → actual dir is PAI/PULSE

File Line Bad reference
PULSE/Observability/observability.ts 69 join(PAI_DIR, "Pulse", "Observability", "out")
PULSE/setup.ts 18 join(PAI_DIR, "Pulse")
PULSE/lib.ts 249 join(..., "PAI", "Pulse")
PULSE/run-job.ts 34 join(..., "PAI", "Pulse")
PULSE/checks/github-work.ts 17 join(HOME, ".claude", "PAI", "Pulse")
PULSE/checks/poller-meta-monitor.ts 23–24 join(PAI_DIR, "Pulse", "state/PULSE.toml")
PULSE/checks/notification-governor.ts 37 join(PAI_DIR, "Pulse", "state", ...)
PULSE/modules/imessage.ts 63–64 join(HOME, ".claude", "PAI", "Pulse", "state/logs")
PULSE/modules/user-index.ts 28 join(PAI_DIR, "Pulse", "state")
TOOLS/DASchedule.ts 18 join(PAI_DIR, "Pulse", "state", "da")

PAI/Algorithm → actual dir is PAI/ALGORITHM

File Line Bad reference
PULSE/modules/wiki.ts 44 join(PAI_DIR, "Algorithm")

PAI/Tools → actual dir is PAI/TOOLS

File Line Bad reference
TOOLS/pai.ts 34 join(homedir(), ".claude", "PAI", "Tools", "Banner.ts")
TOOLS/MemoryRetriever.ts 286 path.join(PAI_DIR, "Tools", "Inference.ts")
PAI-Install/engine/actions.ts 1528 join(paiDir, "PAI", "Tools", "pai.ts")

Immediate workaround

For the Pulse dashboard 404, set an absolute dashboard_dir in PULSE.toml:

[observability]
enabled = true
dashboard_dir = "/home/<user>/.claude/PAI/PULSE/Observability/out"

Suggested fix

Centralise the canonical sub-directory names in one place (e.g. a paths.ts constants file) and use the all-caps names that match the actual directory layout:

export const PULSE_DIR   = join(PAI_DIR, "PULSE")
export const ALGO_DIR    = join(PAI_DIR, "ALGORITHM")
export const TOOLS_DIR   = join(PAI_DIR, "TOOLS")

Alternatively, add a small resolveDir() helper that stat-checks both the mixed-case and uppercase variants — this keeps backwards compatibility for any existing macOS installs that may have mixed-case directories.

Related

Related to #1252 (WSL install problems) — different root cause but same class of Linux-incompatibility.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions