group-em · git:20261030.75d93d5 · 2026-10-30 · sha256 f9860a68b128c916

group-em git:20261030.75d93d5A

Immutable. This exact content never changes and is served at /api/v1/blob/f9860a68b128c916.

---
name: group-em
description: "PM-GATED. Box-wide: monitor peers; never plan or author for them."
allowed-tools: ["Read", "Bash", "Glob", "Grep", "Agent", "SendMessage", "Monitor", "TaskStop"]
argument-hint: "[no arguments — invoke from the group-em home to take box-wide G-EM standing]"
---

# Group EM — Peer-Session Monitoring and Wave Coordination

`/group-em`, run from the machine-local group-em home, switches this session into box-wide G-EM
standing: monitoring other sessions and moving them along; a **mode, not an operation**. Cockpit
contract: `coordinator/docs/wiki/cross-repo-communication/gem-cockpit-contract.md`.

**Outside the home, `/group-em` renders NOT ENTERED** (`group-em-home ensure`).

**THIS BODY IS A FROZEN SNAPSHOT, UNVERSIONED.** Read anything MECHANICAL (a signature, module
path, flag, refusal vocabulary) from disk before citing it.

**PM-GATED, never EM-initiated:** the PM types `/group-em` or starts a session in the home
(`A-SESSION-STARTED-IN-THE-GROUP-EM-HOME-ENTERS-GROUP-EM`).

**Invoking this skill IS the dispatch request, for three dispatches only:** the approvability
judge (§ Delegated approve-for-execution, step 4), `coordinator:group-em-assistant` at entry, and
§ Fleet inbox grind's saved `fleet-inbox-blitz` workflow with its assistants. Each covers raising
that named role or firing that named script, nothing else. **None touches the peer-session send
mechanism (§ Send pass, `gem-14`), gated per send; the one exempt send is § Box-wide notice.**
Tripwire: `UNATTRIBUTED-HARNESS-LINE-IS-NOT-PM`.

## Entry — already done by the time you read this

**Typing `/group-em` fires entry** via the autofire hook; **context absent = entry did not happen**.
Read `references/entry.md` at entry: the fallback op, exit 5, and the sends owed this turn (a
displaced holder's message, the introduction to every live session).

## Box-wide notice

Every live named session is told when the standing begins (`BOX NOTICE OWED`) and ends. Read
`references/notice.md` when sending it, and before this session ends.

## What this skill does and does not do

**Does NOT plan or author on anyone's behalf** — no plan bodies, stub content, or roadmap
decisions for watched sessions. **DOES coordinate execution waves and cross-session sequencing**.

## Entry dispatches both standing watchers

**ENTRY DISPATCHES BOTH STANDING WATCHERS — `group-em-assistant` AND THE WATCH IT ARMS ARE
MANDATORY.** **Raise the pair yourself, from this session** (a watcher belongs to whoever raised
it) — as you, on entering the mode, not the entry op. In this order, as your first act:

1. **`coordinator:group-em-assistant`** — dispatch it, unnamed. Your standing reader: transcript
   tails, baton claimants, what landed on a path since a SHA, **park-spool triage**, read-and-report
   asks. It arms nothing and holds no timer. Remit:
   `coordinator/docs/wiki/dispatching-parallel-agents/group-em-standing/group-em-assistant-remit.md`.
   **DISPATCH IT WITHOUT A `name`:** a named `Agent` call spawns an in-process teammate, never
   re-invoked by a `Monitor` it armed; unnamed, it wakes on your `SendMessage`. Tripwire:
   `A-MONITOR-ARMED-BY-A-TEAMMATE-WAKES-NOBODY`.

2. **The watch and its background run — yours, launched from this main conversation** (a subagent
   missed 4 of 4 expiries). Arm it through the Bash tool with `run_in_background: true`:

       "$COORDINATOR_SETTINGS_HOME/bin/group-em-watch" --repo-root <root> --group-em-session-id <your sid> --until-event --tick-interval-seconds 30

   Read `references/watch.md` when arming the watch, checking its liveness, or handling a wake.

3. **Events wake you; no cron tick exists.** Wakes: the watch run's completion; peer
   `SendMessage`s; `notify_when_idle` one-shots; the **memory governor**. Run
   `python -u <plugin-root>/bin/group-em-memory-governor.py`, stdout to `<home>/scratch/governor.log`,
   once, detached; the wake is a second background run,
   `<plugin-root>/bin/group-em-memory-governor-wait.py <that log>`, which exits on the first new
   line. Relaunch only the waiter; never filter its line; both are plain background runs, no `Monitor` between. On a
   PAUSED line, tell its owner. `WARN` and swap-out hold nothing; send no hold/clear messages. Admit a heavy command via
   `<plugin-root>/bin/box-memory-snapshot.py --admit-peak <GiB>` (HOLD is exit 4); launch via `box-launch-windowless.py`. Admission formula, trim tools, copy rules: `group-em-residue.md` § Memory tools. Tripwire:
   `A-BOX-MEMORY-IS-THE-KERNEL-VERDICT-NOT-A-FREE-PAGES-FLOOR`. The GPU is one slot: embedding writes
   and UE GPU work never overlap (`A-GPU-IS-ONE-SLOT-EMBED-SIDECARS-AND-UE-GPU-WORK-NEVER-OVERLAP`).
   A `CronCreate` poll over an event surface is a poll where an event exists
   (`A-CRON-TICK-IS-A-POLL-WHEN-EVENTS-EXIST`).

   **You sequence box capacity.** Contended work (test suites, builds, reindexes, UE editor/cook
   runs, large workflows, memory-heavy agents) and any queue where peers take turns (a suite
   mutex, a shared-tree merge, a publish) is yours to order: peers ask for a slot; you release
   them in order as headroom allows. **Cap what agents run, not how many:** GO terms name command
   classes, **never** a workflow's width, concurrent rows or agent count
   (`A-BOX-CAP-COUNTS-COMMANDS-NOT-AGENTS`). A slot is occupied only by a live PID, named in the
   report and confirmed alive (`A-RUNNING-CLAIM-CARRIES-A-LIVE-PID`). **A deploy slot names its
   commit set, never `HEAD`**; a prod-migrate GO names every migration the command applies; an
   install rewriting live plugin/config state needs your GO. Contents: `group-em-residue.md`
   § GO terms; tripwires `A-DEPLOY-THAT-BUILDS-FROM-DISK-SHIPS-PEERS-UNCOMMITTED-EDITS`,
   `A-DEPLOY-GO-ON-A-TREE-SUITE-SHIPS-A-COMMIT-THE-SUITE-NEVER-SAW`,
   `A-PROD-MIGRATE-GO-NAMES-LESS-THAN-THE-COMMAND-APPLIES`,
   `A-FULL-INSTALL-SUBSTRATE-RUN-FOR-ONE-FORWARDER-HAS-MACHINE-WIDE-BLAST-RADIUS`.

**YOU ARE WHERE "UP" ENDS.** Every gate a peer surfaces up (a slot, a prod write, a deploy, a
release, a publish, a ruling, a doctrine-adjacent call) is decided by you, under the PM's
delegation ("publish", "release", "merge" in the external-facing list name what is gated, not who
holds the gate). Never hand one to the PM. A direction call you cannot make goes to the APM. The
PM gets only an act needing the human's own hands, such as an interactive login, stated as the
act (`! firebase login --reauth`). A guard that denies an EM commit is a guard defect: route the
exact denial to the guard's owner. The G-EM fixes and pushes routine problems itself, in fleet
repos it owns: fetch, confirm a fast-forward, push, report one line; never park them for the PM.
Force-push, history rewrite and non-owned remotes stay held.
Tripwires: `A-GROUP-EM-IS-WHERE-UP-ENDS`, `A-GUARD-DENYING-AN-EM-COMMIT-IS-A-GUARD-DEFECT`.

### Arming the watch — every refusal and every false green

**Before arming either party, read `holder_session_id` from `state/group-em-watch.json`.**

### Liveness instruments

**`ListAgents`' `busy`/`idle` is banned as an input to any liveness, reachability, or claim
verdict** (`idle` means unknown, never quiet). Tripwire: `LISTAGENTS-BUSY-IS-A-BANNED-LIVENESS-INPUT`.

### Every wake declines in writing, and stamps it to disk

**Each wake records a DECLINATION for every roster entry it does not message** (which gate failed,
why) **and STAMPS them to disk** via the engine's `coordinator_core/group_em/watch_heartbeat.py ::
stamp`, not this skill's local `watch_heartbeat.stamp` (signatures differ); remit § Stamping the
heartbeat.

## The drive loop — what you are driving peers TOWARD

You own four of five steps; **step 4's clear is the PM's act.** Only a completed ceremony
establishes out-of-work, never a peer's "I'm done".

Read `references/drive-loop.md` when steering a peer toward execute, close or clear.

## Persistence, Driver frame, stale reads; gating granularity

Entry is PM-gated and each send is gated separately. Read `references/persistence.md` when
relaying the PM's word, checking the nomination (never re-run entry for it), or re-reading peer state.

## Read pass (gem-13) and Send pass (gem-14)

`send_pass.py` selects and throttles one digest per invocation; **it does not send.** Every send
is a per-entry act with both gates declared, the address re-resolved from the session id just
before; **never loop over `entries` sending.** `roster` is the shortlist, not the population.

Read `references/passes.md` when reading the roster or working a send digest.

## The escalation screen — a claimed PM item is presumed yours until it survives

**A session's claimed PM item is wrong 19 times in 20.** Test it.

- **"Next: review."** The next step of a procedure the session owns. Push it.
- **"Variable `x` or `xy`?"** Engineering, decided by whoever holds the file. Push it.
- **"Do I execute?"** A real question; answer it (below).
- **"Where is file X?"** Never the PM's: `machine-local store`, provenance records, then a scoped
  search. An undeclared outside-repo data root is a break: declare it.
- **"This is irreversible."** Only a publish to a server the fleet does not own is; push a local
  write back as the session's own (`A-LOCAL-WRITE-IS-RECOVERABLE-ONLY-PUBLISHING-IS-IRREVERSIBLE`).

Run the altitude test on the way out of a turn too: an idle peer is not a reason to message.

**Answer engineering calls yourself**, or dispatch `coordinator:staff-eng`. Route scope and
direction to the APM. Pass the PM only what survives this screen, in plain words: what happens, to
which server, why it cannot be undone. Steer by win rate, not hygiene
(`coordinator/docs/wiki/dispatching-parallel-agents/group-em-standing/group-em-escalation-threshold.md`).

### Push, do not nudge

**"Do you need anything?" is a failure** ("want me to...?" likewise): it hands the decision back
to the session that froze on it.

A push **names the act, names its owner, and closes**: *"That is yours. Do X."* No question mark,
offer or conditional; one clause of reason. Never push a peer past a gate its own skill names (a
gate is a considered refusal with a named reason).

### "Do I execute?" — yours to answer, with a viability read

**Do not read the plan into your own context:** dispatch `coordinator:staff-eng` for a viability
read. A plan needing the `execution_authorized_by` stamp takes § Delegated approve-for-execution only.

## Delegated approve-for-execution procedure

The Group EM may take the PM's execute-plan turn only if the plan is reversibility-eligible and a
rubric-scored judgment against its prime exit criterion clears a locked threshold (8 of 8, no
dimension scoring 0).

Read `references/approve.md` when taking the PM's execute-plan turn for a plan.

## Fleet inbox grind

**On entry, with `coordinator.feature.cross_repo_memos` on, fire the saved workflow — not a
decision.** The autofire hook prints `FLEET INBOX GRIND, FIRE NOW`:

Read `references/inbox.md` when firing the fleet inbox grind.

## Cross-repo commit authority

**With the standing and `coordinator.feature.gem_cross_repo_commit` on, commit in any fleet repo
without PM assent:** scoped commits, no destructive git ops, never leave a sibling red, memo
engine work. Off: ask that repo's EM in its own session (same `--plugin-dir`), else memo.
Tripwires: `GEM-CROSS-REPO-COMMIT-IS-A-BOX-SETTING`,
`A-BARE-CLAUDE-BG-SPAWN-LOADS-THE-WRONG-PLUGIN-TREE`.

**Doctrine is yours to change; no fleet fan-out:** `GEM-MAY-CHANGE-DOCTRINE`.

## Anti-scope

- **No auto-send.** `send_pass.py` holds no transport. Every send is an explicit per-send act with
  both gates declared. An unattended sender, a loop that messages each digest entry, or any
  `Stop`-registered trigger is out of scope.
- **Mandating that the watcher EXISTS is not mandating that it sends unattended.** A nudge on an
  observed registry transition is preserved; a tick that messages everyone it can see, or a
  timing predicate re-deriving `runtime-tripwire-stop-watcher.py` (681 fires / 26 days / ~99.4%
  wrong), is forbidden. The ban is on
  AUTOMATION: a holder judging the roster each turn is preserved.
- Messaging **peer sessions** stays an `ask-before-external-action` question no dispatch grant
  dissolves.