Documentation style
The tree
User documentation is one tree under docs/, organized by what the reader is doing:
| directory | mode | shape |
|---|---|---|
getting-started.md |
learning | one linear path, executed as written |
guides/ |
doing | one task per page, entered from a search result with no prior reading, executed as written |
reference/ |
looking up | exhaustive and dry; generated or drift-checked where the code knows the answer |
concepts/ |
understanding | prose about why; no commands |
contributing/ |
building | the same four modes for the contributor |
The top level holds README.md, CONTRIBUTING.md, CHANGELOG.md and LICENSE, nothing else.
The model, architecture, contributor process and Twin roadmap live in this tree. Cross-repo
strategy, proposals and dated work records live in the company workspace. A page that serves two
modes is split; a page named after a task that shipped is deleted.
A tutorial page is its own test
When a bash fence launches background work, its following text fence is the output readiness condition. The runner preserves early output and waits for all expected lines, including when the fence ends with a foreground command. This additional wait uses the expectation-bearing step's deadline; the existing background settling period is unchanged. Missing output remains a failure; the runner does not invent readiness commands.
The tutorial and every guide are executed exactly as written by
packages/cli/src/journeys/tutorials.test.ts, and nothing runs that the page does not show. The
page's fences are the steps, in order:
```bash— every non-comment line is one command the reader types, run in one shell session that persists across the page (env, cwd, background jobs). A trailing&runs a server in the background.```textright after a bash fence — what the reader sees: every line must appear in that command's output, after ports, ids, hashes and times are masked. Show the lines that matter, not the whole screen.```<lang> file=<path>— a file the reader writes at that path before going on. A page declares its own app this way (package.json,.env.example, a script), so it is self-contained. Paths are relative to the app directory in both the runner and recording, including after a shell command changes directory.- Anything else is illustration and does not run.
Every command runs literally, bun add included: the runner publishes this checkout's packages
to a registry on the machine and the page's app installs from it, so bun add -g @volter/world
puts volter on the PATH the way it does for a reader. scripts/docs-media.ts records the same
steps with vhs into docs/media/<page>/ and writes the page's Playback gallery; every page
embeds its recording at the top. A page that drifts from the product fails by line number.
Words
Use the user glossary in every user-facing page, flag and message, and
the build glossary in contributor pages. scripts/docs-language-check.ts holds
the user pages to the user words. The names that changed:
| do not write | write |
|---|---|
| shape (of a vendor) | the vendor's API |
| backing | local, remote |
| placeholder, placeholder remote | default data |
| door | endpoint, the HTTP API |
| pack, twin pack | twin; package for the npm artifact |
| attach, attachment | run, activate |
| profile | size |
| recipe | example |
| sealed world | sandbox |
| narration | summary |
| basis | base |
| key, for our credentials | token |
| a mocked SDK, a fully mocked stack | redirect the real SDK; a world |
Three nouns nest, and the README's first sentence says so: a twin is one vendor, a world is the twins an app needs running together, Volter runs worlds.
Claims
- Say what is real, deterministic, stubbed or externally dependent.
- Never describe an unmodeled operation as supported; a twin refuses it the way the vendor would.
- Never call a sandbox hermetic. Cooperative refusal is not a network boundary.
- Every example states whether it is gated (named in
scripts/twin-check.sh) or manual, and its expected runtime past a minute. - A standing document reads as present-tense truth: no history, no status sections, no amendment narrative. Git is the history; the company repo's notes are the records.
- A number in prose goes stale the day a manifest grows. Link the generated table instead.
Names
File names are what a reader would search for: lowercase, hyphenated, a task or a noun, never a project word. Headings are sentences a reader would say, not labels.
Canonical ownership
concepts/the-model.mdowns storage, branching, push and deployment semantics.concepts/worlds.mdowns lifecycle and capacity;data-and-keys.mdowns custody and access.reference/cli.md,sdk.mdandhttp-api.mdown callable surfaces; verify descriptions against implementation, not only whether method names occur.contributing/architecture.mdand the corresponding policy rules own implementation boundaries.ROADMAP.mdcontains only unresolved Twin work. Do not copy cross-repo plans into it.skills/volter-world/AGENTS.mdowns portable operator instructions;SKILL.mdlinks it.- Package READMEs own vendor-specific usage and limitations. Link shared semantics instead of repeating a storage model. Use the generated catalog for counts and protocol standing.
- The site renders
docs/directly. Its landing page introduces the product and links the tutorial and model rather than maintaining copies of them.
The changelog, dated records and captured upstream source documents are historical evidence. Do not rewrite them as current instructions. Documentation checks cover the standing entry points, guides, reference, contributor pages, package READMEs, cookbook and operator sources.