@rse/specbook 1.0.1 → 1.0.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.
Files changed (2) hide show
  1. package/README.md +272 -121
  2. package/package.json +1 -1
package/README.md CHANGED
@@ -22,63 +22,63 @@ CLI with commands `specbook <xxx>`, and an MCP service with tools
22
22
 
23
23
  **SpecBook** provides the following distinct features:
24
24
 
25
- - **Hierarchical Object Model**:
26
- A specification is a tree of typed objects, each with a kind and
27
- name, an optional id, optional properties, optional description, and
28
- optional child objects. The allowed object hierarchy is defined per
29
- context by the YAML schema configuration.
30
-
31
- - **Versatile Object to Markdown Mapping**:
32
- Objects are authored as plain Markdown headings, property lists,
33
- and description prose. The objects can be mapped to nested sections
34
- ("complex" format) or compact bullet point lists ("concise" and
35
- "group" format).
36
-
37
- - **Wiki-Style Object Linking**:
38
- Objects can hierarchically reference each other through Wiki-style
39
- `[[xxx]]` references, which are resolved against the locally-unique
40
- ids and names of all objects. In the HTML and PDF exports they become
41
- navigable links onto precise anchors.
42
-
43
- - **Strict Validation with Custom Schema**:
44
- The YAML schema configuration strictly defines the allowed object
45
- kinds, hierarchies, and properties, whose values are constrained by an
46
- expression language (regex, enum, tags, list, and reference). Violations
47
- are reported as file- and line-precise diagnostics. A bundled standard
48
- schema configuration applies if no particular one is given.
49
-
50
- - **Object Model Diagram Visualisation**:
51
- Object kinds can declare "graph", "hub", or "grid" diagrams in the
52
- schema, whose nodes and edges are automatically derived from the
53
- object model and its references. The diagrams are rendered with the
54
- sibling project [Gradia](https://github.com/rse/gradia), which is
55
- specialized in rendering object models.
56
-
57
- - **CLI, MCP, and API Interface**:
58
- All commands are implemented once in the API class `SpecBook`, on
59
- which both the CLI and the MCP service are just thin wrappers.
60
- This way, humans, scripts, and AI agents use exactly the same
61
- functionality.
62
-
63
- - **AST Exports for AI/LLMs**:
64
- The parsed specification Abstract Syntax Tree (AST) can be exported in
65
- JSON, JSON5, YAML, or TOON format for machine consumption. Together
66
- with the `describe` command, which explains the models and formats,
67
- this enables LLMs to both read and write specifications.
68
-
69
- - **HTML Export for Developers**:
70
- The HTML export is a self-contained single document with a
71
- table-of-contents, full-text search, embedded images, and a light/dark
72
- theme toggle. It is intended for the day-to-day online reading during
73
- development. The HTML export can map all object kinds to nested
74
- sections or compact tables, or an automatic mixture which collapses
75
- only the deepest level into tables.
76
-
77
- - **PDF Export for Customers**:
78
- The PDF export prints the HTML rendering via Chromium and post-processes
79
- it with page numbers, headers/footers, and a hierarchical PDF outline.
80
- It is intended as a polished, paginated offline document for handing
81
- over to customers.
25
+ - **Hierarchical Object Model**:
26
+ A specification is a tree of typed objects, each with a kind and
27
+ name, an optional id, optional properties, optional description, and
28
+ optional child objects. The allowed object hierarchy is defined per
29
+ context by the YAML schema configuration.
30
+
31
+ - **Versatile Object to Markdown Mapping**:
32
+ Objects are authored as plain Markdown headings, property lists,
33
+ and description prose. The objects can be mapped to nested sections
34
+ ("complex" format) or compact bullet point lists ("concise" and
35
+ "group" format).
36
+
37
+ - **Wiki-Style Object Linking**:
38
+ Objects can hierarchically reference each other through Wiki-style
39
+ `[[xxx]]` references, which are resolved against the locally-unique
40
+ ids and names of all objects. In the HTML and PDF exports they become
41
+ navigable links onto precise anchors.
42
+
43
+ - **Strict Validation with Custom Schema**:
44
+ The YAML schema configuration strictly defines the allowed object
45
+ kinds, hierarchies, and properties, whose values are constrained by an
46
+ expression language (regex, enum, tags, list, and reference). Violations
47
+ are reported as file- and line-precise diagnostics. A bundled standard
48
+ schema configuration applies if no particular one is given.
49
+
50
+ - **Object Model Diagram Visualisation**:
51
+ Object kinds can declare "graph", "hub", or "grid" diagrams in the
52
+ schema, whose nodes and edges are automatically derived from the
53
+ object model and its references. The diagrams are rendered with the
54
+ sibling project [Gradia](https://github.com/rse/gradia), which is
55
+ specialized in rendering object models.
56
+
57
+ - **CLI, MCP, and API Interface**:
58
+ All commands are implemented once in the API class `SpecBook`, on
59
+ which both the CLI and the MCP service are just thin wrappers.
60
+ This way, humans, scripts, and AI agents use exactly the same
61
+ functionality.
62
+
63
+ - **AST Exports for AI/LLMs**:
64
+ The parsed specification Abstract Syntax Tree (AST) can be exported in
65
+ JSON, JSON5, YAML, or TOON format for machine consumption. Together
66
+ with the `describe` command, which explains the models and formats,
67
+ this enables LLMs to both read and write specifications.
68
+
69
+ - **HTML Export for Developers**:
70
+ The HTML export is a self-contained single document with a
71
+ table-of-contents, full-text search, embedded images, and a light/dark
72
+ theme toggle. It is intended for the day-to-day online reading during
73
+ development. The HTML export can map all object kinds to nested
74
+ sections or compact tables, or an automatic mixture which collapses
75
+ only the deepest level into tables.
76
+
77
+ - **PDF Export for Customers**:
78
+ The PDF export prints the HTML rendering via Chromium and post-processes
79
+ it with page numbers, headers/footers, and a hierarchical PDF outline.
80
+ It is intended as a polished, paginated offline document for handing
81
+ over to customers.
82
82
 
83
83
  Overview
84
84
  --------
@@ -97,84 +97,235 @@ $ npm install -g @rse/specbook
97
97
  Usage
98
98
  -----
99
99
 
100
- ### CLI
100
+ ### API
101
101
 
102
- ```bash
103
- $ specbook init [-v] [-c <yaml-file>] [-b <basedir>]
104
- $ specbook lint [-v] [-c <yaml-file>] [-b <basedir>]
105
- $ specbook export [-v] [-c <yaml-file>] [-b <basedir>] [-o [<format>:]<output-file>] [...]
106
- $ specbook describe [-v] [-c <yaml-file>] [-b <basedir>] [-e] [-f <format>] [-p <part>] [-o <markdown-file>]
107
- $ specbook mcp [-v]
102
+ ```ts
103
+ /* the SpecBook API, providing all commands the CLI and MCP service expose */
104
+ export class SpecBook {
105
+ constructor (options?: SpecBookOptions)
106
+
107
+ /* initialize the configured specification artifact files below the
108
+ base directory and return the list of the generated files */
109
+ init (options: {
110
+ config?: string, /* YAML schema configuration (default: bundled standard one) */
111
+ basedir?: string /* base directory (default: ".") */
112
+ }): Promise<string[]>
113
+
114
+ /* parse and validate the specification Markdown files below the base directory */
115
+ lint (options: {
116
+ config?: string,
117
+ basedir?: string
118
+ }): Promise<LintResult>
119
+
120
+ /* export the specification, parsing the input just once and
121
+ returning one buffer per requested format (strict: any diagnostic
122
+ rejects the export with an "Error") */
123
+ export (options: {
124
+ config?: string,
125
+ basedir?: string,
126
+ formats?: ExportFormat[] /* requested output formats (default: [ "json" ]) */
127
+ }): Promise<Buffer[]>
128
+
129
+ /* describe the SpecBook models and formats, optionally pointing to
130
+ the artifacts of the particular project */
131
+ describe (options: {
132
+ config?: string,
133
+ basedir?: string,
134
+ embed?: boolean, /* embed the schema configuration instead of referencing it */
135
+ format?: DescribeFormat, /* output format (default: "md") */
136
+ part?: DescribePart /* document part (default: "all") */
137
+ }): Promise<string>
138
+ }
139
+
140
+ /* the constructor options and the sink of the verbose messages,
141
+ receiving the emitting command and the message */
142
+ export interface SpecBookOptions {
143
+ verbose?: VerboseSink
144
+ }
145
+ export type VerboseSink = (cmd: string, msg: string) => void
146
+
147
+ /* the result of the "lint" command and its file- and line-precise diagnostics */
148
+ export interface LintResult {
149
+ specification: Spec
150
+ diagnostics: Diagnostic[]
151
+ config?: Schema
152
+ }
153
+ export interface Diagnostic {
154
+ file: string
155
+ line: number
156
+ column: number
157
+ message: string
158
+ }
159
+
160
+ /* the supported export formats and describe formats/parts */
161
+ export const formats: readonly [ "json", "json5", "yaml", "toon", "html", "pdf", "md" ]
162
+ export const describeFormats: readonly [ "md", "raw" ]
163
+ export const describeParts: readonly [ "all", "meta", "schema", "spec" ]
164
+ export type ExportFormat = typeof formats[number]
165
+ export type DescribeFormat = typeof describeFormats[number]
166
+ export type DescribePart = typeof describeParts[number]
167
+
168
+ /* the Abstract Syntax Tree (AST) of a parsed specification */
169
+ export type Spec = {
170
+ artifacts: SpecArtifact[]
171
+ }
172
+ export type SpecArtifact = {
173
+ created: Date
174
+ modified: Date
175
+ objects: SpecObject[]
176
+ }
177
+ export type SpecObject = {
178
+ kind: string
179
+ id: string
180
+ anchor?: string
181
+ paren?: string
182
+ name: string
183
+ primary?: boolean
184
+ description?: SpecDescription
185
+ properties: SpecProperty[]
186
+ childs: SpecObject[]
187
+ }
188
+ export type SpecDescription = {
189
+ description: string
190
+ rationale?: string
191
+ embedding?: string[]
192
+ }
193
+ export type SpecProperty = {
194
+ key: string
195
+ value: string
196
+ embedding?: string[]
197
+ }
198
+
199
+ /* the YAML schema configuration, where the nested "diagram" and
200
+ "format" structures are detailed in the "describe" output */
201
+ export type Schema = SchemaObject[]
202
+ export type SchemaObject = {
203
+ kind: string
204
+ name?: string
205
+ id?: string
206
+ file?: string
207
+ desc?: string
208
+ optional?: boolean
209
+ diagram?: SchemaDiagram
210
+ format?: SchemaFormat
211
+ props?: SchemaProperty[]
212
+ childs?: SchemaObject[]
213
+ }
214
+ export type SchemaProperty = {
215
+ name: string
216
+ desc?: string
217
+ value?: string
218
+ optional?: boolean
219
+ }
108
220
  ```
109
221
 
110
- The YAML schema configuration `-c`/`--config` (default: the bundled
111
- standard schema configuration `specbook-format.yaml`) determines the
112
- specification: exactly the artifact files its `file` fields reference
113
- are loaded and parsed; all other Markdown files below the base
114
- directory are ignored. A referenced
115
- file which is absent is reported, unless all of its artifacts are
116
- `optional`, and so is an artifact absent from its present file, unless
117
- it is `optional` itself. Both `lint` and `export` report all
118
- diagnostics and fail on any of them, so a partial or invalid
119
- specification is never exported.
120
-
121
- The base directory `-b`/`--basedir` (default: `.`) is the directory the
122
- referenced artifact files are resolved against, and generated
123
- specification Markdown files are placed inside it, too.
124
-
125
- The export output option `-o`/`--output` (default: `-` for stdout) can
126
- occur multiple times. The format (`json`, `json5`, `yaml`, `toon`,
127
- `html`, `pdf`, or `md`) is inferred from the filename extension, unless
128
- it is explicitly given as a `<format>:` prefix, and plain `-` (stdout)
129
- defaults to JSON.
130
-
131
- The `md` format normalizes the entire corpus into a *single* Markdown
132
- document, whose single frontmatter block carries the earliest `Created:`
133
- and the latest `Modified:` timestamp of all artifacts, so the
134
- per-artifact timestamps do not survive this round-trip.
135
-
136
- The `describe` command outputs the description of the SpecBook models
137
- and formats, extended by a *SpecBook Project Instantiation* section which
138
- points to the YAML schema configuration `-c`/`--config` and the base
139
- directory `-b`/`--basedir`. The schema configuration falls back onto the
140
- bundled standard one, embedded verbatim, as long as no particular
141
- configuration file `-c`/`--config` is given. With `-e`/`--embed` the
142
- given YAML schema configuration is embedded verbatim instead of just
143
- being referenced, so the resulting document describes the specification
144
- format entirely on its own.
145
-
146
- The `describe` document part `-p`/`--part` (default: `all`) reduces the
147
- output to a single part: `meta` for the description of the generic
148
- SpecBook models and formats, `schema` for the YAML schema configuration
149
- (the given one, referenced or embedded with `-e`/`--embed`, else the
150
- bundled standard one, embedded), or `spec` for the reference to
151
- the base directory. The output format `-f`/`--format` (default: `md`)
152
- switches from this rendered Markdown onto the raw original file content
153
- with `raw`, which is available for the file-backed parts `meta` and
154
- `schema` only.
155
-
156
- The default value of every CLI option `--xxx` can be overridden by a
157
- corresponding `SPECBOOK_XXX` environment variable (e.g.
158
- `SPECBOOK_BASEDIR`, `SPECBOOK_CONFIG`, `SPECBOOK_OUTPUT`,
159
- `SPECBOOK_VERBOSE`), while an explicitly supplied option always wins.
160
-
161
- ### API
222
+ Example:
162
223
 
163
224
  ```ts
164
- import { SpecBook, renderVerbose } from "@rse/specbook"
225
+ import { SpecBook } from "@rse/specbook"
165
226
 
166
227
  const specbook = new SpecBook({
167
- verbose: (cmd, msg) => console.error(`specbook: ${cmd}: ${renderVerbose(msg)}`)
228
+ verbose: (cmd, msg) => console.error(`specbook: ${cmd}: ${msg}`)
168
229
  })
169
230
  const result = await specbook.lint({
170
231
  basedir: "smp/broadcast"
171
232
  })
172
233
  ```
173
234
 
174
- ### MCP
235
+ ### CLI
236
+
237
+ Commands:
175
238
 
176
- Run `specbook mcp` to serve the tools `specbook_init`, `specbook_lint`,
177
- `specbook_export`, and `specbook_describe` over stdio.
239
+ ```bash
240
+ $ specbook init \
241
+ [-v|--verbose] \
242
+ [-c|--config <schema-yaml-file>] \
243
+ [-b|--basedir <spec-md-file-basedir>]
244
+
245
+ $ specbook lint \
246
+ [-v|--verbose] \
247
+ [-c|--config <schema-yaml-file>] \
248
+ [-b|--basedir <spec-md-file-basedir>]
249
+
250
+ $ specbook export \
251
+ [-v|--verbose] \
252
+ [-c|--config <schema-yaml-file>] \
253
+ [-b|--basedir <spec-md-file-basedir>] \
254
+ [-o|--output [<format>:]<output-file>] [...]
255
+
256
+ $ specbook describe \
257
+ [-v|--verbose] \
258
+ [-c|--config <schema-yaml-file>] \
259
+ [-b|--basedir <spec-md-file-basedir>] \
260
+ [-e|--embed] \
261
+ [-f|--format <format>] \
262
+ [-p|--part <part>] \
263
+ [-o|--output <output-file>]
264
+
265
+ $ specbook mcp \
266
+ [-v|--verbose]
267
+ ```
268
+
269
+ Options:
270
+
271
+ - `-v|--verbose`:
272
+ Enable verbose logging of processing information to `stderr`.
273
+
274
+ - `-c|--config <schema-yaml-file>`:
275
+ The YAML schema configuration (default: the bundled standard schema
276
+ configuration `specbook-format.yaml`) determines the specification:
277
+ exactly the artifact files its `file` fields reference are loaded and
278
+ parsed; all other Markdown files below the base directory are ignored.
279
+ A referenced file which is absent is reported, unless all of its
280
+ artifacts are `optional`, and so is an artifact absent from its present
281
+ file, unless it is `optional` itself. Both `lint` and `export` report
282
+ all diagnostics and fail on any of them, so a partial or invalid
283
+ specification is never exported.
284
+
285
+ - `-b|--basedir <spec-md-file-basedir>`:
286
+ The base directory (default: `.`) is the directory the referenced
287
+ artifact files are resolved against, and generated specification
288
+ Markdown files are placed inside it, too.
289
+
290
+ - `-o|--output [<format>:]<output-file>` (`export` only):
291
+ The output file (default: `-` for stdout) can be given multiple times.
292
+ The format (`json`, `json5`, `yaml`, `toon`, `html`, `pdf`, or `md`)
293
+ is inferred from the filename extension, unless it is explicitly given
294
+ as a `<format>:` prefix, and plain `-` (stdout) defaults to JSON.
295
+ The `md` export format normalizes the entire corpus into a *single*
296
+ Markdown document.
297
+
298
+ - `-o|--output <output-file>` (`describe` only):
299
+ The output file (default: `-` for stdout) receives the described
300
+ Markdown document.
301
+
302
+ - `-e|--embed` (`describe` only):
303
+ Embed the given YAML schema configuration verbatim instead of just
304
+ referencing it, so the resulting document describes the specification
305
+ format entirely on its own.
306
+
307
+ - `-f|--format <format>` (`describe` only):
308
+ The output format (default: `md`) switches from the rendered Markdown
309
+ onto the raw original file content with `raw`, which is available for
310
+ the file-backed parts `meta` and `schema` only.
311
+
312
+ - `-p|--part <part>` (`describe` only):
313
+ The document part (default: `all`) reduces the output to a single part:
314
+ `meta` for the description of the generic SpecBook models and formats,
315
+ `schema` for the YAML schema configuration (the given one, referenced
316
+ or embedded with `-e|--embed`, else the bundled standard one,
317
+ embedded), or `spec` for the reference to the base directory.
318
+
319
+ The default value of every CLI option `--xxx` can be overridden
320
+ by a corresponding `SPECBOOK_XXX` environment variable (e.g.
321
+ `SPECBOOK_BASEDIR`, `SPECBOOK_CONFIG`, `SPECBOOK_OUTPUT`,
322
+ `SPECBOOK_VERBOSE`), while an explicitly supplied option always wins.
323
+
324
+ Example:
325
+
326
+ ```bash
327
+ $ specbook lint -v -b smp/broadcast
328
+ ```
178
329
 
179
330
  Rendering Examples
180
331
  ------------------
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rse/specbook",
3
- "version": "1.0.1",
3
+ "version": "1.0.2",
4
4
  "publishConfig": { "access": "public" },
5
5
  "description": "Markdown-based Specification Format (API, CLI and MCP service)",
6
6
  "license": "Apache-2.0",