claudebox/.planning/phases/05-per-project-instance-isolation/05-02-SUMMARY.md

4.8 KiB

phase plan subsystem tags dependency-graph tech-stack key-files decisions metrics
05-per-project-instance-isolation 02 gc-lifecycle
gc
cleanup
instance-isolation
cli-flag
bash-testing
requires provides affects
05-01
gc-instances-function
gc-flag
claudebox.sh
test-gc.sh
added patterns
Glob-then-guard pattern
for dir in projects/*/; -d "$dir" || continue
bash-only test
inline function redefinition avoids sourcing full script with side effects
created modified
test-gc.sh
claudebox.sh
gc_instances() defined before --check block so it is available before ANSI formatting variables are set
GC dispatch block placed after --check block, before ANSI formatting — same early-exit pattern as --check
test-gc.sh inlines gc_instances rather than sourcing claudebox.sh to avoid bwrap exec side effects; sed not in PATH in sandbox
(( removed++ )) || true used to prevent set -e exit when removed is 0 (arithmetic returns non-zero)
duration completed tasks_completed files_modified
~20 minutes 2026-04-13 2 2

Phase 05 Plan 02: GC Flag and gc_instances Function Summary

--gc flag and gc_instances() function added to claudebox.sh; removes stale per-project instance directories whose recorded project root no longer exists on disk, with three-case integration test.

What Was Built

claudebox.sh Changes

Flag variable and parsing:

  • Added GC_MODE=false on line 6 (after SHELL_MODE=false)
  • Added --gc) GC_MODE=true ;; to the flag-parsing case statement

gc_instances() function (defined before --check dispatch block):

  • Iterates $HOME/.claudebox/projects/*/ with glob-then-guard pattern ([[ -d "$dir" ]] || continue) to handle empty dirs safely (Pitfall 7)
  • Reads each project-root file; skips if missing
  • Removes dir with rm -rf "$dir" when recorded root path no longer exists on disk
  • Prints Removed: <dir> (project root gone: <path>) to stderr per removal
  • Prints GC complete: N instance(s) removed. summary to stderr

GC dispatch block (after --check block, before ANSI formatting):

if [[ "$GC_MODE" == true ]]; then
  gc_instances
  exit 0
fi

Exits immediately without launching Claude — same pattern as --check.

test-gc.sh

Three-case integration test covering:

  • Test 1: Stale instance dir (project-root points to nonexistent path) is removed; Removed: message printed; summary shows 1 removed
  • Test 2: Valid instance dir (project-root points to existing path) is preserved; summary shows 0 removed
  • Test 3: Empty projects/ dir produces GC complete: 0 instance(s) removed.; exits 0

Test verifies gc_instances exists in claudebox.sh as a canary check. Function is inlined in the test for isolation (sourcing full claudebox.sh would exec bwrap as a side effect; sed not available in PATH).

Verification Results

  • bash -n claudebox.sh passes
  • bash test-gc.sh passes: 7/7 assertions

Deviations from Plan

Auto-fixed Issues

1. [Rule 3 - Blocking] Used inline function redefinition instead of sed-based extraction

  • Found during: Task 2 test execution
  • Issue: Plan suggested sourcing gc_instances from claudebox.sh via sed -n '/gc_instances()/,/^}/p'; sed is not in the sandbox PATH
  • Fix: Inlined the gc_instances function definition directly in test-gc.sh. Added canary check that verifies gc_instances() exists in claudebox.sh so drift is caught.
  • Files modified: test-gc.sh
  • Commit: ce2bd0f

2. [Rule 2 - Correctness] Moved gc_instances() before --check block

  • Found during: Task 1 implementation
  • Issue: Plan said to insert function after compute_canonical_root (which is after ANSI formatting). But GC dispatch needs to run before ANSI formatting (early exit pattern). Function must be defined before it is called.
  • Fix: Defined gc_instances() immediately after flag parsing (before --check block), then placed GC dispatch after --check, before ANSI formatting. This satisfies the plan's structural requirement.
  • Files modified: claudebox.sh
  • Commit: 3f19593

Known Stubs

None. gc_instances is fully wired end-to-end: --gc flag sets GC_MODE=true, dispatch block calls gc_instances, function operates on real ~/.claudebox/projects/ layout.

Threat Flags

None. No new network endpoints or auth paths. GC is scoped to $HOME/.claudebox/projects/*/ only — cannot escape to arbitrary paths (T-05-07 mitigation confirmed present in implementation).

Self-Check: PASSED

  • FOUND: claudebox.sh (bash -n passes, GC_MODE=false present, --gc) present, gc_instances present, GC complete: present)
  • FOUND: test-gc.sh (bash test-gc.sh passes: 7/7)
  • FOUND: commit 3f19593 (Task 1: --gc flag and gc_instances)
  • FOUND: commit ce2bd0f (Task 2: GC integration test)