Knowledge Workspaces
An OKF knowledge workspace is a directory tree of Markdown documents, each carrying a
small YAML frontmatter block with a type: field drawn from a fixed vocabulary
(UmlClassDiagram, Concept, BpmnProcess, …) and — for diagram types — exactly one
` ``kuml ` fenced code block. `kuml workspace inspects, validates and renders such
workspaces.
The canonical entry point is the kuml workspace subcommand group:
kuml workspace init [--name <name>] [--mode knowledge|engineering] # scaffold a new workspace (see below)
kuml workspace info <dir> # mode + document inventory
kuml workspace validate <dir> # structural OKF conformance checks
kuml workspace render <dir> # render every ```kuml block to SVG/PNG
kuml workspace convert <src> --to okf|kts # convert between OKF notes and .kuml.kts scripts
init takes its target from the --output option (default ./<slug>), not a positional
directory argument; info, validate and render each take the workspace root as a
positional <dir>.
There are no top-level kuml validate/kuml render aliases for workspace operations —
kuml validate/kuml render operate on a single *.kuml.kts script, kuml workspace
validate/render operate on a whole document tree. Keep the two mental models separate.
kuml workspace init
kuml workspace init scaffolds a new workspace from a built-in template set — a
.kuml-workspace.toml marker plus starter documents — using the same scaffold engine as
kuml plugin init. The freshly generated workspace passes kuml workspace validate with
zero findings and renders cleanly out of the box.
kuml workspace init --name "My Club Bylaws" --mode knowledge
kuml workspace init --name "My Diagrams" --mode engineering --non-interactive
| Option | Meaning |
|---|---|
|
Human-readable workspace name. Used for the marker’s |
|
Template set to scaffold. |
|
Target directory. Defaults to |
|
Fail with a usage error instead of prompting for a missing |
|
Overwrite the target directory if it already exists and is non-empty. |
The knowledge-mode scaffold produces this tree:
<slug>/
├── .kuml-workspace.toml
├── index.md # type: KumlWorkspace
├── articles/01-introduction.md # type: Article
├── models/domain-classes.md # type: UmlClassDiagram
└── glossary/index.md # type: Glossary
kuml workspace convert
kuml workspace convert converts between OKF knowledge-workspace notes and bare
.kuml.kts engineering scripts (FT-7). The two formats share identical DSL text — an
OKF ` ``kuml ` block’s source is byte-for-byte a valid standalone `.kuml.kts body
(the same fact kuml workspace render relies on). "Convert" is therefore a text
wrap/unwrap plus frontmatter synthesis/stripping operation, not a model
re-serialization.
kuml workspace convert ./scripts --to okf --output ./vault/models # engineering -> knowledge
kuml workspace convert ./vault --to kts --output ./scripts # knowledge -> engineering
| Option | Meaning |
|---|---|
|
A single file or a directory. For |
|
Required. |
|
Output directory. Defaults to a sibling |
|
Overwrite an output file that already exists (default: skip it and report it under
|
|
Escalate |
|
Report output format, matching |
Directionality of losslessness
This is the one property to internalise before relying on convert for a real
workflow:
-
kts → okf → ktsis lossless for the DSL text. Wrapping adds only frontmatter and an H1 heading; extracting discards exactly that and nothing else, recovering the original script byte-for-byte (modulo trailing-newline normalisation — the wrapped block always carries exactly one trailing newline before the closing fence, regardless of how many the source had). -
okf → kts → okfis not lossless. The reverse round trip drops the original prose, the note’s owntitle:/tags:/other frontmatter, and any non-diagram document (Concept,Article,Glossary,KumlWorkspaceindex, …) entirely — only the diagram DSL survives. The regenerated note’stitle:and heading come from the diagram’s own name, not the original note’stitle:.
Keep prose-authored knowledge in the vault as the source of truth; use convert to
pull diagrams out for engineering-side editing, not as a way to shuttle whole documents
back and forth.
Type mapping and unmappable diagram kinds
--to okf evaluates each .kuml.kts script (the only way to know its concrete
diagram kind) and maps it to an OKF type: value. Most UML, C4, SysML 2, BPMN,
Blueprint and ERM diagram kinds have a vocabulary entry (see the type tables below).
A few UML 2.x and C4 diagram kinds do not (e.g. packageDiagram, objectDiagram,
deploymentDiagram, C4’s SystemLandscapeDiagram/DeploymentDiagram/DynamicDiagram)
— convert does not fabricate a vocabulary entry for these; it writes a deterministic
custom type: (e.g. UmlPackageDiagram) and reports OKF-C-003.
A script that declares multiple diagrams in one model only yields its first diagram
on --to okf — the same "first diagram" behaviour as kuml render.
Multi-block documents
Consistent with OKF-W-004 ("one file = one diagram"), a knowledge document with more
than one ` ``kuml ` block is split by `--to kts into <stem>-1.kuml.kts,
<stem>-2.kuml.kts, … (1-based) and reported as OKF-C-002.
Trust model
--to kts is pure text extraction and never evaluates anything — converting a
knowledge document to a script never runs its diagram code. --to okf evaluates every
.kuml.kts script to determine its concrete diagram kind, inheriting the same
arbitrary-code-execution trust model as kuml render / kuml workspace render: only
run it over scripts you already trust.
The .kuml-workspace.toml marker
An optional marker file at the workspace root declares its mode and OKF metadata instead
of leaving kuml workspace info to infer it:
[workspace]
mode = "knowledge"
name = "PZB Domain Model"
kuml-version = ">=0.30.0"
[okf]
version = "0.1"
vocabulary = "dev.kuml.okf@1.0"
strict = false
| Key | Meaning |
|---|---|
|
|
|
Free-form workspace display name. |
|
Declared kUML CLI version constraint (informational; not currently enforced). |
|
Declared OKF spec version the workspace was authored against. |
|
Declared |
|
Declared default for |
The parser is a small hand-rolled subset of TOML — comments (#), [section] headers,
and key = value lines with quoted or bare scalar values. It never throws: a malformed
or partial marker degrades to "field absent", falling back to the inference heuristic
above rather than aborting the scan.
The type: vocabulary
Every document’s frontmatter type: field is resolved against a fixed vocabulary
(current version: 1.0, 29 entries). Types with requiresKumlBlock = true must
contain exactly one ` ```kuml ` fenced code block; the others are prose/collection types.
UML
type: |
Requires a ```kuml block |
|---|---|
|
yes |
|
yes |
|
yes |
|
yes |
|
yes |
|
yes |
C4
type: |
Requires a ```kuml block |
|---|---|
|
yes |
|
yes |
|
yes |
|
yes |
SysML 2
type: |
Requires a ```kuml block |
|---|---|
|
yes |
|
yes |
|
yes |
|
yes |
|
yes |
|
yes |
|
yes |
|
yes |
BPMN
type: |
Requires a ```kuml block |
|---|---|
|
yes |
|
yes |
|
yes |
|
yes |
Knowledge (non-diagram)
type: |
Requires a ```kuml block |
|---|---|
|
no |
|
no |
|
no |
|
no |
|
no |
The vocabulary is checked into the codebase as a machine-readable contract at
kuml-docs/kuml-workspace/src/main/resources/okf/kuml-okf-vocabulary.json (id,
requiresKumlBlock, since, description per entry) and is kept in lockstep with the
OkfType enum by a dedicated contract test. An unrecognised type: value is not an
error by default — custom types are allowed — but see --strict-vocabulary below.
OKF finding codes
kuml workspace validate runs a fixed structural rule set:
| Code | Severity | Meaning |
|---|---|---|
|
ERROR |
Frontmatter missing or has no |
|
WARNING (or ERROR under |
Unrecognised |
|
ERROR |
A diagram type has no ```kuml block. |
|
WARNING |
A document has more than one ```kuml block ("one file = one diagram"). |
|
ERROR |
A relative Markdown link to a |
|
WARNING |
The workspace root has no |
|
ERROR |
A |
kuml workspace convert (FT-7) reports its own, disjoint code space:
| Code | Severity | Meaning |
|---|---|---|
|
(skip, not a finding) |
A knowledge document has no |
|
WARNING (or ERROR under |
A document has more than one |
|
WARNING (or ERROR under |
The diagram’s kind has no OKF vocabulary entry; wrote a custom |
|
ERROR |
A |
OKF-W-002 findings include a did-you-mean suggestion (Levenshtein distance ≤ 3
against the vocabulary) when a close match exists, e.g. type: UmlClassDigram suggests
Did you mean 'UmlClassDiagram'?.
--strict-vocabulary
By default an unrecognised type: is a warning — custom, workspace-local vocabulary is
allowed. Pass --strict-vocabulary to kuml workspace validate to treat it as an error
instead (exit code 5, same as any other validation failure):
kuml workspace validate ./docs --strict-vocabulary
The finding code stays OKF-W-002 in both modes — only the severity changes — so a JSON
consumer parsing kuml workspace validate -o json output keys on a stable code space
regardless of strictness.
Trust model
kuml workspace render executes every ` ``kuml ` block’s Kotlin script source through
the same pipeline as `kuml render — this is arbitrary code execution by design, not
something introduced by workspace rendering. Only run it over workspaces you already
trust, exactly like kuml render itself.