← All specs
Phase tooling plan

Spec Visualization System — Build Plan

Dedicated plan for reworking spec rendering beyond plain markdown. Fenced viz blocks, ~14 repeatable components, covers phases/schemas/ladders/flows/matrices/cards. Attacked post-compact. Keep specs portable markdown; rich components only when they add clarity.

Spec Visualization System — Build Plan

Context for fresh Claude: Shay wanted a dedicated, deep rework of how specs are visualized. Plain markdown wasn't carrying the complexity in the real specs (phase roadmaps, SQL schemas, surface maps, action ladders, flow diagrams). This plan scopes the work. Do it after compact with full force.

Goal

Specs stay portable markdown (works in any editor, readable in GitHub, no MDX lock-in) — but gain ~14 first-class visualization components that activate when a spec uses the viz:<type> fenced-block convention.

The reader of /specs/artifact-platform shouldn't see "a flat table of phases" — they should see a horizontal timeline with gates colored by status, useful-to-audience chips, and expand-to-see tasks under each. Same content, richer surface.

Rendering architecture

Syntax (in .md files)

Regular markdown paragraph.

```viz:phase-timeline
phases:
  - id: 0
    name: Stoka v1
    useful_to: Visitors
    status: shipped
  - id: 1
    name: Solo core
    useful_to: You alone, as daily-use tool
    status: active
    gate_condition: Phase 0

Another regular paragraph. [[spec:messaging]] renders as a spec-chip inline.


The `viz:<type>` fenced block is parsed as YAML. The `[[spec:...]]`, `@handle`, and `{kind:...}` inline patterns get post-processed into chips.

### Pipeline

spec.md ↓ parseFrontmatter() → { data, body } ↓ splitIntoSegments(body) → [ { type: 'md', content }, { type: 'viz', vizType, props }, ... ] ↓ for each segment: type=md → marked.parse() type=viz → route to via type registry ↓ Astro renders a stream of either

or <VizComponent {...props}/> ↓ inline post-processing (spec-chip, pseudonym-chip, kind-chip) injected via a rehype-style pass on the .md segments


### Files to create

src/lib/specs/ ├─ index.ts ← loadSpecs() (exists; move here) ├─ segment-parser.ts ← NEW: splits body into md/viz segments ├─ viz-registry.ts ← NEW: maps 'viz:phase-timeline' → PhaseTimeline component ├─ inline-processor.ts ← NEW: turns specx / @handle / kindx into chip HTML └─ types.ts ← NEW: SpecSegment, VizBlock, etc.

src/components/specs/ ├─ PhaseTimeline.astro ← phase roadmap, horizontal, with gates ├─ SchemaERD.astro ← SQL schema entity-relationship diagram ├─ SurfaceMap.astro ← surface-card grid (Stoka Across Surfaces) ├─ ActionLadder.astro ← vertical escalation ladder (mod actions) ├─ LayerStack.astro ← stacked layers (Bon Appétit / prompt architecture) ├─ ApiRoutes.astro ← HTTP-colored route cards ├─ DecisionMatrix.astro ← comparison grid (visibility, channels×events) ├─ FlowDiagram.astro ← step-by-step flows (Telegram pairing, share cascade) ├─ Ruleset.astro ← rule-cards (mod triggers + action rungs) ├─ KindCards.astro ← kind cards (artifact kinds, inbox item kinds) ├─ Exchange.astro ← terminal-styled conversation mockup (Stoka golden examples) ├─ Callout.astro ← TBD / warning / note / info semantic blocks ├─ SpecChip.astro ← inline specslug rendering ├─ PseudonymChip.astro ← inline @handle rendering └─ KindChip.astro ← inline kindconversation rendering

src/pages/specs/[slug].astro ← UPDATE: use segment renderer, not marked.parse() src/pages/admin/specs.astro ← UPDATE: same, with dark-theme variants of every component


Each viz component ships **two theme variants**: public (light-prose-friendly) and admin (dark-prose). Use `data-theme` attribute or CSS custom properties + a wrapper class.

## Component catalog (detailed)

### 1. `viz:phase-timeline`

Horizontal timeline. Each phase = a node; gates between phases shown as arrows with gate-condition text. Status colors: shipped (green-solid) · active (green-glowing) · queued (gray) · blocked (amber) · deferred (dimmed).

Data shape:
```yaml
phases:
  - id: 1
    name: Solo core
    useful_to: You alone, as daily-use tool
    status: queued
    gate_condition: Phase 0 shipped
    milestones: [optional list, shown in hover/expand]

2. viz:schema-erd

ERD for SQL schemas. Shows tables as boxes with column lists, relationships as connecting lines. Collapsible column details (click table → expand). Index/unique markers in-line. Kind-specific metadata JSON shown as sub-card.

Data shape:

tables:
  - name: identity.artifacts
    columns:
      - name: id
        type: UUID
        pk: true
      - name: pseudonym_id
        type: UUID
        fk: identity.pseudonyms.id
      - name: visibility
        type: TEXT
        default: private
        enum: [private, link_only, public_anonymous]
    indexes:
      - { on: [pseudonym_id, status] }
relationships:
  - from: identity.artifacts.pseudonym_id
    to: identity.pseudonyms.id
    label: author

3. viz:surface-map

Card grid — one card per surface. Each card has: surface name (title), Layer 3 content source, Layer 4 context, "what Stoka does" summary. Visual tie to the "one brain many masks" concept via a shared brain-icon in the center of the grid + radial connections.

Data shape:

brain: Stoka (fixed identity + voice)
surfaces:
  - name: Discovery terminal
    layer_3: RAG chunks from published content
    layer_4: page, history, interests
    role: recommends content
  - ...

4. viz:action-ladder

Vertical escalation ladder. Each rung numbered, with action name, description, reversibility indicator, admin-visibility level. Shown as actual ladder visual (rungs with increasing severity).

Data shape:

target: pseudonym | user
rungs:
  - number: 1
    name: Silent warn
    description: Pseudonym sees notice
    reversibility: automatic
  - ...

5. viz:layer-stack

Stacked layers (Bon Appétit artifact granularity, prompt architecture Layers 0-5). Each layer has a label, description, visibility/depth marker. Click to expand showing layer-specific details. Bon Appétit version: "reader appetite" scrollbar on the right showing reader depth.

Data shape:

title: Bon Appétit granularity ladder
layers:
  - name: Recipe card
    subtitle: what you scan
    description: headline · prompt · why it works · variations · tags
  - name: Method notes
    subtitle: expand once
    description: what was tried · what failed · the moment it clicked
  - ...

6. viz:api-routes

Route table/cards. HTTP method color badges (GET=blue, POST=green, PATCH=amber, DELETE=red). Auth/role badge per route. Description + example request/response (collapsible).

Data shape:

base: /api/dm
routes:
  - method: POST
    path: /threads
    auth: user
    purpose: start/resume by recipient handle
    body: { recipient_handle: string, note?: string }
  - ...

7. viz:decision-matrix

Comparison grid — rows = options, columns = properties. Each cell can be: boolean (✓/—), enum (colored pill), scalar (text), or link (to spec). Highlight the "recommended" row. Used for visibility tiers, notification channels-vs-events, model decisions.

Data shape:

rows: [Private, Link-only, Public anonymous]
columns: [Who sees it, Directory?, Stoka index?, Share-to-DM?]
cells:
  Private: ["Only author", "No", "Personal only", "Yes, grant"]
  ...
highlight: Private  # the default

8. viz:flow-diagram

Numbered step flow with branches. Each step is a node; arrows show progression. Branches (if/else) rendered as forks. Annotations along arrows (e.g., "if artifact is private: grant access"). Can be vertical or horizontal.

Data shape:

orientation: vertical
steps:
  - id: 1
    actor: User
    action: Click share button
  - id: 2
    actor: Client
    action: Opens recipient picker
  - id: 3
    actor: Client
    action: POST /api/artifacts/:id/share
    branches:
      - condition: thread exists
        next: 4a
      - condition: thread does not exist
        next: 4b
  - ...

9. viz:ruleset

Card-per-rule for moderation or any rule-based system. Each card: trigger condition (with detection snippet), action ladder rung(s) it typically escalates to, threshold visibility (public/private).

Data shape:

rules:
  - trigger: Report threshold
    detection: "N user reports on a pseudonym within window"
    rungs: [2, 3]
    threshold_visibility: private
  - ...

10. viz:kind-cards

Grid of cards representing taxonomic kinds (artifact kinds, inbox item kinds). Each card: kind icon, kind name, description, kind-specific metadata schema preview.

Data shape:

kinds:
  - id: conversation
    icon: chat-square  # icon ID from a curated set
    name: Conversation
    description: Bon Appétit conversation extract — recipe + method + source + transcript
    metadata_schema:
      - { key: recipe, type: text }
      - { key: why_it_works, type: text }
      - { key: variations, type: array }
  - ...

11. viz:exchange

Terminal-styled conversation mockup (for Stoka golden examples, Konan chat samples, DM previews). Monospace, speaker labels colored, cite blocks rendered inline.

Data shape:

speakers:
  visitor: { color: muted, prefix: "visitor" }
  stoka: { color: brand, prefix: "stoka" }
turns:
  - speaker: visitor
    text: "what is this?"
  - speaker: stoka
    text: "a terminal. i know everything published here. ask something or don't."
  - speaker: visitor
    text: "tell me about Debono"
  - speaker: stoka
    text: "it transcribes pharmacy lecture slides.\nthe interesting part is how it fails."
    cite:
      slug: debono-error-handling
      quote: "The deck pipeline doesn't retry. It remembers what broke and why."

12. viz:callout

Semantic callouts with icon + color. Variants: tbd (yellow question-mark), warning (red triangle), note (blue circle), rule (emerald lock — for "design rule"), deferred (gray arrow-right).

Data shape (or use a shorter syntax):

variant: rule
title: The Unencumbered Bar
body: |
  Every feature ships against this bar or doesn't ship.
  Optimistic UI, no modals, keyboard-first, instant pseudonym switching.

13-15. Inline chips (processed in markdown, not viz blocks)

  • [[spec:messaging]] → styled chip linking to /specs/messaging
  • @ghost-7c0a → pseudonym chip (gets hover-card in Phase 2+)
  • {kind:conversation} → kind chip with icon
  • {phase:1} → phase chip with status color

Component visual language (shared)

  • Color tokens: brand green #10b981 for primary accents, amber #fbbf24 for warnings/TBDs, red for critical, muted surface grays for chrome.
  • Typography: Inter for body, JetBrains Mono for data (table content, schema types, handles, kinds). Rule: if it's data, it's mono.
  • Iconography: Curated SVG set (Lucide-style). No emoji. Icons consistent across components.
  • Border convention: 1px solid brand-dimmed for active, 1px dashed brand-xdim for placeholder/stub, 1px solid surface-border for neutral.
  • Shadow convention: Soft elevation for cards, brand-glow only for active/selected states.
  • Animation: Micro-transitions (120-180ms) on hover/select. No scroll animations, no parallax. Subtle.

Implementation phases

Phase A — Foundation (post-compact, first pass)

  1. src/lib/specs/segment-parser.ts — splits spec body on \n```viz:<type>\n...\n```\n
  2. src/lib/specs/viz-registry.ts — type → component map
  3. src/lib/specs/inline-processor.ts — chip transforms on markdown segments
  4. Update src/pages/specs/[slug].astro to use segment renderer
  5. Update src/pages/admin/specs.astro to use same (with dark variants)
  6. Build 5 core components: Callout, SpecChip, KindChip, PseudonymChip, PhaseTimeline (the highest-impact visuals first)

Phase B — The meat (post-compact, second pass)

  1. SchemaERD, SurfaceMap, LayerStack, ActionLadder, FlowDiagram

Phase C — Final wave

  1. ApiRoutes, DecisionMatrix, Ruleset, KindCards, Exchange

Phase D — Spec rewrites

  1. Rewrite README.md + artifact-platform.md + messaging.md to use viz blocks where they replace markdown tables / ASCII / SQL blocks.
  2. Spot-adopt in stoka-bot.md where high-impact (Surface Map, Layer Stack, Exchange for golden examples).

Target specs for first visualization pass

In priority order (what will demo best):

  1. artifact-platform.md — has the Bon Appétit layer stack (perfect LayerStack demo), visibility tiers (DecisionMatrix), full schema (SchemaERD), phase plan (PhaseTimeline), kinds list (KindCards)
  2. messaging.md — Telegram pairing flow (FlowDiagram), mod action ladder (ActionLadder), notification matrix (DecisionMatrix), surface map extension, mod triggers (Ruleset)
  3. stoka-bot.md — Surface Map section (SurfaceMap), prompt architecture Layers (LayerStack), golden examples (Exchange)

Admin surface specific

The admin /admin/specs page should let the author edit viz blocks with a structured editor (not raw YAML). Phase E (post all the above):

  • Each viz block gets an "edit in structured mode" button
  • Form renderer per viz type (drag-and-drop phases on PhaseTimeline, table builder for DecisionMatrix, etc.)
  • Saves back as YAML into the viz block, preserving markdown elsewhere

This is Phase E because it's a big editor lift and the viewing experience is the immediate win.

What NOT to do

  • Don't move specs into MDX. Portability is load-bearing — specs should read cleanly in GitHub, any .md previewer, any editor. Viz blocks degrade gracefully to YAML code blocks in dumb renderers.
  • Don't use a heavy chart library. Custom SVG + CSS for every component. Consistency of feel > speed to build.
  • Don't make it React. Stick to Astro components + vanilla JS for interactivity. The site doesn't need a framework.
  • Don't retrofit every existing spec. New specs use new viz. Old specs get retrofitted opportunistically.
  • Don't over-animate. Micro-transitions only. Specs are read, not experienced.

Open questions

  1. Mermaid support? Mermaid could cover several viz types (flow diagram, ERD, timeline) with one library. But it's opinionated and doesn't match the site's visual language. Leaning: custom components, not Mermaid. Revisit if component-count feels oppressive.
  2. Editor mode for public specs? Probably not — specs are authored, not user-generated. Admin-side editor is enough.
  3. Printable / PDF export? Nice-to-have for Phase 3+. Spec components need to degrade cleanly to static for print media query.
  4. Offline rendering? The /specs build is static. No JS should be required for first paint — all viz components SSR to HTML. Interactivity (hover details, click-expand) is progressive enhancement.

Success criteria

  • Reading artifact-platform.md on /specs/artifact-platform feels like reading a well-designed technical book, not browsing a markdown file.
  • Shay can write new specs using viz blocks naturally, without thinking about rendering.
  • Components are genuinely reusable — a schema change in messaging.md is a one-line YAML edit, not a rewrite.
  • Dark admin variant looks as polished as public light variant. Not a hack; a parallel theme.

When to attack

After compact. Full force. 14 components is a real chunk of work — don't fragment across sessions if avoidable.