- This repository is typically worked on inside WSL.
- Non-interactive login shells should have
node(version 22 LTS) andpnpmavailable vianvmfrom~/.profile. - For WSL/Corepack stability, non-interactive shells should have
COREPACK_HOME=$HOME/.cache/corepack; usescripts/setup-corepack.shfor repo Corepack setup issues. - If a shell still does not see
nodeorpnpm, use:source ~/.nvm/nvm.sh && <command>
Graphviz is not required to compile and validate SDD content. It is currently needed for legacy preview flows that turn .dot output into .svg and .png artifacts.
During the renderer migration, treat this as a current legacy workflow detail, not as an architectural requirement for all future SVG or PNG rendering paths.
Install Graphviz in the environment where this workspace runs:
- VS Code Remote - WSL, WSL/Ubuntu, or native Linux: install Graphviz inside that Linux environment, typically with
sudo apt install graphviz - Native Windows-side execution: install Graphviz on Windows and ensure
dot.exeis onPATH
Verify Graphviz setup with:
pnpm run check:graphvizdot -V
Some diagram types in the past did use the Elkjs (Eclipse Layout Kernel) layout engine. The use of Elkjs is no longer being pursued.Avoid using Elkjs. Some remnants of Elkjs remain in the codebase. Elkjs project & readme: https://github.com/kieler/elkjs Elk documentation: https://eclipse.dev/elk/reference.html
- Files in
bundle/v0.1/are the machine-readable source of truth for tools. - Markdown files in
definitions/v0.1/remain explanatory commentary and rationale, and should stay consistent with the bundle. (Originally the definitions files served as the normative input to create the bundles.)
- Rule: markdown explains, bundle governs machine behavior, code executes the bundle.
- For parser, compiler, validator, projection, and renderer feature work, any machine-behavior convention that belongs to the spec must be represented in
bundle/v0.1/and consumed from the loaded bundle at runtime. - If a feature cannot yet be expressed by the bundle, do not hardcode the feature around that gap. Extend the bundle contract, bundle types, loaders, and generic runtime machinery first, then implement the feature through that path.
- Do not encode bundle conventions only in TypeScript or tests via literal keyword lists, statement names, regexes, token tables, node kinds, edge kinds, property keys, profile IDs, view IDs, semantic defaults, or feature switches that bypass bundle data.
- Parser changes must continue to flow through
loadBundle(...)andcreateParserSyntaxRuntime(bundle). Do not add ad hoc grammar, token, or statement parsing branches that sidestep the syntax runtime just to make a new feature work. - Prefer generic bundle-reading mechanisms over feature-specific branches. If code branches on a current spec identifier, justify why that identifier is architectural code ownership rather than bundle-owned data.
- A feature is not complete until a reviewer can point to: the bundle file(s) that encode the behavior, the runtime path that consumes those bundle fields, and tests that prove behavior depends on bundle content rather than hidden code defaults.
- Bundle-only edits should be able to change intended runtime behavior. If changing the relevant bundle data would not change runtime behavior, treat that as a bundle-authority failure.
- Examples, snapshots, and goldens are downstream evidence only. They may demonstrate behavior, but they do not establish the rule; the bundle does.
- Prefer running Node-based commands from repo root.
- For Vitest and any command that may create temporary files, set:
TMPDIR=/tmp - Recommended examples:
TMPDIR=/tmp pnpm testTMPDIR=/tmp pnpm sdd --helpTMPDIR=/tmp pnpm sdd show bundle/v0.1/examples/outcome_to_ia_trace.sdd --view ia_place_map
- In this WSL setup, default temp resolution may point at
/mnt/c/TEMP, which can fail withEACCES. TMPDIR=/tmpavoids that problem and should be the default for test runs.
To enable LLM workflow integration with SDD, we recently created a (Codex-) Skill, a helper-app that assists the skill, and shared authoring infrastructure that supports the helper app and the future future MCP server.
We also recently transitioned some project documentation from README files in sub-folders of the repo to the documentation website of the project at https://knutopia.github.io/Structured-Design-Documents/
The current project goal is to help people (humans) create SDD content by providing a guided authoring experience.
- Preserve parser, compiler, validator, and projection behavior unless the selected migration step explicitly says otherwise.
- Keep projection as the semantic boundary between graph semantics and rendering technology. Do not push layout, routing, text wrapping, or SVG structure into parsing, compilation, validation, or projection.
- Keep the staged renderer pipeline explicit:
projection -> RendererScene -> MeasuredScene -> PositionedScene -> SVG -> PNG. - Keep renderer-owned scene contracts backend-agnostic. Do not store final coordinates, final line breaks, ELK JSON, DOT text, Mermaid text, or SVG strings in
RendererScene. - Treat DOT text rendering, Mermaid text rendering, and Graphviz-backed preview rendering as
LEGACYrenderer paths during the migration. - Preserve
LEGACYoutputs unless the selected migration step explicitly changes that behavior. - Make SVG the first-class artifact backend for the new staged path. Keep PNG as rasterization derived from SVG rather than a separate scene renderer.
- Treat text measurement, text wrapping, width-band policy, overflow policy, theme tokens, layout strategies, routing, and renderer diagnostics as shared renderer infrastructure. If a view exposes a gap, fix the shared layer rather than patching the view with one-off logic.
- Avoid the failed-in-practice use of ELK as a macro-layout strategy for eligible scene subgraphs.
- Preserve deterministic behavior: stable ordering, vendored font usage, canonical
LFnewlines for stored text artifacts, deterministic measurement and layout, deterministic SVG serialization, and explicit renderer diagnostics for degraded output. - Each migration step should land code, tests, and any required documentation updates, not just design notes.
-
Spec-first for doc-driven work: extract a short list of cited, non-negotiable invariants before planning or coding.
-
Separate sources by role: identify the normative contract, architectural guardrails, and visual exemplar before implementation.
-
If the authority hierarchy is unclear, stop and resolve it before coding.
-
For parser or spec-driven feature work: cite the exact bundle file(s) that should change, and name the generic runtime entrypoint that is supposed to consume them.
-
Acceptance before snapshots: do not update snapshots, goldens, or rendered corpus artifacts until the cited acceptance invariants are satisfied.
-
Snapshot refresh is evidence capture, not a way to normalize failure.
-
If tests are green but acceptance invariants still fail, report the work as incomplete.
-
If tests pass only because code duplicated bundle conventions or preserved hidden hardcoded behavior, report the work as incomplete.
-
Proof-case before generalization: for visually complex or migration work, get the explicitly referenced proof case right before broadening shared infrastructure or regenerating wider goldens.
-
Do not generalize from a failing or low-quality proof case.
-
Explicit mismatch reporting: after each substantial pass, report satisfied invariants, violated invariants, and whether the output is acceptable.
-
Do not describe output as implemented, complete, successful, materially better, or ready when core invariants still fail.
-
Decision traceability: any non-obvious placement, routing, ownership, or fallback decision must be justified against the cited contract, not only against tests or local convenience.
-
Stop conditions: stop and surface the problem instead of coding through it when output contradicts cited invariants, when goldens would need updating to hide quality regressions, or when the current strategy is producing structurally wrong output and further tuning is speculative.
-
Also stop when a feature appears to require spec behavior that the bundle cannot yet express: extend the bundle contract first instead of silently moving the rule into code.