System model — the whole thing, in pictures
Status last verified: 2026-09-04 — verified against src/ module layout (config/, export/, generation/, import/, render/, settings/, source/, tier2/, types/, ui/, utils/, validation/, views/) and the roadmap’s locked architectural commitments.
Your data goes in, answers come out
Section titled “Your data goes in, answers come out”Crosswalker takes whatever shape your data ships in — a control spreadsheet, a crosswalk export, a JSON ontology — and turns it into ordinary Markdown notes in your vault. Then it makes those notes answerable. Everything else on this page is detail on that one spine:
data→Ingestwizard or
harness→Tier 1 vaultcanonical
Markdown→Tier 2 cachesqlite,
derived→QueryBases
+ pivot→Outputviews ·
exports
In one line each: Sources are your raw records → Ingest applies an ImportRecipe (the rules for turning rows into notes) → Tier 1 is the real copy, plain Markdown on disk → Tier 2 is a throwaway SQLite cache that makes queries fast → Query + output give you live views, snapshots, reports, and exports.
Two ways in — a wizard, or a recipe file
Section titled “Two ways in — a wizard, or a recipe file ”There are two doors, and you pick whichever fits — you don’t use both. Either door runs the same engine and produces the identical vault.
in one file→
render() engineapplies therecipe
be valid→Tier 1 vaultplain Markdown
notes on disk
Most people use Door A (the wizard). Door B exists for automation, bulk runs, and agents. Both run the same ImportRecipe through the same generation engine (UI first, config as escape hatch).
In the formal vocabulary: the ImportRecipe is a Recipe artifact adjacent to generation — its Recipe Schema Contract governs the instruction, and the Tier 1 Schema Contract governs the generated records. The recipe is never stored inside the vault as ontology content.
What’s the real copy, and what’s just a cache
Section titled “What’s the real copy, and what’s just a cache”The single most important rule: the Markdown in your vault is the real thing. Everything else is either upstream of it or rebuilt from it. Here’s an actual note it produces:
function: DE
category: DE.AEPotentially adverse events are analyzed…
- Delete the cache and nothing is lost — the sidecar rebuilds from the Markdown. If it’s missing, stale, or corrupt, the projector regenerates it.
- Nothing authoritative lives only in Tier 2. That’s what makes the vault portable and the plugin optional.
- The rules are written down, not implied — a Schema Contract governs what a valid note looks like, and a separate one governs what a valid recipe looks like.
Detail: system architecture · representation tiers.
Anything can write the notes — not just this plugin
Section titled “Anything can write the notes — not just this plugin”The wizard and the engine are conveniences, not gatekeepers. Because the note format itself is the contract, any tool that writes conforming notes is a first-class producer.
record validity
This is the schema-as-primitive commitment — the whole reason the system is modular. Deep dive: ETL and import.
One row in, one note out
Section titled “One row in, one note out ”This is the engine room. You give it two things and it hands back a finished note — where it lives and what’s written in it:
- one record — a row from your source, pinned to a stable id. Below it’s a biological species; it could just as easily be a security control, a product, or a city. (Formally: a ConceptIdentity.)
- your rules — which source field becomes the folder, the filename, the tags, the properties, the links. (Formally: an ImportRecipe.)
The function that does it is render() — one pure function, render(Recipe, ConceptIdentity) → Address, and the only place layout decisions live.
recipe
One row just got used five different ways at once — folder depth from the lineage column, the filename from common_name, a tag from habitat, two properties, and a [[wikilink]] from family. Structure comes from whatever you point at it, not from one magic id column. The five things a rule can produce:
Most rules are just fill-in-the-blank templates — {field} with a small closed filter set ({habitat|lower}, plus slug · tagsafe · fs-safe · truncate). The folder rule above does one thing more: split(lineage, ”;”) is a transformation expression (JSONata) that breaks one packed field into three parts. That’s the everyday case for coded taxonomies — a lineage string, a Dewey number, AC-2, DE.AE-02 — where the hierarchy is hiding inside a single column. Anything past the closed filters (conditionals, lookups, concatenation) escapes the same way.
Folders, or not — you pick the shape
Section titled “Folders, or not — you pick the shape ”Splitting a column gives you parts. It says nothing about nesting. You choose whether those parts become folders at all — the same [Mammalia, Carnivora, Felidae] renders four different ways, and you pick the one your team actually works in:
Folder = browse it in the file explorer. Tag = flat and faceted, so one note can sit under many axes at once. Heading = one reference document with an outline. Wikilink = parent/child as graph edges, no folders at all.
And you don’t have to choose only one: also_emit runs mechanisms in parallel, so an import can be a folder tree and a tag facet at the same time — folders to browse, tags to slice (Ranganathan-style faceted classification). Because the mechanism set is closed at five and render() is the only place (level + mechanism) → address is decided, re-pointing the mechanisms re-shapes the whole vault without touching the engine.
Where this is written down: terminology (what Concept, Recipe, Address mean) · recipe.schema.json → $defs.layout_entry (the machine contract — mechanism, template, ordered layout) · v0.1 schema spec (the same, in prose) · hierarchy primitives (the 5 mechanisms) · conventions (template + filter naming rules) · mapping into Obsidian (source → vault) · target-structure synthesis (why render() is the single coupling point).
The readers — one per shape your data arrives in
Section titled “The readers — one per shape your data arrives in ”A reader is a front-end to render(), never a second engine — and the same readers back the wizard’s parsers (one reader, two doors). Between them they produce the only two things a vault holds: concepts (the notes) and relationships (the links between them):
| Source shape | What a reader does | Produces |
|---|---|---|
| Flat table — rows in a CSV or spreadsheet | one row → one concept | concept notes |
| Nested document — records inside a tree (JSON, at an iterator path) | one record → one concept | concept notes |
| Mapping table — one source id against many target ids | each pair → one typed edge | relationship (crosswalk) notes |
The shapes are general. The current named implementations in tools/ — generate-fixtures plus the crosswalk-from-* extractors — happen to target the compliance launch corpus; see the ingestion dev log for those specifics and the readiness board for status.
Getting answers back out
Section titled “Getting answers back out ”A vault is just notes and the typed links between them — a graph, in plain Markdown. You query that graph with a small closed set of operations, then draw the result in whatever shape answers the question:
+ edgesthe graph
aggregate · diff …→view shapestable · pivot
graph · timeline→
exports
- Query primitives — the closed 8-verb set every view is composed from.
- View shapes — how the same data draws as a table, pivot, graph, etc. (the “four dials”: join × shape × layout × view).
A Bases-backed answer is a live view over current data. A saved point-in-time result is a materialized snapshot. Neither changes which copy is authoritative — the Markdown still is.
What an answer means is domain-specific — that’s the application layer, not the system model. The same primitives produce a coverage matrix, a gap list, a dependency graph, or a standard-format export, depending on the question you ask. Example (compliance launch use case): they compose into the Control / Assurance / Risk lenses — a data-morphology move (traverse → summarize → reshape → draw). A different domain frames its own.
The same power from the UI or a recipe file
Section titled “The same power from the UI or a recipe file”Every step of the active Shape workflow is reachable from both surfaces by design; later lifecycle capabilities still have named parity gaps (UI parity audit):
+ schema
The recipe file is the portable path for automation, agents, and power users. The UI edits that same file rather than keeping a second, private configuration model — which is why anything you can click, you can also script. Principle: UI first, config as escape hatch.
Four words that get mixed up
Section titled “Four words that get mixed up”Crosswalker’s vocabulary describes four different dimensions. Keeping them separate stops a Recipe, a Tier, a layer, and a lifecycle capability being read as the same kind of thing.
| Dimension | Question answered | Examples |
|---|---|---|
| Artifact role | What kind of governed thing is this? | Schema Contract (the rules); Knowledge Set (the content); Recipe (the instructions); later Execution Record and Package Manifest |
| Representation tier | Where does knowledge live, and which copy wins? | Tier 0 source; Tier 1 canonical Markdown; Tier 2 derived SQLite cache |
| Logical layer | Which part of the system is doing the work? | Import, storage, projection, query, export, audit |
| Lifecycle capability | What is the user actually trying to do? | Acquire, Shape, Connect, Understand, Share, Maintain |
Tier 1 is therefore a representation and authority tier, not the root artifact. The ImportRecipe sits beside generation: its Recipe Schema Contract governs the instruction, the Tier 1 Schema Contract governs the generated records.
Follow any thread
Section titled “Follow any thread”This page is the hub; each concept goes as deep as you want:
- Foundations — the problem · what makes Crosswalker unique · vision
- Architecture — system architecture (detailed) · embedded vs server substrates · file-based graph database
- Ingest — ETL and import · hierarchy primitives · mapping into Obsidian · conventions
- Query + output — query primitives · view shapes · metadata ecosystem (Bases)
- Lifecycle + landscape — ontology lifecycle · operational landscape
- Vocabulary — terminology · the schema spec
Related
Section titled “Related”- Artifact roles and authority — separates governed artifacts from tiers, derivatives, runtime values, and carriers
- Ontology lifecycle — the six recurring capabilities this system supports
- System architecture — the detailed reference this page illustrates (component matrix, read/write flows, codebase map)
- ETL and import — schema-as-primitive, the two-mode architecture, the input floor
- Hierarchy primitives — the 5 vault mechanisms
render()composes - Mapping into Obsidian — source row → note on disk, and the two kinds of link Crosswalker creates
- Query primitives + view shapes — the answer side
- v0.1 schema spec — the Tier 1 and ImportRecipe Schema Contracts
- Roadmap — how the implementation maps onto this model