{
  "summary": "## Verdict\n\n`perri` is not configured to resume by a saved startup default. Its current durable state is instead contaminated in a way that makes the daemon’s independent wake/reconcile path deterministically choose native resume:\n\n- `perri` is an offline, spt-hosted `live_agent` whose durable rest intent is still `active`.\n- The newest row in its session ledger is the non-UUID test value `anchor-int-proof`.\n- The adapter’s own current-session carrier also contains `anchor-int-proof`.\n- The actual endpoint record currently contains a different session ID, `79205491-82f2-4a1b-9294-af25c1c963f9`.\n- The daemon wake-resume implementation ignores `info.json.session_id` for selection and reads exactly the newest `sessions.log` row. Current daemon logs show it repeatedly selecting `anchor-int-proof` and spawning `[session.resume]` under `claude-spt:ccs`.\n- There is no `anchor-int-proof.jsonl` in the configured CCS transcript tree. The newest real transcript for the recorded project is `c1427211-6e8d-4571-aeb8-30d36fa816a6.jsonl`.\n\n## Exact observed durable state\n\nState root is the Windows default `C:\\Users\\decid\\AppData\\Local\\spt-core`, as defined by `spt_store::perch::spt_home()`.\n\n### Endpoint record\n\n`owlery/perri/info.json` currently contains:\n\n- `id`: `perri`\n- `state`: `live_agent`\n- `status`: `offline`\n- `rest_state`: `active`\n- `adapter`: `claude-spt:ccs`\n- `cwd`: `C:\\Users\\decid\\Documents\\projects\\omp-spt`\n- `session_id`: `79205491-82f2-4a1b-9294-af25c1c963f9`\n- `pid`: `47752`\n- `parent_pid`: `55836`\n- `controllable`: `true`\n- `controlled`: `false`\n- `home_subnet`: `SPT_DEV`\n- captured `read_env.CLAUDE_CONFIG_DIR`: `C:\\Users\\decid\\.ccs\\instances\\bigscreen`\n- `last_active_ms`: `1784211191867`\n\nThe materialized project index agrees on the current project head: project ID `github-com-bigscreenvr-omp-spt`, display `omp-spt`, directory `C:\\Users\\decid\\Documents\\projects\\omp-spt`. Its recorded project history is, newest first: `omp-spt`, `claude-spt-bs` (`...\\spt-claude-code\\tools\\claude-spt`), `projects`, then a context-only `github-com-sabermage-claude-spt` reference.\n\n### Adapter/profile\n\nRegistry record `adapters/claude-spt/record.toml` says:\n\n- active: `true`\n- kind: `harness`\n- mode: `pointer`\n- source: `C:\\Users\\decid\\AppData\\Local\\spt-core\\adapters\\_github\\SaberMage-claude-spt`\n- registered at ms: `1784199962215`\n\nThe active source manifest is version `0.24.1`, minimum core `0.27.0`. `:ccs` is a shipped sparse overlay. The resolved launch roles are:\n\n- Fresh/self: `{adapter_dir}/claude-spt launch --cli ccs --id {id} --node {node}`\n- Resume: `{adapter_dir}/claude-spt launch --cli ccs --id {id} --resume {session_id} --node {node}`\n\nThe adapter launch shim turns those into native CCS/Claude arguments:\n\n- fresh: no `-r`; it emits `-n <display> --remote-control <name> --dangerously-skip-permissions`\n- resume: prefixes `-r <session_id>` before the same naming/permission arguments\n\nThus any wake selection of `anchor-int-proof` reaches CCS as native `-r anchor-int-proof`.\n\n### Saved startup mode\n\n`daemon.json` has only two `startup_endpoints`: `mobile-gw` and `lia`. `perri` is absent. Therefore:\n\n- `perri` has no saved `endpoint run --save` startup default.\n- Even if it did, startup defaults do not save a resume mode or session ID; the schema stores only `{id, adapter, cwd}` and `autostart.rs` always mints a fresh session with `is_resume=false`.\n- `rest_state:\"active\"` is separate durable wake intent, not a startup-default mode. That active intent is what currently enables daemon wake-resume while `status` is offline.\n\n### Session ledger/history\n\n`sessions.log` has 25 valid rows, ordinals 0–24. In order, the recorded IDs are:\n\n0. `d5b46b36-ff77-4131-a774-17f6caa2ff35`\n1. `6db151cc-515e-4fdf-8fe7-9f98697b588b`\n2. `4c5e8257-ef66-4c12-a154-a6f83bdab25a`\n3. `13712404-60aa-4dc9-957b-9e854ac0f73d`\n4. `efdcbb37-8805-4cc2-9d17-ecc2f85984ce`\n5. `6ea67f9d-c88a-454a-b88a-a0e4add41ba8`\n6. `bdc2d185-002c-43fb-9aa7-953755172bb8`\n7. `0841835d-f331-4ec7-abcd-af2ba0217cd0`\n8. `9f809150-e92c-474b-8ff6-ee237b441071`\n9. `57495b6e-3f65-40bd-b9b7-a7177ccb8a8d`\n10. `3a9e5d72-e4e3-4661-a30a-eb6d97f38fb9`\n11. `175d35a3-4eca-4ac8-8885-261f29f277ef`\n12. `0fe6cad5-3efb-4ced-8031-d9a41e22ff81`\n13. `0c476962-db50-49a2-851c-8f4a14e85a36`\n14. `5c76a64f-45cd-41c9-952e-158341e9ca7d`\n15. `0c476962-db50-49a2-851c-8f4a14e85a36`\n16. `26c49822-00bc-4abe-8be2-91f44b9e4fea`\n17. `ecd15339-2c75-4e4c-ba1a-2c25bd437233`\n18. `5377b23a-8a93-4a9a-8cd2-73d2c26c87b6`\n19. `b8f52b79-a26c-444b-bf0e-f3734d431e69`\n20. `ecd15339-2c75-4e4c-ba1a-2c25bd437233`\n21. `b4fe0587-e19f-4b78-81a8-c97931c52126`\n22. `058dcb6f-1586-47a0-a0cd-0a4a085881ca`\n23. `c1427211-6e8d-4571-aeb8-30d36fa816a6`\n24. `anchor-int-proof`\n\nThe newest row is exactly:\n\n`{\"ts\":\"2026-07-16T10:27:26Z\",\"session_id\":\"anchor-int-proof\",\"trigger\":\"boot\",\"cwd\":\"C:\\\\Users\\\\decid\\\\Documents\\\\projects\\\\omp-spt\",\"ordinal\":24,\"adapter\":\"claude-spt:ccs\"}`\n\nDuplicate metadata exists, but only in older rows:\n\n- `0c476962-db50-49a2-851c-8f4a14e85a36` appears at ordinals 13 and 15.\n- `ecd15339-2c75-4e4c-ba1a-2c25bd437233` appears at ordinals 17 and 20.\n\nThose duplicates do not currently select resume because both daemon wake/restart selection paths call `sessions::last_k(perch, 1)` and use only ordinal 24. `sessions::append` deduplicates only an immediate repeat, so a repeated ID separated by another row is intentionally retained.\n\nAdditional session metadata:\n\n- adapter carrier `state/session/perri.sid`: `anchor-int-proof`\n- `owlery/perri/resume.pid`: `76408`\n- endpoint `info.json.session_id`: `79205491-82f2-4a1b-9294-af25c1c963f9`\n- nested Psyche custody ID: `173e4ace-62c0-4983-9af6-ef8a58cdc896` (separate Psyche state; not a Self-resume selector)\n\nThe `resume.pid` matches the PID in the latest observed `WAKE_RESUME` log entry, but this read-only investigation did not query current process liveness. Its present alive/dead status is therefore unobserved.\n\n## Exact contamination provenance\n\nThis is not merely a hypothetical stale row. The real CCS transcript `c1427211-6e8d-4571-aeb8-30d36fa816a6.jsonl`, lines 583–584, records a field test executed from the live `perri` Claude session at `2026-07-16T10:27:26`:\n\n`printf '%s' '{\"session_id\":\"anchor-int-proof\",\"source\":\"startup\"}' | ...\\claude-spt.exe hook SessionStart --host-pid 1`\n\nThe test’s purpose was to prove native Windows host-anchor self-resolution under real `claude.exe` ancestry. Because it ran inside the actual perched session, it inherited `SPT_ENDPOINT_ID=perri`. Adapter `handle_session_start` maps `source=startup` plus a present endpoint ID to the strict `bind` branch, uses the prior carrier as proof, and then persists the supplied SID after successful registration. The ledger row timestamp exactly matches that invocation. The fake SID therefore became both the latest core ledger row and the adapter carrier. No `anchor-int-proof` transcript exists in `C:\\Users\\decid\\.ccs\\instances\\bigscreen\\projects`, confirming it was a test token, not a real Claude conversation ID.\n\n## What the state predicts\n\n### Explicit `spt endpoint run --id perri --create`\n\nAt CLI dispatch, `--create` is deliberately not threaded further; its semantic meaning is simply the absence of `--resume`. Because `perri` already exists, the recorded adapter makes this a direct run under `claude-spt:ccs`. If the CLI actually wins the spawn decision, it:\n\n1. mints a fresh spt-core provisional spawn ID;\n2. sets `is_resume=false`;\n3. selects resolved `[profiles.ccs.session.self]`;\n4. launches CCS without `-r`;\n5. uses the invocation’s current directory, because a fresh direct run does not consult `info.cwd`.\n\nSo `--create` itself predicts fresh Claude Code startup, not the resume picker.\n\nHowever, `--create` does not clear `sessions.log`, does not invalidate `anchor-int-proof`, and does not neutralize `rest_state=active`. The daemon’s wake reconciler is independently eligible while the record is offline. If that reconciler wins first, it launches `[session.resume]` for `anchor-int-proof`; the CLI’s live-session guard then reattaches (default attach) or reports already live (`--start`) instead of spawning a second harness. This is the credible reason an operator can request/create a fresh launch yet encounter the native resume path: the resume did not come from `--create`; it came from the already-armed daemon wake path and stale ledger head.\n\n### Picker/default launch\n\nFor offline local `perri`, the picker exposes two distinct actions:\n\n- **Start now**: `resume=None`, resolved current adapter `claude-spt:ccs`, fresh `[session.self]` — no `-r`.\n- **Resume from history**: explicitly selects a ledger row; the first/default history row is `anchor-int-proof`, carries cwd `...\\omp-spt` and adapter `claude-spt:ccs`, and produces native `-r anchor-int-proof`.\n\nBecause `perri` has multiple project-history references, Start-now first enters the Choose-project screen. Its newest project choice is `omp-spt`; selecting it still remains fresh (`resume=None`). A bare direct `endpoint run --id perri` without the picker is also fresh, but lands in the invoking shell’s cwd.\n\nAgain, the active daemon reconciler can race either fresh UI path. Current logs prove this is not theoretical: `daemon.stderr.log` repeatedly contains, including its latest observed occurrence:\n\n`WAKE_RESUME:perri: resuming session anchor-int-proof under claude-spt:ccs (pid 76408) — online at bind`\n\nEarlier occurrences used PIDs `58672`, `60448`, `3504`, and `74216`; rotated log `.1` also records PIDs `60016` and `48600`. The repeated launches occur because the cold/offline + active-intent condition remains and the fake ledger head never changes to a successful real bind.\n\n## Non-destructive read surfaces\n\nSafe read-only commands for future confirmation, without launching/attaching/stopping an endpoint, are:\n\n- `spt api endpoint-info perri` — committed JSON endpoint identity/adapter/cwd/project surface; explicitly read-only and unauthenticated.\n- `spt endpoint list --json --show-all --detail` — roster/status/project view.\n- `spt adapter list --json` and `spt adapter version claude-spt:ccs` — active registry/profile version.\n- `spt daemon status --json` — daemon/node read view.\n- PowerShell `Get-Content` on `info.json`, `sessions.log`, `daemon.json`, `record.toml`, `state\\session\\perri.sid`, and daemon logs for fields not exposed by one CLI read DTO.\n\nThere is no dedicated public read verb for the complete per-endpoint session ledger; picker history is the UI projection, while `sessions.log` is the exact durable source.\n\n## Safe shadow-endpoint repro plan (not executed)\n\nUse an isolated state universe so neither `perri` nor the production broker/daemon namespace is touched:\n\n1. Choose a unique temporary root, e.g. `SPT_HOME=$env:TEMP\\spt-perri-shadow-<nonce>`. Socket/pipe names derive from `SPT_HOME`, so this creates an isolated daemon/broker universe.\n2. Register the existing active adapter source into that isolated home only: `C:\\Users\\decid\\AppData\\Local\\spt-core\\adapters\\_github\\SaberMage-claude-spt`. Never copy `owlery\\perri`, its API token, spool, carrier, or `resume.pid`.\n3. Use a unique endpoint such as `perri-shadow-<nonce>` and an innocuous trusted test cwd.\n4. Control A: launch that shadow with explicit `--create --start`; capture the manifest/adapter argv or screen. Expected: resolved CCS self role, no `--resume` in the adapter invocation and no native `-r` in CCS argv.\n5. After the shadow has a genuine ledger row, run the same SessionStart field probe only from inside the shadow session, with a unique fake SID such as `shadow-anchor-<nonce>`. Confirm, by reading only the shadow files, that this fake value becomes the newest shadow `sessions.log` row and shadow adapter carrier. This recreates the exact contamination mechanism without involving `perri`.\n6. Confirm there is no corresponding fake transcript under the shadow’s CCS project root.\n7. Let only the shadow become offline while retaining `rest_state=active`. On the isolated daemon’s reconcile, expect `WAKE_RESUME:perri-shadow-<nonce>: resuming session shadow-anchor-<nonce> under claude-spt:ccs` and native CCS `-r shadow-anchor-<nonce>` behavior.\n8. Control B: repeat with a second clean shadow whose latest ledger row is a real UUID, or whose start uses fresh/self; it must not pass `-r` unless Resume-from-history is explicitly chosen.\n9. Destroy only the temporary `SPT_HOME` after evidence capture. Do not issue any lifecycle command against `perri`.\n\nFor an even narrower deterministic core seam before the real-CC shadow, seed an isolated fixture ledger whose final row is the fake SID and exercise `livehost::decide_resume`/`launch_ledger_resume` with a command-capturing mock manifest: assert that active+offline chooses the final row and `is_resume=true`, while CLI/picker fresh passes `resume=None` and selects `[session.self]`.",
  "files": [
    {
      "path": "C:/Users/decid/AppData/Local/spt-core/owlery/perri/info.json",
      "description": "Authoritative current endpoint record: offline live_agent, rest_state active, adapter claude-spt:ccs, omp-spt cwd, current bound SID 79205491…, CCS bigscreen config root."
    },
    {
      "path": "C:/Users/decid/AppData/Local/spt-core/owlery/perri/sessions.log",
      "description": "25-row durable session ledger. Newest selector is fake `anchor-int-proof`; contains two older non-adjacent duplicate IDs."
    },
    {
      "path": "C:/Users/decid/AppData/Local/spt-core/owlery/perri/resume.pid",
      "description": "Wake/restart resume custody PID file; currently `76408`, matching the latest observed WAKE_RESUME launch log."
    },
    {
      "path": "C:/Users/decid/AppData/Local/spt-core/daemon.json",
      "description": "Saved startup defaults. Contains only mobile-gw and lia; proves perri is not startup-saved."
    },
    {
      "path": "C:/Users/decid/AppData/Local/spt-core/index/project-index.json",
      "description": "Materialized project view: perri latest is omp-spt, with four recorded project references used by picker project choice."
    },
    {
      "path": "C:/Users/decid/AppData/Local/spt-core/adapters/claude-spt/record.toml",
      "description": "Active pointer registry record for claude-spt and exact source directory."
    },
    {
      "path": "C:/Users/decid/AppData/Local/spt-core/adapters/_github/SaberMage-claude-spt/manifest.toml",
      "description": "Installed adapter v0.24.1 manifest. Defines base and ccs self/resume roles; ccs resume passes `--resume {session_id}`."
    },
    {
      "path": "C:/Users/decid/AppData/Local/spt-core/adapters/_github/SaberMage-claude-spt/state/session/perri.sid",
      "description": "Adapter-owned prior/current-session auth carrier; currently contaminated with `anchor-int-proof`."
    },
    {
      "path": "C:/Users/decid/AppData/Local/spt-core/logs/daemon.stderr.log",
      "description": "Current daemon evidence of repeated `WAKE_RESUME:perri` selecting `anchor-int-proof`; latest observed spawn PID 76408."
    },
    {
      "path": "C:/Users/decid/AppData/Local/spt-core/logs/daemon.stderr.log.1",
      "description": "Rotated daemon evidence showing the same stale-head resume across earlier daemon/reconcile cycles."
    },
    {
      "path": "C:/Users/decid/.ccs/instances/bigscreen/projects/C--Users-decid-Documents-projects-omp-spt/c1427211-6e8d-4571-aeb8-30d36fa816a6.jsonl",
      "description": "Real perri transcript and exact provenance: lines 583–584 ran installed SessionStart with fake `anchor-int-proof` under perri’s actual Claude ancestry at the ledger row timestamp."
    },
    {
      "path": "C:/Users/decid/Documents/projects/spt-claude-code/tools/claude-spt/src/hook.rs",
      "description": "Adapter SessionStart logic: startup+SPT_ENDPOINT_ID selects strict bind, then successful registration persists the supplied SID carrier."
    },
    {
      "path": "C:/Users/decid/Documents/projects/spt-claude-code/tools/claude-spt/src/launch.rs",
      "description": "Launch shim argument mapping: resume emits native `-r <sid>`; fresh omits it."
    },
    {
      "path": "crates/spt-store/src/perch.rs",
      "description": "Canonical SPT_HOME resolution: Windows default `%LOCALAPPDATA%\\spt-core`."
    },
    {
      "path": "crates/spt-store/src/sessions.rs",
      "description": "Ledger schema/order/cap and append semantics; last_k is oldest→newest tail and only immediate repeats are deduped."
    },
    {
      "path": "crates/spt/src/cli.rs",
      "description": "CLI routing and create/resume semantics: create is absence of resume, explicit existing ID reuses recorded adapter, fresh uses current cwd, resume resolution uses ledger only for provisional recovery."
    },
    {
      "path": "crates/spt/src/picker/data.rs",
      "description": "Offline-local resume rows come from sessions.log newest-first; each row carries its own adapter and cwd."
    },
    {
      "path": "crates/spt/src/picker/model.rs",
      "description": "Picker Start produces resume=None; Resume-from-history produces the selected session ID, recorded adapter, and cwd."
    },
    {
      "path": "crates/spt/src/picker/mod.rs",
      "description": "Single picker dispatch into cmd_endpoint_run and pre-spawn recorded-adapter restamp for explicit history resume."
    },
    {
      "path": "crates/spt-daemon/src/config.rs",
      "description": "StartupEndpoint schema stores id/adapter/cwd only and explicitly defines replay as always fresh."
    },
    {
      "path": "crates/spt-daemon/src/autostart.rs",
      "description": "Daemon startup replay mints a new session and calls launch with is_resume=false; unrelated to perri’s current resume symptom."
    },
    {
      "path": "crates/spt-daemon/src/livehost.rs",
      "description": "Root selection seam: active rest intent + offline state reads newest ledger row, prefers its recorded adapter, and calls the manifest resume role with is_resume=true."
    },
    {
      "path": "crates/spt-runtime/src/registry.rs",
      "description": "Profile resolution merges shipped `profiles.ccs` over the active parent manifest."
    },
    {
      "path": "crates/spt/src/api/reporting.rs",
      "description": "Read-only `api endpoint-info` JSON surface and exact fields it exposes."
    }
  ],
  "architecture": "There are three distinct durable-state planes, and conflating them explains the symptom. (1) `daemon.json.startup_endpoints` is an opt-in replay list and is always fresh; perri is not in it. (2) the perch `info.json` is the current endpoint snapshot, including current adapter/cwd/session and durable rest intent. Its `rest_state=active` tells daemon reconciliation that an offline endpoint should be brought back. (3) `sessions.log` is the ordered, hook-authored harness history. Both daemon wake-resume and daemon-restart survival select `last_k(perch, 1)`, taking that row’s session ID, adapter, and cwd; they do not select `info.json.session_id` and do not validate that a matching native transcript exists. For perri, plane (2) arms wake while plane (3) points to `anchor-int-proof`. The resolved profile then changes only the command leaf: ccs self omits resume, ccs resume forwards it to the launch shim, which emits native `ccs -r anchor-int-proof`. The picker is a separate explicit decision layer: Start produces no resume and Resume-from-history chooses a ledger row. The daemon reconciler runs independently, so an already-armed stale wake can win before a requested fresh launch; the broker’s anti-duplicate guard then causes the manual path to attach/refuse instead of replacing that resume. The fake ledger head was introduced by a SessionStart hook field test executed inside the real perri session, not by the picker or startup defaults."
}