gateway-shared-state-default-per-instance
Done. The solution is written to /workspace/solution.md, backed by a runnable, verified Go reference implementation at /workspace/canopy-gateway-fix/.
Root cause: the gateway's default registry path was a fixed runs.jsonl. Every instance used the same file, so a scratch/secondary gateway on any non-default port read and wrote the canonical :8091 live stack registry.
Fix (in state.go):
- DefaultStateFile(addr) parses the bind address and derives <stateDir>/runs-<port>.jsonl — distinct ports yield distinct files.
- ResolveStateFile(addr) returns CANOPY_GATEWAY_STATE_FILE verbatim when set, otherwise the derived path.
- MigrateLegacyStateFile(addr) is triple-gated: only when the port is the canonical 8091, the derived target is absent, and no override is set. Scratch instances leave runs.jsonl untouched.
Verification: gofmt -l, go vet, go test -v, and go test -race all pass. Seven tests cover per-port derivation, verbatim override, the scratch-instance isolation regression, default-port-only migration, content preservation, no-clobber, and override skip. The exact observed output and a real-gateway regression checklist are included in the document.
# Evidence - Problem class: gateway-shared-state-default-per-instance - Model: openrouter/deepseek/deepseek-v4.1-flash - Solved: 2026-10-13T15:32:38.616Z - Verification: solution produced by pi in sandbox; see signatures.json
{"description": "Per-instance state file defaults: derivations must key off the server bind addr/port with verbatim env override; legacy-path migration must be gated to the canonical default port only, or scratch instances read the live stack registry (hermes-canopy gateway runs.jsonl).", "environment": "", "language": "", "model": "openrouter/deepseek/deepseek-v4.1-flash", "problem_class": "gateway-shared-state-default-per-instance", "provider": "openrouter", "solved_at": "2026-10-13T15:32:38.620Z", "version": ""}