search for standard sites pub-search.waow.tech
search zig blog atproto
0

Configure Feed

Select the types of activity you want to include in your feed.

fix(labels): seeded bans show their domain, not a bare DID

Seeded banned entries have zero replica presence, so authorSite could
never resolve them — the page fell back to raw DIDs ('handles not
resolving'). The registry note's first token IS the domain: store it in
a new author_stats.site column at seed time and prefer it in the
summary. Seed now refreshes the row every boot (site/reason wording)
while still emitting the stream label only once. The page drops the
meaningless score/'0 docs' chrome for hand-banned rows ('excluded
before indexing' instead).

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

+35 -15
+28 -13
backend/src/ingest/classifier.zig
··· 118 118 conn.execNoArgs("ALTER TABLE author_stats ADD COLUMN state INTEGER NOT NULL DEFAULT 0") catch {}; 119 119 conn.execNoArgs("ALTER TABLE author_stats ADD COLUMN review_attempts INTEGER NOT NULL DEFAULT 0") catch {}; 120 120 conn.execNoArgs("ALTER TABLE author_stats ADD COLUMN reason TEXT NOT NULL DEFAULT ''") catch {}; 121 + // display identity for authors with no replica presence (seeded bans): 122 + // the replica can't resolve a site for a DID it has zero docs for. 123 + conn.execNoArgs("ALTER TABLE author_stats ADD COLUMN site TEXT NOT NULL DEFAULT ''") catch {}; 121 124 g_conn = conn; 122 125 logfire.info("classifier: author-stats ready (floor={d} threshold={d:.2})", .{ FLOOR, THRESHOLD }); 123 126 } ··· 203 206 /// Idempotent per scoring version (re-emits after each version's negate+wipe). 204 207 fn seedBannedRegistry(conn: zqlite.Conn) void { 205 208 for (policy.BANNED_ENTRIES) |entry| { 206 - const existing = (conn.row("SELECT state FROM author_stats WHERE did = ?", .{entry.did}) catch continue) orelse null; 207 - if (existing) |row| { 208 - const done = row.int(0) == STATE_LABELED; 209 - row.deinit(); 210 - if (done) continue; 211 - } 209 + const was_labeled = blk: { 210 + const row = (conn.row("SELECT state FROM author_stats WHERE did = ?", .{entry.did}) catch break :blk false) orelse break :blk false; 211 + defer row.deinit(); 212 + break :blk row.int(0) == STATE_LABELED; 213 + }; 214 + // note format: "drivepatents.com patent bot" — first token is the site, 215 + // the rest describes what it is. 216 + const site = if (std.mem.indexOfScalar(u8, entry.note, ' ')) |sp| entry.note[0..sp] else entry.note; 217 + const kind = if (std.mem.indexOfScalar(u8, entry.note, ' ')) |sp| entry.note[sp + 1 ..] else "bulk-generated mirror"; 212 218 var reason_buf: [256]u8 = undefined; 213 - const reason = std.fmt.bufPrint(&reason_buf, "{s} — hand-banned bulk-generated mirror; evidence in docs/exclusions.md", .{if (entry.note.len > 0) entry.note else entry.did}) catch entry.did; 219 + const reason = std.fmt.bufPrint(&reason_buf, "hand-banned {s} — evidence in docs/exclusions.md", .{kind}) catch entry.note; 220 + // row upsert is unconditional (refreshes site/reason wording); the 221 + // stream emit happens once — re-emitting on every boot would be spam. 214 222 conn.exec( 215 - "INSERT OR REPLACE INTO author_stats (did, doc_count, len_sum, empty_titles, digit_titles, title_sample, sample_count, state, reason) VALUES (?, 0, 0, 0, 0, '', 0, ?, ?)", 216 - .{ entry.did, STATE_LABELED, reason }, 223 + "INSERT OR REPLACE INTO author_stats (did, doc_count, len_sum, empty_titles, digit_titles, title_sample, sample_count, state, reason, site) VALUES (?, 0, 0, 0, 0, '', 0, ?, ?, ?)", 224 + .{ entry.did, STATE_LABELED, reason, site }, 217 225 ) catch continue; 218 - _ = labeler.emit(entry.did, labeler.LABEL_BULK_GENERATED, false) catch {}; 219 - logfire.info("classifier: seeded banned-registry label for {s} ({s})", .{ entry.did, entry.note }); 226 + if (!was_labeled) { 227 + _ = labeler.emit(entry.did, labeler.LABEL_BULK_GENERATED, false) catch {}; 228 + logfire.info("classifier: seeded banned-registry label for {s} ({s})", .{ entry.did, entry.note }); 229 + } 220 230 } 221 231 } 222 232 ··· 367 377 try jw.objectField("authors"); 368 378 try jw.beginArray(); 369 379 var r = try conn.rows( 370 - \\SELECT did, doc_count, len_sum, empty_titles, digit_titles, title_sample, state, reason 380 + \\SELECT did, doc_count, len_sum, empty_titles, digit_titles, title_sample, state, reason, site 371 381 \\FROM author_stats WHERE state != 0 372 382 \\ORDER BY CASE state WHEN 2 THEN 0 WHEN 1 THEN 1 WHEN 4 THEN 2 ELSE 3 END, doc_count DESC 373 383 \\LIMIT 500 ··· 387 397 try jw.objectField("did"); 388 398 try jw.write(row.text(0)); 389 399 try jw.objectField("site"); 390 - try jw.write(authorSite(arena.allocator(), row.text(0)) orelse ""); 400 + const stored_site = row.text(8); 401 + if (stored_site.len > 0) { 402 + try jw.write(stored_site); 403 + } else { 404 + try jw.write(authorSite(arena.allocator(), row.text(0)) orelse ""); 405 + } 391 406 try jw.objectField("state"); 392 407 try jw.write(stateName(row.int(6))); 393 408 try jw.objectField("reason");
+7 -2
site/labels.html
··· 110 110 ? `<a class="site" href="https://${esc(host(a.site))}" target="_blank" rel="noopener">${esc(host(a.site))}</a>` 111 111 : `<span class="site nosite">${esc(a.did)}</span>`; 112 112 const pats = (a.patterns || []).slice(0, 2).map(esc).join(' · '); 113 - const evidence = `<div class="evidence" title="what the pattern filter saw: its 0–1 score (≥ 0.50 nominates) and the repeated title shapes, digits shown as #. the verdict above came from the model, not this score.">score ${a.score.toFixed(2)}${pats ? ' · patterns: ' + pats : ''}</div>`; 113 + // hand-banned entries never flowed through the pipeline — no docs in the 114 + // corpus, no meaningful score. their evidence is the exclusions registry. 115 + const evidence = a.docs > 0 116 + ? `<div class="evidence" title="what the pattern filter saw: its 0–1 score (≥ 0.50 nominates) and the repeated title shapes, digits shown as #. the verdict above came from the model, not this score.">score ${a.score.toFixed(2)}${pats ? ' · patterns: ' + pats : ''}</div>` 117 + : ''; 118 + const docs = a.docs > 0 ? `<span class="docs">${a.docs} docs</span>` : '<span class="docs">excluded before indexing</span>'; 114 119 const reason = a.reason 115 120 ? `<div class="reason${muted ? ' muted' : ''}">${esc(a.reason)}</div>` 116 121 : `<div class="reason muted">—</div>`; 117 122 return `<div class="item"> 118 - <div class="item-top">${site}<span class="docs">${a.docs} docs</span></div> 123 + <div class="item-top">${site}${docs}</div> 119 124 ${reason} 120 125 ${evidence} 121 126 <div class="did"><a href="${labelsUrl(a.did)}" target="_blank" rel="noopener" title="the signed label history for this account, straight from the labeler">${esc(a.did)}</a></div>