Skip to content

Commit 34deefc

Browse files
alicodingclaude
andcommitted
Revert dev ribbon to mount-time-only; drop the vite:afterUpdate self-subscription
The "true last build" version subscribed to import.meta.hot.on( 'vite:afterUpdate', ...) from App.tsx -- the same file that keeps getting hot-edited during normal iteration. React Fast Refresh didn't reliably clean up the old listener across repeated hot-swaps of that module, and the ribbon started ticking every second in the real desktop app (confirmed via ps/lsof this wasn't a stale-tab/stale-process issue -- a fresh Playwright tab against the same live dev server showed it static). Not worth chasing further for a dev-convenience ribbon. Back to capturing the timestamp once per mount, which is correct for the case that actually matters (a Go-triggered relaunch forces a fresh mount) and can't have this bug class at all. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01C7zUjYuMtgetjNaxMQPg2h
1 parent 0a731a3 commit 34deefc

2 files changed

Lines changed: 24 additions & 4 deletions

File tree

docs/SPEC.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -380,6 +380,21 @@ that environment, on something testable directly in this dev session:
380380
own inline result block on Runbook, just for the headless hotkey path.
381381
Empty `Result` (failure case) means no expand affordance at all, not an
382382
empty expanded block. `LOCKED`
383+
- **Small `DEV` ribbon (top-right, App.tsx) answers "am I looking at a dev
384+
build, and is it current."** Gated on `import.meta.env.DEV` (true only
385+
under a real `vite serve` process — verified directly that this is
386+
false for `vite build` regardless of `--mode`, see the repo-layout
387+
section above). Shows a timestamp captured once per mount — correct for
388+
a Go-triggered relaunch (the common case that actually needs checking),
389+
not for a frontend-only HMR edit that never remounts. A fancier version
390+
tried tracking true "last build" via `import.meta.hot.on('vite:after
391+
Update', ...)` and was reverted: subscribing to that event from
392+
`App.tsx`, the very file that keeps getting hot-edited, hit React Fast
393+
Refresh not reliably cleaning up the old listener across repeated
394+
hot-swaps of the same module — stray listeners kept firing. Not worth
395+
chasing further for a dev-convenience ribbon; mount-time-only is simpler
396+
and can't have that bug class. `LOCKED` (mount-time approach) / noted so
397+
the HMR-self-subscription approach isn't retried blind.
383398
- **Progressive enhancement by permission, not a hard gate.** `LOCKED`
384399
Zero-permission floor: browsing the Runbook and running an action by
385400
clicking it always works, no OS permission required. Accessibility

frontend/src/App.tsx

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,15 @@ function App() {
2626
const [time, setTime] = useState<string>('Listening for Time event...');
2727
const [actions, setActions] = useState<Action[] | null>(null);
2828
const [activity, setActivity] = useState<ActivityEntry[]>([]);
29-
// Captured once per mount. A Go-file change forces a full app reload
30-
// (Go isn't hot-reloadable, unlike frontend-only edits which apply via
31-
// Vite HMR without remounting) -- so this timestamp doubles as "when
32-
// did the last Go rebuild actually land," not just page-load trivia.
29+
// Captured once per mount -- correct for a Go-triggered relaunch (Go
30+
// isn't hot-reloadable, so a Go change forces a fresh mount) but not
31+
// for a frontend-only HMR edit, which updates live without remounting.
32+
// A vite:afterUpdate-based "true last build" version was tried and
33+
// reverted: subscribing to it from App.tsx, the same file that keeps
34+
// getting hot-edited, hit a real bug where React Fast Refresh didn't
35+
// reliably clean up the old listener across repeated hot-swaps of this
36+
// module, leaving stray listeners firing on unrelated updates. Not
37+
// worth chasing further for a dev-convenience ribbon -- see SPEC.md.
3338
const [loadedAt] = useState(() => new Date().toLocaleTimeString());
3439

3540
useEffect(() => {

0 commit comments

Comments
 (0)