import InfoBox from '../components/InfoBox.astro';
import PullQuote from '../components/PullQuote.astro';

Giving an agent more autonomy starts with deciding where that autonomy ends. The project now opens inside a devcontainer with the application, PostgreSQL, Git tooling, browser automation, and the normal verification commands ready to use. The goal is not merely that every developer gets the same packages. It is that an agent can investigate, implement, test, and inspect the result without quietly reaching into production or inheriting the whole host machine.

## Local means one command

The database runs beside the application, migrations apply on startup, and the development server needs one command. That sounds like documentation, but it became part of the runtime boundary almost immediately. An agent followed the old instructions, tried the Railway path, hit the network restrictions, and reported an apparent database failure even though the local database was healthy. The configuration did not need a fix; the order of the instructions did. The devcontainer path now comes first, and the external alternatives are explicitly marked as external.

<InfoBox title="Three boundaries, three different jobs">
  Application data stays local. Outbound network access defaults to denied and opens only for
  approved development services. Git authentication is scoped to this repository, while commit
  signing uses a separate identity. Each boundary can change without broadening the other two.
</InfoBox>

## The firewall has a lifecycle too

The first network policy worked at startup and then failed later because its refresh process rebuilt only part of the approved rules. A second failure came from installing operating-system tools after the restrictions were already active. The fixes were different: refresh the complete policy rather than a subset, and bake required tools into the image before the container starts. This is the useful part of a sandbox being executable configuration. A boundary that only exists in a setup document cannot reveal that its own maintenance loop deletes half its state.

<PullQuote>The safe environment has to support the work, or the work will find a way around it.</PullQuote>

## Identity without the host account

Git needed the same separation. Forwarding a host-wide credential was convenient but too broad and too dependent on one operating system. The chosen setup keeps repository-scoped authentication inside persistent container storage and uses a different key for signing commits. The author performs the account-level trust decision; the agent gets the narrow ability to fetch, push, and produce verifiable commits. Rebuilding the development image does not silently create a new identity, and rotating one purpose does not disturb the other.

## The browser crosses the boundary

The host browser initially could not reach a server that was healthy inside the container. A stale process had let the server drift to another port, and the firewall saw forwarded host traffic differently from traffic on the container network. The result was a connection that appeared open but carried no page. The server now fails loudly instead of moving, and the host bridge is treated as an explicit local boundary. Playwright and video conversion are baked into the environment as well, so the [scripted gameplay recording](/posts/gameplay-recording-and-icons#script-the-demonstration-not-the-result) runs headlessly in the same sandbox as the tests.

<InfoBox title="The game kept moving during the environment work">
  Daily and duel both gained a shared game log with separate chips for submitted words, spawned
  rewards, and collected fruit. The daily reset also moved to each player's local midnight. These
  changes ride in the same range, but the larger result is that the container can now build, test,
  run, and visually inspect them without a production dependency.
</InfoBox>

## Enough access to finish the loop

By the end of the four-day setup, the agent can start from a fresh clone, run the database and application, use the browser, execute the checks, commit, and push from one constrained workspace. The remaining work is not to make the sandbox disappear. It is to keep its rules close to the tools that depend on them, so a new capability arrives with an explicit boundary instead of another piece of ambient access.