F-11 Build Debugging — 4 build issues уrok
Date: 2026-05-18 Task: Closing F-11 после того как agent ac1b2447 написал code но Docker build падал 8 commits подряд
Context
Agent написал большую часть F-11 (~2.7h actual): Next.js 16.2 + Tailwind 4 + shadcn + Phosphor + brand tokens + modules registry + auth skeleton + 9 страниц + 4 vitest tests + 5 playwright e2e. Build падал на VPS, agent timed out 403s. Я (interactive LLM) finalize за ~1.5h.
4 Issues найдено + fixed
1. Turbopack ignores turbopack.root в pnpm monorepo (Next.js bug #92540)
Symptom:
Error: Turbopack build failed./src/appError: Next.js inferred your workspace root...We couldn't find the Next.js package (next/package.json) fromthe project directory: /app/apps/web/src/appRoot cause: known regression в Next.js 16.2.x — Turbopack ignores turbopack.root config в pnpm monorepos. Issue vercel/next.js#92540.
Fix: build с --webpack flag (Next 16 still ships webpack fallback). Updated:
apps/web/Dockerfile:pnpm exec next build --webpackapps/web/package.json:"build": "next build --webpack"
Phase 1.5 TODO: revisit когда Next 16.3+ зафиксит upstream → вернуть Turbopack.
2. .gitignore line 15 lib/ greedily matched apps/web/src/lib/
Symptom: Webpack build (после Issue #1 fix) выдал:
Module not found: Can't resolve '@/lib/utils'Module not found: Can't resolve '@/lib/auth/jwt'Module not found: Can't resolve '@/lib/api/client'Module not found: Can't resolve '@/lib/api/queries'Root cause: Repo root .gitignore имел lib/ (Python setuptools artifacts pattern из стандартного Python .gitignore). Greedy unanchored pattern → matches любой lib/ dir, включая apps/web/src/lib/. Все 5 файлов (utils.ts, theme/tokens.ts, auth/jwt.ts, api/client.ts, api/queries.ts) никогда не были checked into git. Локально build работал (файлы в working dir), но Docker COPY копировал только git-tracked → missing.
Fix: changed lib/ → /lib/ (anchored к repo root only). Commit 5 missing файлов.
General lesson для пользователя: always check git ls-files after agent создаёт код в типовых dirs (lib/, build/, dist/, vendor/, target/) — могут быть caught Python/Node/Java .gitignore patterns.
3. Next standalone не bundles deps в pnpm monorepo → “Cannot find module ‘next’”
Symptom: Container start crash loop:
Error: Cannot find module 'next'Require stack: /app/server.jsRoot cause: Next standalone build с pnpm + monorepo не находит deps т.к. /app/node_modules/next это symlink на ../../../node_modules/.pnpm/next@.../. В runtime stage скопирован только .next/standalone, без .pnpm/ store.
Fix: добавил outputFileTracingRoot: monorepoRoot в next.config.mjs. Next traces все workspace deps и bundles в .next/standalone/node_modules/. После fix server.js mirrors monorepo path → /app/apps/web/server.js (а не /app/server.js как было до tracing root).
4. Healthcheck wget connects к ::1 (IPv6), server bind 0.0.0.0 (IPv4)
Symptom: Container running, HTTP работает через Docker network, но healthcheck reports “unhealthy”:
wget: can't connect to remote host: Connection refusedRoot cause: node:22-alpine wget resolves localhost → ::1 (IPv6). Next.js server binds 0.0.0.0:3000 (IPv4 only). IPv6 connection refused.
Fix: explicit http://127.0.0.1:3000/ в healthcheck test.
Bonus: Caddyfile bind-mount inode mismatch
После editing /opt/razmakh-stack/Caddyfile host inode changed (atomic write), container’s bind-mounted /etc/caddy/Caddyfile всё ещё old inode = old content. caddy reload re-reads file but file inside container ≠ file on host.
Fix: docker compose restart caddy — перемонтировал bind mount = новый inode.
Bonus: CI deploy stage wrong paths
.github/workflows/ci.yml deploy step had multiple legacy issues:
cd /opt/razmakh-stack && git pull— stack dir не git repo (repo at/opt/razmakh/repo)docker compose build razmakh-api— actual service nameapi- Не билдил/перезапускал
web→ F-11 frontend никогда бы не deploy’ился - “dubious ownership” т.к. repo owned by root → нужен
sudo
Fixed на правильные пути + sudo + добавил web build/up/healthcheck wait.
General lessons
-
Verify git tracking после любого нового кода в стандартных dirs:
git ls-files <new-dir>/— если empty значит gitignore catched. Особенно для multi-language repos (Python .gitignore patterns affect JS!). -
Workaround known framework bugs быстро: Don’t fight Turbopack #92540 —
--webpackflag решает за 1 commit, vs days of trying configs. Add TODO comment + Phase X.Y revisit. -
Test locally в близких к prod условиях: Local pnpm install использует strict checks которые agent’s Docker не имеет. Bypass
next buildнапрямую черезnode node_modules/next/dist/bin/next buildесли pnpm install сам в pre-check падает. -
Bind mounts не survive atomic-write file changes: After
mv tempfile target, container всё ещё видит старый file (старый inode). Restart container для re-mount. -
Alpine wget defaults to IPv6: Если Node binds 0.0.0.0, в healthcheck use explicit
127.0.0.1илиlocalhost4.
Time
- Plan: 2-3 дня (16-24h)
- Agent (ac1b2447): ~2.7h
- Finalization (me): ~1h
- Total actual: ~3.7h ≈ 6× faster than plan
Estimates-recalibration ratio holds: LLM-driven dev = plan/6-8.
Files affected
apps/web/Dockerfile(multiple commits)apps/web/next.config.mjs(outputFileTracingRoot)apps/web/package.json(—webpack flag).gitignore(anchor/lib/)apps/web/src/lib/*(5 files added — were ignored)services/docker-stack/docker-compose.yml(healthcheck 127.0.0.1).github/workflows/ci.yml(deploy stage rewrite)