{
  "summary": "## Verdict\n\n`--create` is presently **syntax-only**. Clap parses it and enforces only its conflict with `--resume`; dispatch then deliberately discards the boolean. The implementation interprets “create” only as `resume == None`, which selects `[session.self]` and mints a provisional session id **if execution reaches the spawn path**. Before that spawn, a broker-session probe can redirect the operation to reattach or an exit-0 already-live refusal. A second, broker-side dedup layer can also turn the spawn request into an ordinary `Spawned(existing_session)` success. Therefore the documented promise “Mint a fresh session” is false whenever the endpoint is broker-live or races another wake/resume spawn.\n\nThe smallest **safe** semantic fix is not a CLI-only check: make fresh creation an atomic broker operation that rejects an already-live endpoint, while retaining the existing reuse/dedup operation for wake/resume. Because a running broker may be N-1 and silently ignore additive request fields, the safest forward-compatible shape is a new IPC kind such as `spawn-fresh` (or an equivalently capability-gated typed operation), not an unacknowledged `SpawnReq.fresh: bool`. Fresh conflict should be a runtime conflict: **exit 1**, stderr token such as `ENDPOINT_CREATE_CONFLICT:<id>: a live broker session already exists; no session was created. Attach with 'spt rc <id>'; end or suspend the live session before retrying --create.`, no attach, no `ENDPOINT_RUN`/`ENDPOINT_RUN_STARTED`, and no durable mutation.\n\n## Exact causal chain\n\n1. **Parse:** `crates/spt/src/cli.rs:344-379` defines `EndpointCmd::Run`. `create: bool` is `#[arg(long, conflicts_with = \"resume\")]`; help says it mints a fresh session and is the default. Thus `--create --resume X` is a Clap usage failure (normally exit 2) before application code, but omitted `--create` and explicit `--create` are otherwise intended to mean the same fresh mode.\n2. **Flag erased:** `crates/spt/src/cli.rs:1387-1393` matches `create: _` and explicitly says it is not threaded further; only absence of `--resume` matters. No later function can distinguish explicit `--create` from omission.\n3. **Target routing ignores create:** `cli.rs:1401-1418` and `1817-1835` resolve only `(adapter?, id?)`. Both present => direct. Lone existing `--id` => direct using `info.adapter`. Lone new id, lone adapter, or neither => picker. Consequently `--create` alone or with a partial target does not force a direct create; it merely accompanies entry into the picker.\n4. **Fresh material is prepared before the live guard:** `cli.rs:1923-1969` maps `resume=None` to `(is_resume=false, mint_session_id())`. A resume request has separate ledger repair logic. This mint is only an in-process value; it does not prove that a child or harness conversation was created.\n5. **CLI live-session decision:** after `ensure_running`, `cli.rs:1975-2018` queries the broker through `rc::SessionProbe`. `rc.rs:861-904` resolves endpoint id against `Brain::sessions()`—broker session-table truth, independent of `info.status` and rest intent. `cli.rs:1772-1798` chooses:\n   - no broker session => `Spawn`;\n   - broker-live and `start == false` (default attach **or** `--view`) => `Reattach` to the existing broker session, with `ENDPOINT_ALREADY_LIVE`, no fresh spawn;\n   - broker-live and `--start` => `RefuseAlreadyLive`, `ENDPOINT_ALREADY_LIVE`, **exit 0**, no fresh spawn.\n   `--create` is unavailable to this decision because it was discarded.\n6. **Existing endpoint identity is reused:** if spawning proceeds, `cli.rs:2204-2327` creates an unbound skeleton only when no readable `info.json` exists. For an existing perch it immediately returns `Ok(())`; it does not clear the endpoint, ledger, tracked context, home, or conversation history. Thus create never promises a new endpoint identity. A new identity requires a new id/fork/purge semantics, not `--create`.\n7. **Manifest/harness selection:** `crates/spt-daemon/src/harnesshost.rs:55-72` mints a 16-lowercase-hex provisional id. `harnesshost.rs:77-128` selects `[session.self]` whenever `is_resume=false`; `is_resume=true` selects `[session.resume]` if present and otherwise falls back to `[session.self]`. `crates/spt-runtime/src/manifest.rs:225-252` declares those two roles; `manifest.rs:499-513` says the actual harness id may be post-spawn or UUID-injected. `harnesshost.rs:129-208` fills the opaque command/env templates. Core guarantees a fresh-role invocation plus a fresh provisional fill, not that the adapter/harness creates a fresh conversation: the command is adapter-authored and the harness later reports its actual session at bind.\n8. **Spawn request:** `harnesshost.rs:213-294` sends a labeled `SpawnReq` through `Brain::spawn_session_pid`; `crates/spt-daemon/src/msg.rs:260-333` has no create/reuse policy and `Spawned` has no disposition bit. `brain.rs:447-487` treats every `Spawned` reply identically.\n9. **Broker dedup:** `crates/spt-daemon/src/broker.rs:191-239` defines the single-flight gate. `broker.rs:3235-3302` applies it to **every non-empty `SpawnReq.endpoint`**, despite comments framing it as wake dedup. If a session already exists, or a concurrent claimant becomes live, broker emits `SPAWN_DEDUP`, sends an ordinary `KIND_SPAWNED` containing the existing broker session/pid, and returns success without spawning. The caller cannot distinguish this from creation. `cli.rs:2071-2116` can therefore print `ENDPOINT_RUN:<id> session=<new provisional> pid=<existing pid>` and `ENDPOINT_RUN_STARTED` even though the provisional was never passed to a new harness. This is the probe-miss/TOCTOU branch.\n10. **Existing coverage codifies the no-op:** `cli.rs:2376-2390` expects live+attach => reattach and live+start => idempotent refusal. `crates/spt/tests/run_no_dup_session_e2e.rs:1-24,210-231,275-319` explicitly expects exit 0, `ENDPOINT_ALREADY_LIVE`, no pid/new session for a headless second run. `crates/spt-daemon/tests/wake_single_flight.rs:1-28,127-180` expects two concurrent generic spawn requests to resolve to the same session. The no-duplicate safety invariant is correct; conflating “fresh create” with “reuse existing wake” is the defect.\n\n## Current no-spawn / no-create cases in scope\n\n| Case | Current observable result | Why |\n|---|---|---|\n| `--create --resume SID` | Clap usage refusal, no application state change, exit 2 | Parse conflict at `cli.rs:359-365`. |\n| `--create` with incomplete target | Picker, not a direct create | Router considers only adapter/id (`cli.rs:1401-1418`, `1817-1835`). |\n| Broker-live + `--create --start` (also implicit fresh + `--start`) | `ENDPOINT_ALREADY_LIVE`, no spawn, **exit 0** | `create` discarded; `RunOnLive::RefuseAlreadyLive` (`cli.rs:2005-2018`). |\n| Broker-live + `--create` / `--attach` | No spawn; attaches existing session | `RunOnLive::Reattach` (`cli.rs:1993-2004`). This may look like “create did nothing” because it is explicitly a reattach. |\n| Broker-live + `--create --view` | No spawn; views existing session | `start=false`; view affects only attach intent. |\n| CLI probe misses/races, broker already-live | Broker no-op-acks existing session as ordinary `Spawned`; CLI may print apparent spawn success | `broker.rs:3235-3302`; no disposition in `msg.rs:322-332`. |\n| Two labeled spawns race | Loser waits up to 2s, then normally no-op-acks winner’s session | `broker.rs:191-239,3251-3302`; exactly-one-tree safety. A >2s leaked claim can be taken over if still no live session. |\n| Existing perch, broker absent | Skeleton creation is a no-op, but harness **does** spawn fresh | Existing endpoint/home/history are intentionally retained (`cli.rs:2241-2244`). This is identity reuse, not a total no-op. |\n| Interactive multi-subnet home prompt answered no | No spawn, clean exit 0 | `cli.rs:2269-2281`; unrelated to broker dedup but another clean no-spawn endpoint-run path. |\n\n## What “create” does and does not promise today\n\n- **Documented promise:** CLI help in `cli.rs:359-360` and generated `docs-site/src/cli/reference.md:1869-1874` says “Mint a fresh session.” The picker also calls its outcome “fresh session” at `picker/model.rs:1002-1016`; shortcut generation always bakes `--create` for fresh runs at `picker/shortcut.rs:113-129`.\n- **Fresh broker PTY/session:** intended, but violated by CLI reattach/refuse and broker dedup.\n- **Fresh harness session/conversation:** core selects `[session.self]` and provides a new provisional id when a spawn occurs. Actual transcript/conversation freshness is adapter/harness-owned; manifests are opaque. Core should document this boundary rather than claim it erases harness history.\n- **Fresh endpoint identity:** not promised or implemented. Existing ids reuse the perch, immutable home, spool, tracked context, and bounded `sessions.log`.\n- **Fresh ledger:** not promised. `crates/spt-store/src/sessions.rs:1-17,26-91,99-180` makes the ledger bounded history across boot/clear/compact and only dedups an immediate same-session append. Create does not clear it. Successful bind should append the newly reported harness session as another Boot row.\n\n## Why perri’s command did nothing\n\nDirectly observed durable/runtime evidence:\n\n- `C:/Users/decid/AppData/Local/spt-core/owlery/perri/info.json` currently says `status:\"offline\"`, `rest_state:\"active\"`, `adapter:\"claude-spt:ccs\"`, `controllable:true`, and an old UUID `session_id`.\n- `.../perri/sessions.log` ends at ordinal 24 with `session_id:\"anchor-int-proof\"`, trigger `boot`, adapter `claude-spt:ccs`, timestamp `2026-07-16T10:27:26Z`.\n- `.../perri/resume.pid` contains `76408`.\n- `logs/daemon.stderr.log.1:934` first records `LIVENESS_RECONCILE_OFFLINE:perri`; later `.log.1:1026` and `:1305` record `WAKE_RESUME:perri ... anchor-int-proof`.\n- Current `logs/daemon.stderr.log:82,1335,2410,2733,2933` repeatedly records brokered sessions launched as `WAKE_RESUME:perri ... anchor-int-proof`; surrounding lines show each broker session/controller detaching and a later resume launching again.\n\nSource chain for those automatic sessions: `livehost.rs:199-204` sends every non-online live-agent perch to `resume_woken_endpoint`; `livehost.rs:304-405` reads the **stored** Active intent plus newest ledger row and launches `[session.resume]`; `livehost.rs:665-744` offlines a dead harness but does not clear rest intent; `livehost.rs:997-1048` runs liveness reconcile immediately before wake reconcile every tick. ADR-0033 lines 16-27 says stored Active is wake intent and reconcile performs the resume. The effective state contract in `resting.rs:210-240` says cold liveness must dominate stale intent, which this wake reader currently bypasses (Issue A).\n\n**[INFERENCE]** No exact argv/output from the latest perri create attempt survives. The logs prove that automatic wake-resume repeatedly made perri broker-live around the incident. If the command’s preflight landed during one of those live windows, `SessionProbe` returned true and the CLI took the direct reattach or exit-0 `ENDPOINT_ALREADY_LIVE` branch. If the session appeared after the preflight, the broker took the `SPAWN_DEDUP` ordinary-success branch. Both branches produce no fresh session. The preflight branch is the likelier direct path; the available logs do not prove which branch handled that exact invocation.\n\n## Recommended behavior matrix\n\nTreat broker session-table presence as the sole create-conflict authority. Stored `status`, stored rest intent, and ledger rows are not live-session proof.\n\n| Observed state | Recommended `--create` behavior |\n|---|---|\n| Broker-live, including an `unbound` perch | Reject atomically. Exit 1. Emit `ENDPOINT_CREATE_CONFLICT:<id>...`; no attach, no spawn, no mutation. |\n| Broker-live while disk says `offline` or rest says active/dormant/suspended | Same conflict. Broker-held PTY is authoritative warm state; disk disagreement must not permit a duplicate. |\n| Broker absent, disk is honestly offline/suspended | Spawn `[session.self]` with a new provisional id; normal success/attach behavior. Reuse endpoint identity and history. |\n| Broker absent, stored `rest_state=active` is stale | After Issue A is fixed to use effective state/liveness, do **not** auto-resume from stale intent. Explicit create is intentional and should spawn `[session.self]` fresh. |\n| Broker absent, ledger contains old/stale/resume-only rows | Ignore ledger for create. Spawn `[session.self]`; preserve old rows; append the newly bound harness id. |\n| Broker live plus stale ledger | Conflict based on broker; never use ledger to override the live conflict. |\n| Session exits between CLI preflight and broker request | Broker atomic operation decides. If gone at broker decision time, create may proceed; if still held/not yet reaped, conflict and the operator retries after reap. Never duplicate. |\n| Fresh create races wake-resume | Exactly one launch tree. If resume wins first, create gets a typed conflict; if create wins first, create succeeds and the reuse-mode wake dedups. No ordinary-success lie to the create caller. Issue A should independently prevent the stale-wake side of this race. |\n\nRecommended conflict contract:\n\n- **Exit:** `1` (runtime state conflict; not Clap/usage exit 2, and not success 0 because the requested freshness was not delivered).\n- **stderr:** stable machine prefix, e.g. `ENDPOINT_CREATE_CONFLICT:<id>: a live broker session already exists; no session was created. Attach with 'spt rc <id>'; end or suspend the live session before retrying --create.`\n- **stdout:** none.\n- **Forbidden on conflict:** no `ENDPOINT_RUN`, no `ENDPOINT_RUN_STARTED`, no automatic attach/view, no kill/replace, no skeleton/ledger/rest mutation.\n- **Default semantics:** because current help says create is the default, absence of `--resume` should use the same fresh-and-conflict behavior as explicit `--create`. If product instead wants omitted mode to mean “ensure/attach,” it must make that a documented third mode and reserve explicit `--create` for fresh-only; silently treating explicit and omitted flags differently without changing help is not acceptable.\n\n## Fix alternatives ranked by safety\n\n1. **Recommended — atomic broker `spawn-fresh` plus existing reuse spawn.** Add a distinct broker IPC operation or capability-gated policy with a typed conflict. Route explicit/implicit fresh CLI and genuinely fresh autostart through it; keep wake/resume on current reuse/single-flight `spawn`. Refactor broker spawn body so both policies share PTY creation and differ only at `WakeGate::AlreadyLive`/post-race outcome. A new kind is N-1 safe: an older broker returns unknown-kind/error loudly rather than silently ignoring a new field and reusing a session. This closes both CLI-preflight and TOCTOU/broker-dedup branches without adapter/manifest changes.\n2. **Acceptable but more protocol machinery — additive policy + mandatory disposition/capability handshake.** Add `ExistingSessionPolicy::{Reject,Reuse}` to `SpawnReq` and `SpawnDisposition::{Created,Reused}` to `Spawned`, but only if the client verifies broker support before relying on it and treats a missing disposition conservatively. Merely adding a serde-defaulted `fresh` field is unsafe because an N-1 live broker ignores unknown fields per `msg.rs:1-9` and still silently dedups.\n3. **Insufficient alone — CLI preflight returns exit 1 for fresh/live.** Very small source diff in `run_on_live_decision`, but leaves the check-then-spawn race and probe-error path; broker can still ordinary-ack an existing session and CLI can still print false success.\n4. **Semantically weak — keep idempotent reuse, rename/document as ensure-running.** Preserves duplicate safety but abandons the advertised fresh-session contract and conflicts with shortcuts/picker “Create new.” Only viable if a distinct fresh verb is added.\n5. **Reject — kill/replace the live session automatically.** A create flag must never destroy an active conversation/PTY. Replacement needs an explicit stop/suspend boundary and its own consent/lifecycle semantics.\n\n## Focused regression tests\n\n1. Extend `cli.rs` unit decision table (currently `run_on_live_never_duplicates`) to include request intent: fresh+live => `CreateConflict` for start/attach/view; resume/ensure+live retains its explicitly chosen behavior; no live => spawn.\n2. Replace/extend `crates/spt/tests/run_no_dup_session_e2e.rs` with `create_over_live_endpoint_conflicts_without_attach_or_spawn`: both `--create --start` and default attach form return 1, exact token present, no `ENDPOINT_RUN` pid, same one broker session/pid, and no control/view stamp change. Keep a separate resume/ensure test for idempotent reattach if that remains intended.\n3. Broker integration `fresh_spawn_rejects_existing_session_atomically`: seed one labeled live session, send fresh operation, receive typed conflict, retain exactly one session. Also assert legacy/reuse `KIND_SPAWN` still returns the existing sid.\n4. Broker race `two_concurrent_fresh_spawns_yield_one_created_one_conflict`: barrier-align two fresh requests; exactly one child/session, one `Spawned`, one conflict. Keep `wake_single_flight.rs` unchanged for two reuse-mode wakes => same sid.\n5. Mixed race `fresh_create_vs_resume_reuse_never_lies_or_duplicates`: one fresh request and one wake/resume request for one id; exactly one launch tree; fresh caller either proves Created or receives conflict, never ordinary Reused success.\n6. CLI/daemon E2E `create_conflict_uses_broker_truth_when_perch_says_offline_active`: disk fixture `status=offline, rest_state=active`, but seed a live broker session; create must conflict.\n7. CLI/daemon E2E `offline_create_ignores_stale_ledger_and_uses_self`: no broker session, existing perch with stale Active intent and `anchor-int-proof` ledger row; after Issue A fix, create invokes the self marker, not resume marker, gets a new harness id, preserves old history, and adds the new Boot row.\n8. IPC compatibility test: new client against old/unknown-kind broker gets a loud unsupported/error result, never `Created`; old client’s generic spawn remains accepted by new broker with reuse semantics.\n9. Clap/help snapshot: create+resume remains exit 2; help contains the conflict/default wording.\n\n## Required docs/help changes\n\n- `crates/spt/src/cli.rs` Run help and generated `docs-site/src/cli/reference.md`: replace unconditional “Mint a fresh session” with precise semantics: invokes `[session.self]`, preserves endpoint identity/history, and fails if a broker session exists; state whether omission is identical to create.\n- `CONTEXT.md:394-422` picker/run contract: add the atomic live-conflict rule and distinguish Create-new endpoint identity from fresh session on an existing id.\n- `docs/MANIFEST.md:138-160`: state that create selects `[session.self]`, resume selects `[session.resume]`; core’s fresh guarantee is invocation/session-id plumbing, while actual harness conversation freshness is the adapter command’s responsibility.\n- Broker protocol comments in `msg.rs`, `brain.rs`, `broker.rs`: name the two dispositions/policies and N-1 behavior; stop describing a universal labeled-spawn dedup gate as wake-only if it remains shared.\n- Picker/shortcut copy (`picker/model.rs:1002-1016`, `picker/shortcut.rs:113-129`): describe live conflict so generated shortcuts do not imply they replace/restart an already-live endpoint.\n- User-facing changelog: explicit create no longer silently reattaches/no-op-acks an existing broker session; it fails loud without disturbing the live endpoint.\n\nInvestigation was read-only. Per instruction, no tests/builds/project commands were executed; the cited existing tests document current behavior rather than a fresh run result.",
  "files": [
    {
      "path": "crates/spt/src/cli.rs",
      "description": "Clap Run definition (344-379); create flag discarded and target routed (1387-1418); resume/live decision models (1746-1798); direct target router (1817-1835); full create/resume/live/spawn/output flow (1884-2149); existing-perch skeleton reuse (2204-2327); current live-decision unit contract (2376-2390)."
    },
    {
      "path": "crates/spt/src/rc.rs",
      "description": "SessionProbe resolves endpoint liveness from the broker sessions table, independent of perch status/rest state (861-904)."
    },
    {
      "path": "crates/spt/src/picker/model.rs",
      "description": "Picker calls Create-new a fresh-session outcome and represents freshness only as resume=None (1002-1016); offline existing bringup also uses resume=None (1324-1365)."
    },
    {
      "path": "crates/spt/src/picker/mod.rs",
      "description": "Picker Outcome::Run converges on cmd_endpoint_run without an explicit create semantic (449-499)."
    },
    {
      "path": "crates/spt/src/picker/shortcut.rs",
      "description": "Generated shortcuts explicitly bake --create whenever no resume id is chosen (113-129, tests 206-248)."
    },
    {
      "path": "crates/spt-daemon/src/harnesshost.rs",
      "description": "Mints provisional ids, selects self vs resume manifest roles, fills opaque argv/env, and sends undifferentiated SpawnReq to broker (55-72, 77-208, 213-294)."
    },
    {
      "path": "crates/spt-runtime/src/manifest.rs",
      "description": "Defines [session.self], optional native [session.resume], and post-spawn vs UUID-injected harness identity semantics (225-252, 499-513)."
    },
    {
      "path": "docs/MANIFEST.md",
      "description": "Public native-resume contract and self fallback (138-160); needs explicit create/fresh responsibility boundary."
    },
    {
      "path": "crates/spt-daemon/src/msg.rs",
      "description": "Forward-compatible broker payload catalog; SpawnReq has no existing-session policy and Spawned has no Created/Reused disposition (1-9, 260-333)."
    },
    {
      "path": "crates/spt-daemon/src/brain.rs",
      "description": "spawn_session_pid accepts any Spawned reply as success and cannot distinguish broker creation from dedup reuse (447-487)."
    },
    {
      "path": "crates/spt-daemon/src/broker.rs",
      "description": "WakeGate and 2s single-flight policy (191-239); universal labeled-spawn dedup implementation returning ordinary Spawned(existing) (3235-3302); unit truth table (5875-5896)."
    },
    {
      "path": "crates/spt-daemon/src/autostart.rs",
      "description": "Autostart calls the same undifferentiated harness launch while claiming every replay is fresh (1-17, 67-112), another caller that needs an explicit policy decision."
    },
    {
      "path": "crates/spt-daemon/src/livehost.rs",
      "description": "Stale-Active automatic resume chain (199-204, 304-405), broker-liveness offline reconciliation that leaves rest intent untouched (665-744), and reconcile ordering (997-1048)."
    },
    {
      "path": "crates/spt-daemon/src/resting.rs",
      "description": "Canonical effective-state rule: cold liveness yields Suspended regardless of stored Active intent (210-240), relevant to preventing stale wake races with create."
    },
    {
      "path": "crates/spt-store/src/sessions.rs",
      "description": "Bounded persistent session history; create must ignore but preserve stale rows, and successful bind appends/dedups session boundaries (1-17, 26-91, 99-180)."
    },
    {
      "path": "crates/spt/tests/run_no_dup_session_e2e.rs",
      "description": "Existing real-broker test codifies current exit-0 already-live no-op for headless run/resume and no second session (1-24, 210-231, 275-319); primary test to update/extend."
    },
    {
      "path": "crates/spt-daemon/tests/wake_single_flight.rs",
      "description": "Existing broker race test proves two generic wake/reuse spawns return the same session; should remain as the reuse-policy guard while fresh gets separate conflict tests (1-28, 127-180)."
    },
    {
      "path": "crates/spt/tests/resume_template_e2e.rs",
      "description": "Existing end-to-end proof that no-resume selects [session.self] and resume selects [session.resume]; useful base for stale-ledger create coverage (1-12, 196-255, 335-363)."
    },
    {
      "path": "CONTEXT.md",
      "description": "User-facing run/picker contract (394-440), unbound broker-live semantics (670-671), and effective instance-state model; needs explicit fresh-conflict language."
    },
    {
      "path": "docs-site/src/cli/reference.md",
      "description": "Generated CLI reference currently repeats the unconditional fresh-session promise at 1869-1874."
    },
    {
      "path": "docs/adr/0033-wake-resume-via-reconcile-intent.md",
      "description": "Defines stored Active as wake intent and daemon reconcile as the resume actor (16-27), explaining the stale-wake/create race."
    },
    {
      "path": "C:/Users/decid/AppData/Local/spt-core/owlery/perri/info.json",
      "description": "Observed current state: offline status but active rest intent, claude-spt:ccs adapter, old bound session id."
    },
    {
      "path": "C:/Users/decid/AppData/Local/spt-core/owlery/perri/sessions.log",
      "description": "Observed durable ledger ending in ordinal 24 / anchor-int-proof, the stale resume source repeatedly selected by daemon reconcile."
    },
    {
      "path": "C:/Users/decid/AppData/Local/spt-core/logs/daemon.stderr.log",
      "description": "Observed repeated WAKE_RESUME:perri launches at lines 82, 1335, 2410, 2733, 2933 with intervening session detach evidence."
    },
    {
      "path": "C:/Users/decid/AppData/Local/spt-core/logs/daemon.stderr.log.1",
      "description": "Observed perri liveness-offline event at line 934 followed by wake-resume launches at 1026 and 1305."
    }
  ],
  "architecture": "Current flow: `EndpointCmd::Run` (Clap) -> `resolve_run_target` (adapter/id only) -> `cmd_endpoint_run` (`resume=None` means fresh; explicit create bit already lost) -> mint provisional/select manifest -> `SessionProbe` broker preflight -> either reattach/exit-0 no-op or `harnesshost::launch_harness_brokered_in` -> `Brain::spawn_session_pid(KIND_SPAWN)` -> `Broker::dispatch_spawn`. The broker’s endpoint-keyed `wake_inflight` gate is the final concurrency authority, but it currently has one universal Reuse outcome: already-live sends the same `Spawned` shape as a new PTY spawn. That collapses two different commands—fresh creation and idempotent wake/resume—into one result.\n\nRecommended architecture: preserve a single shared broker spawn body and single endpoint-keyed claim, but introduce an explicit operation-level existing-session policy at the broker boundary. `Fresh/RejectExisting` is used by explicit/implicit create and genuinely fresh autostart; `ResumeOrReuse` is used by daemon wake/restart resume. At `AlreadyLive`, Fresh returns a typed conflict and Resume returns the existing-session ack. A concurrent claimant waits under the same gate, then receives the policy-appropriate result. Prefer a distinct forward-compatible `KIND_SPAWN_FRESH` so an older stable broker fails loud rather than silently ignoring a new field. CLI preflight remains a UX fast path only; broker response is authoritative. Neither disk `status`, stored rest intent, nor `sessions.log` participates in the live-conflict decision. The separate lifecycle correction must make wake reconcile use effective state/liveness so stale `rest_state=active` cannot continually manufacture resume contenders."
}