{
  "summary": "#311 is a confirmed source-level information-loss bug in the shortform mint→dispatch-result path, not evidence that #223’s sealed-send fix regressed. #223 covered `spt send --seal`; the separate `;;`/now-signal path shipped afterward. No commands, validation, or edits performed.",
  "files": [
    {
      "path": "crates/spt/src/sealverb.rs:133-150,189-205,209-283",
      "description": "mint_outcome already returns the real daemon token; record_shortform_outcome discards it by accepting only admitted: bool and reason. Four recording callsites require migration."
    },
    {
      "path": "crates/spt-store/src/dispatchresults.rs:52-109,119-153,232-304",
      "description": "Persisted DispatchStatus::SealMinted is a unit variant; JSONL reader skips invalid rows. Existing seal/mixed-stream fixtures and historical serialization constraint."
    },
    {
      "path": "crates/spt/src/api/nowsignal.rs:843-873",
      "description": "gather_dispatch_results renders success as bare 'seal minted'; per-session seen identity is ordinal@timestamp."
    },
    {
      "path": "crates/spt/src/api/delivery.rs:293-318,357-390,473-499",
      "description": "Ingest parses closed passages and launches detached seal mint --from-shortform with stdout/stderr discarded; results file is deliberately the author’s only confirmation."
    },
    {
      "path": "crates/spt-daemon/src/broker.rs:7457-7532,7895-7910,15755-15901,16034-16200,16362-16420",
      "description": "Authoritative persisted mint and requester token reply; real ceremony/controller/TOTP and FIDO2 test fixtures."
    },
    {
      "path": "crates/spt/tests/seal_shortform_e2e.rs:53-150",
      "description": "Existing real-binary shortform fixture covers refusal only, not successful token exposure; current setup lacks home_subnet and may refuse before attempting a ceremony."
    },
    {
      "path": "crates/spt/tests/now_signal_delta_e2e.rs:77-195",
      "description": "Useful real ingest→now-signal consumer surface and same-session delta fixture."
    },
    {
      "path": "crates/spt/tests/midturn_span_e2e.rs:306-308",
      "description": "Existing SealMinted pattern must change if success becomes a payload variant."
    },
    {
      "path": "crates/spt/src/api/seal.rs:329-376,401-414",
      "description": "Actual consumer verification: exact content hash first, mint-trim fallback second, FIDO2 signature checks, SEAL_BOUND exit 0."
    },
    {
      "path": "crates/spt/src/cli.rs:11381-11400",
      "description": "Separate #223 seal_answer helper documents and implements sealed-send token suffix; not called by shortform mint."
    },
    {
      "path": "CHANGELOG.md:418-478",
      "description": "Chronology: v0.63.0 sealed-send token fix on August 25; v0.64.0 shortform and now-signal added August 27."
    }
  ],
  "architecture": "IO-compliant api state payload → parse_seal_mints → detached spt seal mint --from-shortform → Brain::seal_ceremony → broker-authenticated ceremony + durable SealStore → token-bearing SealCeremonyReply → mint_outcome → lossy status recording → per-endpoint JSONL → gather_dispatch_results → author’s DISPATCH_RESULTS.",
  "report": "ROOT CAUSE — HIGH CERTAINTY\nThe lost value is `reply.token`, already surfaced as `out` by `mint_outcome` (sealverb.rs:133-150,269). Broker mint saves SealStore before returning Some(record.token) (broker.rs:7499-7530); end_ceremony forwards it to the requester (7895-7910), and Brain::seal_ceremony preserves it (brain.rs:689-720). cmd_seal_mint then reduces the outcome to `record_shortform_outcome(&minter, code == 0, &reply.outcome)` (276). That recorder constructs a tokenless unit SealMinted (195). stdout still prints the token (278-279), but launch_detached_mint explicitly nulls stdout and stderr (delivery.rs:379-388). Persistence therefore cannot retain it, and nowsignal.rs:862 can render only `seal minted`. This is data loss before rendering, not merely missing formatting.\n\n#223 VERSUS #311 — HIGH CONFIDENCE UNCOVERED ARM; NOT A PROVEN REGRESSION\nhttps://github.com/BigscreenVR/spt-bs-releases/issues/223 explicitly scopes plain foreground `printf body | spt send doyle --seal`. Its August 25 gate comment identifies afed25fc, SENT/QUEUED/DEFERRED suffixes, and removal of the admitted overlay notice; field acceptance observed SENT:lia seal=f9zw2d2a4e. Current cli.rs:11381-11400 independently corroborates that exact seam. CHANGELOG.md:418-478 and traceable-reqs.toml:7538-7556 date shortform/dispatch vocabulary to August 27, after #223’s August 25 delivery. Thus #223 did not cover this later arm. https://github.com/BigscreenVR/spt-bs-releases/issues/311 accurately leaves open 'back or never covered'; source/history evidence favors never covered. Direct GitHub HTML and API reads of afed25fc both returned 404, so the actual historical patch was unavailable; do not claim commit-diff proof or absolute never-worked history.\n\nMINIMAL CHANGE SEAM / COMPLETE REFERENCE SET\nKeep existing ceremony, detached execution, persistence location, poll channel and verification untouched. Carry the existing successful token through record_shortform_outcome into durable result data, then render e.g. `-> (seal): seal minted seal=<token>`. Change the recorder’s boolean contract to an explicit typed success/refusal status so success cannot silently discard its payload; migrate all four callsites at sealverb.rs:238,254,264,276. The three early refusal names stay exactly as owned today; final ceremony refusals retain reply.outcome unchanged. Preserve standalone mint’s bare-token stdout.\nA payload-bearing DispatchStatus::SealMinted is the natural typed model. All literal references found across the repository are: declaration dispatchresults.rs:74; production constructor sealverb.rs:195; renderer nowsignal.rs:862; store fixtures dispatchresults.rs:244,262,291; negative match midturn_span_e2e.rs:307. Other enum arms need no semantic changes. SealCeremonyReply, BrokerEvent::SealCeremonyDone, SendVerdict, and CeremonyPurpose already express their required facts and need no token expansion.\nIMPORTANT PERSISTENCE COMPATIBILITY: current serde encoding of the unit success is `\"status\":\"seal_minted\"`. Naively replacing it with a struct variant breaks old rows, which read_all_at silently drops (dispatchresults.rs:149-153). Dropping an old row also changes later ordinals used by the now-signal seen key (nowsignal.rs:851-855), potentially replaying unrelated results. Preserve reading historical rows explicitly and render them honestly tokenless; do not fabricate/recover a token by latest-seal lookup. A required-token new success representation therefore needs a narrowly scoped persisted legacy decode policy. If minimum wire disruption is preferred, an additive optional token on DispatchResult preserves the existing enum serialization and old readers, but entails migrating all DispatchResult constructors and permits irrelevant token/status combinations; it is a tradeoff, not necessary scope. Pick one durable representation, migrate all live callers, retain only historical-data compatibility—not a parallel API. Update wax-seal.md:40-51/frame contract and applicable REQ-IO-DISPATCH-RESULT-VOCABULARY evidence with the chosen observable result; no seal-list command.\n\nREGRESSION SEAM THAT PROVES THE REQUEST\nUse real closed `;;decision text;;` ingest and a real admitted daemon ceremony; after the detached child records, invoke the actual now-signal consumer and extract the token from DISPATCH_RESULTS ONLY. Feed that extracted token plus the ceremony content to actual `spt api seal verify`: require SEAL_BOUND and exit 0; changed content must produce SEAL_NOT_BOUND/nonzero. This catches producer loss, durable-schema loss, renderer omission/wrong token, and a fake/unbound citation. A second poll in the same session must not re-emit it. An existing legacy success row before a new token-bearing row is a useful persistence-boundary case. Neither comparing copied fields nor injecting a hand-built token-bearing status proves the original failure fixed.\nUseful parts to combine: seal_shortform_e2e.rs supplies compliant manifest, real api state payload and detached-child wait/reap; now_signal_delta_e2e.rs supplies real poll/delta assertions and prestarting daemon before synthetic perch; broker.rs supplies provision_seal_subnet, capable controller socket/open ceremony flow, presented-code handling, and FIDO2 admission fixture. Broker fixtures are private to daemon unit tests, so not directly callable by the spt integration fixture: reuse their setup pattern, not a production test bypass. Existing shortform fixture is NOT success coverage: it creates InfoJson without home_subnet and accepts any nonempty refusal, so it may terminate at SEAL_SUBNET_UNRESOLVED despite its no-controller narrative. Configure a real anchor/subnet and capable controller for the success case; preserve a separate genuine no-surface refusal boundary. If end-to-end controller driving is unavailable, state that limitation rather than presenting a mocked ceremony reply as successful ceremony proof.\n\nAUTHORITY / NON-EXPANSION\nToken is a citation/evidence identifier, never authorization (wax-seal.md:16-19; CONTEXT.md:1160-1161). No gate should branch on its presence. Human-presence verification, attempt ledger, persisted mint and content remain daemon-owned; transport only the already issued token. Binding subnet remains the verification audience; do not mix in cross-node trust issue #298. Current verification hashes exact bytes first and then tries mint-compatible trim (api/seal.rs:329-376); FIDO2 additionally verifies its signature. Preserve that real contract, rather than asserting outdated 'only byte-exact' comments. Keep refusal text/outcome authority unchanged, including nonadmitted replies; do not synthesize a new authorization claim or restore admitted PTY residue removed by #223. No LSP tool was available; references were exhaustively located with repository grep. All findings are read-only source/history analysis, not runtime validation."
}