1 Environment gotchas
mikebrandon edited this page 2026-09-04 11:52:58 +00:00

Environment gotchas

Facts about the tools and platforms, not bugs in this code. Each one cost real time at least once, and none of them is discoverable from the symptom.

Windows

tasklist's default output truncates the image name at 25 characters. So here-collector-input-metrics.exe prints as here-collector-input-metr and any substring match against the full name fails. /fo csv prints it in full. Three of this product's binaries are long enough to hit this.

PowerShell 5.1 reads a BOM-less UTF-8 .ps1 as ANSI. An em dash becomes â€", and the stray quote inside that breaks parsing several lines later, so the error points at innocent code. Every script here with non-ASCII characters carries a BOM.

PowerShell 5.1 has no backtick-e escape. ANSI-stripping regexes must use [char]27.

WebView2 suspends painting while its window is occluded, so PrintWindow against a covered console returns a blank white surface that looks exactly like a crashed front end. Raise the window first.

Two copies of the console genuinely cannot both load. The second one fails, which is what its watchdog dialog exists for. "Open" focuses an existing window rather than starting another.

A window that excludes itself from capture cannot be screenshotted, including by you. The pill sets WDA_EXCLUDEFROMCAPTURE, so every screenshot of it is a hole. Render it to a bitmap instead; there is a harness for exactly that.

Plain GDI has no antialiasing. The first hand-drawn icon set looked pixelated at 14px for this reason and nothing else. GDI+ has it.

A pill cannot be driven by synthetic clicks while another window covers it — the clicks go to the window on top. And it grows upward when a card opens, so click helpers have to measure from the window's bottom edge.

WS_EX_NOACTIVATE windows cannot own a menu. A tray menu needs a focusable owner, so the tray has its own hidden owner window. A tray menu also blocks the message loop, which is how the frozen-indicator bug surfaced.

macOS

Three signals need a TCC permission that only the person can grant — Screen Recording, Accessibility and Input Monitoring. Until they are granted, the capability report names exactly which signals are refused and which setting each one needs, rather than switching them on to produce nothing.

The Keychain cannot hold the store's key until the client is signed. An item's access list is per-binary, this client is several processes, and a second unsigned binary reading an item the first created blocks on a modal dialog. One keychain-access-group across a signed bundle is the fix.

Network denial is not enforceable per-process without a paid entitlement. See Porting and platform support.

Cross-compiling

Nothing that depends on here-store can be cross-compiled from a Mac. SQLite is built from C by libsqlite3-sys, and its build script wants the Windows SDK headers. cargo check --target x86_64-pc-windows-msvc dies on stdlib.h not found. That rules out the gate, the indicator, the collectors, the supervisor and the uploader.

here-win and here-os do cross-check cleanly, tests included, because neither depends on the store.

A module that looks macOS-only usually is not. Gating one with cfg(target_os = "macos") can break the Windows build, because its tests are portable and run on both. #[cfg_attr(not(target_os = "macos"), allow(dead_code))] is the form that works: keep the code compiled, excuse it from being called.

Node and the front end

Next's globalThis store cache serves the class as it was at process start. Adding a method to the dev server's store module needs a dev-server restart, or the route 500s with "not a function".