# Code Review: `.agents/skills/lib.sh` — write-isolation redesign (cp -a) implementing refined plan ## Scope This diff (`f2e23c1..ea863c0`, 35 insertions/17 deletions) is the **cumulative** diff against the last commit — it folds together the original agy TOS-seeding work already reviewed three times (`b803c6e5`, `afd375ef`, `8f8b6d63`), *and* implements the write-isolation redesign proposed in the Planner's refined plan (Job `fd3ba323`), which itself responded to a Creator challenge about two issues: 1. Symlinking mutable single-source-of-truth preference/state files causes cross-session/host state corruption. 2. `claude`'s `Library/Keychains` symlink was dead code, since `claude`'s isolation lever only redirects `CLAUDE_CONFIG_DIR`, never `HOME`. `git diff -- .agents/skills/lib.sh` matches this brief byte-for-byte (confirmed blob hashes: HEAD `f2e23c1`, working tree `ea863c0`, matching the diff's `index` line exactly). ## "No other files changed" check `git status --short`: - `M .agents/skills/lib.sh` — the only tracked-file modification. - `?? .agents/skills/multi-agent-mux-delegate-job/multi-agent-mux-delegate-job._.tmp`, `?? .DS_Store` — untracked, non-code artifacts (same benign job-runner scratch pattern observed in every prior review pass; `.DS_Store` is a macOS Finder metadata file, not a code change). Confirmed: **no files other than `.agents/skills/lib.sh` contain reviewable changes.** ## Verification performed - `bash -n .agents/skills/lib.sh` — syntax OK. - Read the full resulting `claude` and `agy` case-arms post-diff to confirm final state, not just the patch in isolation. ## Findings ### 1. `claude`'s `Library/Keychains` symlink block was fully removed — correct The diff's `claude` arm hunk (`@@ -1184,9 +1184,15 @@`) diffs against the pre-`b2e3ec97` baseline, which never had a `Library/Keychains` block for `claude` in committed history — that block only ever existed in the interim uncommitted state reviewed under `b2e3ec97`/`fd3ba323`. Reading the current file directly (lines 1185-1196) confirms the `claude` arm now ends after `cache` seeding with no Darwin/Keychains block at all. This is exactly the fix recommended in the `fd3ba323` refined plan: `claude`'s lever (`isolation_lever()` → `claude_config_dir`) never redirects `HOME`, so `security`/Keychain Services lookups by a spawned `claude` process always resolve against the real `$HOME/Library/Keychains` regardless of `$root` — the removed block was inert. Its removal is a correct dead-code cleanup, not a functional regression (it never had a documented behavior originally). ### 2. `cp -a` write-isolation conversion — correctly scoped and idempotent Nine call sites were converted from `ln -sfn` to a guarded `cp -a`: - `claude`: `settings.json` - `agy`: `.gemini/antigravity-ide`, three `Library/Preferences/$plist` entries, `Library/Application Support/{Antigravity, Antigravity IDE, com.google.GeminiMacOS}`, and the four XDG config/data variants. Each follows the pattern `if [ ! -e/-d/-f "$root/" ]; then cp -a "$HOME/" "$root/"; fi`, which is correctly idempotent: a `root` that was already provisioned (e.g., across a session restart reusing the same isolation directory) will **not** be re-copied, preserving any local mutations (theme changes, TOS-ack state) made during a prior isolated session's lifetime rather than clobbering them with the host's current state on every restart. This matches the refined plan's explicit requirement (`fd3ba323` §3.2: "대상이 `$root`에 이미 존재하지 않을 때만 복사"). `seeded` is still recorded unconditionally whenever the source exists, independent of whether the copy actually ran this time — correct, since the purpose of `seeded` is to report availability, not to log a fresh-copy event. `cp -a` is valid on both BSD/macOS and GNU coreutils `cp`, recursively copies directories, and preserves symlinks-within (does not dereference), so nested references inside a copied tree (if any) remain intact and point at their original absolute targets — no unintended dereferencing side effects. ### 3. Risk-tiering matches the plan; remaining symlinked items are consistent with the "medium/low risk" bucket Items still using `ln -sfn` after this diff — `claude`'s `session-env`/`sessions`/`cache`/`plugins`/`.credentials.json`/`.claude.json`; `agy`'s `.gemini/*` credential files, `.gemini/antigravity`, `.gemini/config`, `Library/Keychains` (agy only — correctly retained since `agy`'s lever is `home` and Keychain access there is real), and `Library/Group Containers` — all correspond to the plan's "medium risk" (append-style history/cache, treated as parity with normal multi-terminal shared-machine behavior) or "low risk" (credential identifiers not rewritten by the running process itself) tiers. No high-risk single-source preference/theme file was left as a live symlink; no low/medium-risk item was unnecessarily converted to `cp -a`. The classification from the accepted plan was applied consistently. ### 4. Minor, non-blocking observation: `Library/Application Support` `mkdir -p` hoisted outside the per-target `if` blocks The parent `mkdir -p "$root/Library/Application Support"` now runs unconditionally before the three Antigravity/Antigravity-IDE/GeminiMacOS checks, rather than only inside the first `if` block as before. This creates an empty `Library/Application Support` directory even when none of the three source directories exist on the host. Harmless (idempotent `mkdir -p`, no functional impact), and arguably cleaner since the same parent is now shared by three sibling `if` blocks instead of being created redundantly inside just one of them. ### 5. Known, plan-acknowledged open question (not a defect in this diff) The `fd3ba323` plan explicitly flagged as an open item whether "medium risk" append-style dirs (`session-env`, `sessions`, `cache`, `conversation_summaries.db`, etc.) should eventually also move to `cp -a` once product intent on cross-session history sharing is confirmed. This diff does not resolve that question — appropriately, since it wasn't in scope for the accepted plan's first implementation pass. Not counted against this diff. No lint tool (shellcheck) is available in this environment; manual read-through found no quoting, unbound-variable, or subshell issues. All space-containing paths (`"Library/Application Support"`, `"Application Support/Antigravity IDE"`) remain correctly double-quoted throughout the new `cp -a` call sites. ## Verdict This diff is a faithful, correctly-scoped implementation of the accepted `fd3ba323` refined plan: it removes the dead `claude` Keychain symlink, converts every identified high-risk single-source preference/theme/TOS file or directory to a guarded, idempotent one-time `cp -a`, and leaves append-style/low-mutation items on the existing symlink strategy per the plan's risk tiering. Syntax is valid, no other files were touched, and the one cosmetic observation (hoisted `mkdir -p`) does not affect behavior. [VERDICT: PASS]