@alfacapital-tech/c4builder 0.9.0 → 0.10.0-rc.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,138 @@
1
+ # BPMN reference
2
+
3
+ `.bpmn` files are business processes in BPMN 2.0 notation. Write **only the semantic model**;
4
+ c4builder validates it, lays it out (horizontal pools and lanes, flow left to right) and
5
+ renders it in the standard bpmn.io notation — offline and deterministically.
6
+
7
+ ## Source format
8
+
9
+ - Standard BPMN 2.0 XML, namespace `http://www.omg.org/spec/BPMN/20100524/MODEL`.
10
+ - **No coordinates.** Do not write a `bpmndi:BPMNDiagram` section: it is ignored anyway, the
11
+ build always computes the layout. There is no way to hand-tune positions.
12
+ - `incoming` / `outgoing` elements are optional — connections are taken from
13
+ `sourceRef` / `targetRef` of the flows.
14
+ - `isExecutable="false"`: this is documentation, not an executable process; no Camunda or
15
+ Flowable extensions are needed.
16
+ - Give elements readable ids with a type prefix (`Task_CheckDocuments`, `Gateway_Decision`,
17
+ `Flow_Approved`): every error message points to an id.
18
+
19
+ Minimal example — a pool with two lanes, an external "black-box" pool, a gateway with
20
+ labelled branches, a boundary timer and message flows:
21
+
22
+ ```xml
23
+ <?xml version="1.0" encoding="UTF-8"?>
24
+ <bpmn:definitions xmlns:bpmn="http://www.omg.org/spec/BPMN/20100524/MODEL"
25
+ id="Definitions_Order" targetNamespace="https://example.com/bpmn/order">
26
+ <bpmn:collaboration id="Collaboration_Order">
27
+ <bpmn:participant id="Pool_Shop" name="Shop" processRef="Process_Order" />
28
+ <bpmn:participant id="Pool_Bank" name="Payment bank" />
29
+ <bpmn:messageFlow id="Message_Charge" name="Charge request"
30
+ sourceRef="Task_Charge" targetRef="Pool_Bank" />
31
+ <bpmn:messageFlow id="Message_Result" name="Payment result"
32
+ sourceRef="Pool_Bank" targetRef="Task_AwaitPayment" />
33
+ </bpmn:collaboration>
34
+ <bpmn:process id="Process_Order" name="Order" isExecutable="false">
35
+ <bpmn:laneSet id="LaneSet_Shop">
36
+ <bpmn:lane id="Lane_Sales" name="Sales">
37
+ <bpmn:flowNodeRef>Start_Order</bpmn:flowNodeRef>
38
+ <bpmn:flowNodeRef>Task_Charge</bpmn:flowNodeRef>
39
+ <bpmn:flowNodeRef>Task_AwaitPayment</bpmn:flowNodeRef>
40
+ <bpmn:flowNodeRef>Gateway_Paid</bpmn:flowNodeRef>
41
+ <bpmn:flowNodeRef>End_Cancelled</bpmn:flowNodeRef>
42
+ <bpmn:flowNodeRef>End_Expired</bpmn:flowNodeRef>
43
+ </bpmn:lane>
44
+ <bpmn:lane id="Lane_Warehouse" name="Warehouse">
45
+ <bpmn:flowNodeRef>Task_Ship</bpmn:flowNodeRef>
46
+ <bpmn:flowNodeRef>End_Shipped</bpmn:flowNodeRef>
47
+ </bpmn:lane>
48
+ </bpmn:laneSet>
49
+ <bpmn:startEvent id="Start_Order" name="Order placed" />
50
+ <bpmn:sendTask id="Task_Charge" name="Request payment" />
51
+ <bpmn:receiveTask id="Task_AwaitPayment" name="Await payment" />
52
+ <bpmn:boundaryEvent id="Timer_PaymentTimeout" name="1 hour" attachedToRef="Task_AwaitPayment">
53
+ <bpmn:timerEventDefinition id="TimerDef_PaymentTimeout" />
54
+ </bpmn:boundaryEvent>
55
+ <bpmn:exclusiveGateway id="Gateway_Paid" name="Paid?" />
56
+ <bpmn:userTask id="Task_Ship" name="Ship order" />
57
+ <bpmn:endEvent id="End_Shipped" name="Order shipped" />
58
+ <bpmn:endEvent id="End_Cancelled" name="Order cancelled" />
59
+ <bpmn:endEvent id="End_Expired" name="Payment expired" />
60
+ <bpmn:sequenceFlow id="Flow_Start" sourceRef="Start_Order" targetRef="Task_Charge" />
61
+ <bpmn:sequenceFlow id="Flow_Charged" sourceRef="Task_Charge" targetRef="Task_AwaitPayment" />
62
+ <bpmn:sequenceFlow id="Flow_Answered" sourceRef="Task_AwaitPayment" targetRef="Gateway_Paid" />
63
+ <bpmn:sequenceFlow id="Flow_Yes" name="Yes" sourceRef="Gateway_Paid" targetRef="Task_Ship" />
64
+ <bpmn:sequenceFlow id="Flow_No" name="No" sourceRef="Gateway_Paid" targetRef="End_Cancelled" />
65
+ <bpmn:sequenceFlow id="Flow_Timeout" sourceRef="Timer_PaymentTimeout" targetRef="End_Expired" />
66
+ <bpmn:sequenceFlow id="Flow_Shipped" sourceRef="Task_Ship" targetRef="End_Shipped" />
67
+ </bpmn:process>
68
+ </bpmn:definitions>
69
+ ```
70
+
71
+ Elements that render: start/end/intermediate events with timer, message, error and other
72
+ definitions, boundary events, `task`, `userTask`, `serviceTask`, `sendTask`, `receiveTask`,
73
+ `manualTask`, `scriptTask`, `businessRuleTask`, exclusive/parallel/inclusive/event-based
74
+ gateways, `subProcess`, `textAnnotation` with `association`, `dataObjectReference`.
75
+ `complexGateway` is not supported by the layout engine.
76
+
77
+ ## Modelling conventions
78
+
79
+ - **Pool = organization**, **lane = role or unit inside it.** An external party whose
80
+ internals you do not describe is a pool without `processRef` (a black box).
81
+ - **Between pools — only message flows.** Sequence flows stay inside one pool; a message
82
+ flow may target a node or the black-box pool itself.
83
+ - **Lanes:** when a process has lanes, list every flow node in exactly one lane
84
+ (`flowNodeRef`). Boundary events may be left out — they sit on their task.
85
+ - **Label everything:** events, tasks, participants, lanes and diverging gateways need a
86
+ `name`. Label every outgoing flow of an exclusive/inclusive gateway (`Yes` / `No`).
87
+ - **Exactly the start and end you mean:** a process needs a start and an end event; a node
88
+ without incoming or outgoing flows is an error, not an implicit start or end.
89
+ - **Overview plus detail** instead of one huge diagram: above ~40 nodes the picture stops
90
+ being readable. Sub-processes are always drawn collapsed — describe their inside in a
91
+ separate `.bpmn` on its own page.
92
+
93
+ ## The loop
94
+
95
+ ```bash
96
+ c4builder check "src/3 Processes/order.bpmn"
97
+ ```
98
+
99
+ `check` runs the whole pipeline — parse, rules, layout and rendering — without a project.
100
+ Exit code 0 means the diagram builds; warnings are printed but do not change the code. Each
101
+ problem is one line:
102
+
103
+ ```text
104
+ ✗ src/3 Processes/order.bpmn: Task_Ship [no-disconnected] Element is not connected
105
+ ⚠ src/3 Processes/order.bpmn: Flow_No [c4builder/gateway-flow-labels] Outgoing flow of a diverging gateway has no label
106
+ ```
107
+
108
+ Format: `<file>: <element id> [<rule>] <description>`. Fix the element with that id and run
109
+ `check` again until the exit code is 0.
110
+
111
+ | Message | Fix |
112
+ |---|---|
113
+ | `[no-disconnected]`, `[no-implicit-start]`, `[no-implicit-end]` | connect the node with sequence flows (check `sourceRef`/`targetRef` spelling) |
114
+ | `[start-event-required]`, `[end-event-required]` | add the missing start or end event |
115
+ | `[label-required]` | add a `name` |
116
+ | `[c4builder/lane-membership]` | list the node in exactly one `flowNodeRef` of its process lanes |
117
+ | `[c4builder/sequence-flow-in-pool]` | replace the sequence flow between pools with a `messageFlow` in the collaboration |
118
+ | `[c4builder/message-flow-between-pools]` | a message flow inside one pool must be a sequence flow |
119
+ | `[c4builder/gateway-flow-labels]` (warning) | name the gateway's outgoing flows |
120
+ | `[no-inclusive-gateway]` (warning) | prefer exclusive or parallel gateways where possible |
121
+ | `X: unresolved reference <Y>` | element `X` refers to an id `Y` that does not exist |
122
+ | `invalid BPMN XML: …` | the file is not well-formed XML or not BPMN 2.0 |
123
+ | `layout failed: …` / `layout lost N element(s): …` | the layout engine could not place the model: simplify it, split it into overview and detail, or move the listed elements |
124
+
125
+ The rule set is fixed (bpmnlint `recommended` without `no-bpmndi`, plus the `c4builder/*`
126
+ rules) and is the same in `check` and in the build — there is no project config for it.
127
+
128
+ ## Output and dependencies
129
+
130
+ - The image is `<name>.svg` (or `.png` with `diagramFormat: png`) next to the page; place
131
+ it inline with `![title](name.bpmn)`. In `llms-full.txt` the source appears in an `xml`
132
+ block.
133
+ - Text is measured with the bundled Nimbus Sans: the SVG is identical on every machine;
134
+ `useSystemFonts` does not affect BPMN.
135
+ - The engine packages (`bpmn-js`, `bpmn-moddle`, `bpmnlint`, `bpmn-auto-layout`, `jsdom`)
136
+ are optional npm dependencies, loaded only when the project has a `.bpmn`. An install with
137
+ `--omit=optional` stops such a build with a hint to reinstall c4builder.
138
+ - Like D2, BPMN has no online renderer: `generateLocalImages` must stay `true`.
@@ -0,0 +1,111 @@
1
+ # `.c4builder` reference
2
+
3
+ `.c4builder` is a JSON file in the project root (another path: `c4builder -c <path>`).
4
+ `c4builder --list` prints the effective values, `c4builder --docs` explains the wizard
5
+ questions, `c4builder --config` re-runs the wizard (interactive — prefer editing the JSON).
6
+
7
+ Validation rules:
8
+
9
+ - **Unknown keys are silently dropped.** A misspelled key (`generateWeb`) changes nothing —
10
+ compare every key with the tables below.
11
+ - A wrong type (a string where a boolean is expected, a bad port) fails the build with a
12
+ message naming the key. `null` means "not set" → default.
13
+ - The wizard asks for every key it knows that is **missing** from the file, so a
14
+ non-interactive build needs a complete config — like the one
15
+ `c4builder --new --name <name> -y` writes (below). `hasRun: true` (set after the first
16
+ successful build) makes invalid values fail the build instead of being asked again.
17
+
18
+ ## Sources and outputs
19
+
20
+ | Key | Default | Meaning |
21
+ |---|---|---|
22
+ | `projectName` | — | documentation title; name of the complete markdown file |
23
+ | `homepageName` | `Overview` | title of the root page |
24
+ | `rootFolder` | `src` | source folder |
25
+ | `distFolder` | `docs` | output folder — **wiped on every build** |
26
+ | `generateMD` | `true` | markdown collection: `README.md` per folder |
27
+ | `generateCompleteMD` | `false` | one `<projectName>.md` with everything |
28
+ | `generateWEB` | `true` | docsify site (`index.html`, `<folder>.md` per folder) |
29
+ | `generateLLMS` | `true` in new projects, off when absent | `llms.txt` (page index) and `llms-full.txt` (full text, diagrams as source) in the site root; needs `generateWEB` |
30
+ | `excludeOtherFiles` | `false` | do not copy non-diagram, non-markdown files (images…) |
31
+
32
+ ## Page content
33
+
34
+ | Key | Default | Meaning |
35
+ |---|---|---|
36
+ | `diagramsOnTop` | `true` | attached diagrams before the text (after a leading `#` title) |
37
+ | `includeBreadcrumbs` | `true` | folder path under the title |
38
+ | `includeNavigation` | `false` | markdown collection: links to parent and children |
39
+ | `includeTableOfContents` | `true` | markdown collection: tree of all pages on every page |
40
+ | `includeLinkToDiagram` | `false` | a link to the image instead of the image |
41
+ | `embedDiagram` | `false` | images inlined as base64 data URIs |
42
+ | `charset` | `UTF-8` | encoding of diagram sources |
43
+
44
+ ## Diagrams
45
+
46
+ | Key | Default | Meaning |
47
+ |---|---|---|
48
+ | `generateLocalImages` | `true` | render locally (Java + bundled PlantUML, bundled D2). `false` = PlantUML images are links to `plantumlServerUrl`; a project with `.d2` files then fails |
49
+ | `plantumlServerUrl` | `https://www.plantuml.com/plantuml` | server for `generateLocalImages: false` |
50
+ | `diagramFormat` | `svg` | `svg` or `png` (PNG is rasterized from SVG; ditaa is always PNG) |
51
+ | `d2Layout` | `dagre` | D2 layout engine: `dagre` or `elk` |
52
+ | `useSystemFonts` | `false` | machine fonts instead of the bundled one — output differs per machine (`--system-fonts` for one run) |
53
+
54
+ ## Site (docsify)
55
+
56
+ | Key | Default | Meaning |
57
+ |---|---|---|
58
+ | `webPort` | `3000` | port of `c4builder --site` (`-p <n>` overrides) |
59
+ | `questionsHeading` | `Open questions` | heading of the section in the source `.md` where `site -w` appends questions left on the page |
60
+ | `uiLanguage` | `auto` | language of the `site -w` page interface: `auto` (browser language), `en` or `ru`; CLI output and feedback batches stay English |
61
+ | `webTheme` | `vendor/vue.css` | docsify theme stylesheet |
62
+ | `supportSearch` | `true` | search box in the sidebar |
63
+ | `repoUrl` | `""` | repository link in the site corner |
64
+ | `executeScript` | `false` | let docsify run `<script>` in pages (forced on by `openapi`) |
65
+ | `docsifyTemplate` | `""` | path to a JS module exporting a function that returns `index.html` |
66
+ | `webFileName` | — | fixed file name for every site page instead of the folder name |
67
+ | `excludeSidebarFolderByPath` | — | array of folder paths, **including** `rootFolder` (`"src/2 Deployment"`), hidden from the sidebar |
68
+
69
+ ## Plugins
70
+
71
+ | Key | Default | Meaning |
72
+ |---|---|---|
73
+ | `plugins` | `[]` | `"name"` or `["name", { options }]` — see [plugins.md](plugins.md). Unlike other keys, a malformed entry always fails the build |
74
+
75
+ Legacy keys (`plantumlVersion`, `generatePDF`, `generateCompletePDF`) only produce a
76
+ warning — remove them when you see one.
77
+
78
+ Complete config written by `c4builder --new --name demo -y` — start from it when adding
79
+ c4builder to an existing repository:
80
+
81
+ ```json
82
+ {
83
+ "projectName": "demo",
84
+ "homepageName": "Overview",
85
+ "rootFolder": "src",
86
+ "distFolder": "docs",
87
+ "generateMD": true,
88
+ "generateCompleteMD": false,
89
+ "generateWEB": true,
90
+ "generateLLMS": true,
91
+ "includeNavigation": false,
92
+ "includeTableOfContents": true,
93
+ "webTheme": "vendor/vue.css",
94
+ "supportSearch": true,
95
+ "repoUrl": "",
96
+ "executeScript": false,
97
+ "docsifyTemplate": "",
98
+ "webPort": "3000",
99
+ "includeBreadcrumbs": true,
100
+ "includeLinkToDiagram": false,
101
+ "diagramsOnTop": true,
102
+ "embedDiagram": false,
103
+ "excludeOtherFiles": false,
104
+ "generateLocalImages": true,
105
+ "plantumlServerUrl": "https://www.plantuml.com/plantuml",
106
+ "diagramFormat": "svg",
107
+ "d2Layout": "dagre",
108
+ "charset": "UTF-8",
109
+ "useSystemFonts": false
110
+ }
111
+ ```
@@ -0,0 +1,77 @@
1
+ # Diagrams reference
2
+
3
+ The backend is chosen by file extension: `.puml` → PlantUML, `.d2` → D2, `.bpmn` → BPMN
4
+ (validation + automatic layout + bpmn-js, see [bpmn.md](bpmn.md)), `.mmd` → mermaid (see
5
+ [mermaid.md](mermaid.md)). All of them can live in one project and one folder (with different
6
+ base names).
7
+
8
+ ## PlantUML and C4-PlantUML
9
+
10
+ Rendering is offline: the PlantUML jar is bundled and runs on Java 17+ with the built-in
11
+ Smetana layout — Graphviz is not used. `!pragma layout elk` needs Java 21.
12
+
13
+ **C4 includes** come from the PlantUML stdlib (C4-PlantUML is inside the jar):
14
+
15
+ | Level | Include | Main macros |
16
+ |---|---|---|
17
+ | System context | `!include <C4/C4_Context>` | `Person`, `System`, `System_Ext`, `Rel` |
18
+ | Container | `!include <C4/C4_Container>` | `Container`, `ContainerDb`, `ContainerQueue`, `System_Boundary` |
19
+ | Component | `!include <C4/C4_Component>` | `Component`, `ComponentDb`, `Container_Boundary` |
20
+ | Dynamic | `!include <C4/C4_Dynamic>` | numbered `Rel` steps |
21
+ | Deployment | `!include <C4/C4_Deployment>` | `Deployment_Node`, `Node` |
22
+
23
+ Each level includes the previous ones. `LAYOUT_WITH_LEGEND()`, `LAYOUT_TOP_DOWN()`,
24
+ `LAYOUT_LEFT_RIGHT()` control layout and legend. Do not include C4 by URL
25
+ (`!include https://…`, `!includeurl`): it needs network on every build and pins nothing.
26
+
27
+ **Shared styles** — one `.iuml` library included after the C4 include, by a path relative
28
+ to the including diagram:
29
+
30
+ ```plantuml
31
+ @startuml
32
+ !include <C4/C4_Context>
33
+ !include ../styles.iuml
34
+ ...
35
+ @enduml
36
+ ```
37
+
38
+ Put `skinparam`s and `UpdateElementStyle(...)` / `AddElementTag(...)` calls there. A `.iuml`
39
+ is never rendered on its own; it is copied to the output like any other file (prefix it
40
+ with `_` to keep it out). Editing an included file re-renders every diagram that includes
41
+ it.
42
+
43
+ **Other PlantUML diagrams** (sequence, class, activity, state, ditaa…) work the same way —
44
+ any `@startuml` file is rendered. ditaa (`@startditaa`) always produces PNG.
45
+
46
+ **Non-Latin text.** Sources are read as UTF-8 (`charset`). The bundled Nimbus Sans font
47
+ covers Latin, Cyrillic and Greek, so diagrams look identical on every machine. Scripts it
48
+ lacks (e.g. CJK) need `useSystemFonts: true` (or `c4builder --system-fonts` for one run)
49
+ and a system font that has them — the output then depends on the machine.
50
+
51
+ ## D2
52
+
53
+ `.d2` files are rendered by the bundled D2 engine (WASM → SVG), which is the optional npm
54
+ dependency `@terrastruct/d2`. A `.d2` file in a project without it stops the build with an
55
+ install hint. D2 has no online renderer, so `generateLocalImages` must stay `true`.
56
+
57
+ - Imports: `@file` / spread `...@file` (without the `.d2` extension), resolved by
58
+ c4builder itself — no network. Keep shared classes in a `_`-prefixed file
59
+ (`src/_c4lib.d2`) and import it with `...@../_c4lib` from a nested folder.
60
+ - Layout: `d2Layout` — `dagre` (default) or `elk`.
61
+ - Validate like PlantUML: `c4builder check path/to/diagram.d2`.
62
+
63
+ ## Placement and output
64
+
65
+ - Every diagram of a folder is attached to the folder's page; `![title](name.puml)` /
66
+ `![title](name.d2)` / `![title](name.bpmn)` / `![title](name.mmd)` in a markdown file of the same folder places it
67
+ inline instead.
68
+ - Image file = diagram base name + `.svg` (or `.png` with `diagramFormat: png`), next to
69
+ the page in the output.
70
+ - A ```` ```plantuml ```` block in a page `.md` is rendered at build time like a `.puml`
71
+ file and replaced by its image in every output (`@startuml` optional, `!include` relative
72
+ to the page folder, a broken block becomes a placeholder plus a warning). To show diagram
73
+ source as code, fence it as `puml` or `text` — those, like `d2` blocks, stay code. A
74
+ ```` ```mermaid ```` block is rendered the same way ([mermaid.md](mermaid.md)).
75
+ - `embedDiagram: true` inlines images as base64; `includeLinkToDiagram: true` replaces
76
+ images with links.
77
+ - Unchanged diagrams are reused from the previous build (checksums in `.c4builder.cache`).
@@ -0,0 +1,78 @@
1
+ # Mermaid reference
2
+
3
+ Mermaid diagrams are rendered **at build time** by real mermaid (the official
4
+ `@mermaid-js/tiny` build) running in jsdom — no browser, no network. Text is measured with
5
+ the bundled Nimbus Sans, so the SVG is identical on every machine. Every output (site,
6
+ markdown, complete markdown, PNG) gets an image; the browser never sees diagram source.
7
+
8
+ ## When mermaid, when PlantUML
9
+
10
+ - **C4 model** (context, containers, components, deployment) — PlantUML with the C4 stdlib,
11
+ see [diagrams.md](diagrams.md). Mermaid C4 diagrams may lay out differently than in a browser.
12
+ - **Mermaid** — flows and processes inside documentation and OpenSpec artifacts:
13
+ `flowchart`/`graph` (with `subgraph`), `sequenceDiagram`, `stateDiagram-v2`, `erDiagram`,
14
+ `classDiagram`, `gantt`, `pie` and other types of the tiny build.
15
+ - **Business processes with pools and lanes** — BPMN, see [bpmn.md](bpmn.md).
16
+
17
+ ## Two sources
18
+
19
+ - **A `.mmd` file** in a page folder, like `.puml`/`.d2`/`.bpmn`: rendered to `<name>.svg`
20
+ (or `.png` with `diagramFormat: png`) and attached to the page, or placed inline with
21
+ `![title](flow.mmd)`. `flow.mmd` and `flow.puml` in one folder collide on the image name.
22
+ - **A ```` ```mermaid ```` block** in a page `.md` or in an OpenSpec artifact (`design.md`,
23
+ `proposal.md`, specs): replaced by its image in every output, like a ```` ```plantuml ````
24
+ block. To show mermaid source as code instead, fence it as `text`.
25
+
26
+ ```mermaid
27
+ sequenceDiagram
28
+ participant К as Клиент
29
+ participant Б as Банк
30
+ К->>Б: Заявка на счёт
31
+ Note right of Б: проверка анкеты
32
+ Б-->>К: Счёт открыт
33
+ ```
34
+
35
+ ## Conventions
36
+
37
+ - Keep labels short. A label longer than ~200 px wraps at spaces; a single long word
38
+ without spaces is split by mermaid character by character.
39
+ - Non-Latin text (Cyrillic etc.) works in ids and labels.
40
+ - The look is fixed: `look: classic`, theme `default`, SVG text labels. `%%{init: …}%%` and
41
+ frontmatter `config:` cannot change `look`, `htmlLabels`, `fontFamily`, `securityLevel` or
42
+ `themeCSS`; other keys (`theme`, `flowchart.curve`, spacing) work as in mermaid.
43
+ - Not supported: `mindmap`, `architecture` and KaTeX math (`$$…$$`) — they are not in the
44
+ tiny build and fail with an explicit `unsupported mermaid …` error.
45
+ - Clicks, tooltips and links are not interactive: the image is static.
46
+
47
+ ## The loop
48
+
49
+ ```bash
50
+ c4builder check "src/3 Processes/flow.mmd"
51
+ ```
52
+
53
+ `check` parses and renders the file exactly like the build, without a project. Exit code 0
54
+ means the diagram builds. Errors carry the line of the file (frontmatter and comments
55
+ counted):
56
+
57
+ ```text
58
+ ✗ src/3 Processes/flow.mmd: line 3: ...A --> B B -->> ((C; Expecting 'AMP', 'COLON', 'PIPE', ..., got 'TAGEND'
59
+ ✗ src/3 Processes/map.mmd: line 1: unsupported mermaid diagram type 'mindmap'
60
+ ```
61
+
62
+ Fix the line and run `check` again until the exit code is 0, then build. A
63
+ ```` ```mermaid ```` block cannot be checked on its own: build the project and read the
64
+ warnings, or copy the block into a temporary `.mmd`.
65
+
66
+ - An error in a `.mmd` file fails the build with the file path and line.
67
+ - An error in a ```` ```mermaid ```` block does not: the build exits with 0, the image is
68
+ a placeholder with the error, and the log has a warning naming the source `.md`.
69
+
70
+ ## Output and dependencies
71
+
72
+ - In `llms-full.txt` a mermaid diagram (file or block) appears as its source in a
73
+ `mermaid` block.
74
+ - The engine package `@mermaid-js/tiny` (about 2.7 MB, with `jsdom`) is an optional npm
75
+ dependency, loaded only when the project has mermaid. An install with `--omit=optional`
76
+ stops a `.mmd` build (and turns blocks into placeholders) with a hint to reinstall c4builder
77
+ without that flag.
78
+ - Like D2 and BPMN, mermaid has no online renderer: `generateLocalImages` must stay `true`.
@@ -0,0 +1,68 @@
1
+ # Plugins reference
2
+
3
+ Plugins add pages from outside `rootFolder` (they go through the normal pipeline: sidebar,
4
+ search, markdown outputs, local diagram rendering) and site assets. They are listed in
5
+ `.c4builder`:
6
+
7
+ ```json
8
+ {
9
+ "plugins": [
10
+ "openspec",
11
+ ["openapi", { "dir": "../contracts", "glob": "*/openapi.yaml" }]
12
+ ]
13
+ }
14
+ ```
15
+
16
+ - An entry is `"name"` or `["name", { options }]`. A malformed entry always fails the build.
17
+ - Name resolution: built-in (`openspec`, `openapi`) → local ESM module
18
+ (`./plugins/my.mjs`, relative to the project) → npm package installed in the project.
19
+ - Options are validated before the build; built-in plugins reject unknown option keys.
20
+ - `${ENV_VAR}` inside string options is replaced from the environment (unset → empty) and
21
+ never printed — keep tokens there, not in the file.
22
+ - Plugin folders are watched by `c4builder --site -w`.
23
+ - Hooks run in list order; an exception aborts the build and names the plugin.
24
+
25
+ ## `openspec` — OpenSpec store as a site section
26
+
27
+ Renders an [OpenSpec](https://github.com/Fission-AI/OpenSpec) store: a summary page
28
+ (counters, task progress), one page per active change (header + first artifact, the other
29
+ artifacts and spec deltas as subpages), the specs tree and the archive. `plantuml` / `d2`
30
+ fenced blocks in artifacts are rendered by the local engines; a broken block gets a
31
+ placeholder image and a warning naming the file instead of failing the build.
32
+
33
+ | Option | Default | Meaning |
34
+ |---|---|---|
35
+ | `dir` | `openspec` | store folder, relative to the project |
36
+ | `mount` | `OpenSpec` | section name and its path in the output |
37
+ | `artifacts` | `["proposal", "design", "tasks"]` | artifact order; the first is shown on the change page |
38
+ | `parentKey` | — | `.openspec.yaml` key pointing at the parent change (e.g. `x-parent`); when set, child changes are nested under their parent in the sidebar, the Changes table and the archive |
39
+ | `groupKey` | — | `.openspec.yaml` key with the change's group (e.g. `x-team`); when set, top-level changes go to `Changes/<group>/<id>`, the Changes table and the archive get per-group sections |
40
+ | `nameKey` | — | `.openspec.yaml` key with the change's name (e.g. `x-name`); when set, the name labels the top-level change and is its page path segment (falls back to the id on `/`, `#`, `?` or a duplicate) |
41
+ | `columns` | — | extra Changes table columns from `.openspec.yaml`: `[{ "key": "x-assignee", "title": "Assignee" }]`; missing value — `—` |
42
+
43
+ ## `openapi` — swagger-ui pages for OpenAPI specs
44
+
45
+ One page per spec found by `glob` (named after the spec's parent folder) plus an index;
46
+ swagger-ui is bundled, readers need no network. Exactly one source — `dir` **or**
47
+ `archive` — is required. It forces `executeScript: true`.
48
+
49
+ | Option | Default | Meaning |
50
+ |---|---|---|
51
+ | `mount` | `API` | section name |
52
+ | `dir` | — | local folder with specs (watched) |
53
+ | `archive` | — | HTTP(S) URL of a `tar.gz` / `zip` archive (e.g. a repository archive) |
54
+ | `subdir` | — | folder inside the archive or `dir` |
55
+ | `headers` | — | HTTP headers for the archive request, e.g. `{"PRIVATE-TOKEN": "${GITLAB_TOKEN}"}` |
56
+ | `glob` | `**/openapi.{yaml,yml,json}` | spec pattern (`**`, `*`, `?`, `{a,b}`); directories starting with a dot are skipped |
57
+
58
+ All `yaml`/`yml`/`json` files of the source are published under `<mount>/_specs/…` with
59
+ their relative layout, so relative `$ref`s keep working. Archive download fails with
60
+ `self-signed certificate in certificate chain` behind a TLS-intercepting proxy → set
61
+ `NODE_EXTRA_CA_CERTS` to the proxy CA bundle.
62
+
63
+ ## Custom plugins
64
+
65
+ A plugin is an ESM module whose default export is an object with `name` and optional
66
+ `options` (zod schema), `watchPaths`, `assets`, `requires`, `afterScan(ctx, opts)` (add
67
+ virtual pages with `ctx.addPage`) and `afterBuild(ctx, opts)`. See the "Writing a plugin"
68
+ section of the c4builder README for the full contract and an example.
@@ -0,0 +1,97 @@
1
+ ---
2
+ name: c4builder-review
3
+ description: Review c4builder pages with a human right on the local site - the human selects text in c4builder --site -w and leaves comments with the Feedback button, the agent receives them in batches with c4builder feedback --wait --as <name>, edits the sources and waits for the next batch until Approve. Use when asked to discuss a change on the site, to show the pages or a design, to review a page, the design or OpenSpec artifacts, when the human says they will leave comments on the page, right after proposing an OpenSpec change in a repository with c4builder, and on /c4builder-review [change-id|page].
4
+ ---
5
+
6
+ # c4builder-review: page comments to the agent
7
+
8
+ The human looks at the pages in the browser (`c4builder --site -w`), selects text and presses:
9
+
10
+ - **Feedback** — a comment to you. It is not written to the files and comes to you in a batch:
11
+ **Send now** sends one comment, **Add to review** → **Submit review** sends several (from several
12
+ pages too), **Approve** means nothing more to change.
13
+ - **Question** — a question for people: c4builder appends it to the source `.md` under the
14
+ `questionsHeading` section (`Open questions` by default). It is not a task for you — leave it
15
+ alone unless asked.
16
+
17
+ Invocation: `/c4builder-review [change-id|page]`. The port is `webPort` from `.c4builder`
18
+ (`<port>` below); when the server runs with `-p <n>`, pass the same `-p <n>` to the commands below.
19
+
20
+ The listener name (`<name>` below) is how the page picks the agent when several share one
21
+ `site -w`: the change id from the argument, otherwise the name of your task. Letters, digits,
22
+ `.`, `_`, `-`, up to 64 characters. Keep one name for the whole review.
23
+
24
+ ## 1. Server
25
+
26
+ ```bash
27
+ curl -s -o /dev/null -w '%{http_code}\n' http://127.0.0.1:<port>/
28
+ ```
29
+
30
+ `200` — the server is up; never start a second one. Otherwise ask the user to start
31
+ `c4builder --site -w`, or ask whether you may start it yourself in the background — many teams
32
+ keep the preview server in the human's hands.
33
+
34
+ ## 2. Link
35
+
36
+ - Argument is an OpenSpec change id: find its page in the build output (`distFolder` from
37
+ `.c4builder`, `docs` by default). The path depends on the `mount`, `groupKey` and `nameKey`
38
+ options of the `openspec` plugin — search, do not guess:
39
+ `find <distFolder> -path '*<change-id>*' -name '*.md' | head` (with `nameKey` the folder carries
40
+ the change's name from its `.openspec.yaml` instead of the id). The address is
41
+ `http://localhost:<port>/#/<path without .md>`.
42
+ - Argument is a page or a section: find it in the build output the same way.
43
+ - No argument: the home page `http://localhost:<port>/`.
44
+
45
+ Give the link, remind in two lines what **Feedback** and **Question** do (see above) and say your
46
+ listener name: with several agents the human picks it in **Send to** on the review bar.
47
+
48
+ ## 3. Wait
49
+
50
+ Start in the background (in Claude Code: Bash with `run_in_background`):
51
+
52
+ ```bash
53
+ c4builder feedback --wait --as <name>
54
+ ```
55
+
56
+ It exits when a batch arrives; its stdout is the batch. Connecting turns the **Feedback** button
57
+ on by itself, the server needs no restart. Errors:
58
+
59
+ - `--as <name> is required` (exit code 2) — the name is missing or invalid: fix it and run again;
60
+ - `no c4builder site -w on …` (exit code 1) — no server or it crashed: back to step 1;
61
+ - `agent feedback is disabled on …` (exit code 1) — the server runs without `-w` or with
62
+ `--no-agent`: ask the user to restart `c4builder --site -w`;
63
+ - `unknown command: feedback` or `unknown option '--as'` — the CLI is older than this skill: tell
64
+ the user, `c4builder update` updates it (only when they agree).
65
+
66
+ ## 4. Batch
67
+
68
+ ```text
69
+ # Page feedback (c4builder)
70
+
71
+ Decision: submitted
72
+ Comments: 1 on 1 page
73
+
74
+ ## 1. OpenSpec/Changes/add-dark-mode/design.md (§ D3)
75
+ Sources: openspec/changes/add-dark-mode/design.md
76
+ Quote: "the selected text"
77
+
78
+ > what to change
79
+ ```
80
+
81
+ Every comment names the site page, the page section (`§`), its source files (`Sources`) and the
82
+ quoted selection; `## General` is the overall comment of a review.
83
+
84
+ - Edit the files listed in `Sources` (change artifacts, `src/` and so on), never the build output.
85
+ No `Sources` — find the quote in the sources (`grep -rn`). The page reloads by itself.
86
+ - Do not copy comments into the questions section: they are instructions to you, not questions
87
+ for people.
88
+ - A comment that is unclear or debatable — ask in the chat instead of guessing; do the rest of the
89
+ batch.
90
+ - After the edits report briefly in the chat what you did for each comment number. Then run
91
+ `c4builder feedback --wait --as <name>` in the background again with the same name — batches
92
+ wait in your mailbox.
93
+
94
+ ## 5. Done
95
+
96
+ `Decision: approved` — nothing more to change: apply the comments of that batch, if any, give a
97
+ summary of the changes by file and stop waiting. Do not commit unless the user asks.