Key Geo state on the pair so two simulations can coexist
What
Geo state moves from a single geo.json to one file per pair, geo up refuses
to build over a cluster that already exists, and every created VM carries an
owner label.
Why
Every other base keys its state on the instance name, so two simulations run side by side on one machine. The Geo archetype was the exception, and the failure it produces costs money:
~/.gitlab-simulation/geo.jsonheld the only record of which two VMs a cluster owned. A secondgeo upoverwrote it, so the first cluster'sgeo downcould no longer find its sites and twoc2d-standard-8VMs kept running with nothing tracking them.geo verifyandgeo statusreported on whichever pair was written last, not the pair the operator meant, and no output revealed the substitution.STATE_DIRderives from$HOMEwith no override, so the only isolation available was fakingHOME, which breaks gcloud's own config path.
A created VM carried purpose, base and ephemeral, all identical across
every simulation on the machine. Attribution existed only as a convention in the
instance name, so an operator reading instances list could not tell which VM
was safe to tear down and which one another session was mid-experiment on.
What changed
| Change | Effect |
|---|---|
SIM_GEO_PAIR=<name> |
State goes to geo-<name>.json. Unset keeps geo.json, so a cluster built before this stays addressable by the commands that built it. |
geo up guard |
Refuses when the state file exists or either instance name is taken, instead of overwriting. |
geo_require_state |
Names the other pairs holding state, so a command run against the wrong pair says so. |
geo list |
Reports every pair on the machine. |
SIM_OWNER |
Free-text owner label on created VMs, sanitized to GCE's label rules. Defaults to unattributed. |
The pair name is validated because it becomes a filename component.
Testing
just ci and just sims-check pass. The SKILL.md description is unchanged,
so no fire-test re-record is required.
I exercised it offline against a real pre-existing pair on the machine:
geo listreports the unnamed pair.geo upon that pair refuses, and names both the teardown and the isolation option.geo statusunder a newSIM_GEO_PAIRreports no state and names the pair that has some.SIM_GEO_PAIR=../evilis rejected.owner_labelmaps empty tounattributed, lowercases and stripsAccount / retroshaped input, and truncates at 63 characters.
I did not run a live geo up. It provisions two VMs and costs money, so it runs
by an operator rather than in CI, per this repo's CI note.
Backwards compatibility
An existing cluster is untouched. With SIM_GEO_PAIR unset the state path is
byte-identical to before, which matters because a session can be mid-experiment
when this merges.