Skip to content

feat(backend): Mermaid diagrams for chapter index pages - #346

Closed
arozumenko wants to merge 1 commit into
mainfrom
feat/cluster-chapter-index-diagrams
Closed

feat(backend): Mermaid diagrams for chapter index pages#346
arozumenko wants to merge 1 commit into
mainfrom
feat/cluster-chapter-index-diagrams

Conversation

@arozumenko

Copy link
Copy Markdown
Owner

Summary

  • Add three new deterministic diagram methods to DiagramGenerator (no LLM calls): generate_class_diagram (Mermaid classDiagram), generate_data_model_diagram (Mermaid erDiagram), and generate_cluster_context_diagram (Mermaid graph LR with subgraph)
  • WikiContentWriter._inject_cluster_diagrams inserts all three sections into every chapter _index.md after ## Overview and before ## Key Components (or ## Sub-pages when Key Components is absent)
  • 38 new unit tests added to test_diagram_generator.py covering happy paths, edge cases, and error handling

Details

generate_class_diagram(cluster_id)

  • Filters nodes to class-like types (class, interface, struct, enum, trait)
  • Emits <<interface>>, <<enumeration>>, <<abstract>> stereotypes
  • Renders member methods with +/- visibility prefixes
  • Follows intra-cluster inheritance edges with --|>
  • Caps at 8 nodes; prefers is_architectural=1 nodes when over cap
  • Returns "" when fewer than 2 class-like nodes

generate_data_model_diagram(cluster_id)

  • Detects Pydantic BaseModel, @dataclass, SQLAlchemy db.Model/DeclarativeBase, @Entity, GORM tags, etc.
  • Emits Mermaid erDiagram with composition/references relationship edges
  • Caps at 8 model nodes; returns "" when fewer than 2 detected

generate_cluster_context_diagram(cluster_id, cluster_title, all_cluster_ids, cluster_titles)

  • Renders the cluster's own nodes inside a subgraph block
  • Cross-cluster edges become edges to a single external node per neighbouring cluster (not individual members)
  • When all_cluster_ids=[] (first pass), shows intra-cluster structure only

Injection in generate_chapter

  • _inject_cluster_diagrams called after _generate_chapter_index completes
  • Graceful: any storage error returns the original markdown unchanged

Test plan

  • 38 new unit tests: TestGenerateClassDiagram, TestGenerateDataModelDiagram, TestGenerateClusterContextDiagram
  • All 4582 existing unit tests still pass
  • python -m py_compile clean on both changed files

🤖 Generated with Claude Code

Add three new deterministic diagram methods to DiagramGenerator:
- generate_class_diagram: Mermaid classDiagram with stereotypes,
  member visibility, and intra-cluster inheritance edges (cap 8 nodes)
- generate_data_model_diagram: Mermaid erDiagram for Pydantic/SQLAlchemy/
  dataclass models with composition edges (cap 8 nodes)
- generate_cluster_context_diagram: graph LR with a subgraph for the
  cluster's own nodes plus external cluster nodes when cross-cluster
  info is available

WikiContentWriter._inject_cluster_diagrams injects all three sections
into every chapter _index.md after ## Overview, before ## Key Components.

38 new unit tests cover happy paths, edge cases (empty cluster, <2 nodes,
>8 nodes cap, storage errors, abstract detection, visibility prefixes).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings May 22, 2026 06:26

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds deterministic Mermaid diagram generation to the backend wiki writer so chapter index pages can include auto-generated visualizations (without LLM calls) for architecture/context, class structure, and data-model relationships.

Changes:

  • Added three new diagram generators to DiagramGenerator: classDiagram, erDiagram, and a cluster context graph LR with subgraph.
  • Injected generated diagram sections into chapter _index.md during generate_chapter().
  • Expanded unit test coverage for the new diagram generators.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 7 comments.

File Description
backend/app/core/wiki_content_writer/diagram_generator.py Implements the new deterministic Mermaid diagram builders (class/data-model/context) and related helpers.
backend/app/core/wiki_content_writer/writer_agent.py Injects the new diagram sections into chapter index markdown after index generation.
backend/tests/unit/wiki_content_writer/test_diagram_generator.py Adds unit tests for the new diagram generation methods and their edge cases.

Comment on lines +299 to +307
# Collect member nodes (methods, properties, fields) whose parent_symbol
# matches one of the selected class nodes.
class_names: set[str] = set(class_name_to_id)
member_map: dict[str, list[dict]] = {_node_name(n): [] for n in class_nodes}
for n in all_nodes:
if (n.get("symbol_type") or n.get("kind", "")) in _MEMBER_TYPES:
parent = n.get("parent_symbol")
if parent and parent in class_names:
member_map[parent].append(n)
Comment on lines +675 to +679
# Inheritance edges: Child --|> Parent
for src_id, tgt_id in inheritance_edges:
src_name = _safe_id(id_to_name[src_id])
tgt_name = _safe_id(id_to_name[tgt_id])
lines.append(f" {src_name} --|> {tgt_name} : implements")
Comment on lines +436 to +447
# Build a node_id → external cluster_id lookup if cross-cluster info given.
node_to_ext_cluster: dict[str, int] = {}
if all_cluster_ids and cluster_titles:
for ext_cid in all_cluster_ids:
if ext_cid == cluster_id:
continue
try:
ext_nodes = self.storage.get_nodes_by_cluster(ext_cid)
except Exception:
ext_nodes = []
for en in ext_nodes:
node_to_ext_cluster[en["node_id"]] = ext_cid
Comment on lines +729 to +737
# External cluster nodes (one node per neighbouring cluster).
seen_ext: set[int] = set()
for _src_nid, ext_cid in cross_cluster_edges:
if ext_cid not in seen_ext:
seen_ext.add(ext_cid)
ext_title = cluster_titles.get(ext_cid) or f"cluster_{ext_cid}"
ext_safe = _safe_id(ext_title[:_MAX_LABEL_CHARS])
ext_label = _sanitize_label(ext_title[:_MAX_LABEL_CHARS])
lines.append(f' {ext_safe}["{ext_label}"]')
Comment on lines +855 to +859
"""Inject Mermaid diagrams into a chapter _index.md after ## Overview.

Inserts Architecture / Class Structure / Data Model sections before
``## Key Components`` (or ``## Sub-pages`` when Key Components is
absent). Returns the original markdown unchanged on any error.
Comment on lines +836 to +839
# ── 4. Inject cluster diagrams into the chapter index ─────────
chapter_index_md = self._inject_cluster_diagrams(
chapter_index_md, chapter_spec.cluster_id, chapter_spec.chapter_title
)
nodes_c2 = [_class_node("n_ext", "WikiService", "class")]

# Storage returns different nodes for different cluster IDs
call_count = {"count": 0}
@arozumenko

Copy link
Copy Markdown
Owner Author

Superseded by #347 which contains a corrected implementation. Closing to keep a single PR per feature.

@arozumenko arozumenko closed this May 22, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants