aboutsummaryrefslogtreecommitdiffstats
path: root/CLAUDE.md
diff options
context:
space:
mode:
Diffstat (limited to 'CLAUDE.md')
-rw-r--r--CLAUDE.md55
1 files changed, 55 insertions, 0 deletions
diff --git a/CLAUDE.md b/CLAUDE.md
index 4d8a208..88e71cd 100644
--- a/CLAUDE.md
+++ b/CLAUDE.md
@@ -343,6 +343,59 @@ do. Read them before writing anything that touches the same mechanism.
the page. `ask.js` draws both in the page, and
`test_no_native_dialogs_in_the_spa.py` bans all three browser dialogs
+- **An upgrade that cannot stop the node installs around it.** In service mode
+ the daemon runs in the task's S4U session, and the installer's unelevated
+ `taskkill` got "Access is denied" — which `main.js` had already recorded on
+ 2026-09-14, for itself only. It also ran in `customInstall`, which
+ electron-builder inserts *after* the files are copied; a test asserted that
+ `taskkill` under the name "stops a running daemon before overwriting it",
+ wrong on both counts. The locked `meshbay-node.exe` was not replaced, the
+ last-resort extract ignored that, and since a onedir exe embeds all the
+ node's Python, the 0.16 app and hub talked to the previous node: "started but
+ could not link", "No operator paired" (a node not yet signed in has not read
+ its roster, and answered `false`), and `service start` printing "started"
+ about a node nobody had checked. Linux never saw it — the package manager
+ restarts the unit. Stopping now happens in `customCheckAppRunning`
+ (`schtasks /end`, which the owner may do), the daemon logs to
+ `%LOCALAPPDATA%\meshbay\state\node.log` because Task Scheduler discards its
+ stderr, and the build starts the frozen daemon instead of only asking for
+ `--help`. **Read the installer framework's template before believing a hook
+ runs when its name suggests**, and **a message about a node must come from a
+ node that was asked** — every one of those four was a guess stated as a fact
+
+- **On Windows the CLI is the process it is stopping.** The frozen
+ `meshbay-node.exe` is the daemon *and* every CLI verb, so the forced-stop
+ fallback `taskkill /IM meshbay-node.exe` killed `autostart stop` and
+ `restart-daemon` themselves: exit 1, no output, and — for a restart — no node
+ afterwards. The app's Restart delegates to that verb, so it reported "the
+ node did not start". Every unit test passed, because `subprocess.run` was
+ mocked; it takes running the installed exe to see. It now spares its own pid
+ and its parent's (a venv's `meshbay-node.exe` is a launcher whose `python.exe`
+ child does the work), and `/T` takes the daemon's children with it.
+ `test_the_forced_stop_really_spares_its_caller` runs it for real, under an
+ image name of its own — under the real one it would kill the developer's node
+
+- **A second instance must fail before it touches anything shared.** The
+ daemon wrote `ui-token` and logged "Control API on …" *before* uvicorn had
+ bound the port. So the sign-in launcher, run while a node was up, started one
+ that overwrote the running node's token, failed to bind inside uvicorn's task,
+ and exited with the reason on a hidden console — nothing in `node.log`. The
+ node that stayed up then refused every graceful stop, status and restart,
+ because the token file named a dead process; the next upgrade had to kill it.
+ Linux has the same order. `bind_control_port` now takes the port first
+ (exclusively on Windows, where `SO_REUSEADDR` would let a second socket
+ share a port in use) and a refusal is logged and exits 2. **Log a claim
+ after it is true**: "Control API on" had always been printed about a
+ server that did not exist yet
+
+- **A test that redirects `HOME` isolates nothing on Windows.** `Path.home()`
+ reads `USERPROFILE` there and the node's directories come from
+ `LOCALAPPDATA`, so the CLI tests wrote `invite-code`, `pair-code` and
+ `invite-link` — `TEST-CODE`, `example.invalid` — into the developer's real
+ node directory on every run, and into a `~/.local/share/meshbay` created for
+ the purpose. The node conftest now points all four variables at a throwaway
+ directory for every test
+
- **A user unit cannot carry `User=`.** `meshbay-node.spec` installed the system
template into `%{_userunitdir}`, where systemd refuses the file outright — the
packaged unit could never have started, and nothing noticed because nobody had
@@ -946,6 +999,8 @@ here are kept only where they are a rule about *editing* the code.
| Flow-control worst case | `packages/meshbay-hub/tests/harness/window_leak.mjs` |
| Session renewal against a hub that enforces rotation | `packages/meshbay-hub/tests/harness/session_harness.mjs` |
| An invitation link opened in the real app, signed out and in | `packages/meshbay-hub/tests/harness/invite_link_probe.py` |
+| A show's modal and the player, walked episode to episode | `packages/meshbay-hub/tests/harness/video_series_probe.py` |
+| A lazily loaded view whose module answers 404 (a tab older than the deploy) | `packages/meshbay-hub/tests/harness/lazy_failure_probe.py` |
## meshbay.org server (target state)