GoogleCloudPlatform / GoogleCloudPlatform/open-knowledge-format
Viewer: resolve bundle-relative and file-relative concept links consistently
- Dominant language
- HTML
- Stars
- 467
- Forks
- 35
- Avg merge
- 9m
- Merged PRs (30d)
- 1
Description
### Problem
The reference viewer handles OKF's two supported internal-link forms inconsistently.
- In `src/reference_agent/viewer/generator.py`, `_extract_links()` skips every target beginning with `/`. As a result, the recommended bundle-relative form, such as `[Orders](/tables/orders.md)`, does not create graph edges or backlinks.
- In `src/reference_agent/viewer/static/viz.js`, `rewriteInternalLinks()` rewrites only targets beginning with `/`. File-relative links such as `[Orders](../tables/orders.md)` create graph edges, but clicking them opens a file/external path instead of navigating inside the viewer.
- Links with fragments such as `/tables/orders.md#schema` are not rewritten because the JavaScript currently requires the href to end with `.md`.
This means neither link form has complete behavior across graph construction and in-viewer navigation.
### Why this matters
OKF v0.2 section 6.1 supports both forms and recommends bundle-relative links because they remain stable when documents move. The checked-in Acme Retail bundle already uses bundle-relative links extensively, for example in `bundles/acme_retail/policies/revenue-recognition.md`. Those relationships are therefore missing from its generated graph and "Cited by" lists.
The README also says the viewer draws edges from each cross-link and rewires internal links for navigation.
### Proposed implementation
1. Add a single Python resolver that normalizes both bundle-relative and file-relative Markdown targets to concept IDs.
2. Strip optional fragments for concept resolution while preserving the original href.
3. Reject external URLs, non-Markdown targets, and paths that escape the bundle root.
4. Include a per-concept raw-href-to-concept-ID mapping in the generated bundle payload.
5. Build graph edges and backlinks from those normalized IDs.
6. Have `rewriteInternalLinks()` use the generated mapping instead of implementing a second, partial path resolver.
7. Continue tolerating broken links: retain them in rendered Markdown, but do not create an edge or internal navigation action when the target concept is absent.
### Acceptance criteria
- Bundle-relative and file-relative links both create graph edges and backlinks.
- Clicking either form navigates to the target concept in the self-contained viewer.
- Both forms work with heading fragments.
- External links remain external.
- Paths escaping the bundle root are ignored.
- Broken links remain tolerated as required by the specification.
- Duplicate links produce only one graph edge.
- Tests cover both supported forms, fragments, external links, escaping paths, broken targets, and deduplication.
Contributor guide
Research direction
Start in src/reference_agent/viewer/generator.py at _extract_links() and src/reference_agent/viewer/static/viz.js at rewriteInternalLinks(), then trace how the generated bundle payload represents concepts. Design the shared mapping around the stated resolver rules and add tests for link forms, fragments, external and escaping paths, broken targets, and deduplication. Done means graph edges, backlinks, and in-viewer navigation behave consistently without breaking tolerated links.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- javascript, python
- Domain
- backend, frontend
- Issue type
- Feature
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Clearly specified
- Newbie friendliness
- 58/100