fix(pulse): cross-platform Windows + case-sensitive filesystem compatibility#1274
Open
alexgordon25 wants to merge 1 commit into
Open
fix(pulse): cross-platform Windows + case-sensitive filesystem compatibility#1274alexgordon25 wants to merge 1 commit into
alexgordon25 wants to merge 1 commit into
Conversation
PAI Pulse references its own directory as both "Pulse" (in code) and
"PULSE" (on disk). On case-insensitive filesystems (Windows NTFS, macOS
HFS+/APFS in default config) this is invisible, but on Linux and any
case-sensitive macOS volume every join(..., "Pulse", ...) resolves to a
non-existent path — silently returning 404s, broken state files, and
empty cron job state.
The Observability dashboard root path also fails to detect Windows
absolute paths because it uses startsWith("/") instead of
path.isAbsolute(), so configuring a dashboard_dir like
"C:\Users\me\dashboard" on Windows joins it onto HOME instead of
treating it as absolute.
Both issues hit me when porting Pulse to Windows 11 last weekend.
Patches are minimal — string-literal swap and one stdlib swap.
Changes:
- 8 "Pulse" -> "PULSE" in active code paths
(Observability/observability.ts x3, checks/github-work.ts,
checks/notification-governor.ts, checks/poller-meta-monitor.ts x2,
lib.ts, modules/imessage.ts x2, modules/user-index.ts,
Performance/cost-aggregator.ts)
- 1 startsWith("/") -> isAbsolute() in observability.ts getDashboardDir
- Add path.isAbsolute import
Verified on Windows 11 with NSSM-managed Pulse service: dashboard now
loads at localhost:31337, all 4 cron jobs (healthcheck, airgradient-poll,
cost-aggregation, cost-tracker) execute successfully against the new
PULSE-cased state paths.
Scope intentionally excludes pulse-old.ts, pulse-unified.ts, run-job.ts,
setup.ts — none are imported from the live daemon and you may have
separate plans for those.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
@
Summary
Two minor cross-platform fixes surfaced while running PAI v5.0.0 on Windows 11 (Pulse as a Windows service under NSSM). Both also help case-sensitive Linux / case-sensitive macOS filesystems.
Fix 1 —
Pulse→PULSEdirectory casing (11 occurrences, 8 files)Directory on disk is
PAI/PULSE/(uppercase), but several modules reference it asPAI/Pulse/(lowercase). Works on case-insensitive Windows NTFS / macOS HFS+ default, fails silently on case-sensitive Linux and APFS-case-sensitive Mac. In particulargetDashboardDir()inobservability.tsresolved to a missing path, producing 404 at the dashboard root.Files touched:
Observability/observability.ts(×3)Performance/cost-aggregator.tschecks/github-work.tschecks/notification-governor.tschecks/poller-meta-monitor.ts(×2)lib.tsmodules/imessage.ts(×2)modules/user-index.tsFix 2 —
path.isAbsolute()for Windows path detectiongetDashboardDir()inObservability/observability.tsuseddir.startsWith("/")to detect absolute paths. POSIX-only — Windows absolute paths begin with a drive letter (C:\…). Replaced withpath.isAbsolute()which handles both.Testing
Both patches running in production on a Windows 11 desktop install for ~6 days under NSSM (
PaiPulseservice). Dashboard atlocalhost:31337/serves all routes; cron jobs run clean; cloud-sync events continue posting.Scope
PR intentionally excludes identical occurrences in standalone scripts not imported from the live daemon (
pulse-old.ts,pulse-unified.ts,run-job.ts,setup.ts). Happy to extend if you would like the sweep to include them.Diff stats
8 files changed, +17 / −15. No new dependencies. No behavior change on case-insensitive filesystems.
@