# Learnitive sandbox home/cache + sync hotfix validation — 2026-09-05

## Observed staging failures

- Dependency restore attempted to read `/home/developer/.bash_profile` and failed with `Permission denied`.
- npm attempted to create `/home/developer/.npm/_cacache/tmp` and failed with `EACCES`, reporting root-owned cache files.
- Interactive Terminal printed `groups: cannot find name for group ID ...`, `.bashrc: Permission denied`, and `I have no name!`.
- The browser repeatedly requested `/environment/download?path=...` for unchanged project files.

## Root causes

1. Runtime home/cache state depended on the image home path and older container mounts. Existing containers could survive a deployment even when the tagged development image/runtime identity changed. Interactive Bash still read `.bashrc`.
2. `sandbox-project-sync.ts` downloaded local and remote bytes for every file before deciding whether a file changed. The editor repeated that reconciliation continuously and allowed overlapping runs.

## Fix contract

- Authenticated sandbox `HOME=/workspace/.learnitive/home`.
- Package caches are under `/workspace/.learnitive/cache/*` and therefore count against the per-user sandbox quota.
- Sandbox runtime contract is `workspace-home-v3`. Container reuse requires the exact current Docker image ID.
- Container startup validates numeric UID/GID, `developer` user/group resolution and home/npm-cache writability.
- Terminal uses `/bin/bash --noprofile --norc -i`. Automated commands already use non-profile/non-rc shells and now receive the same explicit home/cache environment.
- Sync uses metadata snapshots, post-write mtime refresh, a module-level in-flight lock, foreground-only polling, and remote content fetches only when required.

## Local verification

- `node --test server/*.node.test.mjs scripts/learnitive-*.node.test.mjs`: 366/366 PASS.
- `node --experimental-strip-types --test packages/js-lib/project-runtime/src/index.node.test.mjs`: 10/10 PASS.
- `node scripts/learnitive-capability-audit.mjs`: 40/40 PASS, zero blockers.
- pnpm frozen-lock sync PASS: 69 importers, 1581 package records, 1583 snapshots, 1171 reachable lock snapshots.
- Trusted-server runtime manifest PASS: 9 imports.
- R12 release audit PASS.
- Learnitive branding/provenance audits PASS.
- `node --check learnitive-services/console-gateway/server.js` PASS.
- `bash -n deploy/learnitive/install-staging.sh` PASS.

## Required staging acceptance

After deploying this source, open any authenticated project and verify:

1. The environment is recreated once if it was created under an older runtime contract/image.
2. Terminal prompt resolves the `developer` account; `id -un` and `id -gn` both return `developer`.
3. `echo $HOME` returns `/workspace/.learnitive/home`.
4. `npm config get cache` returns `/workspace/.learnitive/cache/npm`.
5. `touch "$HOME/test" "$NPM_CONFIG_CACHE/test"` succeeds without sudo.
6. `npm install`/dependency restore succeeds without `.bash_profile`, `.bashrc` or EACCES cache errors.
7. Network tools show periodic environment/list checks only; unchanged project files are not repeatedly fetched through `/environment/download`.
8. Editing a file locally uploads it once; editing a file in Terminal downloads that changed file once to local storage.
