Archilyzer · Source

archilyzer

Archilyzer
git clone https://archilyzer.pages.dev/source/archilyzer.git
Log | Files | Refs | README | LICENSE

commit 4920e7b459fb9a62ee978dabadb53e2e5a67232f
parent 319e9370383dad6caa89e7ccd3495069f251d7f4
Author: I Mean I'm Just Saying <imeanimjustsaying@kiwifarms.st>
Date:   Tue, 22 Sep 2026 13:26:04 -0400

tags: the assignment-only re-apply destructured a bare key

With `values: false` lmdb-js yields keys, not {key, value}; the fake DB in
the tests ignored the option, so the first assignment-only build on the
real corpus was the first to run that line. The scan is key-only by
convention now, like recencyIndex.ts, and the fake yields bare keys under
`values: false` so the existing assignment test would catch a relapse.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

Diffstat:
Mcommon/controller/curatedTagsIndex.test.ts | 13++++++++++++-
Mcommon/controller/curatedTagsIndex.ts | 5++++-
2 files changed, 16 insertions(+), 2 deletions(-)

diff --git a/common/controller/curatedTagsIndex.test.ts b/common/controller/curatedTagsIndex.test.ts @@ -35,7 +35,18 @@ function makeDb<V>() { put(key: unknown, value: V): void { map.set(k(key), { key, value }); }, - getRange(options?: { start?: unknown[] }): Iterable<{ key: unknown; value: V }> { + // Mirrors lmdb-js: `values: false` yields BARE keys, not {key, value} — + // a caller that destructures {key} under that option must fail here too. + getRange(options?: { start?: unknown[]; values?: boolean }): Iterable<{ key: unknown; value: V }> { + if (options?.values === false) { + return this.getRangeBareKeys(options) as unknown as Iterable<{ key: unknown; value: V }>; + } + return this.getRangeEntries(options); + }, + *getRangeBareKeys(options?: { start?: unknown[] }): Iterable<unknown> { + for (const e of this.getRangeEntries(options)) yield e.key; + }, + getRangeEntries(options?: { start?: unknown[] }): Iterable<{ key: unknown; value: V }> { const start = options?.start as string[] | undefined; const all = Array.from(map.values()).sort((a, b) => k(a.key) < k(b.key) ? -1 : 1, diff --git a/common/controller/curatedTagsIndex.ts b/common/controller/curatedTagsIndex.ts @@ -450,10 +450,13 @@ export async function reapplyCuratedTags( // the cursor is free here because the match set is bounded by the // assignments that moved, not by the channel's size. const hits: IndexKey[] = []; + // Key-only by convention, NOT by `values: false`: with that option + // lmdb-js yields bare keys, not {key, value}, and this destructuring + // reads undefined (it crashed the first assignment-only build on the + // real corpus, 2026-09-22). recencyIndex.ts scans the same way. for (const { key } of byChannel.getRange({ start: [slug], end: [slug, "￿"], - values: false, })) { const ck = key as ChannelKey; if (ck[0] !== slug) continue;