[object Object]

← back to Homesonspec

TK-11125: e2e-proof evidence bundle for the payload guard (R3, scratch DB)

6a1800df962c433f1bdfd9da06955e68c47b40eb · 2026-09-02 13:53:14 -0700 · Steve Abrams

Verdict PASS. 5 data-boundary cases + unit tests, all green on
homesonspec_test. Records the no-migration design divergence + gates
respected (no prod write/deploy/push).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016JRL7REtkaBnRrfHk42iYm

Files touched

Diff

commit 6a1800df962c433f1bdfd9da06955e68c47b40eb
Author: Steve Abrams <steve@designerwallcoverings.com>
Date:   Wed Sep 2 13:53:14 2026 -0700

    TK-11125: e2e-proof evidence bundle for the payload guard (R3, scratch DB)
    
    Verdict PASS. 5 data-boundary cases + unit tests, all green on
    homesonspec_test. Records the no-migration design divergence + gates
    respected (no prod write/deploy/push).
    
    Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_016JRL7REtkaBnRrfHk42iYm
---
 verification/TK-11125-payload-guard-e2e-proof.json | 89 ++++++++++++++++++++++
 1 file changed, 89 insertions(+)

diff --git a/verification/TK-11125-payload-guard-e2e-proof.json b/verification/TK-11125-payload-guard-e2e-proof.json
new file mode 100644
index 00000000..c3dab7b4
--- /dev/null
+++ b/verification/TK-11125-payload-guard-e2e-proof.json
@@ -0,0 +1,89 @@
+{
+  "ticket": "TK-11125",
+  "parentTicket": "TK-10878",
+  "intent": "Forward-only guard that skips minting a spurious StagedRecord generation + SourceEvidence set when a new raw snapshot carries byte-identical extracted property data (only volatile page bytes changed). History-preserving, no deletion, no schema migration.",
+  "spec": ".claude/yolo-queue/verification/TK-10878/TK-11125-impl-spec-2026-09-02.md",
+  "riskTier": "R3 (local user-facing data-pipeline flow; data-layer boundary). Prod deploy separately GATED — not performed here.",
+  "environment": {
+    "machine": "Mac2 (local)",
+    "node": "v26.4.0",
+    "database": "homesonspec_test (scratch; harness refuses any non-*_test DB)",
+    "prodDbTouched": false
+  },
+  "build": {
+    "repo": "/Users/macstudio3/Projects/homesonspec",
+    "branch": "master",
+    "headCommit": "319168ad20f88b70ecd2db7ad06d9a191a02a298",
+    "commits": [
+      "671fbb26 TK-11125: add stableStringify + payloadHash canonical hash helper (shared)",
+      "319168ad TK-11125: forward-only spurious-generation guard in extractStage"
+    ]
+  },
+  "timestamp": "2026-09-02T20:52:33Z",
+  "designDivergenceFromSpec": {
+    "spec": "Add a nullable column StagedRecord.payloadHash to persist the hash.",
+    "implemented": "NO column, NO migration. StagedRecord.payload already stores normalized.fields verbatim (schema.prisma:449), so the latest generation's payloadHash is recomputed on read via one findFirst(orderBy createdAt desc) using the existing @@index([canonicalKey]).",
+    "why": "Honors the hard 'no migrations' task constraint, is pure-code reversible, matches the spec's exact semantics sha256(stableStringify(normalized.fields)), and works on all 170M existing rows immediately (no NULL-first-miss). The column was a read-avoidance optimization; the data is already present.",
+    "safety": "Guard skips ONLY when the latest generation is a DIFFERENT (prior) snapshot AND its canonical payload hash equals the new one. Any canonical-form difference (incl. a float reformat through JSONB) falls through to create a generation = current behavior. The guard can therefore only ever SKIP an exact duplicate, never suppress a real change (no history loss possible).",
+    "sameSnapshotReextract": "latest.snapshotId !== snapshotId escape preserves today's FORCE_REEXTRACT update-in-place semantics."
+  },
+  "baseline": "Working tree clean on master @ c97856c6 before work; existing integration suite 7/7 green pre-change.",
+  "commandsRun": [
+    "pnpm --filter @homesonspec/shared test  (32 passed, incl. 11 new payload-hash unit tests)",
+    "pnpm --filter @homesonspec/shared typecheck  (clean)",
+    "pnpm --filter @homesonspec/workers typecheck  (clean)",
+    "pnpm --filter @homesonspec/workers test:integration  (12 passed: 7 baseline + 5 new guard cases)"
+  ],
+  "assertions": [
+    {
+      "boundary": "unit (pure hash)",
+      "check": "stableStringify is key-order independent across a JSONB round-trip; a real field change / changed provenance envelope yields a different payloadHash; 64-char sha256 hex.",
+      "verdict": "PASS"
+    },
+    {
+      "boundary": "data (StagedRecord + SourceEvidence)",
+      "case": "4a — brand-new home",
+      "check": "1 StagedRecord generation + 2 SourceEvidence rows.",
+      "verdict": "PASS"
+    },
+    {
+      "boundary": "data (StagedRecord + SourceEvidence)",
+      "case": "2 — new snapshot, byte-identical fields (THE FIX)",
+      "check": "extractStage returns 0 stagedIds; generation count stays 1; NO fresh evidence set minted. (Pre-fix this was 1 new generation.)",
+      "verdict": "PASS"
+    },
+    {
+      "boundary": "data (StagedRecord + SourceEvidence)",
+      "case": "3 — new snapshot, real field change (phone changed)",
+      "check": "exactly 1 new generation (count 1 -> 2); evidence 2 -> 4. History preserved.",
+      "verdict": "PASS"
+    },
+    {
+      "boundary": "data (StagedRecord)",
+      "case": "2b — re-seeing settled data on yet another snapshot",
+      "check": "0 new generations (no drift once data settles).",
+      "verdict": "PASS"
+    },
+    {
+      "boundary": "data (StagedRecord + SourceEvidence)",
+      "case": "4b — FORCE_REEXTRACT same snapshot adding a field",
+      "check": "same row updated in place (returned id == latest.id), no new generation; evidence replaced to 3 rows. FORCE_REEXTRACT backfill semantics preserved.",
+      "verdict": "PASS"
+    }
+  ],
+  "negativeChecks": [
+    "Guard never skips a real change — proven by case 3 (real change -> new generation) and the unit test 'gives a DIFFERENT hash for a real field change'.",
+    "Fail-safe direction: any hash mismatch (including provenance-envelope-only changes) falls through to create a generation."
+  ],
+  "cleanup": "Integration test cleans only its own (canonicalKey-scoped) rows in beforeAll and co-exists with the existing pipeline.itest; scratch DB only, no prod state changed.",
+  "gatesRespected": [
+    "No production DB writes or migrations (recompute-from-payload => zero schema change).",
+    "No deletes / pruning / history collapse.",
+    "No deploy / restart.",
+    "No external actions, no remote push.",
+    "Prod deploy remains separately GATED (spec Gate section) — awaiting Steve GO."
+  ],
+  "verdict": "PASS",
+  "status": "complete (local); prod deploy GATED",
+  "safestNextAction": "Parent (iterm-tk10878-readonly-v2) independently inspects the diff + reruns test:integration; then draft the prod-deploy memo to pending-approval for Steve's GO (deploy = pipeline runs via tsx on source; no migration to apply)."
+}

← 319168ad TK-11125: forward-only spurious-generation guard in extractS  ·  back to Homesonspec  ·  HoS mobile: block GTM/GA4/Facebook trackers in Browse WebVie 9e884ed1 →