# W4 — releases#177: the engine room briefs ONCE PER SESSION, not once per attach

Lane: `fix/w4-er-brief-once`, worktree `.worktrees/w4-brief-once`, base
`origin/assembly/concierge-183` @ `c0878cbdd14de5f6c465667b0bb2b4727f1455bc` (the gated golden head;
W4 stacks on it). Own pool claim taken FROM the lane worktree, label `w4-brief-once`.

## The face, bounded

The engine room re-briefs on EVERY user attach. That only makes sense when the session is fresh, and
the endpoint stays running between attachments, so it is pointless more than once per session.

SCOPE: this is the ENLYZEAM face ONLY. The HFENDULEAM no-brief face is ALREADY DISCHARGED by #199 +
#164 (field verify rides the fleet update) — do not re-open it here.

## doyle's six rulings (dispatch 2026-08-19), and how this lane answers each

1. **Fix at the brief-ENQUEUE seam**, `OutputLog::settle_engine_room_seat`'s brief arm — NOT at
   delivery. A same-session seat-taking attach must not ENQUEUE a new briefing when this session
   already had one offered. A FRESH session (new bring-up, daemon restart) briefs exactly as today.
   CONDITION IS NOT CADENCE: payload/condition rules (`briefing::bringup_briefing`, the posture, the
   ruleset table) are untouched; only enqueue cadence is bounded.
   → `present_engine_room_briefing()` stays UNCONDITIONAL. That is not an oversight: it is the
   consuming half (#164/`REQ-ER-BRIEFING-PRESENTED`), and clause 4's retained-row rescue depends on
   the next seat re-offering a row a previous seat failed to present. Suppressing delivery would
   fix #177 by re-breaking #164.
   → Empowerment minting and the operator-facing grant line stay per-seat: a `--take` drops the
   displaced controller's empowerments, so the taker's grant must still be minted and stated.
2. **The head PINS the old behaviour.** `er_briefing_presented_e2e.rs` says
   "`settle_engine_room_seat` fires for every seat-taking attach" in TWO places (module header rung
   5, and the arm-5 inline comment). The arm's SCENARIO survives — it reaps the daemon tree between
   the seats, so seat 2 is a genuinely fresh session and the re-offer still fires — but the
   mechanism SENTENCES become false and are reworded in the SAME commit. Re-read them at MY
   post-change tree before rewording (standing rule: a sequenced edit is re-read at the post-change
   tree, never executed on the strength of when it was queued).
3. **New cell required**: a same-session second attach does NOT re-brief, with the
   green-that-cannot-red guard being a POSITIVE CONTROL in the same cell — the FIRST brief still
   lands in that same run (spool count 1, not 0).
   → int cell `crates/spt/tests/er_brief_once_per_session_e2e.rs`, plus a unit arm on the existing
   broker seat resolver (`taking_the_engine_rooms_controls_costs_a_member_or_admin_code`'s rig
   shape: `engine_room_log()` + `resolve_subscribe(..., Some(code))`).
   → SAME-SESSION is itself pinned, never assumed: the cell asserts `info.session_id` is IDENTICAL
   across the two seats. If the session changed, the arm is about two sessions and its claim would
   be vacuous.
4. **traceable-reqs**: registry checked FIRST. No #177-specific REQ exists. `REQ-ER-SESSION-BRIEFING`
   already owns this sentence ("Every engine-room session opens with a system-authored briefing
   message") — #177 is the CADENCE half of that very requirement, so it is EXTENDED rather than
   duplicated (two requirements owning briefing cadence is the confusion the req audit refuses).
   `required_stages` gains `int` (the new cell is int-shaped, and the existing
   `er_briefing_presented_e2e.rs` already carries an `[int->REQ-ER-SESSION-BRIEFING]` tag).
5. **Lane base + own pool** — done as stated above.
6. **Commit trailer on its OWN LINE with REAL newlines** — separate `-m` paragraphs or a message
   FILE, never a literal `\n` inside one `-m`. Spelling: `Co-authored by: todlando` (space form).

## The mechanism

`settle_engine_room_seat` gets an OutputLog-scoped flag. OutputLog IS the broker-hosted session:
one per hosted session, dropped when the session is re-hosted or the daemon restarts. That maps
exactly onto ruling 1's fresh-session clause with no new on-disk state, no purge interaction, and
no session-id-is-None edge case (an unbound perch reads no session id — a store-keyed marker would
have to guess there).

```
let enqueued = if self.engine_room_briefed { false } else {
    self.brief_engine_room(granted.as_deref());
    self.engine_room_briefed = true;
    true
};
// NOT bounded by the enqueue — bounded by whether anything is OWED.
let owed = enqueued || pending_count_non_deferred_at(&engine_room_perch()) > 0;
if owed { present_engine_room_briefing(); }
```

**The `owed` gate was MEASURED into existence, not designed in.** The first build
called `present_engine_room_briefing()` unconditionally, and the int cell's daemon
log showed the consequence: on the same-session second seat the drive found an empty
spool, took zero rows, and printed
`ENGINE_ROOM_BRIEFING_UNPRESENTED: ... this session opens WITHOUT its posture briefing`.
That line is LOUD by design and it would now be FALSE on every ordinary re-attach —
about a briefing that WAS delivered and is missing from the spool for the best
possible reason. An operator who learns to ignore that line ignores it on the day it
is true. So the drive is gated on something being owed (this seat's own enqueue, or a
row a previous seat left pending), which preserves #164 clause 4's retained-row rescue
exactly — a retained row makes `owed` true — while removing the false alarm. The int
cell now PINS the absence of that line.

Residual, declared: `owed` counts pending rows by author-agnostic predicate, so a
pending ORDINARY message also drives the native inject at a re-attach. That is the
pre-#177 behaviour of this seat unchanged (it always drove), and it is the same native
drain the idle window would run moments later.

Reject: a store-side "last briefed session" record. It would suppress the re-brief after a daemon
restart whenever the harness outlived the broker and kept its session id — the exact case doyle
ruled must brief as today.

## Evidence plan

- doc — CONTEXT.md engine-room entry (existing `[doc->REQ-ER-SESSION-BRIEFING]` site) states the
  cadence: once per session, at the enqueue seam; a fresh session briefs again.
- impl — the flag + the guarded brief arm in `broker.rs`.
- unit — the same-session second attach spools no second row, positive control in the same arm.
- int — the new e2e cell.

## Gate handoff

doyle's gate: diff read + er suite legs + the new cell x3. Report branch + 8+ char sha from
`git rev-parse`.
