One of the tools in this codebase walks the attorney through their open tasks one at a time. Press C to complete, S to skip, U to update, and so on. The walker has a noise filter that hides auto-generated cleanup tasks the attorney shouldn't see — things the system itself created as housekeeping reminders.
The noise filter was a regex:
const TASK_NOISE = /^(VERIFY|Review filed orphan|Review mail filing|REVIEW \(auto)/i;
Three of the alternatives are reasonable. Review filed orphan and Review mail filing are specific phrases the older auto-gen tool emitted; they're unique enough that no human attorney would write them verbatim. REVIEW (auto has the explicit parenthetical marker — also clearly auto-generated.
The fourth alternative — bare ^VERIFY — was way too broad. It matched every task description starting with the word "Verify" (case-insensitive, then anything). The intent was to catch tasks the older auto-gen tool created with the prefix VERIFY (auto-XXXX) or VERIFY APPLICANT — autogen YYYY-MM-DD. The actual effect was to hide any task an attorney started by typing "Verify":
- "Verify date of injury with client"
- "VERIFY: client signature on petition"
- "Verify subpoena was served"
- "verify settlement amount with carrier"
- "Verify dr report received"
These are exactly the tasks the walker is supposed to surface. They're the verification checks that block the next stage of work — the attorney needs to confirm a date, a signature, a receipt — and the walker hid them all.
How widespread was the impact
I couldn't measure exactly how many tasks were being hidden in production because the walker doesn't log "I would have shown you this task but the filter ate it." It silently passes over them. From a sample of typical Workers' Compensation case-management task descriptions, the word "Verify" appears at the start of about 5-10% of legitimate attorney tasks. So roughly that fraction of the queue was invisible.
The blast radius depends on how the attorney works. If they used the walker as their primary queue view (open the walker, work through every task), they'd never see the hidden ones. If they checked the underlying system's task list directly, they'd see everything — but then the walker tool isn't doing what the tool is for.
The bug had been there for many releases. Nobody noticed because the walker doesn't render a "filtered out N tasks" line, and the attorney's other systems still showed the tasks. It looked normal from every angle.
The fix
Narrow the regex to require an explicit auto-gen marker:
const TASK_NOISE = /^(Review filed orphan|Review mail filing|REVIEW \(auto|VERIFY \(auto|VERIFY APPLICANT.*\bautogen\b)/i;
Now the bare ^VERIFY alternative is gone. The two new alternatives match only the actual auto-gen prefixes: a literal VERIFY (auto opening parenthesis, or VERIFY APPLICANT followed (anywhere) by the word boundary autogen — the older auto-task's em-dash format.
I verified the narrowed filter against 12 probe cases — 5 auto-gen patterns that should stay hidden, 7 legitimate attorney "Verify" tasks that should now appear. All 12 passed.
The general lesson
A content-filtering regex is a security boundary in disguise. It's making a "show this / hide this" decision based on free-form text the user controls. False positives are silently destructive — the user sees less than they should, and there's no signal that anything was filtered.
For a high-stakes domain like legal task management, the false-positive cost is much higher than the false-negative cost. A few auto-gen cleanup tasks slipping through is annoying; a verification task that an attorney misses is a missed deadline, a client harm, a compliance issue. The filter should err strongly toward "show by default unless the prefix is unambiguously machine-generated."
The structural pattern that makes a prefix unambiguous is usually punctuation or quoting that a human attorney wouldn't type. (auto with the opening paren is one. An em-dash plus a keyword like autogen is another. ISO-8601 timestamps in the description are another. ^VERIFY alone is none of these — it's a word, and words appear in real human work.
A few other bugs in the same probe round:
The walker also had an inconsistency in how it checked whether a task was complete. One helper checked v === true || v === 1 || v === '1' — the canonical truthy forms. Another check used raw !t.complete which treats string "0" and string "false" as truthy (and therefore complete). If the upstream system ever returned complete: "0" for a not-complete task, the raw check would hide it. Replaced with the canonical helper at both call sites.
And the JSON-parse path could throw silently on a null body. JSON.parse('null').data raises a TypeError because null.data is invalid; the outer try/catch swallowed it and returned an empty list. A backend auth failure that returned literal null looked identical to "no open tasks." Added an explicit non-object guard with a typed error message — same null-body shape we've fixed in three other places in this codebase now.
The version on the install URL is 4.5.96.