@@ -7,6 +7,7 @@ tasks, not a one-off narrative (those belong in `journal/` or a feature doc
77under ` docs/features/ ` ).
88
99## Trust CI history, not a matching local venv, once a change touches Django's model-import chain
10+
1011A local mypy run can pass identically across many sessions and still not be
1112what CI actually checks, if your venv has dependencies CI's isolated
1213pre-commit hooks don't (e.g. ` mypy_django_plugin ` genuinely imports, not just
@@ -20,12 +21,11 @@ not just a local re-run — especially for anything on the models.py import
2021chain.
2122
2223## Concurrent worktree dev servers collide on port 3000
23- Multiple Claude Code sessions/worktrees on this box can and do run `next
24- dev` at the same time; Playwright's ` webServer.reuseExistingServer: true`
24+
25+ Multiple Claude Code sessions/worktrees on this box can and do run ` next dev` at the same time; Playwright's ` webServer.reuseExistingServer: true `
2526will happily attach to whatever's already listening on 3000, which may
2627belong to a different worktree entirely — producing screenshots of stale
27- code with no error. Before trusting a suspicious screenshot, check `ps aux
28- | grep "next dev"` for a PID under a different ` .claude/worktrees/* ` path.
28+ code with no error. Before trusting a suspicious screenshot, check ` ps aux | grep "next dev" ` for a PID under a different ` .claude/worktrees/* ` path.
2929Point your own run at a different port instead of killing another
3030session's process, unless the user directly confirms it's abandoned — then
3131verify the PID's cwd via ` readlink -f /proc/<pid>/cwd ` before killing.
@@ -34,6 +34,7 @@ it's a landmine for the next concurrent session, not something to leave
3434running because it "seems harmless."
3535
3636## Swap in a debug color to disambiguate same-colored overlapping elements
37+
3738A pixel/computed-color check at one sample point can be genuinely ambiguous
3839when two adjacent elements intentionally share a color (e.g. a themed
3940overlay bleeding onto a neighboring placeholder using the same palette).
@@ -43,23 +44,25 @@ element to an unmistakable color never used elsewhere on the page (e.g.
4344the real palette.
4445
4546## Sample cyclic/periodic animations repeatedly, not once
47+
4648A single before/after comparison of a value driven by a short repeating
4749cycle (e.g. a 150ms x 5-frame animation loop) can coincidentally land on
4850the same frame twice and falsely read as "static." Sample several times
4951across at least one full cycle and count distinct values instead of
5052trusting one pair.
5153
5254## Verify cross-session "investigation reports" against git, don't take them as ground truth
55+
5356A report relayed from a different Claude Code session (even one working on
5457a related codebase) is a claim, not a fact — treat it exactly like any
5558other unverified input. One such report claimed a fix commit was "still
5659unmerged on a branch" and described unrelated file changes that didn't
57- exist; ` git show <sha> --stat ` and `git merge-base --is-ancestor <sha >
58- origin/master` disproved both claims in under a minute. Always check
60+ exist; ` git show <sha> --stat ` and ` git merge-base --is-ancestor <sha> origin/master ` disproved both claims in under a minute. Always check
5961` git show ` /` git merge-base ` /` git ls-remote ` before acting on a relayed
6062finding.
6163
6264## Elasticsearch index mapping can drift from the schema declared in code
65+
6366` documents.py ` 's declared field types (e.g. ` KeywordField ` ) don't
6467automatically stay in sync with the live index's actual ` _mapping ` — a
6568field can silently end up ` text ` -analyzed instead, breaking exact-match
@@ -70,10 +73,10 @@ bug. Fix: `manage.py search_index --rebuild -f` inside the django
7073container.
7174
7275## ` factory.Sequence ` counters are process-global for the whole test run
76+
7377Shared factories (` cardpicker/tests/factories.py ` ) increment a single
7478sequence counter across every test file in a pytest session, and some
75- snapshot assertions hardcode exact sequence-derived values (e.g. `"Artist
76- 0"`) that depend on total call count up to that point — so a brand-new,
79+ snapshot assertions hardcode exact sequence-derived values (e.g. ` "Artist 0" ` ) that depend on total call count up to that point — so a brand-new,
7780otherwise-unrelated test file can silently break unrelated snapshots just
7881by sorting earlier in collection order and using the same factory. Fix
7982pattern: an autouse fixture local to the new test file(s) only that
@@ -83,12 +86,13 @@ own increment) and again in teardown, leaving zero net drift. Don't touch
8386` conftest.py ` or existing test files to fix this.
8487
8588## Use ` du -sh path/.[!.]* path/* ` , not a bare ` path/* ` glob, when sizing what's actually large
89+
8690A plain shell glob silently skips dotfiles/dot-directories, which can dwarf
8791everything else being measured (a hidden worktrees directory carrying
88- several full ` node_modules ` copies was 4.7GB and invisible to a `du -sh
89- repo/* ` sanity check before excluding things from a Docker build context).
92+ several full ` node_modules ` copies was 4.7GB and invisible to a ` du -sh repo/* ` sanity check before excluding things from a Docker build context).
9093
9194## ` position: sticky ` and ` overflow ` interact in two non-obvious, easy-to-get-backwards ways
95+
9296(1) A sticky element always paints in front of ordinary in-flow siblings
9397regardless of DOM order or a descendant's own z-index — ` position: sticky `
9498unconditionally establishes a stacking context, so anything positioned
@@ -105,6 +109,7 @@ measuring `getBoundingClientRect()` at multiple offsets — a static
105109screenshot at one scroll position won't reveal a broken sticky context.
106110
107111## A new wrapper placed around an existing effect can silently fight that effect's own CSS
112+
108113When component B is later wrapped around component A, check whether B's own
109114CSS (especially ` overflow ` ) contradicts something A was deliberately built
110115without. A hover-zoom effect was built with no ` overflow: hidden ` on its own
@@ -114,9 +119,9 @@ component added two rounds later wrapped around it out of habit with
114119already contained its image), silently re-clipping the hover-zoom it wrapped.
115120
116121## Verify a deploy against real evidence before assuming the code is wrong
122+
117123A user report of "none of these changes seem to have taken effect" should
118- first be checked against the deploy itself — ` gh run list ` /`gh run view
119- --log` for the right commit SHA, the live bundle content via ` curl`, and
124+ first be checked against the deploy itself — ` gh run list ` /` gh run view --log ` for the right commit SHA, the live bundle content via ` curl ` , and
120125response headers (` Last-Modified ` matching the deploy timestamp,
121126` cf-cache-status ` not edge-cached) — before assuming the code is broken.
122127One such report turned out to be a real deploy that genuinely shipped the
@@ -125,8 +130,29 @@ visible once a live Playwright pass (not just curl) was used to drive the
125130page.
126131
127132## Check for existing ` data-testid ` collisions before reusing a naming convention
133+
128134Before giving a new component a testid that follows an existing naming
129135pattern (e.g. ` <feature>-queue ` ), grep for whether a sibling component
130136already uses that exact string — especially one that stays mounted (hidden)
131137after its tab loses focus, which can produce two simultaneously-mounted
132138elements sharing one testid the instant a user switches tabs.
139+
140+ ## prettier@2.7.1's markdown formatter can silently corrupt text on a second pass
141+
142+ Running prettier on an already-prettier-formatted ` .md ` file is not
143+ guaranteed to be a no-op: a real non-idempotency bug turns bare
144+ ` node_modules ` -style intraword-underscore text into ` node*modules ` , and
145+ ` _italic_ ` emphasis into a broken ` \_italic* ` , with no error — it just
146+ writes wrong content. Reproduced deterministically (not flaky) by adding
147+ new prose to ` docs/infrastructure.md ` and running ` pre-commit run prettier ` /` npx prettier --write ` twice in a row. Fix was to reword the two
148+ trip points (wrap the bare ` node_modules ` mention in backticks, swap
149+ ` _hidden_ ` for ` **hidden** ` ) rather than fight the formatter, then verify
150+ by running the hook an extra time and confirming zero further diff before
151+ trusting it as a stable fixed point. Most ` docs/*.md ` files in this repo
152+ still have pre-existing prettier drift (predates this bug, out of scope to
153+ mass-fix) — the pre-commit hook is now actually installed on this machine
154+ (` pip install --user pre-commit && pre-commit install ` , written into the
155+ shared ` .git/hooks/pre-commit ` so it applies across every worktree of this
156+ repo), so the next session that touches one of those drifted files should
157+ diff prettier's output for corruption like this rather than committing it
158+ blindly.
0 commit comments