# Laptop build containment — no builds lag the workstation

- **Status:** ACTIVE — remote-only landing-controller correction executing in `wt/finish-branch-remote-only`; containment + parity otherwise delivered and deployed.
- **Source request:** owner, 2026-08-15 load fire ("FIRE CPU LOAD 100%"; "working agents take cpu because they are busy. i need them. what i dont need is builds on the laptop").
- **Outcome:** builds never lag the workstation: every build the classifier can see is contained (build.slice, CPUWeight=20/CPUQuota=400%) or offloaded; working agent scopes and the owner's qemu VM are never killed or throttled.

## Acceptance criteria

1. `pnpm … deploy` classifies heavy + local-only (contained via local-gate, never offloaded — it materializes node_modules locally). ✔ tested (cpu-guard-route.test.sh).
2. PHP tooling (php→phpstan/psalm/phpunit/rector, composer install/update/require/create-project) classifies heavy + local-only; `php`/`composer` PATH shims exist. ✔ tested (cpu-guard-route, remote-build.test.mjs).
3. build.slice carries CPUWeight=20 persistently (unit file), so builds yield to desktop/VM/agents. ✔ in branch; runtime property already applied live.
4. PHP work offloads to buildboxes like node builds — follow-up lane (below).
5. Landing-controller test and touched-package typecheck gates pass `--remote-only` to `local-gate`, so controller-owned verification refuses when remote dispatch fails and never falls back to the workstation. In progress.

## Constraints

- NEVER kill/throttle owner qemu VM (vm1) — owner ruling 2026-08-15.
- NEVER stop working confine-agent scopes during overload triage — cap or route builds instead.
- php-toolchain local-only exemption stays until buildboxes carry a parity php toolchain AND remote vendor/ materialization exists.

## Execution

- Remote-only controller correction (2026-08-16): a verified Page translation slice cannot safely use the frozen Press.zone publication wrapper because `finish-branch.sh::run_test_gate()` invokes `local-gate` without `--remote-only`; that dispatcher may fall back to workstation execution. Add the fail-closed flag to ordinary tests and remote touched-package typechecks, extend both controller contract assertions to require it, run the focused test on a registry-selected buildbox, install the landed runtime copy before resuming Page-slice publication, and record the installed proof.
- Current receipt (2026-08-16): remote `debian3` controller-suite execution exercised both new assertions successfully. The suite reports `141` passes; its six documentation-lane frontmatter failures recur unchanged before and after this isolated remote-only change. They are unrelated to controller invocation, and the remote host confirms `markdownlint-cli2@0.23.2` is installed. Next: commit and publish the fail-closed controller correction, deploy its installed copy, verify its exact runtime bytes and a remote-only invocation, then resume the Page-slice publication.

- Branch `wt/build-containment-gaps` @ 1f07d03b1: cpu-guard classifier (+deploy, +php ecosystem), remote-build LOCAL_EXEMPTIONS (+deploy verb, +php-toolchain), bin/php + bin/composer shims, build.slice CPUWeight=20, tests extended (route ×4, exemptions ×5, all green).
- Parallel lane (Opus subagent, running): add php8.4-cli + extensions + composer to buildbox provisioning source, apply to registry-reachable boxes, verify parity. Its worktree branch lands separately; after that plus remote vendor/ materialization, remove the php-toolchain exemption (cpu-guard.sh `_cg_strict_remote`, remote-build.mjs LOCAL_EXEMPTIONS) so phpstan offloads.

## Receipt (2026-08-15, all landed + deployed + verified)

- Fire resolved: load 145 → ~30; no agent killed after owner directive (one re-runnable deploy-script test scope was stopped before it).
- Landed 68749558b (containment: classifier, shims, CPUWeight=20 unit) → deployed sha 728636d1; installed `~/.claude/lib/cpu-guard.sh` diff-verified against origin/main; installed `php` shim probed (`php -r` passthrough OK); `systemctl --user show build.slice -p CPUWeight` = 20.
- Landed 2eca4d14 (install-routing fix: `npx playwright install` stays local; both stale tests now probe the repo copy and distinguish remote-only from gated-local; the 2 script-body failures were this staleness, fixed).
- Landed 55b8c902d (buildbox php parity): debian1/2/3 run PHP 8.4.24 + Composer 2.10.2 from Debian forky/main via `modules/buildbox/lib/buildbox-checks.sh` items `item_php`/`item_composer`; `php -m` diff vs workstation empty on all three; root cause on boxes was a stale hand-pushed `~/.local/bin/php` podman wrapper (dead container), now removed with a behavior guard. No Sury, no upstream composer installer (both premises wrong — Debian forky ships exact parity versions). Boxes NOT rebooted; harden-drift left alone.
- Deploy clone drained to a167442b (includes all three lands, coalesced queue).
- Named gaps: fresh-install php path on a box never exercised end to end; `node-runtime.smoke.sh` pre-existing unrelated failure (seat image node 22 vs want 24); phpstan/phpunit not installed on boxes (composer is the vehicle).

## Next executable action

Open lane (php offload): teach remote jobs to materialize `vendor/` (composer install on-box, warm cache), then remove the php-toolchain local-only exemption in `cpu-guard.sh` `_cg_strict_remote` + `remote-build.mjs` LOCAL_EXEMPTIONS so phpstan offloads like node builds.
