Skip to content

The schema is a level of the graph - #508

Closed
WaylandYang wants to merge 2 commits into
feat/one-canvasfrom
feat/schema-is-a-level
Closed

WaylandYang wants to merge 2 commits into
feat/one-canvasfrom
feat/schema-is-a-level

Conversation

@WaylandYang

Copy link
Copy Markdown
Contributor

Part of #497. Stacked on #499 — its shared canvas is what lets the schema diagram be mounted somewhere else.

The ontology is the contract the graph obeys (0012), and the interface showed the contract on one page and the data on another with one buried link between them. Three classes and four relations produced how many facts? had nowhere to be asked.

What lands

A two-position switch beside the search box, Instances and Schema, recorded in the URL as ?level=schema so a link carries it.

Schema draws the ontology page's diagram. Not a copy: OntologySchemaGraph was already a controlled component, so the graph page mounts the same one. It gained a single optional prop, chromeTop, because embedded it has to let the host page's floating bar go first.

The chrome follows the level. Gone at schema level: the time scrubber, the inference tower, the layout and camera towers, the type legend, the entity panel and the "showing N of M entities" read-out. A class has no interval, is not derived, and the schema diagram brings its own zoom tower and its own legend. The search box switches to searching classes; picking one brings it into view, the same path the ontology page's rail takes.

Two crossings, which are the point.

  • Contract to data. Select a class, and the bar offers Only Person 172. It switches to the instance level with every other type hidden — through the existing type-visibility set, so the legend shows what was hidden and the existing "Show all" undoes it. No second filtering mechanism.
  • Data to contract. The type on an entity panel is now a link. Clicking Organization on Sam Altman lands on ?level=schema&cls=organization with that class selected and focused.

Clicking a class selects it; it does not drill. The first version drilled on click, and the schema level was then unusable for what it exists for — one click and you were in the other level. Selecting shows the class's relations with everything else muted, and drilling is the explicit second step.

The class key, not its id, goes in the URL: a GraphNode carries type_key and no class id, and a key reads better in a shared link.

Three bugs this shook out, all worth the comments they got

  • The instance canvas came back blank. Its effect depends on data.data; the schema level unmounts the container, and a ref appearing does not re-run an effect. level joins the dependency array.
  • The return crossing switched level and was immediately undone. Clearing the selection fires the URL-sync effect, which wrote the whole search object back and dropped the level that goLevel had just set. It now merges instead of replacing.
  • The embedded legend and the host's search dropdown landed on each other. The page's bar moves to z-20, above the canvas's own chrome.

Verified in the browser

Against a copy of the benchmark base, 1415 entities and 916 classes: the switch both ways; the class search finding and focusing Person; Only Person 172 landing on an instance canvas of exactly the people, with Show all (915 hidden) offered; clicking Organization on an entity panel arriving at ?level=schema&cls=organization with the class selected; and the ontology page unchanged.

pnpm build clean: style guard, tsc, vite.

Left for the next cut

The schema level has no panel. Selecting a class shows its shape on the canvas and offers the drill, but not its definition, axioms or description — those live on the ontology page, and whether a read-only version belongs here is worth looking at rather than guessing. The drill's semantics — "only this class", which leaves sparse edges because a class's neighbours are hidden with everything else — is the other thing to look at with real eyes.

🤖 Generated with Claude Code

WaylandYang and others added 2 commits September 8, 2026 17:27
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Signed-off-by: WaylandYang <wayland0916@gmail.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Signed-off-by: WaylandYang <wayland0916@gmail.com>
@WaylandYang

Copy link
Copy Markdown
Contributor Author

Follow-up commit from looking at it in the browser. Four things, three of them things I had left open or broken.

A selected class now says what it is. The read-only panel the PR description called "left for the next cut" is here instead, because a schema level where selecting a class shows nothing is not worth looking at. DockedPanel, PanelHeader, Def and Description move out of Ontology.tsx into pages/classPanel.tsx, so the docked panel stays one shell rather than two — DESIGN.md rule 6 says there is only one kind of docked panel, and that stops being true the moment a second page draws its own. SchemaClassPanel is that shell with three read-only tabs: Definition (parent, disjoint, description), Relations (which relations this class takes part in, and with what on the other side), Instances (paged, and clicking one drops to the instance level on that entity — a third crossing, and the most useful one). Its single action is a link to the ontology page. Reading here, authoring there.

The legend was on its own second row. I had pushed the embedded diagram's chrome down with a chromeTop offset, which is how it ended up as a second line under the search box. It now goes through a portal into a slot the host page puts in its own bar, so search, level switch, drill button and legend are one row. The ontology page passes no slot and keeps its floating legend.

Two flexbox bites on the way: the slot with min-w-0 shrank to zero width and the chips spilled down the canvas in a column; without it, min-width: auto on a flex-wrap child resolves to one chip wide and it still wrapped. shrink-0 is what holds it on one line.

The legend swatches read as uneven line weights. They are all the same 2px, but they used the focus colours — inheritance at 95% white beside relations at 60% white. Two lines differing only in brightness read as "thick and thin", not "two kinds of edge". They are now four opaque colours at one weight, taken from each edge's resting colour, and the identity is carried by hue.

The schema's edges were heavier than the instance level's. MIN_EDGE_THICKNESS was 3. Beyond the mismatch across levels, that floor was flattening a distinction the diagram makes on purpose: inheritance edges are sized 0.9 and relation edges 2, and a floor of 3 drew both at 3. It is now 2, which matches the relation edge's own size, lets inheritance be thin again, and still leaves an edge you can hit with a mouse — the reason the floor exists.

pnpm build clean. All four looked at in the browser on the same base.

@WaylandYang

Copy link
Copy Markdown
Contributor Author

Closing unmerged. The level switch is out: on the graph page, Instances and Schema switch between two different datasets, and deciding which one you are looking at before you can read anything is a tax the page did not use to charge. Judged from looking at it running, not from the description.

What the cut found out along the way is worth keeping, and lands separately in #511 — every one of those was a defect in the schema diagram whether or not it is ever embedded anywhere:

  • it drew every class that has an instance (142 here, most with a single instance), so Person at 172 looked no more important than an ImageObject at 1. It now draws the biggest classes, on the same four-step ladder the instance graph uses, with the stepper beside the +N classes pill that reports what is held back;
  • MIN_EDGE_THICKNESS was 3, which flattened the diagram's own distinction — inheritance edges are sized 0.9 and relation edges 2, and the floor drew both at 3;
  • the legend's swatches used the focus colours, so inheritance at 95% white beside relations at 60% white read as uneven line weights rather than two kinds of edge;
  • the legend row mixed 4px chips and 6px pills at identical size;
  • the force settings differed from the instance graph's for no recorded reason (gravity 0.55 against 0.35), so the same engine drew one graph open and the other balled up.

The read-only class panel and the chromeSlot portal go with the switch; classPanel.tsx keeps the docked shell, which the ontology page now imports rather than defining its own.

#498 is revised rather than dropped: the ontology page keeps the diagram and gains the tables as a second view of the same page, switchable, with its rail intact. The switch that is heavy on the graph page is not heavy there — table and diagram are two drawings of one thing, not two datasets.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant