# Stop literal `%h` directory creation

audience: AI coding agents first.

## Outcome

Stop future processes from treating systemd `%h` specifiers as literal relative paths. Existing `%h` artifacts are explicitly out of scope.

status: DONE
task IDs: #1, #4, #5
source request: Owner asked 2026-08-11: “what is creating all the \"%h\" folderS? I want it to stop”. Owner repeated authorization with “go” after a later stale-process scan; revalidate installed containment and recurrence without killing active sessions or touching preserved WIP.

Execution-discovered gate blocker 2026-08-11: repair the pre-existing concurrent-run collision in `agent-session-passthrough.test.sh` blocking this branch's frozen land gate. Replace fixed `passthrough` ledger identity with one unique, launcher-valid ID per test invocation; use it consistently in ledger JSON filename/content, socket path, and every `AGENT_LEDGER_ID` reference. Preserve assertions, skips, and refusal behavior. Verify syntax, two clean sequential out-of-tmpjail runs, and concurrent runs if feasible. Commit only test source; do not alter production code or `%h` artifacts.

## Acceptance criteria

- Identify exact creator and configuration seam from runtime evidence, not inference.
- Fix canonical source plus installed runtime configuration.
- Restart only affected services; prove healthy installed entrypoint.
- Prove no new `%h` directory appears during bounded recurrence check.
- Every `_human-session` launch path, including `exec_without_tmux`, passes only an absolute normalized `PYTHONPYCACHEPREFIX` to the runtime while preserving unrelated and already-absolute environment values.
- Deterministic forced-fallback coverage proves a runtime receives `$HOME/.cache/python-bytecode` and creates no cwd `%h` directory.
- `agent-session-passthrough.test.sh` derives one launcher-valid ledger ID per invocation, preventing fixed transient-unit, ledger-file, and socket collisions under repeated or concurrent gates.
- All seven passthrough assertions plus existing skip/refusal semantics remain unchanged.
- `bash -n`, two sequential required `systemd-run --user` invocations, and feasible concurrent separate-unit invocations pass cleanly.
- Land via project mechanism, deploy local infrastructure, prove installed entrypoint, zero live carriers, and no recurrence, then record a DONE receipt.

## Preserved WIP

- Delivery worktree `/home/user/Projects/overdeck/.worktrees/stop-percent-h` and branch `wt/stop-percent-h` were removed by the successful frozen controller after landing.
- Final receipt worktree: `/home/user/Projects/overdeck/.worktrees/percent-h-final-receipt`; branch: `wt/percent-h-final-receipt`.
- Existing unrelated shared-checkout WIP remains untouched.
- Existing `%h` paths found across multiple Overdeck worktrees are retained; existing-artifact deletion is outside this request.
- Follow-up revalidation leaves one dead-session shared-checkout WIP set (5 files) untouched and does not terminate active sessions.

## Constraints

- NEVER mutate shared main checkout.
- Existing `%h` artifacts are explicitly out of scope; do not inspect for deletion or remove them.
- Treat systemd specifier expansion by directive according to documented/runtime behavior. Do not globally replace valid `%h` uses in `ExecStart=` or `WorkingDirectory=`.
- Touch only directives proven to leak literal `%h` into child environments.
- Address every test, systemd, deploy, and commit warning.

## Execution steps

1. Preserve prior creator, runtime, and recurrence evidence; leave existing `%h` artifacts untouched.
2. Move `PYTHONPYCACHEPREFIX` normalization before all `_human-session` fallback decisions.
3. Add deterministic isolated coverage that forces an actual `exec_without_tmux` path without signalling live sessions.
4. Run requested syntax and focused regression checks.
5. Review diff and commit task files locally.
6. Land via project mechanism, deploy local infrastructure, re-prove installed entrypoint, zero live carriers, and no recurrence; record DONE.

## Current receipt

- 2026-08-11: Task #1 claimed by main session.
- Isolated worktree created at `/home/user/Projects/overdeck/.worktrees/stop-percent-h` from `origin/main` (`8d36d1468`).
- Exact creator established: stale `PYTHONPYCACHEPREFIX=%h/.cache/python-bytecode` inherited by long-lived tmux-launched agent sessions. Python resolves that relative path under each process working directory.
- Canonical source was already fixed by `493a411fc` on 2026-08-07; regression gate added by `f06a57cf6` on 2026-08-08. Installed `~/.config/environment.d/50-overdeck.conf` now uses `${HOME}` correctly. Systemd user manager and tmux global environments both hold `/home/user/.cache/python-bytecode`.
- Live-process scan found literal `%h` only in this pre-fix Claude process and its QuietContext children. Current tmux session environment is now explicitly corrected for the replacement process.
- Inventory found 242 Overdeck-related `%h` directories, 123,449 files, 2,609,449,659 bytes. Most content is generated bytecode. At least one `%h/gitdir` is real worktree metadata pointing to `/home/user/cdx-offload/incidentspage-0c30098ca13a`; bulk deletion is unsafe and outside the stop-only request.
- `bash tests/os/environment-d-specifiers.test.sh`: PASS=6 FAIL=0, no warnings.

- First pane replacement exposed stale `systray-ai.service`; restarted exact service at 2026-08-11 10:11:43 +07. Service returned active with PID 235801.
- Second replacement still inherited `%h`: `_human-session` serializes the invoking process environment with `export -p` (`modules/workstation/claude/bin/_human-session:115-132`). Long-lived terminals/launchers therefore bypass corrected `environment.d` and tmux state. Restarting systray alone cannot guarantee cleanup.
- Added boundary normalization limited to `PYTHONPYCACHEPREFIX=%h[/…]`; absolute and unrelated environment values remain unchanged.
- Worktree and installed-entrypoint `human-session.test.sh`: PASS=16 FAIL=0. Installed candidate at `~/.local/share/overdeck/deploy/modules/workstation/claude/bin/_human-session`; `~/.claude/bin/_human-session` resolves there and passed the real-entrypoint test.
- Replaced stale pane with explicit absolute prefix. Current process reports `/home/user/.cache/python-bytecode`; live `/proc` scan reports `literal_carrier_count=0`.
- Recurrence probe ran Python from the worktree and left existing `%h` directory metadata unchanged (`1786418481:4096` before and after).
- Commit `aaa6c748` records launcher normalization and regression test; commit gate reported `wrapper-reinvoke-lint: 5 wrapper bodies clean`.
- Independent review found normalization occurs after several `exec_without_tmux` branches. This fix moves it before all fallback decisions and adds an isolated forced-config-missing fallback regression. Existing artifacts remain untouched.
- Focused checks: `bash -n` launcher and test scripts exit 0; `human-session.test.sh` PASS=16 FAIL=0; `human-session-fallback.test.sh` PASS=4 FAIL=0; `environment-d-specifiers.test.sh` PASS=6 FAIL=0. No warnings.
- Local commit records the fallback normalization and regression coverage; landing, deployment, and installed-entrypoint re-proof remain pending.
- Ship review requires `human-session-fallback.test.sh` in the deterministic workstation suite and regenerated CI gate inventory before landing.
- Task #4: registered `workstation:human-session-fallback`; regenerated `tools/ci/gate-inventory.json`; `node tools/ci/inventory.mjs --check` passed; `node tools/ci/inventory.test.mjs` passed 7/7. Landing, deployment, and installed-entrypoint re-proof remain next.

- CI inventory registration committed: `workstation:human-session-fallback` is required; `node tools/ci/inventory.mjs --check` passed and `node tools/ci/inventory.test.mjs` passed 7/7.
- First frozen-controller land attempt exited 20 because `agent-session-passthrough.test.sh` produced empty wrapped terminal output. Focused rerun through its required out-of-tmpjail `systemd-run --user` entrypoint passed all 7 assertions with no warnings; no task source change was warranted.
- Two remote frozen broad gates on registry-reachable Debian3 then failed identically: fixed ledger ID `passthrough` mapped to already-loaded `agent-session-passthrough.service`; launcher refusal left `wrapped.events` absent. Task #5 is active in this worktree to make test invocation identity unique without changing production behavior or assertions.
- Test now derives `passthrough-$$-${TESTROOT##*.}` after atomic `mktemp`, then uses it for ledger JSON content/path, socket path, and `AGENT_LEDGER_ID`. `bash -n` passed. Two sequential required `systemd-run --user --pipe --wait --collect --same-dir --setenv=TERM=xterm-256color` runs each passed 7/7, exit 0. Two concurrent named user units each passed 7/7, exits 0. Outputs contained only successful lifecycle metrics; no warning/error. `git diff --check` passed; exact diff preserves assertions and skip/refusal branches.
- Commit `d876c274719d55e7b55ba2dc5c34ece1b16c6665` (`Make passthrough test identity unique`) contains only `modules/workstation/claude/tests/agent-session-passthrough.test.sh`. Commit emitted no warning or gate notice. Post-commit `git diff HEAD^ HEAD --check` passed; index is clean except this durable receipt.
- Independent ship review found the unique ID launcher-valid, consistent across ledger/socket/environment references, collision-resistant in sequential and concurrent runs, and behavior-preserving. No further source change is required before the frozen controller rerun.
- Frozen controller ticket `ticket.2a34ca2942a64142a7fd1b21d6b53bdd` was externally terminated during dependency refresh before any test ran. Its candidate `harness-deps.log` is empty and no verdict exists, so this is not a failed gate receipt.
- Foreground frozen controller ticket `ticket.6ed5ec2aced24a89b2363aa974f9f009` completed dependency refresh, candidate typecheck, and candidate test gates, then landed `wt/stop-percent-h`. Origin/main and the deployed clone now resolve to merge commit `64dd0cc6`; the delivery worktree and branch were cleaned by the controller.
- Post-deploy installed-entrypoint proof: `HUMAN_SESSION_LAUNCHER=~/.claude/bin/_human-session human-session.test.sh` passed 16/16. Installed forced-fallback proof passed 4/4, including absolute prefix delivery and no cwd `%h` directory.
- Post-deploy `/proc` scan found `literal_carrier_count=0`. Three fresh Python launches under `/home/user/.cache/python-bytecode` produced `fresh_probe_percent_h_count=0`.
- Deployment services are all active. The deploy receipt's final `collector_http=000` was a post-readiness race; immediate verification returned collector HTTP 401, the expected protected response, and web HTTP 200. No service fault remains.
- Existing `%h` artifacts were not removed or modified.
- 2026-08-11 17:19 +07 follow-up: `/proc` scan found `literal_carrier_count=0`. Fresh Python launches in delivery worktree and memory directory inherited absolute `/home/user/.cache/python-bytecode`; neither created a new `%h` path. Existing memory `%h` artifact remained unchanged by probe. No process termination or shared-checkout mutation was needed.
- Follow-up acceptance delta: none; owner repeated authorization required revalidation only because installed containment was already landed and live.

## Next executable action

None. Outcome is landed, deployed, and installed-entrypoint verified. Existing `%h` artifacts remain intentionally untouched.
