Skip to content

fix(devex): stop the raw-colour scanner counting issue references - #2732

Merged
vybe merged 1 commit into
Abilityai:devfrom
L4XB:fix/2718-raw-color-scanner-issue-refs
Sep 13, 2026
Merged

vybe merged 1 commit into
Abilityai:devfrom
L4XB:fix/2718-raw-color-scanner-issue-refs

Conversation

@L4XB

@L4XB L4XB commented Sep 12, 2026

Copy link
Copy Markdown

Description

scan-raw-colors.mjs matched a # followed by three or six hex digits anywhere inside a <template> or <style> block. A three-digit hex is also what an issue reference looks like in rendered copy, so (ent#184), Opt-in per agent (#526). and <a …>#847</a> were counted as hardcoded colours. Nine of them sat in raw-color-baseline.json, and since #2605 made the ratchet actually bite, that turned load-bearing: adding a second reference to a file grows its entry and fails the build for prose.

No lexical rule separates the two, since #190 is both. The rule here is positional, and it is the one the file already implies: code is scanned, rendered copy is not.

  • HEX_RE refuses a # glued to a word, (?<![\w&]), which catches the ent#206 shape even inside a prose attribute such as title="quality (ent#206)". A hex literal is never preceded by a word character, so 1px solid #374151 and bg-[#1e1e1e] are unaffected.
  • The copy of a <template> is blanked before matching, offsets preserved so sample line numbers still point at the source. Tags, attribute values and {{ }} interpolations stay in, so stroke="#10b981" and {{ ok ? '#10b981' : '#ef4444' }} are still counted. <style> blocks are never blanked.
  • The tag scan is quote aware, because v-if="nowX >= 0" would otherwise end the tag early and blank the colour that follows it. ReplayTimeline.vue has exactly that shape.

The prescription in the issue, the \w lookbehind alone, removes only the ent#NNN half: #190, (#526) and >#847< are not preceded by a word character. Both halves are needed, and the spec fails if either is reverted.

Measured on this branch, nothing else moves:

before after
hardcoded_colors 456 447
raw_nongray 815 815
raw_gray 8752 8752
semantic_tokens 4034 4034

The nine are ExecutionsPanel:54, OverviewPanel:359, ReliabilityPanel:7 and :74, ScheduleAnalyticsCard:46, settings/OperatorIntakePanel:9, settings/TelemetrySharingPanel:9, views/Settings:1251, views/enterprise/Index:118. No surviving sample changes line.

The baseline is hand-edited, 8 entries plus the total, rather than regenerated: --baseline rewrites the file and would drop the hand-written refrozen provenance. A _2718_note is added there in the style of the existing ones.

Related Issue

Fixes #2718

Journey Impact

Journey Impact: none: a scanner accuracy fix in the devex tooling; it changes no user-facing behaviour and no promise in tests/journeys/catalog.yaml.

Type of Change

  • Bug fix (non-breaking change that fixes an issue)
  • New feature (non-breaking change that adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)
  • Documentation update

Testing

  • I have tested this locally
  • New tests added (if applicable)
  • All existing tests pass

countHardcodedColors(source, onSample) is exported so the spec can drive it with literal snippets, the way loadingGateRatchet.spec.js drives countBareLoadingGates. Seven cases in tests/unit/rawColorRatchet.spec.js under #2718: issue references in copy, in an attribute and as link text, an HTML entity, hex in an attribute, in an arbitrary class, in a <style> block, rgba(), a hex behind an attribute containing >, and a hex inside an interpolation.

npx vitest run tests/unit/rawColorRatchet.spec.js     14 passed
npm run test:unit                                     2737 passed, 1 failed
npm run check:tokens                                  OK

The one failure is tests/unit/canvasUtils.spec.js > a date axis keeps the default spacing, which fails the same way on dev without this branch.

Checklist

  • My code follows the project's style guidelines
  • I have updated the documentation (if applicable)
  • I have not committed any sensitive data (API keys, credentials, etc.)
  • I have added appropriate logging for new functionality

One documentation note left deliberately: docs/memory/learnings.md still records the durable scanner fix as open debt. Happy to update it here if you would rather it land together.

A '#' followed by three or six hex digits is a colour, and it is also
what an issue reference looks like in rendered copy, so '(ent#184)',
'(Abilityai#526)' and '>Abilityai#847</a>' were counted as hardcoded colours. Nine of them
sat in the baseline, and since Abilityai#2605 made the ratchet bite that turned
load-bearing: adding a second reference to a file grew its entry and
failed the build for prose.

No lexical rule separates the two, so the rule is positional: code is
scanned, rendered copy is not. Tags, attribute values and {{ }}
interpolations stay in, the text between them is blanked before
matching, offsets preserved so sample lines still point at the source.
The hex pattern also refuses a '#' glued to a word, which catches the
'ent#206' shape inside a prose attribute.

hardcoded_colors drops 456 to 447 across 8 files, all of it phantom;
raw_nongray, raw_gray and semantic_tokens do not move and no surviving
sample changes line. The baseline is hand-edited rather than
regenerated, so the refrozen provenance block survives.

Fixes Abilityai#2718

@vybe vybe left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

merge-train: batch validated on train/20260913-0705 (#2745) — lane B, /validate-pr + /review clean; baseline byte-identical to a fresh scan; tests bite under mutation.

@vybe
vybe merged commit 8510eb3 into Abilityai:dev Sep 13, 2026
25 checks passed
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.

2 participants