Document Generation

mandatory

Tipos de documento gerados por categoria de objeto (Stack, Area, Sector, Module, Flow, RFC), requisitos de capa, regras de identidade visual e templates CSS para PDFs. Consultado no início da Fase 3 do `/k-housekeep`.

Spec: Document Generation

*cope:*Defines which document types are generated for each category of Koder Stack object (Stack, Area, Sector, Module, Flow, RFC), cover page requirements, and visual identity rules for generated PDFs.

*nforcement:*/k-housekeep Phase 3 reads this spec and generates or updates the full PDF bundle accordingly.


1. Object categories

The Koder Stack has five object categories that drive documentation generation. Each category has a fixed set of document types (see §2).

Category Definition Examples
*tack* The entire Koder Stack as a whole
*rea* One of the 9 canonical Areas (docs/stack/areas.md) Foundation, Data Platform, Workspace …
*ector* A named grouping of related modules within an Area (second column in areas.md) Koder Linux, KDB, Edge/Jet, Intelligence …
*odule* Any active module in the monorepo (see areas.md rows, third column) platform/id, infra/jet, apps/keys
*low* A named cross-cutting flow that spans two or more Areas (docs/stack/diagrams/flows/) auth flow, data-write flow, AI inference flow …

2. Document types per category

2.1 Stack

Document Format Source / Generator
Technical Reference PDF (A4, Typst) docs/stack/build/technical.typout/koder-stack-technical.pdf
Executive Slides PDF (A4, Typst) docs/stack/presentation/slides/main.typout/koder-stack-slides.pdf

2.2 Area

One set of documents per Area (9 total). Output folder: <N>-<area-slug>/ in the bundle.

Document Format Content
*rea Slide Deck* PDF (A4 landscape, WeasyPrint) Cover + module inventory (one card per module: icon, name, one-line description) + flows & integrations diagram + integration map (which modules call which) + sector breakdown
*rea Deep-Dive* PDF (A4 portrait, WeasyPrint) Cover + Area description + Sector table + permodule summary (35 lines each) + cross-module flow descriptions + diagrams (D2 rendered to PNG and embedded)
*rea Diagrams* PDF (A4 landscape, WeasyPrint) One page per diagram file under docs/stack/diagrams/areas/<area>.d2 (rendered via d2 --theme 0)

2.3 Sector

One set of documents per Sector row in areas.md. Output folder: <N>-<area-slug>/sectors/<sector-slug>/.

Document Format Content
*ector Slide Deck* PDF (A4 landscape, WeasyPrint) Cover + module list (icon, name, one-line description for each module in the sector) + integration diagram within the sector + relationships to other sectors
*ector Overview* PDF (A4 portrait, WeasyPrint) Cover + what the sector does + why it's grouped + module summaries + typical data flows within the sector

2.4 Module

One set per active module. Output folder: <N>-<area-slug>/<module-name>/.

Document Format Content
*eep-Dive* PDF (A4, WeasyPrint) docs/stack/modules/<module>.md — role, couplings, interfaces, status
*FC(s)* PDF (A4, WeasyPrint) Each .md / .kmd under <module>/docs/rfcs/
*anual(s)* PDF (A4, WeasyPrint) Each .md under <module>/docs/technical/, <module>/docs/user/, <module>/docs/operator/
*lide Deck* PDF (A4 landscape, WeasyPrint) Cover + what it does + architecture overview + key interfaces + status + roadmap (sourced from README + deep-dive)
*EADME* PDF (A4, WeasyPrint) <module>/README.md or <module>/README.kmd
*HANGELOG* PDF (A4, WeasyPrint) <module>/CHANGELOG.md if it exists

RFCs and Manuals may not exist for every module — skip silently if source files are absent.

2.5 Flow

One document per flow diagram file under docs/stack/diagrams/flows/.

Document Format Content
*low Diagram* PDF (A4 landscape, WeasyPrint) Cover + rendered D2 diagram + written description of the flow (from companion .md if present, else auto-generated from diagram node labels)

3. Cover page specification

*very generated PDF must start with a cover page.*No exceptions.

3.1 Cover page layout (portrait documents)

┌─────────────────────────────────────────────┐
│                                             │
│  [icon 96×96 px, centered]   ← Module only │
│                                             │
│  ────────────────────────────────────       │
│  KODER STACK                                │ ← brand line, 10pt, #94a3b8
│  <Area / Sector / Module / Flow name>       │ ← category label, 10pt, #64748b
│                                             │
│  <Document Title>                           │ ← 28pt bold, #0f172a
│                                             │
│  <subtitle / tagline — one line>            │ ← 14pt, #475569
│                                             │
│  ────────────────────────────────────       │
│                                             │
│  <Status badge if applicable>               │ ← e.g. "Pre-Alpha", "Draft"
│  <Date>  ·  Koder                           │ ← 9pt, #94a3b8
│                                             │
└─────────────────────────────────────────────┘

3.2 Cover page layout (landscape documents — slide decks, diagrams)

Same structure as portrait but centred horizontally on an A4 landscape page. Icon is 128×128px.

3.3 Icon placement rules

  • *odule documents* the module's icon.svg (rasterised to 96px for portrait, 128px for landscape) appears *entred above the title*on the cover page. Areafirst products (RFC001) may keep the canonical icon.svg at the product root (<area>/<product>/icon.svg) or at a distribution root (<area>/<product>/platform/icon.svg, <area>/<product>/app/icon.svg, <area>/<product>/app/<surface>/icon.svg). The generator resolves deepestfirst for files inside a subproduct, falling back to the product root — it must never substitute the Koder brand mark when a module-local icon.svg exists anywhere in the product tree.
  • *rea documents* use the area's representative icon if one exists under docs/stack/presentation/assets/icons/<area-slug>.svg; otherwise use the Koder brand mark (meta/brand/koder-papelaria/koder-marca.svg scaled to 96px).
  • *ector documents* use the first module icon of the sector (alphabetical by module path) as representative icon.
  • *tack documents* use the Koder brand mark.
  • *low documents* use the Koder brand mark.

*randfallback policy.*The Koder brand mark may only be used as a cover icon for *tack* *rea* and *low*documents. For any *odule*document, if no module icon.svg can be located, the generator must render the cover page *ithout any icon*rather than substitute the Koder mark. Logging a warning is mandatory; silent substitution hides missingicon bugs in the catalogue.

3.4 Icon in document body (first content page)

For *odule documents only* on the first content page (immediately after the cover), place the module icon inline at the *eft of the document title heading*(<h1>). Implemented in the HTML template as:

<h1 class="doc-title">
  <img src="{icon_path}" class="title-icon" alt="">
  {document_title}
</h1>
.doc-title { display: flex; align-items: center; gap: 14px; }
.title-icon { width: 48px; height: 48px; flex-shrink: 0; }

This applies to: Deep-Dive, RFC, Manual, README, CHANGELOG, and Slide Deck (first slide title).


4. Content requirements per document type

4.1 Area Slide Deck — required slides

  1. Cover (§3)
  2. "What is <Area>?" — 35 sentences, area ruleof-thumb
  3. Sector map — one row per Sector: sector name + modules in it (pill list)
  4. Module cards — one slide per module: icon (64px) + name + one-line description + status badge
  5. Integration map — which modules depend on which (generated from deep-dive coupling tables)
  6. Key flows — one slide per flow that is internal to this Area
  7. Connections to other Areas — list of cross-area dependencies

4.2 Module Slide Deck — required slides

  1. Cover (§3, with module icon 128px centred)
  2. "What is <Module>?" — role, one-paragraph description
  3. Architecture overview — diagram (embed docs/stack/diagrams/modules/<module>.d2 if present, else text-based)
  4. Primary couplings — table: dependency | purpose | protocol
  5. Interfaces — APIs, CLI commands, config keys (from deep-dive Interfaces section)
  6. Status & roadmap — status badge + 3-5 bullet points from backlog/STATUS

4.3 RFC — required sections

RFCs are author-written; the generator does *ot*synthesise content. The generator only:

  • Adds the cover page (§3)
  • Adds the module icon to the first <h1> (§3.4)
  • Reformats for A4 margins and page numbering

If an RFC source file already has a cover section (frontmatter with title:, status:, date:), extract those values for the cover page instead of inferring.

4.4 Manual — required sections

Same as RFC rule: generator adds cover + icon + layout, does not synthesise content.


5. Source → output mapping

The generator traverses these source locations in priority order for each module:

<module>/icon.svg               → cover icon, h1 icon
<module>/README.md              → README.pdf
<module>/README.kmd             → README.pdf (prefer over .md if both exist)
<module>/CHANGELOG.md           → CHANGELOG.pdf
<module>/STATUS.md              → included in Slide Deck slide 6
<module>/docs/rfcs
src/**/*.kmd` — source-embedded documentation (not standalone docs)
- `**/.koder-rules
.changeset/**` — release automation metadata
- `**/backlog
node_modules/**`, `**/vendor/**`, `**/target/**` — generated artefacts

**Top-level module filter:** For READMEs and CHANGELOGs, only include files at depth `<area>/<module>/README.{md,kmd}` and `<area>/<module>/CHANGELOG.md` (i.e., module root level). Sub-package READMEs (e.g. `platform/kdb/next/README.md`) are excluded unless the sub-package is itself listed as a distinct module in `areas.md`.

### 10.2 Document type table

| Code | Type | Source pattern(s) | Quantity (surveyed) |
|---|---|---|---|
| **OVW** | Overview / Deep-Dive | `docs/stack/modules
docs/rfcs/*.{md,kmd}` · `docs/stack/rfcs/**/*.{md,kmd}` | ~46 |
| **ARC** | Architecture | `**/docs/technical/architecture*.md` · `**/docs/technical/flows*.md` · `docs/stack/diagrams*.d2` | ~25 |
| **REF** | Reference | `**/docs/technical/api-reference*.md` · `**/docs/technicaldocs/technical/protocols*.md` · `**/docs/technical/configuration*.md` | ~30 |
| **OPS** | Operations | `**/docs/technical/infrastructure*.md` · `**/docs/technical/dependencies*.md` · `**/docs/technical/security*.md` · `**/docs/operator
docs/user/*.md` · `**/docs/technical/user-*.md` | ~10 |
| **REL** | Release / Changelog | `<module>/CHANGELOG.md` (root only) · `<module>/STATUS.md` | ~50 |
| **SLD** | Slides / Presentation | `docs/stack/presentation/slides/main.typ` · synthesised per-area, per-module slide decks | 1 Typst + N synthesised |
| **GOV** | Governance | `<module>/CONTRIBUTING.{md,kmd}` · `<module>/CODE_OF_CONDUCT.{md,kmd}` · `<module>/SECURITY.{md,kmd}` | ~24 |
| **BKL** | Backlog | `**/backlog/{pending,in-progress,done}
.cover        { page-break-after: always; display: flex; flex-direction: column;
                align-items: center; justify-content: center; min-height: 25cm;
                text-align: center; }
.cover-brand  { font-size: 10pt; color: #94a3b8; letter-spacing: .1em;
                text-transform: uppercase; margin-bottom: 4px; }
.cover-cat    { font-size: 10pt; color: #64748b; margin-bottom: 24px; }
.cover-icon   { width: 96px; height: 96px; margin-bottom: 24px; }
.cover-title  { font-size: 28pt; font-weight: 700; color: #0f172a;
                line-height: 1.15; margin-bottom: 12px; }
.cover-sub    { font-size: 14pt; color: #475569; margin-bottom: 32px; }
.cover-line   { width: 60%; border-top: 1px solid #e2e8f0; margin: 0 auto 20px; }
.cover-meta   { font-size: 9pt; color: #94a3b8; }

h1.doc-title  { display: flex; align-items: center; gap: 14px;
                font-size: 21pt; color: #0f172a; }
h1.doc-title .title-icon { width: 48px; height: 48px; flex-shrink: 0; }

12. Screenshot capture for UI modules

Screenshots of module UIs are embedded in Manuals (USR and REF documents) and in Module Slide Decks. This section defines how they are captured, stored, named, and embedded.

12.1 Scope — which modules get screenshots

Screenshots apply only to modules that have a userfacing UI. The generator autodetects by checking:

Signal Inferred platform
<module>/pubspec.yaml exists Flutter app (desktop + mobile + optionally web)
<module>/site/ exists with a running URL Web app
Both Flutter app with web companion
Neither No UI — skip screenshot capture entirely

Modules that *ever*get screenshots: SDKs (sdk/), CLIs, infra (infra/), data engines (data/), pure backend services with no web UI.

12.2 Storage location

All screenshots live at:

<module>/docs/assets/screenshots/
├── web-desktop/        ← Playwright, 1440×900
│   ├── 01-home.png
│   ├── 02-login.png
│   └── …
├── web-tablet/         ← Playwright, 768×1024
│   └── …
├── web-mobile/         ← Playwright, 390×844 (iPhone 14 viewport)
│   └── …
├── desktop-linux/      ← Xvfb + flutter run -d linux
│   └── …
├── mobile-android/     ← AVD + flutter run / adb screencap
│   └── …
└── screenshots.yaml    ← optional: captions + navigation steps

Screenshots are *ommitted to the repo*— they are source assets, not build artefacts. The capture pipeline regenerates them on demand (not on every housekeep — see §12.6).

12.3 Naming convention

Files are named NN-<screen-slug>.png where NN is a two-digit sequence number that controls display order in the document:

01-home.png
02-login.png
03-dashboard.png
04-settings.png

Caption is derived from the filename: 02-login.png"Login", 03-user-dashboard.png"User dashboard". Override via screenshots.yaml (see §12.5).

12.4 Automated capture pipeline — per platform

12.4.1 Web (Playwright)

Requirements: playwright Python package, Chromium browser installed.

for each viewport in [desktop(1440,900), tablet(768,1024), mobile(390,844)]:
  folder = web-desktop | web-tablet | web-mobile
  1. Launch Playwright Chromium (headless)
  2. Navigate to module URL (from koder.toml → url, or inferred from site/ hostname)
  3. Wait for networkidle
  4. Capture full-page screenshot → 01-home.png
  5. If screenshots.yaml has navigation steps, execute each step and capture
  6. Save to <module>/docs/assets/screenshots/<folder>/

Mobile viewport uses device_scale_factor=2 (retina). If a step requires login, use the test account from meta/context/credentials/ (never hardcode in spec).

12.4.2 Desktop — Flutter Linux (Xvfb)

Requirements: Xvfb, scrot, flutter SDK, module must compile for Linux.

1. Start Xvfb on display :99 (1280×800×24)
2. Run: DISPLAY=:99 flutter run -d linux --release 2>/dev/null &
3. Wait 8 seconds for app to reach idle state
4. Capture: DISPLAY=:99 scrot -u <module>/docs/assets/screenshots/desktop-linux/01-home.png
5. If screenshots.yaml has steps, simulate keypresses/clicks via xdotool
6. Kill flutter process, stop Xvfb

Limitation: only captures the initial screen unless screenshots.yaml defines navigation steps using xdotool commands.

12.4.3 Mobile — Android (AVD + ADB)

Requirements: Android SDK, an AVD named koder-pixel7 (Pixel 7, API 34), flutter SDK.

1. Check if AVD is already running: adb devices
2. If not: emulator -avd koder-pixel7 -no-window -no-audio &
3. Wait for boot: adb wait-for-device && adb shell getprop sys.boot_completed == "1"
4. Run: flutter run -d emulator-XXXX --release &
5. Wait 10 seconds for app idle
6. Capture: adb exec-out screencap -p > 01-home.png
7. Crop to device frame (strip status bar if solid colour top 72px)
8. Save to <module>/docs/assets/screenshots/mobile-android/
9. Kill flutter process (emulator stays running for reuse across modules)

12.4.4 Mobile — iOS (Simulator)

Requirements: macOS host with Xcode, an iOS simulator named iPhone 15. *nly runs on macOS*— skip silently on Linux.

xcrun simctl boot "iPhone 15"
flutter run -d "iPhone 15" --release &
sleep 10
xcrun simctl io booted screenshot <dest>/01-home.png

12.5 screenshots.yaml — navigation steps and captions (optional)

If the file <module>/docs/assets/screenshots/screenshots.yaml exists, the capture pipeline reads it for navigation instructions and caption overrides. Format:

# screenshots.yaml
module: platform/id
url: https://id.koder.dev          # override auto-detected URL
auth:                               # use credential key from meta/context/credentials/
  key: koder-id-test-user

screens:
  - id: home
    caption: "Home — sign-in options"
    steps: []                       # just load the URL
  - id: login
    caption: "Email and password login"
    steps:
      - click: "[data-testid=email-login]"
      - wait: networkidle
  - id: dashboard
    caption: "User dashboard after authentication"
    steps:
      - fill: "[name=email]"
        value: "{{auth.email}}"
      - fill: "[name=password]"
        value: "{{auth.password}}"
      - click: "[type=submit]"
      - wait: networkidle

desktop_steps:                      # xdotool commands for Linux desktop
  - xdotool key Tab                 # move focus
  - sleep 0.5
  - xdotool key Return              # activate

mobile_steps: []                    # ADB/simctl input events (future)

If screenshots.yaml is absent, the pipeline captures only the initial landing screen (one screenshot per platform).

12.6 When to regenerate screenshots

Screenshots are *ot regenerated on every housekeep*— they are expensive (require running apps, emulators). The generator regenerates a platform's screenshots for a module only when:

  1. --screenshots flag is passed explicitly to the generation script
  2. The module's screenshots.yaml changed since the last capture
  3. The <platform>/ subfolder is empty or missing
  4. The module's major version changed (detected from koder.toml or pubspec.yaml)

Otherwise, existing PNGs are reused as-is.

12.7 Embedding screenshots in documents

When generating a Manual or Slide Deck PDF for a module that has screenshots, the generator:

  1. Discovers all PNGs in <module>/docs/assets/screenshots/ recursively, sorted by subfolder then filename
  2. For *anuals (USR/REF)* inserts a "Screenshots" section after the main content with one subsection per platform (Web · Desktop · Mobile). Each screenshot is full-width with a caption below.
  3. For *lide Decks* inserts a "UI Walkthrough" slide group — one slide per screenshot, with the caption as the slide title and the image filling 80% of the slide area.
  4. For *onsolidated PDFs* screenshots are embedded in the per-module section just like in Manuals.

CSS for screenshot embedding in portrait documents:

.screenshot-section h3  { font-size: 11pt; color: #64748b; margin: 24px 0 8px;
                           text-transform: uppercase; letter-spacing: .06em; }
.screenshot-wrap        { margin: 12px 0 20px; }
.screenshot-img         { max-width: 100%; border: 1px solid #e2e8f0;
                           border-radius: 8px; box-shadow: 0 2px 8px rgba(0,0,0,.08); }
.screenshot-caption     { font-size: 9pt; color: #94a3b8; margin-top: 6px;
                           text-align: center; font-style: italic; }

12.8 Image size limits

Platform Max width Max file size
web-desktop 1440px 600 KB
web-tablet 768px 300 KB
web-mobile 390px (2× retina → 780px) 300 KB
desktop-linux 1280px 500 KB
mobile-android 1080px (native) 400 KB
mobile-ios 1179px (iPhone 15 native) 400 KB

If a captured PNG exceeds the limit, compress with pngquant --quality=65-85 before saving.

12.9 What the generator must NOT do

  • *nvent screenshots* if capture fails for any reason, log a warning and skip — do not embed a placeholder image.
  • *apture production credentials* navigation steps that require login must use test accounts from meta/context/credentials/. Never embed real user data in screenshots.
  • *apture external services* only capture UIs served by the module itself (local dev server or the module's own production URL). Do not screenshot third-party pages.
  • *lock the housekeep on capture failure* screenshot capture failure is a warning, not an error — the rest of Phase 3 continues normally.

13. Diagram visual standard (D2)

All D2 diagrams under docs/stack/diagrams/ (aerial + perarea + flows + permodule) follow the same visual language so they feel like one family of illustrations when embedded in PDFs and slide decks. This section is the source of truth — docs/stack/build/build.sh and every .d2 file must conform.

13.1 Build command

Render every .d2 file with:

d2 --theme=0 --layout=elk --pad 100 <file>.d2 <file>.svg
rsvg-convert -w 3000 <file>.svg -o <file>.png
  • *-heme=0** (Neutral Default, light) — fundo branco; containers e nós trazem a cor via style.fill` explícito. Não usar o theme 200 dark antigo.
  • *-ayout=elk** (Eclipse Layout Kernel) — muito menos cruzamentos de arestas que dagre`; arestas ortogonais e hierarquia mais limpa.
  • *-ad 100`*— respiração lateral generosa; evita que sombras sejam cortadas.
  • *asterização em 3000px*— nitidez em páginas A4 landscape de slide decks e no PDF técnico.

13.2 Shared classes (obrigatórias)

Todo .d2 com Áreas ou containers coloridos deve declarar o bloco classes abaixo no topo do arquivo, antes de qualquer nó. Isso é DRY: muda num lugar, aplica em todo canto.

classes: {
  area: {
    style: {
      border-radius: 20
      shadow: true
      stroke-width: 0
      font-size: 20
      bold: true
      font-color: "#ffffff"
    }
  }
  node: {
    style: {
      border-radius: 12
      stroke-width: 0
      font-size: 15
      font-color: "#0f172a"
      fill: "#ffffff"
      shadow: true
    }
  }
}

Containers de Área aplicam class: area; módulos/nós dentro deles aplicam class: node. Nunca repetir style.fill, style.font-color, border-radius inline em cada nó — use as classes.

13.3 Gradient fill por Área

Cada Área tem um par de cores (escuro → claro) que formam o fundo via linear-gradient. Isso dá profundidade e coesão — cores chapadas são proibidas para containers de Área.

Área Gradient fill
Foundation linear-gradient(#1e3a8a, #3b82f6)
Data Platform linear-gradient(#0f766e, #14b8a6)
Cloud Infrastructure linear-gradient(#0369a1, #0ea5e9)
Observability linear-gradient(#6d28d9, #a855f7)
Intelligence linear-gradient(#9f1239, #f43f5e)
Developer Platform linear-gradient(#a16207, #eab308)
Workspace linear-gradient(#166534, #22c55e)
Industry Solutions linear-gradient(#9a3412, #f97316)
Brand & Presence linear-gradient(#334155, #64748b)

Aplicar no container de Área:

foundation: Foundation {
  class: area
  icon: /home/koder/dev/koder/sites/foundation/icon.svg
  style.fill: "linear-gradient(#1e3a8a, #3b82f6)"
  linux: Koder Linux {class: node; icon: /home/koder/dev/koder/linux/distro/icon.svg}
  ...
}

13.4 Ícones embutidos nos nós

Cada container de Área recebe o ícone de sites/<area>/icon.svg (9 áreas têm todos). Cada nó de módulo recebe seu próprio icon.svg se existir; sem ícone, cai em pílula sótexto — *ão inventar placeholder* O `/khousekeep §1.6 já reporta módulos sem icon.svg` como ⚠️.

  • Usar *aminho absoluto*(/home/koder/dev/koder/...) — D2 v0.7 não aceita paths relativos para icon:.
  • O ícone aparece no canto do container/nó (top-left) automaticamente.

13.5 Estilo das arestas

Default para todas as arestas:

style: {stroke: "#94a3b8"; stroke-width: 2}

Arestas com label ("depends on", "authenticates", etc.) recebem estilo reforçado:

style: {stroke: "#475569"; stroke-width: 3; font-size: 14; font-color: "#334155"; bold: true}

13.6 Título do diagrama

Toda .d2 começa com um título markdown no topo. Para aerial e áreas:

title: |md
  # Koder Stack
  ## Aerial view — 9 areas · 50+ modules
| {near: top-center; shape: text; style.font-size: 36; style.bold: true; style.font-color: "#0f172a"}

Fontes menores (26/22pt) para flows individuais. Cor sempre #0f172a (slate-900) para contraste em fundo branco.

13.7 Categorias de diagrama

Categoria Path Estrutura Classes usadas
Aerial diagrams/aerial.d2 9 containers de Área, um por cor; módulos como pílulas; arestas inter-Área area + node
Area diagrams/areas/<area>.d2 1 container da Área com todos os módulos; arestas internas area + node
Flow diagrams/flows/<flow>.d2 Actors + etapas numeradas; sem containers de Área node (cor neutra ou cor da Área do actor)
Module diagrams/modules/<module>.d2 Coupling deep-dive; nós = dependências externas node

Para flows, actors de Áreas diferentes recebem style.fill individual com a cor sólida base da sua Área (não gradient — actors são pontos, não blocos). Exemplo: ator foundation/idstyle.fill: "#1e3a8a"; style.font-color: white.

13.8 Proibições

  • ❌ Tema dark (--theme=200, --theme=201) — todos os diagramas são light. Inversão automática para dark mode dos PDFs fica para iteração futura.
  • ❌ Layout dagre — sempre elk.
  • style.fill chapado em containers de Área — sempre linear-gradient.
  • ❌ Repetir estilo inline — sempre via class.
  • icon.svg de placeholder ou genérico — só ícone real do módulo ou ausente.
  • stroke-width > 15 (limite do D2) ou < 1.
  • ❌ Fontes externas via --font-regular enquanto não houver Inter/JetBrains instalados no host de build — ficar no Source Sans Pro default.

13.9 Regeneração

docs/stack/build/build.sh rerenderiza todos os .d2 para .svg + .png a cada execução do `/khousekeep §1.10. Os arquivos .svg e .png sob diagrams são **build artefacts gitignored** (docsstack.gitignore) — só o .d2 fonte entra no git. Após clone, rodar .build/build.sh` gera os assets localmente.

13.10 Pilot de referência

O diagrama canônico do estilo é docs/stack/diagrams/aerial.d2. Ao criar ou refatorar outro .d2, abrir o aerial como template e espelhar:

  1. Bloco classes no topo
  2. Título markdown com font-size 362622
  3. Containers com class: area + icon: + style.fill: "linear-gradient(...)"
  4. Nós com class: node + icon: quando existir
  5. Arestas com estilo neutro padrão (§13.5)

Source: ../home/koder/dev/koder/meta/docs/stack/specs/docs/generation.kmd