v0.5.1
Added
- Spawn correlation token: kill-fork-doesn't-kill-parent + auto-select after fork. Server now mints a UUIDv4
spawnTokenperspawnPiSession()invocation, injects it asPI_DASHBOARD_SPAWN_TOKENinto the spawned pi's environment, and the bridge echoes it back in the firstsession_register. TheheadlessPidRegistryexposes a three-tier link —linkByToken(strong identity) →linkByPid(works for any bridge that sendspid) →linkSession(legacy cwd-FIFO fallback) — used byevent-wiring.tsto resolvesessionId↔pidmappings deterministically. ThependingForkRegistryis keyed by token, eliminating the race where two same-cwd forks would mis-attribute parents.spawn-register-watchdogadds a thirdbyTokenindex alongsidebyCwdandbyPid. The browser protocol gains optionalrequestId(spawn_session,resume_session) echoed inspawn_result/resume_result, plus optionalspawnRequestIdonsession_addedso the client auto-selects the new session for both spawn AND fork — closing the long-standing UX gap where forks did not auto-navigate. All new fields are optional; old bridges, old clients, and old servers continue to work via the lower-tier matching fallbacks. (change:spawn-correlation-token)
Changed
Fixed
- Killing a forked session no longer occasionally kills its parent. Pre-fix,
headlessPidRegistry.linkSession(sessionId, cwd)resolved by first-unsessioned-in-cwd FIFO order, which could swap parent and fork sessionIds when the bridge connect order didn't match the dashboard's spawn order. The new three-tier link (token → pid → cwd-FIFO) makes the mapping race-free for any bridge that sends apidinsession_register(all current bridges do). (change:spawn-correlation-token) - Forking an empty session no longer hangs for 30 seconds with a generic timeout. Previously, forking a session whose
.jsonlhad not been written yet (e.g., a freshly spawned session before any message) causedpi --fork <missing-path>to crash silently — the wrappersh -c "tail -f /dev/null | pi …"kept the parent process alive, so spawn-detached's 300ms crash check passed and the dashboard reportedsuccess: true. The bridge inside the dead pi never registered, so the spawn-register watchdog took 30 seconds to fire a generic "Pi started but never connected" banner. The dashboard now performs anexistsSyncpreflight before fork. When the source has no persisted JSONL, the server silently degrades to a fresh spawn in the same cwd (inheriting the parent'sattachedProposalif any) and surfaces the substitution viacode: "FORK_DEGRADED_TO_NEW"plus a non-blocking toast ("Started a fresh session — the source had no persisted history to fork from."). For empty sources, fork's user-meaningful semantic is identical to a new session, so honoring intent beats refusing. Both the WS handler and the/api/session/:id/resumeREST handler share the same logic. (change:fix-fork-empty-session-silent-timeout)
First-launch unblocking (unsigned binaries)
The Windows installers and macOS DMGs are not yet code-signed / notarized.
Both OSes will block first-launch with a security warning. These are not
malware — the artifacts are the exact ones produced by
.github/workflows/publish.yml
against this tag. Pick whichever workaround fits your workflow.
Tracking: Authenticode signing → change windows-authenticode-signing;
macOS notarization → change macos-notarization (planned). This section
will shrink and eventually disappear as each lands.
Windows — SmartScreen warning
SmartScreen will show "Windows protected your PC" the first time you
run any .exe artifact (Setup, portable, or any .exe extracted from a
ZIP).
Option A — at the SmartScreen dialog:
- Click More info.
- Click Run anyway.
Option B — pre-clear the Mark-of-the-Web:
- Right-click the downloaded
.exe(or the.zip) → Properties. - At the bottom of the General tab, tick Unblock next to
"This file came from another computer...". - Click OK and run as normal.
For ZIP archives, unblock the archive itself before extracting so
the contained .exes inherit the cleared zone.
macOS — Gatekeeper / quarantine
macOS will refuse to launch the app on first run with "PI Dashboard
cannot be opened because the developer cannot be verified" or silently
quarantine it.
Option A — control-click the app:
- Open the DMG and drag PI Dashboard to Applications.
- In Applications, right-click (or Control-click) PI Dashboard →
Open. - Click Open in the confirmation dialog. Subsequent launches are
unrestricted.
Option B — clear the quarantine attribute from the terminal:
xattr -d com.apple.quarantine "/Applications/PI Dashboard.app"If the DMG itself is being blocked, clear it on the mounted volume
before copying:
xattr -d com.apple.quarantine "/Volumes/PI Dashboard/PI Dashboard.app"