From f41b2c615dd19bb7582d037413ab9b60daee6c08 Mon Sep 17 00:00:00 2001 From: teknium1 <127238744+teknium1@users.noreply.github.com> Date: Sat, 12 Sep 2026 10:12:07 -0700 Subject: [PATCH] =?UTF-8?q?feat(skills):=20system-atlas=20=E2=80=94=20expl?= =?UTF-8?q?orable=20isometric=20architecture=20atlases=20(port=20of=20inkb?= =?UTF-8?q?oard/system-atlas,=20MIT)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Ports the system-atlas agent skill: one data.mjs file renders both an interactive isometric HTML map (progressive-disclosure chapters, moving data packets, question tracking by Q-ID) and a generated text twin (SYSTEM.md) for the repo. Why: architecture discussions that outgrow a single diagram — the skill encodes hard-earned rules (max 3 structures per chapter, shapes+labels, docs-policy ask before committing). Upstream 410 stars since Aug 20, VoltAgent-listed; complements architecture-diagram (static SVG) with an explorable, stateful artifact. - optional-skills/creative/system-atlas/: SKILL.md (89 lines), references/ (design language, process lessons), assets/ (build.mjs, template.html, data.example.mjs) vendored verbatim; LICENSE.txt (MIT, Harshyt Goel) - Live smoke: node --check both .mjs OK; node build.mjs produced atlas.html (41.5 KB) + SYSTEM.md from the example data, zero deps - docs: own catalog row + generated page + sidebar entry only --- .../creative/system-atlas/LICENSE.txt | 21 + .../creative/system-atlas/SKILL.md | 89 ++++ .../creative/system-atlas/assets/build.mjs | 104 +++++ .../system-atlas/assets/data.example.mjs | 87 ++++ .../system-atlas/assets/template.html | 423 ++++++++++++++++++ .../references/design-language.md | 34 ++ .../references/process-and-lessons.md | 53 +++ .../docs/reference/optional-skills-catalog.md | 1 + .../creative/creative-system-atlas.md | 105 +++++ website/sidebars.ts | 1 + 10 files changed, 918 insertions(+) create mode 100644 optional-skills/creative/system-atlas/LICENSE.txt create mode 100644 optional-skills/creative/system-atlas/SKILL.md create mode 100644 optional-skills/creative/system-atlas/assets/build.mjs create mode 100644 optional-skills/creative/system-atlas/assets/data.example.mjs create mode 100644 optional-skills/creative/system-atlas/assets/template.html create mode 100644 optional-skills/creative/system-atlas/references/design-language.md create mode 100644 optional-skills/creative/system-atlas/references/process-and-lessons.md create mode 100644 website/docs/user-guide/skills/optional/creative/creative-system-atlas.md diff --git a/optional-skills/creative/system-atlas/LICENSE.txt b/optional-skills/creative/system-atlas/LICENSE.txt new file mode 100644 index 0000000000..3d7770daf1 --- /dev/null +++ b/optional-skills/creative/system-atlas/LICENSE.txt @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2026 Harshyt Goel + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/optional-skills/creative/system-atlas/SKILL.md b/optional-skills/creative/system-atlas/SKILL.md new file mode 100644 index 0000000000..5d452732ed --- /dev/null +++ b/optional-skills/creative/system-atlas/SKILL.md @@ -0,0 +1,89 @@ +--- +name: system-atlas +description: "Build explorable isometric architecture atlases as HTML." +version: 1.0.0 +author: Harshyt Goel (adapted by Nous Research) +license: MIT +platforms: [linux, macos] +metadata: + hermes: + tags: [architecture, diagrams, isometric, documentation] + category: creative + related_skills: [architecture-diagram, excalidraw] + upstream: https://github.com/inkboard/system-atlas (pinned f7005f2) +--- + +# System Atlas Skill + +An atlas is one data file (`data.mjs`) that renders two views: an **interactive isometric map** (a single self-contained `atlas.html` — hover to read, click to pin, go inside for steps, moving data packets you can inspect, chapters that reveal the system a few structures at a time), and a **generated text twin** (`SYSTEM.md`) with the decisions table, every structure, the flows, and the open questions by ID. The data file is the only thing anyone edits; both views rebuild from it. It sits beside a hand-written glossary (`CONTEXT.md`) and ADRs. + +**Does:** interactive architecture maps with progressive disclosure, question tracking across feedback rounds, a generated text twin, and a repeatable update loop. +**Doesn't:** static one-off diagrams (use the architecture-diagram or excalidraw skill), finished systems that only need a README, or a single diagram for a PR. + +## When to Use + +Use whenever someone wants to discuss, design, review, or explain an architecture visually — "make an atlas", "map the system", "make the architecture explorable", "visualize the codebase/agent/pipeline so we can talk about it", "a diagram I can click around", "walk me through how it fits together" — or when an architecture discussion is producing a pile of open questions that need tracking across feedback rounds. Also use it to update an existing atlas after decisions change. Best when the system is new enough that vocabulary, decisions, and questions are still moving and there will be more than one feedback round. + +## Prerequisites + +- Node.js (any recent version; the build uses only `node:fs`, `node:path`, `node:url` — no npm install needed). +- A static server for verification (`npx serve` or `python3 -m http.server`). + +## How to Run + +```bash +mkdir -p /atlas +cp /assets/{template.html,build.mjs} /atlas/ +cp /assets/data.example.mjs /atlas/data.mjs # then fill it in +node /atlas/build.mjs # writes ../SYSTEM.md and ../atlas.html +``` + +Every field of the data file is documented in `assets/data.example.mjs`. + +## Quick Reference + +| File | Role | Edit it? | +|---|---|---| +| `atlas/data.mjs` | Single source of truth: structures, flows, chapters, decisions, questions, prose | Yes | +| `atlas/template.html` + `atlas/build.mjs` | Renderer + generator | Presentation only | +| `atlas.html` | Built atlas; republish at the same URL after every rebuild | No (generated) | +| `SYSTEM.md` | Built text twin | No (generated) | +| `CONTEXT.md` | Glossary, one line per noun | By hand | +| `adr/` | Hard-to-reverse decisions | By hand | +| `research/` | Deep-dive evidence | Append-only | + +## Procedure + +Follow the order — each step was earned by a correction the first time round. + +1. **Read the inputs before drawing.** The vision doc, the repo's existing surfaces, and whatever prior art the user allows (ask — they may forbid a branch or a source). If you will build on a framework, read its docs first; hand long docs to a subagent via `delegate_task` with your specific design questions and have it return a primer with gotchas and a "what it does not give us" list. Drawing before this produces boxes that don't map to anything real. +2. **Discuss before drawing.** Propose the structure in chat, mapped to the runtime's real primitives, and ask only the questions you cannot derive from the repo. Take defaults for the rest and say which. +3. **First atlas — the whole system.** Copy `assets/` into the atlas home (rename `data.example.mjs` to `data.mjs`), fill the data, build with `node`, publish. **Where the atlas home is depends on the repo's docs policy** — ask before committing anything. Docs-friendly repos: `docs//atlas/` in-tree. Repos that commit only ADRs and `CONTEXT.md`: put the atlas, `SYSTEM.md`, and `research/` in a git-ignored scratch dir and attach `SYSTEM.md` + research to the spec issue when published. (Committing the whole set once produced a 3,900-line docs PR and four review rounds reconciling three restatements of one design.) Load the design-md or architecture-diagram skill via skill_view for HTML-artifact guidance if useful; read `references/design-language.md` for the visual rules either way. +4. **Progressive disclosure.** A whole system at once reads as noise. Ten-ish chapters; each adds at most three structures and runs one small flow that only touches revealed structures; the last chapter shows everything with a flow picker. Unrevealed structures stay in the index, dimmed, with their chapter number. Panels are summary-first: one sentence, then *Read more* and *Steps* folded. +5. **Shapes and labels.** Letters on boxes are not enough. Give each role a shape and put a readable name label on the canvas under every structure — see design-language. +6. **Text twin.** `CONTEXT.md` is a glossary and nothing else (the nouns, one line each); ADRs only for decisions that are hard to reverse, surprising without context, and the result of a real trade-off — these two are the in-tree pieces. `SYSTEM.md` is generated and `research/` holds evidence; both live with the atlas (scratch dir or `docs/`, per step 3). Don't open issues unless asked. +7. **Feedback by question ID.** Every question is `Q-` with a state: open (a string), resolved `{q, r}` (answer + date), or routed `{q, to}` (handed to a named next step). Record the user's words. If they call something "not a question", drop it; if they say "I don't get this", explain with a concrete example *before* resolving. After each round: rebuild, republish, update memory. +8. **Deep dives feed back.** Research with subagents (`delegate_task`) against one shared brief (the interface we own, the requirements that separate candidates, a usage model for cost, a fixed deliverable shape). Write a synthesis with a normalized cost/fit grid. Fold resolutions into the data as `{q, r: '… (from the deep dive, date)'}`. If the user rejects a proposal, sweep *every* file and rewrite — a banner on top of a stale section is not enough. +9. **Keep it current.** One source, rebuild and republish after every change, never hand-edit generated files, and leave a `README.md` in the docs folder explaining the set (table in `references/process-and-lessons.md`). + +## Publishing + +`atlas.html` is one self-contained file — no build step, no external assets beyond a Google Fonts stylesheet. Serve the folder with any static server (`npx serve`, `python3 -m http.server`) and hand over the URL, or let the repo's pages host serve the committed file. One URL, republished after every data change, never a second copy. If you keep a stable published URL, put it in `META.artifactUrl` so `SYSTEM.md` links to it. + +## Pitfalls + +- Keep `` first and `` immediately after — otherwise quirks mode and mojibake arrows. +- The renderer rebuilds its whole scene on every draw: a stray `render()` in a hover handler detaches the element under the cursor and the browser stops synthesising clicks — the map looks perfect in a screenshot while nothing responds. +- Some in-app browsers render `file://` as a static snapshot; verify via a static server, not from disk. +- Never delete a question — resolve or mark it dropped, so IDs stay stable. +- After every decision, grep the outputs for stale words (`pending`, the old model name, the rejected design) — the person reads everything. +- Large HTML/JS via shell heredocs is brittle; use `write_file` and keep the data block JSON-serializable. + +## Verification + +- `node /atlas/build.mjs` exits 0 and writes both `SYSTEM.md` and `atlas.html`. +- Syntax-check the built script (`new Function(js)`), then open the served page in a real browser at ~1280×800; check a first chapter, a middle chapter, the last chapter, an inside view, and the light theme. +- Click a structure and confirm the panel says **pinned** and offers *Go inside*; click a packet dot and confirm the payload opens. +- Every structure has `one`, `what`, `how`, a `short` label, a role `kind`, and its questions; ghosts are marked; chapters exist with per-chapter flows; the last chapter is the whole system. +- `SYSTEM.md` carries the decisions table, the question index with IDs and states, and the "how this file is maintained" footer. +- Project memory records the atlas URL, docs paths, locked decisions with dates, what the user rejected and why, and the next step. diff --git a/optional-skills/creative/system-atlas/assets/build.mjs b/optional-skills/creative/system-atlas/assets/build.mjs new file mode 100644 index 0000000000..bd3c1445a6 --- /dev/null +++ b/optional-skills/creative/system-atlas/assets/build.mjs @@ -0,0 +1,104 @@ +// Builds /SYSTEM.md and /atlas.html from data.mjs (same folder). +// Usage: bun /build.mjs — outDir = parent of atlasDir by default, or META.outDir +import { readFileSync, writeFileSync } from 'node:fs'; +import { dirname, join } from 'node:path'; +import { fileURLToPath } from 'node:url'; +import { META, DECISIONS, GROUPS, NODES, FLOWS, CH, HOW_HTML } from './data.mjs'; + +const here = dirname(fileURLToPath(import.meta.url)); +const outDir = META.outDir ? join(here, META.outDir) : join(here, '..'); + +// ---------- shared helpers ---------- +const Q = (c) => (typeof c === 'string' ? { q: c } : c); +const md = (s) => + String(s) + .replace(/(.*?)<\/code>/g, '`$1`') + .replace(/(.*?)<\/mark>/g, '**$1**') + .replace(/(.*?)<\/em>/g, '_$1_') + .replace(/(.*?)<\/b>/g, '**$1**') + .replace(/<\/p>\s*

/g, '\n\n') + .replace(/<[^>]+>/g, '') + .replace(/ /g, ' ') + .replace(/&/g, '&') + .replace(/</g, '<') + .replace(/>/g, '>') + .trim(); +const groupTitle = Object.fromEntries(GROUPS.map((g) => [g.id, g.title])); +const cnt = { open: 0, res: 0 }; +NODES.forEach((n) => (n.cond || []).map(Q).forEach((c) => (c.r || c.to ? cnt.res++ : cnt.open++))); + +// ---------- SYSTEM.md ---------- +function buildSystemMd() { + const out = []; + out.push(`# ${META.title} — System Definition`, ''); + out.push(META.intro, ''); + out.push(`_Question status: **${cnt.open} open · ${cnt.res} resolved**._`, ''); + out.push('## One paragraph', '', META.onePara, ''); + out.push('## Decisions locked', '', '| Axis | Decision | ADR |', '|---|---|---|'); + DECISIONS.forEach((d) => out.push(`| ${d.axis} | ${d.decision} | ${d.adr} |`)); + out.push(''); + out.push('## Cost model', ''); + META.costModel.forEach((l) => out.push(l)); + if (META.deepDive) out.push('## Deep dives', '', META.deepDive, ''); + out.push('## Reading order (the atlas chapters)', ''); + CH.forEach((c, i) => out.push(`${i + 1}. **${c.title}** — ${md(c.lede)}${c.reveal.length ? ` _(adds ${c.reveal.join(', ')})_` : ''}`)); + out.push(''); + out.push('## Structures', ''); + const index = []; + for (const g of GROUPS) { + out.push(`### ${g.title}${g.id === 'off' ? ' (designed for, not built)' : ''}`, ''); + for (const n of NODES.filter((n) => n.group === g.id)) { + out.push(`#### ${n.code} · ${n.name}${n.ghost ? ' _(not switched on)_' : ''}`, ''); + out.push(`**In one line.** ${md(n.one)}`, ''); + out.push(`**What it does.** ${md(n.what)}`, ''); + out.push(`**How it's built.** ${md(n.how)}`, ''); + if (n.steps) { + out.push('**Steps in execution.**', ''); + n.steps.forEach((s, i) => out.push(`${i + 1}. **${s[0]}** — ${s[1]}`)); + out.push(''); + } + const cs = (n.cond || []).map(Q); + if (cs.length) { + out.push('**Questions.**', ''); + cs.forEach((c, i) => { + const id = `Q-${n.code}${i + 1}`; + out.push(c.r ? `- ~~**${id}** ${md(c.q)}~~ ✓ ${md(c.r)}` : c.to ? `- **${id}** ${md(c.q)} → _${md(c.to)}_` : `- **${id}** ${md(c.q)}`); + index.push([id, n.code, c]); + }); + out.push(''); + } + } + } + out.push('## Flows (representative packets)', '', 'Payload shapes are what the design implies, not measured traffic.', ''); + for (const f of FLOWS) { + out.push(`### ${f.name}`, '', '| # | From → To | Packet | Representative payload |', '|---|---|---|---|'); + f.hops.forEach((h, i) => out.push(`| ${i + 1} | ${h[0]} → ${h[1]} | ${h[2]} | \`${JSON.stringify(h[3]).replace(/\|/g, '\\|')}\` |`)); + out.push(''); + } + out.push('## Questions — index', '', 'Reference by ID. ✓ resolved (with date) · otherwise open.', ''); + index.forEach(([id, code, c]) => out.push(c.r ? `- ~~**${id}**~~ (${code}) ✓ ${md(c.r)}` : `- **${id}** (${code}) ${md(c.q)}`)); + out.push(''); + if (META.platformGives || META.weOwn) out.push('## What the platform gives vs what we own', '', `**Platform gives:** ${META.platformGives||''}`, '', `**We own:** ${META.weOwn||''}`, ''); + if (META.filesystem) out.push('## Planned filesystem', '', '```', META.filesystem.trimEnd(), '```', ''); + out.push('## How this file is maintained', '', `Generated from \`${META.sourcePath||'atlas/data.mjs'}\` by \`${META.buildCmd||'bun atlas/build.mjs'}\`, which also builds the interactive atlas (\`atlas.html\`${META.artifactUrl?`, published at ${META.artifactUrl}`:''}). Edit the data file, rebuild, republish — never edit this file by hand.`, ''); + return out.join('\n'); +} + +// ---------- atlas.html ---------- +function buildAtlasHtml() { + const tpl = readFileSync(join(here, 'template.html'), 'utf8'); + const decisionsHtml = DECISIONS.map((d) => `

  • ${d.axis}. ${md(d.decision).replace(/\*\*(.*?)\*\*/g, '$1').replace(/`(.*?)`/g, '$1').replace(/\[(.*?)\]\((.*?)\)/g, '$1')}
  • `).join(''); + const data = [ + `const GROUPS = ${JSON.stringify(GROUPS)};`, + `const NODES = ${JSON.stringify(NODES)};`, + `const FLOWS = ${JSON.stringify(FLOWS)};`, + `const CH = ${JSON.stringify(CH)};`, + `const HOW_HTML = ${JSON.stringify(HOW_HTML)};`, + `const DECISIONS_HTML = ${JSON.stringify(decisionsHtml)};`, + ].join('\n'); + return tpl.replace('__TITLE__', META.title + ' Atlas').replace('/*__DATA__*/', data + `\nconst STATS = ${JSON.stringify(META.stats||[])};\nconst TITLE = ${JSON.stringify(META.title||'System')};`); +} + +writeFileSync(join(outDir, 'SYSTEM.md'), buildSystemMd()); +writeFileSync(join(outDir, 'atlas.html'), buildAtlasHtml()); +console.log(`built SYSTEM.md + atlas.html · ${cnt.open} open · ${cnt.res} resolved · ${NODES.length} structures · ${DECISIONS.length} decisions`); diff --git a/optional-skills/creative/system-atlas/assets/data.example.mjs b/optional-skills/creative/system-atlas/assets/data.example.mjs new file mode 100644 index 0000000000..f739107fe0 --- /dev/null +++ b/optional-skills/creative/system-atlas/assets/data.example.mjs @@ -0,0 +1,87 @@ +// Single source of truth for one atlas. Copy to /data.mjs and edit. +// Build: bun /build.mjs → writes ../SYSTEM.md and ../atlas.html +// The atlas home is docs//atlas/ in repos that commit design docs, or a +// git-ignored scratch directory in repos that only commit ADRs + CONTEXT.md. + +export const META = { + title: 'Example Agent', // " Atlas" in the tab; "<title> — System Definition" in SYSTEM.md + artifactUrl: '', // fill after first publish; keep it stable across rebuilds + sourcePath: 'docs/example/atlas/data.mjs', + buildCmd: 'bun docs/example/atlas/build.mjs', + stats: [{ k: 'System', v: 'example · v0' }, { k: 'Model roles', v: '2' }], // static top-strip stats; chapter/shown/questions are added automatically + intro: `_**This file is the living source of truth for the design.** The interactive atlas is built from the same data._`, + onePara: `One paragraph a newcomer can read in 30 seconds: what the system is, what the loop is, what is not built yet.`, + costModel: ['Optional: cost assumptions and a table. Leave [] to omit.'], + deepDive: '', // optional: summary + links to research/ + platformGives: 'What the runtime/framework provides for free.', + weOwn: 'What we have to build ourselves.', + filesystem: `apps/example/\n agent/…`, +}; + +// Decisions render as the SYSTEM.md table and as chapter-10's "Decisions locked" list. +export const DECISIONS = [ + { axis: 'Runtime', decision: 'What and why, in one line', adr: '[0001](./adr/0001-slug.md)' }, +]; + +export const GROUPS = [ + { id: 'loop', title: 'The main loop' }, + { id: 'mem', title: 'Memory' }, + { id: 'sup', title: 'Supporting the loop' }, + { id: 'off', title: 'Not yet switched on' }, +]; + +// Structure = one isometric box. Fields: +// id/code: 1–2 letters shown on the box · name · short (≤14 chars, canvas label) · group +// gx,gy: grid position · w,d: footprint · h: height px · kind: box|tall|store|cards|slab|screen|gate|job +// ghost: true → dashed "designed for, not built" +// one: one-sentence summary (shown first) · what: plain description · how: implementation (may use <code>, <mark>) +// steps: [[name, desc], …] → the "go inside" view +// cond: questions — string (open) | {q, r} (resolved, r = answer + date) | {q, to} (routed to a named next step) +export const NODES = [ + { id: 'U', code: 'U', name: 'Web chat', short: 'WEB CHAT', group: 'loop', gx: 1.5, gy: 7.5, w: 2, d: 2, h: 44, kind: 'screen', + one: 'The page where you talk to the agent.', + what: 'Plain-language description for a non-engineer.', + how: 'Implementation with <code>identifiers</code> and <mark>key phrases</mark>.', + steps: [['Open', 'Create or continue a session.'], ['Stream', 'Render deltas.']], + cond: ['Where does the page live?', { q: 'Auth scheme?', r: 'Reuse existing session JWT (2026-01-01).' }] }, + { id: 'I', code: 'I', name: 'Root agent', short: 'AGENT', group: 'loop', gx: 10, gy: 2.5, w: 3, d: 3, h: 64, kind: 'tall', + one: 'The brain — one durable conversation per person.', what: '…', how: '…', steps: [['turn.started', '…'], ['Model call', '…'], ['Tools', '…'], ['Stream', '…']], cond: [] }, + { id: 'M', code: 'M', name: 'Memory', short: 'MEMORY', group: 'mem', gx: 6.5, gy: 9.5, w: 3, d: 3, h: 24, kind: 'store', + one: 'What the agent knows about you.', what: '…', how: '…', steps: [['Write', '…'], ['Read', '…']], cond: [{ q: 'Vendor?', to: 'Memory deep dive' }] }, + { id: 'P', code: 'P', name: 'Proactive', short: 'PROACTIVE', group: 'off', ghost: true, gx: 12.5, gy: -1, w: 2, d: 2, h: 34, + one: 'Later: the agent reaches out on a schedule.', what: '…', how: '…', steps: [['Tick', '…']], cond: ['Notification etiquette.'] }, +]; + +// Flows for the final "whole system" chapter. Hop = [from, to, label, payload, bend('xy'|'yx')] +export const FLOWS = [ + { id: 'turn', name: 'One turn', hops: [ + ['U', 'I', 'user message', { message: 'can you move my 3pm?' }, 'yx'], + ['I', 'M', 'recall', { query: 'move my 3pm', k: 12 }, 'xy'], + ['M', 'I', 'memories', { hits: 2 }, 'xy'], + ['I', 'U', 'message.appended', { delta: 'Sure —' }, 'yx'], + ] }, +]; + +// Chapters = progressive disclosure. Each reveals a few structures and runs ONE small flow among revealed ones. +// The last chapter has reveal: [] and flow: null → shows everything with a flow picker. +export const CH = [ + { id: 'you', title: 'You and the agent', reveal: ['U', 'I'], + lede: `Strip everything away and this is the system: you type, it answers.`, + story: `<p>Two or three sentences. <mark>Highlight</mark> the one idea this chapter adds.</p>`, + flow: [['U', 'I', 'user message', { message: '…' }], ['I', 'U', 'reply', { delta: '…' }]] }, + { id: 'know', title: 'Knowing you', reveal: ['M'], + lede: `Before answering, the agent recalls what it knows about you.`, + story: `<p>…</p>`, + flow: [['U', 'I', 'user message', { message: '…' }], ['I', 'M', 'recall', { k: 12 }], ['M', 'I', 'memories', { hits: 2 }], ['I', 'U', 'reply', { delta: '…' }]] }, + { id: 'later', title: 'Later', reveal: ['P'], + lede: `Designed for, not switched on.`, story: `<p>…</p>`, + flow: [['P', 'I', 'scheduled turn', { kind: 'morning_brief' }]] }, + { id: 'all', title: 'The whole system', reveal: [], + lede: `Everything at once, for free exploration.`, + story: `<p>Choose which flow runs (bottom left). Hover anything; click to pin; → goes inside. The <mark>Open questions</mark> tab lists every question by ID.</p>`, + flow: null }, +]; + +// "How it's built" tab with nothing selected (HTML). +export const HOW_HTML = `<div class="eyebrow">Example · v0</div><h1 class="t">How it's built</h1><div class="sub">the shape and what sits around it</div> +<h3 class="sec">Filesystem</h3><pre>apps/example/…</pre>`; diff --git a/optional-skills/creative/system-atlas/assets/template.html b/optional-skills/creative/system-atlas/assets/template.html new file mode 100644 index 0000000000..52f1aab41c --- /dev/null +++ b/optional-skills/creative/system-atlas/assets/template.html @@ -0,0 +1,423 @@ +<!doctype html> +<meta charset="utf-8"> +<title>__TITLE__ + + + +
    +
    +
    +
    + + + + + +
    +
    +
    + +
    + + + + + + + +
    +
    +
    +
    +
    + +
    +
    + enter / ] next chapter[ backhover to readclick to pin→ go inside← come outclick a dot to inspect its packet +
    +
    + + diff --git a/optional-skills/creative/system-atlas/references/design-language.md b/optional-skills/creative/system-atlas/references/design-language.md new file mode 100644 index 0000000000..12c7f76746 --- /dev/null +++ b/optional-skills/creative/system-atlas/references/design-language.md @@ -0,0 +1,34 @@ +# Atlas design language + +When to load: before filling `data.mjs` or touching `template.html` — layout, palette, isometric grammar, shapes by role, labels, copy rules, and the chapter recipe live here. + +The reference was a "codebase as interactive isometric diagram" screenshot: khaki paper, black hatched isometric structures, a left index of components, a right panel with *What it does / How it's built / Condition*, moving dots that are data packets you can inspect, hover to read, go inside a structure to see its steps, pan/zoom. Keep that grammar. + +## Layout + +- **Top strip** — stats (system, model roles, chapter n/N, structures shown n/N, questions open·routed·resolved) + controls: `◂ Back`, `Next ▸` (primary), `‖ Pause / ▸ Play`, `Trace one step`, `Refit`. +- **Left index** — grouped buttons (code · name · count). Unrevealed structures dimmed with `ch N` (click → jump to that chapter). New-in-this-chapter gets a dashed outline. Ghost (not built) = dashed border. +- **Canvas** — isometric SVG, pan by drag, wheel zoom, `+/−`. Chapter rail top-left (numbered squares + title). Flow picker bottom-left on the last chapter only. +- **Right panel** — tabs *What it does / How it's built / Open questions*. Nothing selected → the chapter story (title, lede, 2–3 sentences, "New in this chapter" chips, Back/Next). Structure selected → eyebrow (code · pinned/hovering · new), name, status chip, one-sentence `one`, then `Read more` and `Steps in execution` as `
    `. Packet selected → route + representative JSON payload. +- **Hint bar** — keys: `enter / ] next chapter · [ back · hover to read · click to pin · → go inside · ← come out · click a dot to inspect`. + +## Palette and type + +Paper `#E6DFBE` · ink `#17170F` · muted `#6E6B54` · rule `#B9B293` · face `#EFE9CC` · grid `#CFC8A3`; dark theme swaps to dark olive paper `#1E1D15` / pale ink `#E6DFBE`. Tokens on `:root`, redefined under `prefers-color-scheme: dark` (guarded `:not([data-theme="light"])`) and `[data-theme="dark"]`. One face: IBM Plex Mono (Google Fonts) with a monospace fallback. Key phrases use `` = ink background, paper text. Buttons: 1.5px ink border + 2px hard shadow; primary = inverted. + +## Isometric grammar + +- Tile 72×36; `P(gx,gy,z) = [(gx−gy)·36, (gx+gy)·18 − z]`. Structures sorted by `gx+gy+w+d` for painter's order. Hops are ground-plane polylines with diamond bend markers; route from footprint centre to centre with one bend (`xy` or `yx`); **return hops take the other bend** so request and reply dots don't overlap. +- **Shapes by role** (the user asked for "better box shapes"): `tall` = the brain (big block with a ridge line); `store` = three stacked drums (memory, ledgers, directories); `cards` = a deck of five thin slabs (tools); `slab` = wide flat hatched top (existing backend); `screen` = thin slab with an inset rectangle and text lines (surfaces: web chat, mobile, device); `gate` = box with a dark band (confirm/approval); `job` = hatched-top box (scheduled passes); `box` = everything else. Ghosts: dashed outline, no fill. +- **Labels** (the user asked for "better labelling"): a 1–2-letter code chip on the top face **and** a readable uppercase `short` name (≤14 chars) on a paper-coloured tag under the front corner of every structure. Ghost labels dashed/muted. +- New-in-chapter: pulsing dashed halo on the ground footprint (respect `prefers-reduced-motion`). Selected: top face tinted + chip inverted + label inverted. +- Packets: ink dot with paper stroke; label visible on chapters 1–N−1 (always) and on hover/selection in the last chapter; clicking pauses everything and opens the payload. Dot pauses briefly at each hop and longer at loop start. +- Inside view: steps laid diagonally (`gx 2+i·3.4, gy 2+i·0.6`, 2×2 footprint) with a single packet walking them; breadcrumb replaces the rail; `← Come back out`. + +## Copy rules + +Plain words from the person's side (per the glossary): "confirm card" not "HITL prompt". Structure names are nouns; `one` is a single sentence; `what` is for a non-engineer; `how` names files, tables, APIs with ``; `cond` items are questions or tasks, one line each. Chapter ledes are one sentence; stories 2–3 sentences with one `` idea. Numbers carry their date and source. + +## Progressive-disclosure recipe + +1. You and X (2 structures, one hop each way) → 2. Knowing (context + memory) → 3. Doing (tools + backend) → 4. Asking first (gate) → 5. Learning (hooks, signals, log) → 6. Reflecting (nightly job) → 7. Many voices (characters + directory) → 8. Keeping it honest (evals, o11y) → 9. Later (ghosts) → 10. The whole system (flow picker). Adapt the nouns; keep the shape: each chapter adds ≤3 structures and one flow that only touches revealed structures. diff --git a/optional-skills/creative/system-atlas/references/process-and-lessons.md b/optional-skills/creative/system-atlas/references/process-and-lessons.md new file mode 100644 index 0000000000..8868da6ef1 --- /dev/null +++ b/optional-skills/creative/system-atlas/references/process-and-lessons.md @@ -0,0 +1,53 @@ +# Process and lessons + +When to load: before your first feedback round, a deep dive, or when deciding docs layout — this is the session-by-session record the skill was distilled from, plus the README table, the subagent deep-dive pattern, cost-model habits, and things that bit. + +From the session this skill was distilled from: one agent-architecture atlas, built and then reworked across several rounds of feedback. + +## How the session actually went — and what to repeat + +| Step | What happened | Repeat / avoid | +|---|---|---| +| Inputs | Fetched the vision doc; looked for a whiteboard photo (not attached — asked, moved on); the user forbade one prior-art branch mid-way | Ask which prior art is allowed; never assume | +| Runtime digest | A subagent read the framework's bundled docs against 13 concrete design questions and returned a ~2.5k-word primer with gotchas and a BYO list | Do this before proposing structure; cite the primer's gotchas in the atlas | +| Discussion | Proposed 7 structures mapped to runtime primitives; 7 sharp questions; user answered with one-liners | Take defaults where the user says "defaults are fine" and say which | +| v1 atlas | Whole system at once, 21 structures, two packet flows | Fine as a first draft — but expect "hard to parse" | +| Feedback 1 | "Make it easier via progressive disclosure"; "better box shapes/labelling" | Chapters + role shapes + labels — now the default | +| Text twin | "Keep a text version in context/ADRs" → CONTEXT.md (glossary only), 7 ADRs, SYSTEM.md generated from atlas data, README | Generate the text from the atlas data from day one | +| Question rounds | The user answered by structure; several "this is not a question", "I don't get this — give a concrete example", "this is a stupid question because…" | Explain before resolving; drop non-questions; thank and move on | +| Deep dive | Scope set by the user (two vendors + a simpler DIY); three researchers on one brief with a shared usage model; synthesis with a normalized $/user/month grid; two different model cost bases | Normalize costs so columns carry the same components; fetch prices live (a cached price was wrong by 33%) | +| Rejected proposal | The synthesis proposed a "truth table in Neon, vendor as index"; the user asked what it was, then rejected it as v0 state ("YAGNI"), and later noticed the doc still described it | After a rejection, sweep every file and rewrite — a banner is not enough | +| Brain swap | The user switched the underlying model choice after an earlier decision had already been written up | Sweep every mention of the old choice; re-run the cost model; note which conclusions flip (on a cheap brain, the memory vendor dominates cost) | +| Sprawl | The user: "you now have a ton of competing docs rather than coordinated" and "the atlas is great for me — but not if it's not up to date" | One source file in the repo, one build script, both views generated, README; rebuild + republish every change | + +## Docs-folder table (copy into README.md) + +| File | Role | Edit it? | +|---|---|---| +| `atlas/data.mjs` | Single source of truth: structures, flows, chapters, decisions, questions, cost model, prose | Yes | +| `atlas/template.html` + `atlas/build.mjs` | Rendering + generator | Presentation only | +| `atlas.html` | Built atlas; republished at the same URL after every rebuild | No (generated) | +| `SYSTEM.md` | Built text twin | No (generated) | +| `CONTEXT.md` | Glossary (domain-modeling convention) | By hand | +| `adr/` | Hard-to-reverse decisions | By hand | +| `research/` | Evidence | Append-only | + +## Subagent pattern for deep dives + +- Write one `BRIEF.md`: the port/interface we own, requirements that separate candidates, a usage model (scenarios × cadences × fleet sizes) and a fixed deliverable shape (sections, citations, return only a ≤250-word summary + grid + path). +- One subagent per candidate via `delegate_task`, in parallel, writing reports to files; the main agent synthesizes (fit table, normalized cost grid, verdict, per-question resolutions, "considered and rejected"). +- Copy reports into the atlas home's `research/`; fold resolutions into `data.mjs` as `{q, r: '… (from the deep dive, date)'}`. + +## Cost-model habits + +- Always state: model price with fetch date and source, calls per turn, tokens per call (cached vs not), output tokens incl. thinking, turns/day scenarios, fleet sizes. +- Present at least two brain bases if the choice is open; the memory/vendor share of the bill flips with the brain price. +- A nightly job can use a batch API at 50% off; say so. + +## Things that bit + +- The published file needs `` at the top, or the arrows render as mojibake. +- `fitView` with a zero-size rect produced a negative scale once a paused-tab tween resumed; guard and cancel tweens. +- Some in-app browsers render `file://` as a static snapshot (no scripts, no fonts) — serve the folder with a static server and verify there, not from disk. +- Bash heredocs with large HTML/JS are brittle; write files with `write_file`, patch with small Python/Node scripts, and keep the data block as JSON-serializable objects so scripts can mutate it safely. +- Index badges count only open questions; keep IDs stable by never deleting a question — resolve it or mark it dropped. diff --git a/website/docs/reference/optional-skills-catalog.md b/website/docs/reference/optional-skills-catalog.md index eb659ff542..74aba30b71 100644 --- a/website/docs/reference/optional-skills-catalog.md +++ b/website/docs/reference/optional-skills-catalog.md @@ -78,6 +78,7 @@ hermes skills uninstall | [**simple-english**](/docs/user-guide/skills/optional/creative/creative-simple-english) | Rewrite text to ASD-STE100 Simplified Technical English. | | [**sketch**](/docs/user-guide/skills/optional/creative/creative-sketch) | Throwaway HTML mockups: 2-3 design variants to compare. | | [**social-media-content-calendar**](/docs/user-guide/skills/optional/creative/creative-social-media-content-calendar) | Plan multi-platform social campaigns: briefs to posting. | +| [**system-atlas**](/docs/user-guide/skills/optional/creative/creative-system-atlas) | Build explorable isometric architecture atlases as HTML. | | [**tldraw-offline**](/docs/user-guide/skills/optional/creative/creative-tldraw-offline) | Drive and script tldraw offline canvases with an agent. | | [**unreal-mcp**](/docs/user-guide/skills/optional/creative/creative-unreal-mcp) | Automate Unreal Engine editor scenes, actors, and renders. | diff --git a/website/docs/user-guide/skills/optional/creative/creative-system-atlas.md b/website/docs/user-guide/skills/optional/creative/creative-system-atlas.md new file mode 100644 index 0000000000..27f08b0f2b --- /dev/null +++ b/website/docs/user-guide/skills/optional/creative/creative-system-atlas.md @@ -0,0 +1,105 @@ +--- +title: "System Atlas — Build explorable isometric architecture atlases as HTML" +sidebar_label: "System Atlas" +description: "Build explorable isometric architecture atlases as HTML" +--- + +{/* This page is auto-generated from the skill's SKILL.md by website/scripts/generate-skill-docs.py. Edit the source SKILL.md, not this page. */} + +# System Atlas + +Build explorable isometric architecture atlases as HTML. + +## Skill metadata + +| | | +|---|---| +| Source | Optional — install with `hermes skills install official/creative/system-atlas` | +| Path | `optional-skills/creative/system-atlas` | +| Version | `1.0.0` | +| Author | Harshyt Goel (adapted by Nous Research) | +| License | MIT | +| Platforms | linux, macos | +| Tags | `architecture`, `diagrams`, `isometric`, `documentation` | +| Related skills | [`architecture-diagram`](/docs/user-guide/skills/bundled/creative/creative-architecture-diagram), [`excalidraw`](/docs/user-guide/skills/optional/creative/creative-excalidraw) | + +## Reference: full SKILL.md + +:::info +The following is the complete skill definition that Hermes loads when this skill is triggered. This is what the agent sees as instructions when the skill is active. +::: + +# System Atlas Skill + +An atlas is one data file (`data.mjs`) that renders two views: an **interactive isometric map** (a single self-contained `atlas.html` — hover to read, click to pin, go inside for steps, moving data packets you can inspect, chapters that reveal the system a few structures at a time), and a **generated text twin** (`SYSTEM.md`) with the decisions table, every structure, the flows, and the open questions by ID. The data file is the only thing anyone edits; both views rebuild from it. It sits beside a hand-written glossary (`CONTEXT.md`) and ADRs. + +**Does:** interactive architecture maps with progressive disclosure, question tracking across feedback rounds, a generated text twin, and a repeatable update loop. +**Doesn't:** static one-off diagrams (use the architecture-diagram or excalidraw skill), finished systems that only need a README, or a single diagram for a PR. + +## When to Use + +Use whenever someone wants to discuss, design, review, or explain an architecture visually — "make an atlas", "map the system", "make the architecture explorable", "visualize the codebase/agent/pipeline so we can talk about it", "a diagram I can click around", "walk me through how it fits together" — or when an architecture discussion is producing a pile of open questions that need tracking across feedback rounds. Also use it to update an existing atlas after decisions change. Best when the system is new enough that vocabulary, decisions, and questions are still moving and there will be more than one feedback round. + +## Prerequisites + +- Node.js (any recent version; the build uses only `node:fs`, `node:path`, `node:url` — no npm install needed). +- A static server for verification (`npx serve` or `python3 -m http.server`). + +## How to Run + +```bash +mkdir -p /atlas +cp /assets/{template.html,build.mjs} /atlas/ +cp /assets/data.example.mjs /atlas/data.mjs # then fill it in +node /atlas/build.mjs # writes ../SYSTEM.md and ../atlas.html +``` + +Every field of the data file is documented in `assets/data.example.mjs`. + +## Quick Reference + +| File | Role | Edit it? | +|---|---|---| +| `atlas/data.mjs` | Single source of truth: structures, flows, chapters, decisions, questions, prose | Yes | +| `atlas/template.html` + `atlas/build.mjs` | Renderer + generator | Presentation only | +| `atlas.html` | Built atlas; republish at the same URL after every rebuild | No (generated) | +| `SYSTEM.md` | Built text twin | No (generated) | +| `CONTEXT.md` | Glossary, one line per noun | By hand | +| `adr/` | Hard-to-reverse decisions | By hand | +| `research/` | Deep-dive evidence | Append-only | + +## Procedure + +Follow the order — each step was earned by a correction the first time round. + +1. **Read the inputs before drawing.** The vision doc, the repo's existing surfaces, and whatever prior art the user allows (ask — they may forbid a branch or a source). If you will build on a framework, read its docs first; hand long docs to a subagent via `delegate_task` with your specific design questions and have it return a primer with gotchas and a "what it does not give us" list. Drawing before this produces boxes that don't map to anything real. +2. **Discuss before drawing.** Propose the structure in chat, mapped to the runtime's real primitives, and ask only the questions you cannot derive from the repo. Take defaults for the rest and say which. +3. **First atlas — the whole system.** Copy `assets/` into the atlas home (rename `data.example.mjs` to `data.mjs`), fill the data, build with `node`, publish. **Where the atlas home is depends on the repo's docs policy** — ask before committing anything. Docs-friendly repos: `docs//atlas/` in-tree. Repos that commit only ADRs and `CONTEXT.md`: put the atlas, `SYSTEM.md`, and `research/` in a git-ignored scratch dir and attach `SYSTEM.md` + research to the spec issue when published. (Committing the whole set once produced a 3,900-line docs PR and four review rounds reconciling three restatements of one design.) Load the design-md or architecture-diagram skill via skill_view for HTML-artifact guidance if useful; read `references/design-language.md` for the visual rules either way. +4. **Progressive disclosure.** A whole system at once reads as noise. Ten-ish chapters; each adds at most three structures and runs one small flow that only touches revealed structures; the last chapter shows everything with a flow picker. Unrevealed structures stay in the index, dimmed, with their chapter number. Panels are summary-first: one sentence, then *Read more* and *Steps* folded. +5. **Shapes and labels.** Letters on boxes are not enough. Give each role a shape and put a readable name label on the canvas under every structure — see design-language. +6. **Text twin.** `CONTEXT.md` is a glossary and nothing else (the nouns, one line each); ADRs only for decisions that are hard to reverse, surprising without context, and the result of a real trade-off — these two are the in-tree pieces. `SYSTEM.md` is generated and `research/` holds evidence; both live with the atlas (scratch dir or `docs/`, per step 3). Don't open issues unless asked. +7. **Feedback by question ID.** Every question is `Q-` with a state: open (a string), resolved `{q, r}` (answer + date), or routed `{q, to}` (handed to a named next step). Record the user's words. If they call something "not a question", drop it; if they say "I don't get this", explain with a concrete example *before* resolving. After each round: rebuild, republish, update memory. +8. **Deep dives feed back.** Research with subagents (`delegate_task`) against one shared brief (the interface we own, the requirements that separate candidates, a usage model for cost, a fixed deliverable shape). Write a synthesis with a normalized cost/fit grid. Fold resolutions into the data as `{q, r: '… (from the deep dive, date)'}`. If the user rejects a proposal, sweep *every* file and rewrite — a banner on top of a stale section is not enough. +9. **Keep it current.** One source, rebuild and republish after every change, never hand-edit generated files, and leave a `README.md` in the docs folder explaining the set (table in `references/process-and-lessons.md`). + +## Publishing + +`atlas.html` is one self-contained file — no build step, no external assets beyond a Google Fonts stylesheet. Serve the folder with any static server (`npx serve`, `python3 -m http.server`) and hand over the URL, or let the repo's pages host serve the committed file. One URL, republished after every data change, never a second copy. If you keep a stable published URL, put it in `META.artifactUrl` so `SYSTEM.md` links to it. + +## Pitfalls + +- Keep `` first and `` immediately after — otherwise quirks mode and mojibake arrows. +- The renderer rebuilds its whole scene on every draw: a stray `render()` in a hover handler detaches the element under the cursor and the browser stops synthesising clicks — the map looks perfect in a screenshot while nothing responds. +- Some in-app browsers render `file://` as a static snapshot; verify via a static server, not from disk. +- Never delete a question — resolve or mark it dropped, so IDs stay stable. +- After every decision, grep the outputs for stale words (`pending`, the old model name, the rejected design) — the person reads everything. +- Large HTML/JS via shell heredocs is brittle; use `write_file` and keep the data block JSON-serializable. + +## Verification + +- `node /atlas/build.mjs` exits 0 and writes both `SYSTEM.md` and `atlas.html`. +- Syntax-check the built script (`new Function(js)`), then open the served page in a real browser at ~1280×800; check a first chapter, a middle chapter, the last chapter, an inside view, and the light theme. +- Click a structure and confirm the panel says **pinned** and offers *Go inside*; click a packet dot and confirm the payload opens. +- Every structure has `one`, `what`, `how`, a `short` label, a role `kind`, and its questions; ghosts are marked; chapters exist with per-chapter flows; the last chapter is the whole system. +- `SYSTEM.md` carries the decisions table, the question index with IDs and states, and the "how this file is maintained" footer. +- Project memory records the atlas URL, docs paths, locked decisions with dates, what the user rejected and why, and the next step. diff --git a/website/sidebars.ts b/website/sidebars.ts index 69288dc970..c9cabd8eaa 100644 --- a/website/sidebars.ts +++ b/website/sidebars.ts @@ -374,6 +374,7 @@ const sidebars: SidebarsConfig = { 'user-guide/skills/optional/creative/creative-simple-english', 'user-guide/skills/optional/creative/creative-sketch', 'user-guide/skills/optional/creative/creative-social-media-content-calendar', + 'user-guide/skills/optional/creative/creative-system-atlas', 'user-guide/skills/optional/creative/creative-tldraw-offline', 'user-guide/skills/optional/creative/creative-unreal-mcp', ],