Main -> Development#2399
Merged
Merged
Conversation
…files Replace end-of-stream single flush with per-BATCH_SIZE flushes during the CSV parse loop. Valid and invalid item batches are written to DB every 100 rows, arrays are cleared, and totalProcessed is updated incrementally so progress is visible on long-running jobs. Remaining rows are flushed after the loop as before. Fixes evo (174K rows) and gearx (166K rows) jobs stuck in 'running' forever.
Clothing and footwear brands (kuhl, obozfootwear, prana) routinely omit weight data, causing 0% ingest rates. Weight is important for comparisons but it is better to ingest items without it than to reject them entirely. Items missing weight are stored as-is and simply excluded from weight views. Weight and weightUnit remain nullable at the DB layer (no schema change).
The ON CONFLICT DO UPDATE SET clause was using COALESCE(table.field, excluded.field) which means existing non-null values could never be corrected by a fresh scrape. Changed to excluded.field directly so re-scraping always wins, allowing price, weight, availability, and other fields to be corrected when the source data changes. Exception: created_at retains COALESCE so the original creation timestamp is preserved across upserts.
…state Manually runnable script that fails any ETL job that has been in 'running' status for more than 30 minutes. Addresses jobs left stuck when the Worker crashes mid-stream (e.g. OOM) without reaching the error handler.
Protect against scrapers returning weight=0 or weight<0 overwriting valid existing weight data. Weight and weight_unit now only update when the incoming value is a positive number; otherwise the stored value is preserved. All other fields continue to accept the fresh scraped value so stale data can still be corrected by re-scraping.
- Create packages/units with NIST-exact avoirdupois constants (1 oz = 28.349523125 g, 1 lb = 453.59237 g — single source of truth) - Expose normalize, fromGrams, convert, displayWeight, isWeightUnit, parseWeightUnit; 174 tests including cross-validation vs convert-units v3 - Migrate all call sites: apps/expo weight utils, computePackWeights, computePackTemplateWeights, computeCategories, lib/utils/compute-pack, packages/api weight utils and compute-pack - Fix convertToGrams/convertFromGrams which were NOT inverses of each other (used 28.3495 vs 28.35 — silent drift of ~0.016 oz per 100 oz) - Fix computeCategories percentage bug: was mixing pack.totalWeight (in preferred unit) with convertToGrams, giving wrong % for non-gram users - Update all test suites to NIST values; 730 tests passing (0 failures) - Add convert-units 3.0.0-beta.8 as devDependency for cross-validation 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
…lidation-v2 Fix/etl memory and weight validation v2
- Add @media (prefers-reduced-motion: reduce) to landing app globals.css to satisfy WCAG 2.3.3 accessibility requirement (fixes react-doctor check) - Bump 8 expo packages to SDK-54 required patch versions: expo ^54.0.33→~54.0.34, expo-dev-client/file-system/glass-effect/ image-picker/linking/updates/web-browser each +0.0.1 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
Satisfies the no-raw-typeof custom lint rule enforced by the pre-push hook.
… boundaries
- Add 50-item pagination (URL ?page=N) to catalog, packs, users pages
- Debounce search input 300ms; resets page param on new search
- POST /api/admin/analytics/catalog/etl/reset-stuck endpoint replaces raw SQL script
- Reset Stuck Jobs button in ETL card with spinner + result feedback
- Root + dashboard error boundaries
- Delete packages/api/scripts/reset-stuck-etl-jobs.sql
- Fix queryKeys.admin.* to accept { q, page, limit } params
…ey invalidation
- Add nuqs for type-safe URL query state (search, pagination)
- SearchInput simplified to ~10 lines: useQueryState handles debounce (300ms
throttle), URL sync, and unmount cleanup automatically
- Pagination pages use parseAsInteger — invalid ?page=foo safely defaults to 0
- queryKeys.admin.{users,packs,catalog} restructured to .all (prefix, for
invalidation) and .list(params) (for useQuery) — fixes post-delete not
refreshing the list
- catalogAnalytics.etl same pattern: .all for invalidation, .list(limit) for
queries — fixes ETL table not updating after reset-stuck
- Wire NuqsAdapter into app/layout.tsx
…root-based invalidation
- Add global-error.tsx as true root error boundary (with inline html/body)
- Rename RootError in error.tsx (was incorrectly named GlobalError)
- Add usePaginatedSearch hook so search atomically resets page via nuqs
- Wire onSearch={setSearch} on catalog/packs/users pages
- Show "no stuck jobs found" and error state on Reset Stuck ETL button
API: expand all three list endpoints to return full field sets - users: +avatarUrl, +updatedAt - packs: +isAIGenerated, +tags, +image, +updatedAt - catalog: +description, +productUrl, +sku, +model, +ratingValue, +reviewCount, +availability, +color, +size, +material, +seller, +currency, +images, +variants, +techs, +links UI: - Replace hand-rolled error.tsx files with react-error-boundary ErrorBoundary in layouts; add shared ErrorFallback component - Add RawObjectDialog (Braces icon) on every row: users, packs, catalog items, ETL jobs — shows full JSON in a scrollable dialog - Users: avatar thumbnail / initial fallback in User column - Packs: AI badge, inline tags (up to 3) - Catalog: Status column with availability + star rating, product URL link icon, description/model sub-lines - ETL table: +Invalid column (red when >0), +Completed column
- ErrorBoundary: add resetKeys={[pathname]} so boundary auto-resets
on route changes instead of keeping fallback across navigation
- error-fallback.tsx + global-error.tsx: stop surfacing raw error.message
to users; log to console instead
- RawObjectDialog: add visually-hidden DialogDescription to silence
Radix UI aria-describedby warning
- Note: .returning({ id }) on reset-stuck blocked by Drizzle TS types
in this version; full .returning() retained
feat(units): weight math audit — new @packrat/units package with NIST constants and 174 tests
…lidation-v2 feat(admin): pagination, search debounce, reset-stuck UI, error boundaries
Introduces apps/trails — a standalone Next.js + Cloudflare Worker app deployed to trails.packratai.com. Visitors can explore nearby trails on a public Leaflet/Overpass map without auth. Search is gated behind account creation, converting anonymous visitors into PackRat users before nudging them toward the native app. Key pieces: - CF Worker hybrid: serves Next.js static export + proxies /api/* to PackRat API with Bearer token pass-through, CORS, rate limiting, and edge caching on trail detail responses - Public map: Overpass API queries via @packrat/overpass, no auth required, geolocation with US center fallback - Auth gate: tabbed register/login/forgot-password dialog; full email OTP verification flow using existing /api/auth/* endpoints - Web token storage: localStorage with resilientTokenStorage pattern (JSON-parse guard for atomWithStorage compat) - Authenticated search: authedFetch with automatic 401 refresh + retry - Download CTA: dismissable sticky banner with mobile UA detection for App Store / Google Play deep links 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
workers-types ^4.20250620.0→^4.20250405.0, @types/leaflet ^1.9.17→^1.9.21, wrangler ^4.21.1→^4.21.2
UserInfo/AuthResponse now use zod schemas; Tab narrowing uses makeEnumGuard.
…PackRat API The worker was a same-origin proxy adding rate limiting and CORS, but the PackRat API already handles both. Pointing @packrat/api-client straight at the API via NEXT_PUBLIC_PACKRAT_API_ORIGIN (defaults to api.packratai.com) eliminates the extra deployment layer. Removes: worker/index.ts, wrangler.jsonc, @cloudflare/workers-types, wrangler dep 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
feat(admin): ETL failure drill-down + load-more pagination
Catalog: 40×40 thumbnail from first image in images[] Packs: cover image thumbnail; sub-line shows updatedAt when different from createdAt Users: sub-line shows last activity date (updatedAt) when different from joined date Analytics overview: replace Avg Price card with Price Range (min–max) Analytics ETL table: show filename and scraper revision (truncated) under source 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
…tend feat(trails): trail search micro frontend acquisition surface
processCatalogEtl never set status='completed' on the happy path —
the updateEtlJobProgress completion check only fired when remainingItems>0,
so jobs whose row count was an exact multiple of BATCH_SIZE (100) stayed
'running' until Reset Stuck marked them 'failed' 3 hours later.
Fix: unconditionally set status='completed'/completedAt after flushing
all remaining batches, before the catch block.
Also adds POST /analytics/catalog/etl/:jobId/retry (admin API) which
reconstructs the R2 key as v2/{source}/{filename} from stored job metadata,
creates a new ETL job, and re-queues it — allowing failed loads to be
replayed without re-scraping.
Surfaces a Retry button in the ETL pipeline table for failed jobs.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
fix(etl): mark jobs completed explicitly + add retry for failed jobs
feat(admin): surface hidden data across catalog, packs, users, and analytics screens
- Remove redundant TranslationFunction casts in recent-packs and current-pack - Add doctor:react script to apps/trails and apps/web - Fix TrailMap.tsx useEffect cleanup: track markers and call marker.off() - Add expo-font and expo-image plugins to app.config.ts - Run expo install --fix to update 15 expo packages to SDK 55 expected versions - Upgrade react/react-dom from 19.2.0 to 19.2.6 to satisfy @ai-sdk/react peer dep - Exclude react/react-dom from expo-doctor version check (SDK 55 vs @ai-sdk/react conflict) - Sort root package.json
Release/2.0.25
Contributor
Deploying with
|
| Status | Name | Latest Commit | Updated (UTC) |
|---|---|---|---|
| ✅ Deployment successful! View logs |
packrat-admin | 3535b94 | May 09 2026, 04:49 PM |
Contributor
Deploying with
|
| Status | Name | Latest Commit | Updated (UTC) |
|---|---|---|---|
| ✅ Deployment successful! View logs |
packrat-api | 3535b94 | May 09 2026, 04:49 PM |
Contributor
Coverage Report for API Unit Tests Coverage (./packages/api)
File Coverage
|
||||||||||||||||||||||||||||||||||||||||||||
Contributor
Coverage Report for Expo Unit Tests Coverage (./apps/expo)
File Coverage
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Contributor
|
Caution Review failedThe pull request is closed. ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: ASSERTIVE Plan: Pro Run ID: ⛔ Files ignored due to path filters (1)
📒 Files selected for processing (113)
WalkthroughAdds Trails app (auth, search, map), introduces ChangesTrails App
Shared Units Refactor
Admin Dashboard
API Backend
Expo App
Repo Configs/Docs
Estimated code review effort🎯 5 (Critical) | ⏱️ ~120 minutes Possibly related PRs
Suggested labels
Suggested reviewers
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
|
This was referenced May 14, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary by CodeRabbit
Release Notes
New Features
Improvements
Bug Fixes