/** * What to suggest when a record looks like dead weight — one sentence per kind. * * `UsageBadge` deliberately takes the advice as a prop rather than deriving it, * because the COUNTS read identically for every kind and the REMEDY does not: a * snippet nobody opens should probably go, while a rule or a lesson in the same * position more often has a trigger that fires on the wrong work. Telling an * operator to delete one of those would be the wrong nudge about half the time. * * The table lives here because the copy was about to exist in five places. * Three already had their own: `SnippetListView`, `RuleListPane`, and * `LessonDetailView` with the sentence inline in its template. The unified * Knowledge browse renders notes, tasks, processes, snippets and lessons in one * mixed feed (#4230), so it needs all of them at once — and a per-view constant * is how three surfaces end up giving three different answers to the same * question. * * Every sentence names the COST of leaving it, not just the fact. "Never * opened" is an observation; "takes a slot in every future menu" is why the * reader should care, and it is the half that makes the chip actionable. */ /** The record kinds the Knowledge feed can show, plus the ones only their own * views show. Keyed by `note_type`, with `rule` alongside — rules live in a * separate table but answer the same question (see `RecordUsage`). */ export type DeadWeightKind = | "note" | "task" | "process" | "snippet" | "lesson" | "rule"; export const DEAD_WEIGHT_ADVICE: Record = { snippet: "Offered repeatedly without ever being opened — consider rewriting its " + "“when to reach for it” so it says when, or deleting it. It takes a slot " + "in every future auto-inject menu.", rule: "Kept arriving without being read. Either its trigger fires on the wrong " + "work — reword “when to apply” so it says when — or it is not wanted here. " + "Until one or the other, it takes a slot in every write it matches.", lesson: "Repeatedly offered and never opened usually means the trigger fires on " + "the wrong situation — re-key `when_to_apply` rather than deleting the " + "claim.", note: "Surfaced again and again and never opened. Usually the title is the " + "problem: recall matches on it first, so a note titled for its author " + "rather than for the situation keeps winning slots it cannot pay for.", process: "Offered without ever being run. Either the steps no longer match how " + "the work is actually done, or it is being matched on the wrong trigger " + "— check which before retiring it.", task: "Surfaced repeatedly and never opened. On a task this more often says " + "the work has gone stale than that the record is wrong — decide whether " + "it is still wanted before re-titling it.", }; /** The advice for a kind, falling back to the note wording. * * The fallback is deliberate rather than an empty string: a kind added to the * feed later should still get a usable sentence, and "the title is doing the * matching" is the reading that holds for any record recall can choose. */ export function deadWeightAdvice(kind: string | null | undefined): string { return DEAD_WEIGHT_ADVICE[kind as DeadWeightKind] ?? DEAD_WEIGHT_ADVICE.note; }