Skip to content

chore(quality): real lint coverage, vitest + knip gates, dead-file removal - #370

Merged
PastaPastaPasta merged 4 commits into
stagingfrom
chore/quality-gates
Sep 7, 2026
Merged

chore(quality): real lint coverage, vitest + knip gates, dead-file removal#370
PastaPastaPasta merged 4 commits into
stagingfrom
chore/quality-gates

Conversation

@PastaPastaPasta

Copy link
Copy Markdown
Owner

First PR of the anti-slop cleanup series. This one makes the quality gates real and removes what is provably dead, so the later consolidation PRs land on a tree where lint, typecheck, unit tests and dead-code detection all mean something.

The gate that wasn't

npm run lint was a bare next lint, which only walks pages/ app/ components/ lib/ src/. hooks/ (5.9k LOC) and contexts/ were never linted, locally or in CI. Running ESLint over them surfaced two real errors (no-var-requires in a dead hook) and ~40 warnings. Every rule was also warn, so 115 warnings had accumulated with a green CI.

  • lint now names every source directory and runs with --max-warnings 0.
  • The previously-warn rules are error. The tree is at zero, so this only bites regressions.
  • @next/next/no-img-element is off: under output: 'export' images are unoptimized, next/image adds nothing, and 13 sites already disabled it inline (those inline disables are removed).
  • The two remaining no-explicit-any disables are gone: pagination-utils gets a minimal structural SDK interface, the DiceBear style map uses Style<object>.

New gates

Gate Command CI job
Unit tests (Vitest) npm run test unit
Dead code (knip) npm run lint:dead dead-code

Vitest starts with 48 specs over the pure lib/ modules: WIF/hex codecs, AES-GCM round-trip and tamper detection, hash160 known vectors, bloom filter (no false negatives, FP rate at design load, serialization), compression/chunking, slugs, tag and mention extraction. These are the modules the primitive-consolidation PRs will touch next.

knip enforces unused files, unused dependencies and unlisted dependencies now. Unused exports (69) and types (96) are reported but not yet enforced; that backlog is worked down in the following PRs, after which the job goes strict.

Dependencies

@dashevo/wasm-sdk (11 files), @storacha/access and @ucanto/principal were imported directly but only present transitively; they are listed explicitly (wasm-sdk pinned to the same 4.2.0-dev.8 as evo-sdk, one lockfile entry). @radix-ui/react-slider had no importers and is removed.

Dead code removed

Ten files with zero importers: types/sdk.ts, hooks/use-require-encryption-key.ts, hooks/use-platform-detection.ts, components/compose/upload-progress.tsx, components/layout/mobile-header.tsx, components/post/feed-reply-context.tsx, lib/utils/contact-methods.ts, serve.py (superseded by scripts/serve-static.mjs), assets/yappr.png (byte-identical to public/yappr.png), and lib/dash-platform-client.ts.

DashPlatformClient duplicated postService.getTimeline behind an any-typed cache and a third copy of the SDK response normalizer. Its two callers (For You feed, explore search) now call postService.getTimeline, which returns transformed Post objects, so the feed no longer re-transforms documents it already has. The platform-auth clientIdentity port existed only to feed this client and is dropped. Note the per-page 2-minute cache inside the old client is gone; use-feed-data still caches the first page via cacheManager, so this only affects re-scrolling already-seen pages.

The app store carried a currentUser slot seeded from mock data that nothing read; it and the mock user are gone, leaving lib/mock-data.ts as the default-avatar helper it actually is (CLAUDE.md updated to say so).

Lint fixes

Behavior-preserving except where noted:

  • Floating promises in hooks/contexts get .catch handlers that log. The enrichment completion tracker uses allSettled.
  • Non-null assertions replaced with narrowing. In private-post-content.tsx the three private fields are destructured once per callback; attemptRecovery gains the guard attemptDecryption already had.
  • exhaustive-deps: use-blog-follow's toggle now depends on followerCount, which fixes a stale rollback value. fetchReplyChain in use-post-detail is memoized (its only dep, enrich, is stable). The validation hooks depend on the memoized array instead of .join(',').
  • any casts: profile maps are typed as UnifiedProfileDocument, dropping 39 dead (profile as any)?.data || profile fallbacks (getProfilesByIdentityIds already returns flat documents). Notification queries go through the typed queryDocuments helper instead of sdk.documents.query(... as any).

Config leftovers

tsconfig target: es5es2020. Malformed last .gitignore line (.gitignore worktrees) → worktrees/. Stale ./pages/** tailwind glob and images.unsplash.com domain removed. README no longer names a nonexistent build:gh-pages script or files that do not exist.

Overlap

#369 also touches lib/feed/load-for-you-feed.ts and hooks/use-feed-data.ts. Whichever lands second will need a small rebase; the conflict is confined to the loadForYouFeed call site and the removed forceRefresh option.

Validation

npm run lint (0 warnings), npx tsc --noEmit, npm run test (48/48), npx knip --include files,dependencies,unlisted, npm run build all clean locally.

🤖 Generated with Claude Code

PastaPastaPasta and others added 4 commits September 7, 2026 11:34
…direct deps

The lint script was a bare 'next lint', which only covers app/ components/ lib/ (and pages/ src/), so hooks/ and contexts/ were never linted locally or in CI and two real errors hid there. It now names every source directory and fails on warnings; the previously warn-level rules are errors since the tree is at zero.

Adds Vitest with 48 specs over the pure lib modules (WIF/hex codecs, AES-GCM, hash160, bloom filter, compression/chunking, slugs, tag/mention extraction) and knip for dead files/exports/deps, both wired into CI. knip enforces files/dependencies/unlisted now; unused exports are reported until the backlog is cleared.

Direct imports of @dashevo/wasm-sdk, @storacha/access and @ucanto/principal were only satisfied transitively; they are listed explicitly. Drops the unused @radix-ui/react-slider. Also: tsconfig target es5→es2020, malformed .gitignore line, stale pages/ tailwind glob and unsplash image domain.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Floating promises in hooks/contexts get .catch handlers that log; the enrichment completion tracker uses allSettled. Non-null assertions are replaced with narrowing (private post fields destructured once, variant axes captured, cart load returns its value). exhaustive-deps: real missing deps added (blog comment count callback, blog follower count, fetchReplyChain now memoized), the validation hooks depend on the memoized array instead of a join, and the sidebar effect reads primitives.

Explicit any: profile maps are typed as UnifiedProfileDocument (dropping the dead '.data || profile' fallbacks), notification queries go through the typed queryDocuments helper, pagination-utils gets a minimal structural SDK interface instead of any, and the DiceBear style map uses Style<object>.

@next/next/no-img-element is turned off in config: with output:export images are unoptimized, next/image adds nothing here, and 13 sites already disabled it inline.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
build:gh-pages never existed (the script is build:subpath). The structure tree listed a profile-migration-service, lib/utils.ts, types/sdk.ts, a /profile route, the deleted hooks, and dash-platform-client, none of which exist.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…m knip config

postService.getTimeline hands back createDefaultUser placeholders (hasDpns: false, 'Unknown User'), but PostCard reads hasDpns === undefined as 'still resolving' and false as 'no DPNS name', so every For You card would flash a truncated identity id until enrichment landed. The feed now resets the author to the loading shape, matching what transformRawPost produced. The now-unused forceRefresh option is dropped.

knip's own hints: the plugin-covered config entries and the default-ignored dirs were redundant.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Sep 7, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Team

Run ID: 77406f55-d298-49d6-a82e-cb7f0ac1f370

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@thepastaclaw

thepastaclaw commented Sep 7, 2026

Copy link
Copy Markdown
Collaborator

🕓 Ready for review — 28 ahead in queue (commit 59554f1)
Queue position: 29/29 · 2 reviews active
ETA: start ~07:43 UTC · complete ~08:45 UTC (median 1h 2m across 30 recent reviews; 2 slots)
Queued 6m ago · Last checked: 2026-09-07 17:10 UTC

@cloudflare-workers-and-pages

Copy link
Copy Markdown

Deploying yappr with  Cloudflare Pages  Cloudflare Pages

Latest commit: 59554f1
Status: ✅  Deploy successful!
Preview URL: https://c4c3c58d.yappr.pages.dev
Branch Preview URL: https://chore-quality-gates.yappr.pages.dev

View logs

@cloudflare-workers-and-pages

Copy link
Copy Markdown

Deploying yappr-v2 with  Cloudflare Pages  Cloudflare Pages

Latest commit: 59554f1
Status: ✅  Deploy successful!
Preview URL: https://e20a0db0.yappr-v2.pages.dev
Branch Preview URL: https://chore-quality-gates.yappr-v2.pages.dev

View logs

@PastaPastaPasta
PastaPastaPasta merged commit 70b6bb3 into staging Sep 7, 2026
10 checks passed
This was referenced Sep 7, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants