Found by dogfooding my own change: I wrote `executor.ts` in the
payload-first/sync-fallback shape while adopting #3140's better
fallback, **predicted in a comment that the guards would stay counted**,
and the gate reported **zero**. The prediction was wrong in the
direction that matters — the gate under-reports.
## The gap
`syncLaneLocals` registered a local only when its initializer **was** a
call expression:
```ts
const sync = payload ? undefined : localSync(store, id);
return column === sync?.hold; // inert, and counted as nothing
```
Conditionals and `??`/`||` chains are now unwrapped, so a sync call in
any branch registers the local. Still a **name** match, not dataflow —
the file's LIMITS section still applies.
## Why this shape matters more than the inline one already guarded
**The missed shape is the one authors are steered toward.** Falling back
to the sync resolver is *better* than falling back to legacy literals —
it is best-effort under legacy SQLite, whereas a literal can never be
right on a renamed board. So writing the guard well is what made it
invisible.
A ratchet that goes quiet exactly when the code improves is worse than
none: it rewards the worse degraded path with a tidier number.
## Known remaining gap, stated in the test rather than implied
Only **one hop** is followed. The two-hop form is still uncounted:
```ts
const sync = payload ? undefined : localSync(store, id);
const lanes = { hold: payload?.hold ?? sync?.hold ?? "todo" };
if (from !== lanes.hold) … // still invisible
```
`executor.ts` is written that way today, which is why it reads 0 while
the sync call is still present. Closing it needs propagation through
object-literal construction — a larger change than this one, and I would
rather ship the one-hop fix with the gap documented than imply full
coverage.
## Verification
| | result |
|---|---|
| gate on `main` | **exit 0**, output unchanged (11 = triage 7 +
executor 4) |
| test suite | **5 pass** |
| new case against the **unfixed** gate | **fails** — `the
conditional-initializer shape must be counted` |
The regression case drives a real file through the scanned tree rather
than calling a helper, because the bug was in which nodes the scan
**visits**. A helper-level assertion would have been written against the
same wrong mental model that produced the gap — which is how the
inline-spelling hole in this same file survived its first draft.
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Bug Fixes**
* Improved detection of sync-lane conversions in conditional
expressions, fallback logic, awaited and parenthesized values, and
object-literal relays.
* Corrected matching for identifiers containing special characters.
* Updated validation results to include two additional findings that
were previously missed.
* **Tests**
* Added integration coverage for conditional initializers, chained
object-literal conversions, and special-character identifiers.
* Ensured temporary test files are cleaned up automatically.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
---------
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>