fix: make standalone checkouts work and repair page.evaluate under tsx - #7
Merged
Merged
Conversation
…nder tsx Three defects found by running a clean clone from GitHub in a sandbox with no surrounding deployment tree. docker compose was unusable in any standalone checkout. The mcp service pulled in `../.env.shared`, a file that only exists in the deployment tree this repo is normally checked out into. Compose validates env_file for *every* service when it loads the project, not just the one being started, so `docker compose run --rm app` failed with "env file ../.env.shared not found" in a fresh clone — as did config, build and the test profile. Marked optional via the long-form env_file syntax. The other two lkv couplings turn out not to block anything: the external agentic-ops network is only required by services that attach to it (app uses network_mode: host), verified by pointing it at a network that does not exist. Auto-scrolling silently did nothing on every page. `npm run crawl` is `tsx`, which transforms through esbuild, whose keepNames pass rewrites named function expressions as `__name(fn, "name")` — including inside page.evaluate() callbacks, which Playwright serialises and runs in the browser where `__name` is undefined. The headless scroll callback declares `const scrollStep`, so it threw `ReferenceError: __name is not defined` on every page; the surrounding try/catch turned that into a warning, so lazy-loaded content was never triggered before extraction and nobody noticed. Shimmed in a preNavigationHook rather than by banning named inner functions, so future evaluate callbacks cannot regress. Unused under `node dist/` — tsc emits no __name. The crawl manifest wrote `"previousCrawlDate": ""` for full crawls; the field means "the crawl this one was diffed against", so it is now omitted instead. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…ndler Fixing the __name ReferenceError let the headless scroll callback actually run for the first time, which exposed what it does: 50px every 800ms, plus a 3-second pause every 15 steps, until it reaches the bottom. On a long page that is minutes. Crawlee bounds the request handler by requestTimeoutSecs (60s in crawler.yml), so every page now aborted as a timeout and got retried — a sandbox crawl capped at 8 pages was still on "Processing page 13/8" after ten minutes. More load on the target, not less; the same failure mode the load-shaping docs warn about for --rate-limit. Scrolling is here to trigger lazy-loaded content, not to satisfy a bot detector, so it is now bounded three ways: reaching the bottom, a 40-step cap (a backstop for infinite-scroll pages whose scrollHeight grows as you go), and a 5s wall-clock budget — all far below the handler timeout. Steps are roughly a viewport each with jitter, so a normal page finishes in well under a second. Browser globals are hoisted to single-line consts inside the callback: an eslint-disable comment covers only the following line, and Prettier is free to wrap a long expression across several, which silently uncovered them. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
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.
Found by cloning this repo fresh from GitHub into a sandbox with no surrounding deployment tree — no ops-proxy, no
agentic-opsnetwork, no sibling repositories — and running the documented workflow end to end.1.
docker composewas unusable in any standalone checkoutThe
mcpservice referenced../.env.shared, a file that only exists in the deployment tree this repo is normally checked out into. Compose validatesenv_filefor every service when it loads the project, not just the one being started, so a clean clone failed on every compose command —config,build,run --rm app, the test profile:Marked optional with the long-form
env_filesyntax. The other two lkv couplings turn out not to block anything, verified rather than assumed:../.env.sharedagentic-opsexternal networkappusesnetwork_mode: host. Confirmed by repointing it at a network that does not exist and runningappanyway../ludekkvapil/public/seoapp/test/typecheck; only themcpservice mounts itREADME gains a short "Standalone checkouts" section stating what a fresh clone does and does not need.
2.
page.evaluate()threw on every page, so auto-scrolling never rannpm run crawlistsx, which transforms through esbuild, whosekeepNamespass rewrites named function expressions as__name(fn, "name"). That rewrite also lands insidepage.evaluate()callbacks, which Playwright serialises and executes in the browser — where__nameis undefined. The headless scroll callback declaresconst scrollStep, so every page produced:Each evaluate has its own try/catch, so this only ever surfaced as a warning: lazy-loaded content was never triggered before extraction and nobody noticed. Shimmed in a
preNavigationHookrather than by banning named inner functions, so future callbacks cannot regress. Unused undernode dist/— tsc emits no__name.3. …which then exposed that the scroll itself was pathological
With the callback finally running, the original walk showed its true cost: 50px every 800ms plus a 3-second pause every 15 steps — minutes on a long page. Crawlee bounds the handler by
requestTimeoutSecs(60s), so every page aborted as a timeout and got retried: a crawl capped at 8 pages was still onProcessing page 13/8after ten minutes. More load on the target, not less — the same failure mode the load-shaping docs warn about for--rate-limit.Scrolling exists to trigger lazy-loaded content, not to satisfy a bot detector, so it is now bounded three ways: reaching the bottom, a 40-step cap (backstop for infinite-scroll pages whose
scrollHeightgrows as you go), and a 5s wall-clock budget — all far below the handler timeout.__nameerrorspage 13/8Browser globals are now hoisted to single-line consts: an
eslint-disablecomment covers only the following line, and Prettier is free to wrap a long expression across several, which silently uncovered them.4. Manifest cosmetic
_crawl-meta.jsonwrote"previousCrawlDate": ""for full crawls. The field means "the crawl this one was diffed against", so it is omitted instead.Verification
Fresh clone of this branch into an empty directory with no siblings present:
docker compose configtargets resolve;build,run, and the test profile work_crawl-meta.jsonwritten with nopreviousCrawlDatekeyreport:404andseo-auditproduce correctly scoped outputtsc --noEmitclean; lint back at its 90-warning baseline, 0 errors🤖 Generated with Claude Code