Concept map: dependency diagram + descendants table for all definitions and results (#872)#873
Concept map: dependency diagram + descendants table for all definitions and results (#872)#873github-actions[bot] wants to merge 24 commits into
Conversation
|
Claude finished @d-morrison's task in 2m 25s —— View job Code Review: PR #873 — Relationship Diagram for Definitions & ResultsStatus: Review complete
SummaryThis PR is a draft stub with no implementation — the branch has 0 changed files relative to Issue #872 RequirementsThe feature asks for:
Scale of the ProblemAfter scanning the repository:
Most-referenced items:
Existing Conventions to FollowThe repo already has small-scale relationship diagrams (e.g., For a global diagram, the appropriate tools would be:
The existing What a Correct Implementation NeedsStep 1 — Extraction script (
Step 2 — Diagram generation (new
Step 3 — Table:
Step 4 — Title audit:
Issues With Current State
RecommendationThis is a complex, multi-step feature that requires:
The draft PR in its current empty state should remain a draft until at minimum the extraction script and a proof-of-concept diagram with a small subset of nodes (e.g., just the probability chapter) are committed. That would allow meaningful review of the approach before investing in the full 441-node graph. |
|
Claude Code CLI (local session) is working on this — paws off until I'm done. |
New appendix `chapters/concept-map.qmd` visualizes how every definition and result in the notes depends on the others: - a color-by-type dependency diagram, with node size proportional to the number of descendants so the most foundational results stand out, and - a table listing each result's direct and indirect descendants (live `@ref` cross-reference links), sorted by number of direct descendants. The graph is built by `data-raw/callout-graph.R`, which scans the `.qmd` sources and saves the result to `inst/extdata/callout-graph.rds`. The appendix reads that saved artifact, so the scan does not re-run on every render — re-run the script when divs are added, removed, or re-titled. References are attributed to the enclosing callout, or to the callout an immediately-following proof/solution div belongs to; references that aren't inside a result (plain prose) don't create edges. Stacked on the title-audit PR (#875), which gives every node a concise label. Registered as the final appendix in the book and website configs. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Co-authored-by: d-morrison <2474437+d-morrison@users.noreply.github.com>
61b44fc to
758807a
Compare
|
Claude finished @d-morrison's task in 6m 23s —— View job Code Review: PR #873 — Concept Map Appendix
SummarySolid implementation. The stack-based Issues1. Diagram labels show raw IDs, not titles —
|
|
Claude finished @d-morrison's task in 3m 54s —— View job Code Review: PR #873 — Concept Map Appendix
SummaryOne new bug found (website navbar omission). Three findings from the prior review remain unaddressed. The overall implementation is solid — the parser, graph construction, and RDS pattern are correct — but these four issues should be resolved before merging. Issues1. (NEW)
|
|
@claude add the new chapter to the dropdown menu too; make a note to always do this when adding new chapters; maybe add a skill |
|
👀 Picked up by workflow run #26921319634. R/Quarto/renv setup runs first (~3-5 min); Claude itself responds after that. |
|
@claude and make sure to show all the div titles, and use those titles as the nodes (maybe put boxes around them) instead of drawing circles with offset labels |
|
👀 Picked up by workflow run #26921362033. R/Quarto/renv setup runs first (~3-5 min); Claude itself responds after that. |
|
Claude finished @d-morrison's task in 2m 52s —— View job Code Review: PR #873 — Concept Map Appendix
|
| Prior finding | Fixed in |
|---|---|
do.call(rbind, nodes) crash when list is empty (callout-graph.R:127) |
566a09c |
\index{} stripping + str_trim() in extraction script (callout-graph.R:61) |
52e8329, fa7db3f |
\index{} stripping + trimws() at render time (concept-map.qmd:36) |
5f53a29, fa7db3f |
Proof-detection regex false-positive (callout-graph.R:81) |
52e8329 |
Diagram labels show raw IDs not titles (concept-map.qmd) |
e29bc1b |
Min font size below 8pt (concept-map.qmd:122) |
fa7db3f — now range = c(4.0, 8.0) (4.0 mm ≈ 11 pt) |
| Dead whitespace in sugiyama layout | fa7db3f — switched to "stress" layout |
| Direct-descendants column missing from table | 13c85b2 |
| Node label font not scaling by descendant count | 13c85b2 |
| Concept Map missing from website navbar | d1ea852 |
Remaining observations (no blocking issues)
1. subcomponent() deprecated in igraph 2.x — callout-graph.R:191, 199
# line 191
function(v) length(subcomponent(ig, v, mode = "out")) - 1L,
# line 199
reach <- setdiff(subcomponent(ig, v, mode = "out")$name, v)subcomponent() was deprecated in igraph 2.0.0 (locked version is 2.3.0) and emits a deprecation warning each time the script runs. The computation is correct. The modern replacement is bfs(ig, v, unreachable = FALSE)$order for vertex traversal; or subgraph_from_edges() + V() if staying close to the existing pattern. Low urgency — runs offline only.
2. new-chapter.md doesn't mention regenerating callout-graph.rds — .claude/commands/new-chapter.md
Step 2 now correctly covers adding to the website navbar, but doesn't mention that adding callout divs in a new chapter requires re-running Rscript data-raw/callout-graph.R. The regeneration reminder exists in concept-map.qmd prose, but the workflow command is where a contributor (or @claude) would look when scaffolding a new chapter.
Suggested addition to step 2 in new-chapter.md:
If the chapter contains `def`/`thm`/`lem`/`cor`/`prp` callout divs, re-run
`Rscript data-raw/callout-graph.R` to refresh `inst/extdata/callout-graph.rds`.
3. Double-stripping of \index{} at render time — concept-map.qmd:36
cg$nodes$title <- trimws(gsub("\\\\index\\{[^}]*\\}", "", cg$nodes$title))Since the extraction script (callout-graph.R:61) now strips \index{} before saving to the RDS, this render-time strip is redundant. It's harmless — graceful fallback for any RDS file built before the fix — but can be removed once the RDS is regenerated.
What looks good overall
graphlayouts(needed forlayout = "stress") is confirmed present inrenv.lock✓- Stress layout with
geom_label_repel(max.overlaps = Inf, force = 3)is the right approach for even distribution without overlap ✓ scale_size_continuous(range = c(4.0, 8.0))— minimum 4.0 mm ≈ 11 pt, well above the 8 pt floor ✓- HTML/revealjs-only figure with
unless-formatblocks; separatewhen-formatfallback for PDF and docx ✓ concept-map.qmdplaced in appendices in both_quarto-book.ymland_quarto-website.ymlnavbar ✓new-chapter.mdstep 2 now reminds about navbar additions ✓- Table columns: Result (title), Type, Direct descendants, Total descendants — clean and no unresolved
@reflinks ✓ edgesempty-list guard at line 132-133 ✓;nodesguard at line 127-130 ✓set.seed(204)beforecreate_layout()+seed = 204ingeom_label_repelboth in place ✓
|
@claude there's still a ton of blank space; spread out the nodes |
|
👀 Picked up by workflow run #27191772220. R/Quarto/renv setup runs first (~3-5 min); Claude itself responds after that. |
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
Claude finished @d-morrison's task in 3m 1s —— View job Code Review: PR #873 — Concept Map Appendix
|
| User request / Prior finding | Fixed in |
|---|---|
| Dead whitespace / spread nodes | e049fb2 — FR layout + axis normalisation |
| All four prior-round blocking bugs | ✓ committed earlier |
What Looks Good
- FR layout + axis normalisation is a pragmatic solution: FR's global repulsion spreads isolated clusters, and the normalisation eliminates margin whitespace.
niter = 2000gives better convergence than the default 500. nodesempty-list guard at lines 127-130 ✓;edgesguard at lines 132-133 ✓- Proof-detection uses
\\b(proof|solution)\\bwith word boundaries ✓ \index{}stripped +str_trim()applied at extraction time ✓_quarto-website.yml: chapter inrender:list and Appendices navbar ✓_quarto-book.yml: chapter in appendices list ✓new-chapter.mdstep 2 navbar reminder ✓- HTML/revealjs-only figure via nested
unless-formatblocks; separate fallback prose for PDF and docx ✓ - Count-only descendants table (no unresolved
@reflinks) ✓ set.seed(204)beforecreate_layout()+seed = 204ingeom_label_repel✓
|
@claude address reviews and make font size bigger |
|
👀 Picked up by workflow run #27786501793. R/Quarto/renv setup runs first (~3-5 min); Claude itself responds after that. |
Replace the two subcomponent() calls (deprecated in igraph 2.x) with bfs(..., mode = "out", unreachable = FALSE)$order equivalents. No change in computed results; removes deprecation warnings when the script runs. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- norm_axis: guard against diff(range(x)) == 0 (all nodes collapse to the same coordinate in a sparse graph) to prevent silent NaN positions and an empty figure. - scale_size_continuous: widen font-size range from c(4.0, 8.0) to c(8.0, 16.0) to make node labels more readable. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
When a new chapter contains def/thm/lem/cor/prp callout divs, contributors need to re-run Rscript data-raw/callout-graph.R to keep the concept map current. Add this as an explicit step 5 in the new-chapter skill. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The committed callout-graph.rds was stale: def-expectation had acquired
\index{} commands in its heading after the last regeneration, and the
dependency graph had grown (new content merged from main). Re-run
data-raw/callout-graph.R to refresh it (434 results, 115 links). With the
.rds back in sync, the extraction script already strips \index{} from
titles, so the duplicate render-time strip in concept-map.qmd is redundant
and removed.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011CqGbHzLqKVGnbEpLEdadG
|
Addressed all three findings from the latest review (
Checks: @claude please re-review. Generated by Claude Code |
|
👀 Picked up by workflow run #27813761617. R/Quarto/renv setup runs first (~3-5 min); Claude itself responds after that. |
|
Claude finished @d-morrison's task in 3m 38s —— View job Code Review: PR #873 — Concept Map Appendix
|
| Finding | Commit | Confirmed |
|---|---|---|
subcomponent() deprecated → replaced with bfs() |
68e1149 |
callout-graph.R:192,199 — bfs(ig, v, mode = "out", unreachable = FALSE)$order ✓ |
new-chapter.md step 5: re-run callout-graph.R |
cb82496 |
git diff origin/main...HEAD confirms step 5 is in committed state ✓ |
Redundant render-time \index{} strip removed |
9a75c85 |
concept-map.qmd:35 — only readRDS(); no post-load stripping ✓ |
All Prior Blocking Issues — Resolved ✓
| Finding | Fixed in |
|---|---|
do.call(rbind, nodes) crash when list empty |
566a09c — callout-graph.R:127-130 ✓ |
Proof-detection regex (proof|solution) false-positive |
52e8329 — word boundaries \\b(proof|solution)\\b ✓ |
\index{} in extracted titles + str_trim() |
52e8329, fa7db3f — callout-graph.R:61 ✓ |
| Diagram labels showing raw IDs not titles | e29bc1b — geom_label_repel(aes(label = title, ...)) ✓ |
norm_axis division-by-zero on degenerate layout |
489a72b — concept-map.qmd:90-94 guard ✓ |
| Website navbar missing Concept Map entry | d1ea852 — _quarto-website.yml:127-128 ✓ |
| Font size below 8pt | fa7db3f, 489a72b — range = c(8.0, 16.0) (8mm ≈ 22.7pt min) ✓ |
| Direct descendants column in table | 13c85b2 — concept-map.qmd:176 ✓ |
new-chapter.md navbar reminder |
dd97e4a — step 2 expanded ✓ |
Remaining Observations (no action required)
distances() for direct neighbours — callout-graph.R:198
direct <- setdiff(names(which(distances(ig, v, mode = "out")[1, ] == 1)), v)distances() computes the full shortest-path matrix from v to all vertices, then filters to distance 1. neighbors(ig, v, mode = "out") would give the same result in a single pass. No practical impact since this runs offline; noted for completeness.
Independent axis normalisation preserves no aspect ratio — concept-map.qmd:95-96
Normalising x and y independently (each to [-1, 1]) stretches whichever axis was naturally compressed in the FR output. This is the same visual-judgement observation from the prior round; the current layout trades aspect-ratio fidelity for full canvas use. Fine as-is.
What Looks Good Overall
callout-graph.Rparser: stack-based, handles 4-colon fences and nested non-callout divs ✓- Edge direction
from = referenced,to = referencing→ outgoing edges reach descendants ✓ bfs()descendant counting at lines 192, 199 — correct mode and unreachable-exclusion ✓edgesguard atcallout-graph.R:132-133;nodesguard at127-130✓concept-map.qmdplaced in both_quarto-book.ymlappendices and_quarto-website.ymlnavbar and render list ✓- HTML/revealjs-only figure via nested
unless-formatblocks; PDF and docx fallback prose ✓ - Count-only descendants table — no unresolved
@reflinks ✓ set.seed(204)beforecreate_layout()+seed = 204ingeom_label_repel✓\index{}stripped at extraction time incallout-graph.R:61; redundant render-time strip correctly removed ✓- All three packages (
igraph,ggraph,ggrepel) confirmed present inrenv.lock✓
The PR is ready to merge.
|
Working tree is clean and no additional Code Review: PR #873 — Concept Map AppendixRe-review of the three addressed findings from the triggering comment — all confirmed resolved. Verified
Everything else checked and still good
The two non-blocking observations from prior rounds ( The PR is ready to merge. — posted by @claude post-step from workflow run |
Built to branch |

Stacked PR for #872 (base:
claude/issue-872-divs→ PR #875).What this adds
A new appendix,
chapters/concept-map.qmd, that visualizes how every definition and result in the notes depends on the others:@refcross-reference links, sorted by number of direct descendants.How it works (saved artifact, not re-scanned each render)
data-raw/callout-graph.Rscans the.qmdsources fordef/thm/lem/cor/prpcallouts and the@type-idreferences inside them, computes the dependency graph + descendant lists, and saves it toinst/extdata/callout-graph.rds..rds(viahere::here(...)) rather than re-scanning on every render. Re-runRscript data-raw/callout-graph.Rwhenever divs are added, removed, or re-titled.Current snapshot: 433 results, 88 dependency links, 65 results with ≥1 descendant; top hub
thm-prob-to-odds(6 direct / 20 total descendants).Edge attribution
A reference becomes an edge if it sits inside a callout's statement, or inside a
proof/solutiondiv that immediately follows a callout (only blank lines /---/ slidebreaks between). References in plain prose don't create edges. This "immediately follows" rule was added after testing the approach in theqwttemplate repo, where a proof in a separate section was otherwise mis-attributed to the wrong theorem.Checks
quarto render chapters/concept-map.qmd --to html✅ — figure + 66-row table buildlintr✅ — 0 findings ondata-raw/callout-graph.Randchapters/concept-map.qmdspelling::spell_check_package()✅ — clean@reflinks in the table point to results in other chapters, so they show as unresolved when rendering this chapter in isolation (the single-chapter render CLAUDE.md prescribes). They resolve in the full book/website build, which shares one cross-reference namespace — verified that rme's native theorem crossrefs resolve (e.g.probability.htmlhas zero unresolved refs).🤖 Generated with Claude Code