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:
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user