Conversation
This was referenced Sep 12, 2026
dmarx
force-pushed
the
claude/typed-lineage-graph
branch
from
September 13, 2026 03:34
4cc7938 to
c3a7f8c
Compare
dmarx
force-pushed
the
claude/site-graph-config
branch
2 times, most recently
from
September 13, 2026 03:42
03f2859 to
d14bcbb
Compare
dmarx
pushed a commit
that referenced
this pull request
Sep 13, 2026
The source half of this landed as the docs-generate bot's own `docs: repair sources` commits on #242 and #243, where those three documents actually live -- this branch had them only because the rebase carried them up. What is left is the generated side: the decision index, the tag and status pages, the devlog books, the reports, and the README's two badge counts (needs decision 3 -> 5, cited-not-in-force 0 -> 3, both counting this stack's still-Proposed ADRs). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01YSRQzpm4kAWQSaKWD6V9x2
dmarx
force-pushed
the
claude/typed-lineage-graph
branch
from
September 13, 2026 04:03
679a6a4 to
819ea9f
Compare
dmarx
force-pushed
the
claude/site-graph-config
branch
from
September 13, 2026 04:03
d14bcbb to
a4952b7
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/typed-lineage-graph
branch
from
September 13, 2026 09:11
819ea9f to
4ed3f6e
Compare
dmarx
force-pushed
the
claude/site-graph-config
branch
from
September 13, 2026 09:11
a4952b7 to
b700c3d
Compare
dmarx
force-pushed
the
claude/typed-lineage-graph
branch
from
September 14, 2026 09:12
4ed3f6e to
9930327
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/typed-lineage-graph
branch
from
September 15, 2026 09:04
9930327 to
6e38ec0
Compare
Both graphs a luria site can draw are computed: Quartz's page-link neighbourhood, and the typed-edge lineage graph. Neither is a picture anybody drew, so a project that knows its own shape had no way to say so. [luria.site] graph points at a strata-g `Canvas — graph data (JSON)` export. Set, that one curated picture replaces Component.Graph on every page, where Quartz's local graph was — the swap is positional as well as functional. Unset, nothing changes. Replacing is right here and was wrong for the lineage graph, for one reason. The objection there was measured density: 47% of scheme documents have any typed edge, so most pages would have got an empty box. A configured graph is the same picture everywhere — no page it is empty on, so no page the swap makes worse. And two graphs above every document's first paragraph is not a thing anyone chooses. The file is validated at build time and the error names which way it is wrong: missing, not JSON, not a graph, a node with no position. A site that builds and then shows an empty box has told the author nothing. Two failure modes the tests caught before a build did. The viewer asset was written only when the LINEAGE count was non-zero, so a project with a configured graph and no typed edges got an element and no script to mount it. And `graph` set without a `base_url` did nothing, silently — the viewer is served from the site root. Both are now in the staging report. A node whose URL the viewer will not follow is reported too, rather than rejected: a graph whose nodes are not links is a fine picture; one that looks clickable and silently is not, is not. tests/fixtures/strata_g_export.json came out of strata-g's real export dialog rather than being written here to match. The contract between the two projects is a file format, and a fixture that only matches this module's idea of it would pass forever while the two drifted. Verified against a real build: luria site → Quartz v4.5.2 → the page carries the configured map and the page's lineage graph, Component.Graph is gone from the layout, the map sits above the document's heading, and a click on a spoke requested docs/decisions/README. No page errors. NOT enabled on this record. The key is documented and tested; which graph luria's own site shows is a picture somebody has to draw, and inventing one would be deciding what the project's front door looks like on every page. 1112 passed, 33 skipped. luria lint clean. 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 15, 2026 09:12
482db1f to
54073e3
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.
Summary
Both graphs a luria site can draw are computed: Quartz's page-link neighbourhood, and the typed-edge lineage graph from #242. Neither is a picture anybody drew, so a project that knows its own shape had no way to say so.
Set, that one curated picture replaces Quartz's own graph on every page, where its local graph was — the swap is positional as well as functional, so a reader who knew where to look still finds it there. Unset, nothing changes.
The file comes from strata-g's
Canvas — graph data (JSON)export (dmarx/strata-g#783): design the graph in that app, export, point the key at it.Why replacing is right here, having argued the opposite in #242
The objection to swapping Quartz's graph for the lineage graph was measured density: 47% of scheme documents have any typed edge, so most pages would have got a box with nothing in it.
A configured graph is the same picture everywhere. There is no page it is empty on, so there is no page the swap makes worse. And two graphs stacked above every document's first paragraph is not a thing anyone chooses deliberately. The lineage graph still appears — at the foot, where it is a place to go next rather than a toll.
Failing usefully
A site that builds and then shows an empty box has told the author nothing (DP-1), so every way of getting this wrong is named at build time:
SystemExit, naming the export that produces oneSystemExit, saying whichgraphset with nobase_urlThe last two are reports rather than errors on purpose. A graph whose nodes are not links is a perfectly good picture; a node that looks clickable and silently is not, is not.
Two of these were bugs the tests found before a build did. The viewer asset was written only when the lineage count was non-zero, so a project with a configured graph and no typed edges anywhere got an element and no script to mount it. And
graphwithoutbase_urldid nothing at all, in silence.What the config overhaul changed
#257 landed between this PR being written and this push. Three things moved, and the middle one is the interesting one:
The swap is now a key, not a splice. Under Quartz 4 this PR removed a
Component.Graph({…})block from a generatedquartz.layout.tsby leaving a substitution empty — luria wrote TSX for the sole purpose of moving one component. Quartz 5 puts layout on each plugin, so the whole of that is:with
graph_enabledset to"false"when the project configured its own. The overhaul made this PR smaller and clearer; nothing about the behaviour changed.The tests parse the config instead of matching substrings. They asserted
"Component.Graph({" not in layout. They now readquartz.config.yamland assertenabled is False— which is stricter, because a substring check passes on a commented-out block.The fixture had to stop concatenating.
configure()appended a second[luria.site]table to the TOML text, which TOML merges. YAML mappings do not: pastingsite:onto the end either duplicates the key or silently replaces what the base config put there. It now parses, sets, and re-dumps.Verification
A real export is the fixture.
tests/fixtures/strata_g_export.jsoncame out of strata-g's actual export dialog, driven through its real UI. The contract between the two projects is a file format, and a fixture written here to match this module's idea of it would pass forever while the two drifted apart. One test does nothing but feed it to the loader.The swap is checked in both directions on a real build, not only in fixtures — a reading of
enabled: falsemeans nothing unless the same build yieldstruewhen the key is absent:luria.yamlsite.graphsetenabled: falsesite.graphremoved, same buildenabled: trueDriven against a real browser build when first written — the lesson from #242, where local verification skipped the pipeline the bugs were in: two graphs mounted (the configured map and the page's lineage graph, 7 nodes / 6 edges each), the map above the document's
#heading where Quartz's was, a click on a spoke issuing a request fordocs/decisions/README, no page errors.Measured rather than guessed: the panel scrolls at the default height. At 320px the side panel wants 198px and gets 143px — the stacked layout caps it at 45%. Nothing is lost (
overflow-y: auto), and raising the default would cost every page the height to save one scroll.graph_heightis the dial.python -m pytest -q→ 1313 passed, 33 skipped.luria lintdocs-clean.Not enabled on this record
The key is documented and tested, but which graph luria's own site shows is a picture somebody has to draw. I built one to verify the pipeline and then took it back out — inventing one would be deciding what the project's front door looks like on every page. #244, stacked on this, is where this record actually turns it on.
🤖 Generated with Claude Code
https://claude.ai/code/session_01YSRQzpm4kAWQSaKWD6V9x2