chore(memory): BLK-021/022, LRN-150/151, BDR-088, EVAL-029 — macOS port

Capitalizes the macOS port and the gstack Chromium deadlock, plus an
append-only correction to BLK-008 / LRN-038: their "ubuntu24.04 fallback
build" cause is refuted — macOS arm64 has a native Playwright 1.58.2 build,
no fallback, and the same hang reproduces. The real variable was the Node
version, and that wrong record misdirected this investigation for an hour.

EVAL-029 records two process failures worth keeping: the first fix
recommendation (pin node@22) was reversed only because the user asked
whether the browser was current — staleness had gone unpriced; and the grep
sweep returned empty twice while defects were present, once to `set -e`,
once to a pattern that could not match `${1,,}`.

Index rows added for all four registries. Pre-existing index drift
(BLK-018..020, LRN-144..149) left alone — backfilling means summarising
entries someone else wrote.
This commit is contained in:
2026-09-15 21:39:22 -04:00
parent a53a5a26a8
commit 66012a97a7
6 changed files with 95 additions and 0 deletions
+25
View File
@@ -37,6 +37,8 @@ rules:
| BLK-015 | 2026-07-03 | `gitflow_finish` ignored its `<type> <name>` args → merged the CHECKED-OUT branch not the one named → wrong-branch merge (audit LOT3) | resolved |
| BLK-016 | 2026-07-04 | rtk compression PATH-dead 30 days — 6/5070 Bash commands compressed (~460K tokens missed); installer sources cargo env so its own check passes, Claude tool shell never gets ~/.cargo/bin | resolved |
| BLK-017 | 2026-07-17 | Bing Webmaster API unusable for a multi-client agency: OAuth swamp (localhost redirect refused, rotated single-use refresh tokens race our parallel dispatch), API key = wrong model (client-owned sites) | open/deferred |
| BLK-021 | 2026-09-13 | gstack Chromium install hangs forever on macOS: Playwright 1.58.2 deadlocks on Node 26 mid-extraction (39/333 files, all threads idle) | resolved |
| BLK-022 | 2026-09-13 | macOS bash 3.2 + BSD userland: six silent defects, most fail-OPEN (SSRF guard, commit scope guards, gate criteria) | resolved |
---
@@ -116,6 +118,7 @@ rules:
- **2026-06-23 UPDATE — Solution REVERTED, status downgraded to UPSTREAM/open** (commit b9c3937): the `PLAYWRIGHT_HOST_PLATFORM_OVERRIDE` solution above does NOT work on 26.04. The fallback build downloads to 100% then HANGS at extraction (chrome binary never appears, no headless-shell download starts; reproduced on real machine + sandbox) → turned a 0.5s fast-fail into an install-blocking hang (user Ctrl+C). Reverted to the fast-fail (non-fatal; gstack OFF by default, browser only for /browse,/qa,screenshots). The earlier "verified ldd + headless render" was an isolated test on a sibling already-extracted build (rev 1228) — it masked the rev-1208 install-path hang. **Real fix = upstream**: gstack bumps Playwright to a version that lists ubuntu26.04. Until then gstack's browser is unavailable on 26.04, install completes cleanly. See [[LRN-038]] correction.
- **2026-06-23 FINAL — RESOLVED** (commit 3b8ffb1): gstack browser now works on Ubuntu 26.04. Two layers fixed: (1) bumped gstack's pinned Playwright 1.58.2 → 1.61 (`bun add playwright@latest` in the submodule; 1.61 ships a native ubuntu26.04 build — chromium rev 1228), automated in the installer (`gstack_bump_playwright_if_unsupported`, idempotent, OS-gated); (2) `GSTACK_CHROMIUM_NO_SANDBOX=1` to work around the AppArmor userns restriction (`sysctl kernel.apparmor_restrict_unprivileged_userns=1`), persisted to `.bashrc` + installer Step 9 (sysctl-gated). Verified end-to-end: `browse goto https://example.com` → "Navigated (200)". Caveat: the Playwright bump is a local submodule edit, reset by `git submodule update`, re-applied by the next install. See [[BDR-029]], [[LRN-040]].
- **2026-09-13 CORRECTION — the diagnosis above is wrong, the fix was right**: the rev-1208 "downloads 100% then HANGS at extraction" was imputed to the `ubuntu24.04` FALLBACK build. REFUTED on macOS arm64, where Playwright 1.58.2 has a NATIVE build and no fallback exists: the SAME hang reproduces with the SAME signature (39/333 files, every thread idle). The real variable is the NODE version — 1.58.2 deadlocks on a runtime newer than itself, platform-independently. The 1.58.2→1.61 bump did resolve 26.04, but for a reason not recorded here: it also cleared that Node incompatibility. See [[BLK-021]] / [[LRN-150]].
---
@@ -242,3 +245,25 @@ rules:
- **Status**: resolved (A: ext hooks only terminals born after activation → install ext THEN start/re-attach session; B: Code app volume 0 in Windows mixer).
- **Lesson**: two independent client faults presented as one symptom ("nothing works"). Splitting probe = run signal in FRESH terminal + play VS Code's own sound preview. Preview bypasses terminal/BEL/hook/dtach/ext → isolates renderer audio in one step. Do that FIRST next time, before any server-side archaeology.
- **Reference**: [[BLK-019]] bell-only variant (resolved differently — setting alone insufficient here), [[LRN-145]] terminalSequence-not-/dev/tty pattern. Silent-degradation class [[LRN-047]].
## BLK-021 — gstack Chromium install hangs forever on macOS (Playwright 1.58.2 x Node 26) — 2026-09-13
- **Friction**: `make plugin` froze at step 2/10. Log ends mid-Chromium install: 100% of 162.3 MiB downloaded, then nothing — no error, no timeout, no progress. Steps 3-10 (RTK, GSD, marketplace plugins, link.sh, shell profile) never ran.
- **Real cause**: gstack's lockfile froze Playwright **1.58.2** (published 2026-02-06) → chromium rev 1208. Its extraction DEADLOCKS under **Node 26.5.0**: both processes (`playwright install` + child `oopDownloadBrowserMain.js`) fully idle — main thread in `kevent`, V8 AND libuv workers in `__psynch_cvwait`, 0% CPU, 2.5s CPU total — stuck at exactly 39/333 files. Zip fully downloaded and intact (170206961 B). NOT network, disk (396Gi free), Gatekeeper, quarantine (none set), nor Intego VirusBarrier — an AV block parks a thread in `write`; none was. PW 1.58.2 declares `engines: node >=18`, so Node 26 is formally SUPPORTED: the incompatibility is undeclared upstream.
- **Proof (3-way, one variable moved)**: Node 26 x PW 1.58.2 = hang (2/2 reproductions); Node 22.23.1 x PW 1.58.2, same command + same rev = OK (336 files); Node 26 x PW 1.63.0 = OK (347 files, 360MB, Chrome 153.0.8010.12).
- **Solution**: bump gstack Playwright 1.58.2 → 1.63.0 (rev 1243). In-range, not a pin break — `package.json` declares `"playwright": "^1.58.2"`; only `bun.lock` froze it. Installer now pre-installs the browser under a deadline with bump-retry ([[BDR-088]]). The submodule edit stays LOCAL (reset by `git submodule update`, re-applied by the next install — the [[BDR-029]] pattern).
- **Status**: resolved. Gate verified: `chromium.launch()` → `LAUNCH OK — Chromium 153.0.8010.12`, rc 0.
- **Corrects upstream record**: [[BLK-008]] / [[LRN-038]] imputed this exact signature on Ubuntu to the `ubuntu24.04` FALLBACK build. REFUTED: macOS arm64 has a NATIVE 1.58.2 build, no fallback exists there, and the same hang reproduces with the same signature. The real variable is the NODE version. The 1.58.2→1.61 bump did fix 26.04, but for a reason not recorded there — it also cleared the Node incompatibility.
- **Cost of the wrong record**: it sent the 2026-09-13 investigation hunting fallback builds first. A fix that WORKS can freeze a WRONG cause.
## BLK-022 — macOS bash 3.2 + BSD userland: six fail-OPEN or silent-no-op defects — 2026-09-13
- **Friction**: repo moved to macOS (Darwin 25.6, arm64). `make test` red across 5 suites, and several guards PASSED while doing nothing at all.
- **Real cause**: `/bin/bash` is **3.2.57** and `#!/usr/bin/env bash` resolves to it (no Homebrew bash on PATH). Every failure is silent:
- `${1,,}` (bash 4.0+) in `lib/url-guard.sh` → "bad substitution", subshell exits 1 = "not local" → the SSRF guard returned rc 0 for localhost, 127.x, 10.x, 192.168.x, 172.16-31.x, **169.254.169.254** and metadata.google.internal. FAIL-OPEN on every Mac; `url-guard.test.sh` recorded it as 13x "got[0] want[2]".
- `mapfile` in the 3 surgical-commit helpers → empty arrays → scope guards fail-OPEN, commits degrade to "nothing pending — no-op" while reporting success.
- `declare -A` in `hooks/session-start.sh` → every plugin cost read 0 → the >50%-budget warning could never fire.
- `timeout` (coreutils, absent from a stock macOS) in `lib/gates.sh` → exit 127 → EVERY criterion recorded NOT-MET whatever the check did.
- GNU `sed -i` x3 in `install-plugins.sh` → BSD sed errors → aborts the installer under `set -euo pipefail`.
- Test-side GNU-isms: `touch -d`, BSD `wc -l` padding (`got[ 48] want[48]`), `/bin/grep` (does not exist on macOS), `stat -c`, `sed -i` + `\n` in the replacement.
- **Solution**: `_read_lines_into` (portable mapfile), `shopt -s nocasematch` (bash 3.1+, keeps the no-fork property), `case` for plugin costs, resolved timeout binary + pure-bash fallback, `_sed_inplace` + awk. Split over 5 branches.
- **Status**: resolved. Every suite 0 failures except `gitflow-test.sh` (13 failures, PRE-EXISTING and unattributed: 92/14 on pristine develop vs 93/13 after — nothing worsened, one case better). shellcheck 1 finding before and after (pre-existing SC2016).
- **Bonus found while porting**: the orphan-comment cleanup `{N; /^\n$/d;}` in `install-plugins.sh` was a no-op on EVERY platform — after `N` the pattern space starts with '#', so the `^\n$` anchor pair never applied. Rewritten in awk and tested.