From 90c68faa25d9df748c822c88a87ccf2453fb25c6 Mon Sep 17 00:00:00 2001 From: Moheeb Zara Date: Sat, 1 Aug 2026 21:31:34 -0700 Subject: [PATCH] fix(door): correct parseHeatSyncLog stale time + token reuse (L5) (a) Reset h/mi/e after each event so a later event with no H:M:E of its own no longer inherits the previous event's time-of-day (fabricated audit timestamp + dedupeKey). (b) Track consumed high-half token indices so one g/d token can no longer be paired with two adjacent grants (wrong reconstructed card numbers). Co-Authored-By: Claude Opus 4.8 (1M context) --- __tests__/door-log-logic.test.ts | Bin 6339 -> 7563 bytes lib/door-log-logic.ts | 8 +++++++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/__tests__/door-log-logic.test.ts b/__tests__/door-log-logic.test.ts index 2981b69b43c0c1eddde9b996757d4348819091fb..a512088ceac7e7d802ff277a80c792a5a622858b 100644 GIT binary patch delta 855 zcmZWnJCD;q5LOOOkxohhCr$zhX$nvhP#h=0iSY3dF9iuWDAEy%jXklK*t^m0Iwl3m z51{lPIf<5zf|5T(!FZiZ#L@V%^X<&{n4i6Gr{}*LZ;t@DX*ENM8iX{!MU09YV6arU z;xf~KD-;F{Pq8ECosg}erBI{M@Vfi1`wEt*DokkRn-wiSeRE%xFNG zV#t|6D$Qk*$Xu6@)PZM^(6NF@F=2=oK(`AyH!%^j<3Y}etOl72NHcBV?EM53W*Y5~ zIak_TuVythxDS2T^WA|{{J7d}OvTuTp*t0k4{lLAcu}0!Pl~&TA8rBQmn8L;`i9^8lC zy+MC89KmCt_o!dUgF74hWgW433<=iX!G@mqz%AD{(_BPQj?QJ4gpeyKBHF}=uMo;R g|F#~K4qw`UfT{2-OJ}IsPL)X6z2<)Z)%bJt7jr=ic>n+a delta 12 TcmeCSK5V$*Jn!b|LSMK5CF%vC diff --git a/lib/door-log-logic.ts b/lib/door-log-logic.ts index 15c471b..db3a155 100644 --- a/lib/door-log-logic.ts +++ b/lib/door-log-logic.ts @@ -75,6 +75,9 @@ export function parseHeatSyncLog(text: string, opts?: { maxEvents?: number }): D let h: number | null = null let mi: number | null = null let e: number | null = null + // High-half tokens already paired to a low half. Each g/d belongs to exactly + // one grant/deny, so a consumed index must not be borrowed by a later event. + const usedHi = new Set() for (let i = 0; i < toks.length && events.length < max; i++) { const t = toks[i] if (t.key === 'H') { h = t.val; continue } @@ -89,7 +92,7 @@ export function parseHeatSyncLog(text: string, opts?: { maxEvents?: number }): D // pairing a G with a distant unrelated g when this event's half is missing. let hiTok: Tok | undefined for (let j = i + 1; j < toks.length && j <= i + 3; j++) { - if (toks[j].key === hiKey) { hiTok = toks[j]; break } + if (toks[j].key === hiKey && !usedHi.has(j)) { hiTok = toks[j]; usedHi.add(j); break } } const low = t.val >= 0 ? BigInt(t.val) : 0n const high = hiTok && hiTok.val >= 0 ? BigInt(hiTok.val) : 0n @@ -105,6 +108,9 @@ export function parseHeatSyncLog(text: string, opts?: { maxEvents?: number }): D detail: tod ? `${result} card #${cardNumber} at ${tod}` : `${result} card #${cardNumber}`, dedupeKey: `hs:${t.slot}:${t.key}:${cardNumber}:${tod ?? ''}`, }) + // Time-of-day applies only to the event it immediately preceded; clear it so + // a later event without its own H/M/E does not inherit a stale timestamp. + h = mi = e = null } return events }