diff --git a/okf/src/reference_agent/viewer/generator.py b/okf/src/reference_agent/viewer/generator.py index 3e342d98..337277a0 100644 --- a/okf/src/reference_agent/viewer/generator.py +++ b/okf/src/reference_agent/viewer/generator.py @@ -2,6 +2,7 @@ import json import re +from urllib.parse import unquote from dataclasses import dataclass, field from pathlib import Path from typing import Any @@ -70,7 +71,7 @@ def _extract_links(body: str, doc_dir: Path, bundle_root: Path) -> list[str]: seen: set[str] = set() bundle_root_resolved = bundle_root.resolve() for m in _LINK_RE.finditer(body): - target = m.group(1) + target = unquote(m.group(1)) if "://" in target or target.startswith("/"): continue try: diff --git a/okf/tests/test_viewer.py b/okf/tests/test_viewer.py index 47e6add4..e9c6293b 100644 --- a/okf/tests/test_viewer.py +++ b/okf/tests/test_viewer.py @@ -187,3 +187,36 @@ def test_v02_signals_appear_in_graph_payload(tmp_path: Path): def test_raises_when_bundle_missing(tmp_path: Path): with pytest.raises(FileNotFoundError): generate_visualization(tmp_path / "nope", tmp_path / "viz.html") + +def test_percent_encoded_links_produce_edges(tmp_path: Path): + bundle = tmp_path / "bundle" + _write( + bundle / "metrics" / "gross margin.md", + """ + --- + type: Reference + title: Gross Margin + description: Gross margin metric. + generated: {by: 'reference_agent/gemini', at: '2026-05-28T00:00:00+00:00'} + --- + The gross margin metric. + """, + ) + # links using %20 (percent-encoded space) — the bug case + _write( + bundle / "tables" / "orders.md", + """ + --- + type: BigQuery Table + title: Orders + description: Orders table. + generated: {by: 'reference_agent/gemini', at: '2026-05-28T00:00:00+00:00'} + --- + See [gross margin](../metrics/gross%20margin.md). + """, + ) + out = tmp_path / "viz.html" + generate_visualization(bundle, out) + data = _extract_bundle_data(out.read_text(encoding="utf-8")) + pairs = {(e["data"]["source"], e["data"]["target"]) for e in data["edges"]} + assert ("tables/orders", "metrics/gross margin") in pairs \ No newline at end of file