{
  "summary": "One recorded UserPromptSubmit produced two distinct helper receipts. Source reveals a concrete dual-report contract mismatch: state submits verbatim prompt bytes, now-signal submits trimmed/capped text, while core deduplicates by exact payload SHA-256. The incident input ends in LF, so these two source paths produce different keys. This strongly explains the records, but retained evidence does not bind either receipt ID to its report payload/callsite; definitive incident attribution remains STOP-AND-REFER.",
  "files": [
    {
      "path": "C:/Users/decid/AppData/Local/spt-core/owlery/webbie/helper-fetch.jsonl:1-2",
      "description": "Two helper records with full UUIDs, identical path/URL, 107ms apart."
    },
    {
      "path": "C:/Users/decid/AppData/Local/spt-core/owlery/webbie/io-events.log:160",
      "description": "USER_INPUT at 1790027897608; exact payload includes trailing LF after pasted_content closing tag."
    },
    {
      "path": "C:/Users/decid/AppData/Local/spt-core/adapters/_github/SaberMage-claude-spt/hook-trace.log:680-681",
      "description": "Single UPS begin/completion pair, PID 47736, with busy/poll/now-signal stage timings."
    },
    {
      "path": "C:/Users/decid/Documents/projects/spt-claude-code/tools/claude-spt/src/hook.rs:3187,3271-3276,4039-4055,4086-4090,4114-4145",
      "description": "Adapter source reports original prompt via state stdin, then trimmed/capped prompt via now-signal argv."
    },
    {
      "path": ".worktrees/317-quoted-span-paths/crates/spt/src/api/mod.rs:648-661,775-789",
      "description": "Both NowSignal and authenticated State USER_INPUT independently call report_user_input."
    },
    {
      "path": ".worktrees/317-quoted-span-paths/crates/spt/src/api/nowsignal.rs:1085-1150",
      "description": "One report transport invocation per caller; report carries endpoint/session/payload, without a shared turn identifier."
    },
    {
      "path": ".worktrees/317-quoted-span-paths/crates/spt-daemon/src/inputreceipt.rs:28-94,127-193",
      "description": "In-memory receipt book keys session plus exact payload digest, mints UUID, rejects repeat replies, copies original receipt UUID into helper record."
    },
    {
      "path": ".worktrees/317-quoted-span-paths/crates/spt-daemon/src/broker.rs:9023-9121",
      "description": "Receipt admission and reply completion; helper append occurs after locked completion."
    },
    {
      "path": ".worktrees/317-quoted-span-paths/crates/spt/src/rc.rs:3108-3150",
      "description": "Owner registration/reply preserves request receipt ID rather than minting a second ID."
    }
  ],
  "architecture": "Adapter UPS → state busy and now-signal → common core input report → broker-session ReceiptBook keyed by (session, SHA256(exact payload)) → controller owner registration → receipt-bound reply → helper-fetch append. Display dedupe is separate from receipt admission.",
  "report": "## Evidence chain\n\nHome containing the exact incident records: `C:/Users/decid/AppData/Local/spt-core`. This matches Windows default resolution in `crates/spt-store/src/perch.rs:24-54` (SPT_HOME override first, then LOCALAPPDATA/spt-core). I did not execute an environment query; finding the exact supplied UUID/time pair establishes the relevant store rather than assuming a default directory is authoritative.\n\n1. `owlery/webbie/helper-fetch.jsonl:1`: msg_id `3919de80-fa8b-4240-bbd4-8d0257413ad0`, at_ms `1790027897746`.\n2. Same file, line 2: msg_id `774ce64c-be6d-49c2-9321-8ade7fbc1106`, at_ms `1790027897853`.\n3. Both records: path `C:\\Users\\decid\\Pictures\\image.png`; URL `http://localhost:5474/enlyzeam/f/image.png`. Difference: 107ms.\n4. `owlery/webbie/io-events.log:160`: USER_INPUT at `1790027897608`, payload `how about a path without a space? \\n\\n<pasted_content id=\"9af8\">\\n\"C:\\Users\\decid\\Pictures\\image.png\"\\n</pasted_content id=\"9af8\">\\n`. The last LF is retained, not an inferred formatting artifact.\n5. Registered adapter `adapters/claude-spt/record.toml:1-7` points to `adapters/_github/SaberMage-claude-spt`, registration `1790027422600`. Its `hook-trace.log:680-681` records ONE matching UserPromptSubmit: PID `47736`, begin `1790027897584`, completion `1790027897748`, total 163ms, busy 26ms, poll 76ms, now-signal 60ms. No second matching UPS invocation appears in the incident-window search. The second helper completion occurs after the hook returns; broker owner replies are asynchronous, so this does not establish another invocation.\n6. `logs/daemon.stderr.log:1668-1669`, between timestamped neighbors at `1790027896858` and `1790027900950`, has two identical declines for webbie path `/pasted_content`, reason `INPUT_PATH_INVALID`. They carry no receipt ID or timestamp of their own, so they support two processing results but cannot assign either UUID.\n\n## Source-level finding\n\nThe adapter source available locally is `C:/Users/decid/Documents/projects/spt-claude-code/tools/claude-spt/src/hook.rs`:\n- `3187`: UPS calls report_busy_with_input with original prompt and sid.\n- `4114-4120`: user_input_payload checks a trimmed view for eligibility but returns `prompt.to_string()` unchanged.\n- `4130-4145`: state busy receives that payload on stdin; fallback is payload-free, not a second payload report.\n- `3271-3276`: the same UPS sends now_signal_arg(prompt) to now_signal_poll with the same sid.\n- `4086-4090`: now_signal_arg is `text.trim().chars().take(4000).collect()`.\n- `4039-4055`: now-signal passes that transformed string as --user-input. Exact authored-text tracing is opt-in; the relevant trace has no captured authored-text payload.\n\nCore `api/mod.rs:658` reports the now-signal argument; `784-786` reports the state payload. `delivery.rs:51-69` and `cli.rs:9051-9054` preserve state stdin bytes. `nowsignal.rs:1099-1149` does not normalize the payload and invokes its FnOnce sender once; `brain.rs:2335-2351` sends one report frame with no retry loop around send.\n\n`inputreceipt.rs:61-67` deduplicates `(session, SHA256(payload.as_bytes()))`, not extracted path/URL or shared turn ID. For the recorded short payload, original and now-signal versions differ by the final LF, hence differ as dedupe inputs. `77` mints a fresh UUID on each admission. This is a demonstrable contract mismatch in the inspected sources, not evidence of two user prompts.\n\n## What is ruled out or bounded\n\n- Same-receipt owner reply replay cannot mint the second UUID in the inspected implementation: owner reply preserves request.receipt_id (`rc.rs:3150`); completion rejects answered receipts (`inputreceipt.rs:143-145`), and helper msg_id is the stored request UUID (`170-175`). Broker holds the book lock across completion (`broker.rs:9098-9102`).\n- A single reply cannot legitimately duplicate one requested path: exact path/result multiplicity is checked (`inputreceipt.rs:146-154`).\n- Distinct helper UUIDs are consistent with two admitted reports. No retained record maps either UUID to a session, payload digest, originating CLI verb/PID, or admission time. ReceiptBook is in memory and has no successful-admission audit in the inspected path.\n- The local adapter checkout is source evidence, not an attestation of the deployed executable's exact build. Installed manifest reports 0.41.2; no build/source correspondence was proven.\n- Exact-ID searches found no matching receipt audit in current daemon stderr. Initial searches of the large rotated stderr/effect logs were limited by the search tool's first-4MB limit; do not cite them as exhaustive absence. Effect-log sampled records are operation bookkeeping, not report payload custody. No receipt/audit-named file was found by narrow then broader filename discovery. No owner node was contacted or its registration changed.\n\n## Ownership / smallest supported correction\n\nCore owns the integration assumption that both callsites provide identical authoritative bytes; the adapter deliberately documents now-signal as trimmed/capped scan text, unlike state payload content. Therefore indiscriminately treating both as the same receipt source is a core integration concern, not proof that an adapter hook fired twice. The smallest incident-specific change to investigate is avoiding a second authoritative receipt report from a lossy scan-text channel when the exact state-ingest path already owns that report. However, removing now-signal reporting may affect other adapters, and changing dedupe to trim or path-only would change semantics. Neither is justified as an unconditional patch by this investigation alone.\n\nThe separately requested emitted-line dedupe can prevent duplicate display but does NOT repair duplicate receipt admission.\n\n**STOP-AND-REFER for definitive historical attribution:** missing evidence is receipt-ID → endpoint/session/payload digest/reporting callsite mapping, plus deployed adapter/core source identity. With those absent, report the source-level dual-report/trim mismatch as a supported explanation, not a proven ID-by-ID historical cause. No speculative source edits, builds, tests, prompts, injections, registration mutations, or other validation commands were performed."
}
