Skip to content

fix(check): bill a clipped text box once, not twice#2803

Draft
xuanruli wants to merge 1 commit into
mainfrom
xuanru/clipped-text-single-code
Draft

fix(check): bill a clipped text box once, not twice#2803
xuanruli wants to merge 1 commit into
mainfrom
xuanru/clipped-text-single-code

Conversation

@xuanruli

Copy link
Copy Markdown
Contributor

Problem

nearestConstraint returns the element itself when the element clips — a clipping box is a constraint candidate (isConstraintCandidate). textOverflowIssues then reported the same physical defect a second time as text_box_overflow <sel> inside <same sel>, so every clipped_text arrived as two errors and inflated errorCount.

The guard needs both conditions

container === element && containerClips, not container === element alone. A painted, sized box is also a constraint candidate without clipping anything, and there clipped_text cannot speak for it (it requires clipsOverflow). An earlier revision of this PR omitted the second condition, and review caught it: a painted 200px chip whose text ink ran 520px past its edge went from error text_box_overflow {right: 792px} to reporting nothing at all.

Both cases are now pinned:

implementation clipped_text double-count test non-clipping self-constraint test
HEAD fails (still double-bills) passes
container === element only passes fails (silences a real defect)
this PR passes passes

Verification

31 fixtures (ovf corpus + the reviewer's own): 9 changed, all the same shape — the duplicate text_box_overflow removed, the clipped_text error and ok: false retained. 22 unchanged. Among the 9 are four fixtures that are genuine defects wearing deliberate-truncation CSS (overflow:auto body copy cut off, overflow:scroll headline, an ellipsis stat truncated to $1,2…, a headline clamped from 3 lines to 1) — all four still gate, so no recall was traded for the de-duplication.

13 registry examples byte-identical. packages/cli: 2148 tests pass; the single failure (src/telemetry/agent_runtime.test.ts, agent-env detection) reproduces on clean HEAD and is environment-dependent, unrelated. oxlint / oxfmt / tsc --noEmit clean.

Not in scope — three error-severity false positives remain

Confirmed by measurement in the same round, and deliberately left out of this PR after two reviews rejected my first attempt at them. All three currently fail the build on correct compositions:

  • -webkit-line-clamp, text-overflow: ellipsis, and overflow: auto/scroll each produce clipped_text at error. My first attempt exempted them wholesale; that silenced real defects — 4 of 7 lines of body copy invisible in an overflow:auto card, a stat truncated to $1,2…, a headline clamped away — because deliberate-truncation CSS is a mechanism, not a statement that the truncation is acceptable. It was also axis-blind: text-overflow applies only to inline overflow and -webkit-line-clamp only to block overflow, but the gate returned early on either. The reviewers' concrete design: keep auto/scroll reporting (nobody scrolls an MP4 — content past the fold is unconditionally invisible in the output) and exempt ellipsis/line-clamp only below a hidden-fraction threshold, per axis, using the already-computed overflowX / scrollWidth and scrollHeight / clientHeight.
  • Text placed wholly outside a non-clipping container reports text_box_overflow at error. My first attempt vetoed it downstream; that threw the element away instead of continuing the constraint walk, so text escaping two nested boxes reported nothing, and escaped_container does not cover the gap (it requires position: absolute and explicitly skips the detached-but-hugging case). The right fix is in isConstraintCandidate — a non-clipping candidate should have to intersect the text rect, letting nearestConstraint walk on — which is a bigger change with its own corpus sweep.

Also unfixed, larger, and deliberately separate: staticIssueKey includes formatOverflow(issue.overflow), so a breach whose depth changes between samples splits per-sample and every group is demoted to info — un-gating real errors for any moving element across all 9 tiered codes. That fix makes the audit louder and touches the same tuple as #2801; landing it alongside "stop failing on ellipsis" would make the net corpus effect unattributable.

Doc note

skills/hyperframes-core/references/data-attributes.md:59 states the current doctrine: "overflow: hidden clips the visual but does not suppress a layout finding. This attribute is the escape hatch; CSS overflow is not." This PR does not change that contract — it only stops double-billing — so the doc stays accurate. The deferred FP fixes above will contradict it and must update it.

🤖 Generated with Claude Code

`nearestConstraint` returns the element itself when the element clips, because a
clipping box is a constraint candidate. `textOverflowIssues` then reported the
same physical defect a second time as `text_box_overflow <sel> inside <same
sel>`, so every `clipped_text` arrived as two errors and inflated `errorCount`.

The guard is `container === element && containerClips`, not `container ===
element`: a painted, sized box is also a constraint candidate without clipping
anything, and there `clipped_text` cannot speak (it needs `clipsOverflow`). An
earlier revision omitted the second condition and silenced a real defect — a
painted 200px chip whose text ink ran 520px past its edge reported nothing at
all. The new test pins that case; it fails against the over-broad guard and the
duplicate test fails against HEAD.

Measured over 31 fixtures: 9 changed, all the same shape — the duplicate gone,
the `clipped_text` error and `ok: false` kept. Includes four fixtures that are
genuine defects wearing `overflow:auto` / `ellipsis` / `line-clamp`; all four
still gate. 13 registry examples byte-identical.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant