SLOPGUARD

Classification: revise before release
run 001 target hexento.com (frozen source) 2026-08-08 files 51 candidates 207 → verified 158 4 lenses · adversarial verify
Markdown, with paths and line numbers — paste it into your agent's terminal and say "fix these."
view raw markdown

  

Editor's note

The core recommendations survive this review: no verified finding contradicts the advice to prefer DIY opt-outs or to skip paid antivirus. The failures concentrate in the trust apparatus. Interactive tools promise that answers stay in the browser while their shipped scripts send answer-derived events to analytics, and the HideMy.Name partnership earns commission while going unnamed in partner lists that claim to be complete. Start with SG-001, where the exposure check promises nothing is sent anywhere as its own code sends events; it verifies in minutes, and fixing it forces the analytics decision behind the sibling privacy findings. SG-002 documents the matching disclosure gap.

5 trust-killers 51 embarrassing 102 nits
SG-001
trust-killer claim-code-contradiction 4/4 lenses

Exposure check promises "nothing is sent anywhere" while its own code sends answer-derived analytics events

The exposure-check intro (line 67) and the result card (line 395: "Nothing you answered was sent anywhere.") make an absolute no-transmission promise, but the same page's click handler fires H.track("tool_complete", ...) with best_code set to your computed exposure band (line 404) and score_tier set directly from your answer to the time question (line 405). A summary of what you answered — including whether you're a "paid_fit" — leaves the browser in an analytics event.

claim — apex/privacy/index.html:67
Answers stay in your browser — nothing is sent anywhere.
ships — apex/privacy/index.html:405
score_tier: answers.time === "no" ? "paid_fit" : "diy_fit"

This page explicitly courts post-harassment and safety-concerned visitors. Anyone who opens dev tools or reads the source after being told twice that nothing is transmitted will see an event fire the moment they click — on a privacy-advice site, that single catch destroys trust in every other promise on the domain.

fix — Delete best_code and score_tier from the exposure-check tool_complete H.track payload (lines 402-406) so the promises at lines 67 and 395 become true, or soften both promises to disclose anonymous completion events.

this line
SG-002
trust-killer claim-code-contradiction 4/4 lenses

The on-page partner disclosure omits HideMy.Name, which is an active tracked-commission partner.

The 'How this works' section names exactly three partners, but the catalog marks a fourth option (hidemy) as an active CJ program with a tracked affiliate link. The page's own disclosure list is incomplete on the one topic where the site stakes its credibility.

claim — tools/pickguard/index.html:118
Some outbound links are labeled partner links (currently NordVPN, Surfshark, NordPass).
ships — tools/pickguard/src/catalog.js:4
// Partner status: nordvpn, surfshark, nordpass, hidemy = Active CJ programs (tracked links).

This site's entire pitch is 'money, disclosed.' A visitor who clicks Visit HideMy.Name, notices the jdoqocy.com tracking hop, and rereads the three-name disclosure will conclude the honesty framing is theater — the exact trust the site is built on evaporates.

fix — Update tools/pickguard/index.html line 118 to include HideMy.Name in the named partner list, or replace the hardcoded roster with "see the disclosure page for the current list" so it cannot drift again.

this line
SG-003
trust-killer claim-code-contradiction 4/4 lenses

The meta description and JSON-LD advertise a backup-tool chooser that does not exist in the catalog.

Both the search-snippet description and the structured data (line 35: 'VPNs, password managers, and backup tools') promise a backup category, but CATEGORIES contains only 'vpn' and 'password'. A visitor arriving to choose a backup tool finds nothing.

claim — tools/pickguard/index.html:7
Pick a VPN, password manager, or backup tool against your actual constraints.
ships — tools/pickguard/src/catalog.js:9
export const CATEGORIES = [
  { id: "vpn", label: "VPN" },
  { id: "password", label: "Password manager" },
];

Someone who clicked from a search result promising backup-tool picks lands on a two-category chooser with no backup option anywhere. The very first promise the site made them is false — they close the tab and remember the site as bait.

fix — Search tools/pickguard/index.html for the string "backup" and remove backup-tool mentions from the meta description (line 7) and the JSON-LD description (line 35) to match the shipped two-category catalog.

sweep all instances
SG-004
trust-killer claim-code-contradiction 3/4 lenses

Privacy policy says calculator inputs stay in the browser, but the calculator sends its inputs to analytics

The true-cost calculator has exactly two user inputs — the horizon and the intro term — and cost.js transmits both in a "true_cost_run" analytics event (lines 286–291: term: state.term, horizon_months: state.horizon) on initial load and on every change. That is precisely what the privacy policy says does not happen.

claim — apex/privacy.html:50
We do not put your answers, names, emails, or device advertising IDs into analytics events — quiz and calculator inputs stay in your browser.
ships — apex/vpn/true-cost/cost.js:288
term: state.term,

The privacy policy is the site's self-declared "trust surface." A stranger who verifies its central claim against the shipped code finds it false on the very first tool they check, which converts the whole cookieless-analytics pitch from reassurance into marketing.

fix — Either rewrite the policy sentence at lines 50-51 to disclose input-derived event fields, or search every H.track( call for user-input fields — term, horizon_months, best_code, score_tier — and remove them (cost.js 286-291, privacy hub 402-406, pm hub 434-438).

sweep all instances
SG-005
trust-killer stale-claim 3/4 lenses

Calculator disclosure says HideMy.Name is not a true-cost row, but the table ships a HideMy.Name partner row

The affiliate disclosure directly above the table states HideMy.Name is "not yet a true-cost row," yet cost.js defines a HideMy.Name provider with a live CJ partner link (lines 77–90) that renders in the table with a "Visit" partner button and a "Partner link" note. The disclosure also claims prepaid codes "don't map cleanly to intro/renewal math," while the code models them anyway (renewYr: 48 / 36).

claim — apex/vpn/true-cost/index.html:73
NordVPN and Surfshark rows include labeled partner links (HideMy.Name is partner-live on the hub/Pickguard but not yet a true-cost row — prepaid codes don’t map cleanly to intro/renewal math)
ships — apex/vpn/true-cost/cost.js:80
link: { type: "partner", href: CJ.hidemy },

This site's entire differentiator is disclosure precision. A visitor who reads the disclosure and then sees a third "Partner link" label in the table two scrolls later catches the disclosure being factually wrong about its own page — the exact failure the site accuses competitors of.

fix — Rewrite the disclosure at line 73 to read 'NordVPN, Surfshark, and HideMy.Name rows include labeled partner links', deleting the parenthetical claiming HideMy.Name is not yet a true-cost row.

this line
SG-006
embarrassing claim-hedge-contradiction 4/4 lenses

The sibling-brands page states its core ownership fact confidently, then dissolves it into hedges

The lede asserts flatly that NordVPN and Surfshark have shared a holding company since early 2022. The body paragraph meant to substantiate this collapses into "Cyberspace B.V. era combination announced 2022; Nord Security / Kape-era coverage varies by article — verify current org charts when it matters to you" — jargon soup that tells the reader the site itself is not sure.

claim — apex/guides/sibling-vpn-brands.html:75
Nord Security / Kape-era coverage varies by article — verify current org charts when it matters to you).
ships — apex/guides/sibling-vpn-brands.html:53
Since early 2022 they’ve shared a holding company. That doesn’t make either product fake —

This page's only job is to establish one corporate fact. When the supporting detail says "coverage varies by article, go verify yourself," a stranger wonders why they needed this page at all — and whether the confident lede was earned. Either state the ownership chain plainly with a date, or do not build a page on it.

fix — Rewrite the parenthetical on sibling-vpn-brands.html lines 74-75 to state the ownership plainly with one dated source (e.g. 'both owned by Nord Security since the 2022 merger'), deleting 'coverage varies by article — verify current org charts when it matters to you'.

this line
SG-007
embarrassing inaccessible-evidence 4/4 lenses

The site's central price evidence is an unlinked internal snapshot named in code formatting

The page promises "These are not vibes" and then points the full evidence table at "our research snapshot (product-facts-2026-08)" — an internal artifact name rendered in code font, with no link. The same unexplained "snapshot" jargon recurs in meta-lines across the guides ("prices from snapshot 2026-08-01", "study refs from snapshot").

apex/guides/vpn-renewal-trap.html:72
(<code>product-facts-2026-08</code>); re-verify before you buy — these age fast.

The whole pitch is verifiable, dated numbers, but the receipt is a filename the visitor cannot open. To a stranger it reads like leaked dev notes, and the precise figures ($94.23, $139.08/yr) become take-our-word-for-it claims — exactly what the page says it exists to prevent. Link the table or drop the reference.

fix — Replace 'Full table lives in our research snapshot (<code>product-facts-2026-08</code>)' with either a link to a published version of the table or plain text like 'all prices checked 2026-08-01', removing the internal artifact name.

this line
SG-008
embarrassing stale-claim 4/4 lenses

Homepage badge says the VPN hub has 2 live partners; the hub discloses three

The homepage VPN card badge reads "2 live partners," but the VPN hub's own disclosure names three tracked partner links (NordVPN, Surfshark, HideMy.Name), confirmed again in its FAQ. The sitemap shows the homepage was touched 2026-08-04, after the hub's 08-02 HideMy.Name check — so the badge is stale on the fresher page.

claim — apex/index.html:116
<span class="badge badge-live">2 live partners</span>
ships — apex/vpn/index.html:58
The NordVPN, Surfshark, and HideMy.Name buttons on this page are tracked partner links

The badges exist purely to signal meticulous disclosure hygiene. A visitor who counts partner buttons on the hub and gets a different number than the homepage promised learns the disclosure layer isn't actually maintained — a small slip that lands hard on a site selling exactly this precision.

fix — Change the homepage VPN card badge text at line 116 from '2 live partners' to '3 live partners'.

this line
SG-009
embarrassing privacy-optics 4/4 lenses

A privacy-advice site loads analytics from an unrelated third-party domain and tracks return visits.

hexento.com serves its tracker from analytics.playkeg.com — a brand with no visible relationship to Hexento — and the analytics module stamps a first-seen timestamp in localStorage to report days-since-first-visit on every return.

claim — tools/pickguard/index.html:40
<script defer src="https://analytics.playkeg.com/script.js" data-website-id="3e5eb140-4d7f-40e2-89c8-36a64c69fc07"></script>
ships — tools/pickguard/src/analytics.js:85
track("return_visit", { days_since_first: days, surface: "pickguard" });

The exact audience this tool targets (privacy-conscious VPN and password-manager shoppers) is the audience most likely to open the network tab. Seeing a mystery domain 'playkeg.com' tracking them on a privacy site is a credibility hit the copy can't talk its way out of.

fix — Search for 'analytics.playkeg.com' (index.html line 40, analytics.js line 6) and serve the script from a first-party hexento.com host, and delete visitRetention()'s localStorage first-seen/return-visit tracking (analytics.js lines 76-90).

sweep all instances
SG-010
embarrassing thin-identity 3/4 lenses

The operator is a first name with no surname, bio, photo, or verifiable link anywhere on the About page.

The page makes 'who's behind it' a trust pillar, then answers with an unverifiable 'Ken' — no last name, no GitHub/LinkedIn/portfolio, no track record. The anti-fake-masthead framing is good, but the replacement offers nothing a stranger can actually check.

claim — apex/about/index.html:70
Hexento is run by <strong>Ken</strong> — an independent builder shipping small web tools and experiments.
ships — apex/about/index.html:76
That smallness is a feature for accountability

For a site asking me to take security-purchase advice and click its commission links, 'run by Ken' is exactly as verifiable as an invented masthead. Honest-sounding, but I still can't confirm a single human exists.

fix — In the 'Who's behind it' paragraph, give 'Ken' at least one verifiable anchor — a full name or a link to a real GitHub/portfolio/LinkedIn profile.

this line
SG-011
embarrassing off-brand-third-party 3/4 lenses

Every page loads analytics from an unexplained unrelated domain, analytics.playkeg.com.

A security-advice site quietly ships visitor data to 'playkeg.com', a domain that appears nowhere on the About or Disclosure pages and has no visible relationship to Hexento. It is presumably the operator's own Umami instance, but nothing shipped here says so.

claim — apex/analytics.js:8
var SCRIPT_URL = "https://analytics.playkeg.com/script.js";
ships — apex/antivirus/index.html:193
<strong>Double-agent “security”</strong> — products monetizing your browsing data (see Avast, above).

The privacy-savvy visitor this site courts will open devtools, see requests to a random game-sounding domain, and have no way to tell self-hosted analytics from data resale — on a site that just lectured them about Avast selling browsing data.

fix — Serve the Umami script from a first-party host (e.g. analytics.hexento.com) or add one sentence to the privacy/disclosure pages naming analytics.playkeg.com as the operator's own self-hosted Umami instance.

this line
SG-012
embarrassing dead-contact-channel 2/4 lenses

The site's only contact address is admitted, on both trust pages, to possibly not receive mail.

privacy@hexento.com is the sole contact channel on the About and Disclosure pages, and both hedge that the mailbox may not actually work yet. A commission-earning site whose accountability pitch rests on 'smallness is a feature for accountability' ships with a possibly-dead inbox and no fallback (no form, no social, no second address).

claim — apex/about/index.html:104
(mailbox may lag DNS mail setup)
ships — apex/disclosure.html:86
(mailbox may be enabled after DNS mail setup)

A visitor with a privacy question or a complaint reads 'mailbox may lag DNS mail setup' as 'you probably can't reach anyone.' On the two pages meant to establish accountability, that quietly undoes the pitch.

fix — Search for the string 'DNS mail setup' and delete the parenthetical caveat in both apex/about/index.html ('(mailbox may lag DNS mail setup)') and apex/disclosure.html ('(mailbox may be enabled after DNS mail setup)'), leaving the bare mailto link once the mailbox is confirmed working.

sweep all instances
SG-013
embarrassing claim-code-contradiction 2/4 lenses

The 'cookieless' analytics script does longitudinal visitor tracking via a permanent localStorage timestamp.

The header sells the analytics as cookieless/no-PII, but the same file writes a permanent hexento_first_seen value to localStorage and reports return_visit events with days_since_first. That is functionally the persistent cross-visit tracking cookies are used for — just stored somewhere the word 'cookieless' doesn't cover.

claim — apex/analytics.js:1
/* Hexento shared Umami helper (cookieless).
ships — apex/analytics.js:79
track("return_visit", { days_since_first: days });

This site's exact audience is privacy-conscious people who check what runs in their browser. Discovering a persistent first-seen identifier behind a 'cookieless' label reads as the same word-lawyering the site accuses vendors of.

fix — Remove visitRetention(), its two call sites (lines 103 and 115), and FIRST_SEEN_KEY from apex/analytics.js, or amend the header comment and the site's privacy page to disclose the persistent localStorage first-seen identifier.

restructure
SG-014
embarrassing unverifiable-citation 2/4 lenses

The page promises checkable lab citations but links to zero lab reports.

The table asserts very specific results (18/18, 99.1%, 42 false positives, dated rounds) and says they're cited so you can verify them, yet the only sourcing shipped is two bare domain names in a footnote — not one hyperlink to an actual report, despite the site linking freely everywhere else.

claim — apex/antivirus/index.html:67
cited so you can check them yourself.
ships — apex/antivirus/index.html:107
Sources: av-test.org and av-comparatives.org public reports; renewal figures from vendor checkout fine

'Check them yourself' with no links means the stranger must go hunt av-test.org for the right round themselves. The precision of the numbers combined with the absence of links is exactly the pattern affiliate slop uses, which this site otherwise loudly avoids.

fix — In the Sources footnote (line 107), hyperlink the specific AV-TEST and AV-Comparatives report pages for each cited round instead of naming bare domains.

this line
SG-015
embarrassing uncited-claim 2/4 lenses

The FAQ appeals to 'every expert roundup we cite' but no roundup is cited anywhere on the page.

No expert roundups are named or linked on this page, so 'every expert roundup we cite' references a citation set that doesn't visibly exist. On a site whose brand is receipts, this is a borrowed-authority sentence with no receipt.

apex/antivirus/index.html:216
Every expert roundup we cite puts those above scanner brand choice.

A skeptical reader who tries to follow this claim finds nothing to follow, and starts wondering how many of the page's other confident claims are equally unbacked.

fix — Either name and hyperlink the expert roundups being referenced or rewrite the sentence to drop 'we cite' (e.g. 'Every serious security guide puts those above scanner brand choice', with a link).

this line
SG-016
embarrassing claim-code-contradiction 2/4 lenses

Disclosure promises pending partners get a dead placeholder, but /go/ redirects for pending brands are live.

ExpressVPN and 1Password are listed as pending partner applications, yet apex/go/expressvpn and apex/go/1password ship instant, working redirects to the vendors — not dead placeholders. They carry no tracking IDs today, but the mechanism is identical to the live affiliate redirects (/go/hidemy, /go/nordpass), so the URL can silently become a tracking link the day an application is accepted, with no visible change for the user.

claim — apex/disclosure.html:67
Pending programs show a dashed “pending” badge and a dead placeholder — never a live tracking URL.
ships — apex/go/expressvpn/index.html:8
<script>location.replace('https://www.expressvpn.com/');</script>

A wary buyer who audits the disclosure against the site finds the very first checkable mechanical claim is not literally true, which makes the rest of the labeling promises feel aspirational rather than enforced.

fix — In apex/go/, find every pending-brand redirect (search for 'location.replace' in apex/go/expressvpn/ and apex/go/1password/) and replace the meta refresh and script with a non-redirecting placeholder page stating the program is pending with no live link.

sweep all instances
SG-017
embarrassing disorienting-redirect 2/4 lenses

Partner redirect pages show a raw gibberish tracker URL instead of the destination brand name

The NordVPN and Surfshark /go/ pages display an opaque affiliate-network domain (anrdoezrs.net, jdoqocy.com on apex/go/surfshark/index.html line 11) as the visible destination. A visitor who clicks "NordVPN" and glimpses this page — or lands on it with JS off or a slow connection — sees what looks like a malware redirect, not NordVPN.

apex/go/nordvpn/index.html:11
Redirecting to <a href="https://www.anrdoezrs.net/click-101847653-15545954" rel="sponsored noopener">https://www.anrdoezrs.net/click-101847653-15545954</a> (partner link — may earn commission)…

At the exact moment of conversion, the site that preaches trust hands the visitor a link that looks like a phishing hop. Cautious readers — the site's target audience — will close the tab rather than click a domain of random consonants. Saying 'Redirecting to NordVPN (partner link)' would keep the honesty without the scare.

fix — In every apex/go/*/index.html, change the visible anchor text from the raw tracker URL to the destination brand name (e.g. 'Redirecting to NordVPN (partner link — may earn commission)…') while keeping the href; search for 'anrdoezrs.net' and any other affiliate-network domains used as link text.

sweep all instances
SG-018
embarrassing cross-page-inconsistency 2/4 lenses

Two sibling data-removal guides disagree on whether DROP enforcement is a done fact or still in flux

One guide states as settled fact that enforcement "began August 1, 2026" and names a portal URL; the other guide — updated three days later (2026-08-04) — still describes DROP as a "direction" whose "process details will keep moving." A reader following the internal link between these two pages gets two different pictures of the same law in the same week.

claim — apex/guides/how-data-brokers-get-your-data.html:96
The state’s Delete Act portal (consumer.drop.privacy.ca.gov) makes registered brokers honor one deletion request within 90 days, with suppression lists so you stay deleted. Enforcement began August 1, 2026.
ships — apex/guides/data-removal-diy-vs-paid.html:108
California’s Delete Act / DROP direction (consumer-facing phase and broker compliance dates in 2026 per our snapshot) is worth tracking if you’re a CA resident — process details will keep moving.

Californians are the exact audience for this advice, and the site's differentiator is precision. Contradicting itself on a legal effective date — the most checkable kind of claim — makes a careful reader doubt every other dated claim, and the unlinked portal URL cannot be sanity-checked from the page.

fix — Update data-removal-diy-vs-paid.html line 108 to the same settled facts as how-data-brokers-get-your-data.html line 96 (DROP portal live at consumer.drop.privacy.ca.gov, enforcement began August 1 2026) so both guides agree.

this line
SG-019
embarrassing claim-code-contradiction 2/4 lenses

Quiz result note references a "Bitwarden link above" that does not exist — only the partner button is clickable

In the "dedicated manager" verdict card, Bitwarden appears as plain unlinked text (line 417) while NordPass gets a styled "Try NordPass free" partner button. The cta-note's claim about a "Bitwarden link above" is false — there is no anchor — so the only one-click action in the verdict is the commission-earning one.

claim — apex/password-managers/index.html:421
Bitwarden link above earns us nothing
ships — apex/password-managers/index.html:417
<li><strong>Budget-first:</strong> Bitwarden — free tier syncs unlimited devices; $19.80/yr for Premium. Not a partner link.</li>

A visitor who takes the budget-first advice goes to click Bitwarden and finds nothing clickable, while the paid path is a big button. That asymmetry is exactly the soft steering the site denounces, and the inaccurate note makes it look deliberate rather than sloppy.

fix — Wrap 'Bitwarden' at line 417 in a real anchor (<a href="https://bitwarden.com/" target="_blank" rel="noopener noreferrer">Bitwarden</a>) so the 'Bitwarden link above earns us nothing' note is true.

this line
SG-020
embarrassing placeholder-leak 2/4 lenses

The privacy contact email admits it may not actually receive mail

The only contact channel on the privacy policy is privacy@hexento.com, immediately undercut by a parenthetical saying the mailbox may not be set up yet. That is builder-scaffolding language shipped to production on the trust-surface page.

apex/privacy.html:70
(mailbox may be enabled after DNS mail setup)

A visitor with a privacy question is handed an address that the site itself says might be a black hole. It signals the site is half-launched and that accountability promises (contact, recourse) are decorative.

fix — Delete the parenthetical '(mailbox may be enabled after DNS mail setup)' at line 70 and verify privacy@hexento.com actually receives mail before shipping.

this line
SG-021
embarrassing dev-note-leak 2/4 lenses

The privacy policy's only contact address admits it may not receive mail

The Contact section offers privacy@hexento.com followed by a parenthetical operations note that the mailbox "may be enabled after DNS mail setup" — i.e., privacy questions sent to the published address may silently vanish.

claim — apex/privacy.html:70
(mailbox may be enabled after DNS mail setup).
ships — apex/privacy.html:69
Privacy questions: <a href="mailto:privacy@hexento.com">privacy@hexento.com</a>

A visitor with a privacy question is handed an address the site itself says might not work; it reads as an internal TODO shipped to production on the page where reliability matters most.

fix — Delete the parenthetical "(mailbox may be enabled after DNS mail setup)." from apex/privacy.html line 70 and only publish privacy@hexento.com once the mailbox actually receives mail (otherwise substitute a working contact method).

this line
SG-022
embarrassing selective-omission 2/4 lenses

Optery is named the best-tested paid service, then omitted from the "Your options, priced honestly" table

The page cites Optery as the top paid performer in the Consumer Reports test, but the options table (lines 108–158) lists only DIY, DROP, EasyOptOuts, Incogni, and DeleteMe. The untested Incogni — the site's pending affiliate application — gets a row; the best-measured paid service gets none.

claim — apex/privacy/index.html:85
DeleteMe (27%) and the best performer Optery (68%)
ships — apex/privacy/index.html:144
<th scope="row">Incogni</th>

A careful reader asks the obvious question: if you know the best-tested paid option, why isn't it in a table titled "priced honestly"? The pattern (pending-partner in, non-partner best-performer out) looks like partner-pipeline bias on the one page that currently brags about having no partner links.

fix — Add an Optery row (price, model, 68% CR removal rate, catch) to the 'Your options, priced honestly' table so the best-measured paid service the page itself cites is listed.

this line
SG-023
embarrassing partner-bias 2/4 lenses

The one VPN with zero audits in 19 years gets the longest, warmest write-up — and a commission link

HideMy.Name's "Often fits" paragraph is roughly three times longer and far more effusive than any other option's, complete with heroic framing, while the page's own comparison table scores its no-logs audit column a red "None — ever (19 yrs)" and its jurisdiction as "Belize entity; ex-RU roots." It is also one of only three options carrying a live partner button, and the price-line admits the site "now lives at hide.mn."

claim — apex/vpn/index.html:289
a documented spine: it fought Russia’s censor in court, won delisting in 2019, became the first VPN ever to sue Roskomnadzor (2023) — and got branded a “foreign agent” for it.
ships — apex/vpn/index.html:116
<td class="bad">None — ever (19 yrs)</td>

A stranger comparing slots notices the obscure, unaudited, ex-Russian service gets the most enthusiastic sales copy on a page that preaches "evidence over adjectives" and "payout never overrides." The obvious inference — it's here because the affiliate program accepted them — undercuts the site's core promise even though the downsides are disclosed.

fix — Cut the HideMy.Name 'Often fits' paragraph at line 289 to the same length and temperature as the other slots' fit paragraphs, reducing the Roskomnadzor history to one neutral clause.

this line
SG-024
embarrassing partner-bias 2/4 lenses

Commission rows are the only visually highlighted rows in tables that claim commission-neutral presentation

Sorting is genuinely by total cost, but cost.js applies the "hl" highlight class if and only if a row has a partner link (line 219), and the VPN hub's renewal table does the same (tr class="hl" on exactly NordVPN, Surfshark, HideMy.Name at lines 86, 94, 110). Nothing on either page discloses that the visual emphasis maps one-to-one to commission.

claim — apex/vpn/true-cost/index.html:74
Rows are sorted by <em>your chosen horizon’s total cost</em>,
ships — apex/vpn/true-cost/cost.js:219
if (p.link.type === "partner") tr.className = "hl";

A visitor scanning the table has their eye pulled to precisely the rows that pay the site, under a disclosure that talks only about sort order. When they notice the pattern — Mullvad and Proton never highlighted — the "never by commission" promise reads as technically true and practically hollow.

fix — Remove the commission-mapped highlight: search for 'tr.className = "hl"' in cost.js (line 219) and '<tr class="hl">' in apex/vpn/index.html (lines 86, 94, 110) and either drop the partner-conditional styling or apply/disclose it on a non-commission basis.

sweep all instances
SG-025
embarrassing claim-code-contradiction 2/4 lenses

The README's exhaustive partner list omits hide.me, which ships as a live commission-earning CJ link.

The README states the partner set is NordVPN, Surfshark, and NordPass, but go/hidemy/index.html carries a CJ click URL and is explicitly labeled a commission link. The site's own disclosure documentation is out of sync with what actually earns money.

claim — tools/pickguard/README.md:19
Partner links (NordVPN, Surfshark, NordPass = Active CJ) route through `/go/<id>/`
ships — tools/pickguard/go/hidemy/index.html:11
rel="sponsored noopener">https://www.dpbolvw.net/click-101847653-15618467</a> (partner link — may earn commission)…

For a site whose entire pitch is a 'visible, deterministic rubric' and honest disclosure, an undisclosed fourth partner is precisely the kind of discrepancy that makes a skeptical visitor assume the transparency framing is marketing rather than practice.

fix — Update tools/pickguard/README.md line 19 to include hidemy in the Active CJ partner list: "(NordVPN, Surfshark, NordPass, HideMy.Name = Active CJ)".

this line
SG-026
embarrassing misleading-cta 2/4 lenses

The 'Visit Apple Passwords / Google PM' button sends visitors to another Hexento article, not the product.

Every result card gets a 'Visit <name>' button, but the built-in option's outbound URL is a hexento.com guide page. A user clicking 'Visit Apple Passwords / Google PM' expects Apple or Google and lands on more of the site's own content.

claim — tools/pickguard/src/app.js:203
rel="${opt.partner ? "sponsored noopener noreferrer" : "noopener noreferrer"}">Visit ${escapeHtml(opt.name)}</a>
ships — tools/pickguard/src/catalog.js:151
outbound: "https://hexento.com/guides/password-manager-vs-built-in.html",

A button that says 'Visit X' and delivers 'read our other article' feels like a content-farm trick, especially right under a note bragging 'Not a partner link — no commission on this one.'

fix — For the builtin option, relabel the CTA to match the destination (e.g. 'Read our built-in vs. manager guide') or change its outbound in catalog.js line 151 to the vendors' actual product pages.

this line
SG-027
embarrassing conflict-of-interest-optics 2/4 lenses

The only obscure, never-audited VPN in the 'curated' six-option catalog happens to be a paying partner.

Mullvad, Proton, Nord, Surfshark, ExpressVPN are household names; HideMy.Name is the lone oddball, carries a devastating caveat list, gets a glowing court-battle blurb — and is the fourth commission partner. Its presence in a deliberately small curated set reads as pay-to-play.

claim — tools/pickguard/src/catalog.js:81
No independent audit in 19 years; streaming unreliable in recent tests; apps still ship PPTP/L2TP (WireGuard via manual config); no Android kill switch; 5 devices must each use a different server.
ships — tools/pickguard/index.html:122
4–6 options per category, curated against a <a href="https://hexento.com/methodology/">public methodology</a> — not an exhaustive market map.

A skeptical visitor pattern-matches instantly: 'why is this random unaudited VPN sitting next to Mullvad? Oh — affiliate link.' That one inclusion undercuts 'curated against a public methodology' and 'commission never moves a score' more than any single sentence could.

fix — Either drop hidemy from the curated VPN catalog or add a visible editorial justification for including a never-audited partner, and add HideMy.Name to the partner list in index.html line 118 which currently omits it.

restructure
SG-028
embarrassing insider-meta 1/4 lenses

The About page defines the brand mostly by negating affiliate-industry slop tropes visitors have never heard of.

Fake labs, invented mastheads, stock-photo team pages, "we tested 47 products" (line 95), "synonym listicles" (line 77) — this is discourse aimed at people who audit affiliate sites, not at a consumer choosing a VPN. Whole sections read as a rebuttal to critics rather than an introduction for readers.

apex/about/index.html:71
There is no twelve-person “research lab,” no invented editorial masthead, and no stock-photo team page.

A first-time visitor is handed a tour of scams they weren't worried about until now, delivered in industry-insider vocabulary. Protesting honesty this hard, in this register, makes a normal reader wonder why the defense was necessary.

fix — Rewrite the About page's negation-heavy passages (lines 71, 77, 95) to describe what Hexento does for readers, cutting insider references to fake labs, invented mastheads, stock-photo team pages, 'we tested 47 products', and 'synonym listicles'.

restructure
SG-029
embarrassing stale-claim 1/4 lenses

The evidence table claims August 2026 currency while its AV-Comparatives column cites a Jul–Oct 2025 test window.

The caption asserts these are the most recent public results as of 2026-08-01 and even admits both labs retest continuously, yet the AV-Comparatives Real-World column is a window that ended ten months earlier while the AV-TEST column cites Jan–Apr 2026 rounds. By August 2026 a newer Real-World series would almost certainly be published, making the 'most recent' framing likely false for that column.

claim — apex/antivirus/index.html:71
Most recent public results as of 2026-08-01. Both labs retest continuously; scores move.
ships — apex/antivirus/index.html:77
AV-Comparatives Real-World (Jul–Oct 2025)

The whole lede is 'backed by current lab data.' A skeptic who visits av-comparatives.org and finds a newer report the page ignored will stop believing every other number on the site, including the renewal-price claims.

fix — Update the AV-Comparatives column (header line 77 and its cells) to the latest published Real-World round, or reword the caption to state the actual date of each lab's cited round instead of claiming 'most recent as of 2026-08-01'.

this line
SG-030
embarrassing ranking-follows-money 1/4 lenses

The commission-free antivirus page steers the freed budget into the site's monetized password-manager category.

The page boasts 'no partner links at all — nothing here earns us a cent,' then its top recommendation is to spend the antivirus money on a password manager instead — the exact category where the disclosure says a live NordPass affiliate deal exists (PM hub and Pickguard). The security advice is defensible, but the incentive adjacency is never acknowledged on this page.

claim — apex/antivirus/index.html:120
money on a password manager or backups — they close bigger risks.
ships — apex/disclosure.html:52
<strong>NordPass</strong> (on the <a href="/password-managers/">password manager hub</a> and Pickguard),

A skeptical buyer who follows the money notices the 'buy nothing' page only exists where there is nothing to sell, and that its call to action routes spend toward pages that do pay commissions — a pattern that undercuts the halo the no-affiliate banner creates.

fix — Where the antivirus page steers readers to password managers (the card at lines 118-120 and the FAQ at line 216), add a brief note that the linked password-manager hub contains labeled partner links.

this line
SG-031
embarrassing hedged-attribution-mismatch 1/4 lenses

Search snippet hedges the study as "Consumer Reports-style" while the page cites Consumer Reports itself

The meta description says "Consumer Reports-style testing," implying an imitation of CR methodology, but the body directly attributes the numbers to "Consumer Reports’ August 2024 four-month study." One of these framings is wrong.

claim — apex/guides/data-removal-diy-vs-paid.html:7
Consumer Reports-style testing found manual opt-outs removed more listings than a major paid service.
ships — apex/guides/data-removal-diy-vs-paid.html:66
In Consumer Reports’ August 2024 four-month study, manual opt-outs removed about

A visitor arriving from a search result that said "Consumer Reports-style" and then reading a direct CR citation registers a small bait-and-hedge; on a site whose whole brand is precise attribution, that inconsistency is noticed.

fix — Change the meta description on data-removal-diy-vs-paid.html line 7 from 'Consumer Reports-style testing' to 'Consumer Reports testing', matching the body's direct attribution at line 66.

this line
SG-032
embarrassing disclosure-inconsistency 1/4 lenses

Data-removal disclosures disagree: vague 'partners when live' on one guide, 'one pending application' on another

One data-removal guide discloses ambiguously ('may earn... when those programs are live'), while the other states precisely that there is exactly one pending, unlinked partner application (Incogni). A reader cannot tell from the DIY guide whether money is flowing today, and the precise version proves the vague version could have been specific.

claim — apex/guides/data-removal-diy-vs-paid.html:58
Hexento may earn commissions from data-removal partners when those programs are live.
ships — apex/guides/how-data-brokers-get-your-data.html:57
Hexento has a pending partner application with one data-removal service

Disclosure near a buying decision is where a wary consumer looks hardest. Getting a fog-of-war answer on one page and a precise answer on its sibling suggests the vagueness is a choice, which taints the site's otherwise strong disclosure habit.

fix — Rewrite the disclosure on data-removal-diy-vs-paid.html line 58 to the same precise status as how-data-brokers-get-your-data.html line 57: 'No data-removal partner links are live today; one application is pending (Incogni, unlinked until accepted).'

this line
SG-033
embarrassing overclaim-vs-own-data 1/4 lenses

'Beating every paid service tested' oversells the site's own 'about 70%' vs 'about 68%' near-tie

The 'Receipts' box frames DIY as decisively beating every paid service, but the sibling guide's own numbers show manual at 'about 70%' versus Optery at 'about 68%' — a two-point gap inside the site's own rounding language. One page presents nuance; the other converts it into a slogan.

claim — apex/guides/how-data-brokers-get-your-data.html:103
approach removed <strong>70%</strong> of found records in four months, beating every paid service tested.
ships — apex/guides/data-removal-diy-vs-paid.html:67
<strong>70%</strong> of tested listings; Optery about <strong>68%</strong>; EasyOptOuts about <strong>65%</strong>

A reader who opens both guides sees the same study told two ways — measured on one page, triumphal on the other. That is the exact 'spin the data toward the free-content halo' move the site claims to be above, and it makes the reader re-check every other stat.

fix — Change 'beating every paid service tested' on how-data-brokers-get-your-data.html line 103 to language matching the sibling page's numbers, e.g. 'narrowly edging the best paid services (about 70% vs Optery's 68%) and far outperforming others'.

this line
SG-034
embarrassing claim-content-contradiction 1/4 lenses

'These are not vibes' introduces a price list where a third of the rows are ± guesses from unnamed trackers

The list that follows this declaration includes Surfshark's renewal as '~$79/yr ±' sourced to unnamed 'trackers' and ExpressVPN as '~$69.72 / 28 mo ±' with 'checkout often bot-blocked; treat as approximate'. Figures a buyer cannot trace to any named source, with explicit approximation flags, are closer to vibes than the intro admits.

claim — apex/guides/vpn-renewal-trap.html:70
These are not vibes. They’re vendor fine print, payments APIs, or tracker-corroborated figures
ships — apex/guides/vpn-renewal-trap.html:87
(ToS confirms a jump; dollar figure via trackers when the storefront is coy).

A skeptical buyer doing renewal math notices the confident framing collapses into tildes and plus-minus signs two rows later. The honesty of the ± flags is good; the 'not vibes' chest-thump above them reads as marketing and undercuts it.

fix — Soften vpn-renewal-trap.html line 70 to admit the mix, e.g. 'Where vendors print the number, we quote it verbatim; where they hide it, figures below are marked approximate' — or move approximate rows under an explicit 'estimated' label.

this line
SG-035
embarrassing operator-plumbing-leak 1/4 lenses

Consumer prose narrates the site's own scraping operations ('bot-blocked', 'via trackers', 'payments APIs').

The pricing bullets describe how the numbers were harvested from the operator's point of view: ExpressVPN's 'checkout often bot-blocked', Surfshark's 'dollar figure via trackers when the storefront is coy' (line 87), and sourcing from 'payments APIs, or tracker-corroborated figures' (line 70). That is data-collection ops talk, not buyer guidance.

apex/guides/vpn-renewal-trap.html:92
(checkout often bot-blocked; treat as approximate until you see your own receipt).

A shopper just wants the renewal price; instead they learn the site runs bots against vendor checkouts. It shifts the register from 'editor who checked' to 'scraper log', and makes a careful reader wonder how sturdy any of the figures are.

fix — Search for 'bot-blocked', 'via trackers', 'tracker-corroborated', and 'payments API' in guide prose and rewrite each aside in reader-facing language (e.g. 'we could not fully confirm this at checkout — verify against your own receipt').

sweep all instances
SG-036
embarrassing audience-mismatch 1/4 lenses

A consumer FAQ answer leans on unexplained ad-industry jargon ('intro ARPU ads convert').

ARPU is subscription-analytics vocabulary; 'ads convert' is marketer shorthand. The FAQ is answering an ordinary buyer asking why vendors hide renewal prices, and the answer is written for someone who reads growth dashboards.

apex/guides/vpn-renewal-trap.html:169
Because intro ARPU ads convert and renewals pay the bills.

The reader this page courts — someone burned by a surprise renewal — hits an acronym from the vendor's side of the table and bounces off the one sentence meant to explain the trap to them.

fix — Rewrite the FAQ answer's first sentence in plain English, e.g. 'Because the cheap intro price is what wins the ad click, and renewals are where the money is.'

this line
SG-037
embarrassing internal-vocabulary-leak 1/4 lenses

In-house research-pipeline vocabulary ('snapshot') is used in visible prose across at least four pages.

The meta lines say 'prices from snapshot', 'study refs from snapshot' (data-removal-diy-vs-paid line 56), 'corporate facts from snapshot' (sibling-vpn-brands line 56); body copy says 'per our snapshot' (data-removal-diy-vs-paid line 108), 'Snapshot reality check' (line 137), '(2026-08 snapshot)' (security-stack-order line 126). 'Snapshot' is the team's internal data-ops term used as if readers know the pipeline; plain register would be 'prices checked 2026-08-01'.

apex/guides/vpn-renewal-trap.html:55
· prices from snapshot <time datetime="2026-08-01">2026-08-01</time>

First-time visitors have to reverse-engineer house jargon to learn a simple fact — when the numbers were checked. It quietly signals the page was written for the people who maintain the dataset, not the people reading it.

fix — Search for the word 'snapshot' across all guide pages and replace each instance with plain phrasing such as 'checked 2026-08-01' or 'as of our August 2026 price check'.

sweep all instances
SG-038
embarrassing audience-mismatch 1/4 lenses

Enterprise-networking jargon ('ZTNA') and retail-catalog jargon ('SKU') land unexplained in a beginner skip-list.

This bullet targets the least-technical readers — people who bought the fear ad — yet resolves in two initialisms neither audience half is guaranteed to know. 'SKU' recurs as house shorthand elsewhere ('per SKU', vpn-renewal-trap line 112; 'each SKU is best in class', sibling-vpn-brands line 81).

apex/guides/when-you-dont-need-a-vpn.html:82
You need employee identity / company access — that’s corporate ZTNA, not a consumer streaming SKU.</li>

A reader who doesn't know ZTNA can't tell whether the bullet describes them, so the skip signal — the page's whole product — fails exactly for the visitor it was written to protect.

fix — Search for 'ZTNA' and 'SKU' across all guide pages and replace with plain terms (e.g. 'your company's remote-access system', 'plan' or 'product').

sweep all instances
SG-039
embarrassing claim-content-contradiction 1/4 lenses

Homepage promises cited, dated tests, but pages lean on uncited, undated test claims.

The VPN hub asserts HideMy.Name streaming is 'unreliable in recent independent tests' with no tester named and no date, and the comparison table credits Mullvad with 'Regular third-party audits' with no auditor or year — despite the methodology's own rule that security claims 'cite the auditor and year where one exists' (line 113).

claim — apex/index.html:233
Not a fake lab. If we didn’t run a test, we don’t claim we did — we cite who did, with dates.
ships — apex/vpn/index.html:290
streaming unreliable in recent independent tests

The whole anti-content-farm pitch rests on sourcing discipline. The first uncited 'independent tests' hand-wave a reader finds makes the meticulously dated claims elsewhere look like selective rigor rather than a standard.

fix — Add source and date to every uncited test/audit claim: search apex/vpn/index.html for 'recent independent tests' (line 290) and 'Regular third-party audits' (line 124) and name the tester/auditor and year, or cut the claim.

sweep all instances
SG-040
embarrassing internal-jargon 1/4 lenses

Pages are labeled with the operator's planning term 'Trust surface' instead of language for the reader

The eyebrow over 'How we score' (and again over Privacy, apex/privacy.html line 37) is the builder's internal taxonomy — 'trust surface' is conversion-playbook vocabulary for methodology/about pages, printed where a reader-facing label belongs.

apex/methodology/index.html:49
<p class="eyebrow">Trust surface</p>

Readers who know the affiliate-SEO playbook recognize its vocabulary on a site whose pitch is rejecting that playbook; everyone else reads a label that describes the page's role in the funnel, not its content.

fix — Search all pages for the exact string "Trust surface" and replace the eyebrow with reader-facing wording such as "Our rulebook" or "How we work".

sweep all instances
SG-041
embarrassing claim-code-contradiction 1/4 lenses

Password audit promises answers stay in the browser, then sends an answer-derived verdict to analytics

After the quiz runs, the page fires tool_complete with best_code encoding the verdict (line 436) and score_tier encoding whether hygiene answers were bad (line 437: fixes.length ? "fix_first" : "clean"). The verdict is a direct function of the eco and share answers, so a compressed form of the user's answers does leave the browser despite the promise.

claim — apex/password-managers/index.html:68
Answers stay in your browser.
ships — apex/password-managers/index.html:436
best_code: needsDedicated ? "dedicated" : "builtin",

Weaker than the exposure-check case but the same pattern: a security-literate visitor checking the network tab sees an event describing their quiz outcome right after being told answers stay local, and starts reading every other claim on the site adversarially.

fix — Remove best_code and score_tier from the pm_audit tool_complete H.track payload (lines 434-438), or amend 'Answers stay in your browser.' at line 68 to disclose the anonymous completion event.

this line
SG-042
embarrassing tone-drift 1/4 lenses

The partner-linked HideMy.Name slot swells into hero-narrative copy several times longer than non-partner slots

Every other slot's 'Often fits' runs 30–50 clipped words; the HideMy.Name fit paragraph runs ~130 words of underdog storytelling ('a documented spine'), for the page's only never-audited option — which happens to be a live partner link. The frank 'Watch' paragraph offsets it only partially.

apex/vpn/index.html:289
and a documented spine: it fought Russia’s censor in court, won delisting in 2019, became the first VPN ever to sue Roskomnadzor (2023) — and got branded a “foreign agent” for it.

The page promises 'constraint examples · not a ranking,' but the warmest, longest prose gravitating to a commission link is exactly the sponsorship gravity the site claims to have escaped; a wary stranger feels the thumb on the scale through the tone alone.

fix — Trim the HideMy.Name 'Often fits' paragraph at apex/vpn/index.html line 289 to the ~40-word clipped register of the other slots, cutting the 'documented spine' hero narrative or moving the litigation history to a neutral one-line aside.

this line
SG-043
embarrassing ranking-follows-money 1/4 lenses

Table rows are visually highlighted solely because they carry a commission link.

The calculator code applies the highlight class purely from partner status — Mullvad and Proton Free never get emphasis regardless of being cheapest. The static VPN hub table mirrors this (hl on exactly the NordVPN, Surfshark, HideMy.Name rows at lines 86/94/110), as does the PM hub (NordPass row, line 106). Nothing on either page tells the reader the highlight means 'paid partner'.

claim — apex/vpn/true-cost/cost.js:219
if (p.link.type === "partner") tr.className = "hl";
ships — apex/methodology/index.html:127
<li><strong>Commission rate.</strong> Payout never overrides a reputation or fit fail, and higher-paying programs get zero ranking benefit.</li>

The disclosure swears rows are 'sorted by total cost, never by commission' and the methodology promises 'zero ranking benefit' to paying programs — yet the eye is drawn to paid rows by an unexplained highlight. Sorting is honest; salience is not, and salience is what actually drives clicks.

fix — Remove partner-driven emphasis: in cost.js line 219 delete the `if (p.link.type === "partner") tr.className = "hl"` rule (or key hl to cheapest-total instead), and search all hub tables for `<tr class="hl">` to ensure highlighted rows are chosen editorially (e.g. best value) with a visible legend, not by partner status.

sweep all instances
SG-044
embarrassing operator-leak 1/4 lenses

A rendered row note tells shoppers that ExpressVPN's checkout blocked the site's scraper

sourceNote strings render verbatim under the calculator table (#source-notes, line 277). ExpressVPN's note narrates scraping operations ('blocked automated verification') and an internal editorial decision ('so it's omitted') as consumer copy.

apex/vpn/true-cost/cost.js:61
vendor checkout blocked automated verification. Monthly price reports conflict, so it’s omitted.

Mid-purchase-decision, the register jumps from buying advice to an engineering standup; a visitor learns the site runs bots that get blocked instead of what the price means for them. An editor would rewrite as 'we couldn't verify this at checkout.'

fix — Rewrite the ExpressVPN sourceNote in apex/vpn/true-cost/cost.js line 61 in reader-facing language, e.g. "Intro and $99.95/yr renewal corroborated by July 2026 trackers; we could not confirm at checkout. Monthly-plan price reports conflict, so no monthly row is shown."

this line
SG-045
embarrassing operator-content-leak 1/4 lenses

An operator document full of deploy and analytics detail lives inside the directory that ships to the web root.

The README (droplet paths, nginx layout, build commands, analytics event schema, local-server workarounds) sits in tools/pickguard, which deploy.sh copies to /var/www/pickguard. Unless deploy explicitly excludes it, hexento.com/pickguard/README.md becomes a live URL serving pure ops content — the same failure class as DNS-setup talk on a privacy page.

tools/pickguard/README.md:52
`./deploy.sh` → droplet `/var/www/pickguard`, served at `hexento.com/pickguard/` via nginx path.

A visitor or journalist who tries /pickguard/README.md gets the site's internal wiring — hosting, tracking plan, affiliate machinery — presented in developer register, which reframes the consumer tool as an operation being run on them.

fix — Update deploy.sh to exclude README.md, build_go.py, and deploy.sh from the copy to /var/www/pickguard (or move README.md out of the deployed directory).

this line
SG-046
embarrassing opaque-tracking-url 1/4 lenses

Partner redirect pages show a raw numeric CJ tracking URL on an unrecognizable domain instead of the vendor name.

The visible destination on the hidemy interstitial (and identically on nordvpn and nordpass, which show anrdoezrs.net URLs) is a bare affiliate-network click URL like dpbolvw.net/click-101847653-15618467. Nothing on the page says which product you are being sent to.

tools/pickguard/go/hidemy/index.html:11
<p>Redirecting to <a href="https://www.dpbolvw.net/click-101847653-15618467" rel="sponsored noopener">https://www.dpbolvw.net/click-101847653-15618467</a> (partner link — may earn commission)…</p>

This tool's audience is people shopping for VPNs and password managers — exactly the crowd trained to treat 'redirecting to dpbolvw.net/click-101847653-...' as a phishing or malware pattern. If the redirect stalls for even a second, the instinctive reaction is to close the tab and distrust the whole site.

fix — In build_go.py, render the vendor name on every partner redirect (title "Redirecting to NordVPN…", body "Taking you to NordVPN (partner link — may earn commission)") instead of printing the raw CJ click URL, then regenerate all /go/ pages — search for the pattern "Redirecting to <a href=\"https://www." to find instances.

sweep all instances
SG-047
embarrassing claim-overreach 1/4 lenses

The hero promises a visible rubric, but the actual scoring weights never appear anywhere on screen.

The UI shows dot chips (Privacy ●●●○○) and a final score, but the real rubric — base 40, ×8 priority multipliers, ±14 flat-pricing bonuses, normalization against a hypothetical perfect option — lives only in unrendered JavaScript. Line 118 repeats the claim: 'the rubric is on screen.'

claim — tools/pickguard/index.html:66
with the rubric visible
ships — tools/pickguard/src/catalog.js:282
let score = 40;

A visitor who takes the transparency pitch seriously and looks for the rubric finds only dots and an unexplained NN/100 number. The gap between 'visible rubric' and what is actually visible makes the transparency branding feel like marketing copy.

fix — Search for the exact strings "with the rubric visible" (line 66) and "the rubric is on screen" (line 118) and either soften them to match the dot-chip display or add an on-page "how scoring works" panel listing the real base, multipliers, and normalization.

sweep all instances
SG-048
embarrassing schema-vocab-leak 1/4 lenses

The hero lede's first sentence is un-English: visitors answer questions, they don't "answer constraints".

The internal data-model word — the CONSTRAINTS export in catalog.js — has been bent into visitor copy until grammar breaks. The same key drives the eyebrow ("Constrained chooser", line 62), the H1, the step heading, and the share text, so the page's opening line reads like the codebase talking.

tools/pickguard/index.html:65
Answer a few constraints. Get a best fit, a runner-up with a different tradeoff, or an honest

It is the first body sentence a visitor reads, and it doesn't parse as something a person would say. First-sentence oddness is where strangers decide whether a site was written for them.

fix — Rewrite the lede's first sentence at index.html line 65 as natural English, e.g. 'Answer a few quick questions about your constraints.'

this line
SG-049
embarrassing visible-duplication 1/4 lenses

Result cards print the same blurb sentence twice — once as the paragraph and again as the first 'why' bullet.

cardFor renders opt.blurb as the card paragraph, then whyBullets pushes opt.blurb again as a bullet for every password-manager result (line 355) and as the fallback for sparse VPN results (line 361). The identical sentence appears back-to-back on the most important screen.

claim — tools/pickguard/src/app.js:195
<p style="margin:0.2rem 0 0">${escapeHtml(opt.blurb)}</p>
ships — tools/pickguard/src/catalog.js:355
bullets.push(opt.blurb);

The results card is the payoff moment. Seeing the exact same sentence repeated two inches apart reads as sloppy machine-generated output and makes the visitor doubt whether any human checked the recommendations either.

fix — Search catalog.js for 'bullets.push(opt.blurb)' (lines 355 and 361), delete both, and replace with constraint-derived bullets so the card paragraph is never repeated verbatim as a 'why' bullet.

sweep all instances
SG-050
embarrassing trust-theater 1/4 lenses

The 'no commission on this one' badge is displayed on vendors the site is actively applying to monetize.

Result cards wear 'Not a partner link — no commission on this one' as a trust credential, but the catalog comment reveals affiliate applications are pending for ExpressVPN and Proton — the badge flips the moment CJ approves, with no editorial change. The label is monetization status, not editorial stance.

claim — tools/pickguard/src/app.js:191
Not a partner link — no commission on this one
ships — tools/pickguard/src/catalog.js:5
// expressvpn / proton = pending applications → plain vendor URLs, no tracking.

A buyer reads that badge as 'we recommend this against our own financial interest.' Learning it means 'we haven't been accepted into their program yet' reframes the badge as theater and taints the disclosure system it anchors.

fix — Reword the badge at app.js line 191 to a neutral factual status (e.g. 'No affiliate relationship for this link') and remove the pending-applications comment from shipped catalog.js line 5.

this line
SG-051
embarrassing rubric-inconsistency 1/4 lenses

Never-audited HideMy.Name gets the same 3/5 privacy dots as Deloitte-audited Surfshark.

The scoreboard chips show identical Privacy ●●●○○ for a provider with 'no independent audit in 19 years' and one the site itself describes as 'Deloitte-audited no-logs' — the visible rubric contradicts the visible prose.

claim — tools/pickguard/src/catalog.js:82
attrs: { privacy: 3, streaming: 2, value: 4, devices: 3, ease: 3, flat: true, renewal_jump: 0 },
ships — tools/pickguard/src/catalog.js:57
Unlimited simultaneous devices — the whole-household budget play. Deloitte-audited no-logs.

A visitor comparing chips against the caveats sees the numbers disagree with the words, which quietly undermines confidence that the scores mean anything at all.

fix — Lower hidemy's privacy attr in catalog.js line 82 (e.g. to 2) or raise surfshark's so the Deloitte-audited provider visibly outscores the never-audited partner on the Privacy chip.

this line
SG-052
embarrassing partner-puffery 1/4 lenses

The partner option HideMy.Name gets the longest, most romantic blurb in the catalog.

Every other blurb is one clipped sentence; the commission-paying HideMy.Name gets a two-sentence hero narrative ('endorsed', 'truly one-time', courtroom valor) that reads like ad copy, while its damning caveats are pushed into a separate field. 'Endorsed' by whom is never said.

claim — tools/pickguard/src/catalog.js:79
stockpiling for trips is endorsed, crypto (incl. Monero) makes it truly one-time. Fought Russia's censor in court
ships — tools/pickguard/src/catalog.js:24
blurb: "Flat €5/month, numbered accounts, Sweden. The calm-pricing privacy default.",

A skeptical reader comparing card tone across results will notice the paid option is the only one being sold rather than described — classic ranking-follows-money smell even if the score math were clean.

fix — Cut hidemy's blurb (catalog.js line 79) to one clipped factual sentence matching the catalog's house style and delete the unattributed 'endorsed'.

this line
SG-053
embarrassing claim-code-contradiction 1/4 lenses

The default password-manager run produces a four-way tie at 100/100, defeating the normalization's stated purpose.

With the default answers (priority=privacy, no toggles, budget=free), Bitwarden, KeePassXC, and Proton Pass each score exactly PERFECT's total (40+40+20=100), and the built-in option scores 102 via its +10 single-ecosystem bonus (which PERFECT, being builtin:false, never receives) before being clamped to 100. The 'Full scoreboard' renders 100/100, 100/100, 100/100, 100/100, 88, 88.

claim — tools/pickguard/src/catalog.js:248
/* A hypothetical perfect option used to normalize scores — keeps real options
 * differentiated instead of piling up at a clamped 100. */
ships — tools/pickguard/src/catalog.js:262
s.score = Math.max(0, Math.min(100, Math.round((s.score / perfect) * 100)));

A first-time visitor who just clicks 'Show my fit' on the password category sees four supposedly differentiated options all rated perfect — which looks like a broken or fake rubric on a page that says 'Transparency beats a black box.'

fix — Rework normalization so PERFECT is a strict ceiling in every branch (include the +10 builtin bonus case or add headroom to the denominator) and verify default password answers no longer produce multiple 100/100 ties; otherwise delete the 'keeps real options differentiated' comment.

restructure
SG-054
embarrassing internal-fact-contradiction 1/4 lenses

ExpressVPN is called the 'Priciest mainstream renewal' while NordVPN's own entry renews $39 higher.

ExpressVPN's renewal is listed as ~$99.95/yr (line 69), but NordVPN — equally mainstream, two cards away — renews at $139.08/yr per its own price_note. The superlative is contradicted by the site's own data on the same screen.

claim — tools/pickguard/src/catalog.js:70
caveat: "Priciest mainstream renewal; parent Kape's pre-2018 Crossrider history is documented.",
ships — tools/pickguard/src/catalog.js:47
price_note: "Basic: $94.23 first 27 months, then renews at $139.08/yr — their own fine print.",

A comparison shopper reading both cards side by side will spot the contradiction in seconds, and every other confident-sounding price claim on the page loses credibility with it.

fix — Remove or correct 'Priciest mainstream renewal' in catalog.js line 70, since NordVPN's own listed renewal ($139.08/yr, line 47) is higher than ExpressVPN's ~$99.95/yr.

this line
SG-055
embarrassing date-inconsistency 1/4 lenses

HideMy.Name's price note says checked 2026-08-02, one day after the sitewide 'catalog verified 2026-08-01' claim.

LAST_VERIFIED is '2026-08-01' and both the footer and the constraint-panel note render that date, yet the hidemy price_note visible on its result card claims a check on 2026-08-02. The two dates appear on the same page.

claim — tools/pickguard/src/catalog.js:80
$11/mo · $48/yr · $120/5yr, no intro/renewal gap documented (checked 2026-08-02).
ships — tools/pickguard/index.html:141
we may earn a commission at no extra cost to you. Catalog last verified 2026-08-01.

For a site whose differentiator is verification rigor, a verification date that postdates the declared 'last verified' stamp makes the whole verification claim look sloppy or invented.

fix — Update LAST_VERIFIED in catalog.js line 7 to "2026-08-02" (or re-date the hidemy price_note to 2026-08-01) so the card date and the sitewide verification date agree.

this line
SG-056
embarrassing operator-leak 1/4 lenses

Shipped source comments expose the affiliate back office: CJ program status, pending applications, build tooling.

catalog.js is fetched by every visitor's browser, and its header narrates the business side — which CJ programs are active, which affiliate applications are pending, and that redirects are "generated by build_go.py". This is operator log-keeping, not product content.

claim — tools/pickguard/src/catalog.js:5
// expressvpn / proton = pending applications → plain vendor URLs, no tracking.
ships — tools/pickguard/src/catalog.js:3
// Outbound URLs are wired via /go/<id>/ redirects generated by build_go.py.

Anyone who views source — likely on a site that dares you to inspect its rubric — reads that ExpressVPN and Proton recommendations are awaiting monetization. It reframes the editorial catalog as a revenue pipeline in progress.

fix — Delete the operator comments at catalog.js lines 3-5 (CJ program status, pending affiliate applications, build_go.py) from the shipped file and keep them in internal docs.

this line
SG-057
nit visible-typo 4/4 lenses

An unclosed parenthesis renders as "(stack order." in the DIY skip-box

The bullet opens a parenthesis before the stack-order link and never closes it, so the visitor sees "(stack order." mid-list.

apex/guides/data-removal-diy-vs-paid.html:88
(<a href="/guides/security-stack-order.html">stack order</a>.</li>

One stray paren in a cornerstone guide is exactly the kind of small sloppiness a skeptical first-time reader uses to gauge how carefully the numbers elsewhere were checked.

fix — On data-removal-diy-vs-paid.html line 88, change 'stack order</a>.</li>' to 'stack order</a>).</li>' to close the parenthesis opened before the link.

this line
SG-058
nit template-residue 3/4 lenses

The disclosure carries Amazon Associates boilerplate for a program the site has zero links to.

A dedicated section discloses Amazon affiliate participation while stating there are no such links, which reads as pre-emptive template text rather than a description of the actual site.

apex/disclosure.html:79
Where Amazon Associates links appear (none at present), we also use this disclosure:

It signals the disclosure was partly assembled from boilerplate, slightly diluting the impression that every line describes something real.

fix — Delete the 'Amazon' section (lines 77-81) from apex/disclosure.html until Amazon Associates links actually exist on the site.

this line
SG-059
nit unexplained-jargon 3/4 lenses

The Jump column's "+232%/mo" reads as a monthly compounding increase, not a one-time step-up

jumpPct computes the one-time percentage difference between the intro-term effective monthly rate and the renewal monthly rate (e.g., NordVPN 2yr: $3.49 → $11.59 = +232%), but the "/mo" suffix makes it look like the price rises 232% every month. The unit is never explained on the page.

claim — apex/vpn/true-cost/cost.js:237
: `<span class="up">+${jump}%/mo</span>`;
ships — apex/vpn/true-cost/index.html:102
<th scope="col">Jump</th>

The calculator's headline metric is momentarily unbelievable — "+232%/mo" looks like a bug or scare tactic — which is a bad flinch to trigger in a tool whose pitch is sober, honest math.

fix — In apex/vpn/true-cost/cost.js line 237, change the template from `+${jump}%/mo` to `+${jump}%` (or `+${jump}% at renewal`) so the one-time jump does not read as a monthly rate.

this line
SG-060
nit unfinished-todo 3/4 lenses

The README ships a live TODO admitting the analytics site does not exist yet.

'when the Umami site exists' is an unfinished-setup note left in the public-facing repo documentation for a tool described as a completed v1 rebuild.

tools/pickguard/README.md:48
No PII, no answer text. Wire the website id in `index.html` when the Umami site exists.

Anyone evaluating the project from its repo reads this as 'still half-wired', which slightly undercuts the polished, verified-catalog framing two sections above.

fix — Delete or update the sentence "Wire the website id in `index.html` when the Umami site exists." at README line 48, since index.html line 40 already ships the wired data-website-id.

this line
SG-061
nit weird-redirect 3/4 lenses

Choosing the built-in-password-manager option bounces through an external-style redirect to the site's own guide.

An internal guide page is served through the same /go/ interstitial used for external vendors, complete with a 'not a partner link' disclaimer that makes no sense for the site's own content.

tools/pickguard/go/builtin/index.html:11
Redirecting to <a href="https://hexento.com/guides/password-manager-vs-built-in.html" rel="noopener">https://hexento.com/guides/password-manager-vs-built-in.html</a> (not a partner link)…

A visitor sees a 'Redirecting…' flash and a disclaimer about partner status just to read another page on the same site — a small 'huh?' moment that makes the plumbing feel bolted together.

fix — Link the builtin option's recommendation directly to /guides/password-manager-vs-built-in.html (special-case internal targets in build_go.py/app.js) instead of generating a /go/builtin/ interstitial with a "(not a partner link)" label.

this line
SG-062
nit trust-theater 2/4 lenses

The disclosure page labels itself 'Trust surface,' exposing builder jargon that frames trust as a design artifact.

The rendered eyebrow above the Disclosure heading reads 'Trust surface' — internal growth/design vocabulary shipped to visitors, implying trust is a UI element being engineered rather than earned.

apex/disclosure.html:37
<p class="eyebrow">Trust surface</p>

A skeptical reader who catches the phrase gets a peek behind the curtain: the page is self-consciously performing trustworthiness, which is exactly the vibe a disclosure page must avoid.

fix — Change the eyebrow text at line 37 from 'Trust surface' to reader-facing wording such as 'Transparency'.

this line
SG-063
nit evidence-standard-inconsistency 2/4 lenses

Antivirus prices are given to the cent with no date or source, unlike the dated VPN prices

The VPN pages carefully stamp every dollar figure with a snapshot date and describe how each number was corroborated. The antivirus guide drops equally precise renewal figures with no date, source, or hedge — just "Last updated 2026-08-01" at the top of the page.

claim — apex/guides/do-you-need-antivirus.html:111
Norton 360 Deluxe: $49.99 first year, renews $119.99. Malwarebytes Ultimate: $139.99, renews $279.99. If a tier doesn’t publish its renewal rate (some don’t), treat that as your answer.
ships — apex/guides/vpn-renewal-trap.html:55
prices from snapshot <time datetime="2026-08-01">2026-08-01</time>

A visitor who reads both pages notices the double standard: one category gets receipts discipline, the other gets bare assertions. It quietly undercuts the methodology brand the site leans on everywhere else.

fix — Add a dated source note to the antivirus renewal-price bullet on do-you-need-antivirus.html line 111, e.g. '(vendor pricing pages, checked 2026-08-01)', matching the dating discipline of the VPN guides.

this line
SG-064
nit uncited-namedrop 2/4 lenses

A heading name-drops EFF but the section never cites or links EFF

The heading invokes 'EFF-style ordering' for authority; the body immediately retreats to the anonymous 'independent consumer-security education' and never links EFF material. The reader can’t tell whether EFF actually endorses this ordering.

claim — apex/guides/security-stack-order.html:144
<h2>What EFF-style ordering is really saying</h2>
ships — apex/guides/security-stack-order.html:146
Independent consumer-security education has repeated the same hierarchy for years:

Borrowing a trusted org’s name in a heading without a citation looks like authority-laundering to a skeptical reader — the exact move the page criticizes in vendors.

fix — Either link an actual EFF resource (e.g. Surveillance Self-Defense) in the section body on security-stack-order.html lines 144-150, or remove 'EFF-style' from the heading.

this line
SG-065
nit count-mismatch 2/4 lenses

Homepage badge says 'partners pending' (plural) for a hub that discloses exactly one pending application

The data-removal hub's disclosure says the site has applied to a single program in the category (Incogni), but the homepage badge pluralizes it as "partners pending".

claim — apex/index.html:130
<span class="badge badge-pending">partners pending</span>
ships — apex/privacy/index.html:59
We’ve applied to one program in this category (Incogni — pending, unlinked)

Trivial, yet on a site whose brand is precise partner accounting, plural-vs-one is the sort of drift attentive readers use to gauge how carefully everything else was checked.

fix — In apex/index.html line 130, change the badge text "partners pending" to "partner pending".

this line
SG-066
nit overclaim 2/4 lenses

Quiz claims every answer changes the verdict, but only two answers actually decide it

The verdict card (dedicated vs built-in) is determined solely by needsDedicated = eco === "mixed" || share === "often" (line 405). The other four answers only add or remove "fix first" advice items; toggling them never flips the verdict.

claim — apex/password-managers/index.html:396
<strong>Answer all six</strong> — each one changes the verdict.
ships — apex/password-managers/index.html:405
var needsDedicated = answers.eco === "mixed" || answers.share === "often";

A visitor who replays the quiz with different hygiene answers sees the same verdict and concludes the "each one changes the verdict" line is filler — a small crack in a site that stakes everything on saying only what's true.

fix — Change 'each one changes the verdict' at line 396 to 'each one shapes the advice' (matching the privacy hub's 'changes the plan' phrasing), since only the eco and share answers flip the verdict card.

this line
SG-067
nit disclosure-inconsistency 2/4 lenses

Top-of-page affiliate disclosure omits the Proton Pass pending application that the FAQ discloses.

The page's main disclosure block enumerates partner statuses but skips Proton Pass, which appears below as 'partner pending' (line 267) and is correctly listed alongside 1Password in the FAQ.

claim — apex/password-managers/index.html:59
1Password is a pending application (no link).
ships — apex/password-managers/index.html:313
1Password and Proton Pass are pending applications

Minor on its own, but on a site selling disclosure completeness, an enumeration that misses one of its own pending programs chips at the claim that the disclosure block is the authoritative surface.

fix — Change line 59 of the top disclosure to '1Password and Proton Pass are pending applications (no links).' so it matches the slot badge and FAQ.

this line
SG-068
nit internal-reference 2/4 lenses

The README's first link-like reference points to an internal path a repo visitor cannot follow.

Both the brief (earn/docs/tools/pickguard.md) and the affiliate source-of-truth (earn/docs/research/cj-active-links.md, line 36) are bare paths outside this tool's directory, unusable as links and referencing internal revenue-ops docs.

tools/pickguard/README.md:6
- **Brief:** `earn/docs/tools/pickguard.md`

A curious stranger's first click target in the README is a dead reference, and the visible mention of private affiliate-ops files makes the doc feel like internal notes accidentally published rather than a project front door.

fix — Search tools/pickguard/README.md for the pattern "earn/docs/" and remove or replace both internal path references (lines 6 and 35-36) with public equivalents or delete them.

sweep all instances
SG-069
nit inconsistent-dates 2/4 lenses

The footer's catalog-verified date is earlier than a 'checked' date shown inside a result card.

The footer (and LAST_VERIFIED, echoed in the chooser's catalog note) says 2026-08-01, but the HideMy.Name price note visitors see says its pricing was checked 2026-08-02.

claim — tools/pickguard/index.html:141
Catalog last verified 2026-08-01.
ships — tools/pickguard/src/catalog.js:80
no intro/renewal gap documented (checked 2026-08-02)

For a site whose differentiator is verified freshness, mismatched verification dates on the same screen make a careful reader wonder which date — if either — is real.

fix — Bump LAST_VERIFIED in catalog.js line 7 and the footer at index.html line 141 to 2026-08-02 so no visible per-option check date postdates the catalog-verified date.

this line
SG-070
nit confusing-microcopy 2/4 lenses

The streaming toggle's helper text 'if it's genuinely your job' is baffling on first read.

It presumably means 'only weight streaming if that's genuinely the job you're hiring the VPN for,' but as written it sounds like the toggle is reserved for professional streamers.

tools/pickguard/src/catalog.js:178
Only score this if it's genuinely your job

A first-time visitor pauses at a form control they don't understand; every 'huh?' in a two-step tool that promised 'under a minute' costs momentum and finishes.

fix — Rewrite the sub-label at catalog.js line 178 to plain language, e.g. 'Turn this on only if streaming is a main reason you're getting a VPN.'

this line
SG-071
nit unverifiable-citation 2/4 lenses

'Tracker-corroborated' cites unnamed trackers with no link, so the corroboration cannot be checked.

Two price notes lean on '(tracker-corroborated)' as evidence, but no tracker is ever named or linked from the rendered card; the reader is asked to trust an anonymous source. The header comment defers sourcing to 'hexento.com hubs' off-page.

claim — tools/pickguard/src/catalog.js:58
Starter: $67.23 first 27 months, then renews ~$79/yr (tracker-corroborated).
ships — tools/pickguard/src/catalog.js:2
// Facts snapshot: 2026-08-01 (vendor pages + corroborating trackers; see hexento.com hubs for sources).

Citation-shaped words without a checkable citation are trust theater; a skeptic reads 'tracker-corroborated' the same way they read 'studies show'.

fix — Search catalog.js for '(tracker-corroborated)' (lines 58 and 69) and either name and link the price tracker or delete the parenthetical.

sweep all instances
SG-072
nit protesting-too-much 1/4 lenses

The share-card description leads with denials of fraud nobody had yet accused the site of.

'No fake lab, no invented masthead' as the social preview means the very first thing a stranger reads is fraud vocabulary. The About body carries the same tic ('no twelve-person research lab,' 'no stock-photo team page'). Honesty is better demonstrated than announced.

apex/about/index.html:13
<meta property="og:description" content="A small honest brand for decision utilities. No fake lab, no invented masthead." />

Preemptive 'we're not scamming you' framing primes a first-time visitor to think about scams, and self-applied 'honest' labels are a pattern strangers have learned to discount.

fix — Rewrite the og:description at line 13 (and the matching twitter:description at line 20) to lead with visitor value, e.g. 'Small tools and guides that help you pick consumer security software — or skip the purchase.'

this line
SG-073
nit grammar-parallelism 1/4 lenses

The 'What we won't do' list mixes noun-phrase and verb-phrase items, so half the bullets don't follow the heading.

Items one and two are noun phrases ('Fake testimonials…', 'Scareware patterns…') that read as things-we-won't-do, but items three and four are bare verb phrases — 'What we won't do: Guarantee illegal outcomes' parses as a broken sentence.

claim — apex/about/index.html:97
Guarantee illegal outcomes, total anonymity, or permanent deletion from the internet.
ships — apex/about/index.html:95
Fake testimonials, fake lab counts, or “we tested 47 products” without a real method.

It's the page's ethics manifesto; uneven parallelism makes the most quotable list on the About page read as hastily assembled rather than carefully considered.

fix — Rewrite bullets one and two of the 'What we won't do' list (lines 95-96) to start with verbs — e.g. 'Publish fake testimonials…' and 'Use scareware patterns…' — so every item completes the heading.

this line
SG-074
nit audience-mismatch 1/4 lenses

The search-result description leads with internal positioning jargon: "one-operator brand for decision utilities".

"Decision utilities" and "one-operator brand" are strategy-memo vocabulary; this string is what a stranger sees in a Google result or link preview. The plain second half ("help you pick... or confidently skip the purchase") is the actual visitor-facing pitch buried behind it.

apex/about/index.html:7
Hexento is a small, one-operator brand for decision utilities — tools and guides that help you pick consumer security software, or confidently skip the purchase.

In a SERP full of competitors, the site introduces itself in words no consumer uses, and the term "decision utilities" recurs on-page (line 52), so the visitor hits the jargon twice before learning what the site does for them.

fix — Reorder the meta description at line 7 to open with the plain pitch — 'Tools and guides that help you pick consumer security software, or confidently skip the purchase' — and drop 'one-operator brand for decision utilities'.

this line
SG-075
nit sloppy-framing 1/4 lenses

"The honest options are on the same pages as the partner ones" implies the partner options are dishonest.

The sentence (completed on line 90: "are on the same pages as the partner ones.") means to say free/non-partner picks aren't hidden, but its wording sets "honest" and "partner" as opposites — undercutting the page's own claim that partner links don't corrupt recommendations.

apex/about/index.html:89
you can check us against it on any hub: the honest options

A careful reader catches the site accidentally conceding that its monetized recommendations sit outside the "honest" set.

fix — Replace 'the honest options' at line 89 with 'the free and non-partner options'.

this line
SG-076
nit claim-code-contradiction 1/4 lenses

The click-attribution fallback knows NordVPN, Surfshark, and NordPass but not HideMy.Name, a declared live partner.

Disclosure lists four live partners; the analytics href-sniffing fallback maps only three CJ ad IDs. HideMy.Name's ID (15618467, visible in apex/go/hidemy/index.html) is absent, so any HideMy.Name partner click without an explicit data-offer attribute is logged as offer 'unknown'.

claim — apex/analytics.js:140
if (href.indexOf("15545954") !== -1) offer = "nordvpn";
ships — apex/disclosure.html:49
<strong>NordVPN</strong>, <strong>Surfshark</strong>, and <strong>HideMy.Name</strong>

Invisible to visitors, but it shows the partner roster and the tracking code drifted apart — the same drift pattern that produced the visitor-facing disclosure mismatches.

fix — Add 'else if (href.indexOf("15618467") !== -1) offer = "hidemy";' to the href fallback chain in bindOutboundClicks (after line 142).

this line
SG-077
nit js-dead-queue 1/4 lenses

If the Umami script fails to load, every subsequent event is queued forever and never flushed or capped.

onerror sets ready = true but umami.track never exists, so track()'s condition stays truthy and every later call pushes into a queue nothing will ever drain. The 'queue-until-ready' design has no failure branch that stops queueing or bounds the array.

claim — apex/analytics.js:56
if (!ready || !(global.umami && typeof global.umami.track === "function")) {
ships — apex/analytics.js:111
s.onerror = function () {
      ready = true;
    };

No visible breakage, but on an ad-blocked visit (common for this privacy-minded audience) the page slowly accumulates dead event objects for the whole session — sloppy for a file whose header banner promises 'never break page' discipline.

fix — Change track() to queue only while the script may still arrive — push only when !ready, and once ready is true without umami.track drop the event (or cap the queue, e.g. if (queue.length < 50)).

this line
SG-078
nit garbled-superlative 1/4 lenses

The lede's key superlative is both ungrammatical and unverifiable.

Regulators fine companies, not records, so the sentence doesn't parse, and 'worst ... ever' is exactly the kind of sweeping claim the page elsewhere refuses to make. The rap-sheet section below supports a strong claim; this phrasing overshoots it in the very first paragraph.

apex/antivirus/index.html:54
this category has the worst renewal-pricing record regulators have ever fined.

The lede is the 30-second read. A garbled hyperbole there makes a careful reader stumble before reaching the genuinely well-sourced material.

fix — Rewrite the lede clause to a grammatical, verifiable claim, e.g. '— and this category has a renewal-pricing record regulators keep fining', removing 'worst … ever'.

this line
SG-079
nit unexplained-jargon 1/4 lenses

'Pickguard' sits unexplained in the primary nav on every page.

Four nav items are self-explanatory categories; 'Pickguard' is a coined product name (also literally a guitar part) with zero context in the nav. Only the About page explains it, and About isn't in the primary nav.

apex/antivirus/index.html:41
<a href="/pickguard/">Pickguard</a>

A first-time visitor scanning the nav can't guess what Pickguard is, and the flagship tool — the thing the site most wants clicked — is the one label that communicates nothing.

fix — Search every page for the primary-nav entry '<a href="/pickguard/">Pickguard</a>' and add context — a visible descriptor like 'Pickguard chooser' or a title attribute explaining it is the software-picking tool.

sweep all instances
SG-080
nit navigation-dead-end 1/4 lenses

The breadcrumb names a 'Decision hubs' level that is not a link and has no index page anywhere.

The breadcrumb implies a hubs directory exists between Home and Antivirus, but 'Decision hubs' is plain text and no such listing is linked from nav or footer. Meanwhile About — the who-are-you page — is absent from the primary nav entirely, reachable only via some footers.

apex/antivirus/index.html:48
<p class="crumbs"><a href="/">Home</a> · Decision hubs · Antivirus</p>

Minor friction: the visitor who wants 'show me all the hubs' or 'who runs this' finds the obvious click paths missing and has to guess at footer links instead.

fix — Search for '· Decision hubs ·' in the crumbs of every hub page and either link that level to a real hubs index page or remove it, leaving 'Home · Antivirus'.

sweep all instances
SG-081
nit asymmetric-evidence 1/4 lenses

The Norton row in the evidence table hand-waves its lab scores while every other row gets precise numbers.

Defender and Malwarebytes get exact scores and dates; Norton — the product the page most criticizes on renewals — gets 'scores competitively in both labs' and 'top cluster historically' with no figures or dates. An evidence table that goes vague exactly where the criticism is sharpest weakens its own standard.

apex/antivirus/index.html:99
<td class="muted">scores competitively in both labs</td>

A skeptic notices the asymmetry and wonders whether the vague cells are unchecked filler, which taints the credibility of the precise cells too.

fix — Replace the Norton row's 'scores competitively in both labs' and 'top cluster historically' cells (lines 99-100) with dated numeric lab scores matching the precision of the other rows.

this line
SG-082
nit awkward-phrasing 1/4 lenses

'Older laptops feel heavyweight suites the most' is a clipped construction that stumbles on first read.

'Feel' is used transitively with the suite as its object — the reader expects 'feel the weight of heavyweight suites' or 'feel it the most'. As written it momentarily parses as laptops touching software.

apex/antivirus/index.html:179
Older laptops feel heavyweight suites the most.

Minor, but it sits inside the constraint checklist that is the page's most practical section; each stumble accumulates against the crisp-editor persona the copy is selling.

fix — Rewrite to 'Older laptops feel the weight of heavyweight suites the most.'

this line
SG-083
nit defensive-meta 1/4 lenses

The regulatory-actions intro volunteers the denial "not allegations we invented".

No reader was wondering whether the site fabricates regulatory allegations until the sentence raised it. It belongs to the same protesting-too-much register as the About page's fake-lab denials.

apex/antivirus/index.html:146
not allegations we invented:

Unprompted denials of dishonesty make a neutral reader briefly consider the dishonesty; a citation list with sources needs no such caveat.

fix — Delete ', not allegations we invented' from lines 145-146 so the intro ends 'All documented public actions:'.

this line
SG-084
nit claim-code-contradiction 1/4 lenses

Disclosure promises rel="sponsored noopener noreferrer" but shipped partner links omit noreferrer.

The disclosure states tracked outbound links carry noreferrer, but the live partner redirects for HideMy.Name and NordPass ship rel="sponsored noopener" only. Tiny, but it's a testable promise on the trust page that the shipped code fails.

claim — apex/disclosure.html:66
Tracked outbound links use <code>rel="sponsored noopener noreferrer"</code>.
ships — apex/go/hidemy/index.html:11
rel="sponsored noopener"

Invisible to most visitors, but the exact kind of reader this disclosure courts — one who inspects link attributes — will find the site's most checkable promise is inaccurate.

fix — Search all pages for rel="sponsored noopener" and replace with rel="sponsored noopener noreferrer" on tracked partner anchors (or relax the disclosure bullet at line 66 to match what actually ships).

sweep all instances
SG-085
nit inconsistent-navigation 1/4 lenses

Every page ships a different footer link set: disclosure drops Pickguard, antivirus drops Methodology.

The About footer offers Home/Pickguard/Methodology/Disclosure/Privacy, the antivirus footer swaps Methodology for About, and the disclosure footer drops both Pickguard and Disclosure. The variation goes beyond omitting the current page — each footer is a different hand-rolled list.

claim — apex/disclosure.html:92
<nav aria-label="Footer">
        <a href="/">Home</a>
        <a href="/about/">About</a>
        <a href="/methodology/">Methodology</a>
        <a href="/privacy.html">Privacy</a>
      </nav>
ships — apex/about/index.html:120
<nav aria-label="Footer">
        <a href="/">Home</a>
        <a href="/pickguard/">Pickguard</a>
        <a href="/methodology/">Methodology</a>
        <a href="/disclosure.html">Disclosure</a>
        <a href="/privacy.html">Privacy</a>
      </nav>

Visitors learn footer geography quickly; links that appear and vanish between pages make the site feel stitched from copies rather than templated, a classic fast-built tell.

fix — Search for aria-label="Footer" across all pages and standardize every footer nav to one link set (Home, About, Methodology, Disclosure, Privacy), at most omitting the current page.

sweep all instances
SG-086
nit inconsistent-metadata 1/4 lenses

disclosure.html is the only reviewed page with no Open Graph or Twitter card metadata.

About and antivirus each carry a full og:/twitter: block with image dimensions; disclosure's head jumps straight from canonical to favicons. A share of the disclosure page renders a bare link card.

claim — apex/disclosure.html:9
<link rel="canonical" href="https://hexento.com/disclosure.html" />
ships — apex/about/index.html:10
<meta property="og:type" content="website" />

Small, but disclosure is exactly the page skeptical people share when vetting a review site; a naked link preview makes it look like the afterthought page.

fix — Insert a standard og:/twitter: metadata block (og:type, og:site_name, og:title, og:description, og:url, og:image with dimensions, twitter:card set) into apex/disclosure.html's head after the canonical link, matching the pattern used in apex/about/index.html lines 10-21.

this line
SG-087
nit missing-meta deterministic

The page head omits og:title.

apex/disclosure.html:3
<head> contains no og:title

Search results and link previews render this page worse than pages that ship complete metadata.

fix — Add the missing head elements: og:title.

this line
SG-088
nit missing-meta deterministic

The page head omits meta description, canonical, og:title, viewport.

apex/go/1password/index.html:3
<head> contains no meta description, no canonical, no og:title, no viewport

Search results and link previews render this page worse than pages that ship complete metadata.

fix — Add the missing head elements: meta description, canonical, og:title, viewport.

this line
SG-089
nit duplicate-title deterministic

24 pages share the identical title.

apex/go/1password/index.html:7 · apex/go/bitwarden/index.html:7 · apex/go/builtin/index.html:7 · apex/go/expressvpn/index.html:7 · apex/go/hidemy/index.html:7 · apex/go/keepassxc/index.html:7 · apex/go/mullvad/index.html:7 · apex/go/nordpass/index.html:7 · apex/go/nordvpn/index.html:7 · apex/go/proton_pass/index.html:7 · apex/go/proton_vpn/index.html:7 · apex/go/surfshark/index.html:7 · tools/pickguard/go/1password/index.html:7 · tools/pickguard/go/bitwarden/index.html:7 · tools/pickguard/go/builtin/index.html:7 · tools/pickguard/go/expressvpn/index.html:7 · tools/pickguard/go/hidemy/index.html:7 · tools/pickguard/go/keepassxc/index.html:7 · tools/pickguard/go/mullvad/index.html:7 · tools/pickguard/go/nordpass/index.html:7 · tools/pickguard/go/nordvpn/index.html:7 · tools/pickguard/go/proton_pass/index.html:7 · tools/pickguard/go/proton_vpn/index.html:7 · tools/pickguard/go/surfshark/index.html:7
<title>Redirecting…</title>

Identical tab titles make the pages indistinguishable in history, tabs, and search results.

fix — Give each page a distinct title; the duplicate is "Redirecting…".

sweep all instances
SG-090
nit missing-meta deterministic

The page head omits meta description, canonical, og:title, viewport.

apex/go/bitwarden/index.html:3
<head> contains no meta description, no canonical, no og:title, no viewport

Search results and link previews render this page worse than pages that ship complete metadata.

fix — Add the missing head elements: meta description, canonical, og:title, viewport.

this line
SG-091
nit missing-meta deterministic

The page head omits meta description, canonical, og:title, viewport.

apex/go/builtin/index.html:3
<head> contains no meta description, no canonical, no og:title, no viewport

Search results and link previews render this page worse than pages that ship complete metadata.

fix — Add the missing head elements: meta description, canonical, og:title, viewport.

this line
SG-092
nit missing-meta deterministic

The page head omits meta description, canonical, og:title, viewport.

apex/go/expressvpn/index.html:3
<head> contains no meta description, no canonical, no og:title, no viewport

Search results and link previews render this page worse than pages that ship complete metadata.

fix — Add the missing head elements: meta description, canonical, og:title, viewport.

this line
SG-093
nit scary-redirect 1/4 lenses

Clicking a partner link flashes a raw gibberish tracking URL (dpbolvw.net/click-101847653-...).

The interstitial honestly labels the commission, but what the visitor actually sees mid-redirect is an unexplained numeric URL on dpbolvw.net — a domain indistinguishable from malware redirectors to a normal person. Nothing on the page says 'this is the CJ affiliate network.'

apex/go/hidemy/index.html:11
Redirecting to <a href="https://www.dpbolvw.net/click-101847653-15618467" rel="sponsored noopener">https://www.dpbolvw.net/click-101847653-15618467</a> (partner link — may earn commission)…

A cautious user who clicked 'HideMy.Name' and lands on dpbolvw.net for a beat may abort the click or conclude the site is shady, despite the label doing the right thing.

fix — In every apex/go/*/index.html, search for 'Redirecting to <a href' and rewrite the visible body text to name the destination brand — e.g. 'Taking you to HideMy.Name (partner link — may earn commission)…' — keeping the raw URL in the href only.

sweep all instances
SG-094
nit missing-meta deterministic

The page head omits meta description, canonical, og:title, viewport.

apex/go/hidemy/index.html:3
<head> contains no meta description, no canonical, no og:title, no viewport

Search results and link previews render this page worse than pages that ship complete metadata.

fix — Add the missing head elements: meta description, canonical, og:title, viewport.

this line
SG-095
nit missing-meta deterministic

The page head omits meta description, canonical, og:title, viewport.

apex/go/keepassxc/index.html:3
<head> contains no meta description, no canonical, no og:title, no viewport

Search results and link previews render this page worse than pages that ship complete metadata.

fix — Add the missing head elements: meta description, canonical, og:title, viewport.

this line
SG-096
nit missing-meta deterministic

The page head omits meta description, canonical, og:title, viewport.

apex/go/mullvad/index.html:3
<head> contains no meta description, no canonical, no og:title, no viewport

Search results and link previews render this page worse than pages that ship complete metadata.

fix — Add the missing head elements: meta description, canonical, og:title, viewport.

this line
SG-097
nit missing-meta deterministic

The page head omits meta description, canonical, og:title, viewport.

apex/go/nordpass/index.html:3
<head> contains no meta description, no canonical, no og:title, no viewport

Search results and link previews render this page worse than pages that ship complete metadata.

fix — Add the missing head elements: meta description, canonical, og:title, viewport.

this line
SG-098
nit missing-meta deterministic

The page head omits meta description, canonical, og:title, viewport.

apex/go/nordvpn/index.html:3
<head> contains no meta description, no canonical, no og:title, no viewport

Search results and link previews render this page worse than pages that ship complete metadata.

fix — Add the missing head elements: meta description, canonical, og:title, viewport.

this line
SG-099
nit missing-meta deterministic

The page head omits meta description, canonical, og:title, viewport.

apex/go/proton_pass/index.html:3
<head> contains no meta description, no canonical, no og:title, no viewport

Search results and link previews render this page worse than pages that ship complete metadata.

fix — Add the missing head elements: meta description, canonical, og:title, viewport.

this line
SG-100
nit link-cloaking-smell 1/4 lenses

Non-partner Proton links use the same noindex instant-redirect cloaking as the affiliate links

Links declared 'not a partner link' are routed through the identical /go/ noindex, zero-second-redirect infrastructure used for commissionable CJ links. A user hovering a /go/ URL cannot distinguish paid from unpaid, and the indirection means a target could later be swapped to an affiliate URL without any visible change at the click site.

claim — apex/go/proton_vpn/index.html:11
<p>Redirecting to <a href="https://protonvpn.com/" rel="noopener">https://protonvpn.com/</a> (not a partner link)…</p>
ships — apex/go/nordvpn/index.html:6
<meta http-equiv="refresh" content="0;url=https://www.anrdoezrs.net/click-101847653-15545954" />

Affiliate-style link cloaking on allegedly non-commercial links is a pattern skeptical users specifically check for. Linking Proton directly would cost nothing and remove the smell.

fix — Link non-partner destinations (Proton VPN) directly from content pages instead of through /go/ redirects, reserving the /go/ infrastructure for tracked partner links; then delete apex/go/proton_vpn/.

restructure
SG-101
nit missing-meta deterministic

The page head omits meta description, canonical, og:title, viewport.

apex/go/proton_vpn/index.html:3
<head> contains no meta description, no canonical, no og:title, no viewport

Search results and link previews render this page worse than pages that ship complete metadata.

fix — Add the missing head elements: meta description, canonical, og:title, viewport.

this line
SG-102
nit missing-meta deterministic

The page head omits meta description, canonical, og:title, viewport.

apex/go/surfshark/index.html:3
<head> contains no meta description, no canonical, no og:title, no viewport

Search results and link previews render this page worse than pages that ship complete metadata.

fix — Add the missing head elements: meta description, canonical, og:title, viewport.

this line
SG-103
nit naming-inconsistency 1/4 lenses

The /privacy/ hub is called 'privacy hub', 'Data-removal hub', and nav’s 'Data removal' interchangeably

The same URL is named three different ways across pages, while the footer’s 'Privacy' link goes to a different destination (/privacy.html, the policy). 'Privacy hub' next to a footer 'Privacy' link invites the wrong click.

claim — apex/guides/data-removal-diy-vs-paid.html:153
On the <a href="/privacy/">privacy hub</a> we keep DIY and “skip paid” as first-class outcomes.
ships — apex/guides/how-data-brokers-get-your-data.html:133
<a href="/privacy/">Data-removal hub</a>

A visitor told to visit the 'privacy hub' may reasonably click the footer 'Privacy' link and land on a privacy policy instead of the data-removal hub — small navigation friction that reads as sloppiness.

fix — Search for 'href="/privacy/"' across all pages and standardize the link text to 'Data-removal hub' (matching the nav's 'Data removal'), replacing 'privacy hub' at data-removal-diy-vs-paid.html line 153 and 'Privacy hub' at line 182.

sweep all instances
SG-104
nit self-referential-narration 1/4 lenses

A consumer guide dedicates a full section to the site's own future editorial policy.

The section is a promise memo about how the site will label links and treat commissions ('When partner links are live, they stay labeled') — governance narration, future tense, about Hexento rather than for the reader's decision.

apex/guides/data-removal-diy-vs-paid.html:151
<h2>How Hexento will treat this category</h2>

One paragraph of incentive transparency builds trust; a standing section about 'how we will behave' reads as the site performing its own integrity instead of finishing the reader's job.

fix — Fold the promises in the 'How Hexento will treat this category' section (data-removal-diy-vs-paid.html lines 151-157) into the existing affiliate-disclosure block at lines 57-61 or the methodology page, and delete the standalone section.

restructure
SG-105
nit navigation-confusion 1/4 lenses

"Privacy" in the footer and "Data removal" in the nav point to two different /privacy destinations

On every page, footer "Privacy" goes to /privacy.html (presumably the privacy policy) while the nav's "Data removal" goes to /privacy/ (the product hub). Two near-identical URLs carry two unrelated meanings, and the word "Privacy" is used for the policy while the privacy product hub is labeled something else.

claim — apex/guides/do-you-need-antivirus.html:173
<a href="/privacy.html">Privacy</a>
ships — apex/guides/do-you-need-antivirus.html:39
<a href="/privacy/">Data removal</a>

A visitor hunting for the data-removal content who clicks footer "Privacy" lands on a legal policy page instead; a visitor pasting /privacy/ expecting a policy gets a product hub. It is a small maze on a site selling clarity.

fix — Search for 'href="/privacy.html">Privacy<' across all pages and rename the footer link text to 'Privacy policy' to disambiguate it from the /privacy/ data-removal hub.

sweep all instances
SG-106
nit uncited-claim 1/4 lenses

"Every expert roundup we cite" names Wirecutter and PCWorld but links to neither

The sentence claims citations, but neither source is linked or dated beyond "2025 assessment," while the same page tells readers in its FAQ to "Check our sources yourself." The lab sources get URLs (av-test.org); the editorial ones get name-drops.

apex/guides/do-you-need-antivirus.html:133
Every expert roundup we cite (Wirecutter’s security-expert consultations, PCWorld’s 2025 assessment)

A reader invited to verify sources will notice that half the sources cannot be followed, which weakens the page's strongest trust play.

fix — Add links to the specific Wirecutter and PCWorld pieces on do-you-need-antivirus.html line 133, or change 'we cite' to 'we consulted'.

this line
SG-107
nit unverifiable-superlative 1/4 lenses

'Worst renewal record regulators have ever put on paper' is unverifiable superlative rhetoric

The superlative can't be checked, and the supporting list mixes cases that are not renewal cases (the FTC Avast action was about selling browsing data; the $35M 'PC health checks' settlement was a retail tech-support scheme). Lumping them under 'renewal record' overstates the specific claim.

apex/guides/do-you-need-antivirus.html:105
This category has the worst renewal record regulators have ever put on paper — an $80M McAfee settlement

The underlying enforcement history is genuinely damning and doesn't need inflation; a reader who knows any one of these cases spots the category-stretching and starts discounting the page's other claims.

fix — Replace the superlative on do-you-need-antivirus.html line 105 with a verifiable claim (e.g. 'a long regulator paper trail on billing and renewal practices') and reframe the Avast and $35M cases as general trust actions rather than renewal cases.

this line
SG-108
nit claim-tool-mismatch 1/4 lenses

Antivirus guide sells the VPN true-cost calculator as built 'for exactly' suite-vs-pieces pricing

Everywhere else the /vpn/true-cost/ tool is described strictly as a VPN intro-vs-renewal calculator. Claiming it exists 'for exactly' pricing a security-suite bundle (VPN + password manager + identity monitoring + backup) against separate purchases oversells what the tool does.

claim — apex/guides/do-you-need-antivirus.html:87
price it against buying the pieces on their own merits (we have a <a href="/vpn/true-cost/">calculator</a> and <a href="/password-managers/">hub</a> for exactly this)
ships — apex/guides/vpn-renewal-trap.html:156
<a href="/vpn/true-cost/">VPN true-cost calculator</a> — intro vs renewal over 1 / 2 / 3 years,

A reader who clicks through expecting a bundle-vs-pieces comparison finds a VPN-only price tool — a small broken promise on a site whose brand is not overselling.

fix — Change 'for exactly this' on do-you-need-antivirus.html line 87 to accurate scope, e.g. 'a calculator for the VPN piece and a hub for comparing manager plans'.

this line
SG-109
nit unverifiable-superlative 1/4 lenses

'The only rigorous independent test' is an unverifiable absolute claim

Declaring one study the only rigorous test in an entire category is a universal negative the site cannot prove, and it quietly disqualifies all other evidence in advance. The DIY guide's own gentler framing ('one study isn't eternal law') handles the same fact honestly.

apex/guides/how-data-brokers-get-your-data.html:102
in Consumer Reports’ 2024 study — the only rigorous independent test — this manual

Absolutes are the tell of advocacy. A careful reader discounts a site that anoints its single supporting study as uniquely rigorous.

fix — Change 'the only rigorous independent test' on how-data-brokers-get-your-data.html line 102 to 'the most rigorous independent test we know of'.

this line
SG-110
nit audience-mismatch 1/4 lenses

A consumer skip-list bullet resolves in three unglossed enterprise acronyms and calls itself 'a consumer page'.

SSO/SCIM/IAM in one breath is IT-procurement register; and 'not a consumer page' is the page describing itself to the reader rather than addressing them.

apex/guides/password-manager-vs-built-in.html:163
You need enterprise SSO / SCIM / compliance — that’s a business IAM buy, not a consumer page.</li>

Mild — the readers who need this bullet mostly know the terms — but the self-referential 'consumer page' aside is the site talking about its own information architecture mid-sentence.

fix — Rewrite password-manager-vs-built-in.html line 163 in plain language, e.g. 'Your company needs centralized business logins and compliance — that's an IT purchase; ask your employer.'

this line
SG-111
nit template-drift 1/4 lenses

security-stack-order’s breadcrumb drops the hub crumb every other guide carries

All seven other guides show Home · <Hub> · Guide; this one shows Home · Guide. If the omission is deliberate (cross-category guide), nothing signals that; it just looks like a missing crumb.

claim — apex/guides/security-stack-order.html:48
<p class="crumbs"><a href="/">Home</a> · Guide</p>
ships — apex/guides/vpn-renewal-trap.html:48
<p class="crumbs"><a href="/">Home</a> · <a href="/vpn/">VPN</a> · Guide</p>

Minor: a reader loses the one-click path back to a category hub that every sibling page offers, and the pattern break is noticeable to anyone reading more than one guide.

fix — Add a middle crumb to security-stack-order.html line 48 to match the Home · Hub · Guide pattern — either the most relevant hub or a neutral 'Guides' label.

this line
SG-112
nit non-sequitur 1/4 lenses

An obscure brand, HideMy.Name, appears in the FAQ with no prior mention on the page

The page discusses Nord, Surfshark, Incogni, Express/Kape, and Mullvad, then the FAQ suddenly fields a question about HideMy.Name — a brand a mainstream visitor has never heard of and that appears nowhere else in these files.

apex/guides/sibling-vpn-brands.html:161
<summary>What about HideMy.Name / smaller brands?</summary>

The out-of-nowhere name makes the FAQ feel generated or scraped from someone else's comment section rather than answering questions this page's readers would actually have.

fix — Generalize the FAQ question on sibling-vpn-brands.html line 161 to 'What about smaller brands?' or introduce HideMy.Name earlier in the body with context (and note its partner status per disclosure.html).

this line
SG-113
nit vague-disclosure 1/4 lenses

Live partners are disclosed as NordVPN and Surfshark '(among others)' without naming the others

On the page whose entire subject is hidden commercial relationships, the site's own disclosure names two partners and waves at an unnamed remainder. The reader must click through to disclosure.html to learn who else pays.

apex/guides/sibling-vpn-brands.html:59
(among others). This page is not a crown ceremony for either brand. See

'Among others' is exactly the phrasing this page teaches readers to distrust in comparison charts; naming the full live-partner list inline would cost one sentence and match the site's stated standard.

fix — Replace '(among others)' on sibling-vpn-brands.html line 59 with the actual remaining live partners per disclosure.html: '(plus HideMy.Name and NordPass)'.

this line
SG-114
nit template-drift 1/4 lenses

The logo checkmark on sibling-vpn-brands.html is missing stroke-linecap="round"

Every other page’s brand SVG draws the checkmark with round line caps; this page’s copy dropped the stroke-linecap attribute, so the checkmark ends render as flat butt caps. The logo is subtly different on exactly one page.

claim — apex/guides/sibling-vpn-brands.html:33
<path d="M23 32.5 29.5 39 42 25.5" fill="none" stroke="#5eead4" stroke-width="5.5" stroke-linejoin="round"/>
ships — apex/guides/vpn-renewal-trap.html:33
<path d="M23 32.5 29.5 39 42 25.5" fill="none" stroke="#5eead4" stroke-width="5.5" stroke-linecap="round" stroke-linejoin="round"/>

Nearly invisible, but it means the header logo is not pixel-identical across pages — the kind of drift that betrays copy-paste templating when someone does notice.

fix — Search for 'stroke-width="5.5" stroke-linejoin="round"' (the variant without stroke-linecap) and add stroke-linecap="round" — affected: sibling-vpn-brands.html, data-removal-diy-vs-paid.html, and password-manager-vs-built-in.html, each at line 33.

sweep all instances
SG-115
nit vague-insinuation 1/4 lenses

Unnamed 'auto-renewal class actions involving major consumer VPN brands' is insinuation without a citation

No brands, no case names, no links — just 'public reporting' about unspecified litigation. On a page that names exact renewal dollar figures, refusing to name the defendants reads as either fear of partners or a claim that can't survive specificity.

apex/guides/vpn-renewal-trap.html:142
As of the 2026-08 snapshot, there was public reporting on auto-renewal class actions involving major consumer VPN brands.

A skeptical reader can't check it, so it carries zero evidentiary weight while still smearing the category — the same move fear-based VPN ads make in the other direction.

fix — Either name at least one specific case and brand with a link to the reporting, or delete the litigation sentence and keep the practical advice about reading the cancel flow.

this line
SG-116
nit invented-notation 1/4 lenses

The page invents a dangling '±' price notation that then needs its own legend to decode.

'~$79/yr ±' and '~$69.72 / 28 mo ±' (line 91) stack a tilde and a bare plus-minus with no range, and line 106 has to explain what '±' means. Consumer prose that requires a notation key has drifted into the researcher's private shorthand.

apex/guides/vpn-renewal-trap.html:86
renews near <strong>~$79/yr ±</strong>

A shopper scanning for one number meets ambiguous math symbols and a footnote about corroboration; the precision theater reads as hedging rather than rigor.

fix — Search for the '±' character in guide prose and replace each dangling '±' with words (e.g. 'about $79/yr — not confirmed at checkout'), then delete the now-unneeded legend paragraph at vpn-renewal-trap.html lines 105-107.

sweep all instances
SG-117
nit label-inflation 1/4 lenses

Every single guide is labeled "Cornerstone guide," making the label meaningless

All eight guide pages under review carry the identical "Cornerstone guide" eyebrow. If everything is a cornerstone, the badge conveys nothing, and a visitor who opens a second guide immediately sees the template.

apex/guides/when-you-dont-need-a-vpn.html:49
<p class="eyebrow">Cornerstone guide</p>

Repeated self-applied importance labels read as SEO-content-farm styling to an experienced web reader — the opposite of the handcrafted, evidence-first identity the copy works hard to build.

fix — Search for '<p class="eyebrow">Cornerstone guide</p>' across all guide pages and replace each with a page-specific eyebrow (e.g. the category name: 'VPN guide', 'Data removal guide') or remove it.

sweep all instances
SG-118
nit coy-reference 1/4 lenses

A recommended "prepaid access-code VPN" is teased but deliberately left unnamed

The page describes a specific, unusual product category and says the hub "covers one" without naming it, forcing a click to learn which product is meant.

apex/guides/when-you-dont-need-a-vpn.html:130
you can keep a code in a drawer until the trip actually happens (the <a href="/vpn/">VPN hub</a> covers one)

On a site that criticizes coy vendor pricing, withholding a product name to farm a click reads as the same move in miniature; naming it costs nothing and the hub link could stay.

fix — Name the specific prepaid access-code VPN in the parenthetical on when-you-dont-need-a-vpn.html line 130 instead of 'covers one', keeping the hub link.

this line
SG-119
nit cross-page-inconsistency 1/4 lenses

Category OG images are assigned inconsistently across same-category guides

Two VPN guides (vpn-renewal-trap, sibling-vpn-brands) use og-vpn.png but the third VPN guide (when-you-dont-need-a-vpn) falls back to generic og.png. Same pattern in the privacy category: data-removal-diy-vs-paid uses og-privacy.png while how-data-brokers-get-your-data uses og.png.

claim — apex/guides/when-you-dont-need-a-vpn.html:15
<meta property="og:image" content="https://hexento.com/og.png" />
ships — apex/guides/vpn-renewal-trap.html:15
<meta property="og:image" content="https://hexento.com/og-vpn.png" />

When these pages are shared side by side on social, siblings from the same category show mismatched card art, making the site look assembled rather than curated.

fix — Search for 'content="https://hexento.com/og.png"' in category guides and set og:image and twitter:image to og-vpn.png on when-you-dont-need-a-vpn.html and og-privacy.png on how-data-brokers-get-your-data.html.

sweep all instances
SG-120
nit unexplained-jargon 1/4 lenses

"Pickguard" sits unexplained in the primary nav on every page

The nav item is an invented brand word with no descriptor. The homepage explains it two screens down, but a stranger landing directly on any hub page sees "Pickguard" between "Antivirus" and "Methodology" with zero context.

apex/index.html:52
<a href="/pickguard/">Pickguard</a>

Minor friction: first-time visitors either ignore an unlabeled nav item or click it blind. A two-word descriptor ("Pickguard chooser") would remove the guesswork.

fix — Search every page for the exact string `<a href="/pickguard/">Pickguard</a>` and add a descriptor (e.g. rename the nav label to "Pickguard chooser" or add title="Constraint-based chooser for VPNs and password managers").

sweep all instances
SG-121
nit internal-jargon 1/4 lenses

A consumer pricing footnote explains the vendor's JavaScript rendering to justify data sourcing

The footnote under the price table justifies tracker-sourced NordPass figures by describing how the vendor's web page is built ('renders prices via JS') — scraper-methodology detail in a shopping context. 'NordPass doesn't publish its renewal rate' is the visitor-relevant fact.

apex/password-managers/index.html:132
(vendor page renders prices via JS and hides renewal rates)

Non-technical shoppers hit dev jargon mid-table; the sourcing honesty survives without narrating the scraping obstacle.

fix — Replace "(vendor page renders prices via JS and hides renewal rates)" at apex/password-managers/index.html line 132 with "(NordPass doesn’t publish its renewal rate on its pricing page)".

this line
SG-122
nit navigation-confusion 1/4 lenses

Two different "privacy" pages (/privacy/ and /privacy.html) require an apology box to disambiguate

The nav's "Data removal" points to /privacy/ while the footer's "Privacy" points to /privacy.html, and the policy page opens with a note-box redirecting confused visitors. The URL collision is baked into the information architecture.

apex/privacy.html:42
Looking for <em>data-broker removal</em> advice? That’s a different page:

A visitor who lands on the wrong privacy page gets a mild "huh?" moment; the site clearly knows it's confusing (hence the box) but shipped the collision anyway.

fix — Move the data-removal hub off /privacy/ (e.g. to /data-removal/) with a redirect, updating nav, footer, canonical, and sitemap links sitewide so /privacy.html is the only privacy-named URL.

restructure
SG-123
nit missing-meta deterministic

The page head omits og:title.

apex/privacy.html:3
<head> contains no og:title

Search results and link previews render this page worse than pages that ship complete metadata.

fix — Add the missing head elements: og:title.

this line
SG-124
nit logic-gap 1/4 lenses

Users who answered 'Looked — found nothing' can still be told they are probably listed and to file opt-outs

The clean answer only subtracts 2 from the score, so e.g. US + 15+ years + property owner (7 − 2 = 5) lands in the moderate band: the verdict asserts "Probably listed on at least the major aggregators" and, because band !== "low", the step logic tells this user to run the full opt-out first pass and save confirmations — for listings they just said they verified don't exist.

claim — apex/privacy/index.html:368
moderate: "Probably listed on at least the major aggregators",
ships — apex/privacy/index.html:363
if (answers.seen === "clean") score -= 2;

The tool contradicts the user's own reported observation, making the 'each one changes the plan' quiz feel like it isn't actually listening.

fix — When answers.seen === 'clean', route users to the spot-check/re-check step instead of the full opt-out first pass (change the condition at line 378 to exclude seen === 'clean', or cap the band at 'low' for clean answers).

this line
SG-125
nit build-narration 1/4 lenses

A personalized exposure plan pauses to report the site's pending Incogni affiliate application

Inside the quiz's tailored advice — for someone who may have selected 'harassment or safety concern' — a step interrupts itself to narrate the site's affiliate-program status. The same pipeline narration recurs in the 'Partner status' note box (line 238: 'we’ve applied to Incogni’s affiliate program (pending — the name above is not a link)').

apex/privacy/index.html:387
and our partner application there is pending, so that name is not a link today

The reader asked what to do about being listed on people-search sites; the site answers partly with its own business-development diary. Labeling links that exist serves visitors — explaining links that don't exist serves the operator's conscience.

fix — In apex/privacy/index.html line 387, delete the clause "— and our partner application there is pending, so that name is not a link today" from the quiz step; the Partner status note-box at line 238 already discloses this.

this line
SG-126
nit stale-claim 1/4 lenses

Sitemap lastmod for /vpn/ predates the page's own 'Last updated: 2026-08-02' stamp

The VPN hub displays Last updated 2026-08-02 (and cites prices "checked 2026-08-02"), but the sitemap still says 2026-08-01 for /vpn/ — and for /vpn/true-cost/, whose visible verification date is also 2026-08-01/02.

claim — apex/sitemap.xml:5
<url><loc>https://hexento.com/vpn/</loc><lastmod>2026-08-01</lastmod></url>
ships — apex/vpn/index.html:56
<time datetime="2026-08-02">2026-08-02</time>

Minor, but a date-obsessed site whose machine-readable dates lag its visible ones hands skeptics an easy 'they don't actually maintain this' gotcha.

fix — In apex/sitemap.xml update the <lastmod> for https://hexento.com/vpn/ (line 5) and https://hexento.com/vpn/true-cost/ (line 6) to 2026-08-04, and audit every remaining `<lastmod>2026-08-01` entry against its page's visible Last-updated <time> stamp.

sweep all instances
SG-127
nit arithmetic-drift 1/4 lenses

HideMy.Name is 'running since 2006' but the audit gap is stated as 19 years in a 2026 snapshot

The fit paragraph dates the service to 2006 while the comparison table cell says "None — ever (19 yrs)" and the watch paragraph repeats "no independent audit in 19 years"; 2006 to the page's 2026-08 snapshot is 20 years by ordinary reckoning, so the two figures only reconcile if the service launched after August 2006 — which the page never says.

claim — apex/vpn/index.html:289
a no-account design that’s been running since 2006
ships — apex/vpn/index.html:116
<td class="bad">None — ever (19 yrs)</td>

A reader doing the subtraction gets a different number than the page's, which chips at the credibility of the site's signature 'we date everything' precision.

fix — Reconcile the age math: search apex/vpn/index.html for '19 yrs' (line 116) and '19 years' (line 290) and change both to 20, or replace 'since 2006' with the actual launch month that makes 19 correct.

sweep all instances
SG-128
nit internal-jargon 1/4 lenses

A pricing-table cell cites 'Proton's payments API' as a source in consumer-facing copy

The 'Renews at' cell annotates the figure with how the builder verified it (an API query), repeated at line 276 and in cost.js line 75. The parallel Nord cell's 'vendor-disclosed' is the right register; 'payments API' is developer sourcing-jargon in a consumer comparison table.

apex/vpn/index.html:129
<span class="muted">via Proton’s payments API</span>

Small, but the table momentarily addresses someone who audits data pipelines rather than someone buying a VPN.

fix — Search for the string "payments API" (apex/vpn/index.html lines 129 and 276, plus any occurrence in cost.js) and replace with reader-facing sourcing such as "vendor-disclosed renewal price".

sweep all instances
SG-129
nit invented-figure 1/4 lenses

Calculator shows HideMy.Name renewing at $36/yr, a rate the vendor never bills

For the 2-year term the "Renews at" cell renders usd(renewYr) = "$36/yr", but HideMy.Name's actual repeat purchase is $72 per 2 years; $36/yr is a silent annualization. The VPN hub's own table refuses to print a renewal number for this vendor ("No gap documented"), so the two surfaces present the same fact differently.

claim — apex/vpn/true-cost/cost.js:83
"2yr": { introTotal: 72, introMonths: 24, renewYr: 36 },
ships — apex/vpn/index.html:113
<td class="num">No gap documented<br /><span class="muted">card buys auto-renew; crypto is one-time</span></td>

A visitor cross-checking against hide.mn finds no $36/yr price anywhere, on a site that promises it will not present pricing it can't verify.

fix — In apex/vpn/true-cost/cost.js, stop rendering '$36/yr' for HideMy.Name: mark the row flat (flat: true) or add a per-plan renewNote so the Renews-at cell prints '$72/2yr — no gap documented' instead of usd(renewYr), keeping renewYr:36 only for the internal pro-ration math.

this line
SG-130
nit datetime-mismatch 1/4 lenses

Machine-readable datetime claims a single day while the visible text claims a two-day range

The 'Prices last verified' time element carries datetime="2026-08-02" but displays "2026-08-01/02"; the attribute and the human-readable value disagree, and "2026-08-01/02" is itself a nonstandard range rendering.

claim — apex/vpn/true-cost/index.html:69
<time datetime="2026-08-02">2026-08-01/02</time>
ships — apex/vpn/true-cost/cost.js:7
const CHECKED = "2026-08-01/02";

Tiny, but it is a dated-snapshot site getting its own date markup wrong on the page whose headline feature is verification dates.

fix — Make the time element's datetime match its text — either display the single date 2026-08-02 or split the range into two <time> elements with datetime="2026-08-01" and datetime="2026-08-02".

this line
SG-131
nit aria-misuse 1/4 lenses

The true-cost page marks the /vpn/ nav link aria-current="page" though it is a different page

On /vpn/true-cost/ the primary nav flags the /vpn/ hub link as the current page. aria-current="page" tells assistive tech the link target is the page being viewed; a screen-reader user hears "current page" on a link that navigates away (aria-current="true" or section semantics would be correct).

claim — apex/vpn/true-cost/index.html:49
<a href="/vpn/" aria-current="page">VPN</a>
ships — apex/vpn/true-cost/index.html:9
<link rel="canonical" href="https://hexento.com/vpn/true-cost/" />

Screen-reader users get told they are on the VPN hub while using the calculator — a small accessibility inaccuracy on an otherwise carefully ARIA-annotated site.

fix — In apex/vpn/true-cost/index.html line 49, change aria-current="page" to aria-current="true" (or remove the attribute) on the /vpn/ nav link, since /vpn/ is the section, not the current page.

this line
SG-132
nit claim-code-contradiction 1/4 lenses

The README says non-partner redirects go to plain vendor URLs, but go/builtin targets a hexento guide page.

"Everything else redirects to plain vendor URLs" is contradicted by the shipped builtin redirect, whose target is hexento.com's own guide, not a vendor. Small, but it means the outbound documentation is already drifting from what ships.

claim — tools/pickguard/README.md:36
`earn/docs/research/cj-active-links.md`); everything else redirects to plain vendor URLs.
ships — tools/pickguard/go/builtin/index.html:6
<meta http-equiv="refresh" content="0;url=https://hexento.com/guides/password-manager-vs-built-in.html" />

Each place the docs and the shipped pages disagree teaches a careful reader that the written claims are approximate — costly for a tool whose differentiator is a "transparent scoreboard".

fix — Amend README line 36 to note the builtin option redirects to the site's own guide page while all other non-partner options redirect to plain vendor URLs (or make it true by fixing 121).

this line
SG-133
nit missing-meta deterministic

The page head omits meta description, canonical, og:title, viewport.

tools/pickguard/go/1password/index.html:3
<head> contains no meta description, no canonical, no og:title, no viewport

Search results and link previews render this page worse than pages that ship complete metadata.

fix — Add the missing head elements: meta description, canonical, og:title, viewport.

this line
SG-134
nit missing-meta deterministic

The page head omits meta description, canonical, og:title, viewport.

tools/pickguard/go/bitwarden/index.html:3
<head> contains no meta description, no canonical, no og:title, no viewport

Search results and link previews render this page worse than pages that ship complete metadata.

fix — Add the missing head elements: meta description, canonical, og:title, viewport.

this line
SG-135
nit missing-meta deterministic

The page head omits meta description, canonical, og:title, viewport.

tools/pickguard/go/builtin/index.html:3
<head> contains no meta description, no canonical, no og:title, no viewport

Search results and link previews render this page worse than pages that ship complete metadata.

fix — Add the missing head elements: meta description, canonical, og:title, viewport.

this line
SG-136
nit missing-meta deterministic

The page head omits meta description, canonical, og:title, viewport.

tools/pickguard/go/expressvpn/index.html:3
<head> contains no meta description, no canonical, no og:title, no viewport

Search results and link previews render this page worse than pages that ship complete metadata.

fix — Add the missing head elements: meta description, canonical, og:title, viewport.

this line
SG-137
nit missing-meta deterministic

The page head omits meta description, canonical, og:title, viewport.

tools/pickguard/go/hidemy/index.html:3
<head> contains no meta description, no canonical, no og:title, no viewport

Search results and link previews render this page worse than pages that ship complete metadata.

fix — Add the missing head elements: meta description, canonical, og:title, viewport.

this line
SG-138
nit missing-meta deterministic

The page head omits meta description, canonical, og:title, viewport.

tools/pickguard/go/keepassxc/index.html:3
<head> contains no meta description, no canonical, no og:title, no viewport

Search results and link previews render this page worse than pages that ship complete metadata.

fix — Add the missing head elements: meta description, canonical, og:title, viewport.

this line
SG-139
nit missing-meta deterministic

The page head omits meta description, canonical, og:title, viewport.

tools/pickguard/go/mullvad/index.html:3
<head> contains no meta description, no canonical, no og:title, no viewport

Search results and link previews render this page worse than pages that ship complete metadata.

fix — Add the missing head elements: meta description, canonical, og:title, viewport.

this line
SG-140
nit missing-meta deterministic

The page head omits meta description, canonical, og:title, viewport.

tools/pickguard/go/nordpass/index.html:3
<head> contains no meta description, no canonical, no og:title, no viewport

Search results and link previews render this page worse than pages that ship complete metadata.

fix — Add the missing head elements: meta description, canonical, og:title, viewport.

this line
SG-141
nit missing-meta deterministic

The page head omits meta description, canonical, og:title, viewport.

tools/pickguard/go/nordvpn/index.html:3
<head> contains no meta description, no canonical, no og:title, no viewport

Search results and link previews render this page worse than pages that ship complete metadata.

fix — Add the missing head elements: meta description, canonical, og:title, viewport.

this line
SG-142
nit missing-meta deterministic

The page head omits meta description, canonical, og:title, viewport.

tools/pickguard/go/proton_pass/index.html:3
<head> contains no meta description, no canonical, no og:title, no viewport

Search results and link previews render this page worse than pages that ship complete metadata.

fix — Add the missing head elements: meta description, canonical, og:title, viewport.

this line
SG-143
nit missing-meta deterministic

The page head omits meta description, canonical, og:title, viewport.

tools/pickguard/go/proton_vpn/index.html:3
<head> contains no meta description, no canonical, no og:title, no viewport

Search results and link previews render this page worse than pages that ship complete metadata.

fix — Add the missing head elements: meta description, canonical, og:title, viewport.

this line
SG-144
nit sketchy-redirect-experience 1/4 lenses

The affiliate redirect page displays a raw jdoqocy.com tracking URL as its visible text.

If the instant redirect ever stalls, the visitor sees a bare page whose only content is 'Redirecting to https://www.jdoqocy.com/click-101847653-15438560' — an opaque tracking-network URL with no mention of Surfshark by name.

tools/pickguard/go/surfshark/index.html:11
Redirecting to <a href="https://www.jdoqocy.com/click-101847653-15438560"

Random-looking click-tracker domains are the visual signature of malware redirects. A visitor who catches this page mid-hop gets a jolt of 'is this site safe?' right at the moment of conversion.

fix — In build_go.py's redirect template (and every generated go/*/index.html), replace the anchor's visible text — currently the repeated raw tracking URL — with the vendor name, e.g. 'Redirecting to Surfshark'.

sweep all instances
SG-145
nit missing-meta deterministic

The page head omits meta description, canonical, og:title, viewport.

tools/pickguard/go/surfshark/index.html:3
<head> contains no meta description, no canonical, no og:title, no viewport

Search results and link previews render this page worse than pages that ship complete metadata.

fix — Add the missing head elements: meta description, canonical, og:title, viewport.

this line
SG-146
nit self-praise-repetition 1/4 lenses

The page badges itself "honest" four times — in the meta, the JSON-LD, the hero, and the how-it-works panel.

"honest no-fit path" (line 7), "an honest no-fit path" (line 35), "an honest 'don't buy yet'" (line 66), and this heading. Honesty asserted this often reads as protesting too much; the no-fit behavior itself is the proof and doesn't need the adjective.

tools/pickguard/index.html:113
<div class="n">Honest no-fit</div>

Strangers discount self-applied virtue words, and repetition compounds the discount — by the fourth "honest" the visitor starts wondering why the site needs to keep saying it.

fix — Search index.html for 'honest' (lines 7, 35, 65-66, 113) and keep at most one instance, e.g. rename the panel heading to 'No-fit is an answer' and drop the adjective elsewhere.

sweep all instances
SG-147
nit slogan-repetition 1/4 lenses

The page leans on a repeating aphorism template and repeats "black box" twice in adjacent sections.

"Transparency beats a black box" (line 100), "no black-box 'AI ranking'" (line 110), "Shared vaults beat texted passwords" (catalog.js line 222), plus the hero's "Not another 'Best VPN 2026' listicle" sneer — the X-beats-Y / not-like-the-others tic stacks up until the voice sounds like it's performing itself.

tools/pickguard/index.html:100
Transparency beats a black box.

One aphorism lands; three in one scroll read as house filler, and the defensive 'we're not them' framing spends visitor attention on competitors instead of the visitor's decision.

fix — Search index.html and catalog.js for 'beats' and 'black box' (index.html lines 100 and 110, catalog.js line 222) and rewrite all but one instance to break the repeated X-beats-Y template.

sweep all instances
SG-148
nit audience-mismatch 1/4 lenses

"Deterministic" is an engineering term used as a consumer-facing panel heading.

The body copy beneath it ("Same inputs, same answer") already says the idea in plain language; the CS-vocabulary heading serves the builder's self-image, not the shopper.

tools/pickguard/index.html:109
<div class="n">Deterministic</div>

A non-technical VPN shopper skims headings first; a word from a programming textbook signals the page was written by and for developers.

fix — Rename the panel heading at index.html line 109 from 'Deterministic' to plain language such as 'Same inputs, same answer' and adjust the body copy to avoid repeating it.

this line
SG-149
nit affiliate-jargon 1/4 lenses

"Click out" is affiliate-industry metric vocabulary surfacing in visitor-facing copy.

Clickout is what the operator's revenue dashboard counts; the visitor just "visits a site" or "follows a link". The sentence's reassurance is good — the word choice reveals which side of the transaction wrote it.

tools/pickguard/index.html:86
Useful even if you never click out.

Readers who know the term recognize they're being measured; readers who don't find the phrase slightly off. Either way the monetization register pokes through the editorial one.

fix — Replace 'click out' at index.html line 86 with visitor phrasing, e.g. 'Useful even if you never follow a link.'

this line
SG-150
nit build-narration-shipped 1/4 lenses

Shipped JS opens with self-referential build narration about a lesson learned on another product.

"(Playkeg lesson)" is a note from the operator to themselves about a different project, delivered to every visitor's browser alongside the second playkeg.com leak (the analytics domain).

tools/pickguard/src/analytics.js:1
// Queue-until-ready Umami helper (Playkeg lesson). Shared Hexento website id.

View-source readers — the audience this site explicitly courts — get diary entries instead of product code, reinforcing that hexento.com is one person's side-project lattice rather than the sober review outfit the copy performs.

fix — Delete '(Playkeg lesson)' from the analytics.js line 1 header comment.

this line
SG-151
nit claim-overreach 1/4 lenses

The runner-up is always labeled 'different tradeoff' but is simply whatever scored second.

rank() picks scored[1] with no check that it differs from the winner on any axis; the 'different tradeoff' framing is unconditional decoration that can be false (e.g. two near-identical mainstream picks).

claim — tools/pickguard/src/app.js:159
cardFor(result.runner, "runner", "Runner-up · different tradeoff", result)
ships — tools/pickguard/src/catalog.js:275
runner: runner && runner.score >= MIN - 8 ? runner.opt : null,

When the 'different tradeoff' turns out to be a near-clone of the winner, the label reads as canned copy and chips at the tool's claim of being smarter than a listicle.

fix — Search for 'different tradeoff' (app.js line 159, index.html line 65) and either drop the qualifier to plain 'Runner-up' or derive the label from an actual attribute delta between winner and runner-up.

sweep all instances
SG-152
nit copy-overreach 1/4 lenses

The VPN step claims the pool includes 'free / built-in picks' but no free or built-in VPN option is scored.

The catalog note renders the same parenthetical for every category, yet the six scored VPN entries are all paid products (Proton's free tier exists only as a price-note aside on its paid listing, and there is no built-in VPN at all).

claim — tools/pickguard/src/app.js:55
Scoring ${pool.length} options (including free / built-in picks)
ships — tools/pickguard/index.html:114
If nothing clears the bar, we say so. Free tiers and built-ins are in the catalog and allowed to win.

A budget-minded user told the scoreboard includes free picks scans it, finds none, and files the promise with every other listicle's 'we considered everything' boilerplate.

fix — Make the catalog note in app.js line 55 category-aware: omit '(including free / built-in picks)' for VPN or render per-category text that matches what the pool actually contains.

this line
SG-153
nit silent-failure 1/4 lenses

The Copy result button fails silently without clipboard access, yet still logs share_clicked.

If navigator.clipboard is absent (insecure context, older browsers) the optional chain short-circuits and nothing happens — no 'Copied ✓', no fallback, no error handling on rejection either — while track('share_clicked') at line 237 fires unconditionally.

tools/pickguard/src/app.js:231
navigator.clipboard?.writeText(text).then(() => {

A user clicks Copy, sees no feedback, pastes nothing, and quietly loses faith in the tool's polish; meanwhile the analytics count a share that never happened.

fix — In onCopy (app.js lines 224-238), guard for missing navigator.clipboard with a fallback, add a .catch that shows a failure state, and move track('share_clicked') inside the success handler.

this line
SG-154
nit internal-vocab-leak 1/4 lenses

Recommendations are "options" in the UI but "offers" in the shipped analytics payload.

The outbound-click event names the recommended product an offer_code — sales-funnel vocabulary observable in the network tab of a page that insists commission never moves a score.

tools/pickguard/src/app.js:208
offer_code: opt.id,

A curious visitor watching requests sees their 'best fit' logged as an offer with a placement — the internal register quietly contradicts the editorial one the page works hard to project.

fix — Rename the analytics property 'offer_code' to 'option_id' in app.js line 208.

this line
SG-155
nit jargon 1/4 lenses

Form labels use reviewer jargon like 'Budget posture' and 'Privacy / audit posture'.

'Posture' (used twice — line 162's 'Privacy / audit posture' and here) is security-industry insider vocabulary; normal shoppers say 'budget' and 'privacy'.

tools/pickguard/src/catalog.js:191
label: "Budget posture",

Insider phrasing in a consumer-facing form makes a first-timer feel the tool was written for the author's peers, not for them — a small but real friction on a page selling accessibility.

fix — Search catalog.js for 'posture' (lines 162, 191, 235, 347) and replace with plain labels: 'Budget posture' → 'Budget', 'Privacy / audit posture' → 'Privacy & audits'.

sweep all instances
SG-156
nit gibberish-units 1/4 lenses

NordPass's price note renders a dangling '(±)' with no value attached.

'(±)' with no number after it is meaningless notation that will render verbatim on the result card; every other price note uses complete phrasing.

tools/pickguard/src/catalog.js:104
Premium ~$23.88 first year, renews ~$35.88/yr (±). Free tier: unlimited items, one active session.

Broken shorthand in a price line — on the one partner-linked password manager, no less — reads like an unfinished editing pass exactly where readers scrutinize hardest.

fix — Delete the dangling '(±)' in catalog.js line 104 or replace it with an explicit qualifier such as '(varies by promo)'.

this line
SG-157
nit date-arithmetic 1/4 lenses

HideMy.Name is 'since 2006' but the caveat says 'No independent audit in 19 years' — off by one in 2026.

As of the page's own 2026-08 verification stamp, a service operating since 2006 has run roughly 20 years, not 19, unless it launched after August 2006. Blurb and caveat on the same card imply different ages.

claim — tools/pickguard/src/catalog.js:79
No-account access codes since 2006:
ships — tools/pickguard/src/catalog.js:81
caveat: "No independent audit in 19 years; streaming unreliable in recent tests;

Number-checkers — the exact audience this tool courts — will catch the mismatch on one card and start double-checking everything else.

fix — Replace 'No independent audit in 19 years' in catalog.js line 81 with age-proof phrasing such as 'never independently audited' so it cannot drift out of sync with 'since 2006'.

this line
SG-158
nit a11y-inaccessible-rating 1/4 lenses

Rating chips are raw dot characters with no accessible text alternative.

The chips render as literal ●/○ glyphs inside a span (app.js line 187) with no aria-label or visually-hidden score, so screen readers announce a string of 'black circle' / 'white circle' instead of e.g. 'Privacy 4 out of 5'.

tools/pickguard/src/catalog.js:340
return "●".repeat(v) + "○".repeat(5 - v);

Screen-reader users get the rubric — the site's core trust artifact — as unintelligible symbol soup, on a results section that is otherwise carefully aria-labeled.

fix — In app.js line 187's chip template, add aria-label="{k} {n} of 5" to each .bar span and aria-hidden="true" on the .dots span, passing the numeric value through alongside the dot string.

this line

Rollup — 97 failure classes

missing-meta26
claim-code-contradiction13
audience-mismatch5
stale-claim4
internal-jargon3
unexplained-jargon3
claim-content-contradiction2
claim-overreach2
cross-page-inconsistency2
disclosure-inconsistency2
navigation-confusion2
operator-leak2
partner-bias2
ranking-follows-money2
template-drift2
trust-theater2
uncited-claim2
unverifiable-citation2
unverifiable-superlative2
a11y-inaccessible-rating1
affiliate-jargon1
aria-misuse1
arithmetic-drift1
asymmetric-evidence1
awkward-phrasing1
build-narration1
build-narration-shipped1
claim-hedge-contradiction1
claim-tool-mismatch1
conflict-of-interest-optics1
confusing-microcopy1
copy-overreach1
count-mismatch1
coy-reference1
date-arithmetic1
date-inconsistency1
datetime-mismatch1
dead-contact-channel1
defensive-meta1
dev-note-leak1
disorienting-redirect1
duplicate-title1
evidence-standard-inconsistency1
garbled-superlative1
gibberish-units1
grammar-parallelism1
hedged-attribution-mismatch1
inaccessible-evidence1
inconsistent-dates1
inconsistent-metadata1
inconsistent-navigation1
insider-meta1
internal-fact-contradiction1
internal-reference1
internal-vocab-leak1
internal-vocabulary-leak1
invented-figure1
invented-notation1
jargon1
js-dead-queue1
label-inflation1
link-cloaking-smell1
logic-gap1
misleading-cta1
naming-inconsistency1
navigation-dead-end1
non-sequitur1
off-brand-third-party1
opaque-tracking-url1
operator-content-leak1
operator-plumbing-leak1
overclaim1
overclaim-vs-own-data1
partner-puffery1
placeholder-leak1
privacy-optics1
protesting-too-much1
rubric-inconsistency1
scary-redirect1
schema-vocab-leak1
selective-omission1
self-praise-repetition1
self-referential-narration1
silent-failure1
sketchy-redirect-experience1
slogan-repetition1
sloppy-framing1
template-residue1
thin-identity1
tone-drift1
uncited-namedrop1
unfinished-todo1
vague-disclosure1
vague-insinuation1
visible-duplication1
visible-typo1
weird-redirect1