Problem
Paths are printed through rich.console.Console.print, which parses [...] as markup. Any path containing a bracketed segment — every Next.js dynamic route — has that segment silently deleted from the output.
$ python3 -c "from rich.console import Console; Console().print('src/app/api/prospects/[id]/route.ts')"
src/app/api/prospects//route.ts
The data on disk is correct. Only the display lies — and it lies in the worst possible way, because src/app/api/prospects//route.ts collapses on POSIX to src/app/api/prospects/route.ts, a different file that also exists. A reader following fieldnotes get goes and reads the wrong route and concludes the note is wrong.
Where it shows
Every command that prints a reference path: get, stale, verify, brief, touched, for, diff, gaps. Real output from a production Next.js repo:
0001 audit-log-fail-fast stale:src/app/api/prospects//rou…
0031 rls-with-check-gates-rows-not-co… stale:src/app/api/meetings//rout…
Both notes actually pin [id] routes.
Fix
markup=False (and probably highlight=False) on path output, or rich.markup.escape() on the interpolated path. The pattern is already in the codebase at cli.py:800 for diff bodies:
console.print(rd.diff, markup=False, highlight=False)
Representative sites: cli.py:702, :714, :796, :945, :993. There are ~101 console.print calls total, so a helper (print_path() / escaping at the formatting boundary) beats patching each one.
Corrects the diagnosis in #2
Issue #2's "Related parsing artifact" section attributes the doubled slash to churn_map in gaps.py not normalizing git log --name-only rename entries. That's not it — the artifact appears in commands that never touch git log, and the repro above is pure Rich. That section of #2 can be dropped in favor of this issue.
Found while healing 10 stale notes in a Next.js repo on 2026-07-24.
Problem
Paths are printed through
rich.console.Console.print, which parses[...]as markup. Any path containing a bracketed segment — every Next.js dynamic route — has that segment silently deleted from the output.The data on disk is correct. Only the display lies — and it lies in the worst possible way, because
src/app/api/prospects//route.tscollapses on POSIX tosrc/app/api/prospects/route.ts, a different file that also exists. A reader followingfieldnotes getgoes and reads the wrong route and concludes the note is wrong.Where it shows
Every command that prints a reference path:
get,stale,verify,brief,touched,for,diff,gaps. Real output from a production Next.js repo:Both notes actually pin
[id]routes.Fix
markup=False(and probablyhighlight=False) on path output, orrich.markup.escape()on the interpolated path. The pattern is already in the codebase atcli.py:800for diff bodies:Representative sites:
cli.py:702,:714,:796,:945,:993. There are ~101console.printcalls total, so a helper (print_path()/ escaping at the formatting boundary) beats patching each one.Corrects the diagnosis in #2
Issue #2's "Related parsing artifact" section attributes the doubled slash to
churn_mapingaps.pynot normalizinggit log --name-onlyrename entries. That's not it — the artifact appears in commands that never touch git log, and the repro above is pure Rich. That section of #2 can be dropped in favor of this issue.Found while healing 10 stale notes in a Next.js repo on 2026-07-24.