- TypeScript 60%
- C# 24.5%
- JavaScript 7.2%
- PowerShell 4.2%
- C++ 4%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
Deletes the four full-resolution avatar candidate PNGs under
.voidbot/voice/norn-candidates/ (a-thread-cartographer, b-rust-wasm-weaver,
c-well-of-urd-oracle, d-triune-fate-weaver; 7.71 MiB total). The installed
avatar is confirmed by sha256/md5 match to be the repixelized crop of
candidate A (.voidbot/voice/norn.png == norn-a-thread-cartographer-repixelized.png,
kept), per docs/norn-avatar-prompts.md's "Current Pick" note. The
contact sheet and the repixelized survivor are left in place.
Search performed before deletion (zero consumers found for any of the
four exact filenames):
- Textual search within Norn (rg -n -F per filename): no hits outside
the images themselves; docs/norn-avatar-prompts.md refers to the
candidates only by title heading, never by file path.
- Estate-wide textual sweep across all ~92 repo directories under
F:/Projects (rg -F per filename, excluding .git/node_modules/Library/
bin/obj/target and *.png): the only hits are the census document itself
(gamecult-ops/docs/repo-census-2026-09/repos/Norn.md) listing these as
deletion candidates.
- Explicit check of VoidBot and Epiphany (the two repos called out for
Persona-state/doc risk): no filename or even case-insensitive "norn"
hits in Epiphany; one incidental "Norn/TeX" mention in a VoidBot note
unrelated to avatar files.
- .voidbot/state/norn.cc inspected directly (it is an OpenPGP-keyring-
shaped binary blob, not JSON); strings shows only a key comment
("norn-steward-norn-contracts"), no filename or stale-path references
to these four candidates.
- mcp__voidbot__search_sources and search_history queried per filename
(semantic retrieval, indexed corpus + archived Discord): confirms the
same picture — docs/norn-avatar-prompts.md discusses all four prompts
by title but the only file paths named as installed/mirrored are
norn.png and the repixelized survivor; no Discord history hit ties
these filenames to a still-active reference.
No build/typecheck applies to a straight image-asset deletion.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
|
||
| .voidbot | ||
| benchmarks | ||
| docs | ||
| scripts | ||
| web/norn-viewer | ||
| .gitignore | ||
| FRIENDLINESS_TUNER.md | ||
| Norn.csproj | ||
| Program.cs | ||
| README.md | ||
| RichSvgRenderer.cs | ||
| TUNING.md | ||
Norn
React-first graph viewer for Epiphany typed graph state.
The live package is web/norn-viewer. It is what clients and agents
should reach for when they want to render architecture, dataflow, and typed
cross-links in a UI.
The older .NET generator, MSAGL SVG renderer, and MCP server still exist as support tools for note exports and legacy inspection. They are not competing client surfaces. Do not make consumers choose between engines like this repo is a sad little trade show booth.
React Viewer
cd E:\Projects\Norn\web\norn-viewer
npm install
npm run dev
import { NornViewer } from "@gamecult/norn-viewer";
import type { NornGraphsState } from "@gamecult/norn-viewer";
export function GraphScreen({ state }: { state: NornGraphsState }) {
return (
<NornViewer
state={state}
layoutMode="combined-force"
motion={{ strength: 1.05, flow: 1.1, orbit: 0.85 }}
performance="fast"
/>
);
}
The public viewer API is intentionally coarse:
layoutMode:layered,stress,force, orcombined-forcemotion: viewer-owned force tuning for Rust-solver combined-force layoutsperformance:quality,balanced,fast, or explicitsimulationBudgetMsrealtime knobsselection,focusSelection,expandedNode, and callbacks for app integration- typed state and event payloads
Norn owns graph layout, viewport motion, selection, focus, inspection, and the interaction boundary of expanded node articles. Consumers own graph meaning and article content. When an expanded article fills a node surface, Norn derives wheel and drag behavior from that surface's committed article geometry; consumers do not need product-specific classes or data attributes to make the article scrollable.
What It Does
The support generator:
- scans markdown notes under a vault folder
- resolves Obsidian wikilinks and regular markdown note links
- optionally starts from an entry note and keeps only reachable notes
- classifies notes into
source-treeandcontrol-flowgraph families - lays out each family as its own graph partition
- reports cross-links that still jump between those families
- runs Microsoft Automatic Graph Layout
- writes:
manifest.jsonsource-tree.svgsource-tree.msagl.svgsource-tree.rich.svgsource-tree.jsoncontrol-flow.svgcontrol-flow.msagl.svgcontrol-flow.rich.svgcontrol-flow.jsoncross-links.jsonwarnings.txt
CLI Usage
Run from source:
dotnet run --project . -- `
--vault-root "E:\Projects\Aetheria-Economy\Aetheria\Source Tree Map" `
--entry-note "Source Tree Map" `
--renderer rich `
--output-dir ".\out\source-tree-map"
After packing as a .NET tool:
norn `
--vault-root "E:\Projects\Aetheria-Economy\Aetheria\Source Tree Map" `
--entry-note "Source Tree Map" `
--renderer rich `
--output-dir ".\out\source-tree-map"
MCP Usage
The MCP server exposes one tool:
generate_obsidian_graph_layout
Run From Source
Use this in an MCP client config when you want to launch the server straight from the repo:
{
"mcpServers": {
"norn": {
"command": "dotnet",
"args": [
"run",
"--project",
"E:\\Projects\\Norn\\Norn.csproj",
"--",
"--mcp"
]
}
}
}
Pack As A .NET Tool
Build the package:
dotnet pack . -c Release -o .\nupkg
Install it from the local package output:
dotnet tool install --global --add-source .\nupkg Norn
Then point your MCP client at the installed command:
{
"mcpServers": {
"norn": {
"command": "norn",
"args": ["--mcp"]
}
}
}
MCP Tool Arguments
vaultRoot: path to the Obsidian vault folderentryNote: optional entry note name or relative note pathoutputDir: optional output directory, defaults to./outlayout:sugiyamaormdsrenderer:msaglorrichincludeUnreachable: keep notes that are not reachable from the entry note
MCP Tool Result
The tool writes manifest.json, primary partition SVGs, raw .msagl.svg variants, custom .rich.svg variants, partition JSON files, cross-links.json, and warnings.txt, then returns:
- output paths for each partition
- seed note IDs used for traversal
- total note and edge counts
- per-partition node and edge counts
- warnings
- the resolved entry note ID, if one was used
Graph Families
By default, notes whose basename contains Control Flow land in the control-flow partition, and everything else lands in source-tree.
You can override that with frontmatter on a note:
---
norn-family: control-flow
---
or:
---
norn-families:
- source-tree
- control-flow
---
Supported keys:
norn-familynorn-familiesgraph-familygraph-families
If your chosen entryNote is itself one of the explicit family roots, the generator also seeds traversal from any sibling family roots it can find.
Source Tree Mapwill also pull inControl Flow MapControl Flow Mapwill also pull inSource Tree Map
That keeps structurally separated note graphs from vanishing just because they no longer link to each other directly.
Layout Modes
sugiyama: layered, better for hierarchy-heavy note treesmds: force-ish spread, better when the graph is cross-linked chaos
mds is the closest MSAGL-native approximation to the Obsidian or Kamada-Kawai vibe. It is not a named Kamada-Kawai mode.
Renderer Modes
msagl: the stock MSAGL SVG, useful as the plain baselinerich: a custom SVG renderer that consumes MSAGL graph geometry and semantic metadata, then draws something with more visual hierarchy and less beige despair
Support Tool: Norn Viewer Demo
The web-side viewer package lives under web/norn-viewer/.
It consumes the typed Epiphany graph state shape directly:
graphs.architecturegraphs.dataflowgraphs.links
and packages:
- Rust hybrid solver layout through bundled WASM
- zoom and pan
- zoom-gated label and detail pop-in
- node, edge, and code-ref inspection
- typed cross-link browsing between architecture and dataflow
- combined-force motion tuning for clients that want the lively overview
Run it locally with:
cd E:\Projects\Norn\web\norn-viewer
npm install
npm run dev
Notes
- unresolved and ambiguous links are written to
warnings.txt - node IDs in the partition
.jsonfiles are relative note paths without.md - the current implementation estimates label sizes instead of using a platform text measurer, because this is a generator, not a cathedral
source-tree.svgandcontrol-flow.svgare the primary outputs for the selected renderer- raw MSAGL output is always preserved as
*.msagl.svg - the custom renderer currently emits
*.rich.svgfrom MSAGL geometry, not from post-processing the stock SVG