## The fourth shape: a sync lane handed to a wrapper
#3169 taught `unwrapForSyncCall` to walk await, parenthesized,
conditional and binary expressions. It still stops at the **call
boundary**, so a source call sitting in an *argument* position stays
invisible:
```ts
const parked = mergeParkedColumns(resolveTaskParkedColumnsSync(store, id), lanes);
```
That prefers the event payload and falls back to the sync answer
whenever `lanes` is absent. The callee is `mergeParkedColumns`, not a
source — so the walker never looked inside, and **the entire
`scheduler.ts` file read as clean**.
```
main today: 9 (triage 7, executor 2, scheduler 0)
this PR: 22 (scheduler 13, triage 7, executor 2)
```
Thirteen guards. And `check:inert-sync-lanes` has run in `test:gate`
since #3136, so CI is currently enforcing a ratchet that reports a file
it cannot see into as fully converted. The green is official, which
makes it worse than the version nobody ran.
## Is the fallback still reachable?
Yes, which is why these are not retired. #3135 attached lanes at every
*live* emitter, but absence remains reachable three ways: the two
`lifecycle-ops.ts` emitters on the SQLite-only polling path, any future
emitter added without lanes, and the three forwarders
(`project-manager.ts`, `remote-node-runtime.ts`,
`child-process-runtime.ts`) that reconstruct the event object
field-by-field rather than forwarding it.
A rarely-exercised fallback is still a fallback. Counting it as clean is
how the ledger stops meaning anything.
## The change
One line inside your walker, plus its note:
```js
if (ts.isCallExpression(n)) { for (const a of n.arguments) walk(a); }
```
Every shape #3169 added is preserved. Still a name match, not dataflow —
the limits section still applies.
## Mutation evidence — all three shapes, one tree
| Mutant | Result |
|---|---|
| baseline (22) | exit 0 |
| **argument position** (this PR) | **exit 1**, 13 → 14 |
| conditional (#3169's) | exit 1, 13 → 14 |
| inline (#3062's) | exit 1, 13 → 14 |
`scheduler.ts` restored clean after each run.
## Baseline 9 → 22
**Detection, not regression.** No production file changes in this PR. 22
is the exact union I measured before #3169 merged (13 + 7 + 2) and
posted on both PRs at the time — it landing unchanged is the
confirmation that the two fixes were additive rather than overlapping.
## Census before / after
```
before: COLUMN guards (the backlog): 12
after: COLUMN guards (the backlog): 12
```
Unchanged — this converts nothing. It restores 13 guards to a ledger
that had silently dropped them.
## Supersedes #3122#3122 carried this fix as a standalone rewrite of `syncLaneLocals` and
conflicted with #3169 the moment it landed. This is the six-line version
I offered there; #3122 is closed.
## Verification
`test:gate` exit 0 · `check:inert-sync-lanes` exit 0 at the re-recorded
baseline · plus `fnxc-future-dates`, `lifecycle-columns`,
`quarantine-ledger`, `inert-flag-seams`, `lane-wiring`,
`sql-column-literals` — all exit 0. Gate script + baseline only.
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Bug Fixes**
* Improved detection of synchronous operations nested within wrapper
arguments.
* Updated synchronization checks to report all currently identified
findings, including additional scheduler-related cases.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->