CONTENT-WP-0004 keeps outgoing and incoming labels apart, limits the graph to two hops, and stores focus and detail in the URL. Assistant: grok Assistant-Session: 01a1531b-6698-7732-8587-f28ea604bcdf
59 lines
4.4 KiB
Markdown
59 lines
4.4 KiB
Markdown
# CONTENT-WP-0004 implementation notes
|
||
|
||
Date: 2026-10-19
|
||
|
||
Hop bound: 2 (`HOP_BOUND` in `ui/lib/graph.ts`). A requested distance above 2 is clamped. Neighborhood walks are undirected. Each edge keeps its stored `from`, `to`, predicate, and id.
|
||
|
||
Journey fields did not require a schema bump. Manifest and snapshot 0.1 still set `additionalProperties: false` at the document root, and entity `properties` is already an open object. Collections, related ids, reading paths, glossary text, and link previews live there. Today's fixtures still validate.
|
||
|
||
## T01 — outgoing and incoming blocks
|
||
|
||
`partitionIncident` places every relation that touches an entity in exactly one block. Outgoing wording is the manifest forward label. Incoming wording is the inverse label. A self-loop is outgoing. `EntityDetail` renders the two blocks separately. When a caller lists only part of the incident set, `relationRemainder` is shown as “N more relations are not listed.”
|
||
|
||
Systems-thinking Feedback uses forward “Represented by” on `represented-by`. The incoming `models` edge uses “Modeled by”, which is not the forward string “Models”.
|
||
|
||
## T02 and T05 — bounded graph
|
||
|
||
`selectNeighborhood` returns the focus plus nodes within the hop bound. Cycles stop because each node is visited once. Parallel edges stay as separate adjacency records (`id`, `predicate`, `from`, `to`, `direction: "out"`). Both parents of a node stay. A node with no edges remains in the graph model and can be focused. The route is `/{dataspace}/graph?focus=<entity id>&detail=<entity id>&hops=1`. Hop 2 omits `hops`. The page shows the excluded-relation count.
|
||
|
||
## T03 — collections, related objects, reading paths
|
||
|
||
A declared `properties.collection` lists member links. `properties.related` lists related objects. `properties.readingPath` is rendered in that order. The crumb for the open entity is the current step. Each earlier crumb is a link to that step.
|
||
|
||
Feedback declares the collection “Ways to draw feedback”, a related link to Emergence, and the path System boundary → Feedback → Causal loop diagram.
|
||
|
||
## T04 — glossary and previews
|
||
|
||
`RecordLink` shows a glossary tooltip only when the target has `properties.glossary`, and a preview only when `properties.preview` has both a title and a summary. Causal loop diagram has both. Stock and flow model has neither: its link still resolves, and the page does not render a tooltip or preview for it. System boundary has no journey properties and still renders.
|
||
|
||
## T06 — nothing incident is silent
|
||
|
||
The Feedback page lists every incident relation id from the snapshot in exactly one block. The graph page prints the count of relations outside the neighborhood.
|
||
|
||
## T07 — focus and detail in the URL
|
||
|
||
`GraphExplorer` reads and writes `focus` and `detail` through the same history helper the page uses in the browser. Reload passes the query back in as `initialSearch`. Back and forward restore the previous focus and detail. Covered in `ui/components/GraphExplorer.history.test.tsx`.
|
||
|
||
## T08 — synthetic fixture
|
||
|
||
`ui/fixtures/large-graph.json` is a chain `n0`–`n8` (8 edges) plus an isolated node `solo`. It is a test fixture, not a published dataspace, so `validate_fixtures.py` still checks only the two example dataspaces.
|
||
|
||
From `n0` at hop bound 2, the neighborhood is `n0`, `n1`, and `n2`. `n8` is outside. `excludedCount` is 6, equal to the edges that do not have both ends inside that neighborhood. Focusing `solo` returns that node and excludes all 8 edges.
|
||
|
||
## Checks
|
||
|
||
Durable tests:
|
||
|
||
- `ui/lib/graph.test.ts`
|
||
- `ui/components/EntityDetail.test.tsx`
|
||
- `ui/components/GraphExplorer.history.test.tsx`
|
||
|
||
Captured on 2026-10-19 under `/tmp/grok-goal-aedf5fe6975e/implementer/`:
|
||
|
||
- `ui-test-1.txt` and `ui-test-2.txt`: `npm test` in `ui/`, 11 files, 32 tests, both exit 0.
|
||
- `typecheck.txt`: `npm run typecheck` in `ui/`, exit 0.
|
||
- `fixtures.txt`: `python3 scripts/validate_fixtures.py`, `python3 -m unittest tests.test_contract tests.test_ingest`, and `python3 scripts/check_ui_boundary.py`, exit 0.
|
||
- `launch-1.html` and `launch-2.html`: HTTP 200 for `/systems-thinking/graph?focus=urn:ce:systems-thinking:concept:feedback`. Both bodies contain “Represented by” and “Modeled by”.
|
||
- `graph.png`: headless Chromium loaded that URL with no page error. Focusing Causal loop diagram changed the neighborhood and the `focus` query. The screenshot is not blank.
|
||
|
||
No R6 deviation. The safeguard is the hop bound of 2, not a graph database or a draw-everything view.
|