# Tier 2 Sandbox File Leak Prevention — Spec **Track:** `tier2_leak_prevention_20260620` **Created:** 2026-06-20 **Type:** fix (recovery + defense-in-depth) **Scope:** 5 new files, 1 modified file, 4 commits ## Background On 2026-06-19, commit `00e5a3f2` ("chore(env): pre-existing tier2 setup files") was pushed to `origin/master`. The commit contained 9 file changes: | Status | File | Notes | |--------|------|-------| | ADDED | `.opencode/agents/tier2-autonomous.md` | tier-2 SANDBOX agent (canonical source: `conductor/tier2/agents/tier2-autonomous.md`) | | ADDED | `.opencode/commands/tier-2-auto-execute.md` | tier-2 SANDBOX command (canonical source: `conductor/tier2/commands/tier-2-auto-execute.md`) | | MODIFIED | `opencode.json` | tier-2 sandbox overrode MCP path → `manual_slop_tier2`, default_agent → `tier2-autonomous`, model → `minimax-coding-plan/MiniMax-M3` | | MODIFIED | `mcp_paths.toml` | tier-2 sandbox cleared `extra_dirs` to `[]` | | MODIFIED | `project_history.toml` | timestamp update only (out of scope) | | ADDED | `scripts/tier2/artifacts/.../*.py` | 4 throwaway scripts (out of scope; legitimately tier-2 working artifacts) | The commit message ("pre-existing tier2 setup files") was misleading. The actual root cause: `setup_tier2_clone.ps1` legitimately modifies these files **in the clone** (`C:\projects\manual_slop_tier2\`), but the modifications leaked into the **main repo** via an accidental `git add .` in the tier-2 clone. The canonical sources live at `conductor/tier2/*` (per `setup_tier2_clone.ps1:48-49`); the main repo should NEVER see the sandbox's local config drift. ## What the user asked for 1. **Selective revert** of the offending files: `./opencode/*`, `mcp_paths.toml`, `opencode.json`. Leave the 4 throwaway scripts and `project_history.toml` timestamp at HEAD per the user's explicit list. 2. **A way to make sure tier-2 autonomous never commits those files** — explicitly NOT via gitignore. ## Design ### Layer 1 (existing): OpenCode permission system The tier-2-autonomous agent profile denies direct edits to the forbidden files. This was already in place but the deny rules didn't cover the auto-modifications done by `setup_tier2_clone.ps1` (the script itself writes the files, not the agent directly). ### Layer 2 (this track): pre-commit hook at the commit boundary `conductor/tier2/githooks/pre-commit`: - Reads `conductor/tier2/githooks/forbidden-files.txt` (substring patterns, one per line) - For each staged file, checks if any pattern is a substring of the path - Auto-unstages matching files via `git rm --cached --force` - Always exits 0 (removes the leak rather than blocking the commit, since tier-2 cannot run `git restore --staged` per the sandbox permission rules) - Hook source lives at `conductor/tier2/githooks/pre-commit`; config lives alongside as `conductor/tier2/githooks/forbidden-files.txt` ### Layer 3 (this track): working-tree audit `scripts/audit_tier2_leaks.py`: - Default mode (informational, exit 0): scans working tree for forbidden files - `--strict` mode (CI gate, exit 1 if leaks): catches anything the hook missed (manual edits, ops mistakes) - `--json` mode: machine-readable output for CI integration - Skips `tests/`, `conductor/`, `node_modules/`, `.git/`, etc. - Reports only `untracked` and `modified` files (tracked-and-clean files are legitimate) ### Hook installation `scripts/tier2/setup_tier2_clone.ps1` step 4 (Install git hooks) is updated to copy the new `pre-commit` hook into the clone's `.git/hooks/` directory alongside the existing `pre-push` and `post-checkout` hooks. The forbidden-files.txt config is already committed to the clone (as part of the canonical `conductor/tier2/*` source), so the hook can find it via the project root. ## Forbidden patterns (substring matches) ``` .opencode/agents/tier2-autonomous # sandbox agent, NOT the interactive tier2-tech-lead .opencode/commands/tier-2-auto-execute # sandbox slash command opencode.json # MCP path / default_agent / model override mcp_paths.toml # extra_dirs cleared in clone ``` Patterns are SPECIFIC (not prefix-based) so they do not match the legitimate interactive tier-2 tech-lead prompt at `.opencode/agents/tier2-tech-lead.md`. ## Tests - `tests/test_tier2_pre_commit_hook.py` (12 tests): pre-commit hook behavior - `tests/test_audit_tier2_leaks.py` (13 tests): audit script behavior All 25 tests pass. ## Files changed | Status | File | |--------|------| | NEW | `conductor/tier2/githooks/pre-commit` | | NEW | `conductor/tier2/githooks/forbidden-files.txt` | | NEW | `scripts/audit_tier2_leaks.py` | | NEW | `tests/test_tier2_pre_commit_hook.py` | | NEW | `tests/test_audit_tier2_leaks.py` | | MODIFIED | `scripts/tier2/setup_tier2_clone.ps1` | ## Out of scope - Wiring `audit_tier2_leaks.py --strict` into CI (deferred to a follow-up track) - Rebasing stale tier-2 branches on the new master tip (user action required; see `TRACK_COMPLETION_tier2_leak_prevention_20260620.md` §Next Steps) - The 4 throwaway scripts in `scripts/tier2/artifacts/.../*.py` (legitimate tier-2 working artifacts per the tier-2 convention) - The `project_history.toml` timestamp update (harmless side effect)