How it’s built — the five layers, the data contract, kernel and shell, and the path from template to a finished cockpit. One load-bearing distinction: kernel and shell are pinned (never edited in the consumer), the template is copied and filled.
Every cockpit is made of the same five layers. The middle column — pinned or copied — is the most important distinction: it decides what you touch and what you adopt unchanged.
| Layer | What | Where | Lifecycle |
|---|---|---|---|
| Contract | The 4-axis model + JSON schema — the shape-truth. | contract/ + references/ | versioned |
| Kernel | The pure compute core — Gate·Fit·Cost·Risk scoring + fork narrowing. | engine/kernel.js | pinned |
| Shell | The mechanism — boot/render/URL loop, view registry, fork renderers. | shell/shell.js | pinned |
| Template | The copy-me scaffold — spec over mount() + station renderers + stub data. | template/ | copied |
| Instance | The filled template — one engagement’s cockpit. | customers/*/site/ | filled |
Pinned vs. copied — kernel and shell are pinned via the _methodology submodule and never edited in the consumer (like brand → website/_brand); improvements flow back, then the consumer re-pins. The template is copied and filled.
The data contract used to be prose documentation you followed by hand. Plan 15 inverted it: the JSON schema (contract/schema/) is now the machine-checkable source of shape-truth, with contract.md the doctrine on top.
→ The generated field reference · → The data contract in detail · → The data pipeline & CLIs
A new solution cockpit is born by copying template/ — never by forking another engagement.
copy
Template → site/
Copy the copy-me scaffold template/ into <engagement>/site/.
fill
Fill data/
Author the data — JSON files, or per-record YAML shards for the big ones (solutions · research).
build
Assemble
assemble.mjs stitches shards → the served JSON; generators emit requirements.md / landscape.json.
check
Validate
node contract/validate.mjs <engagement>/data — shape, semantics, docs.
live
Deploy
CI builds the static site and ships it to the Caddy VM.
→ The data pipeline & CLIs · → The front-end & the build in detail
Both cockpits consume kernel + shell through one pinned _methodology submodule — like the website pulls the brand via _brand. The instance supplies only a thin spec.
The shell owns the mechanism (boot → load → render loop, view registry, fork renderers, keyboard nav); the instance supplies the content (the data manifest, the render(ctx) callbacks per view, the cost hooks). app.js is a thin instance spec over DecisionShell.mount(spec).
<!-- Load order: brand tokens → brand CSS → shell CSS → app CSS,
then kernel → shell → app -->
<link rel="stylesheet" href="styles/tokens.css">
<link rel="stylesheet" href="shell.css">
<script defer src="engine/kernel.js"></script>
<script defer src="shell.js"></script>
<script defer src="app.js"></script>
engine//shell/, then the consumer re-pins.Whatever an engagement needs on top goes into an extension — not a fork of the core. An extension schema composes the base (allOf + $ref) and adds its own fields; unevaluatedProperties: false rejects anything neither base nor extension documents.
A typed cost model (seasonal seats, annual discount, peak weeks) as a per-project extension of the base solutions schema.
A 6th facet (integration) alongside the five generic knowledge facets — how the core tool docks the AI layer.
The front-end — the five layers, the template, the two registers and the explorer.
references/cockpit.md
The data contract as doctrine — naming grammar and fully declared field shapes (the schema is the shape-truth).
references/contract.md
Transferring between engagements — the rule of three: when to harvest, when to copy.
references/transferring-between-engagements.md