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
4.4 KiB
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.tsui/components/EntityDetail.test.tsxui/components/GraphExplorer.history.test.tsx
Captured on 2026-10-19 under /tmp/grok-goal-aedf5fe6975e/implementer/:
ui-test-1.txtandui-test-2.txt:npm testinui/, 11 files, 32 tests, both exit 0.typecheck.txt:npm run typecheckinui/, exit 0.fixtures.txt:python3 scripts/validate_fixtures.py,python3 -m unittest tests.test_contract tests.test_ingest, andpython3 scripts/check_ui_boundary.py, exit 0.launch-1.htmlandlaunch-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 thefocusquery. 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.