Repository navigation
Measured checks ad-heavy and text-warped; navigation paths in interaction analytics - #99
Open
Karanvir1729 wants to merge 7 commits into
Open
Karanvir1729 wants to merge 7 commits into
Karanvir1729 wants to merge 7 commits into
Conversation
…on analytics ad-heavy (VISUAL.md 3.24): the share of the first screen and of the page that ad slots cover (named by id, class or ad attributes, or cross-site frames at fixed ad sizes), against the Coalition for Better Ads thresholds, plus fixed and interstitial ads. text-warped (3.25): overlapping line boxes, lines cut by their overflow box, lone surrogates and unassigned code points, mirrored or skewed text, letter spacing that splits words, text drawn below 8 px. Both are kind "check", report only, in the lazy chunk's idle slices, never model input. Interaction analytics (ANALYTICS.md 11): how each view was reached, the previous route and the time between, the first interaction per view, and at pagehide the exit and the ordered path; collector counters and a dashboard section. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…nly findings; RESULTS section 21 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
# Conflicts: # packages/runtime/CHANGELOG.md
# Conflicts: # docs/runtime/API.md # docs/runtime/RESULTS.md # docs/runtime/VISUAL.md # packages/runtime/CHANGELOG.md # packages/runtime/README.md # packages/runtime/src/types.ts # packages/runtime/src/visual/engine.ts # packages/runtime/test/visual-checks.test.ts
…romium gives the clamped line two nested boxes) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
# Conflicts: # PRIVACY.md # docs/runtime/API.md # packages/runtime/CHANGELOG.md # packages/runtime/TELEMETRY.md # packages/runtime/src/analytics/index.ts # packages/runtime/src/types.ts # packages/runtime/test/analytics.test.ts # telemetry-worker/README.md # telemetry-worker/src/dashboard.ts # telemetry-worker/src/pages.ts # telemetry-worker/src/sample.ts # telemetry-worker/test/pages.test.ts
# Conflicts: # packages/runtime/README.md # packages/runtime/test/analytics.test.ts
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The owner asked for GenClass to "detect strange sites, like too many ads, warped text, and exact specifics of how a user navigates the site". This adds two measured visual checks and navigation paths to interaction analytics, within AGENTS.md rules 1, 2, 3 and 8.
Two measured visual checks (
docs/runtime/VISUAL.md3.25, 3.26; 3.24 is main'srequest-stalled)Both are kind
"check"(labelled as measured, never a model finding), report only (no runtime fix, nothing written to the page in any mode), run in the lazy chunk's idle slices on the full tier, and never feed situations, facts, the event log, the gate or the model.ad-heavy. Ad-like regions: elements whose id or class contains the wordad,ads,advert…,adslot,adunit,adsbygoogle,sponsored(split into words, soheader,badge,add-to-cart,adaptivedon't match), the AdSense / Ad Manager / Prebid attributes, and cross-site iframes at a fixed ad size within 2 px. Only the outermost region counts. Thresholds (Coalition for Better Ads standards):interstitialstickydensityfirst-screenIt reports the share of the first screen, the share of the page, the fixed share and the count. A reason must still hold 2 s later, after network quiet.
text-warped. Text a reader cannot read as text. It is measured fromRange.getClientRects()line boxes, rects, the computed transform chain and code points, never from the wording:overlapclippedtofutext-encoding)mirrored/skewedbackface-visibility: hidden); skew > 20° or stretch ≥ 2x; pure rotation is never reportedspacingtinypointer-events: noneFalse reports and recall (
docs/runtime/RESULTS.mdsection 22)Run on the development Mac in Chromium 153. The faults and fixtures were written by the author of the checks, so recall here is a mechanism check, not an independent figure.
test/browser/visual, 49 tests)clean-strange.htmldesktop and phone, and the 44 existing fixtures' exact sets are unchangedad-heavy, 10text-warpedacross the 7 reasons)text-warped95 / 95,ad-heavy14 / 14text-warped15 / 15,ad-heavy8 / 8visual-measure.ymlloads about 40 public sites, which is the owner's callThe only finding outside the planted faults on the fault loads is a real
layout-shift: the harness inserts the ad slots after load, so the content does move.Cost (demos, same machine, main's engine against this branch): first pass p50 15.1 → 21.4 ms at 1x and 70.5 → 78.8 ms at 4x. The longest slice is unchanged (≤ 13.9 ms at 4x). One of 7 throttled loads ends its first pass as partial.
First load: the code is byte-identical to main.
first-load-size.mjsshows +3 B / +0 B, and that is only the hashed names of the lazy chunks. The lazy visual chunk grows by +6.7 KB gzip and the analytics chunk by +0.57 KB.Navigation paths in interaction analytics (
docs/runtime/ANALYTICS.mdsection 11)This is still off unless the app sets
analytics: truewith its token. Every telemetry opt-out and GPC still applies. Element names are the existing keys (data-genclass-name, test id, id, link target, classes, short path), never text.What the
interactionsevents now also send (this widens rule 8, at the owner's request):navon a view's first event:load,reload,back_forward,push,back,forwardorpop. The type comes from Navigation Timing and the direction from the Navigation API's entry index.fromandfromMs: the previous view's route in the same page load and the ms between the two.firstandfirstMs: the element key of the first click, or of the first keyboard focus on a form field, and the time to it. Sent once per view.exit: trueandpathon the pagehide event: the page load's routes in order, at most 10, then"(more)".Never sent: the referrer, history entry keys, or anything that links two page loads. A full page navigation therefore starts a new path.
The collector adds the
ix_entry,ix_nav,ix_nav_ms,ix_arrive,ix_first,ix_first_n,ix_first_ms,ix_exitandix_pathcounters, within the same per-batch budget and with no migration. The dashboard's Visitors view gains "How visitors move through this app": paths, page-to-page steps with average time, entries, exits, back/forward use and the first interaction per page. It is hidden for runtimes that don't send these fields.TELEMETRY.md, PRIVACY.md (dated 2026-10-25), both READMEs, the console notice, the
InitOptions.analyticsJSDoc, API.md, the CHANGELOG, the dashboard footer and the telemetry-worker README now say exactly what is added. The site's privacy page lives in genclass-site and is not touched here.Checks run (after merging main at 651aa1c: PRs 95 and 98)
npm run typecheck -w @genclass/runtimeandnpm run build -w @genclass/runtime: cleanreview-perf: 4 passed; no review test editedgit diff --stat packages/runtime/src/situation packages/runtime/src/util.ts: empty (situation-v2.3unchanged)npx playwright test --config test/browser/visual/playwright.config.tsin Chromium: 49 passed. In one earlier full run the "10,000 elements with hover" test saw one 52 ms long task with the checks' longest slice at 9.7 ms; it passed 4/4 on its own and in the two full runs afternode test/first-load-size.mjsagainst main's dist (651aa1c): +3 B / +0 B, within the 0.6 KB limitNot run: the compat and public-site bench (above), Firefox and WebKit.
🤖 Generated with Claude Code