fix(codebase-memory): stop nginx mangling the CDN font URL (blank 3D node labels)#82
Merged
Merged
Conversation
…node labels)
The codebase-memory-ui nginx sub_filter rewrote every `/font-files/` occurrence
in the served SPA bundle to `/codebase-memory/font-files/`. But the pinned v0.8.1
bundle NEVER requests `/font-files/` from its own origin: the only occurrence is
`${base}/font-files/${id}/...` where `base` is the EXTERNAL unicode-font-resolver
CDN (https://cdn.jsdelivr.net/gh/lojjic/[email protected]/packages/data).
So the rewrite could only corrupt that CDN URL, producing
`.../packages/data/codebase-memory/font-files/latin/...woff` -> 404 on jsdelivr ->
every 3D graph node label silently failed to load (troika-three-text logs
"Failure loading font" and skips the glyph; the failure is non-fatal/graceful, so
the graph geometry still renders, but labels are blank).
Root cause: the two `/font-files/` sub_filter rules were based on the false premise
(carried in the original design comments) that the UI serves fonts from its own
origin. It does not. Removing the rules is the upstream fix — not a per-URL
workaround — because there is no legitimate origin-relative `/font-files/` request
to rewrite for this bundle.
Fix: drop both `/font-files/` sub_filter rules; document precisely why re-adding
them is wrong; correct the stale "serves /font-files" claims in entrypoint.sh and
README.md so the declared behavior matches reality.
Evidence (live, 2026-07-09):
- served bundle: single `"/font-files/` occurrence, always `V+"/font-files/"` where
V = the jsdelivr CDN base (grep verified before/after).
- before: headless render logged
`Failure loading font https://cdn.jsdelivr.net/.../packages/data/codebase-memory/font-files/latin/sans-serif.normal.100.woff`
- after recreate: the same font requests return `200` from `<CDN>/font-files/latin/
sans-serif.normal.{100,400}.woff`; zero console errors; graph loads 50k nodes.
- assets/rpc/api still 200 through nginx; PR #75 auto-index still fires on start and
re-populates 539,944 nodes / 554,184 edges after the recreate.
Scope note: this removes the one reproducible in-scope defect. The operator's
whole-canvas black screen could NOT be reproduced as a build-context cause (assets,
rpc, api, auth 202, process supervision, and 539k-node data all verified healthy);
the residual black canvas seen headlessly is a swiftshader software-GL artifact,
not representative of a real-GPU browser. See PR body for the shared-edge findings.
Co-Authored-By: Claude Opus 4.8 <[email protected]>
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.
Symptom
Operator reports the codebase-memory 3D graph UII at
/codebase-memory/shows a black screen (page loads, graph area stays dark).Diagnosis (read-only, live evidence)
Walked every layer of the running
ordo-v2-codebase-memory-ui-1(image rebuilt today by PR #75):codebase-memorybinary (pid 12, 127.0.0.1:9749) both running; PR #75 auto-index wrapper intact/codebase-memory/.../rpc,/api/*/api/layoutreturns real 3D coordinates/codebase-memory/*route unchanged & correct; obsidian PRs (#76–81) added/obsidian/after it without touching itNo PR #75 regression, no CBM_VERSION bump, sub_filter matches the pinned v0.8.1 bundle.
Root cause found (in scope)
The nginx
sub_filterrewrote every/font-files/in the bundle to/codebase-memory/font-files/. But the v0.8.1 bundle has exactly one/font-files/occurrence and it is always${base}/font-files/${id}/...wherebaseis the external unicode-font-resolver CDN (https://cdn.jsdelivr.net/gh/lojjic/[email protected]/packages/data). The rewrite corrupts that CDN URL →.../packages/data/codebase-memory/font-files/latin/…woff→ 404 on jsdelivr → every 3D node label fails to load. troika-three-text logsFailure loading fontand skips the glyph (graceful — geometry still renders, labels blank).The original design comments falsely assumed the UI serves
/font-files/from its own origin. It never does.Fix
Remove both
/font-files/sub_filter rules (upstream fix, not a per-URL workaround — there is no legitimate origin-relative/font-files/to rewrite for this bundle). Correct the stale "serves /font-files" claims inentrypoint.sh+README.mdso declared behavior matches reality.Acceptance (live, post-recreate)
V+"/font-files/"(un-mangled).<CDN>/font-files/latin/sans-serif.normal.{100,400}.woff; the previousFailure loading fonterror is gone; 0 console errors; graph loads 50k nodes.Operator should now see: the 3D graph canvas with nodes, and — the substantive fix here — legible node labels (previously blank).
Honest scope caveat + shared-edge signal (for the parallel Obsidian agent)
The whole-canvas black could not be reproduced as a build-context cause: assets, rpc, api, auth (202), process supervision, and 539k-node data are all healthy. The residual black canvas observed in headless capture is a swiftshader software-GL artifact (this three.js renderer doesn't rasterize under swiftshader), not representative of the operator's real-GPU Firefox.
Shared-edge finding (diagnosis only — Caddyfile NOT edited): the
/codebase-memory/*and/obsidian/*routes are independenthandleblocks behind the sameforward_auth; the obsidian PRs added/obsidian/after@codebasememorywithout modifying it, and today's caddy reload only reconciled the/grafana/drift + added the obsidian route. No shared edge change degrades/codebase-memory/*handling, headers, or route ordering. So the two black screens most likely do not share an edge-layer root cause — Obsidian's is in its own (selkies/websocket/GUI) scope, which the parallel agent owns.🤖 Generated with Claude Code