fix(census): a DELIBERATE-LITERAL marker on a ternary arm was invisible (#3099)

## The gap

The marker works above a statement or a function. It does **not** work
in the position people actually use it — on the fallback arm itself,
right beside the literal it excuses:

```ts
flags
  ? flags.hold === true
  /* DELIBERATE-LITERAL — the no-metadata fallback. */
  : column === "in-progress";
```

That comment sits **before the `:` token**, so it's the colon's leading
trivia rather than the arm expression's — `getLeadingCommentRanges` at
the arm's full start never sees it. The ancestor walk doesn't rescue it
either: the next ancestor is the `ConditionalExpression`, whose own
leading comments are somewhere else entirely.

## Measured, not hypothesised

`in-review-stall.ts` carried a marker in exactly this position **and
stayed on the backlog**. The only way I could clear it was to
restructure the code into a named set (#3064).

That's the tool dictating shape rather than reading intent — and a
marker that silently does nothing trains people to stop marking. Given
this fleet phase has had several workers reach for `DELIBERATE-LITERAL`
(#3056 used it successfully at statement level), the failure mode is one
worker's marker working and another's not, for reasons neither can see.

## Scope and controls

Scoped to the span between the previous arm (or the condition) and this
one, so it can't pick up a comment belonging to anything else. Verified
both directions with a probe:

| case | before | after |
|---|---|---|
| marker above the statement | `deliberate` | `deliberate` |
| marker on the ternary arm | **`column`** | `deliberate` |
| unrelated marker on a neighbouring statement | `column` | `column`
(unchanged) |

**The real tree's count is unchanged at 51** — nothing is silently
reclassified, because the one site that had an arm marker was already
converted away. This is forward-looking.

## Not fixed here — pre-existing red on `main`

`lifecycle-column-census.test.ts` has two failures (`expected 22 to be
26`, `expected +0 to be 1`) whose fixture arithmetic drifts with real
tree counts as fleet conversions land. **Verified identical on
`origin/main`** before and after this change, so it isn't mine — but
someone should decide whether that fixture ought to be derived rather
than pinned, since every fleet merge moves it.

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
gsxdsm
2026-07-31 04:19:11 -07:00
committed by GitHub
parent a7b2a757fa
commit dca67a79a3

View File

@@ -213,6 +213,37 @@ function hasDeliberateMarker(sourceFile, node) {
if (ranges.some((range) => fullText.slice(range.pos, range.end).includes(DELIBERATE_MARKER))) {
return true;
}
/*
FNXC:LifecycleColumnCensus 2026-07-31-19:10:
A TERNARY ARM'S OWN MARKER WAS INVISIBLE, which is the position people actually use.
flags
? flags.hold === true
/* DELIBERATE-LITERAL — the no-metadata fallback. *\/
: column === "in-progress";
That comment sits before the `:` token, so it is the COLON's leading trivia, not the arm
expression's — `getLeadingCommentRanges` at the arm's full start never sees it. The ancestor walk
does not help either: the next ancestor is the ConditionalExpression, whose own leading comments
are somewhere else entirely.
Measured before fixing: `in-review-stall.ts` carried a marker in exactly this position and stayed
on the backlog, and the only way to clear it was to restructure the code into a named set. That
is the tool dictating shape rather than reading intent — and a marker that silently does nothing
trains people to stop marking.
Scoped to the span between the previous arm (or the condition) and this one, so it cannot pick up
a comment belonging to anything else.
*/
const parent = current.parent;
if (parent && ts.isConditionalExpression(parent)) {
const previousEnd = current === parent.whenFalse ? parent.whenTrue.end
: current === parent.whenTrue ? parent.condition.end
: undefined;
if (previousEnd !== undefined && fullText.slice(previousEnd, current.getStart()).includes(DELIBERATE_MARKER)) {
return true;
}
}
current = current.parent;
}
return false;