chore: add changesets for 0.0.4 - #53
Conversation
resolveFigmaCompareOptions replaces defaultFigmaProfile: default component-scope comparisons now override cluster on top of component/strict's own numbers, so a defect concentrated in one region fails even when match ratio, SSIM, deltaE, and the pixel cap all individually pass. Explicitly-named profiles are untouched. The resolved clusterCheck override is persisted through the score attachment into the durable VerificationContract and visual-score.json instead of being re-derived from the already-resolved profile name at report time -- re-deriving would hit resolveFigmaCompareOptions' explicit-profile branch and silently drop the forced default, letting a live pass disagree with the replayed/done-gate verdict. Closes #4
Design-token drift (wrong padding by a few px, wrong color hex) can't
be caught by pixel-diffing alone. Adds extractFigmaStyle(node) -> a
pure function that normalizes a raw Figma node's fills, auto-layout
padding, TEXT style, and cornerRadius into a StyleSnapshot for direct
comparison against rendered code's computed CSS (packages/verify/src
only -- the DOM/computed-CSS half and pipeline wiring are separate,
parallel tickets).
Padding is only reported as spacing when all four sides
(paddingTop/Right/Bottom/Left) are present; a node missing any one of
them leaves spacing undefined rather than fabricating 0 for the rest,
per the ticket's own "missing fields are simply absent" criterion.
Color is always emitted as an 8-digit hex (#rrggbbaa, opaque = "ff")
rather than 6 -- paint opacity (a field separate from color's own
alpha) was previously read from color.{r,g,b} only and silently
dropped, losing real design information for semi-transparent fills
(e.g. a disabled-state overlay). Uniform 8-digit output also means the
eventual property-diff (#7) never has to special-case 6-vs-8-digit
strings against the DOM-side encoding.
Closes #5
Adds captureElementStyle(page, selector) to packages/playwright, reading an element's live computed style (color, padding, fontSize, fontWeight, borderRadius) and normalizing it into a StyleSnapshot shape directly comparable to the Figma-side snapshot from ticket #5: colors become lowercase hex, spacing/fontSize are parsed to plain numbers, and browser-inconsistent fontWeight keywords ("normal"/"bold") are mapped to their numeric equivalents. cornerRadius only collapses to a single value when all four corners are circular (horizontal === vertical radius) and agree with each other, per the shared single-scalar shape — elliptical or per-corner-differing radii correctly fall back to undefined instead of silently reporting a misleading scalar. Color is always encoded as 8-digit hex (#rrggbbaa, opaque = ff) rather than 6, so alpha is never silently dropped (e.g. rgba(0,0,0,0.5) previously normalized identically to opaque black) and a later equality-based diff against the Figma-side snapshot never has to special-case 6-vs-8-digit hex. Not wired into the compare pipeline or matchers (ticket #7); does not touch packages/verify (ticket #5). Closes #6
Contract authors can now tighten or loosen specific compare() thresholds (minMatch, maxDiffPixels, minSSIM, maxAvgDeltaE, maxAreaGapPercent) without switching named profiles, mirroring how #4 added the clusterCheck override: an additive `profileOverrides?: Partial<Profile>` field merged on top of the resolved profile in compare(), threaded through toMatchFigma and persisted verbatim (not re-derived) through report-projection into the durable contract and visual-score.json. Closes #7
This update introduces a new `compareStyles` function to facilitate field-by-field comparisons between Figma and rendered styles, identifying non-blocking style issues such as color and typography mismatches. The `captureElementStyle` function now captures background colors alongside other computed styles, and the `extractFigmaStyle` function has been updated to differentiate between text and background colors. Additionally, tests have been added to ensure the accuracy of style extraction and comparison. Closes #17
This update introduces a new computed property to track style mismatches related to color and typography issues in the ContractDetails component. The changes include displaying these mismatches in the UI, enhancing the contract result structure to include topIssues, and updating the relevant schemas and types across the dashboard and contracts packages. Additionally, tests have been added to ensure proper projection of style-comparison issues in the dashboard. Closes #17
This commit introduces a new utility function, `hasEvidenceNotes`, to determine if the evidence-notes section of a contract has any relevant information to display. The `ContractDetails` component has been updated to utilize this function, simplifying the conditional rendering logic. Additionally, tests for the new utility function have been added to ensure its correctness. Closes #24
This commit introduces a new `gateEligible` property to the contract schema, allowing explicit control over whether a contract's resolved threshold blocks the CI merge gate. The property is integrated into various components, including the report projection, validation logic, and done gate checks. Tests have been added to ensure correct persistence and validation of the `gateEligible` flag across contracts and scores, addressing the need for more granular control over contract gating. Closes #10
This commit introduces support for masked regions in the image comparison pipeline. A new `MaskBounds` type is added, and functions are updated to utilize a mask bitmap to exclude specified areas from pixel comparisons, SSIM calculations, and deltaE evaluations. The `buildMaskBitmap` utility is implemented to create a bitmap representation of masked areas. Tests are added to ensure that masked regions are correctly handled, including scenarios where comparisons pass despite differences in masked areas. Closes #XX (replace with relevant issue number if applicable)
This commit enhances the ContractDetails component by introducing a new section that displays the resolved threshold values for contracts. It includes a computed property to generate a tooltip with detailed threshold information and updates the template to render this information conditionally. Additionally, mock data for resolved thresholds has been added to the dashboard mock data for testing purposes. Closes #8
This commit improves the handling of masked regions in the image comparison process. It introduces the ability to exclude masked pixel areas from scoring by updating the `compare` function to accept `maskBounds` derived from both capture sources. Additionally, tests have been added to verify that masked elements are correctly excluded from match scoring, ensuring accurate comparison results even when elements diverge visually.
* Add agent skills documentation and new skills for task management This commit introduces a new `AGENTS.md` file detailing agent skills, including issue tracking, triage labels, and domain documentation. Additionally, it adds several new skills such as `ask-matt`, `claude-handoff`, `code-review`, and `diagnosing-bugs`, each with specific functionalities for task management and debugging. The `skills-lock.json` file is also created to manage these skills, ensuring a structured approach to agent capabilities. * Add style tolerance overrides for style comparison This commit introduces a new `styleToleranceOverridesSchema` to allow explicit per-contract style-comparison tolerance overrides, enhancing the `compareStyles` function to accept these overrides. The implementation includes default tolerances for color, font size, and spacing, which can be adjusted through the new schema. Additionally, tests have been added to validate the functionality of these overrides, ensuring that style mismatches are accurately flagged or ignored based on the specified tolerances.
This commit introduces the ability to define style check-points within page contracts, allowing for CSS selectors paired with Figma node IDs to be specified. The `--style-check-selector` and `--style-check-node-id` options have been added to the CLI for non-interactive contract creation. Additionally, the interactive prompt now supports adding multiple style check-points. The schema has been updated to reflect these changes, and tests have been added to ensure proper functionality and validation of style check-points in contracts.
This commit introduces the ability to perform style comparisons at page-scope using defined check-points, allowing for multiple style checks to be executed per page. Each style issue is now tagged with its corresponding selector, improving the clarity of style mismatch reporting. The `expectStyleToSnapshot` function has been added to facilitate the conversion of expected styles into a format suitable for comparison. Additionally, tests have been implemented to validate the new functionality, ensuring that style issues are accurately captured and reported based on the defined check-points.
This commit updates the ContractDetails component to utilize a new function, `groupStyleMismatches`, for organizing style issues by their originating check-point selectors. The UI now displays these issues in distinct groups, enhancing clarity in reporting style mismatches. Additionally, the `hasEvidenceNotes` function is retained for evidence note checks, and relevant tests have been added to ensure the correct functionality of the new grouping logic.
Dashboard's contract detail view now groups style-comparison topIssues by their originating check-point selector for page-scope contracts, matching how masked-region and threshold evidence already reads. Region-scope contracts (single implicit origin, no selector tag) collapse to one unlabeled group, unchanged from today. Static reports (`framelia report`) inherit the same grouping since they render through the same ContractDetails.vue component. Closes #28
v4's action script runs on the now-deprecated Node 20 GitHub Actions runtime, surfacing a deprecation warning on every CI run. v6 targets a supported Node runtime.
) * fix: surface style-check capture failures instead of silent swallow captureStyleIssues caught every capture error (stale selector, detached element) and returned an empty issues array -- indistinguishable from a clean style-check pass. Add a style-check-error TopIssue kind so a failed capture reports itself as a non-blocking diagnostic instead. Style checks still never fail the match, per existing informational-only design. Closes #35 * fix: report style-check-error on style-check timeout too, not just capture errors withStyleCheckTimeout's timeout path still returned [] on a slow/hung selector, same silent-swallow this PR otherwise fixes -- a style check that timed out looked identical to a clean pass. Emit the same non-blocking style-check-error diagnostic there. Page-scope now applies the timeout per check-point instead of once for the whole batch, so one slow selector's diagnostic doesn't erase its siblings' real results and still carries its own selector tag. Addresses CodeRabbit review on #43.
…style comparison (#44) cornerRadius collapsed to undefined whenever corners were asymmetric or elliptical, hiding real per-side mismatches. Report every corner independently instead, mirroring Figma's own rectangleCornerRadii model on the Figma side (falling back to a uniform cornerRadius when that's all the node has) and per-corner border-radius on the DOM side. lineHeightPx/letterSpacingPx were captured into ExpectStyle at contract- authoring time but had no StyleSnapshot counterpart and were silently dropped before ever reaching compareStyles -- along with their LINE_HEIGHT_TOLERANCE_PX/LETTER_SPACING_TOLERANCE_PX constants, both unused since introduction. Wire both fields through DOM capture, Figma extraction, and comparison, with new maxLineHeightDeltaPx/ maxLetterSpacingDeltaPx contract overrides matching the existing tolerance-override pattern. Closes #36
…style comparison (#45) cornerRadius collapsed to undefined whenever corners were asymmetric or elliptical, hiding real per-side mismatches. Report every corner independently instead, mirroring Figma's own rectangleCornerRadii model on the Figma side (falling back to a uniform cornerRadius when that's all the node has) and per-corner border-radius on the DOM side. lineHeightPx/letterSpacingPx were captured into ExpectStyle at contract- authoring time but had no StyleSnapshot counterpart and were silently dropped before ever reaching compareStyles -- along with their LINE_HEIGHT_TOLERANCE_PX/LETTER_SPACING_TOLERANCE_PX constants, both unused since introduction. Wire both fields through DOM capture, Figma extraction, and comparison, with new maxLineHeightDeltaPx/ maxLetterSpacingDeltaPx contract overrides matching the existing tolerance-override pattern. Closes #36
Adds `styleGateEligible` alongside the existing `gateEligible`, resolvable at profile-default or per-contract-override level and defaulting to false everywhere (informational-only, unchanged from today). When enabled, the done gate blocks on style-color/style-typography mismatches and style-check-error capture failures (see #35) at or above STYLE_GATE_MIN_SEVERITY, mirroring the residual-cluster gating path. Threads the resolved flag through to the dashboard so the style-mismatch section states whether it's enforced or informational. Closes #39
extractFigmaStyle previously ignored SolidPaint.boundVariables.color and always compared against the stale literal fill value, so any node whose fill is bound to a Figma Variable (increasingly the default in modern Figma files) produced false positives/negatives in the style gate. Fetching the resolution needs the variables/local endpoint, which is Enterprise-plan-gated on Figma's side, so fetch-baseline only calls it when a node's fill actually carries a bound color id, and treats a fetch failure (403, other HTTP error, deleted variable, non-COLOR variable, unresolved alias chain) as non-fatal: it warns and falls back to the literal paint color, same as today's behavior. Mode resolution uses the node's own explicitVariableModes when present, else the collection's defaultModeId -- ancestor-level mode overrides aren't visible from a single fetched node, a documented limitation rather than a silent wrong answer. Scoping: no contract or fixture in this repo currently uses a bound color variable, so the real-world impact here is zero-cost by construction (the extra API call only fires when a bound color is actually present). Closes #37
…city, gap) (#48) Style comparison previously checked only 6 fields despite styleCheckPointSchema implying broader coverage. Adds Figma-side extraction (strokeWeight, effects, opacity, itemSpacing), DOM-side capture (border-top-width, box-shadow, opacity, gap), and tolerance-based comparison for all four, following the existing per-field pattern. All new fields are optional and backward-compatible. Closes #38
Cross-references pixel-diff clusters against page-scope style-check selector bounds so a diff region can be attributed to the check-point it overlaps (e.g. "this cluster = mismatch on .header") instead of staying an unexplained pixel blob. Unattributed regions are left as-is rather than guessed. Surfaced in toMatchFigma's topIssues and in the dashboard alongside existing style-mismatch evidence. Closes #40
Mask regions were 100% manually authored per-contract with no heuristic/auto-suggest path, unlike Percy/Playwright's convention-based auto-masking of dynamic content. - packages/verify: mask-suggest.ts scans an already-settled Page for common dynamic-content signals (<time>, [data-dynamic], avatar images, ad slots, [aria-live]) and proposes candidate mask selectors (prefers a match's own data-testid/id, falls back to the heuristic's selector + maxMatches when multiple elements share no unique identifier). suggest-masks.ts drives the browser: navigates, reuses capture/settle.ts's settle() -- the same readiness pipeline every toMatchFigma/toMatchPage capture already runs -- then scans. - packages/cli: `framelia contract suggest-masks --target-url <url>` prints candidates as JSON. Proposals only -- never reads or writes a contract file; accepting a suggestion is a manual edit the caller makes themselves.
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (5)
Included review availability: Your plan provides up to 1 included review per hour; 0 remain after this review. 📝 WalkthroughWalkthroughThe pull request adds five Changesets entries. Each entry records a related feature change and declares patch releases for five Framelia packages. ChangesRelease metadata
Estimated code review effort: 1 (Trivial) | ~5 minutes Merge Risk: ⚪ Minimal · up to This PR only queues synchronized patch releases and release notes without changing product behavior; no actionable merge-blocking risk remains after normal checks and review. 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
Full details: Docstring CoverageExplanation No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check. Docstring coverage is scoped to functions touched by this diff. Analyzed 0 functions across 0 files. (5 skipped: 5 unsupported.) ✨ Finishing Touches🧪 Generate unit tests (beta)
Warning Your free Security trial is over. An organization admin can activate billing to continue. Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
d084118 to
c78791c
Compare
Summary
patchbump for all 5 published packages (@framelia/contracts,@framelia/verify,@framelia/dashboard-server,@framelia/playwright,framelia) so they stay version-synchronized as required by CI'spublishjob.pnpm version-packagesafter merge will bump all 5 packages to0.0.4.Verified with
pnpm exec changeset status --verbose: all 5 packages bump to0.0.4(patch), no packages bump as minor/major.Test plan
pnpm exec changeset status --verboseshows synchronized 0.0.4 patch bump for all 5 packagespnpm version-packages, review the diff, then merge that follow-up to triggermain'spublishCI job🤖 Generated with Claude Code
Summary by CodeRabbit