Follow-up to the 'NEVER USE APPDATA' directive. The agent kept
trying to use \C:\Users\Ed\AppData\Local\Temp / \C:\Users\Ed\AppData\Local\Temp / %TEMP% / %TMP% — the previous
deny rule (*AppData\\\\* and *AppData\\Local\\Temp\\*) only matched
the literal expanded path, not the env-var form. The agent would
self-block based on its own interpretation of the rule, but it still
TRIED before self-blocking (the 'fucking tired of it fucking with
AppData' complaint).
Fix:
1. opencode.json.fragment: add bash deny patterns matched against
the LITERAL command string (before shell expansion):
*\C:\Users\Ed\AppData\Local\Temp* - PowerShell env var (the form the agent tried)
*\C:\Users\Ed\AppData\Local\Temp* - PowerShell env var
*%TEMP%* - cmd env var
*%TMP%* - cmd env var
*GetTempPath* - .NET API
*gettempdir* - Python tempfile module
*mkstemp* - Python tempfile.mkstemp
Applied to BOTH the top-level permission.bash (for default agents)
and the tier2-autonomous agent's permission.bash.
2. conductor/tier2/agents/tier2-autonomous.md: rewrite the Temp
files section to explicitly list ALL forbidden literals and
reiterate 'every one of those literal command strings is denied
at the bash level'. Updated changelog note.
3. conductor/tier2/commands/tier-2-auto-execute.md: same.
4. tests/test_tier2_slash_command_spec.py: extend
test_config_fragment_denies_temp_writes to assert each of the 9
patterns in both the top-level and the agent's bash.
Verified: re-ran setup against the live clone. tier2 agent's bash
has 13 deny patterns (9 AppData/temp + 4 git). 37/37 default-on
tests pass.
Note: the user's prior commit (fix(tier2): remove AppData allow
rules from OpenCode permission JSON) already removed the AppData
allow rules from read/write and added the broader *AppData\\\\*
deny rule. This commit layers on top of that with the env-var-form
deny patterns.
Same reconciliation as the agent prompt (previous commit). Three
paths in conductor/tier2/commands/tier-2-auto-execute.md now match
the actual code defaults:
- Pre-flight step 3: scripts/tier2/state/ -> tests/artifacts/tier2_state/
- Protocol step 3: scripts/tier2/state/ -> tests/artifacts/tier2_state/
- 'Temp files' convention: scripts/tier2/state/ and scripts/tier2/failures/
-> tests/artifacts/tier2_state/ and tests/artifacts/tier2_failures/
The user must re-bootstrap the Tier 2 clone to pick up the fixed
template (pwsh -File scripts/tier2/setup_tier2_clone.ps1).
Refs: conductor/tracks/tier2_no_appdata_20260618 (post-merge followup)
Four changes to conductor/tier2/commands/tier-2-auto-execute.md:
1. Pre-flight step 3: previous-run check now references
scripts/tier2/state/<track-name>/state.json (not <app-data>).
2. Protocol step 3: failcount state init path is
scripts/tier2/state/<track-name>/state.json (not <app-data>).
3. Conventions / Temp files: rewritten to point at inside-clone paths
and say 'NEVER USE APPDATA'. Documents the 2026-06-18 reversal.
4. Hard Bans footer: filesystem boundary now says 'Tier 2 clone only'
(no +AppData exception) and includes the NEVER USE APPDATA rule.
Refs: conductor/tracks/tier2_no_appdata_20260618
The Tier 2 agent wrote audit_exception_handling.py output to
C:\\Users\\Ed\\AppData\\Local\\Temp\\audit_initial.json via shell
redirection. This is OUTSIDE the sandbox allowlist (which is
C:\\projects\\manual_slop_tier2 + C:\\Users\\Ed\\AppData\\Local\\
manual_slop\\tier2 + C:\\Users\\Ed\\AppData\\Local\\manual_slop\\
tier2_failures). The OpenCode session-level guard fires the 'ask'
prompt for paths outside the project root, which has no answer in an
autonomous session, so ops halted mid-track.
Fix (3 layers):
1. opencode.json.fragment: add bash deny rule
'*AppData\\Local\\Temp\\*': 'deny' to BOTH the top-level
permission.bash (for default agents) and the tier2-autonomous
agent's permission.bash. The agent physically cannot run shell
commands that target the global Temp dir.
2. conductor/tier2/agents/tier2-autonomous.md: add 'Temp files'
convention telling the agent to use
C:\\Users\\Ed\\AppData\\Local\\manual_slop\\tier2\\ for scratch
/ audit-output / intermediate files, NOT %TEMP%.
3. conductor/tier2/commands/tier-2-auto-execute.md: same convention
in the slash command so the agent sees it at slash-command time.
Tests (default-on):
- test_agent_denies_temp_writes: agent prompt has the Temp deny in
frontmatter bash + the app-data dir note
- test_config_fragment_denies_temp_writes: both top-level and agent
bash have the deny rule
All 16 tier 2 slash command tests pass.
Also: cleaned up the leaked audit_initial.json + audit.json +
audit_after*.json from %TEMP% (they were leftovers from a prior
run). Re-ran setup against the live clone; opencode.json's agent
bash and top-level bash both have the deny rule.
User feedback from the first sandbox run (send_result_to_send_20260616,
2026-06-17) identified 6 conventions Tier 2 must follow. Update the agent
prompt template, slash command template, user guide, and workflow doc:
1. Test runner: ALWAYS use 'uv run python scripts/run_tests_batched.py'
(NOT 'uv run pytest'). The batched runner provides tier filtering,
parallelization (xdist), and a summary table that direct pytest lacks.
2. Default branch: this repo uses 'master', not 'main'. The Tier 2 slash
command now does 'git fetch origin master' (was 'origin main').
3. Line endings: preserve existing. This repo has a mix of CRLF and LF;
a repo-wide LF standardization is a future track.
4. Throw-away scripts: write to 'scripts/tier2/artifacts/<track>/', NOT
the base 'scripts/tier2/' directory. The base is reserved for
production code; throw-away scripts are kept for archival but
isolated per-track.
5. End-of-track report: write 'docs/reports/TRACK_COMPLETION_<track>.md'
and update 'state.toml' to 'status=completed'. The user reads this
to decide merge. Previously this was implicit; now it's explicit.
6. Run-time expectation: tracks are 1-4 hours. If context runs out, Tier
2 notes progress to disk and continues. The --resume flag picks up
from the last completed task.
Also updated the user guide with a 'Conventions' section and a
troubleshooting entry for the resume flow. The verify-the-sandbox
checklist now uses 'origin master' instead of 'origin main'.