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:
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;