Release history

Loupely Lens Changelog

Every release, documented. What shipped, what changed, and why it matters.

16 releases

version 1.0.35
19 Apr 2026 Patch

Triage output layer ships: 4 routes, 8 warning types, and confirming state redesign

What this is

The triage output layer shipped. Every CSS diagnosis now routes to one of 4 specific next steps: a CSS override you paste yourself (with an editable code block and platform-specific navigation instructions), a settings change in your page builder or theme, a developer handoff with a numbered sequence and pre-written message, or a file prepared for an AI tool. The route was determined by the CSS evidence in the capture, not by the diagnosis model's judgment.

8 warning types were added to the result page: page-builder-cache (fix may be overridden on next save), css-in-js (class name will change on rebuild), dynamic selector, !important, inline-attribute, selector breadth, preference_breakage, and animation. These appeared inline with the triage instructions.

The confirming state was redesigned. The detection card was removed. The description-first flow replaced it: you describe what you see, then confirm. A free download path was added so you could download the capture file without running a diagnosis. The auth callback bug that caused the popup to revert to sign-in form after the first diagnosis was fully resolved.

What it answers

- what does loupely lens tell me to do after a diagnosis
- does loupely lens give me the css code to paste
- how does loupely lens handle elementor css overrides
- what are the loupely lens triage warning messages
- what changed in the loupely lens confirming state

Why we built it

The diagnosis alone wasn't useful. The triage route was the product. Without it, knowing what was wrong was just information without an action.

Improvements 6
  • Diy_override route built: editable code block, copy button, platform-specific navigation (Elementor: Site Settings > Custom CSS; WordPress: Appearance > Customize > Additional CSS; other: generic)
  • Diy_settings route built: settings instruction in highlighted box with fallback to developer_handoff if instruction is thin
  • Developer_handoff route built: numbered 2-step sequence (download file, copy message), founder description feeds message lead when present
  • 8 warning types added to result page: page-builder-cache, css-in-js, dynamic selector, !important, inline-attribute, breadth, preference_breakage, animation
  • Confirming state redesigned (Option C, v1.0.34): detection card removed, description-first flow, free download path added, credit balance shown
  • Capture file schema 3.0.0 verified: diagnosis.model and diagnosis.jargon_detected fields present and correct
Bug Fixes 1
  • Auth callback bug fixed: stale picker state cleared on auth callback, retry delay added (1500ms), storage re-read after retry
version 1.0.28
17 Apr 2026 Patch

Picker cancel bug fixed: the overlay now stays stable during pick

What this is

The picker overlay was cancelling itself about 2 seconds into every pick. The root cause was the MutationObserver AJAX-navigation cancel, which was watching all DOM mutations and firing on the picker's own hover mutations (tooltip text changes, outline style changes). It was treating the picker's own activity as a page navigation and cancelling the pick.

The fix moved the picker deadline timer from the popup (which closes the instant picking starts, making its timer useless) into content.js, which owns the page context and survives the full pick. The timer was raised to 60 seconds. The MutationObserver was updated to ignore attribute and characterData mutations and picker-owned nodes, firing only on genuine childList navigation changes. The picker was verified stable through 24 seconds of deliberate hovering.

What it answers

- why does loupely lens picker cancel on its own
- why does the loupely lens overlay disappear when i hover
- loupely lens picker keeps cancelling before i click
- how does loupely lens picker timeout work
- why did my loupely lens pick fail before i clicked

Why we built it

A picker that cancels during normal hover is unusable. This was the most disruptive live-testing failure and was fixed before any other work continued.

Bug Fixes 2
  • Picker deadline moved from popup to content.js and raised to 60 seconds; popup timer is now display-only
  • MutationObserver updated to ignore attribute mutations, characterData mutations, and picker-owned nodes; fires only on genuine childList navigation
version 1.0.26
15 Apr 2026 Patch

Diagnosis quality pass: jargon removed, layout scoring fixed

What this is

2 diagnosis quality problems were identified in live testing and fixed in a single release. The jargon rewrite, which ran a second Haiku API call after the first to rephrase the diagnosis in normal human terms, was removed entirely. It added several seconds to every diagnosis and rarely worked correctly. The system prompt was strengthened instead: it now forbids explaining the CSS mechanism in technical terms and instructs the model to name the concrete source directly. The containsJargon telemetry signal was kept but made non-blocking.

The detectProblemClass scoring was rebalanced. The layout_constraint class had been over-firing because the original scoring counted flex, grid, and overflow:auto signals universally across the full ancestor chain, which are present on almost every modern website. The fix: only genuine constraints count, only the nearest 3 ancestors are inspected, and the total layout contribution is hard-capped at 2. Verified on 2 controlled fixtures.

What it answers

- why does loupely lens diagnosis take so long
- why does loupely lens say layout constraint when it isn't
- how does loupely lens avoid css jargon in its diagnosis
- does loupely lens still run 2 api calls per diagnosis
- how accurate is loupely lens layout problem detection

Why we built it

A diagnosis that takes 8 seconds and uses CSS jargon isn't useful. Neither is one that classifies every page as a layout constraint. Both problems were caught in the first live session and fixed before any more sessions ran.

Improvements 4
  • Jargon rewrite second Haiku call removed from lens-diagnose.ts; one API call per diagnosis, diagnosis is final
  • System prompt strengthened: model now forbidden from explaining CSS mechanisms in technical terms; must name the concrete source (theme, Elementor, a plugin, a setting in your page builder)
  • ContainsJargon kept as non-blocking telemetry: jargon_detected still populates the session row and capture file without triggering any rewrite
  • DetectProblemClass scoring rebalanced: layout signal contribution capped, only nearest 3 ancestors inspected, total layout score hard-capped at 2
Bug Fixes 1
  • Layout_constraint over-firing fixed: Elementor button that previously misdetected as layout_constraint HIGH now correctly reads color_wrong MEDIUM
version 1.0.25
11 Apr 2026 Patch

Loupely Lens delivers its first real diagnosis end-to-end

What this is

The first real end-to-end diagnosis ran. A click on an Elementor button, a problem class confirmed, a diagnosis returned in normal human terms, a triage route chosen, a session row written to Supabase, and a credit decremented. The full chain worked.

The credit system was verified: zero-credit accounts returned a 402 with the session row still written, annual plan accounts bypassed the credit check, and the insufficient_credits error routed correctly to the no-credits popup state. The full popup state machine shipped: picking_active, confirming, diagnosing, result, no_credits, and error states, each with specific messages and exits. The triage page was built separately, opened from the result state.

A founder description field was added to the confirming state (280 characters, optional), which later fed the developer handoff message. Bold weight was reduced across the popup and the popup result text was trimmed to one sentence plus route label.

What it answers

- does loupely lens actually work end-to-end
- how does loupely lens charge credits for a diagnosis
- what does the loupely lens popup show after a diagnosis
- does loupely lens work with annual plan accounts
- what is the confirming state in loupely lens

Why we built it

Nothing in Phase 2 was worth anything until the diagnosis pipeline ran real. This release proved it did.

Improvements 4
  • Credit system verified: 0-credit accounts return 402 with session row preserved, annual plans (bundle) bypass credit check and return credit_balance_remaining: null
  • Full popup state machine shipped: loading, unauthenticated, idle, picking_active, confirming, diagnosing, result, no_credits, and error states
  • Triage page built: triage.html, triage.css, triage.js with route-specific display, copy buttons, and download
  • Founder description field added to confirming state: 280 characters, optional, feeds developer handoff message
version 1.0.21
6 Apr 2026 Patch

The full CSS capture pipeline ships: origin classification, ancestor traversal, and schema 3.0.0

What this is

The full CSS capture pipeline shipped across 9 stages. Every aspect of what Loupely Lens captures when you click an element was built in this release: where each CSS rule came from, how it competed against other rules, what the ancestor chain was doing to constrain the element, which nearby elements were interfering, and whether the problem was one of 9 specific visual failure types.

Origin classification assigned each CSS rule to one of 12 categories: theme, plugin-internal, plugin-external, page-builder-cache, css-in-js, mu-plugin, js-injected, inline-attribute, browser-default, and others. isSelectorDynamic detection covered 9 patterns including Styled Components, Emotion, Gutenberg block hashes, and Bricks builder. Ancestor traversal captured 30 levels of parent context, 63 CSS properties each. Competitor detection captured up to 10 nearby elements with their types and relationships. CSS variable resolution chains traced values up to 5 levels deep.

The credential scan ran before the relay write. Schema 3.0.0 structured the output with top-level keys: meta, stylesheet_map, target_element, ancestor_chain, competitors.

What it answers

- how does loupely lens know which plugin is causing a css conflict
- how many ancestor levels does loupely lens capture
- does loupely lens detect css-in-js styled components
- what is included in the loupely lens capture file
- how does loupely lens find competing css rules

Why we built it

The diagnosis is only as accurate as the evidence it reads. Every component of the capture pipeline existed to give the diagnosis model a complete, correctly classified picture of the CSS state.

Improvements 9
  • Origin classification built: 12 categories covering theme, css-in-js, mu-plugin, page-builder-cache, plugin-internal, js-injected, and flex-computed detection
  • IsSelectorDynamic extended to 9 patterns, adding Styled Components, Emotion (2 patterns), Gutenberg block hashes, and Bricks builder to the original 4
  • GetAccessibleSheets extended to traverse @layer block rules, @container rules with a hard cap at 200, and document.adoptedStyleSheets
  • Losing rules cap added at 10 per property in buildMatchedRuleMap, with a meta.losing_rules_truncated flag when exceeded
  • Ancestor traversal built from scratch: 30 levels, 63 computed properties each, selection_context on every entry, chain ends at body
  • CSS variable resolution chains added: up to 5 levels deep, color-first ordering, _variableChainTruncated flag when truncated
  • Competitor detection added: overlap competitors, flex and grid siblings captured, html/body/ancestors/descendants excluded, cap at 10 with _competitorsTruncated flag
  • Problem detection added: detectProblemClass scores captures against 9 problem classes and writes problem_class_detected, problem_class_confidence, and problem_classes_secondary to the relay
  • Credential scan added before relay write, scanning inline style attributes, data attributes, and URL query strings