2026-10-31: One Compass for Every Horizon

Open The Holocron on manoir and the Status crystal glowed steady green. Click deeper and the illusion cracked. Home Assistant refused to connect on loopback. Cilghal’s balance wing painted an offline card. Jocasta’s chat spun for fifteen seconds and gave up, while carrying mbp onto another network left Family dark. Nine separate places still assumed the entire haus lived on 127.0.0.1 at June’s paths, while October’s thirteen graduated Rust daemons ran underneath without a seat on the glass.
Nine quiet drifts between summer and autumn
Section titled “Nine quiet drifts between summer and autumn”Every drift had a reason when someone wrote it. None survived autumn intact. Auditing every IPC handler in main.js and every fetch() in src/renderer/ against the live listeners on manoir, mbp, and chalet turned up nine concrete mismatches plus a crash-looping Archives server:
| Surface | What the app assumed | What the runtime actually did |
|---|---|---|
Home Assistant (HausControlPanel) |
Hardcoded http://127.0.0.1:8123 unless HA_URL was exported in the shell |
launchd GUI apps do not inherit interactive shell exports; Home Assistant Green lives on the LAN / bridge100 airlock in ~/.sanctum/endpoints.json. |
Castellan Memory Pool (App.tsx) |
Polled GET :2189/capacity and read budgeted_used_mb + loaded[].service |
Rust sanctum-castellan serves GET :2189/status returning used_mb, headroom_mb, and loaded[].name / phys_footprint_mb — leaving :2189/capacity permanently 404. |
Cilghal Balance (App.tsx) |
Hardcoded a raw tailnet IP on :8770/panel/#${VITE_CILGHAL_COACH_TOKEN} |
cilghal-coach binds loopback behind tailscale serve (matching MagicDNS Host headers, returning 404 on raw IP), and packaged builds lacked build-time env tokens without Keychain hydration. |
Kiwix Library (SettingsPage & ⌘K) |
Hardcoded http://127.0.0.1:8888 |
kiwix-serve-start.sh intentionally binds the tailnet interface only (no LAN listener), refusing loopback connections. |
:38883 Origin Proxy (ServiceIframe) |
Encoded origins with base64url (- / _) in React, decoded standard base64 in main.js |
Any origin whose base64 encoding contained - or _ decoded into a malformed hostname, and a duplicated 302 block rewrote Location headers twice. |
Jocasta Chat (chat-with-jocasta) |
Opened a plain http.request to TLS :4040, never called req.write(postData), and sent no bearer token |
Every chat timed out after 15 seconds; worse, unauthenticated :4040/v1/messages routes to metered cloud fallback instead of $0 subscription seats. |
Family & Screen Flow (ScreenTimePanel, ScreenFlowHero, TopAppsCard, ActivityCard) |
Fetched http://127.0.0.1:4077 directly from the renderer (including raw DELETE on holidays) |
holocron-tunnel on mbp only forwarded :2187, :2189, and :3344, leaving Family blind off-box and bypassing force-flow-delete parent-unlock IPC. |
Vault Ceremony (gvRun & GV_BIN_DEFAULT) |
Hardcoded a developer workspace path and spawned sanctum-vault attached to the parent TTY |
Launching from a terminal let Rust rpassword open /dev/tty instead of piped stdin, hanging paper-escrow recovery drills indefinitely. |
Startup & Archives (ensureSanctumBackends + jocasta-crm) |
Probed plain HTTP :1111 and spawned a retired script; jocasta-crm-server.py referenced Dict[str, Any] without importing typing |
haus.sanctum.jocasta-crm (:6666) crash-looped on NameError, holding Watchdog overall status in degraded. |
Resolving the topology before painting a pixel
Section titled “Resolving the topology before painting a pixel”Qui-Gon’s rule for multi-node software is simple: ask the host what it is, verify what answers, and let the operator override anything in one 0600 file. We built resolveHolocronEnvironment() in main.js and paired it with <HolocronConfigProvider> in the renderer so a single .app bundle adapts to every Sanctum configuration:
- Five deployment profiles plus
auto. On launch, the resolver inspects~/.sanctum/.node_id,~/.sanctum/endpoints.json, and installed LaunchAgents to classify the Mac ashub(manoir),remote(mbp),satellite(chalet),standalone(single-Mac127.0.0.1install), orcustom, merging operator overrides from~/.sanctum/state/holocron-config.json(0600). - Parallel candidate probing and Keychain hydration. Each of the ten service endpoints races its ordered candidates (
127.0.0.1, MagicDNS / LAN registry entries, and post-quantum TLS:4078for remote Force Flow) with sub-second timeouts, while Cilghal’s#tokenfragment is hydrated main-side from~/.sanctum/secrets/cilghal-coach-tokenor login Keychain (cilghal-coach-token) so packaged builds never need build-time secrets baked into JavaScript bundles. - IPC transport for Force Flow and subscription-first Jocasta. A shared
ffGet()helper routes Family and Activity reads throughforce-flow-getinmain.js(and holiday removals throughparent-unlock-gatedforce-flow-delete).chat-with-jocastanow injects live Watchdog, Chi, and Sidecar telemetry into Jocasta’s system prompt and cascades strictly across$0subscription and local seats (:4200Grok OAuth ->:3456Claude Max ->:6543Gemini AGY ->:1337Local MLX Cathedral). - Full October 2026 stack surface (
SanctumStackPanel+TopologySettingsCard). Status now renders progressive-disclosure Apple Settings cards for the Chi energy field (:7777/chiGPU/RAM/thermal/token axes) and$0inference seats, Windu’s6/6security locks plus/Volumes/SanctumVaultarmor andsanctum-chi fseventsdprobes, and the live daemon fleet parsed from~/.sanctum/rust-readiness/rust_readiness.yaml+ps/launchctlwith Touch ID–gatedhaus.sanctum.*user-agent restarts. Settings gains a full Topology & Configuration card with profile pills, sidebar module switches (Family,Haus,Voice,AI Council),holocron-tunnelcontrol, and a live ten-endpoint reachability matrix.
The CDP race inside native Electron E2E
Section titled “The CDP race inside native Electron E2E”Shipping the Developer ID–signed bundle exposed one last seam. HOLOCRON_E2E_MODE=native failed on launch. Specifically, tests/holocron-e2e.sh polled http://127.0.0.1:9223/json/version and immediately ran agent-browser connect 9223. Chromium’s DevTools socket answers /json/version milliseconds before app.whenReady() opens the first BrowserWindow. At that instant /json/list is still [], so agent-browser issues Target.createTarget — a call Electron’s DevTools server rejects outright (Not supported). Waiting for "type": "page" in /json/list and keeping native reloads on the packaged file:// bundle closed the race for good.