You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Zero-conflict launch: OS-assigned ports + single-instance lock + per-user data dir
Three layered fixes that turn AdForge launch into "click icon → app opens"
with no port collisions, no double-spawn races, and no data loss on upgrade:
COMMIT A — OS-assigned ports on first run
- scripts/resolve-ports.cjs: new askOsForFreePair() binds to :0 (kernel-
assigned ephemeral port), reads back the assigned port, releases it. Used
on truly-first run (no .env.local yet) so we skip the contested
3000-range entirely. Zero collision risk because the OS just confirmed
the ports are free at that exact moment.
- Default port range bumped: 3010-5010 → 41573-49998 (IANA "registered but
rarely used" range). New defaultStartPort() seeds from a hash of the
install folder path so two AdForge installs begin at different bases.
- AdForge.bat + AdForge.command no longer seed .env.local with 3005/3006 —
the resolver does it with OS-assigned ports.
- Verified locally: first run → OS-assigned 57828/57829. Second run reads
from saved .env.local. Zero hits in the 3000-range.
COMMIT B — Single-instance lock + browser auto-refresh
- scripts/local-sync.cjs: acquireSingletonLock() writes pid to
data/.adforge.pid at boot. If another sidecar from this install is
already running (pid alive per signal-0 check), exits immediately.
Prevents the "user double-clicks AdForge.bat twice" race where two
processes both try to writeEnvLocal.
- New SESSION_TOKEN bumps on every sidecar start. /health endpoint exposes
it. public/launcher.html polls every 2s; when the token changes the
page reloads itself. Effect: user relaunches AdForge (or reboots their
machine and restarts the sidecar) → existing browser tab refreshes
automatically. No manual F5.
COMMIT C — Per-user data dir (OS conventions)
- scripts/local-sync.cjs: DATA_DIR now resolves to OS-native config:
Windows: %APPDATA%\AdForge\
macOS: ~/Library/Application Support/AdForge/
Linux: ~/.config/adforge/ (respects $XDG_CONFIG_HOME)
- Override via ADFORGE_DATA_DIR env var for testing / portable setups.
- One-time migrateLegacyDataDirOnce() copies any existing
./data/snapshot.json from the install folder to the new location. The
legacy file is not deleted (breadcrumb if user wants it).
- Result: user can re-clone AdForge into a new folder or replace their
install — saved snapshot persists. Aligns with native-app conventions.
- Verified locally: legacy snapshot was migrated to
C:\Users\princ\AppData\Roaming\AdForge\snapshot.json on first run.
Verification: tsc clean, 43/43 unit tests pass, next build compiles. The
existing 47/47 Playwright smoke tests still apply (routes weren't touched).
0 commit comments