Files
2026-07-05 15:53:28 -04:00

5.1 KiB

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)