Skip to content

Gap noise filter

Source: platform/apps/app/src/lib/chat/gap-noise.ts · rendered from main on every deploy — edit in the repo, not here

platform/apps/app/src/lib/chat/gap-noise.ts
/**
* ADR-0069 v2 — gap-queue noise filter.
*
* A real customer's gap queue was ~half non-content noise (greetings, test
* messages). Hide rows that aren't a genuine knowledge question so the queue
* stays actionable (the "looked once, abandoned" failure mode ADR-0069
* exists to prevent). Pure so it's unit-tested; the loader filters at read
* time, leaving rows un-dismissed in D1 in case the heuristic is wrong.
*/
import { classifyIntent } from './intent.js';
const TEST_LIKE = /^(test|ทดสอบ|ทดลอง|asdf+|qwer+|ppp+|aaa+|\.+|\W)$/i;
/** True when a gap row's question is NOT a real content gap worth triaging:
* missing, ultra-short fragment, test-like, or a *short* non-knowledge message
* (pure greeting/thanks/farewell/meta).
*
* Bias is deliberately toward KEEPING: hiding a real gap is worse than showing
* noise (an agent dismisses noise in one click, but can't act on a gap they
* never see). So the intent filter only applies to short messages — a real
* question that merely *starts* with a greeting ("hi, how do I register?") or a
* short Thai question ("สอบยากไหม") must still surface. */
export function isNoiseGap(question: string | null | undefined): boolean {
if (!question) return true;
const q = question.trim();
if (q.length < 3) return true; // bare fragments: "ร", "ok", "็ร"
if (TEST_LIKE.test(q)) return true; // test / garbage
// Pure small-talk is short; a greeting-prefixed real question is not.
if (q.length <= 15 && classifyIntent(q) !== 'knowledge') return true;
return false;
}