Skip to content

vpdmf_alhazen

Gully Burns edited this page Apr 16, 2026 · 1 revision

A VPDMf-Inspired View Layer for Alhazen

Specifying and Generating Dashboard Components from a Knowledge Graph Schema

Gully A.P.C. Burns · Draft · March 2026


1. Background and Motivation

The View-Primitive Data Model framework (VPDMf) was a software engineering framework developed for the NeuroScholar neuroinformatics system. Its central contribution was a clean separation between (a) a UML-based domain model describing scientific entities and their relationships, and (b) a layer of view definitions that specified how groups of those entities should be composed into coherent, transactional units for user interaction. A system-builder script transformed these two inputs — the domain model and the view annotations — into a relational database schema plus a corresponding Java object model, with views as the first-class transactional currency.

The Alhazen system takes a structurally analogous approach to knowledge curation over scientific literature, but uses a TypeDB knowledge graph as its data backbone rather than a relational database, and a React-based dashboard as its interface rather than a Swing GUI. This document proposes adapting the VPDMf pattern to Alhazen: using TypeDB schema definitions plus lightweight YAML annotation files as view specifications, and generating React browse components from those specifications.

The motivation is the same as in the original VPDMf: rather than hand-authoring one dashboard component per entity type, we want a principled, schema-driven methodology that guarantees coverage of the domain, makes the interlocking of views explicit, and reduces the cost of extending the system as the schema evolves.


2. Core Concepts

2.1 Primitives

In the original VPDMf, a primitive was the smallest independently instantiable unit of the domain model — a UML class that could exist on its own without being subsumed by a containing view. In TypeDB terms, the primitives are entity types (and occasionally relation types that carry significant attribute structure of their own). Every entity type in the TypeDB schema is either:

  • A primary primitive — the root entity of a named view, browseable as a top-level list.
  • An inline primitive — always rendered inside another view, never navigated to directly.
  • A portal target — reachable from a named portal link within another view, which itself has its own view.

Every entity type must fall into at least one of these three categories. This is the coverage guarantee.

2.2 Views

A view is a named, composite domain object built around a primary primitive. It defines:

  • Primary primitive: the TypeDB entity type at the root of the view.
  • Inline components: related entity types and relation types rendered inside the view's card or detail panel, with no separate navigation link.
  • Portals: named outbound links to other views, parameterized by a TypeDB role or relation. A portal is the edge connecting two views in the view graph.
  • Display hints: label field, sort field, card subtitle, color tag, and any filtering defaults for the browse list.

Views interlock to form a view graph — a directed graph where nodes are views and edges are portals. The view graph must be connected (no orphaned views) and must collectively provide a path to every entity type in the schema.

2.3 The View Spec File

Each view is defined in a YAML annotation file. An example for a hypothetical Position view:

view: Position
primary_primitive: position
label_attribute: title
subtitle_attribute: organization
sort_attribute: application_date
inline_components:
  - type: requirement
    relation: position-requires
  - type: compensation
    relation: position-offers
portals:
  - name: Opportunity
    target_view: Opportunity
    via_relation: opportunity-includes
    via_role: included-position
  - name: Interviews
    target_view: InterviewEvent
    via_relation: event-concerns
    via_role: concerned-position
  - name: Learning Gaps
    target_view: LearningGap
    via_relation: gap-exposed-by
    via_role: exposing-position
custom_instructions:
  - "Render the interview timeline as a compact swimlane chart grouped
     by interview stage, with outcome badges on each event node."
  - "Add a skills match panel that compares the position's requirements
     against the agent's profile attributes and displays a gap summary."

The structured fields above cover the standard browse and detail pattern. For views that warrant richer UI treatment, the spec also supports a custom_instructions block — freeform natural language directives that are passed through verbatim into the component plan for Claude Code to interpret.

These instructions are not parsed or validated by the plan script — they are opaque to it. Their meaning is entirely interpreted by Claude Code at implementation time. This gives the spec expressive power that would be impractical to encode structurally: arbitrary layout choices, custom chart types, domain-specific visual metaphors, and composite panels that don't fit the standard inline component model.

The division of responsibility is therefore clear: structured fields handle everything the plan script can reason about automatically (type hierarchy, portal wiring, query construction, TypeScript interfaces), while custom_instructions handle everything that requires human design intent and agent-level interpretation. The plan script's job is simply to ensure the instructions arrive in the right place in the plan document, paired with the correct view context.

TypeDB's own type hierarchy handles inheritance automatically: if a view is defined for a parent entity type, child subtypes are included in the browse list with a subtype filter applied.

2.4 The Esoteric Instructions Vocabulary

Although custom_instructions are freeform, it is worth establishing a loose shared vocabulary so that view spec authors have a consistent reference for what kinds of requests are well-supported. The following categories cover the most useful cases:

  • Timeline / Sequence views: for entities with date or stage attributes. Examples: Gantt swimlane, event timeline, pipeline funnel.
  • Comparison / Matrix views: for juxtaposing multiple instances or matching two entity types against each other. Examples: skills gap matrix, side-by-side position comparison.
  • Status / Progress views: for entities with lifecycle state. Examples: Kanban board, progress ring, burndown chart.
  • Graph / Network views: for exposing relational structure visually. Examples: portal neighborhood graph, concept map, citation network.
  • Aggregate / Summary panels: for dashboard-level statistics derived from a view's instance set. Examples: application stage histogram, reading coverage heatmap.

These categories are suggestive rather than prescriptive. A custom_instructions block can request anything a capable frontend agent can implement — the vocabulary just helps authors write clearer specs and helps Claude Code recognize common patterns quickly.


3. The Job Hunt Domain View Graph

As a concrete test case, the Alhazen job hunting domain defines the following primary entity types. The table below gives the proposed view for each, its inline components, and its outbound portals.

View Primary Primitive Inline Components Portals
Agent agent preferences, skills summary — (singleton; no portals needed)
Opportunity opportunity (3 subtypes) status, source, notes Positions →, Conversations →
Position position requirements, compensation ← Opportunity, Interviews →, Learning Gaps →, Background Reading →
Interview / Event interview_event participants, outcome notes ← Position, Learning Gaps →, Background Reading →
Background Reading background_reading citation, abstract, tags ← Position, ← Interview / Event, ← Learning Gap
Learning Gap / Plan learning_gap status, target date, plan text ← Position, ← Interview / Event, Background Reading →

A few structural observations about this view graph:

  • Position is the hub. It has the most portals and is the natural pivot of the job hunt domain — most navigation flows through it.
  • Background Reading is a spoke. It has no outbound portals of its own; it is always navigated to, never navigated from. This reflects its role as terminal reference material.
  • Opportunity subsumes subtypes. Rather than three separate views for the three opportunity subtypes, a single Opportunity view uses TypeDB's subtype polymorphism to handle all three, with the browse list filtered by subtype via a tab or dropdown.
  • Agent is a singleton. There is exactly one agent instance (the job seeker). The Agent view functions as a configuration/profile panel rather than a browseable list.

4. The Plan Generation Pipeline

The VPDMf system-builder was a set of scripts that consumed UML + XML and emitted Java + SQL directly. The Alhazen approach takes a different position on the division of labor: rather than attempting to template React source code from Python, the pipeline's job is to emit a structured implementation plan that Claude Code then uses to generate the actual source. This keeps the Python script lightweight and auditable, and delegates idiomatic component authoring to an agent that is good at it.

The pipeline consumes TypeDB schema (.tql) files plus YAML view specs and produces a component plan document — a structured Markdown or JSON file that specifies, for each view, exactly what needs to be built and how the pieces connect. Claude Code reads this plan and implements the components. The pipeline has three stages:

4.1 Schema Parsing

The TypeDB schema is parsed to extract the type hierarchy: entity types, their owns attributes, and their plays roles in relation types. This produces an in-memory model of the primitives — the raw material that view specs draw from. TypeDB's sub hierarchy is resolved so that child types are automatically associated with any view defined for their parent.

4.2 View Spec Resolution and Coverage Check

Each YAML view spec is validated against the parsed schema: every inline component type and portal relation must exist in the schema. The resolver also checks the coverage guarantee — every entity type must be reachable as a primary primitive, inline component, or portal target in at least one view. Violations are reported as errors at plan-generation time, not at build time. The plan is only emitted if the coverage check passes.

4.3 Component Plan Emission

For each resolved view, the pipeline writes a plan entry describing what Claude Code should build. Each entry specifies:

  • Component names: e.g. BrowseListPosition, DetailPanelPosition.
  • Props interface: the TypeScript props each component should accept, derived from the view's primary primitive attributes and portal targets.
  • TypeQL queries: the exact match/get queries needed to fetch the primary primitive plus inline components, written out in full by the plan script so Claude Code does not need to reason about TypeDB syntax.
  • Portal wiring: for each outbound portal, the target component name and the filter parameter to pass, so Claude Code can wire navigation links correctly.
  • Display hints: label field, subtitle field, sort order, status badge attribute, and any subtype filter tabs — giving Claude Code enough context to make reasonable layout decisions without over-specifying the UI.
  • Custom instructions: the verbatim contents of the view spec's custom_instructions block, reproduced in full in the plan entry. These are flagged clearly as agent-interpreted directives so Claude Code knows to treat them as design intent rather than structural constraints.

The plan document also includes a shared types section defining the TypeScript interfaces for each primitive, derived from the schema, so that all generated components share a consistent type model. The plan is self-contained: a developer (or Claude Code) should be able to implement the full dashboard from the plan alone, without needing to consult the raw schema or view specs.

4.4 The Claude Code Handoff

The plan document is passed to Claude Code as a structured prompt context. Claude Code is instructed to implement each component entry in order, following the existing Alhazen React conventions (component structure, styling approach, query hook pattern). The plan's role is specification, not scaffolding — Claude Code writes fresh, idiomatic React rather than filling in templates. This means the generated code is maintainable and extensible in the same way as hand-authored code, and can be revised by Claude Code in future iterations as the schema or view specs evolve.


5. The View Graph as a First-Class Design Artifact

In the original VPDMf, the view definition graph was visualized explicitly — the NeuroScholar ELN paper showed it as a navigable graph with view nodes and shared-primitive edges. This proved valuable not just as documentation but as a design tool: gaps in coverage and awkward navigation paths showed up visually before any code was written.

The Alhazen pipeline should emit a view graph visualization as part of its build output — a Mermaid or D3 diagram showing views as nodes and portals as directed edges, with inline components listed inside each node. This serves as:

  • A coverage audit: any entity type not appearing in any node is flagged.
  • A navigation UX review: views with no inbound portals (other than the top-level nav) may be hard to discover.
  • Living documentation: the diagram regenerates automatically when the schema or view specs change.

6. Relationship to Alhazen's Agentic Layer

The view layer described here is a human-facing navigation layer. But Alhazen is fundamentally an agentic system — its primary consumers of the KG are AI agents that curate, reason over, and extend the graph. The view specs serve the agentic layer as well as the dashboard:

  • Query generation: The TypeQL query modules emitted by the pipeline can be used by MCP tool implementations to fetch structured view instances for agent consumption, not just for React rendering.
  • Schema grounding: When an agent needs to populate a new entity, the view spec defines which attributes and relations constitute a "complete" instance — giving the agent a target structure to fill rather than requiring it to reason about the raw schema.
  • Provenance: The inline component boundary defines what gets saved as a single transactional unit — directly relevant to how the agent logs curation actions.

In this sense, the view layer is the shared interface between the human navigating the dashboard and the agent curating the KG. Both see the same domain structure, expressed at the same level of granularity.


7. Next Steps

  1. Finalize the TypeDB schema for the job hunt domain and confirm the entity type inventory.
  2. Author YAML view spec files for each of the six views in the job hunt view graph.
  3. Build the Python schema parser and view spec resolver, including the coverage checker.
  4. Define the component plan document format (structure, required fields per view entry, shared types section).
  5. Implement the plan emitter: schema + view specs → component plan document.
  6. Emit the view graph visualization as a Mermaid diagram as part of the plan output.
  7. Develop the Claude Code prompt context and handoff protocol for implementing components from the plan.
  8. Run Claude Code against the job hunt plan and evaluate the generated components against Alhazen's existing conventions.
  9. Iterate on the plan format based on the quality of the first Claude Code pass.
  10. Extend to a second Alhazen domain (e.g., literature curation) to test generality of the plan format.

This document is a working design note and will evolve as implementation begins.

Clone this wiki locally