Skip to content

feat(remap): affectedSurfaces — sound, opt-in selective-remap core (#75)#158

Merged
BenSheridanEdwards merged 3 commits into
mainfrom
feat/affected-surfaces
Jul 5, 2026
Merged

feat(remap): affectedSurfaces — sound, opt-in selective-remap core (#75)#158
BenSheridanEdwards merged 3 commits into
mainfrom
feat/affected-surfaces

Conversation

@BenSheridanEdwards

@BenSheridanEdwards BenSheridanEdwards commented Jul 5, 2026

Copy link
Copy Markdown
Owner

What and why

Closes the core of #75 (selective remap) — the sound reasoning half, as a new opt-in export. Given the files a change touched, a surface→entry map, and a module graph, affectedSurfaces returns exactly the surfaces that could have rendered differently, or the sentinel 'all'.

Validated first as spikes — #155 (why not GitNexus: it drops CSS edges and false-negatives on lazy) and #157 (dependency-cruiser is sound; the ceiling is dynamic composition + the global-CSS classifier). This lands that decision as real, tested code.

Design choices that keep it safe and framework-agnostic:

  • The module graph is an input, not a dependency. Pass any tool's output as { from, to } edges (dependency-cruiser's modules[].dependencies[] maps directly). StyleProof adds no dependency and stays framework-agnostic; graph production — where framework-specific resolution lives — is the caller's.
  • Sound by construction / fail closed. A wrong "unaffected" is silent and fatal in the committed-map model, so it over-approximates: global & vanilla (unscoped) stylesheets, createGlobalStyle, design-system configs, an unbounded dynamic import(x), and files the graph can't place all force 'all'. A computed template-literal import with a static directory prefix is recovered as a bundler context module (directory-level precision, never a miss).
  • Never touches the default gate. Purely additive export; existing specs unaffected. The gate still captures every surface and lets the map be the oracle. This is a helper for wiring a faster pre-push/CI path yourself, with main capturing all as the trust-but-verify net.

Proof (required)

Rendered/screenshot proof is Not applicable: this adds a pure, deterministic reasoning function with no capture/diff/report rendering path and no visual output — so the evidence is behavioural, per the template's "Behaviour / guards / CLI: paste the actual command or test output".

End-to-end on a real dependency-cruiser graph (generic home/pricing/dashboard fixture — a static import, a string-literal lazy, a computed template-literal import over ../components/, a CSS module, a vanilla sheet, a global token sheet):

changed file                            | affected surfaces  (real dependency-cruiser graph)
----------------------------------------+--------------------------------------
src/widgets/Isolated.tsx                | {pricing}               # static component, isolated dir
src/components/PriceTable.tsx           | {dashboard, pricing}    # component in a context-glob dir
src/components/Promo.tsx                | {dashboard, home}       # string-literal lazy component
src/components/Widget.tsx               | {dashboard}             # reachable only via computed import
src/components/Badge.module.css         | {dashboard, pricing}    # scoped CSS module -> stays selective
src/components/Header.css               | all                     # vanilla stylesheet -> full re-capture
src/tokens.css                          | all                     # global :root token sheet -> full re-capture

Reads: a scoped change resolves to just the surfaces that can render it (the win); a global / vanilla / unbounded change resolves to all (never a silent miss); a computed import is soundly coarsened to its whole directory.

Tests — 25 new (13 classifier cases across vanilla / CSS Modules / styled-components / vanilla-extract / Tailwind / Sass, 12 reachability + fail-closed cases). Full suite:

# tests 274
# pass 274
# fail 0

Gates — pass (run by the pre-commit hook): build · typecheck · lint · format:check all clean; fallow — ✓ No issues in 5 changed files.

Checklist

  • Proof above — pasted the real end-to-end command output + test results; rendered proof Not applicable with the technical reason
  • If you changed capture/diff/report rendering, ran npm run demo:report — N/A, rendering untouched
  • npm run build && npm run typecheck && npm run lint && npm run format:check pass
  • npm test passes (274/274); test:e2e N/A — no capture/engine path changed
  • Added/updated tests — 25 new
  • Updated README / CHANGELOG — new "Optional: selective remap" section + [Unreleased] entry
  • Captured output changed — N/A (additive, no baseline impact)
  • Followed .agents/DEFINITION_OF_DONE.md and .agents/skills/pr-inline-screenshot-proof/SKILL.md
  • Screenshots inline, or proof says Not applicable with the technical reason — latter
  • No bare screenshot links, local paths, relative paths, or proof placeholders

🤖 Generated with Claude Code

Given the files a change touched, a surface→entry map, and a module graph
(any tool's output as { from, to } edges — dependency-cruiser maps directly),
return exactly the surfaces that could have rendered differently, or the
sentinel 'all'. Sound by construction: over-approximates and resolves every
uncertainty to 'all' — global/vanilla stylesheets, createGlobalStyle,
design-system configs, unbounded import(x), and unplaceable files force a full
re-capture; computed import(`../dir/${x}`) is recovered as a bundler context
module (directory-level, never a miss). Ships classifyStyleChange.

Purely additive, adds no dependency, never touches the default gate. Answers
#75's Q1 (global classifier), Q2 (dynamic composition), Q4 (graph tool);
groundwork validated in the #155/#157 spikes.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@github-actions

github-actions Bot commented Jul 5, 2026

Copy link
Copy Markdown

🗺️ StyleProof report

📊 View the side-by-side visual report →


To accept: rebuild the map with styleproof-map, then rerun the report.

@github-actions

github-actions Bot commented Jul 5, 2026

Copy link
Copy Markdown

Fallow audit report

No GitHub PR/MR findings.

Generated by fallow.

@github-actions

github-actions Bot commented Jul 5, 2026

Copy link
Copy Markdown

Fallow audit report

0 inline findings selected for GitHub review.

StyleProof Test and others added 2 commits July 5, 2026 10:55
@BenSheridanEdwards BenSheridanEdwards merged commit da90d80 into main Jul 5, 2026
7 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.

1 participant