Commit Graph

1 Commits

Author SHA1 Message Date
Eugene Eisenstein 846ecd19f6 feat(sandbox): committed ephemeral Honcho sandbox with one-command reset
A local Honcho that comes up already seeded and resets to that exact state in
under a second, so harness integration testing stops depending on machine state.

`docker-compose.yml.example` gave the topology but was an example, unseeded, and
had no teardown path, so every harness change was verified against whatever state
a given laptop was in. The blocker to fixing that was the deriver's provider call,
which made a sandbox neither free nor deterministic; src/mock_provider removes it.

Reset restores a Postgres template database rather than re-deriving: `seed`
snapshots the finished state, `reset` drops the live database and recreates it
from that snapshot, then flushes Redis. Nothing is stopped or restarted --
DROP DATABASE ... WITH (FORCE) evicts the connection pools and both services
reconnect on their own. Measured 0.86s in mock mode, 1.29s in real mode against
a 361s seed.

Two provider modes, both first class. Mock is the default: deterministic, free,
no egress. Real points the same stack at a configured provider, reading
credentials from one gitignored file rather than ambient environment. The
difference matters and is documented: mock embeddings are hash-derived and carry
no semantic similarity, so vector-recall assertions are impossible there, and
mock conclusions come out explicit-only. On the committed fixture, mock yields 4
synthetic explicit conclusions and real yields 22 across all three levels.

The sandbox is configured only by what Compose injects. PYTHON_DOTENV_DISABLED
and HONCHO_CONFIG_TOML_DISABLED are both set because src/config.py calls
load_dotenv(override=True) at import and the Dockerfile bakes any local
config.toml into the image; without them a developer's own provider config wins
silently. Deriver scheduling is pinned for the same reason: on stock settings a
sandbox seeded with a handful of messages produces zero conclusions and gives no
indication why, because work units wait for a 512-token batch or 30 minutes and
startup jitter delays the first poll by up to 30s.

Snapshots can go stale, so each carries a fingerprint -- Alembic revision,
fixture hash, provider mode -- and reset refuses on a mismatch instead of
restoring a state that predates a migration. Templates are per-mode, so both can
coexist.

Note: the pinned digest in sandbox/image.env predates the mock provider, so
`--build` is required until that lands and a new image is published. sandbox.sh
detects this and says so rather than crash-looping on a missing module.
2026-09-03 17:29:44 -04:00