DWSD.md

The document header — title: and tags: (all five DSLs)

All five dwsd DSLs — board, flight route, topology, org chart and units — carry the same document-level header: an optional title: and an optional descriptive tags: list. Same keys, same meaning, same shape, in all five. (Board, route and topology established the convention; the two Phase-41 structure views inherit it unchanged.)

All five DSLs paint the header. The header is data in every DSL and every view paints it the same way: title: as a heading on the left, tags: as chips on the right, above the content, over a white canvas. The units view has done so since Phase 41; the org chart since Phase 41’s gap-closure round (the close-out walk asked for the same look as the topology). With neither key a view reserves no header band. See the org chart reference and the units reference.

Dark theme. In the editor preview under a dark theme the canvas is transparent and the title takes the editor’s foreground color, on all five kinds. Every export stays white with the dark #333333 title: PNG, SVG, the copied image, the CLI, VS Code’s Markdown preview and the published example pictures.

title: Team Board — Q3
tags: [delivery, squad-aurora]
columns:
  - ToDo
  - Doing
  - Done
title: Feature Delivery
tags: [strategy, flsa]
for: idee
title: Bakery Operations
tags: [ops, pilot]
mode: declared

title: — the document name

title: is optional in all five DSLs. It names the document; it does not declare what kind of document this is. The artifact type is already carried by the file extension (.dwsd-board / .dwsd-flightroute / .dwsd-topology / .dwsd-orgchart / .dwsd-units) and by the fence tag (```dwsd.board), so a type-named key would only restate it redundantly.

Missing values are represented honestly

When title: is absent, the field is omitted — not set to an empty string, not set to a placeholder. This is one convention across all five DSLs, so a consumer asks the same question everywhere:

'title' in ast // false when the document has no title, in ALL five DSLs
ast.title // undefined — never ''

The same rule governs tags:: absent means omitted, never an empty list standing in for “none”. Renderers that need to show something for an untitled document decide that at render time (the board preview shows an honest empty state); the AST never invents a value the author did not write.

tags: — descriptive chips

tags: is a list of descriptive category strings, available at document level in all five DSLs. A scalar string is accepted as a one-element list. Tags are descriptive only — they carry no color tint. (On boards, the tint is the separate, column-scoped status-category: concern; see Columns.)

Board has carried doc-level tags: for some time. Route and topology gained it in Phase 27 — route previously had no tag concept at all, and topology had no document-level tags field.

Route’s tags are DOCUMENT level only

Route accepts tags: only on the document, deliberately. There are no band-level or stage-level route tags, and this is a scoping decision rather than an unimplemented feature:

Colour and information belong only where they carry meaning.

At a stage, a tag would merely repeat what the band position already says. The shared document header is the one place a route tag adds something the diagram does not already show.

Retired keys — board: and route:

Before Phase 27 the board and route document titles were authored with type-named keys. Both are retired with no alias: there is exactly one spelling per concept, and the old spellings are a hard error rather than a silently-accepted synonym.

DSLRetired keyDiagnostic codeSeverity
boardboard:board.retired-keyerror
flight routeroute:route.retired-keyerror
topology(none — topology’s key was always title:)——

Each names its own fix, verbatim:

`board:` is retired — rename it to `title:` to name this board
`route:` is retired — rename it to `title:` to name this route

The diagnostics are emitted by the parser, and the retired key’s value is dropped rather than read — so a document authoring the retired key gets the error and no title, never a title that quietly still works.

Two things the retired-key error deliberately does not do:

  • It does not fire on a nested key. Only a board: / route: at the root of the document is the retired document-title key. An indented board: — such as a route’s bound-to: > boards: > - board: "[[x]]" binding — is a different, legitimate key and is untouched.
  • It is orthogonal to value handling. title: 42 is not a retired-key problem; the parser stays tolerant and simply omits the field.

Topology never had a retired document-title key: it authored title: from the start, which is why the other two converged onto its spelling.

Reading the header generically

Because all five ASTs agree on title and tags, one accessor reads any of them:

import { getDocumentTitle, getDocumentTags } from '@worksystems-design/dwsd-dsl';
getDocumentTitle(ast); // string | undefined — board, route, topology, org chart, or units
getDocumentTags(ast); // string[] | undefined — board, route, topology, org chart, or units

The accessor takes the structural { title?, tags? } shape, so the two Phase-41 ASTs (OrgchartAst, UnitsAst) pass without a change.

This is the point of the convergence: a consumer that wants “the document’s title and tags” no longer branches per DSL.

See also

Like what you see? → Start — build your own org folder in ~2 min

document-header.md
# The document header — `title:` and `tags:` (all five DSLs)
All five dwsd DSLs — **board**, **flight route**, **topology**, **org chart**
and **units** — carry the same document-level header: an optional **`title:`**
and an optional descriptive **`tags:`** list. Same keys, same meaning, same
shape, in all five. (Board, route and topology established the convention;
the two Phase-41 structure views inherit it unchanged.)
> **All five DSLs paint the header.** The header is *data* in every DSL and every
> view paints it the same way: `title:` as a heading on the left, `tags:` as
> chips on the right, above the content, over a white canvas. The **units view**
> has done so since Phase 41; the **org chart** since Phase 41's gap-closure
> round (the close-out walk asked for the same look as the topology). With
> neither key a view reserves no header band. See the
> [org chart reference](./orgchart/index.md#design-notes) and the
> [units reference](./units/index.md#design-notes).
**Dark theme.** In the editor preview under a dark theme the canvas is
transparent and the title takes the editor's foreground color, on all five kinds.
Every export stays white with the dark `#333333` title: PNG, SVG, the copied
image, the CLI, VS Code's Markdown preview and the published example pictures.
```dwsd.board
title: Team Board — Q3
tags: [delivery, squad-aurora]
columns:
- ToDo
- Doing
- Done
```
```dwsd.flightroute
title: Feature Delivery
tags: [strategy, flsa]
for: idee
```
```dwsd.topology
title: Bakery Operations
tags: [ops, pilot]
mode: declared
```
## `title:` — the document name
`title:` is **optional in all five DSLs**. It names the document; it does not
declare what kind of document this is. The artifact type is already carried by
the file extension (`.dwsd-board` / `.dwsd-flightroute` / `.dwsd-topology` /
`.dwsd-orgchart` / `.dwsd-units`) and by the fence tag (`` ```dwsd.board ``), so
a type-named key would only restate it redundantly.
### Missing values are represented honestly
When `title:` is absent, the field is **omitted** — not set to an empty string,
not set to a placeholder. This is one convention across all five DSLs, so a
consumer asks the same question everywhere:
```js
'title' in ast // false when the document has no title, in ALL five DSLs
ast.title // undefined — never ''
```
The same rule governs `tags:`: absent means omitted, never an empty list
standing in for "none". Renderers that need to show something for an untitled
document decide that at render time (the board preview shows an honest empty
state); the AST never invents a value the author did not write.
## `tags:` — descriptive chips
`tags:` is a list of descriptive category strings, available at **document
level in all five DSLs**. A scalar string is accepted as a one-element list.
Tags are descriptive only — they carry **no** color tint. (On boards, the tint is
the separate, column-scoped `status-category:` concern; see
[Columns](./board/columns.md#status-tint).)
Board has carried doc-level `tags:` for some time. **Route and topology gained
it in Phase 27** — route previously had no tag concept at all, and topology had
no document-level tags field.
### Route's tags are DOCUMENT level only
Route accepts `tags:` **only on the document**, deliberately. There are no
band-level or stage-level route tags, and this is a scoping decision rather than
an unimplemented feature:
> Colour and information belong only where they carry meaning.
At a stage, a tag would merely repeat what the band position already says. The
shared document header is the one place a route tag adds something the diagram
does not already show.
## Retired keys — `board:` and `route:`
Before Phase 27 the board and route document titles were authored with
type-named keys. Both are **retired with no alias**: there is exactly one
spelling per concept, and the old spellings are a hard error rather than a
silently-accepted synonym.
| DSL | Retired key | Diagnostic code | Severity |
|-----|-------------|-----------------|----------|
| board | `board:` | `board.retired-key` | error |
| flight route | `route:` | `route.retired-key` | error |
| topology | *(none — topology's key was always `title:`)* | — | — |
Each names its own fix, verbatim:
```
`board:` is retired — rename it to `title:` to name this board
`route:` is retired — rename it to `title:` to name this route
```
The diagnostics are emitted by the **parser**, and the retired key's value is
**dropped** rather than read — so a document authoring the retired key gets the
error and no title, never a title that quietly still works.
Two things the retired-key error deliberately does *not* do:
- **It does not fire on a nested key.** Only a `board:` / `route:` at the **root**
of the document is the retired document-title key. An indented `board:` — such
as a route's `bound-to: > boards: > - board: "[[x]]"` binding — is a different,
legitimate key and is untouched.
- **It is orthogonal to value handling.** `title: 42` is not a retired-key
problem; the parser stays tolerant and simply omits the field.
Topology never had a retired document-title key: it authored `title:` from the
start, which is why the other two converged onto *its* spelling.
## Reading the header generically
Because all five ASTs agree on `title` and `tags`, one accessor reads any of
them:
```js
import { getDocumentTitle, getDocumentTags } from '@worksystems-design/dwsd-dsl';
getDocumentTitle(ast); // string | undefined — board, route, topology, org chart, or units
getDocumentTags(ast); // string[] | undefined — board, route, topology, org chart, or units
```
The accessor takes the structural `{ title?, tags? }` shape, so the two Phase-41
ASTs (`OrgchartAst`, `UnitsAst`) pass without a change.
This is the point of the convergence: a consumer that wants "the document's title
and tags" no longer branches per DSL.
## See also
- [Board DSL index](./board/index.md) — the board DSL's header fields and diagnostics.
- [Topology DSL](./topology/index.md) — the topology header fields.
- [Org Chart DSL](./orgchart/index.md) · [Units DSL](./units/index.md) — the two
structure views; both paint the header.
- [Columns](./board/columns.md#status-tint) — `status-category:`, the tint concern that
is *not* `tags:`.