docs(lanes): three measured claims of mine had gone stale — date them or delete them (#2904)

Comment-only. No source change, no behaviour change.

#2903 corrected a note that named a caller which had since been
converted. This applies the same check to my own notes, and all three
measured claims I wrote are now wrong:

| claim | where | actual |
|---|---|---|
| "`self-healing.ts` alone issues **49** such reads" |
`project-lane-vocabulary.ts` + its test | **37** |
| "**51** such destinations exist in production" |
`workflow-lifecycle-traits.ts` | ~34 |
| "**22** deliberately pass `recoveryRehome: true`" | same | ~18 |

All were accurate when measured. The shq fleet has been converting
`self-healing.ts` since, and this program has been converting `moveTask`
destinations all day. The repo-wide read-shaped total is now 37 *in
total*, so "49 in one file" could not have remained true regardless.

## Two different repairs, because the claims differ in one way that
matters

**The self-healing figure has a reproduction.** `node
scripts/lifecycle-column-census.mjs --json` reports `queryByFile` and
`queryRoles`. So the number is kept, marked explicitly as a dated
measurement, and the reader is pointed at the command rather than asked
to trust the figure.

**The `moveTask` counts have none.** Nothing regenerates them — the
census cannot see call arguments, which is the very point the note is
making. So they are **deleted** rather than refreshed, with the grep
that approximates them inlined and labelled approximate.

Refreshing an un-reproducible number just resets the clock on the same
failure. The shape of the finding is what the note is for; the count was
decoration that decays.

## Two process notes worth recording

**Notes that assert facts about other files are a decay class with no
detector.** The census counts literals; the unwired-lane guard counts
declarations; neither reads prose. Two of these corrections in a row
(#2903 and this) came from *reading a note and checking its claim*,
which is not something the toolchain will ever do for us. The durable
form is: cite a command, or state the shape without the number.

**I nearly published a wrong replacement figure.** My first probe
against the census AST returned `0` because I wired `summarize()`
incorrectly — the third time this session a probe has been wrong before
the product was. That is why the corrected note cites `--json` output
rather than another hand count.

## Verification

- `pnpm test:gate` — 161 / 487 / 13 / 71 passed
- `pnpm lint` — clean
- `tsc --noEmit` (`@fusion/core`) — clean
- `project-lane-vocabulary.test.ts` — 9 passed
- census `--strict` — exit 0, counts unchanged

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
gsxdsm
2026-07-30 17:52:56 -07:00
committed by GitHub
parent 8e505dc4e1
commit d1ea33ee79
3 changed files with 29 additions and 6 deletions

View File

@@ -9,11 +9,15 @@ impossible one for a read:
await store.listTasks({ column: "in-review" }) // there is no task to resolve from yet
#2800 measured the consequence: `self-healing.ts` alone issues 49 such reads, and on a renamed board
#2800 measured the consequence: `self-healing.ts` alone issued 49 such reads, and on a renamed board
every one returns an EMPTY array, so the sweep never executes. The census scores the comparison
INSIDE the loop, not the query above it — so converting those comparisons drops a count while the
loop body stays unreachable. In that file the census total is not a floor; it is misleading.
The 49 is dated, not fixed: 37 as of this writing, and falling as the fleet converts them. Regenerate
with `node scripts/lifecycle-column-census.mjs --json` (`queryByFile`, `queryRoles`) rather than
trusting the figure — an un-reproducible count is how a comment starts lying about another file.
WHAT THIS MODULE IS FOR. It gives the query class one shared answer instead of each site inventing
its own. I wrote this logic once inline for the legacy auto-merge stamp backfill; a second copy is
how two readers of the same fact begin to disagree.

View File

@@ -8,11 +8,17 @@ and the wrong shape for a QUERY, because a query runs before any task is in hand
await store.listTasks({ column: "in-review" }) // ← nothing to resolve from
`#2800` measured the cost: `self-healing.ts` alone issues 49 such reads, and on a board whose lanes
`#2800` measured the cost: `self-healing.ts` alone issued 49 such reads, and on a board whose lanes
are renamed every one returns an EMPTY array, so the sweep it feeds never executes. The census scores
the comparison inside the loop, not the query above it, so converting those comparisons drops a count
and changes nothing an operator can observe — the loop body was already unreachable.
That 49 is a MEASUREMENT WITH A DATE, not a constant: it was 37 at the time of writing and falls as
the fleet converts them. Reproduce rather than trust it —
`node scripts/lifecycle-column-census.mjs --json` reports `queryByFile` and `queryRoles`. Quoting a
hand-counted figure with no way to regenerate it is how a note starts lying about another file, which
this program has now corrected twice in comments that were true when written.
Fixing a query needs a different answer: not "this task's lane" but "every column ANY workflow in this
project declares for this role". That is what this module returns, and it is deliberately shared
rather than re-derived per call site — I wrote this logic once inline for the legacy auto-merge stamp

View File

@@ -395,12 +395,25 @@ MOVE-TARGET resolvers, kept beside `resolveTaskLifecycleColumns` because they an
for the other half of a conversion.
The lifecycle-column census is an AST scan for COMPARISONS, so a `moveTask` DESTINATION — a call
argument — is invisible to it. 51 such destinations exist in production; 22 deliberately pass
`recoveryRehome: true` (the #1411 legacy safe-landing escape, which must not be converted), and the rest
are rejected outright on a board that does not declare the target now that U12 hoisted the
`workflowHasColumn` check out of its dead flag-gated branch. See
argument — is invisible to it. A share of those deliberately pass `recoveryRehome: true` (the #1411
legacy safe-landing escape, which must not be converted); the rest are rejected outright on a board
that does not declare the target, now that U12 hoisted the `workflowHasColumn` check out of its dead
flag-gated branch. See
`docs/solutions/architecture-patterns/hardcoded-movetask-destinations-are-census-invisible.md`.
THE COUNTS THAT USED TO BE HERE ARE GONE ON PURPOSE. This note read "51 such destinations exist in
production; 22 deliberately pass `recoveryRehome: true`". Both were true when measured and neither is
now — the program has been converting them since — and unlike the census totals there is no command
that regenerates these, so the figures could only rot. A comment that states an un-reproducible count
about other files is a comment that will eventually lie; the shape is what matters here, and the
current numbers are one grep away:
grep -rnE 'moveTask\([^,]+, *"(todo|in-progress|in-review|done|archived|triage)"' packages \
--include='*.ts' | grep -v __tests__
(approximate — it sees single-line call sites only, which is precisely why it was never a total worth
pinning in prose).
Both fall back to the legacy id: `resolveWorkflowIrForTask` degrades to the BUILT-IN IR rather than
throwing, so a board whose workflow cannot be read behaves exactly as before.