Skip to content

Latest commit

 

History

History
213 lines (139 loc) · 11.7 KB

File metadata and controls

213 lines (139 loc) · 11.7 KB

Graph Model

The graph is built from nodes and edges with structure driven by persisted relationships.

Species

Current taxonomy has exactly 5 species.

Level Species Role React Flow node type
1 flow Ordered sequence container flow
0 view Reusable page/screen view
data-model Data entity/table dataModel
api-endpoint API endpoint apiEndpoint
acceptance A testable promise: What (title), How (metadata.gherkin, one Given/When/Then), Why (metadata.values, Bain elements), with per-platform status in metadata.platformStatuses. Id prefix AC-. acceptance

Config source: lib/config/species.ts

Canvas Visibility (Journey Map)

  • The canvas is the Journey map (vision.md § Core Product, spec/maps.md): it renders flow and view species as React Flow nodes over the full compose closure from the root — views chain the traversal onward, flows render as collapsed, expandable cards.
  • data-model and api-endpoint remain persisted graph species, editable from panels and import/export. They render as standalone cards on the System map (/project/[id]/maps/system); on the Journey map they surface inline on View cards via embedded API actions and in the detail panel's Connections section.
  • Cross-layer edges (calls, displays, queries) draw whenever both endpoints are visible.

Source: components/maps/JourneyMap.tsx, lib/utils/journey-graph.ts, components/graph/nodes/ViewNode.tsx

Library Views

Project library is available at /project/[id]/library with two browsing modes:

  • Gallery: card grid with title, prefixed ID, species/status badges, platforms, and flow playlist preview.
  • Directory: sortable table for id, title, species, status, and used in flow count.

Filtering:

  • Species selection is owned by the sidebar (?species= deep links: all when absent, or one of flow, view, data-model, api-endpoint, acceptance); the in-page bar carries search and the display-mode toggle only.
  • Search matches node title and description text.

Library source:

Acceptances View

  • Acceptances (/project/[id]/acceptances) — the parity matrix: acceptances grouped by the view/flow they cover, one status column per platform, filterable by platform/status/value/anchor/parity-gap. Editing (Gherkin, values, per-platform status) happens in the node detail panel.

Pyramid View

  • Pyramid (/project/[id]/pyramid) — the value-element gauge grid: four Bain tier sections (functional → emotional → life-changing → social impact), each rendering its value elements as cards showing the element's icon + label + per-platform delivery gauge + acceptance count. A platform chip row filters the gauges to a single platform (or all), and each element card links to the Acceptances matrix pre-filtered on that value (?value=<id>).

Composition Model

Root Node

  • project.root_node_id is the explicit canvas anchor when present.
  • If root_node_id is not set, the canvas infers roots from nodes with no incoming composes edge.

Source: components/maps/JourneyMap.tsx, lib/utils/journey-graph.ts, lib/data/types.ts

Playlist Expansion

  • Persisted parent/child links are composes edges.
  • Child ordering is read from node.metadata.playlist.entries.
  • When playlist entries do not reference all compose-edge children, missing children are appended after playlist-derived ordering.

Source: components/maps/JourneyMap.tsx, lib/utils/journey-graph.ts

The canvas walks the compose closure from the anchor (project.root_node_id, or inferred roots when absent): views are always rendered and chain the walk onward; flows are rendered as collapsed cards whose interiors (playlists) render only when expanded. Flows start collapsed, except that the first top-level flow (a flow reached without passing through another flow) auto-expands on initial load. Top-level expansion is accordion-style: opening one top-level flow collapses any other top-level flow already open.

Expanded flow children follow a strict alternating drill layout:

  • Root children are rendered horizontally below the root.
  • Level 2 children are rendered vertically below each level 1 node.
  • Level 3 children are rendered horizontally below each level 2 node.
  • The pattern continues alternating by depth.
  • Vertical drill segments always use top/bottom handles for both flow and view nodes.

Layout is computed by elkjs (Eclipse Layout Kernel, layered algorithm). The page builds a flat list of nodes and compose edges with position: {x:0, y:0}, then an async useEffect calls computeElkLayout() which runs the ELK layered algorithm and returns positioned nodes.

Layout source: lib/utils/elk-layout.ts

Source: components/maps/JourneyMap.tsx, lib/utils/journey-graph.ts

Node Reuse

  • view and flow nodes are reusable and can appear multiple times across playlists.
  • Reuse is many-to-many: a single node can be referenced by many flow playlists, and one flow playlist can reference many nodes.
  • The source of truth for sequence semantics is the playlist (metadata.playlist.entries), while composes edges provide structural connectivity.
  • The detail panel's where-used UI derives reverse references by scanning all flow playlists.

Source: components/panels/NodeDetailPanel.tsx, lib/utils/where-used.ts, lib/data/types.ts

Playlist Entry Types

flow nodes store ordered playlist data in node.metadata.playlist.entries.

Entry Type Required Fields Notes
view view_id Reference to an existing view node
flow flow_id Reference to an existing flow node (cycle-checked before persist)
condition label, if_true, if_false Two branch lists, each a recursive PlaylistEntry[]
junction label, cases[] Each case has label + entries: PlaylistEntry[]

Editing source: components/panels/PlaylistEditor.tsx, components/panels/PlaylistEntryRow.tsx

Type source: lib/data/types.ts

Status Model

Statuses are configured in:

Rollup behavior:

  • acceptance is the primary carrier of stored per-platform status values (metadata.platformStatuses).
  • view also stores metadata.platformStatuses, but this is now a deprecated fallback: it is authoritative only while no acceptance covers the view (see covers under Edge Types).
  • flow status is computed for display by recursively walking playlist entries and aggregating descendant view platform statuses, including nested sub-flows and branch entries.
  • data-model and api-endpoint use single lifecycle status.

Sources:

Platforms

Platforms are configured in:

Views can target one or more platforms; per-platform notes/statuses are stored in node metadata.

Source:

Edge Types

Edge Type Use
composes Composition hierarchy and ordered flow sequences
calls View/flow to API relationship, or API endpoint to API endpoint (first-party endpoint fanning out to internal/external APIs)
displays View to data-model relationship
queries API to data-model relationship
covers Acceptance to view/flow relationship — anchors a testable promise to the surface(s) it covers

Config source: lib/config/edge-types.ts

Rendering mapping source: lib/utils/journey-graph.ts, lib/utils/system-graph.ts

calls edges between a view and API endpoint are projected into View card UI:

  • API -> View: inbound/read affordance (cloud-download icon)
  • View -> API: outbound/write affordance (cloud-upload icon)

calls edges between two API endpoints (a first-party endpoint fanning out to internal/external APIs) have no view endpoint to project onto, so they surface only on the System map (/project/[id]/maps/system), drawn between the two endpoint cards.

Source: components/maps/JourneyMap.tsx, lib/utils/journey-graph.ts, components/graph/nodes/ViewNode.tsx

covers — acceptance → view | flow. Zero covers edges = product-level acceptance (legal, not an orphan). Stored per-platform status lives on acceptances; a covered view's per-platform status is computed from its covering acceptances, falling back to the view's stored platformStatuses when uncovered (spec §3.4).

Source: packages/schema/src/acceptance.ts (projections; not yet consumed by the app's status rollups — see the Surfaces plan).

Node And Edge Components

Node registration is in:

Current custom registrations:

  • flow -> FlowNode
  • view -> ViewNode
  • dataModel -> DataModelNode
  • apiEndpoint -> ApiEndpointNode

dataModel and apiEndpoint remain registered node types for compatibility, but the current project page renderer does not add those species into visibleNodes.

acceptance nodes and covers edges have no custom Canvas registration yet — they render with generic node/edge components, and the map-kind defaults exclude them (see the dated note under the Taxonomy Update Checklist).

Edge registration is also in components/graph/Canvas.tsx.

Taxonomy Update Checklist

  1. Update config array in lib/config/*.
  2. Update graph builders and rendering filters in lib/utils/journey-graph.ts and lib/utils/system-graph.ts.
  3. Update Canvas registrations in components/graph/Canvas.tsx.
  4. Update forms/panels that branch by species.
  5. Update seed data in seed/pebbles.json.
  6. Update this document.

2026-07-19 — acceptance/covers: steps 3–4 deferred to the Surfaces plan (docs/superpowers/specs/2026-07-19-acceptance-value-model-design.md §9); maps exclude acceptances by default. Step 1 is done (lib/config/species.ts, lib/config/edge-types.ts); step 2 needed no change — journey and system map kinds' species defaults in packages/schema/src/maps.ts exclude acceptance, so lib/utils/journey-graph.ts and lib/utils/system-graph.ts have no acceptance-specific branches. lib/utils/graph-build.ts already maps acceptance to React Flow node type "acceptance" as a forward-fix placeholder for when Canvas registration lands. Step 5 is done (seed).