# SEMAPHORE (#242) — pre-plan grill, doc-grounded (doyle, 2026-08-29)

Milestone: releases#242, six members attached (#237 #238 #239 #241 #235 #229), state backlog.
Method: every member interrogated against the record (issue body + comments, CONTEXT/frames docs,
REQ registry, KNOWN-HAZARDS, broker/lifecycle source at main `4b63de27`). Gray areas either RULED
here with the grounding cited, or NAMED as an operator fork. NOW-SIGNAL (#23, GREENLIT, 9 open
members) was deliberately NOT poached — the 422 one-parent refusal was correct; it stands as the
natural next milestone after SEMAPHORE.

## Members with NO gray areas

- **#241 emission single-write** — BUILT, all waves gated PASS, parked at `d0fdd58d`
  (feat/emit-single-write). Assembly-only work remains: compose off current main with the
  pick-fidelity audit (the new `xtask pick-audit` from IR-57 — its first real assembly is this
  one), never-executed-cells list in the hand-off. Never-executed at golden depth: the converted
  emitters' e2e paths ran in the lane batteries but the assembled composition is first-run.
- **#237 schema internal-codes sweep** — already RULED at the W1 gate (my PR#171 comment
  5458378678): ALL internal codes out of schema descriptions (ADR refs included — dead pointers
  to adapter authors), gate widens to manifest.schema.json in the same change. Shape known
  (manifest.rs doc comments → regen). Coverage = manifest_schema_shape drift test + widened gate.

## Members with gray areas — RULED here

- **#235 wake-gate CLAIM fallback.** The deciding arm (`wake_gate_decision`, broker.rs:272) is
  deliberate and documented: past-deadline claim ⇒ `Claim`, "availability over a vanishingly
  rare dup." The premise ("vanishingly rare") is MEASURED FALSE under battery load (winner's
  ConPTY create > 2s ⇒ loser double-creates; REQ-SPAWN-FRESH-TRUTHFUL falsified once at a W2
  battery). **RULING: the decision gains a fourth observable — CLAIM-HOLDER LIVENESS — instead of
  a longer clock.** Extending the deadline moves the window (generous-bound craft: the wait bound
  is a liveness PROXY); probing the holder closes it. Past-deadline + holder ALIVE ⇒ stay
  `Racing` (re-wait); past-deadline + holder DEAD ⇒ `Claim` (the leaked-claim arm survives
  unchanged). The probe MUST be authenticated (image-path-corroborated), not bare-pid — the
  bare-pid class is releases#140/#143's measured hazard and adding a 10th unsound site inside the
  spawn guard would be filing the next issue ourselves. The pure-fn truth table stays a unit (one
  more input column). Deterministic rig per the issue's own shape: stretch the winner past 2s,
  two concurrent spawns, assert one Created + one typed outcome — plus the dead-holder arm as a
  second cell so the availability path keeps its coverage.
- **#229 role-absence asymmetry.** Source: echo_commune absence ⇒ ONE `ECHO_ROLE_ABSENT` warn +
  skip (lifecycle.rs:488-496, REQ-PSYCHE-ROLE-OPTIONAL-SKIP — whose own history says the pre-fix
  hard-fail-every-fire shape was a defect); psyche_resume absence ⇒ every ephemeral psyche turn
  errs and feeds the failure budget — per-fire STRIKES for a STRUCTURAL condition. **RULING:
  align to skip-with-loud-status.** Absence of `[session.psyche_resume]` is detected ONCE,
  structurally (at bind/first-fire): one loud `PSYCHE_ROLE_ABSENT` line + a surfaced state field
  (the endpoint-list psyche field family), psyche turns SKIPPED, ZERO strikes — the failure
  budget is for a declared role that FAILS, not for one that was never declared. Grounding: the
  silent-degraded-resume hazard is real (commune-ingest class), so absence must be LOUD and
  status-visible — but per-fire strikes are noise wearing signal's clothes: they exhaust a
  budget built for a different mechanism and surface as psyche_host_error churn (#136-adjacent).
  The REQ gains the sentence naming psyche_resume load-bearing-when-declared; missing-role test
  for BOTH polarities per the issue's ask.
- **#238 mid-turn dedup respec (the non-operator half).** The double-parse hazard: mid-turn
  payloads AND the closing AGENT_OUTPUT both traverse ingest, and REQ-IO-SHORTFORM-GATE's
  no-release-parses-twice clause is load-bearing. **RULING: non-overlap stays the ADAPTER'S
  reporting contract** — the integration-checklist row is respec'd from "ONE payload-carrying
  call per turn" to "every reported payload span is reported EXACTLY ONCE across the turn"
  (mid-turn chunks + closing remainder are disjoint), and core's parse remains per-ingest-call
  with no cross-call dedup machinery. Grounding: core-side span dedup would need core to model
  turn assembly, which the funnel design deliberately refuses (adapter knows its harness's turn
  shape; core owns delivery). The doc sweep (frames.md mid-turn paragraph, patterns.md dedup
  note, integration checklist) rides the lane per the issue's item 3 — and folds in the
  parse-vs-16KB-frame-cap ordering sentence (parse runs over the FULL ingested payload; the cap
  bounds only the emitted frame body) queued from perri's filing.
- **#238 rate re-derivation + W3 comment correction** ride the lane as specified (item 4);
  ADR-0048 decisions 1-3 stay perri's locked contract (item 5). Not gray — restated so the
  builder brief carries them.

## Operator forks — RULED (operator, greenlight session 2026-08-29)

1. **#238: ATTRIBUTE on AGENT_OUTPUT** (against the gater lean, ruled on semantics: "it'd be
   confusing if AGENT_OUTPUT excluded *some* agent output"). SCOPE EXTENSION in the same ruling:
   **core-owned shortform messaging reacts to ALL agent output including mid-turn, and the same
   applies to the `;;` seal-mint markers.** Recorded as releases#238 comment 5461768445.
   Lane consequences: the #22 taxonomy row's end-of-turn sentence amends (doc sweep item 3);
   both shortform families parse mid-turn ingested payloads (exactly-once span reporting carries
   dedup, per the ruling above); NEW DESIGN GATE — bare trailing `;;` "seals through end of
   output" under chunked ingest points at text the parser has not seen; design proposal required
   before build (gater lean: defer odd-marker resolution to turn close, per-turn parser state);
   verify the shipped #234 reader's tolerance of an unknown attribute (attr-passthrough
   precedent) at design.
2. **#239: NEW `boundary` frame category** as recommended — event-class, three variants
   (boot/clear/compact) minted whole. Recorded as releases#239 comment 5461768503; the
   needs-operator flag CLEARED on that recorded discussion (board verified: flags none).
3. **Composition GREENLIT as composed.** #242 BACKLOG → GREENLIT executed through alchemy,
   cascade verified to all six members. NOW-SIGNAL #23 intact as the standing next milestone.

## Wave plan (dispatched 2026-08-29)

- **W1 (todlando): #235** — holder-liveness observable per the ruling above.
- **W2 (todlando): #238** — design proposal first (attribute shape, mid-turn parse, bare-seal
  deferral, reader attr tolerance), gater signs the proposal, then build. Blocks perri; largest.
- **W3 (todlando): #239** — boundary category emitter + docs.
- **W4 (todlando): #229** — skip-with-loud-status alignment per the ruling above.
- **hertz: #237** — comment sweep + gate widening + drift-test coverage; plus per-wave consumer
  batteries and any test defects surfaced.
- **doyle: #241** — assembly at milestone close (first real `xtask pick-audit` use where the
  chain is pick-shaped; blob-parity leg where merged), per-wave gates, hand-off to deployah with
  the never-executed-cells list per the amended runbook.

## Riders (infra, not board members)

- IR-57 pick-fidelity audit: LANDED PR#180 (gate pending, todlando's entry-figure correction
  310/308→302/300 queued for next register batch). First real use = #241's assembly.
- IR-59 disk-floor verb: design ACKED, building.
