Skip to content

feat(mermaid): human/AI-readable node ids instead of MD5 hashes (#210)#213

Merged
zaebee merged 2 commits into
mainfrom
feat/issue-210-readable-mermaid-ids
Jun 12, 2026
Merged

feat(mermaid): human/AI-readable node ids instead of MD5 hashes (#210)#213
zaebee merged 2 commits into
mainfrom
feat/issue-210-readable-mermaid-ids

Conversation

@zaebee

@zaebee zaebee commented Jun 12, 2026

Copy link
Copy Markdown
Owner

Closes #210.

What

Replaces n_<md5> Mermaid node ids with deterministic readable slugs, so edge lines are matchable back to nodes by eye and by an LLM — no more cross-referencing hashes against the label block.

Before:

n_a62c26d1… -->|CALLS| n_600a3205…

After (real output from cgis impact MermaidCompiler.compile):

subgraph sg_cli["cli.py"]
subgraph sg_mermaid["mermaid.py"]
cli_render_graph                     -->|CALLS| mermaid_MermaidCompiler_compile
mcp_server_render_subgraph           -->|CALLS| mermaid_MermaidCompiler_compile
collector_ContextCollector_graph_sections -->|CALLS| mermaid_MermaidCompiler_compile

Pairs with the just-merged #209: JSON with real FQNs for machine joins, readable Mermaid for humans. Since machines now have the JSON path, the Mermaid ids only need to be human-scannable, not joinable — so readability wins.

How

  • Internal node<file_stem>_<Class>_<method>: the symbol suffix is peeled off the module FQN derived from file_path (exact, since internal FQNs are built from file_path_to_module_fqn); a module/file node → bare stem.
  • Phantom / external / raw_call: endpoints (no module context) → readable FQN-tail slug via _fqn_slug.
  • _IdAllocator guarantees uniqueness: idempotent per key, _2/_3 suffix on collision, deterministic in call order. Threaded through compile / _render_subgraphs / _render_edges; subgraph ids become sg_<stem>.
  • Guards: Mermaid reserved words (end, graph, subgraph, …) and leading digits get an id_ prefix so a method literally named end can't break the diagram.

The scheme (full-path slug) was chosen over a compact initialism because an LLM parses IngestionPipeline_run far better than IP_R (no legend to hold in context).

Scope & notes

  • mermaid.py + test_mermaid.py only. _normalize_id (md5) removed.
  • Labels are unchanged (they already showed name + location).
  • The committed generated diagrams (docs/architecture/diagrams/pipeline_flow.mermaid, README graph) will refresh to the new ids via the autodoc workflow post-merge — not hand-touched, per our generated-docs-are-owned-by-autodoc policy.

Verification

make format && make lint && make type-check && make pytest && make doc-coverage all green — 846 passed, doc-coverage 99.5%, self-drift unchanged (mermaid is display-only). Dogfooded on the self-graph (shown above). New tests cover slug format, module-node stem, collision _2 suffixing, reserved-word/leading-digit guarding, and readable phantom raw_call ids.

🤖 Generated with Claude Code

Replace `n_<md5>` node ids with deterministic readable slugs so edge lines
can be matched back to nodes by eye (and by an LLM) without cross-referencing
the label block. Pairs with #209: JSON for machine joins, readable Mermaid
for humans.

- internal node → `<file_stem>_<Class>_<method>` (symbol suffix peeled off the
  module FQN derived from file_path); module/file node → bare stem
- phantom/external/raw_call endpoints → readable FQN-tail slug (`_fqn_slug`)
- `_IdAllocator` guarantees uniqueness (idempotent per key; `_2`/`_3` suffix on
  collision, deterministic in call order) and threads through compile/subgraphs/
  edges; subgraph ids become `sg_<stem>`
- guards: Mermaid reserved words (`end`, `graph`, …) and leading digits get an
  `id_` prefix so the diagram never breaks
- since #209 ships JSON with real FQNs for machine joins, these ids only need to
  be human-scannable, not joinable — readability wins

Before: `n_a62c26d1… -->|CALLS| n_600a3205…`
After:  `cli_render_graph -->|CALLS| mermaid_MermaidCompiler_compile`

`_normalize_id` (md5) removed; tests updated to assert the slug format,
collision suffixing, and reserved-word guarding. 846 passed, self-drift
unchanged (mermaid is display-only).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@zaebee zaebee self-assigned this Jun 12, 2026

@gemini-code-assist gemini-code-assist Bot 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.

Code Review

This pull request replaces deterministic MD5 hashing for Mermaid node IDs with human-readable slug IDs based on file stems, classes, and methods, and introduces an _IdAllocator to manage unique IDs and handle collisions. Feedback on these changes highlights a potential mismatch between node IDs and module FQNs when custom source roots are configured, as well as a potential IndexError in _guard_token if an empty slug is processed.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment thread src/cgis/query/mermaid.py Outdated
Comment thread src/cgis/query/mermaid.py
…y-slug guard

Address gemini review on PR #213:

- HIGH: when the ingest root differs from the file path's root (e.g. `cgis ingest
  ./src` yields ids `cgis.pipeline.X` while file_path derives `src.cgis.pipeline`),
  the exact-prefix check failed and dropped the `<file_stem>` prefix. `_node_slug`
  now matches the longest module suffix of the path FQN (extracted into
  `_internal_node_slug`), keeping the stem regardless of root. Regression test
  added (red before this fix).
- MEDIUM: `_guard_token` guards against an empty slug before indexing `slug[0]`
  (defensive — all current callers pass sanitized non-empty tokens).

847 passed, mypy strict + ruff clean.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@zaebee

zaebee commented Jun 12, 2026

Copy link
Copy Markdown
Owner Author

Thanks @gemini-code-assist — both addressed in f8e55dd:

  • HIGH source-root mismatch — real catch, and one I hit myself while dogfooding (cgis ingest ./src gives ids like cgis.pipeline.X while the file path derives src.cgis.pipeline). The exact-prefix check fell back to _fqn_slug and dropped the <file_stem>. Adopted the longest-suffix match (extracted into _internal_node_slug, longest-first so it can't match a too-short suffix) — the stem survives any root offset. Added a regression test that's red without the fix.
  • MEDIUM empty-slug guard — added slug and (...) in _guard_token. Not a live bug (every caller feeds _sanitize_token output, which is never empty), but it's correct to make the helper safe standalone.

847 passed, mypy strict + ruff + Sonar green.

@gemini-code-assist

Copy link
Copy Markdown
Contributor

Thanks for the update, @zaebee. The implementation of _internal_node_slug using a longest-suffix match is a robust way to handle the source-root mismatch, and adding the regression test ensures this behavior remains stable. The _guard_token logic also provides a clean, safe way to handle Mermaid keywords and digits. Great work getting the test suite and static analysis passing.

@sonarqubecloud

Copy link
Copy Markdown

@zaebee

zaebee commented Jun 12, 2026

Copy link
Copy Markdown
Owner Author

/gemini review

@gemini-code-assist gemini-code-assist Bot 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.

Code Review

This pull request replaces the MD5-hash-based ID generation for Mermaid diagrams with a human- and AI-readable slug-based ID system. It introduces several helper functions for token sanitization, guarding reserved words, and generating readable slugs based on file stems, classes, and methods. Additionally, an _IdAllocator class is introduced to handle ID allocation and resolve collisions deterministically. Unit tests have been updated and expanded to verify the new slug generation, collision handling, and edge cases. There are no review comments, so I have no feedback to provide.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

@zaebee zaebee merged commit 0b5ae7e into main Jun 12, 2026
3 checks passed
@zaebee zaebee deleted the feat/issue-210-readable-mermaid-ids branch June 12, 2026 20:16
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.

mermaid: human/AI-readable node ids instead of MD5 hashes

1 participant