Files
fusion/packages/engine
gsxdsm 543f4a556c Tell an already-converted fallback literal from an unconverted guard — 19 of 19 dashboard scan hits were the former (#2677)
The batch phase is about to hand per-file guard lists to cheap workers,
and the census currently cannot distinguish **"not yet converted"** from
**"converted, with a documented degradation."**

## The measurement that makes this a class, not a preference

A proximity scan for *"legacy literal near a role-resolved call"* — the
heuristic that produced #2670 and #2672 from the engine — returned **19
hits across the dashboard and zero defects.** Every one was:

```ts
if (flags) return flags.hold === true || flags.countsTowardWip === true;
return column === "todo" || column === "in-progress";      // reachable only without traits
```

That literal is **correct**: it answers for callers with no resolved
column metadata, which is the case `resolveLifecycleColumns` returns
`undefined`-for-the-whole-struct to preserve. A worker told to "convert"
it would delete the only answer available when traits are absent.

## And the difference is structural, so the parser can see it

In **both** engine defects the literal sat in a **separate statement
beside resolved data**, not in a fallback branch. Proximity cannot tell
those apart; an AST can.

`traitFallback` flags the ternary form and the **early-return** form
(which is how most are actually written), and deliberately does **not**
flag a fallback whose test is itself a column-*name* check — otherwise
any `if/else` over column names would launder itself.

## Reported beside the backlog, not subtracted from it

```
COLUMN guards (the backlog):   746
  of the column guards, 9 are trait-fallback branches (already converted)
```

A fallback literal is still a literal and should go when the trait path
becomes unconditional. This only says which **kind** of work it is.

**Advisory, and structurally so:** `traitFallback` never changes `kind`,
and the count lives *outside* `totals`. My first attempt put it in
`totals` and broke two existing suites that correctly deep-equal that
shape — an advisory number does not belong in the structure that defines
the bar.

## Revert proof

Forcing `traitFallback: false` fails **3 of 33** (both fallback forms,
plus the kind-unchanged case). The two *negative* cases pass under the
revert — which is the point: they assert what must **not** be flagged,
and a classifier that flags nothing satisfies them trivially. Worth
stating, because a revert proof that only counts failures would look
stronger than it is.

## Baseline

Re-recorded: `executor.ts` 87 → 85 was **main's own drift** from #2568
landing, so `--strict` was red on main again. #2668 made the re-record
possible; the auto-tighten (coordinator item 2) is still open, and this
is the third time in this program that a legitimate merge has left the
gate red for everyone else.

## Verification

62/62 across both census suites, `pnpm test:gate` **71/71**, `--strict`
exits 0, `pnpm lint` clean.

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

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **New Features**
* Added reporting for legacy column comparisons found in trait-fallback
branches.
* Census results now include a separate count for these fallback-related
column guards.
* Human-readable reports display the new metric alongside the existing
backlog totals.

* **Tests**
* Added coverage for fallback detection across ternary, early-return,
and conditional patterns.
* Added safeguards to prevent false positives in resolved-data and
column-name checks.

* **Maintenance**
  * Updated baseline census metrics to reflect revised classifications.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-30 02:33:19 -07:00
..
2026-07-26 18:11:47 -07:00