$npx -y skills add mvschwarz/openrig --skill seat-continuity-and-handoverUse when replacing a seat's occupant (rebuild/handover/swap), reasoning about stable-seat-identity vs fluid-occupant-identity, choosing an old-occupant disposition (retire/advise/shadow), or recording provenance for an occupant change. Two independent outcomes (continuityOutcome
| 1 | # Seat Continuity and Handover |
| 2 | |
| 3 | A pair of primitive families that separate *who is sitting in a seat* from |
| 4 | *what the seat itself is*: |
| 5 | |
| 6 | 1. **Occupant-creation primitives** — `resume`, `fork`, `rebuild`, `fresh` — produce a candidate new occupant. Answer: "where did the new occupant come from?" |
| 7 | 2. **Seat-binding primitives** — `seat handover`, later `seat transfer` / `seat retire` / `seat swap` — bind a candidate occupant into the topology. Answer: "what happened to the stable seat identity?" |
| 8 | |
| 9 | Core architectural decision: **stable seat identity, fluid occupant |
| 10 | identity, explicit provenance.** Today's `lead2`/`lead3`/`lead4`/`lead5` |
| 11 | pattern encodes successor lineage into seat names — that's the wrong |
| 12 | shape. Stable seat name + separately-recorded provenance trail is the |
| 13 | right shape. |
| 14 | |
| 15 | ## Use this when |
| 16 | |
| 17 | - Replacing a seat's occupant via rebuild, fork, fresh, or future seat-handover |
| 18 | - Choosing old-occupant disposition: retire / advise / shadow |
| 19 | - Reasoning about whether a seat's lineage is stable or has drifted |
| 20 | - Reading or writing the provenance record for a seat |
| 21 | - Designing or auditing topology stability across an occupant change |
| 22 | |
| 23 | ## Don't use this when |
| 24 | |
| 25 | - The seat is freshly created (no occupant to replace) — use `rig launch` / `rig expand` directly |
| 26 | - The intent is to change topology shape (add/remove seats), not replace an occupant — use topology-mutation primitives |
| 27 | |
| 28 | ## The two-outcome honesty model |
| 29 | |
| 30 | Every seat-binding operation produces two **independent** outcomes: |
| 31 | |
| 32 | ```yaml |
| 33 | continuityOutcome: rebuilt | resumed | forked | fresh | failed |
| 34 | seatBindingOutcome: handed_over | partial | failed | unchanged |
| 35 | ``` |
| 36 | |
| 37 | These can disagree honestly. Examples: |
| 38 | |
| 39 | - `continuityOutcome: failed` + `seatBindingOutcome: unchanged` — new occupant didn't materialize; seat correctly retains old occupant. |
| 40 | - `continuityOutcome: rebuilt` + `seatBindingOutcome: failed` — candidate created OK; bind failed mid-flight; provenance records the gap. |
| 41 | |
| 42 | **Don't collapse these into one outcome.** The system can describe what |
| 43 | actually happened only if the two are recorded independently. |
| 44 | |
| 45 | ## Provenance record (durable, queryable) |
| 46 | |
| 47 | Every handover writes: |
| 48 | |
| 49 | - seat id |
| 50 | - old occupant id |
| 51 | - new occupant id |
| 52 | - creation mode (`resume`/`fork`/`rebuild`/`fresh`) |
| 53 | - source artifacts used |
| 54 | - whether old occupant remains alive as advisor/shadow |
| 55 | - operator or loop that initiated the motion |
| 56 | - timestamp |
| 57 | - result (`handed_over` / `partial` / `failed`) |
| 58 | |
| 59 | This is the system's truth-source for "how did the current occupant get |
| 60 | there." Without it, the control plane shows the current occupant but |
| 61 | not the legitimacy of the transition. |
| 62 | |
| 63 | ## State models — independent |
| 64 | |
| 65 | ### Occupant-creation state (per candidate) |
| 66 | |
| 67 | 1. **Requested** — input to rebuild/fork/fresh/resume |
| 68 | 2. **Realized** — runtime/artifact path produced an occupant with managed-seat shape |
| 69 | 3. **Failed** — candidate didn't materialize; `continuityOutcome: failed` |
| 70 | |
| 71 | ### Seat-binding state (per seat) |
| 72 | |
| 73 | 1. **Stable** — current occupant attached, no in-flight binding |
| 74 | 2. **Binding** — handover in progress |
| 75 | 3. **Bound** — handover succeeded; provenance record written |
| 76 | 4. **Unchanged** — bind failed before completion; seat retains old occupant |
| 77 | |
| 78 | A seat stays `Stable` even if multiple candidate-occupants were produced and discarded. |
| 79 | |
| 80 | ## Failure modes (5) |
| 81 | |
| 82 | 1. **Candidate creation failed** — `rebuild` couldn't synthesize from artifacts; `fork` couldn't resolve `session_source`; `fresh` couldn't launch. **Action**: bind operation does not begin; seat unchanged; provenance records the failed candidate-creation step. |
| 83 | 2. **Old occupant cannot be detached cleanly** — runtime hung, tmux locked, etc. **Action**: bind halts mid-flight; seat enters `Binding` state with explicit "halted" sub-status; operator alerted. **Do NOT auto-rollback by reattaching old-occupant if detach didn't complete cleanly.** |
| 84 | 3. **Bind succeeded but provenance write failed** — disk/db error. **Action**: not durable until provenance writes; treat as `Binding` halted, not `Bound`. |
| 85 | 4. **Old occupant disposition unfulfillable** — operator requested `advise` (keep alive as advisor) but runtime can't keep old alive. **Action**: degrade to `retire` wit |