Files
HologramAgent-DSH-Memory-Port/test
jianf 73a0a6b8d0 test(memory): pin D1 — a corrupt vector cannot take the recall path down (D1)
D1 was the one item on the coverage list with genuinely no criterion. Measured by
mutation, not by grepping test names:

    corrupt vector handling: skip -> throw
    phase-b-h 137/137 green, phase-b-a 38/38 green, recall-accounting 5/5 green
    -> 145 criteria, zero red

That is decision §0.4 unguarded: "the vector side failing must not take the main
path down". One bad row would cost the whole turn its memory, and nothing noticed.

## The same probe found three items that ARE covered

Recorded because the parent's coverage matrix derived "zero hits" from grepping
criteria IDs against test names, and three of those were false negatives — the
criteria exist, they are just named after their subject rather than their ID:

    C6  centroid partitioned by fingerprint   loadCentroid ignoring it -> 3 red
                                              (ticket②, ticket②-strong, W8)
    W1  exec.signal reaches embedText         dropping it -> 2 red (W5, W9c)
    F1  fingerprint from provider info()      deriving locally -> 5 red

So the matrix under-reports as well as over-reports. Only mutation distinguishes
"labelled" from "enforced".

## What the criterion does

Writes a corrupt payload straight into the row and requires the recall to survive:

    store.raw().prepare('UPDATE memory_blocks SET vector = ? WHERE id = ?')
      .run('["a","b","c","d"]', broken.id)   // right length, non-numeric elements

Two guards narrowed what "corrupt" can mean, both measured and documented in the
criterion:

  · DDL enforces `json_valid(vector)` — a syntactically broken payload is refused
    outright (`ERR_SQLITE_ERROR: malformed JSON`), so it cannot reach the read path;
  · a trigger re-derives `vector_dim`, so a wrong-LENGTH payload is filtered in SQL
    before scoring sees it.

An array of the right length with non-numeric elements clears both and still cannot
be scored — which is exactly what a provider that changed its encoding, or a
migration that stringified values, would leave behind.

Assertions: no throw, the healthy neighbour is still recalled, and the bad row is
counted in `skippedUnscoreable` (D1's other half is D2's rule: skipping silently is
the same defect).

Mutation — a non-numeric component throws instead of skipping:

    not ok 6 - D1: a corrupt vector payload cannot take the recall path down
    error: D1: a single corrupt vector payload threw out of the recall path
           (M-D1: non-numeric vector component). Decision §0.4: ...

Gates: npm test 304/304 (0 skipped), npm run check 12/12.
2026-11-05 12:13:17 +08:00
..