# DIFF-FIX — neg-corpus d01/d02/d03 differential repin (corpus v1.2.1)

Date: 2026-10-05. Author: ARION worker subagent (AI-authored).

## Symptom

`lua5.4 run_negcorpus.lua` reported **70/73** with three failing
differential cases:

- `d01-id-trailing-newline` — emitted `core :: id is not a lowercase UUID`
  in loose mode; manifest `expect_loose` was `[]`
- `d02-offset-min-60` — emitted `core :: created_at is not a valid
  calendar date/time` in loose mode; manifest `expect_loose` was `[]`
- `d03-prov-trailing-newline` — emitted `core :: provenance_class is not
  a known class` in loose mode; manifest `expect_loose` was `[]`

(The strict legs already matched: `strictDiff` was empty on all three.)

## Root cause — stale oracle, not a port bug

The manifest's `expect_loose: []` legs froze the **pre-fix** kit's
leniencies (trailing-newline tolerance in the id/provenance patterns,
`+10:60` offset normalization). They were generated against
`/tmp/zambo @ ad09360` and deliberately retained in corpus v1.2.0 as a
record of pre-fix behavior (see REBASE-109.md).

Evidence the pins were stale rather than the port being wrong:

1. `node ../neg-corpus/run.js` (canonical `verify.js`) failed the same
   three cases with **byte-identical** emitted reasons — Lua matched the
   reference verifier exactly.
2. The shipped `kit-snapshot/aer-1/conformance.js` `check()` — which
   post-dates the vendor's fix — emits the same three reasons on the
   same vectors: `id is not a lowercase UUID`,
   `created_at is not a valid calendar date/time`,
   `provenance_class is not a known class`. So the `expect_loose: []`
   pins described a kit snapshot that isn't in the repo at all.

The manifest is a *self-oracle generated by* `generate.js`
(`expect_loose`/`expect_strict` are snapshots of observed output), so
the honest fix was to repin the three legs to the reference behavior —
not to weaken `aer1verify.lua`, which was already correct.

## What changed

- `neg-corpus/generate.js` — d01/d02/d03 `addDiff` legs `"pass"` →
  `"fail"` (the generator's self-oracle guard would otherwise refuse to
  emit), spec strings rewritten to describe the fixed behavior;
  `corpus_version` bumped to `1.2.1` with a `rebase_v121` metadata block
  recording the repin.
- `neg-corpus/manifest.json` — regenerated via
  `node generate.js ../kit-snapshot`. Diff vs v1.2.0: only the three
  `expect_loose` sets, their `spec` strings, version, and timestamp
  changed. **All 73 vector files are byte-identical**
  (`diff -r` verified).
- `neg-corpus/README.md`, `neg-corpus/REBASE-109.md` — updated the
  differentials/status prose that still claimed the `expect_loose: []`
  pins were current.
- `lua/run_negcorpus.lua` — default corpus path `../../neg-corpus` →
  `../neg-corpus` (the corpus is a sibling of `lua/`; the old default
  resolved to a nonexistent `deliverables/neg-corpus` and crashed on a
  bare invocation).
- `lua/results.txt` — recaptured; `lua/LUA-PORT.md` and
  `lua/EXPECTED.md` — "Expected results" updated to 73/73.

**Not changed:** `aer1verify.lua` verifier logic — zero diff; it already
emitted verify.js's exact `{check, reason}` pairs. `verify.js` itself is
untouched.

Note on semantics: d01 remains a true differential — loose and strict
reject with *different* reasons (`lowercase UUID` vs `UUID v4`). d02/d03
now pin identical reasons in both legs; they still serve as regression
tripwires for the fixed-kit behavior.

## Verification

| command | result |
|---|---|
| `cd lua && lua5.4 run_negcorpus.lua` (bare and `../neg-corpus`) | **73/73 conform**, exit 0 |
| `cd neg-corpus && node run.js` | **73/73 conform**, exit 0 |
| `lua5.4 aer1verify.lua --selftest` | all ok, exit 0 |
| `lua5.4 aer1verify.lua ../kit-snapshot/aer-1/test-vectors` | CONFORMANCE: **7/30** (unchanged), exit 1 |
| `lua5.4 aer1verify.lua ../kit-snapshot/aer-1/frozen-vectors/v1.3.0` | CONFORMANCE: **5/18** (unchanged), exit 1 |
| `node generate.js ../kit-snapshot` re-run | regenerates identically; self-oracle passes |
