diff --git a/PLATFORM.md b/PLATFORM.md index 25a1abe37..68df7e015 100644 --- a/PLATFORM.md +++ b/PLATFORM.md @@ -54,6 +54,15 @@ This document tracks all platform-specific code and dependencies across PAI, pro - **Fix:** Updated to reflect Linux is fully supported - **Status:** Documentation now accurate +6a. βœ… `Pulse` vs `PULSE` directory casing mismatch + - **Files:** `Releases/v5.0.0/.claude/PAI/PULSE/{run-job,lib,setup,pulse-unified}.ts`, + `PULSE/modules/{imessage,user-index}.ts`, `PULSE/Performance/cost-aggregator.ts`, + `PULSE/checks/{notification-governor,poller-meta-monitor,github-work}.ts`, + `PULSE/Observability/observability.ts` (11 files, 14 occurrences) + - **Issue:** Source referenced `~/.claude/PAI/Pulse/...` but directory on disk is `PULSE`. Worked on macOS APFS (case-insensitive default) but broke on Linux ext4 and case-sensitive APFS β€” config and state lookups silently missed. + - **Fix:** Aligned all `path.join(...)` literals to `"PULSE"`. + - **Tested:** Linux (Ubuntu, runtime-verified). Behavior unchanged on case-insensitive filesystems (macOS default, NTFS). + --- ### πŸ“‹ ALREADY HANDLED (No Action Needed) diff --git a/Releases/v5.0.0/.claude/PAI/PULSE/Observability/observability.ts b/Releases/v5.0.0/.claude/PAI/PULSE/Observability/observability.ts index 984c1b448..a55180e93 100644 --- a/Releases/v5.0.0/.claude/PAI/PULSE/Observability/observability.ts +++ b/Releases/v5.0.0/.claude/PAI/PULSE/Observability/observability.ts @@ -66,7 +66,7 @@ const SECURITY_LOG_DIR = join(MEMORY_DIR, "SECURITY") const SETTINGS_PATH = join(HOME, ".claude", "settings.json") const LADDER_DIR = join(HOME, "Projects", "Ladder") -const DEFAULT_DASHBOARD_DIR = join(PAI_DIR, "Pulse", "Observability", "out") +const DEFAULT_DASHBOARD_DIR = join(PAI_DIR, "PULSE", "Observability", "out") // ── In-Memory Store (hook-pushed state/events) ── @@ -149,7 +149,7 @@ function getDashboardDir(): string { const dir = config.dashboard_dir ?? DEFAULT_DASHBOARD_DIR // Resolve relative paths against Pulse directory if (!dir.startsWith("/")) { - return join(HOME, ".claude", "PAI", "Pulse", dir) + return join(HOME, ".claude", "PAI", "PULSE", dir) } return dir } @@ -1647,7 +1647,7 @@ function readDirMdFiles(dir: string): { name: string, content: string, sections: function handleUserIndexApi(filter: string | null): Response { try { const PAI_DIR = process.env.PAI_DIR || join(process.env.HOME || "", ".claude", "PAI") - const indexPath = join(PAI_DIR, "Pulse", "state", "user-index.json") + const indexPath = join(PAI_DIR, "PULSE", "state", "user-index.json") const raw = Bun.file(indexPath) if (!raw.size) { return Response.json( diff --git a/Releases/v5.0.0/.claude/PAI/PULSE/Performance/cost-aggregator.ts b/Releases/v5.0.0/.claude/PAI/PULSE/Performance/cost-aggregator.ts index f6c5af5ce..727620fab 100644 --- a/Releases/v5.0.0/.claude/PAI/PULSE/Performance/cost-aggregator.ts +++ b/Releases/v5.0.0/.claude/PAI/PULSE/Performance/cost-aggregator.ts @@ -17,7 +17,7 @@ const HOME = process.env.HOME ?? "" const PAI_DIR = join(HOME, ".claude", "PAI") const PROJECTS_DIR = join(HOME, ".claude", "projects") const OUTPUT_FILE = join(PAI_DIR, "MEMORY", "OBSERVABILITY", "session-costs.jsonl") -const STATE_FILE = join(PAI_DIR, "Pulse", "Performance", "aggregator-state.json") +const STATE_FILE = join(PAI_DIR, "PULSE", "Performance", "aggregator-state.json") // Model pricing per million tokens (as of 2026-04) const MODEL_PRICING: Record = { diff --git a/Releases/v5.0.0/.claude/PAI/PULSE/checks/github-work.ts b/Releases/v5.0.0/.claude/PAI/PULSE/checks/github-work.ts index 78782f17d..79ad44953 100644 --- a/Releases/v5.0.0/.claude/PAI/PULSE/checks/github-work.ts +++ b/Releases/v5.0.0/.claude/PAI/PULSE/checks/github-work.ts @@ -14,7 +14,7 @@ import { parse } from "smol-toml" import { SignJWT, importPKCS8 } from "jose" const HOME = process.env.HOME ?? "" -const PULSE_DIR = join(HOME, ".claude", "PAI", "Pulse") +const PULSE_DIR = join(HOME, ".claude", "PAI", "PULSE") const STATE_FILE = join(PULSE_DIR, "state", "work-token.json") // ── Worker Config (from PULSE.toml [worker] section) ── diff --git a/Releases/v5.0.0/.claude/PAI/PULSE/checks/notification-governor.ts b/Releases/v5.0.0/.claude/PAI/PULSE/checks/notification-governor.ts index fb1a62ea3..6947efa48 100644 --- a/Releases/v5.0.0/.claude/PAI/PULSE/checks/notification-governor.ts +++ b/Releases/v5.0.0/.claude/PAI/PULSE/checks/notification-governor.ts @@ -34,7 +34,7 @@ import { createHash } from "crypto"; const HOME = process.env.HOME || ""; const PAI_DIR = process.env.PAI_DIR || join(HOME, ".claude", "PAI"); -const STATE_FILE = join(PAI_DIR, "Pulse", "state", "notification-governor.json"); +const STATE_FILE = join(PAI_DIR, "PULSE", "state", "notification-governor.json"); const LOG_FILE = join(PAI_DIR, "MEMORY", "OBSERVABILITY", "notification-governor.jsonl"); const NOTIFY_URL = "http://localhost:31337/notify"; const VOICE_ID = "fTtv3eikoepIosk8dTZ5"; diff --git a/Releases/v5.0.0/.claude/PAI/PULSE/checks/poller-meta-monitor.ts b/Releases/v5.0.0/.claude/PAI/PULSE/checks/poller-meta-monitor.ts index 5ca27d1c6..7340c8054 100644 --- a/Releases/v5.0.0/.claude/PAI/PULSE/checks/poller-meta-monitor.ts +++ b/Releases/v5.0.0/.claude/PAI/PULSE/checks/poller-meta-monitor.ts @@ -20,8 +20,8 @@ import { join } from "path"; const HOME = process.env.HOME || ""; const PAI_DIR = process.env.PAI_DIR || join(HOME, ".claude", "PAI"); -const PULSE_STATE = join(PAI_DIR, "Pulse", "state", "state.json"); -const PULSE_TOML = join(PAI_DIR, "Pulse", "PULSE.toml"); +const PULSE_STATE = join(PAI_DIR, "PULSE", "state", "state.json"); +const PULSE_TOML = join(PAI_DIR, "PULSE", "PULSE.toml"); // Jobs we specifically monitor β€” the Currentβ†’Ideal pipeline ones. const WATCHED_JOBS = [ diff --git a/Releases/v5.0.0/.claude/PAI/PULSE/lib.ts b/Releases/v5.0.0/.claude/PAI/PULSE/lib.ts index 93d77fac6..8889825be 100644 --- a/Releases/v5.0.0/.claude/PAI/PULSE/lib.ts +++ b/Releases/v5.0.0/.claude/PAI/PULSE/lib.ts @@ -246,7 +246,7 @@ export async function spawnScript(command: string, timeoutMs = 60_000): Promise< const proc = Bun.spawn(["bash", "-c", command], { stdout: "pipe", stderr: "pipe", - cwd: join(process.env.HOME ?? "~", ".claude", "PAI", "Pulse"), + cwd: join(process.env.HOME ?? "~", ".claude", "PAI", "PULSE"), env: { ...process.env }, }) diff --git a/Releases/v5.0.0/.claude/PAI/PULSE/modules/imessage.ts b/Releases/v5.0.0/.claude/PAI/PULSE/modules/imessage.ts index c6fe58bce..32e3d3a99 100644 --- a/Releases/v5.0.0/.claude/PAI/PULSE/modules/imessage.ts +++ b/Releases/v5.0.0/.claude/PAI/PULSE/modules/imessage.ts @@ -60,8 +60,8 @@ export interface IMessageHealth { const HOME = process.env.HOME ?? "" const CWD = join(HOME, ".claude") -const STATE_DIR = join(HOME, ".claude", "PAI", "Pulse", "state", "imessage") -const LOGS_DIR = join(HOME, ".claude", "PAI", "Pulse", "logs", "imessage") +const STATE_DIR = join(HOME, ".claude", "PAI", "PULSE", "state", "imessage") +const LOGS_DIR = join(HOME, ".claude", "PAI", "PULSE", "logs", "imessage") let pollTimer: ReturnType | null = null let running = false diff --git a/Releases/v5.0.0/.claude/PAI/PULSE/modules/user-index.ts b/Releases/v5.0.0/.claude/PAI/PULSE/modules/user-index.ts index 7ee19c501..aac3f1dda 100644 --- a/Releases/v5.0.0/.claude/PAI/PULSE/modules/user-index.ts +++ b/Releases/v5.0.0/.claude/PAI/PULSE/modules/user-index.ts @@ -25,7 +25,7 @@ import { join, relative, basename, dirname } from "path" const HOME = process.env.HOME ?? "" const PAI_DIR = process.env.PAI_DIR || join(HOME, ".claude", "PAI") const USER_DIR = join(PAI_DIR, "USER") -const STATE_DIR = join(PAI_DIR, "Pulse", "state") +const STATE_DIR = join(PAI_DIR, "PULSE", "state") const INDEX_PATH = join(STATE_DIR, "user-index.json") const MODULE_NAME = "user-index" diff --git a/Releases/v5.0.0/.claude/PAI/PULSE/pulse-unified.ts b/Releases/v5.0.0/.claude/PAI/PULSE/pulse-unified.ts index ad45bd166..bac9cfa6e 100644 --- a/Releases/v5.0.0/.claude/PAI/PULSE/pulse-unified.ts +++ b/Releases/v5.0.0/.claude/PAI/PULSE/pulse-unified.ts @@ -22,7 +22,7 @@ import { parse } from "smol-toml" const HOME = process.env.HOME ?? "~" const PAI_DIR = join(HOME, ".claude", "PAI") -const PULSE_DIR = join(PAI_DIR, "Pulse") +const PULSE_DIR = join(PAI_DIR, "PULSE") const envPath = join(HOME, ".claude", ".env") try { diff --git a/Releases/v5.0.0/.claude/PAI/PULSE/run-job.ts b/Releases/v5.0.0/.claude/PAI/PULSE/run-job.ts index de5b6f50a..afaf35783 100644 --- a/Releases/v5.0.0/.claude/PAI/PULSE/run-job.ts +++ b/Releases/v5.0.0/.claude/PAI/PULSE/run-job.ts @@ -31,7 +31,7 @@ if (!jobName) { process.exit(1) } -const PULSE_DIR = join(process.env.HOME ?? "~", ".claude", "PAI", "Pulse") +const PULSE_DIR = join(process.env.HOME ?? "~", ".claude", "PAI", "PULSE") const config = await loadConfig(PULSE_DIR) const job = config.jobs.find((j) => j.name === jobName) if (!job) { diff --git a/Releases/v5.0.0/.claude/PAI/PULSE/setup.ts b/Releases/v5.0.0/.claude/PAI/PULSE/setup.ts index a743ea2f3..44fe69136 100644 --- a/Releases/v5.0.0/.claude/PAI/PULSE/setup.ts +++ b/Releases/v5.0.0/.claude/PAI/PULSE/setup.ts @@ -15,7 +15,7 @@ import { existsSync, mkdirSync } from "fs" const HOME = process.env.HOME ?? "~" const PAI_DIR = join(HOME, ".claude", "PAI") -const PULSE_DIR = join(PAI_DIR, "Pulse") +const PULSE_DIR = join(PAI_DIR, "PULSE") // ── Helpers ──