Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 22 additions & 1 deletion .planning/ROADMAP.md
Original file line number Diff line number Diff line change
Expand Up @@ -202,9 +202,30 @@ Plans:
- [x] 16-04-PLAN.md — Integration: Review page wiring + visual verification
**UI hint**: yes

### Phase 17: Graph as Entity-Scoped Tab in Detail Pane
**Milestone**: v0.5.0
**Goal**: Move the entity graph from a peer-tab in Developer view (and a hidden icon button in Standard view) into a `Detail | Graph` tab strip at the top of the right-side detail pane, applied uniformly across both views and across all three entity types (class, property, individual). Property graphs render real domain/range/parent-property edges (an explicit improvement over WebProtege's empty-island treatment).
**Depends on**: none (touches Standard and Developer layouts independently of other Phase 17+ work)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Align Phase 17 dependency with the stated PR gate.

Depends on: none conflicts with this PR’s stated implementation gate on PR #88 (entity graph). This can cause incorrect scheduling/parallelization assumptions in planning.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.planning/ROADMAP.md at line 208, Update the Phase 17 dependency statement
to reflect the actual PR gate: replace or modify the line "Depends on: none" in
.planning/ROADMAP.md so it references PR `#88` (entity graph) or otherwise marks
the entity graph as a prerequisite; ensure the text explicitly matches the PR
gate (e.g., "Depends on: PR `#88` (entity graph)") so scheduling and
parallelization tools/readers will not treat Phase 17 as independent.

**Requirements**: R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11 (locked in 17-SPEC.md)
**Success Criteria** (what must be TRUE):
1. Both Standard and Developer views render a `Detail | Graph` tab strip at the top of the right-side detail pane for all three entity types (class, property, individual). The Developer view's `Tree | Source | Graph` peer-tab strip is reduced to `Tree | Source` — no separate graph view.
Comment thread
coderabbitai[bot] marked this conversation as resolved.
2. Single-click on a non-focus graph node re-centers the graph; double-click fully selects the entity (URL update, tree highlight, detail pane refresh). Pre-existing behavior preserved.
3. The active tab persists across selection changes (clicking a different entity in the tree, in search, or via double-click in the graph keeps the user on whichever tab they were on).
4. The default tab on first entity load in a new session is Detail; subsequent selections honor the user's last-active tab.
5. The in-pane graph has an "Expand" affordance that opens the existing `EntityGraphModal` (no new modal component).
6. Property graphs render domain classes, range classes, parent/child properties, and see-also as actual nodes/edges — not a single isolated focus node. Annotation properties render an empty-state message when they have no domain/range/see-also.
7. The Standard view's prior small "Graph" icon button in the detail panel is removed; the new tab strip is its only graph entry point in that view.
**Plans**: 3 plans
Plans:
- [ ] 17-01-PLAN.md — ontokit-api: extend /entity-graph for property + individual focus + edge_kind enum + tests (cross-repo, autonomous: false)
- [ ] 17-02-PLAN.md — ontokit-web plumbing: PaneTabStrip + SourceTabBody + FullSourceOverlay + useFullSourceOverlay + selectionStore activePaneTab + EntityModal rename + OntologyEdge palette extension
- [ ] 17-03-PLAN.md — ontokit-web layout integration: wire PaneTabStrip into Standard + Developer layouts; remove Graph icon button + Source link + Tree|Source|Graph mode strip; AI smoke test + human UAT checklist
**UI hint**: yes
**Refs**: `.planning/notes/graph-as-entity-pane.md` (decision capture)

## Progress

**Execution Order:** 7 -> 8 -> 9 -> 10 -> 11 -> 12 -> 13 -> 14 -> 15 -> 16
**Execution Order:** 7 -> 8 -> 9 -> 10 -> 11 -> 12 -> 13 -> 14 -> 15 -> 16 -> 17

| Phase | Milestone | Plans Complete | Status | Completed |
|-------|-----------|----------------|--------|-----------|
Expand Down
16 changes: 8 additions & 8 deletions .planning/STATE.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,15 @@ gsd_state_version: 1.0
milestone: v0.4.0
milestone_name: LLM-Assisted Ontology Improvements
status: completed
stopped_at: Phase 16 complete — human-verify approved for 16-04
last_updated: "2026-04-08T15:38:02.879Z"
stopped_at: Phase 17 plans approved
last_updated: "2026-05-02T18:49:51.167Z"
last_activity: 2026-04-08
progress:
total_phases: 10
total_phases: 11
completed_phases: 9
total_plans: 35
total_plans: 38
completed_plans: 35
percent: 100
percent: 92
Comment on lines +6 to +14

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Resolve Phase-state drift between frontmatter/session continuity and current-position sections

Line 6 and Lines 212–214 now point to Phase 17, but the active-position block still reports Phase 16 and 70% progress. This leaves two conflicting sources of truth in the same state file and can break resume handoff behavior.

Also applies to: 212-214

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.planning/STATE.md around lines 6 - 14, The frontmatter field stopped_at
currently says "Phase 17" but the active-position/progress block still reports
Phase 16 and 70%—update the active-position and progress fields to match the
frontmatter: set active-position.phase to Phase 17, update
progress.completed_phases/total_phases and completed_plans/total_plans (or at
minimum progress.percent) so the percent reflects the 9/11 -> 92% values shown
in stopped_at, and ensure any session-continuity fields mirror stopped_at to
remove the conflicting sources of truth (fields to edit: stopped_at,
active-position, and progress).

---

# Project State
Expand Down Expand Up @@ -209,6 +209,6 @@ None yet.

## Session Continuity

Last session: 2026-04-08T15:27:40.844Z
Stopped at: Phase 16 complete — human-verify approved for 16-04
Resume file: None
Last session: 2026-05-02T18:49:51.159Z
Stopped at: Phase 17 plans approved
Resume file: .planning/phases/17-graph-as-entity-scoped-tab-in-detail-pane/17-03-PLAN.md
149 changes: 149 additions & 0 deletions .planning/notes/graph-as-entity-pane.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
---
title: Graph as Entity-Scoped Tab in Detail Pane — Design Decisions
date: 2026-05-02
context: Pre-phase exploration + sketch session; captured for Phase 17 spec/plan.
references:
- WebProtege Entity Graph (stacked under detail panel)
- Folio Enrich (Candidate Details | Entity Graph tab strip)
- Current OntoKit Standard view (Graph icon button in right-side detail panel)
- Current OntoKit Developer view (Graph as peer-tab next to Tree/Source)
sketches:
- .planning/sketches/001-tab-strip-language/ (winner: D — icon + label, ABOVE entity header)
- .planning/sketches/002-standard-view-layout/ (winner: D — Compact + 50/50 tabs)
- .planning/sketches/003-developer-view-and-modal/ (winner: applied + Source-as-third-tab restructure)
- .planning/sketches/004-open-full-source/ (winner: C — Modal ⇄ Maximize round-trip)
---

# Graph as Entity-Scoped Tab in Detail Pane

The graph today is misplaced in both views: a peer-tab in Developer (alongside Tree/Source — implies it's a *navigation surface*, not an entity-scoped view), and a small icon button in Standard that users miss entirely. This note captures the design decisions made during exploration (Decisions 1-8) and refined through a four-sketch validation pass (Decisions 9-11 + visual specs).

## Problem statement

A graph is fundamentally an entity-scoped view — it shows a focused class/property/individual surrounded by its neighborhood. The current placement in both views obscures that relationship. Users in Standard view don't realize the graph exists. Users in Developer view treat it as a separate mode they switch to, breaking the connection between the selected entity and what's rendered.

## The design contract (11 decisions)

### 1. Purpose: read-only neighborhood view (verify + explore)

The graph is a read-only context view. It helps users see the selected entity in relation to its siblings, parents, cousins. It is not a manipulation surface (no drag-to-reparent in this scope) and not a presentation/screenshot surface (that's a side benefit).

### 2. Layout: tabbed swap inside the existing detail pane

The right-side detail pane gains a tab strip at the top. The two (Standard) or three (Developer) tabs swap content in the same pane. Same screen real estate as today; tabs are one click away; swapped content is never visible simultaneously.

**Sketch refinements (from 001 + 002):**
- **Tab strip sits ABOVE the entity header** (not below). Reads as "Entity workspace with mode selector," not "Entity card with buried tab." Sketch 001 Variant D.
- **Compact density** — tab buttons use 8px vertical padding + text-xs, matching the left-pane tree-tabs strip exactly so the bottom borders align horizontally across the whole editor. Sketch 002 Variant D.
- **Tabs span the full pane width** — `flex: 1 1 0` so 2 tabs are 50/50, 3 tabs are 33/33/33. Reads as a major mode-selector, not a small control collapsed to one side.
- **Active state** — accent underline + accent-tinted background fill. Same visual language as the left-pane tree-tabs (Classes / Properties / Individuals), so the two strips read as a coherent family.
- **Icons + sentence-case labels** — Lucide `file-text` for Detail, a 3-node graph glyph for Graph, `chevrons-left-right` for Source. Underlines indicate active.

### 3. Old peer-tab Graph: removed entirely

Developer view's `Tree | Source | Graph` peer-tab strip is removed. Graph is *only* ever in the right-pane tab strip. Standard view's small icon button is also removed.

**Sketch refinement (from 003):** the entire left-pane mode strip (Tree | Source) is removed. The left pane shows only the tree (with `Classes | Properties | Individuals` sub-tabs). Source migrates to the right pane as a third tab — see Decision 9.

### 4. Full-screen affordance: reuse existing EntityGraphModal

The in-pane graph has an "Expand" button (top-right of the canvas). Clicking it opens the existing `EntityGraphModal` component as a centered overlay above the editor, dismissable via Escape / click-outside / close button. Same component reused for both Standard and Developer views.

### 5. Entity-type scope: all three (class, property, individual)

Class, Property, and Individual detail panes each get the tab strip. The graph component adapts per entity type:

- **Class:** parent classes, child classes, siblings, equivalent classes, disjoint classes, see-also.
- **Property:** **domain classes, range classes**, parent/child properties, see-also. _Explicit improvement over WebProtege, which leaves the property graph as an isolated single-node island._ OntoKit's property graph must show the relationships that make a property meaningful.
- **Individual:** class assertions (rdf:type), object property values, see-also, sameAs.

**Edge case (defer to plan/build):** Annotation properties typically have no domain/range. Graph for them shows just see-also if any, plus a friendly empty state otherwise.

### 6. Click behavior: preserve current single/double-click semantics

- **Single-click on a non-focus node** → re-center the graph on that node (graph navigation only; global selection unchanged).
- **Double-click on a non-focus node** → fully select that entity (URL updates, Tree highlights, Detail tab shows new entity).

Preserves the "explore the graph without losing your place" model that's a real differentiator vs WebProtege.

### 7. Tab persistence: stay on current tab across selection changes

When the user picks a new entity (tree click, search, or double-click in graph), the active tab does *not* reset. If they were on Graph, they stay on Graph. If on Detail, they stay on Detail. If on Source (Developer-only), they stay on Source.

### 8. Default tab on first load: Detail

First entity opened in a new session lands on the Detail tab. Decision 7 then keeps the user on whichever tab they choose for the rest of the session.

### 9. Source as right-pane Developer-only tab _(new — from sketch 003)_

The Source affordance migrates from two places that no longer exist:

- The left-pane `Tree | Source` peer-tab strip (removed per Decision 3 refinement).
- The `</> Source` link button in the entity-actions area of the detail header (removed).

…into a **third tab in the right-pane tab strip** alongside Detail and Graph. Source tab is **conditionally rendered** based on editor mode:

- **Standard view:** right pane has `Detail | Graph` (2 tabs at 50/50). No Source tab.
- **Developer view:** right pane has `Detail | Graph | Source` (3 tabs at 33/33/33).

The Source tab shows the **entity-scoped Turtle snippet** — just the block defining the currently-selected entity, with a comment line indicating where in the full file it lives (e.g., `# File: ontology.ttl, line 4,217`). A toolbar above the snippet exposes:

- **↗ Open full source** — opens the full ontology source (see Decision 10).
- **⎘ Copy snippet** — copies the entity-scoped snippet to clipboard.

### 10. "Open Full Source" — Modal ⇄ Maximize round-trip _(new — from sketch 004)_

When the user clicks **↗ Open full source** from the Source tab, a centered **modal** opens at ~92% viewport with a dim backdrop, reusing the same modal frame component as `EntityGraphModal`. Inside the modal, the user can:

- **Stay in modal** — Esc / click-outside / ✕ dismisses fully back to the Source tab.
- **⤢ Maximize** (modal header) — promotes the modal to a full editor takeover (tree + detail hidden; only the app header and project bar remain). Inside the takeover:
- **⊟ Restore** (takeover header) — returns to the modal view. Bouncing maximize ↔ restore is symmetric and preserves scroll position.
- **← Back to entity** — dismisses fully back to the Source tab.

**Terminology:** the takeover-side button is labelled **"Restore"** (matching Windows OS Maximize ↔ Restore convention) with tooltip *"Restore to modal view."* "Minimize" was rejected because in OS land it means send-to-taskbar (hide entirely), not return-to-previous-size — the wrong mental model.

**Round-trip integrity:** the Restore button is only shown when the takeover was reached via the modal's Maximize. If a user reaches the takeover by some other path (none currently designed, but kept open as a constraint), the Restore button is absent — preserving the chain.

**State:**
- A `cameFromModal` boolean tracks whether the takeover was reached via Maximize.
- Esc dismisses fully from either size; Restore only changes size.
- Active right-pane tab (Detail / Graph / Source) doesn't change when the source overlay opens or closes.

### 11. Tree → Source auto-jump (behavior spec) _(new — from sketch 004 follow-up)_

When the user has the Source tab active and selects a different entity in the Tree (or via search), the Source tab's content auto-updates to show the newly-selected entity's snippet — no extra click.

If the **full-source overlay is also open** (in either modal or maximized size), it auto-scrolls to the new entity's lines and re-applies the highlight rule. The overlay does not dismiss on selection change.

This complements Decision 7 (tab persistence) and Decision 10 (round-trip) — together they make the Source tab feel like a continuously-synced view of "whatever you're looking at in the tree."

## Implicit consequences (worth flagging for the plan)

- **Standard view's small Graph icon button** in the right-side detail panel — the affordance the user described as "not obvious" — is removed. The new tab strip replaces it.
- **Developer view's Tree | Source peer-tab strip** is removed entirely. The left pane is just the tree.
- **`</> Source` link in entity-actions** is removed in both views (replaced by the Source tab in Developer; not exposed at all in Standard).
- **Tab strip component** is shared across both views but receives a `tabs` prop that drives `flex: 1 1 0` layout: 2 tabs in Standard, 3 in Developer. One component, two configurations.

## Visual decisions captured from sketches

| What | Decision | Source |
|---|---|---|
| Tab strip position | Above the entity header (topmost chrome of the right pane) | Sketch 001 D |
| Tab styling | Icon + sentence-case label, accent-fill on active, accent underline | Sketch 001 D |
| Tab density | Compact: 8px vertical padding, text-xs, matching left tree-tabs height | Sketch 002 D |
| Tab width | `flex: 1 1 0` — fills the pane (50/50 in Standard, 33/33/33 in Developer) | Sketch 002 D |
| Standard view layout | 2-pane: Tree (~280px) \| Detail/Graph (rest) | Sketch 002 |
| Developer view layout | 2-pane: Tree (~280px, no mode strip) \| Detail/Graph/Source (rest) | Sketch 003 |
| Modal frame | Reuse `EntityGraphModal` shell — same border radius, shadow, dismissal | Sketch 004 |
| Open Full Source default | Modal at ~92% viewport, dim backdrop | Sketch 004 C |
| Open Full Source escape | ⤢ Maximize → full editor takeover; ⊟ Restore returns to modal | Sketch 004 C |
| Restore button label | "Restore" (Windows convention; rejected: Minimize, Exit fullscreen, Back to Modal) | Sketch 004 |

## Out of scope for Phase 17

- Drag-to-reparent in the graph.
- Per-user / per-project default tab preference.
- Graph for properties of properties (rdf:Property meta-level).
- Graph export to SVG/PNG for screenshots (separate feature).
- Source view editing UX changes (the new tab inherits whatever the current Source view does for keybindings, autocomplete, etc.).
- Two-way navigation from full-source line clicks back to tree selection (existing source-IRI index already supports it; just preserve behavior).
Loading
Loading