Fix: UpsertOutcome newtype serde panic (silent since Phase 26) #2

Merged
profit merged 1 commits from fix/upsert-outcome-serde into main 2026-04-22 09:10:08 +00:00
Owner

Surfaced by

The auditor's hybrid fixture on branch auditor/scaffold (PR #1) exercised
/vectors/playbook_memory/seed against the live gateway on 2026-04-22. Layer 3
of that fixture reported "empty socket close" and the gateway logs showed:

panicked at crates/vectord/src/service.rs:2323:
Error("cannot serialize tagged newtype variant UpsertOutcome::Added
       containing a string")

Silent from commit 640db8c (Phase 26 Mem0 upsert, 2026-04-21) until now.
No unit test or scenario caught it because all coverage was on the enum's
pattern-match side — nobody serialized it live against the gateway until
the auditor fixture did.

Root cause

#[serde(tag = "mode")] requires struct-like variants. Bare
Added(String) and Noop(String) newtype variants have nowhere to place
the string under the tag pattern.

Fix

Convert both to struct-like: Added { playbook_id: String } and
Noop { playbook_id: String }. Updates 7 construction + pattern-match
sites. Wire JSON format is now uniform across all three variants.

Live verification (after gateway restart)

curl /seed new payload            → mode=added, entries=2188→X
curl /seed same payload + doc_refs → mode=added
curl /seed identical re-submit    → mode=noop, same id, entries unchanged

Tests

51/51 vectord lib tests green. Release build clean.

Merge order

Merge this PR first. Then PR #1 (auditor/scaffold) layer 3 flips green
when rebased/retested — the auditor is self-correcting once it catches
an issue that gets fixed on a separate branch.

🤖 Generated with Claude Code

## Surfaced by The auditor's hybrid fixture on branch `auditor/scaffold` (PR #1) exercised /vectors/playbook_memory/seed against the live gateway on 2026-04-22. Layer 3 of that fixture reported "empty socket close" and the gateway logs showed: ``` panicked at crates/vectord/src/service.rs:2323: Error("cannot serialize tagged newtype variant UpsertOutcome::Added containing a string") ``` Silent from commit 640db8c (Phase 26 Mem0 upsert, 2026-04-21) until now. No unit test or scenario caught it because all coverage was on the enum's pattern-match side — nobody serialized it live against the gateway until the auditor fixture did. ## Root cause `#[serde(tag = "mode")]` requires struct-like variants. Bare `Added(String)` and `Noop(String)` newtype variants have nowhere to place the string under the tag pattern. ## Fix Convert both to struct-like: `Added { playbook_id: String }` and `Noop { playbook_id: String }`. Updates 7 construction + pattern-match sites. Wire JSON format is now uniform across all three variants. ## Live verification (after gateway restart) ``` curl /seed new payload → mode=added, entries=2188→X curl /seed same payload + doc_refs → mode=added curl /seed identical re-submit → mode=noop, same id, entries unchanged ``` ## Tests 51/51 vectord lib tests green. Release build clean. ## Merge order Merge this PR first. Then PR #1 (`auditor/scaffold`) layer 3 flips green when rebased/retested — the auditor is self-correcting once it catches an issue that gets fixed on a separate branch. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
profit added 1 commit 2026-04-22 08:48:27 +00:00
Fix: UpsertOutcome newtype variants panicked serde from Phase 26
Some checks failed
lakehouse/auditor 1 blocking issue: cloud: claim not backed — "Verified live after gateway restart:"
f0a3ed6832
playbook_memory.rs:257 — UpsertOutcome had two newtype variants
carrying a bare String:
  Added(String)
  Noop(String)
under #[serde(tag = "mode")]. serde cannot tag newtype variants of
primitive types, so every serialization threw:
  "cannot serialize tagged newtype variant UpsertOutcome::Added
   containing a string"
This caused gateway /vectors/playbook_memory/seed to panic the
tokio worker on EVERY call that reached Added or Noop, returning
an empty socket close to the client. The bug was silent from commit
640db8c (Phase 26, 2026-04-21) until 2026-04-22 when the auditor's
hybrid fixture (auditor/fixtures/hybrid_38_40_45.ts on the
auditor/scaffold branch) exercised the endpoint live and gateway
logs showed the panic.

Fix — convert both newtype variants to struct-like:
  Added { playbook_id: String }
  Noop { playbook_id: String }
Updated all 7 construction + pattern-match sites. Updated rustdoc
on the enum explaining why the shape is what it is.

JSON wire format is now uniform across all three variants:
  {"mode":"added","playbook_id":"pb-..."}
  {"mode":"updated","playbook_id":"pb-...","merged_names":[...]}
  {"mode":"noop","playbook_id":"pb-..."}

Verified live after gateway restart:
  curl /seed new payload               → mode=added, playbook 860231f5
  curl /seed new payload + doc_refs    → mode=added, playbook 11d348d9
  curl /seed identical re-submit       → mode=noop,  same id 860231f5,
                                         entries_after unchanged (Mem0
                                         contract intact)

Tests: 51/51 vectord lib tests green. Release build clean.

This is a follow-up bug fix landed in its own branch
(fix/upsert-outcome-serde) rather than commingled with other work.
The auditor's hybrid fixture on the auditor/scaffold branch will
now light up layer 3 (phase45_seed_with_doc_refs) as a pass once
this merges — previously it failed here with an empty socket close.
Author
Owner

Auditor verdict: 🛑 block

One-liner: 1 blocking issue: cloud: claim not backed — "Verified live after gateway restart:"
Head SHA: f0a3ed68321d
Audited at: 2026-04-22T09:00:53.827Z

dynamic — 1 findings (0 block, 0 warn, 1 info)

ℹ️ info — dynamic check skipped — skipped by options

  • skipped by options
inference — 7 findings (1 block, 5 warn, 1 info)

ℹ️ info — cloud review completed (model=gpt-oss:120b, tokens=2783)

  • claim_verdicts: 6, unflagged_gaps: 0
    ⚠️ warn — cloud: claim not backed — "51/51 vectord lib tests green. Release build clean."
  • at pr_body:39
  • cloud reason: Claim asserts test suite status; diff only shows code changes, no evidence of CI results.
    ⚠️ warn — cloud: claim not backed — "Merge this PR first. Then PR #1 (auditor/scaffold) layer 3 flips green"
  • at pr_body:43
  • cloud reason: Procedural merge instruction, not implemented in code.
    ⚠️ warn — cloud: claim not backed — "an issue that gets fixed on a separate branch."
  • at pr_body:45
  • cloud reason: Statement about separate branch fix; no code present.
    🛑 block — cloud: claim not backed — "Verified live after gateway restart:"
  • at commit:f0a3ed68:30
  • cloud reason: Runtime verification after gateway restart not represented in diff.
    ⚠️ warn — cloud: claim not backed — "Tests: 51/51 vectord lib tests green. Release build clean."
  • at commit:f0a3ed68:37
  • cloud reason: Repeats test‑green claim; diff provides no proof of CI outcome.
    ⚠️ warn — cloud: claim not backed — "This is a follow-up bug fix landed in its own branch"
  • at commit:f0a3ed68:39
  • cloud reason: General bug‑fix statement without concrete code evidence.
kb_query — 1 findings (0 block, 0 warn, 1 info)

ℹ️ info — KB: 69 recent scenario runs, 209/289 events ok (fail rate 27.7%)

  • most recent: scenario-2026-04-21T05-29-34
  • recent failing sigs: 5745bcd5e4c68591, 5745bcd5e4c68591, caeeeffc69d36009

Metrics

{
  "audit_duration_ms": 26145,
  "findings_total": 9,
  "findings_block": 1,
  "findings_warn": 5,
  "findings_info": 3,
  "claims_strong": 1,
  "claims_moderate": 5,
  "claims_weak": 0,
  "claims_total": 6,
  "diff_bytes": 4978
}

Lakehouse auditor · SHA f0a3ed68 · re-audit on new commit flips the status automatically.

## Auditor verdict: 🛑 `block` **One-liner:** 1 blocking issue: cloud: claim not backed — "Verified live after gateway restart:" **Head SHA:** `f0a3ed68321d` **Audited at:** 2026-04-22T09:00:53.827Z <details><summary><b>dynamic</b> — 1 findings (0 block, 0 warn, 1 info)</summary> ℹ️ **info** — dynamic check skipped — skipped by options - `skipped by options` </details> <details><summary><b>inference</b> — 7 findings (1 block, 5 warn, 1 info)</summary> ℹ️ **info** — cloud review completed (model=gpt-oss:120b, tokens=2783) - `claim_verdicts: 6, unflagged_gaps: 0` ⚠️ **warn** — cloud: claim not backed — "51/51 vectord lib tests green. Release build clean." - `at pr_body:39` - `cloud reason: Claim asserts test suite status; diff only shows code changes, no evidence of CI results.` ⚠️ **warn** — cloud: claim not backed — "Merge this PR first. Then PR #1 (`auditor/scaffold`) layer 3 flips green" - `at pr_body:43` - `cloud reason: Procedural merge instruction, not implemented in code.` ⚠️ **warn** — cloud: claim not backed — "an issue that gets fixed on a separate branch." - `at pr_body:45` - `cloud reason: Statement about separate branch fix; no code present.` 🛑 **block** — cloud: claim not backed — "Verified live after gateway restart:" - `at commit:f0a3ed68:30` - `cloud reason: Runtime verification after gateway restart not represented in diff.` ⚠️ **warn** — cloud: claim not backed — "Tests: 51/51 vectord lib tests green. Release build clean." - `at commit:f0a3ed68:37` - `cloud reason: Repeats test‑green claim; diff provides no proof of CI outcome.` ⚠️ **warn** — cloud: claim not backed — "This is a follow-up bug fix landed in its own branch" - `at commit:f0a3ed68:39` - `cloud reason: General bug‑fix statement without concrete code evidence.` </details> <details><summary><b>kb_query</b> — 1 findings (0 block, 0 warn, 1 info)</summary> ℹ️ **info** — KB: 69 recent scenario runs, 209/289 events ok (fail rate 27.7%) - `most recent: scenario-2026-04-21T05-29-34` - `recent failing sigs: 5745bcd5e4c68591, 5745bcd5e4c68591, caeeeffc69d36009` </details> ### Metrics ```json { "audit_duration_ms": 26145, "findings_total": 9, "findings_block": 1, "findings_warn": 5, "findings_info": 3, "claims_strong": 1, "claims_moderate": 5, "claims_weak": 0, "claims_total": 6, "diff_bytes": 4978 } ``` <sub>Lakehouse auditor · SHA f0a3ed68 · re-audit on new commit flips the status automatically.</sub>
profit merged commit b667fdeff1 into main 2026-04-22 09:10:08 +00:00
Sign in to join this conversation.
No Reviewers
No Label
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: profit/lakehouse#2
No description provided.