Skip to content

fix(reports): default report scripts to the latest crawl, not the historical union - #5

Merged
siva01c merged 2 commits into
mainfrom
fix/report-crawl-snapshot-scope
Aug 31, 2026
Merged

siva01c merged 2 commits into
mainfrom
fix/report-crawl-snapshot-scope

Conversation

@siva01c

@siva01c siva01c commented Aug 30, 2026

Copy link
Copy Markdown
Owner

Problem

storage/datasets/<domain>/<domain>.jsonl accumulates every crawl of a domain into one merged JSONL. dedupePagesByUrl() correctly keeps only the newest record per URL, but never drops a URL the latest crawl didn't visit at all — a page retired months ago (now redirected, so nothing links to it and the crawler never reaches it again) keeps its stale record forever, and that record is still "newest" for that URL.

Reports built on the full union therefore described a site state that had stopped existing. Verified against ludekkvapil.cz: 9 phantom 404s and 40 phantom missing-JSON-LD findings, all last crawled 2026-06-14, none of them true against the 2026-08-28 crawl (0 and 0 respectively).

Fix

  • New splitByCrawlSnapshot() / selectSnapshot() / resolveSnapshotMode() helpers in scripts/page-records.ts.
  • Wired into report-404s.ts, report-seo-issues.ts, report-link-graph-issues.ts, generate-title-description-fixes.ts, seo-audit.ts.
  • Default is now the newest crawl only. --all-crawls opts back into the historical union.
  • Every report prints how many pages it covers and how many stale URLs it excluded — nothing disappears silently.
  • report-404s.ts keeps excluded 404s in a separate stale_not_in_latest_crawl field (plus a snapshot/last_seen CSV column pair) instead of dropping them, so a genuinely dead legacy URL stays visible for manual verification without counting as a current issue.
  • Also includes a separately-reviewed, pre-existing uncommitted diff adding load-shaping CLI flags (--concurrency, --delay-min/max, --max-retries, --block-assets) to src/main.ts for gentler third-party crawls, with matching AGENTS.md docs — as its own commit.

Verification

  • New src/tests/services/pageRecords.test.ts (13 tests) covering the snapshot-splitting logic.
  • Full suite: npm test → 260 passed, npm run style clean, tsc --noEmit clean.
  • End-to-end against real data: npm run report:404 -- --domain ludekkvapil.cz → 311 pages, 0 findings, 47 stale excluded, --all-crawls restores 358/9/40.

Note: the branch was originally cut from security/remove-internal-topology, which has since been merged and deleted — rebased cleanly onto current main.

🤖 Generated with Claude Code

siva01c and others added 2 commits August 30, 2026 12:26
Adds --concurrency, --delay-min/--delay-max, --max-retries and
--block-assets to src/main.ts, overriding config/crawler.yml for a
single run so a deliberately gentle crawl doesn't require editing the
shared config.

--block-assets skips CSS/images/fonts/JS subresource requests during
navigation via Crawlee's playwrightUtils.blockRequests — the main
document is never blocked, so extractors still see full server-rendered
markup (title, meta, canonical, JSON-LD, links); JS-rendered content
will not appear.

Documents in AGENTS.md why --concurrency/--delay-min/--delay-max/
--block-assets are preferable to --rate-limit for low-load crawling:
the rate limiter's sleep happens inside the request handler, which
Crawlee bounds by requestHandlerTimeoutSecs (60s) — a throttle longer
than that aborts as a timeout and gets retried, increasing load instead
of reducing it.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…torical union

storage/datasets/<domain>/<domain>.jsonl accumulates every crawl of a
domain into one merged JSONL. dedupePagesByUrl() correctly keeps only
the newest record per URL, but never drops a URL the latest crawl
didn't visit at all — a page retired months ago (now redirected, so
nothing links to it and the crawler never reaches it again) keeps its
stale record forever, and that record is still "newest" for that URL.

Reports built on the full union therefore described a site state that
had stopped existing: on ludekkvapil.cz this surfaced as 9 phantom 404s
and 40 phantom missing-JSON-LD findings, all last crawled 2026-06-14,
none of them true against the 2026-08-28 crawl.

Adds splitByCrawlSnapshot()/selectSnapshot()/resolveSnapshotMode() to
scripts/page-records.ts and wires them into report-404s.ts,
report-seo-issues.ts, report-link-graph-issues.ts,
generate-title-description-fixes.ts and seo-audit.ts. Default is now
the newest crawl only; --all-crawls opts back into the historical
union. Every report prints how many pages it's covering and how many
stale URLs it excluded, so nothing disappears silently.

report-404s.ts additionally keeps excluded 404s in a separate
`stale_not_in_latest_crawl` field (and a snapshot/last_seen CSV column
pair) instead of dropping them — a genuinely dead legacy URL stays
visible for manual verification without being counted as a current
issue.

Adds src/tests/services/pageRecords.test.ts covering the new helpers.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

@siva01c
siva01c merged commit 40181de into main Aug 31, 2026
4 checks passed
siva01c added a commit that referenced this pull request Aug 31, 2026
fix: address code review findings from PR #5
@siva01c
siva01c deleted the fix/report-crawl-snapshot-scope branch August 31, 2026 16:13
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.

1 participant