# Barkday™ Repo Review — 2025-10-26 14:54:48 CT Below is a concise review of the uploaded fileset. Items are ordered by impact. ## Findings - **High** — **.github/workflows/ai-health.yml**: Workflow references docs/ai-pack-all.txt endpoint that does not exist in repo; will 404 in CI. - _Suggested fix:_ Either (A) switch PACK_URL to '/Barkday/dog-gifts.json' (simple) or (B) add a pack builder to emit docs/ai-pack-all.txt. - **High** — **app.js**: GIFT_FEED_URL reads from raw.githubusercontent.com; loadGifts() has no local fallback path if the network blocks or rate-limits. - _Suggested fix:_ Use BarkdayFetch.fetchJSONWithETag first; if null, fallback to local 'dog-gifts.json'. See patch below. - **High** — **app.js**: Chewer mapping collapses to non-schema enums. dog-gifts.schema.json allows 'any','gentle','normal','power'. Current code maps 'power'→'strong' and 'gentle'→'normal', breaking matches. - _Suggested fix:_ Normalize synonyms into the canonical four enums. See patch below. - **Medium** — **service-worker.js**: Cache-first with ignoreSearch for all requests except index/app.js. JSON under /data/ and gift feed may serve stale copies despite ?v= bumps. - _Suggested fix:_ Handle JSON (and /data/) as network-first with cache fallback, or stop ignoring search for .json. Patch below shows a safe rule. - **Medium** — **index.html**: No visible affiliate disclosure near 'Gift ideas' section; only appears in Privacy page. - _Suggested fix:_ Insert a short affiliate note under the Gift section for compliance. ## What’s already good - Service Worker precache list resolves to existing assets; maskable icons present. - ICS export uses UTC (`toISOString()` → `Z`), which is correct for cross-timezone calendars. - PDF add‑on already uses `QR_SCALE = 0.6` (~60%), per your request. - Breed naming is corrected to “Greater Swiss Mountain Dog” in all uploaded data files. - All `data/*.json` parsed successfully (no syntax errors detected). - Manifest `start_url` and `scope` = `/Barkday/` matches GitHub Pages base path. ## Ready-to-apply patches (surgical) ### app.js ```diff // --- Replace the chewer normalization block in app.js with this --- const normChew = (s) => { // Map synonyms → canonical set: 'any','gentle','normal','power' let t = String(s || '').toLowerCase(); // Strip obvious filler and punctuation t = t.replace(/\bchew(ers?)?\b/g, '').replace(/[^a-z]/g, '').trim(); const map = { any: 'any', all: 'any', whatever: 'any', gentle: 'gentle', soft: 'gentle', light: 'gentle', normal: 'normal', regular: 'normal', medium: 'normal', power: 'power', strong: 'power', tough: 'power', super: 'power', heavy: 'power' }; return map[t] || t; }; // ... // In loadGifts(), replace the initial fetch with ETag + local fallback: async function loadGifts(){ els.gifts.innerHTML=''; els.giftMeta.textContent='Loading…'; try{ let items = await (window.BarkdayFetch?.fetchJSONWithETag ? BarkdayFetch.fetchJSONWithETag(GIFT_FEED_URL, { cacheMinutes: 120, lsKey: 'giftFeed' }) : fetch(GIFT_FEED_URL, { cache:'no-store' }).then(r=>r.json()) ); if (!items) { // robust local fallback if remote is blocked or returns HTML try { items = await fetch('dog-gifts.json', { cache:'no-store' }).then(r=>r.json()); } catch {} } if (!Array.isArray(items)) throw new Error('Gift feed unavailable'); // ... (rest of the existing filtering code follows unchanged) } catch (e) { console.warn('[Barkday][Gifts] failed:', e); els.giftMeta.textContent = 'Gift ideas are temporarily unavailable (network/cache). Try again in a bit.'; return; } } ``` ### service-worker.js ```diff // --- Insert in service-worker.js, replacing the fetch handler with this policy --- self.addEventListener('fetch', (event) => { const req = event.request; const url = new URL(req.url); const isNav = req.mode === 'navigate'; const isAppJs = url.pathname.endsWith('/app.js') || url.pathname.endsWith('app.js'); const isJSON = url.pathname.endsWith('.json') || url.pathname.includes('/data/'); // Network-first for index.html, app.js, and JSON/data (to avoid stale packs) if (isNav || isAppJs || isJSON) { event.respondWith( fetch(req).then((res) => { const copy = res.clone(); const key = isAppJs ? new Request(url.origin + url.pathname) : req; caches.open(CACHE).then((c) => c.put(key, copy)); return res; }).catch(() => { // Return cached copy (match ignores search for resilience on ?v= cache-busters) const fallbackKey = isAppJs ? new Request(url.origin + url.pathname) : req; return caches.match(fallbackKey, { ignoreSearch: true }); }) ); return; } // Everything else: cache-first event.respondWith( caches.match(req, { ignoreSearch: true }).then((cached) => { if (cached) return cached; return fetch(req).then((res) => { const copy = res.clone(); caches.open(CACHE).then((c) => c.put(req, copy)); return res; }); }) ); }); ``` ### .github/workflows/ai-health.yml ```diff # --- Replace PACK_URL line in .github/workflows/ai-health.yml --- const PACK_URL = 'https://candidquality.github.io/Barkday/dog-gifts.json'; // And remove the pack parsing; gifts = await (await fetch(PACK_URL)).json(); ``` ### index.html ```diff
As an Amazon Associate, Barkday™ earns from qualifying purchases. This does not affect which products are shown.
```