generated from coulomb/repo-seed
Document graph explorer adapter boundary
This commit is contained in:
@@ -31,6 +31,19 @@ views are stored in browser `localStorage`, URL query parameters carry normal
|
||||
filter state, and copied state URLs include a state blob so manual overrides can
|
||||
be shared without a profile service.
|
||||
|
||||
The refined rule panel is also browser-local. Rules target either nodes or
|
||||
edges, optionally narrow by type and by attributes present on the currently
|
||||
available elements, and then apply one of five modifiers:
|
||||
|
||||
- `show`, `hide`, and `blur` are visibility states.
|
||||
- `highlight` keeps an element visible and adds visual emphasis.
|
||||
- `remove` hides matching elements and excludes them from the next layout run.
|
||||
|
||||
Rules are applied top to bottom. Later matching rules refine earlier matching
|
||||
rules. Manual overrides win after rules except for `remove`, which is treated as
|
||||
stronger because it changes the layout membership. Edges connected to hidden
|
||||
nodes are hidden; edges connected to removed nodes are removed.
|
||||
|
||||
## Refresh
|
||||
|
||||
Refresh this checkout into the running registry:
|
||||
@@ -69,8 +82,8 @@ The automated coverage for this slice lives in `tests/test_graph_explorer.py`:
|
||||
- registered-only repo projection
|
||||
- `railiance-fabric export --format graph-explorer`
|
||||
- registry API routes for manifest, payload, and UI
|
||||
- static UI wiring for profile controls, orientation text, and shared-state
|
||||
support
|
||||
- static UI wiring for profile controls, rule controls, orientation text, and
|
||||
shared-state support
|
||||
|
||||
Manual smoke checks for a local registry:
|
||||
|
||||
@@ -108,7 +121,8 @@ The extracted repository should own:
|
||||
|
||||
- `GraphExplorerManifest` and `GraphExplorerPayload` schemas
|
||||
- static graph explorer assets and mount/bootstrap code
|
||||
- display-state evaluation helpers for hosts that want client-side rules
|
||||
- display-state and rule evaluation helpers for hosts that want client-side
|
||||
rules, including `show`, `hide`, `blur`, `highlight`, and `remove`
|
||||
- browser-local profile handling, URL state, copied state blobs, and profile UI
|
||||
- Cytoscape rendering, layouts, hover popups, detail panels, focus modes, and
|
||||
manual override controls
|
||||
@@ -117,11 +131,57 @@ The extracted repository should own:
|
||||
Host repositories should keep:
|
||||
|
||||
- graph projection and domain metadata enrichment
|
||||
- host vocabulary and manifest labels for node types, edge types, rule fields,
|
||||
modes, and orientation terms
|
||||
- host-side profile persistence, when shared/team profiles are required
|
||||
- authentication, authorization, and deployment
|
||||
- domain-specific modes and deep links
|
||||
- registry or analysis service APIs
|
||||
|
||||
## Adapter Readiness Notes
|
||||
|
||||
The refined shell is closer to extraction, but these Fabric-specific assumptions
|
||||
should be made manifest-driven or host-adapted before `graph-explorer-engine`
|
||||
becomes a separate repo:
|
||||
|
||||
- The shell still expects the internal element type field to be named `layer`.
|
||||
User-facing text now says nodes and node types, but the shared contract should
|
||||
either rename this to `nodeType` or declare the field through
|
||||
`manifest.identity`.
|
||||
- Node shapes are hardcoded against Fabric node type ids such as `repository`,
|
||||
`service`, `deployment`, `server`, `capability`, `interface`, `dependency`,
|
||||
`binding`, and `library`.
|
||||
- Rule-builder attributes are derived from a fixed allowlist. Repo-scoping can
|
||||
use the model, but the allowlist should move to manifest filter fields so a
|
||||
host can expose facts, evidence, confidence, freshness, scope, ability, or
|
||||
other domain attributes without changing engine code.
|
||||
- Mode behavior is hardcoded for Fabric's `onboarding-gaps`, `unresolved`,
|
||||
`selected-path`, and `neighborhood` semantics. The reusable engine should
|
||||
either provide generic selectors or let hosts define mode predicates.
|
||||
- The orientation panel still contains Fabric-specific renderers for
|
||||
repositories, services, interfaces, dependencies, and capabilities. This
|
||||
should stay host-owned or become a manifest-provided details adapter.
|
||||
- The default detail rows know about `source`, `target`, `edgeType`, `strength`,
|
||||
deep links, and source references. That is acceptable as a shared baseline,
|
||||
but host-specific row ordering should be manifest-driven.
|
||||
|
||||
The current rule-panel data model is compatible with repo-scoping if repo-scoping
|
||||
maps its graph elements into the same basic shape:
|
||||
|
||||
```json
|
||||
{
|
||||
"target": "node",
|
||||
"type": "fact",
|
||||
"attribute": "reviewState",
|
||||
"value": "candidate",
|
||||
"action": "blur"
|
||||
}
|
||||
```
|
||||
|
||||
For extraction, prefer repo-scoping adapter parity as the next workplan. One
|
||||
more Fabric-side polish pass is still useful for orientation workflows, but it
|
||||
does not need to block proving the second host.
|
||||
|
||||
Suggested public API:
|
||||
|
||||
```ts
|
||||
|
||||
@@ -6,7 +6,7 @@ from typing import Any
|
||||
from urllib.parse import urlparse
|
||||
|
||||
|
||||
DISPLAY_STATES = ("show", "blur", "hide")
|
||||
DISPLAY_STATES = ("show", "blur", "hide", "highlight", "remove")
|
||||
LAYER_ORDER = (
|
||||
"repository",
|
||||
"server",
|
||||
@@ -377,8 +377,13 @@ def fabric_graph_explorer_payload(
|
||||
"rules": [],
|
||||
"manual_overrides": {},
|
||||
"orphaned_overrides": [],
|
||||
"precedence": "later rules override earlier rules; manual overrides win last",
|
||||
"connected_edge_behavior": "edges connected to hidden nodes are hidden",
|
||||
"precedence": (
|
||||
"later rules override earlier rules; remove excludes matching elements "
|
||||
"from layout and wins over manual overrides; otherwise manual overrides win last"
|
||||
),
|
||||
"connected_edge_behavior": (
|
||||
"edges connected to hidden nodes are hidden; edges connected to removed nodes are removed"
|
||||
),
|
||||
},
|
||||
"elements": elements,
|
||||
"hidden_elements": [],
|
||||
|
||||
@@ -136,6 +136,8 @@ properties:
|
||||
- show
|
||||
- blur
|
||||
- hide
|
||||
- highlight
|
||||
- remove
|
||||
fields:
|
||||
type: array
|
||||
items:
|
||||
|
||||
@@ -208,6 +208,8 @@ $defs:
|
||||
- show
|
||||
- blur
|
||||
- hide
|
||||
- highlight
|
||||
- remove
|
||||
profile:
|
||||
type: object
|
||||
additionalProperties: true
|
||||
|
||||
@@ -41,6 +41,7 @@ def test_graph_explorer_manifest_and_payload_validate() -> None:
|
||||
|
||||
assert manifest["profile_persistence"] == "local"
|
||||
assert manifest["shareable_state"]["profile_id"] is True
|
||||
assert set(manifest["filter"]["actions"]) >= {"show", "hide", "blur", "highlight", "remove"}
|
||||
assert {layer["id"] for layer in manifest["layers"]} >= {"server", "deployment"}
|
||||
filter_labels = {field["id"]: field["label"] for field in manifest["filter"]["fields"]}
|
||||
assert filter_labels["layer"] == "Node Type"
|
||||
@@ -68,6 +69,7 @@ def test_graph_explorer_manifest_and_payload_validate() -> None:
|
||||
assert payload["metrics"]["server_node_count"] >= 1
|
||||
assert payload["metrics"]["registered_repo_count"] == 2
|
||||
assert payload["metrics"]["unresolved_count"] == 0
|
||||
assert "removed nodes are removed" in payload["filter"]["connected_edge_behavior"]
|
||||
|
||||
|
||||
def test_cli_exports_graph_explorer_payload(capsys) -> None:
|
||||
@@ -101,7 +103,10 @@ def test_graph_explorer_payload_accepts_repo_scoping_shape() -> None:
|
||||
"manual_overrides": {"feature:1": "show"},
|
||||
},
|
||||
"filter": {
|
||||
"rules": [],
|
||||
"rules": [
|
||||
{"action": "highlight", "match": {"layer": "fact", "reviewState": "candidate"}},
|
||||
{"action": "remove", "match": {"layer": "stale_fact"}},
|
||||
],
|
||||
"manual_overrides": {},
|
||||
"orphaned_overrides": [],
|
||||
},
|
||||
|
||||
@@ -202,7 +202,7 @@ Acceptance notes:
|
||||
|
||||
```task
|
||||
id: RAIL-FAB-WP-0009-T06
|
||||
status: todo
|
||||
status: done
|
||||
priority: medium
|
||||
state_hub_task_id: "934ea4d9-0d36-414d-9ed7-10f39410da8d"
|
||||
```
|
||||
|
||||
Reference in New Issue
Block a user