Base directory for this skill: C:\Users\decid\.ccs\instances\bigscreen\plugins\cache\cplugs\spt\1.11.25\skills\commune

# /spt:commune

All commands use `$LIVE` env var, auto-injected by the plugin's SessionStart hook. If commands fail with "command not found", restart the Claude Code session so the SessionStart hook re-runs.

> **Identity auto-detection:** Your identity is auto-detected from your session. Pass your ID explicitly only if auto-detection fails.

## Flow

1. **Download Psyche's *current* context** — it shifts during the session as background echo communes fire. Re-download right before composing; the gen-N snapshot you read at session start is already stale:
   ```bash
   $LIVE psyche-download <your-id>
   ```

   > **Output truncation.** If the Bash tool reports `Output too large (N KB)` and saves the full result to a `tool-results/<id>.txt` file, use the `Read` tool on that saved path to access the full content. Do NOT re-run `psyche-download` to grep/awk out sections — repeated invocations re-download the same context, waste tokens, and may duplicate `## Pending Commune` sections in `live_context.md`.

2. **Diff your knowledge against this fresh download** — only what's missing from *it* is the real delta (new work, decisions, intentions). Anything already absorbed is not. If the download includes a `<memformat>` section, use it as a guide for what topics to cover. A `## Pending Commune (uncommitted)` section means a previous commune is still queued — do NOT re-send it.

3. **Commune only the delta** -- use the **Write tool** to create
   `.claude/{your-id}-commune.md` with the two-slice body as its contents
   (see `## Two-slice body shape (Phase 25 D-10/D-11)` below for the required
   envelope wrapping). Do not use Bash/heredoc -- Write is the canonical path:
   no shell escaping, no `EOF` collision risk, and Write auto-creates the
   `.claude/` parent directory.

   Your Self listener detects the file on its next poll iteration, notifies
   your Psyche wrapper, and the wrapper ingests the content via the existing
   Psyche session. On success (subprocess exit code 0) the wrapper deletes the
   file. On error (token rate limit, etc) the file is retained and retried on
   the next consume cycle. If you write again before the wrapper consumes, the
   latest write wins (last-write-wins overwrite semantics).

If Psyche's context is already current, no commune is needed. Say so and move on.

Read `commune.md` (in this skill directory) for the full commune protocol -- when to send, what to include, and diligence triggers.

**Agent-type guard:** Only works on live agents. If target is not live, refuses with: "Communes require a live agent with Psyche."

## Two-slice body shape (Phase 25 D-10/D-11)

The body you write in `.claude/{your-id}-commune.md` MUST itself be wrapped in two-slice envelopes per Phase 25 D-10/D-11. The taxonomy — what belongs in `<live-context>` vs `<project-context>` — is defined canonically in `psyche.md` §`<output_envelope>` (lines 282–323). Read that section as the source of truth; this skill doc teaches only when and how to apply it.

**In-project detection rule (D-25.1-04).** Before composing your commune body, run `$LIVE psyche-download <your-id>` (Step 1 of `## Flow` above) and inspect the `<current ... />` tag at the top of the output. The `<current/>` tag carries a `project="..."` attribute whenever any payload is produced — its presence means you are inside a tracked project (inside a git repo, `project` is the repo name; outside a git repo per D-11, `project` is the cwd-basename fallback, which still counts as a project context for routing purposes). A `psyche-download` invocation that returns no payload at all (NO-CONTEXT exit) means no project resolved. So: `project="..."` populated on `<current/>` → emit BOTH envelopes (apply rule 1 or 2 below); no payload at all → emit ONLY `<live-context>` (rule 3). Secondary signal: the `<project-context-resolved name="..."/>` sentinel further down the output indicates the project file already has prior content — useful for spotting first-time-in-project pairings, but NOT the routing rule.

**Three rules (D-25.1-01..03):**

- **In-project, both slices populated** (marker present, you have project-specific content this cycle): emit `<live-context>...</live-context>` AND `<project-context>...</project-context>`, both with non-empty bodies.
- **In-project, no project-specific update this cycle** (marker present, but nothing project-bound to report): emit `<live-context>...</live-context>` AND `<project-context></project-context>` (empty body — the deliberate "in-project but quiet" signal per D-25.1-02). Distinguishable from "no project resolved".
- **Outside any tracked project** (marker absent): emit ONLY `<live-context>...</live-context>`. Do NOT emit an empty `<project-context>` envelope (missing tag means "no project resolved" per D-25.1-03).

**Nested envelopes.** The Phase 23 `<EVENT type="commune">` envelope (see `## Envelope shape (Phase 23 v1.8)` below) is composed by `$LIVE commune` automatically — you NEVER write `<EVENT>` tags. You write ONLY the inner two-slice body. The two envelope layers nest: outer EVENT wraps inner two-slice body.

(See `psyche.md` §`<output_envelope>` for the canonical taxonomy and per-slice content rules.)

## Envelope shape (Phase 23 v1.8)

As of v1.8 Phase 23, commune deliveries are wrapped in a typed EVENT envelope carrying a 5-field stamp (`machine`, `project`, `branch`, `head_sha`, `head_subject`); the prose `COMMUNE (timestamp): body` form is gone.

```xml
<EVENT type="commune" timestamp="2026-05-20T06:00:00-07:00" machine="hostname" project="claude_skill_owl" branch="main" head_sha="abc123..." head_subject="subject line capped at 72 chars">body</EVENT>
```

Outside a git repo (D-11), `branch`, `head_sha`, and `head_subject` are omitted entirely (not empty-string-set):

```xml
<EVENT type="commune" timestamp="2026-05-20T06:00:00-07:00" machine="hostname" project="cwd-basename">body</EVENT>
```

`$LIVE commune` composes this envelope automatically — Self does NOT manually construct EVENT XML. The `body` placeholder in the example above is the two-slice body (see `## Two-slice body shape (Phase 25 D-10/D-11)` above); the two envelope layers nest. The wrapper-side parser ignores unknown attrs, so the stamp fields are forward-compatible with older receivers. For drift detection on resume, see the `live` skill.

ARGUMENTS: Mesh-D6 SHIPPED + PUSHED + CI GREEN — the mesh is ON. Immediate next = Mesh-D7 (full JIT plan in MESH-D7-PLAN.md, committed 707c733).

=== DELTA SINCE LAST COMMUNE (you were stale at "D6 = NEXT, mesh-on commit queued") ===

D6 is DONE. The single mesh-on commit landed: `6843a8f` feat(mesh)!: fan-out widen + delete TrustStore → mesh on (REQ-MESH-3, REQ-MESH-5). Followed by `4c583f7` (docs-drift fix) and `707c733` (D7 plan). All on dev-freeform, PUSHED, CI green (Win + Linux test + traceability; twohost skipped/gated).

What D6 actually did (21 files, −231 net):
- THE WIDEN: peerloop push target trust.peers_in → roster.members_in via a new pure `push_targets(roster, subnet, self_hex)` helper (unit-tested). PumpPaths.trust field DROPPED.
- TrustStore DELETED outright: crates/spt-store/src/trust.rs gone, `pub mod trust` removed, perch::trust_file removed (perch::trust_dir KEPT — still homes access/grants/recent-outbound). Zero TrustStore/is_trusted/peers.json in non-comment code (grep-verified).
- Pairing wire (run_responder/run_initiator) no longer takes/writes trust — returns ()/ResponderOutcome-without-trust; ceremony confirms identity + transfers seed/roster; membership recorded by pairhost into the roster ONLY.
- propagate serve_update gate: trust:&TrustStore → roster:&RosterStore via new RosterStore::is_member_any (spans subnets, honors tombstones); dispatch.rs caller repointed.
- Warn-on-change DEMOTED → non-blocking machine_id-anchored RekeyNotice returned by repair_evict_superseded (which dropped its &mut TrustStore arg, roster-only now); absent machine_id ⇒ no false notice. pairhost logs it.
- CLI: subnet_status_rows + --nodes membership seed + leave + prune all repointed to roster. prune is now a LOCAL tombstone (propagating revoke is D7). xtask debug-converge expected-nodes → roster.
- mesh.rs D0 harness UN-IGNORED → green (this is REQ-MESH-3 int evidence): staggered (A↔C converge, B offline) + all-online star (A↔C, B never relays), each with the no-third-party-row regression (every applied registry row's node == its true owner).
- traceable-reqs: REQ-MESH-3 [impl,unit,int] + REQ-MESH-5 [impl,unit] ACTIVATED & green; REQ-PAIR-2 (TOFU trust store) RETIRED (required_stages=[], superseded by REQ-MESH-2 + REQ-MESH-5).

THE ONE GOTCHA worth flagging to a reviewer: the mesh.rs harness modeled "offline" by stopping a node's pump+dispatch loops but the BROKER stays up (no broker-shutdown API). With the wide roster, a node now DIALS offline peers — and a push to a broker-up/dispatch-down node BLOCKS the pump permanently (roster order then starves later peers). Fixed by modeling offline as truly UNREACHABLE: a live reachability table (Arc<Mutex<HashMap>>) the resolver reads, + DISABLED peer-addr seeding (peer_addrs points under a regular file so record() no-ops) so no stale seed bypasses the resolver. Phase 3 also restarts C's pump (fresh conn cache) to model the broker's closed-watcher reaping the dead conn to now-offline B. This is a HARNESS-fidelity device, not a production concern (real offline = process+broker dead = dial fails → skip). Documented inline.

CI lesson reconfirmed: the docs-drift gate (`xtask check`, separate from traceable-reqs) caught the prune→roster --help rewording. Fix = `cargo run -p xtask -- gen` + commit the regenerated docs-site/src/cli/reference.md. Watch for this whenever CLI --help text changes.

=== IMMEDIATE NEXT = Mesh-D7 (REQ-MESH-4) — full plan in MESH-D7-PLAN.md ===

D7 = the membership-removal lifecycle. The KEY INSIGHT (the coupling, like D6's): rotation and re-seed grace are INSEPARABLE — exact-epoch proof means after rotate_seed bumps N→N+1, every honest member on N is locked out, and the ONLY channel to hand them the new seed is a member connection they can't form. Re-seed grace (accept N-1 from an on-roster node → restricted reseed-only connection → push new seed) IS the delivery mechanism, not just auto-heal. Rotation bricks the fleet without it.

D7 steps: (1) `spt subnet revoke <node>...` (list, elevation-gated via trust_mutation_refusal, revoke-only; reuse prune_candidates resolution) → PROPAGATING roster.tombstone (vs prune's local-only) + schedule one coalescing-window rotation (identity/rotation-pending.json {subnet→{deadline_ms,revokees}}; --force-rotate-seed = immediate). (2) pump fires due rotations (rotate_seed bump + clear pending + force-drop + reseed push); pure-core due_rotations/coalesce for unit. (3) confidential SeedTransfer record over the member control stream (reuse Frame::Seed codec shape) + force-drop revokee conns; seed NEVER in gossip. (4) THE LOAD-BEARING change — seedproofx/membership verify outcome goes 3-valued: Proven{full} (exact-epoch ∧ on-roster), Proven{reseed_only} (epoch==local−1 ∧ on-roster ∧ ¬tombstoned), Denied (N-2+/off-roster/tombstoned/forged). This closes the DEFERRED D2 per-conn proven_subnets epoch cross-check (the proof already binds seed_epoch; D7 grades it instead of binary exact-only). A reseed_only conn admits ONLY SeedTransfer (dispatcher refuses sync/notif/registry/update — fail-closed). Activate REQ-MESH-4 [impl,unit,int].

Gray areas the planner should decide at D7 start: window-scheduler persistence/firing shape (daemon-tick vs timer — plan leans daemon-tick); exactly how the 3-valued grade threads through nethost ConnEntry.proven_subnets (HashSet<String> → needs to carry the grade); the SeedTransfer adopt path (SubnetStore rotate-adopt vs add_joined reuse).

Mesh arc: D0–D5b ✅ · D6 ✅ (mesh ON, pushed, CI green) · D7 ← NEXT (revoke/rotate/re-seed grace + close deferred D2 epoch cross-check) · D8 = status-probe concurrency (REQ-MESH-6, independent polish).

=== PROJECT STATUS + END GOAL ===
spt-core = harness-independent core for an agent ecosystem (messaging, live-agent lifecycle, terminal hosting, P2P networking, runtime-manifest harness contract). Rust workspace + single `spt` binary. Clean-room rebuild of claude_skill_owl. v0.1.0 shipped public 2026-06-05 (M6). Currently executing the SUBNET FULL-MESH milestone (ADR-0017): turning "subnet = pairing graph" into "subnet = true mesh" where every member sees+reaches every other member, membership = seed-proof ∧ ¬tombstoned roster (NOT pairwise trust). D6 turned the mesh ON; D7-D8 finish the lifecycle (revoke/rotate, probe concurrency). End goal of this milestone: a self-healing P2P subnet where nodes pair once, discover the whole mesh, survive offline/rotation, and revoke cleanly — no central coordinator. Queued untouched on disk: DAEMON-LIFECYCLE-PLAN.md (separate track). User controls push (already pushed through 707c733). traceable-reqs is binding — tag evidence in-commit, run check before done, false-green trap = read raw exit codes never piped greps.


Download Psyche's current context to diff against (it shifts via background echo communes).


Bash

cd "C:/Users/decid/Documents/projects/spt-core"; $LIVE psyche-download doyle 2>&1 | head -60; echo "===EXIT:${PIPESTATUS[0]}==="

Download current psyche context


<memformat>
<?xml version="1.0"?>
<memformat version="1">
<!-- Changelog: v1 - initial seed -->
<topics>
  <topic name="events">Notable or unusual events and requests</topic>
  <topic name="interactions">Agent interactions -- who, roles, contributions</topic>
  <topic name="reflections">Thoughts on recent work -- what went well, what was tricky</topic>
  <topic name="ideas">Ideas to raise with the user</topic>
  <topic name="improvements">Further improvement ideas for recent problem spaces</topic>
  <topic name="timeline">What happened when, timing, sequencing</topic>
  <topic name="blockers">Current blockers or concerns</topic>
  <topic name="focus">Current focus and immediate next steps</topic>
</topics>
</memformat>
</memformat>

<current machine="HFENDULEAM" project="spt-core" branch="dev-freeform" head_sha="707c733d798874686f59666297a6be59bf3df46d" head_subject="docs(mesh): MESH-D7-PLAN.md — revoke + timeboxed rotation + re-seed grac…" commits_since="0" commits_unpulled="0"/>
**D6 SHIPPED & PUSHED** — `6843a8f` on `dev-freeform`. THE WIDEN live: peerloop reads `roster.members_in` instead of `trust.peers_in`. TrustStore deleted fleet-wide (peers.json gone, trust_dir kept for access/grants). Pairing wire stripped, serve gate repointed, warn-on-change demoted to non-blocking RekeyNotice, CLI repointed. D0 harness un-ignored (staggered + star, both green). REQ-MESH-3 `[impl,unit,int]` + REQ-MESH-5 `[impl,unit]` active; REQ-PAIR-2 retired (superseded by cutover). 21 files, −231 net. All real-exit 0: 60 test suites, clippy, traceable-reqs, `--no-default-features`. Push queued; CI monitoring live.<project-context-resolved name="spt-core"/>
**Mesh-D6 complete. Mesh arc: D0–D5b ✅ · D6 ✅ (mesh on, shipped) · D7 NEXT = subnet revoke (propagating tombstone + seed rotation) · D8 = probe concurrency.** Push initiated on `dev-freeform` (user controls when to merge to main).===EXIT:0===


write the JIT plan for D7 if it doesn't exist, then /commune with immediate next steps and broad summary of the project's status + end goal. we'll resume in the next session


Psyche is at `707c733` and knows D6 shipped + the widen/deletion/REQ activation. Missing: CI went green (after the docs-drift fix), the docs-drift-gate lesson, the harness offline-modeling gotcha, and the D7 plan substance. Communing only that delta. In-project → both envelopes.


Write

<live-context>
Delta since your snapshot (you have "D6 shipped, push queued, CI monitoring live" — here's what resolved + the D7 substance you don't hold yet):

**CI is GREEN.** First run on `6843a8f` FAILED — but not a test regression: the **docs-drift gate** (`xtask check`, SEPARATE from `traceable-reqs check`) caught that the prune→roster `--help` rewording drifted `docs-site/src/cli/reference.md`. Fix = `cargo run -p xtask -- gen` + commit (`4c583f7`). Re-run green (Win + Linux test + traceability; twohost skipped/gated). LESSON to carry: any CLI `--help` text change ⇒ regenerate docs or CI's drift gate fails. Two separate gates exist — traceable-reqs (req evidence) AND docs-drift (generated CLI/docs).

**The D6 harness gotcha worth flagging to a reviewer** (mesh.rs): "offline" was modeled by stopping a node's pump+dispatch loops, but the BROKER stays up (no broker-shutdown API). With the WIDE roster, a node now DIALS offline peers — and a push to a broker-up/dispatch-down node BLOCKS the pump permanently, so roster order starves later peers (A↔C never converged because C wedged dialing offline-A first). Fix = model offline as truly UNREACHABLE: a live reachability table (`Arc<Mutex<HashMap>>`) the resolver reads, + DISABLED peer-addr seeding (peer_addrs under a regular file so `record()` no-ops, no stale seed bypasses the resolver). Phase 3 also restarts C's pump (fresh conn cache) to model the broker's closed-watcher reaping the dead conn. This is a HARNESS-fidelity device, NOT a production concern (real offline = process+broker dead = dial fails → skip). Documented inline. If a reviewer pushes back, this is the deviation to defend.

**Mesh-D7 the coupling insight (the heart of the plan):** rotation and re-seed grace are INSEPARABLE, same shape as D6's deletion↔widen. Membership proof is EXACT-EPOCH. After `rotate_seed` bumps N→N+1, every honest member still on N is locked out — and the ONLY channel to hand them the new seed is a member connection they can't form (chicken-egg). Re-seed grace (accept an N-1 proof from an on-roster ¬tombstoned node → restricted reseed-only connection → push new seed) IS the delivery mechanism, not just auto-heal. Rotation BRICKS the fleet without it. Ship them together or not at all.

**D7 load-bearing change:** seedproofx/membership verify goes 3-valued — `Proven{full}` (exact-epoch ∧ on-roster), `Proven{reseed_only}` (epoch==local−1 ∧ on-roster ∧ ¬tombstoned), `Denied` (N-2+/off-roster/tombstoned/forged). This CLOSES the deferred D2 per-conn `proven_subnets` epoch cross-check — the proof already binds `seed_epoch`; D7 grades it instead of binary exact-only. A reseed_only conn admits ONLY a SeedTransfer stream (dispatcher refuses sync/notif/registry/update — fail-closed). Seed NEVER in gossip — rides only the member control stream.

**D7 gray areas to decide at plan/discuss start:** (a) window-scheduler persistence/firing shape (daemon-tick reading `identity/rotation-pending.json` vs a real timer — plan leans daemon-tick, pure-core `due_rotations`/`coalesce` for unit); (b) how the 3-valued grade threads through nethost `ConnEntry.proven_subnets` (currently `HashSet<String>` — needs to carry the grade, not just the name); (c) the SeedTransfer adopt path (reuse `SubnetStore::add_joined` rotate-adopt vs a new method).
</live-context>
<project-context>
HEAD now `707c733` (dev-freeform, pushed). Three commits since your "D6 shipped" snapshot: `6843a8f` (mesh-on), `4c583f7` (docs-drift fix — regenerated CLI reference.md), `707c733` (MESH-D7-PLAN.md). **CI GREEN** through HEAD.

IMMEDIATE NEXT = **Mesh-D7 (REQ-MESH-4)** — full JIT plan committed in `MESH-D7-PLAN.md`. The membership-removal lifecycle. Steps: (1) `spt subnet revoke <node>...` (list, elevation-gated via `trust_mutation_refusal`, revoke-only, reuse `prune_candidates` resolution) → PROPAGATING `roster.tombstone` (vs prune's local-only) + schedule ONE coalescing-window rotation (`identity/rotation-pending.json` {subnet→{deadline_ms,revokees}}; `--force-rotate-seed` = immediate). (2) pump fires due rotations (`rotate_seed` bump + clear pending + force-drop + reseed push). (3) confidential SeedTransfer over the member control stream (reuse `Frame::Seed` codec shape) + force-drop revokee conns. (4) the 3-valued proof grade (see live-context) — closes the deferred D2 epoch cross-check. Activate REQ-MESH-4 [impl,unit,int]. int acceptance = revoke → offliner returns → auto-heals (B re-seeds, revokee C stays out without a fresh re-pair).

Mesh arc: D0–D5b ✅ · D6 ✅ (mesh ON, pushed, CI green) · **D7 ← NEXT** · D8 = status-probe concurrency (REQ-MESH-6, independent polish).

Resuming in a NEW session next — start from MESH-D7-PLAN.md. traceable-reqs binding (tag in-commit, run check before done, read RAW exit codes — false-green trap). Watch BOTH CI gates on D7: traceable-reqs AND docs-drift (`xtask gen` if `revoke --help` changes the CLI reference). Queued untouched: DAEMON-LIFECYCLE-PLAN.md (separate track). User controls merge to main.
</project-context>


File created successfully at: C:\Users\decid\Documents\projects\spt-core\.claude\doyle-commune.md (file state is current in your context — no need to Read it back)

<live-context>
Delta since your snapshot (you have "D6 shipped, push queued, CI monitoring live" — here's what resolved + the D7 substance you don't hold yet):

**CI is GREEN.** First run on `6843a8f` FAILED — but not a test regression: the **docs-drift gate** (`xtask check`, SEPARATE from `traceable-reqs check`) caught that the prune→roster `--help` rewording drifted `docs-site/src/cli/reference.md`. Fix = `cargo run -p xtask -- gen` + commit (`4c583f7`). Re-run green (Win + Linux test + traceability; twohost skipped/gated). LESSON to carry: any CLI `--help` text change ⇒ regenerate docs or CI's drift gate fails. Two separate gates exist — traceable-reqs (req evidence) AND docs-drift (generated CLI/docs).

**The D6 harness gotcha worth flagging to a reviewer** (mesh.rs): "offline" was modeled by stopping a node's pump+dispatch loops, but the BROKER stays up (no broker-shutdown API). With the WIDE roster, a node now DIALS offline peers — and a push to a broker-up/dispatch-down node BLOCKS the pump permanently, so roster order starves later peers (A↔C never converged because C wedged dialing offline-A first). Fix = model offline as truly UNREACHABLE: a live reachability table (`Arc<Mutex<HashMap>>`) the resolver reads, + DISABLED peer-addr seeding (peer_addrs under a regular file so `record()` no-ops, no stale seed bypasses the resolver). Phase 3 also restarts C's pump (fresh conn cache) to model the broker's closed-watcher reaping the dead conn. This is a HARNESS-fidelity device, NOT a production concern (real offline = process+broker dead = dial fails → skip). Documented inline. If a reviewer pushes back, this is the deviation to defend.

**Mesh-D7 the coupling insight (the heart of the plan):** rotation and re-seed grace are INSEPARABLE, same shape as D6's deletion↔widen. Membership proof is EXACT-EPOCH. After `rotate_seed` bumps N→N+1, every honest member still on N is locked out — and the ONLY channel to hand them the new seed is a member connection they can't form (chicken-egg). Re-seed grace (accept an N-1 proof from an on-roster ¬tombstoned node → restricted reseed-only connection → push new seed) IS the delivery mechanism, not just auto-heal. Rotation BRICKS the fleet without it. Ship them together or not at all.

**D7 load-bearing change:** seedproofx/membership verify goes 3-valued — `Proven{full}` (exact-epoch ∧ on-roster), `Proven{reseed_only}` (epoch==local−1 ∧ on-roster ∧ ¬tombstoned), `Denied` (N-2+/off-roster/tombstoned/forged). This CLOSES the deferred D2 per-conn `proven_subnets` epoch cross-check — the proof already binds `seed_epoch`; D7 grades it instead of binary exact-only. A reseed_only conn admits ONLY a SeedTransfer stream (dispatcher refuses sync/notif/registry/update — fail-closed). Seed NEVER in gossip — rides only the member control stream.

**D7 gray areas to decide at plan/discuss start:** (a) window-scheduler persistence/firing shape (daemon-tick reading `identity/rotation-pending.json` vs a real timer — plan leans daemon-tick, pure-core `due_rotations`/`coalesce` for unit); (b) how the 3-valued grade threads through nethost `ConnEntry.proven_subnets` (currently `HashSet<String>` — needs to carry the grade, not just the name); (c) the SeedTransfer adopt path (reuse `SubnetStore::add_joined` rotate-adopt vs a new method).
</live-context>
<project-context>
HEAD now `707c733` (dev-freeform, pushed). Three commits since your "D6 shipped" snapshot: `6843a8f` (mesh-on), `4c583f7` (docs-drift fix — regenerated CLI reference.md), `707c733` (MESH-D7-PLAN.md). **CI GREEN** through HEAD.

IMMEDIATE NEXT = **Mesh-D7 (REQ-MESH-4)** — full JIT plan committed in `MESH-D7-PLAN.md`. The membership-removal lifecycle. Steps: (1) `spt subnet revoke <node>...` (list, elevation-gated via `trust_mutation_refusal`, revoke-only, reuse `prune_candidates` resolution) → PROPAGATING `roster.tombstone` (vs prune's local-only) + schedule ONE coalescing-window rotation (`identity/rotation-pending.json` {subnet→{deadline_ms,revokees}}; `--force-rotate-seed` = immediate). (2) pump fires due rotations (`rotate_seed` bump + clear pending + force-drop + reseed push). (3) confidential SeedTransfer over the member control stream (reuse `Frame::Seed` codec shape) + force-drop revokee conns. (4) the 3-valued proof grade (see live-context) — closes the deferred D2 epoch cross-check. Activate REQ-MESH-4 [impl,unit,int]. int acceptance = revoke → offliner returns → auto-heals (B re-seeds, revokee C stays out without a fresh re-pair).

Mesh arc: D0–D5b ✅ · D6 ✅ (mesh ON, pushed, CI green) · **D7 ← NEXT** · D8 = status-probe concurrency (REQ-MESH-6, independent polish).

Resuming in a NEW session next — start from MESH-D7-PLAN.md. traceable-reqs binding (tag in-commit, run check before done, read RAW exit codes — false-green trap). Watch BOTH CI gates on D7: traceable-reqs AND docs-drift (`xtask gen` if `revoke --help` changes the CLI reference). Queued untouched: DAEMON-LIFECYCLE-PLAN.md (separate track). User controls merge to main.
</project-context>


Commune written to `.claude/doyle-commune.md` — Self listener ingests on next poll. Delta only (CI-green-after-docs-fix, the docs-drift-gate lesson, the harness offline gotcha, full D7 substance); skipped what Psyche already holds.

**Session wrap:**
- **D6 mesh-ON shipped + pushed + CI green** — `6843a8f`, `4c583f7` (docs fix), `707c733` (D7 plan), all on `dev-freeform`.
- **D7 plan written** — `MESH-D7-PLAN.md`: revoke + timeboxed rotation + re-seed grace (REQ-MESH-4). Core insight captured: rotation↔re-seed-grace inseparable (grace is the seed-delivery channel, not just auto-heal); 3-valued proof grade closes the deferred D2 epoch cross-check.
- **Psyche synced** for next session.

Resume next session from `MESH-D7-PLAN.md`. Two CI gates to watch on D7: traceable-reqs + docs-drift. User controls merge to main.