Conversation
3 tasks
dmarx
force-pushed
the
claude/site-graph-config
branch
from
September 13, 2026 03:34
a685c91 to
5094ebf
Compare
dmarx
force-pushed
the
claude/principle-pages
branch
from
September 13, 2026 03:34
bbe1931 to
540ea53
Compare
dmarx
force-pushed
the
claude/site-graph-config
branch
from
September 13, 2026 03:42
03f2859 to
d14bcbb
Compare
dmarx
force-pushed
the
claude/principle-pages
branch
from
September 13, 2026 03:42
540ea53 to
063addd
Compare
dmarx
force-pushed
the
claude/site-graph-config
branch
from
September 13, 2026 04:03
d14bcbb to
a4952b7
Compare
dmarx
force-pushed
the
claude/principle-pages
branch
from
September 13, 2026 04:03
063addd to
358696a
Compare
dmarx
added a commit
that referenced
this pull request
Sep 13, 2026
`[luria.site] graph`, `graph_height` and `graph_depth` are on main with nothing behind them. There is no `luria/site_graph.py` here and `site.py` imports none, so a project that sets `graph = "..."` gets its Quartz local graph and no explanation -- the documented, defaulted, parsed key is simply never looked at. They arrived by accident. #245 was lifted out of the #242->#243->#244 stack as an isolated change, and its branch carried this hunk across with the `cite` work it was actually for. Nothing caught it, because from outside there is nothing to catch: `docs/configuration.md` is generated from these dataclasses, so a field publishes its own reference row whether or not any code reads it, and an unimplemented setting is indistinguishable from a working one until someone tries it. So the check is the interesting half. A `Site` field is consumed if some module other than config.py names it on a `site` receiver -- `site.icon`, `cfg.site.publish`, `current().site.base_url`, which is how all nine real readers spell it. Crude on purpose: it is the cheapest rule that separates the nine from these three, and it fails naming them. Its own positive control is next to it, because a pattern that matched nothing would report this file clean. The keys come back with the code that implements them, on the stack that has it; nothing else on the record mentions them, and configuration.md loses its rows without being touched. Claude-Session: https://claude.ai/code/session_01YSRQzpm4kAWQSaKWD6V9x2 Co-authored-by: Claude <noreply@anthropic.com>
dmarx
force-pushed
the
claude/site-graph-config
branch
from
September 13, 2026 09:11
a4952b7 to
b700c3d
Compare
dmarx
force-pushed
the
claude/principle-pages
branch
from
September 13, 2026 09:11
358696a to
024c734
Compare
dmarx
force-pushed
the
claude/site-graph-config
branch
from
September 14, 2026 09:12
b700c3d to
482db1f
Compare
dmarx
force-pushed
the
claude/principle-pages
branch
from
September 14, 2026 09:12
024c734 to
1233a17
Compare
dmarx
force-pushed
the
claude/site-graph-config
branch
from
September 15, 2026 09:12
482db1f to
54073e3
Compare
dmarx
force-pushed
the
claude/principle-pages
branch
from
September 15, 2026 09:12
1233a17 to
6be41ea
Compare
dmarx
force-pushed
the
claude/site-graph-config
branch
from
September 16, 2026 09:05
54073e3 to
2f99b0f
Compare
dmarx
force-pushed
the
claude/principle-pages
branch
from
September 16, 2026 09:05
6be41ea to
632e9fd
Compare
The example `[luria.site] graph` promised by ADR-tmp0hx52, produced the way the docs now tell you to produce one: strata-g's luria-record backend loaded against this clone, two computed columns, a filter, four appearance bindings, and the `Canvas — graph data (JSON)` export. Nothing hand-edited. ADR-tmp40zph is what made it one rule. Before principles had pages the URL column needed a special case reconstructing …/docs/design-principles#dp- and the number; now every scheme document answers at /<code> and the expression is `code ? "https://dmarx.github.io/luria/" & code : ""`. That special case was the reason to give them pages in the first place. Curated to 37 nodes, and the threshold is measured rather than picked. All 110 decisions and principles render as an unreadable ball at this height — seen, not assumed. Cited five or more times gives a shape you can read, and 4.5 KB gzipped per page instead of 11.8. `graph_height` is 420px for the same reason. Two defaults luria supplies, both only when the file is silent: navigateOnClick, because these nodes ARE pages of this site and opening one is what a click means there; and the panel title, because a bare export carries none and the viewer falls back to "Graph", which names nothing on a page that already has a title. Temporary codes are filtered out: `luria concretize` numbers those where merges serialize, so a node for one would link to a page that does not exist yet and then move when it does. Verified through a real Quartz v4.5.2 build: Component.Graph gone from the layout, the map on every page above the heading, the page's own lineage graph still at the foot, cursor `pointer` over a node, and a click on ADR-042 requesting ADR-042. Four probe bugs found along the way, all mine, none the code's: extensionless paths against http.server, an unstripped #fragment, a click at a negative page coordinate, and a rect read before smooth scrolling had finished. The handler was right every time. 1115 passed, 33 skipped. luria lint clean. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01YSRQzpm4kAWQSaKWD6V9x2
The first version cut to 37 nodes on a `citations >= 5` threshold, and the reason was legibility — which is a bad reason to drop data from a thing whose job is navigation. A reader who looks for ADR-070, does not find it, and concludes it does not exist has been misled by the picture. Now 248 nodes and 482 edges: everything luria knows about. Density is what the viewer's zoom, pan, search and Fit are for, and `graph_height` is 560px so the shape reads at a glance. A document with a code links to its page; a journal entry or changelog fragment has no code and no page, so its node does not navigate. That is the truth about it, and better than inventing an address. The cost, stated rather than hidden: 24 KB gzipped inlined per page. docs/graphs/README.md loses the threshold justification along with the threshold, and gains the definition of `citations` — a document's in-degree, typed relations plus prose citations, deduped where both join the same pair. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01YSRQzpm4kAWQSaKWD6V9x2
…d apart dmarx's design, and better than what it replaces. The luria record backend gives typed edges; the repository's markdown loaded as an Obsidian vault gives the markdown-link edges. Nodes merge on filename with no configuration — the vault labels by filename stem and the record's `code` is that same string — and the edge Color-by `kind` tells the two kinds apart. 454 nodes, 827 edges: 345 markdown links, 421 cites, 58 influenced_by, 3 superseded_by. Quartz's graph knows only the first group; the lineage graph at the foot of each page knows only the rest. This is both at once, which is the argument for drawing a map by hand rather than generating one. Load order matters and it is a strata-g bug, not a preference: with the vault layer loaded FIRST, `kind` never reaches the edge Color-by catalog even after the record layer is added. Reproduced independently by dmarx. Documented in the recipe as a step, and filed upstream. Label by `code`, because merged containers otherwise inherit the vault node's long title and the labels collide into a paragraph — seen on a real build before it was fixed. Cost stated rather than hidden: 40 KB gzipped inlined per page, up from 24. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01YSRQzpm4kAWQSaKWD6V9x2
The configured graph was one picture inlined on every page — the same everywhere, which is a poster rather than a map of where you are. Each page now shows the nodes within `graph_depth` hops of its own (default 1); `0` restores the whole map for a project that wants the poster. Every one of this record's 151 staged pages finds its node, 117 by repo path and 34 by basename — the two shapes a multi-layer map uses, both of which the build already knows about the page it is staging. Median 6 nodes a page rather than 454. The positions are the author's and are not recomputed: a document sits where it was drawn, so it is in the same place on whichever page you meet it. A nested record now gets NO configured graph. Its pages are not nodes of the parent's map, and the parent's map whole is a picture of a different record — which on an example's page said nothing and cost 38 KB gzipped a page to say it. That was 6.1 MB of the 6.3 MB total; the whole site is now 0.17 MB. Node sizing is uniform, at an exported size near 9, and the number is not taste. nodeRadius is max(1.5, size * min(1, cap/maxSize) * zoom) and a label needs radius > 6 — and min(1, ...) means the viewer only ever shrinks a node, never grows one, so the exported size has to carry it. Sizing by citations pins the floor at 2, which renders at ~2.5px: the low-cited nodes lost their labels while the high-cited ones covered the edges. Two wrong guesses before that (scale 0.5 → ratio 4.3, floor under the threshold; uniform at size 1 → radius 1.5) came from assuming the viewer normalised the largest node to a fraction of the canvas. Reading nodeRadius settled it. Verified on a real Quartz build: ADR-042's page draws a 13-node / 23-edge neighbourhood with readable labels and all four edge colours visible. 1118 passed, 33 skipped. luria lint clean. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01YSRQzpm4kAWQSaKWD6V9x2
Two things the deployed site got wrong. The embedded map did not update when you reached a page by any link other than a node in the graph itself. Quartz routes in-page navigation client-side and MORPHS the existing DOM rather than replacing it, so the custom element survived with a new data-graph attribute and an already-mounted graph inside — connectedCallback had fired once and nothing fired again. Re-pin the vendored viewer to the build that watches its own attribute and re-renders (strata-g#786). Measured on a real Quartz build, with a positive control: ADR-042 → ADR-005 by an ordinary prose link draws 26 nodes, matching a hard reload of the same URL; the previously vendored viewer leaves 13 on screen beside an attribute that says 26, and leaks a graph instance per hop. And the nodes were labelled with bare codes, which is an address rather than a name. Label by title instead. The obvious refinement — a computed column that truncates with an ellipsis rather than cutting mid-word at the canvas's 60 characters — is accepted by the UI and silently ignored, because strata-g stamps virtual columns after it stamps labels (strata-g#787). That investigation also killed a claim this repository was making: the two layers do not "merge on filename". The merge is by on-screen label, the two layers title a document differently, and 112 of the 454 nodes are one document drawn twice. Documented as it is, with the bug named. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01YSRQzpm4kAWQSaKWD6V9x2
The rebase onto main dropped this branch's two commits whose content merged as #245, and one of them was the ADR the map had a node for. A map naming a document that no longer exists anywhere is worse than a stale one: the node is drawn, labelled, and links to a 404. So it is drawn again, by the recipe in docs/graphs/README.md, against the rebased record and a strata-g built from its current main. 454 nodes / 827 edges -> 456 / 922, and ADR-tmp40zph is replaced by ADR-094, the number concretize gave that work when #245 merged. Every figure in the recipe and the changelog fragment is re-measured rather than adjusted: markdown-link edges 345 -> 313 and `cites` 421 -> 548, which is #245's repair moving DP citations off the assembled document's anchors and onto principle pages, where the record layer sees them as citations. The merge counts are the ones that would have been easiest to assume and they moved least -- 112 documents still render as two nodes, 122 (was 120) fold together -- so the label-merge caveat stands as written. Per-page cost re-measured off a real `luria site` stage: median 7 nodes and 1,062 gzipped bytes a page against a 39 KB whole map, over the 151 pages that carry it. Those two counts, 151 and 79, are luria's own report of the same stage, which is what says the measurement classified the configured graph and the lineage graphs correctly rather than counting one twice. The devlog entry of 2026-09-12 keeps its own numbers. It is a dated observation of what that draw contained, and its claim -- the two layers merge by label, not by filename -- is what the re-measurement confirms. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01YSRQzpm4kAWQSaKWD6V9x2
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01YSRQzpm4kAWQSaKWD6V9x2
dmarx
force-pushed
the
claude/site-graph-config
branch
from
September 17, 2026 09:06
2f99b0f to
a34a6c2
Compare
dmarx
force-pushed
the
claude/principle-pages
branch
from
September 17, 2026 09:06
632e9fd to
0cd23c5
Compare
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.
Rebased onto
main, which shed about half of what this PR used to be. Principle pages, thecitekey and the citation retargeting all merged as #245 and are gone from this diff. What is left is the part that was actually still being workshopped: this record showing a map of itself.The record shows a map of itself
[luria.site] graphnow points atdocs/graphs/record-map.json, drawn in strata-g from this record — 456 nodes, 922 edges, composed from two layers:citesinfluenced_bysuperseded_byThat combination is the point: Quartz's graph knows only the links, the lineage graph knows only the typed edges, and this is both at once, told apart by edge colour.
The two layers do not fully merge, and an earlier revision of this description said they did. strata-g folds nodes together when their on-screen LABELS match, not their filenames. The record layer titles a decision
ADR-001: Four layers of record…; the vault layer reads the bare headingFour layers of record…. So 122 nodes merge — where the two labels coincide by accident, a changelog fragment's title is its timestamp — and 112 documents are drawn twice. The fix would be a computed column stripping theCODE:prefix, which dmarx/strata-g#787 blocks. The docs describe what the file is rather than what it was meant to be.Nothing is filtered. An earlier revision cut to 37 nodes on a
citations >= 5threshold for legibility; that was wrong and is gone. A map that quietly dropped two thirds of the decisions is one you cannot trust — a reader who looks forADR-070, doesn't find it, and concludes it doesn't exist has been misled by the picture. Density is what the viewer's zoom, pan, search and Fit are for;graph_heightis 560px.Each page shows its own neighbourhood
[luria.site] graph_depth— hops from the page's own node, 1 by default. A page is a place, and the useful picture there is where you are, not the whole atlas. Measured off a realluria sitestage: median 7 nodes and 1,062 gzipped bytes a page against a 39 KB whole map, 0.19 MB over the 151 pages that carry it.graph_depth = 0restores the whole map on every page for a project that wants one poster.Two fixes off the deployed site
The map now follows you across an ordinary link. Quartz routes in-page navigation client-side and morphs the existing DOM rather than replacing it, so the
<strata-g-graph>element survived with a newdata-graphattribute and an already-mounted graph inside —connectedCallbackhad fired once and nothing fired again. Clicking a node in the graph worked only because that path is a full page load. Fixed upstream (dmarx/strata-g#786) and re-pinned here.Measured on a real build, with a positive control: ADR-042 → ADR-005 by a prose link draws 26 nodes, matching a hard reload of the same URL, 2 registered instances. The previously vendored viewer leaves 13 on screen — ADR-042's neighbourhood, on ADR-005's page — beside an attribute that says 26, and leaks an instance per hop (registry grows to 5).
Nodes are labelled by title, not by code.
ADR-001,DP-004,ADR-093is an address, not a name; a reader gets nothing from it they didn't have from the URL. The canvas cuts at 60 characters, which is the cost. The obvious refinement — a computed column truncating with an ellipsis — is accepted by the select and ignored by the canvas, because strata-g stamps virtual columns, metrics and transform columns after it stamps labels (dmarx/strata-g#787).What the rebase changed
Two commits were dropped whole, because #245 is where that work merged:
A document-rendered scheme's sources are published as pagesandA citation goes to the cited document's page, and the target is configurable.mainalready carriesdocument_source(),_rebase(), the narrowedpublishable(), thecitekey andretarget_view_citations, so replaying them would have been a conflict with nothing on the other side of it.Three things did not survive that cleanly, and each is its own commit rather than a silent fixup:
mainchanged underneath it.test_a_scheme_rendered_into_one_document_resolves_to_its_anchorrequiredDP-002to resolve todocs/design-principles#dp-…; principles have pages now. Renamed and re-pointed in the commit that introduces it, so the branch never contains a test it then corrects.ADR-tmp40zphwas one of the dropped commits' own ADRs — drawn, labelled, and linking to a 404. So the map is drawn again by the recipe, against the rebased record and a strata-g built from its currentmain, and every figure indocs/graphs/README.mdand the changelog fragment is re-measured rather than adjusted. The interesting move is markdown-link edges 345 → 313 againstcites421 → 548: that is A cited document gets a page, and citations point at it #245's repair taking DP citations off the assembled document's anchors and onto principle pages, where the record layer counts them as citations. The merge counts are the ones it would have been easiest to assume and they moved least — 112 documents still render as two nodes, 122 (was 120) fold together — so the label-merge caveat stands as written.luria repairreports exactly 3 files, which is how you can tell nothing else on the record moved.The devlog entry of 2026-09-12 keeps its original numbers. It is a dated observation of what that draw contained, and its claim — the two layers merge by label, not by filename — is exactly what the re-measurement confirms.
One thing
mainis currently carrying that it cannot useWorth flagging separately, because it is a defect I introduced in #245 rather than anything this PR does: that PR's branch picked up the
[luria.site]config surface forgraph,graph_heightandgraph_depth— theDEFAULTSentries, theSitedataclass fields, the docstring and the_site()reader — without the code that consumes them.mainhas noluria/site_graph.pyandluria/site.pynever imports one, so a project settinggraph = "…"onmaintoday gets silence. This stack is what makes those keys mean something; merging it closes the gap, andgit log -S graph_depthis the receipt if it is worth its own note.Verification
python -m pytest -q→ 1138 passed, 33 skipped.luria lint→ docs lint clean; its warnings are the three still-Proposed ADRs in this stack and three pre-existingDP-017acknowledgements.The map is a snapshot and still names two temporary ADR codes from this stack.
luria concretizerenumbers those on merge, so it wants one more re-export afterwards — the recipe says so.🤖 Generated with Claude Code
https://claude.ai/code/session_01YSRQzpm4kAWQSaKWD6V9x2