---
title: "Rules Only Stick If They're Lived: The Retroactive Cleanup We Never Started"
canonical: https://dxdev.com/blog/enforcement-without-retroactive-cleanup/
datePublished: 2026-09-14
---
One ticket had a dozen small updates stacked in the comment thread, and scrolling past them cost you the actual status. Not a policy violation, just noise: small updates piling into a ticket tracker thread instead of one comment that stays current. We'd written a standard for this weeks earlier. Nothing enforced it.

The standard said: one living status comment per ticket, edited in place, instead of a new comment every time something changes. It also said replies should be capped, because a thread that grows by one comment per small update is functionally the same flood with extra steps. Both rules existed only as text in a doc. Every write path to the shared workspace, our own agent posting a close summary, a teammate's terminal posting from their own station, a cron job pushing a sync line, could still just call the comment endpoint directly and add another line to the pile.

## Finding the paths

The fix wasn't one function, it was finding every place a comment could originate. I started by grepping for the ticket tracker comment call across the repo and found it called from four separate places: the ticket-close flow, a teammate's interactive session helper, the daily sync script that appends session summaries, and a standalone reply utility that nothing was actually calling with a limit.

That last one was the interesting part. The reply-limit function existed in the codebase already, presumably written for this exact purpose, and had no caller. It computed a count, checked it against a threshold, and returned a boolean nobody read. So the enforcement work wasn't building new logic, it was tracing four call sites back to one shared choke point and wiring the existing check into all of them, including the path that belonged to someone else's station, not just my own.

## The part that didn't ship

While I was in there I went looking for what the retroactive side of this would take: how many existing tickets already had the old pattern, a stack of five or ten small comments instead of one living one. I opened a handful of tickets to eyeball it, saw the pattern confirmed, and then didn't write anything down. No list, no query, no ticket ids captured anywhere. I moved on to finish the gate work because that was the part with a deadline shape to it, and the cleanup felt like it could happen later, as a pass.

It's 10:47 PM. The session log for that work reads, almost verbatim: retroactive cleanup did not happen because the list was never written down anywhere. That's not a vague regret, it's a literal description of the failure mode. I looked at the evidence, confirmed the problem was real, and then produced zero artifact that a future session, mine or anyone else's, could pick up and act on. A gate that stops new noise from forming is not the same as cleaning up the noise that's already there, and the second one now has no starting point except re-deriving it from scratch.

What stuck wasn't about the ticket tracker specifically. It was about where I let a task end. Building the gate had a clear finish line: reply-limit function gets a caller, verify it fires, done. Auditing existing tickets had no finish line I'd defined, so it defaulted to "I'll remember," which is exactly the thing a status-comment standard exists to stop trusting. The gate enforces that new work doesn't repeat old mistakes. It does nothing for the mistakes already sitting in the tracker, and now finding them again means another manual sweep instead of running a saved query against a known ticket list. Next time the fix is small: any audit that surfaces a list, even an informal one, gets written to a file before the session closes, not held in the summary of what I noticed.
