- registry.npmjs.org was intermittently ETIMEDOUT mid-download from this host; switched to registry.npmmirror.com (also raised npm's own retry budget as a second line of defense). - frontend/package-lock.json on disk was actually an empty directory (untracked, root-owned — a stray artifact, likely from an old bad bind-mount), which broke `COPY . .` once npm install got past it. - documents/page.tsx had a real type error (selectedItem.file narrowing didn't survive into the .map() closure) that `next dev` never surfaced but `next build`'s stricter check does — fixed by hoisting the narrowed array into selectedFiles once instead of re-narrowing selectedItem.file at each use. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Gh2UXUQUVBWroWEnn1FLFG