@heroiclands/package-build 20.3.1 → 20.5.0

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 (195) hide show
  1. package/CHANGELOG.md +351 -0
  2. package/CONTENT.md +322 -110
  3. package/README.md +21 -10
  4. package/bin/content-build.mjs +204 -92
  5. package/bin/package-build.mjs +48 -15
  6. package/config.mjs +6 -8
  7. package/content-config.mjs +518 -151
  8. package/docs/api.md +1352 -0
  9. package/docs/commands.md +1609 -0
  10. package/docs/configuration.md +1432 -0
  11. package/docs/content-format.md +73 -74
  12. package/docs/diagnostics.md +356 -0
  13. package/docs/getting-started.md +813 -0
  14. package/docs/project-setup.md +469 -0
  15. package/e2e.mjs +4 -4
  16. package/engine/actor-compiler.mjs +64 -61
  17. package/engine/address-charset.mjs +6 -6
  18. package/engine/address-diff.mjs +57 -52
  19. package/engine/anchored-sections.mjs +1 -1
  20. package/engine/anchors.mjs +1 -1
  21. package/engine/base-compiler.mjs +42 -38
  22. package/engine/bundle-notes.mjs +4 -4
  23. package/engine/bundles.mjs +17 -8
  24. package/engine/code-fences.mjs +3 -3
  25. package/engine/compendiums.mjs +8 -8
  26. package/engine/compile-corpus.mjs +4 -5
  27. package/engine/content-address.mjs +24 -24
  28. package/engine/content-charset.mjs +1 -1
  29. package/engine/content-format-check.mjs +24 -25
  30. package/engine/content-format.mjs +8 -8
  31. package/engine/content-html.mjs +202 -0
  32. package/engine/content-icons.mjs +196 -165
  33. package/engine/content-index.mjs +61 -40
  34. package/engine/content-links.mjs +74 -41
  35. package/engine/content-lint.mjs +64 -34
  36. package/engine/content-package.mjs +7 -9
  37. package/engine/content-slug.mjs +2 -2
  38. package/engine/content-tables.mjs +38 -34
  39. package/engine/content-tree.mjs +1 -1
  40. package/engine/derived-fields.mjs +174 -0
  41. package/engine/diagnostics.mjs +3 -4
  42. package/engine/document-subtypes.mjs +6 -7
  43. package/engine/field-reference.mjs +8 -8
  44. package/engine/field-spec.mjs +29 -30
  45. package/engine/folder-notes.mjs +18 -16
  46. package/engine/foreign-catalog.mjs +8 -9
  47. package/engine/foundry-entries.mjs +19 -20
  48. package/engine/frontmatter-lint.mjs +95 -103
  49. package/engine/frontmatter.mjs +11 -11
  50. package/engine/generate.mjs +44 -39
  51. package/engine/helpers.mjs +147 -84
  52. package/engine/homepage.mjs +20 -22
  53. package/engine/ids.mjs +15 -15
  54. package/engine/index-records.mjs +4 -4
  55. package/engine/index.mjs +26 -10
  56. package/engine/item-compiler.mjs +54 -29
  57. package/engine/item-docs.mjs +11 -13
  58. package/engine/item-registry.mjs +13 -13
  59. package/engine/journals.mjs +24 -15
  60. package/engine/macros.mjs +3 -3
  61. package/engine/map-notes.mjs +6 -6
  62. package/engine/metadata-index.mjs +5 -5
  63. package/engine/note-claims.mjs +51 -41
  64. package/engine/note-ids.mjs +5 -5
  65. package/engine/note-package.mjs +4 -4
  66. package/engine/note-renames.mjs +3 -3
  67. package/engine/note-schemas.mjs +3 -8
  68. package/engine/note-vocabulary.mjs +56 -54
  69. package/engine/pack-config.mjs +39 -25
  70. package/engine/pack-router.mjs +0 -0
  71. package/engine/pdf-build.mjs +464 -0
  72. package/engine/pdf-fonts.mjs +420 -0
  73. package/engine/pdf-render.mjs +798 -0
  74. package/engine/pdf-toc.mjs +525 -0
  75. package/engine/prose-config.mjs +9 -9
  76. package/engine/prose-lint.mjs +12 -13
  77. package/engine/region-events.mjs +2 -2
  78. package/engine/retired-fields.mjs +24 -22
  79. package/engine/runtime-only-fields.mjs +1 -1
  80. package/engine/scene-levels.mjs +1 -1
  81. package/engine/scenes.mjs +33 -25
  82. package/engine/schema-check.mjs +21 -21
  83. package/engine/schema-extract.mjs +1 -1
  84. package/engine/site-build.mjs +66 -50
  85. package/engine/site-index.mjs +17 -18
  86. package/engine/sql-tables.mjs +21 -13
  87. package/engine/subtype-registry.mjs +5 -4
  88. package/engine/system-block.mjs +18 -19
  89. package/engine/systems.mjs +2 -2
  90. package/engine/web-wikilinks.mjs +41 -38
  91. package/engine/wikilink-syntax.mjs +16 -16
  92. package/engine/wikilinks.mjs +40 -42
  93. package/hm3/actors.mjs +30 -22
  94. package/hm3/document-subtypes.mjs +5 -5
  95. package/hm3/index.mjs +2 -2
  96. package/hm3/item-builders.mjs +1 -1
  97. package/hm3/item-fields.mjs +3 -3
  98. package/hm3/items.mjs +28 -8
  99. package/hm3/template-priority.mjs +2 -2
  100. package/lang.mjs +3 -3
  101. package/manifest.mjs +17 -20
  102. package/package.json +1 -2
  103. package/release.mjs +66 -6
  104. package/sohl/actors.mjs +36 -28
  105. package/sohl/affiliation-standings.mjs +2 -2
  106. package/sohl/being-info.mjs +5 -5
  107. package/sohl/default-item-art.mjs +5 -5
  108. package/sohl/document-subtypes.mjs +5 -5
  109. package/sohl/index.mjs +3 -3
  110. package/sohl/item-builders.mjs +7 -7
  111. package/sohl/item-fields.mjs +8 -9
  112. package/sohl/items.mjs +28 -6
  113. package/sohl/kb-passes.mjs +5 -5
  114. package/sohl/note-schemas.mjs +12 -12
  115. package/sohl/skill-base.mjs +1 -1
  116. package/types/content-config.d.mts +91 -39
  117. package/types/e2e.d.mts +3 -3
  118. package/types/engine/actor-compiler.d.mts +45 -40
  119. package/types/engine/address-charset.d.mts +6 -6
  120. package/types/engine/address-diff.d.mts +60 -6
  121. package/types/engine/base-compiler.d.mts +27 -21
  122. package/types/engine/bundle-notes.d.mts +3 -3
  123. package/types/engine/bundles.d.mts +10 -1
  124. package/types/engine/code-fences.d.mts +3 -3
  125. package/types/engine/compendiums.d.mts +3 -3
  126. package/types/engine/compile-corpus.d.mts +1 -1
  127. package/types/engine/content-address.d.mts +20 -20
  128. package/types/engine/content-format-check.d.mts +6 -6
  129. package/types/engine/content-format.d.mts +2 -2
  130. package/types/engine/content-html.d.mts +78 -0
  131. package/types/engine/content-icons.d.mts +139 -92
  132. package/types/engine/content-index.d.mts +59 -15
  133. package/types/engine/content-links.d.mts +8 -8
  134. package/types/engine/content-lint.d.mts +8 -6
  135. package/types/engine/content-package.d.mts +6 -8
  136. package/types/engine/content-tables.d.mts +49 -18
  137. package/types/engine/derived-fields.d.mts +101 -0
  138. package/types/engine/diagnostics.d.mts +2 -2
  139. package/types/engine/document-subtypes.d.mts +3 -3
  140. package/types/engine/field-spec.d.mts +37 -39
  141. package/types/engine/folder-notes.d.mts +4 -5
  142. package/types/engine/foreign-catalog.d.mts +3 -3
  143. package/types/engine/foundry-entries.d.mts +6 -7
  144. package/types/engine/frontmatter-lint.d.mts +10 -9
  145. package/types/engine/frontmatter.d.mts +7 -7
  146. package/types/engine/generate.d.mts +7 -7
  147. package/types/engine/helpers.d.mts +128 -56
  148. package/types/engine/homepage.d.mts +16 -18
  149. package/types/engine/ids.d.mts +13 -13
  150. package/types/engine/index-records.d.mts +3 -3
  151. package/types/engine/index.d.mts +6 -0
  152. package/types/engine/item-compiler.d.mts +21 -5
  153. package/types/engine/item-docs.d.mts +2 -2
  154. package/types/engine/item-registry.d.mts +6 -6
  155. package/types/engine/journals.d.mts +12 -3
  156. package/types/engine/map-notes.d.mts +2 -2
  157. package/types/engine/metadata-index.d.mts +4 -4
  158. package/types/engine/note-claims.d.mts +30 -22
  159. package/types/engine/note-ids.d.mts +4 -4
  160. package/types/engine/note-package.d.mts +1 -1
  161. package/types/engine/note-renames.d.mts +3 -3
  162. package/types/engine/note-vocabulary.d.mts +31 -203
  163. package/types/engine/pack-config.d.mts +7 -7
  164. package/types/engine/pack-router.d.mts +1 -1
  165. package/types/engine/pdf-build.d.mts +42 -0
  166. package/types/engine/pdf-fonts.d.mts +30 -0
  167. package/types/engine/pdf-render.d.mts +144 -0
  168. package/types/engine/pdf-toc.d.mts +114 -0
  169. package/types/engine/prose-config.d.mts +9 -9
  170. package/types/engine/prose-lint.d.mts +3 -4
  171. package/types/engine/region-events.d.mts +2 -2
  172. package/types/engine/retired-fields.d.mts +10 -9
  173. package/types/engine/scenes.d.mts +10 -1
  174. package/types/engine/schema-check.d.mts +13 -13
  175. package/types/engine/site-build.d.mts +52 -25
  176. package/types/engine/site-index.d.mts +3 -4
  177. package/types/engine/sql-tables.d.mts +11 -5
  178. package/types/engine/subtype-registry.d.mts +3 -3
  179. package/types/engine/system-block.d.mts +3 -3
  180. package/types/engine/web-wikilinks.d.mts +7 -7
  181. package/types/engine/wikilink-syntax.d.mts +17 -17
  182. package/types/engine/wikilinks.d.mts +14 -14
  183. package/types/hm3/actors.d.mts +9 -1
  184. package/types/hm3/document-subtypes.d.mts +1 -1
  185. package/types/hm3/items.d.mts +9 -2
  186. package/types/hm3/template-priority.d.mts +1 -1
  187. package/types/manifest.d.mts +8 -8
  188. package/types/release.d.mts +15 -4
  189. package/types/sohl/actors.d.mts +12 -4
  190. package/types/sohl/affiliation-standings.d.mts +2 -2
  191. package/types/sohl/being-info.d.mts +2 -2
  192. package/types/sohl/document-subtypes.d.mts +1 -1
  193. package/types/sohl/items.d.mts +9 -2
  194. package/types/sohl/note-schemas.d.mts +1 -1
  195. package/MIGRATING.md +0 -608
package/CHANGELOG.md CHANGED
@@ -1,5 +1,356 @@
1
1
  # @heroiclands/package-build
2
2
 
3
+ ## 20.5.0
4
+
5
+ ### Minor Changes
6
+
7
+ - cbe3266: **A reference for every subpath entry this package exports**
8
+
9
+ `docs/api.md` documents the whole programmatic surface — `engine`, `sohl`
10
+ and `hm3` included, on the same footing as the packaging half — organized by
11
+ how a consumer imports it: signature, what it returns, and when to reach
12
+ for it, with a runnable example per subpath. Most of it is pure — source
13
+ text or already-loaded data in, findings or values out, leaving discovery,
14
+ I/O and reporting to the caller — and the reference names the handful of
15
+ packaging functions that necessarily touch the filesystem or a subprocess.
16
+ - 8e2b5d3: **A key-by-key reference for `package-build.config.yaml`**
17
+
18
+ `docs/configuration.md` documents every top-level key, every nested key, its
19
+ type, whether it is required, its default, and the exact message an author
20
+ sees when a value is wrong — quoted from the validator, so the error a build
21
+ prints is searchable against the page that explains it.
22
+
23
+ It also documents the values a repository never writes: `rootDir` and
24
+ `foundryPackage` are derived from where the file sits and from the adjacent
25
+ `package.json`; `stats.systemVersion` is derived from `package.json` or from
26
+ `systems:`; `itemBuilders` accepts a registry name (`sohl`, `hm3`) in YAML,
27
+ resolved before validation. Authoring the first three directly is refused,
28
+ with the message that says so.
29
+
30
+ `packageBuild:` — the section `@heroiclands/package-build`'s own packaging
31
+ half reads — gets the same treatment: staging assets, the manifest
32
+ pass-through and the keys it derives and refuses to have overwritten, the
33
+ localization coverage settings, the container and end-to-end test
34
+ configuration.
35
+ - cc3d90b: **The content tree publishes as a book**
36
+
37
+ A third surface beside the compendium packs and the website: one searchable,
38
+ bookmarked PDF, built by `content-build pdf` and attached to a release by
39
+ `package-build release`.
40
+
41
+ **A book is a selection, not a rendering of everything.** The packs and the site
42
+ publish the whole tree; a book is a declared structure whose leaves pick notes
43
+ out of the corpus with a `WHERE` clause, interleaved with prose that need not be
44
+ in the tree at all. `pdf.document` names that structure.
45
+
46
+ ```yaml
47
+ pdf:
48
+ title: The Hârn Ensemble
49
+ document: book.yaml
50
+ fonts:
51
+ serif: Libertinus Serif
52
+ mono: DejaVu Sans Mono
53
+ ```
54
+
55
+ **`publish.site` decides whether one is built, and it is the only switch.**
56
+ `content` builds a book; `homepage` does not — the same fence that stops the
57
+ tree being walked for pages stops it being walked for a book, so the four
58
+ packages that publish only a homepage cannot start emitting a content document
59
+ because a `pdf:` block appeared. A package with no block, no tree, or no
60
+ compiler builds nothing, says why, and exits 0.
61
+
62
+ | Property | How it is got |
63
+ | ----------------------- | ------------------------------------------------------------------- |
64
+ | Searchable | Real text; every embedded font carries a `ToUnicode` map. |
65
+ | Bookmark outline | Every section and entry is a heading, so the sidebar is the way in. |
66
+ | Page-numbered contents | Shallower than the bookmarks — 2,500 entries would be 40 pages. |
67
+ | Repeating table headers | A property table spilling a page keeps its column names. |
68
+ | Internal references | A wikilink between two notes of the book resolves inside the PDF. |
69
+ | External references | A cross-package link, or a note not selected, stays a URL. |
70
+
71
+ **Typst is a binary, not a dependency.** It is found on `PATH` or named by
72
+ `pdf.binary`. Bundling a native compiler would put a platform-specific artefact
73
+ in the dependency tree of three repositories, only one of which is mostly a
74
+ book. A missing binary is a finding, and the `.typ` source is written anyway.
75
+
76
+ Proved against `harn-ensemble`: 2,517 entries, 1,270 pages, 10,421 outline
77
+ nodes, 34 seconds, no findings.
78
+
79
+ Additive — a package that configures no `pdf:` block is unaffected.
80
+ - c9dfa50: **A `doc` has two more genres to choose from**
81
+
82
+ `subType: howto` and `subType: concept` join `rules`, `userguide` and
83
+ `reference`:
84
+
85
+ - **`howto`** — a task with an outcome, written as the steps that reach it.
86
+ - **`concept`** — an explanation of how something works and why it is shaped
87
+ that way, read to understand rather than to follow.
88
+
89
+ Between them they cover the prose a package writes about itself, which had no
90
+ genre to declare and was left to a directory name to imply.
91
+
92
+ `subType` stays _a genre and only a genre_: it says what kind of page this is,
93
+ never who reads it. A page written for a developer is a `howto` or a `concept`
94
+ like any other, and the audience is the section it sits in.
95
+
96
+ Both spellings are one word, as `userguide` is: a `subType` is held to the
97
+ address charset, so `how-to` is refused for its hyphen.
98
+ - 00ce257: **A package that publishes documentation**
99
+
100
+ `packageKind` takes a third value, `documentation`: a package that publishes a
101
+ website and the book built from the same notes, and compiles no Foundry
102
+ documents at all. `systems` and `modules` say where Foundry installs a package;
103
+ `documentation` says it installs nowhere.
104
+
105
+ ```yaml
106
+ contentPackage: toolkit
107
+ packageKind: documentation
108
+
109
+ publish:
110
+ site: content
111
+ address: { prefix: guide/ }
112
+
113
+ site:
114
+ out: site/content
115
+ ```
116
+
117
+ `publish` is required, and `site: content` — publishing the tree is the whole of
118
+ what the kind does, and `content` is also what builds the book.
119
+
120
+ **What it refuses, by name and with a locator.** `packs`, `itemBuilders`,
121
+ `docs`, `compatibility`, `relationships`, `systems`, `requiresSystem`, `stats`
122
+ and `foundryPackage` each describe a Foundry package, so each fails at load
123
+ naming the key and the line and column it was written on, rather than being read
124
+ and ignored. `packs` is otherwise still required to declare at least one pack.
125
+
126
+ **What follows from the kind.**
127
+
128
+ - _No manifest, and no compile._ `package-build manifest` refuses rather than
129
+ writing a `module.json` for a package Foundry never installs. The compile
130
+ passes refuse too, rather than exiting 0 having compiled nothing.
131
+ - _No Foundry ids to author._ A note's id is derived from its address, and no
132
+ pass here asks for a pinned one.
133
+ - _`doc` and `homepage` are the whole vocabulary._ Every other note type exists
134
+ to become a Foundry document, so a note carrying one has no destination;
135
+ `content-build lint` reports it at its `type:` line.
136
+ - _No asset root._ `assetRoot` and `foundryPackage` resolve to nothing, so a
137
+ note's `img:` names the owning package (`systems/…`, `modules/…`) or a URL.
138
+ A path this package would have to serve itself is refused.
139
+ - _A content index all the same._ `content-build content-index` emits
140
+ `<contentPackage>-metadata.jsonl` as it does everywhere else, so another
141
+ package can resolve an address into this one.
142
+
143
+ Systems and modules are unchanged: the asset root, the `_stats` stamp and the
144
+ pack requirement all behave exactly as before.
145
+ - 46d6de3: **Getting started** — `docs/getting-started.md` walks an empty directory to a
146
+ package that builds: identity, configuration, a first note, the checks, the
147
+ compiled packs, the manifest, the content index and the release archive. Each
148
+ step says what it produces and how to tell it worked, with the output it
149
+ actually prints. It was written by walking it.
150
+
151
+ **Project setup** — `docs/project-setup.md` covers what a repository carries
152
+ beyond the build configuration: `package.json` and what each script in the chain
153
+ is _for_, the shared Prettier re-export and what `.prettierignore` is really
154
+ guarding, the packaged git hooks and their per-hook switches, `.changeset/` and
155
+ the four settings that are decisions rather than preferences, the label registry
156
+ pair, and the directory layout — what the build reads, and everything it writes
157
+ under `build/`.
158
+ - f9e0e27: **`content-build pdf --version` is now `--book-version`.**
159
+
160
+ `--version` collided with yargs' own reserved top-level `--version`, so the
161
+ option could not actually take a value — passing one failed with
162
+ `Unknown argument`. `--book-version` stamps the title page and the file name
163
+ exactly as before; the plain `content-build --version` answers this package's
164
+ own version, unaffected.
165
+
166
+ **A thrown error from `content-build pdf` no longer crashes with a
167
+ `ReferenceError`.** It now reports the same located diagnostic and non-zero
168
+ exit every other command's catch block produces.
169
+ - a6c77d2: **A guide to reading this toolchain's diagnostics**
170
+
171
+ `docs/diagnostics.md` explains the `file:line:column: severity: message` form
172
+ every warning and error carries: why a field is dropped rather than guessed,
173
+ why both severities print to stderr, how a configuration error is located,
174
+ and which commands fail a run on an error-severity finding. It closes with a
175
+ runnable example that parses a command's output programmatically.
176
+ - 51e334a: **A full command reference**
177
+
178
+ `docs/commands.md` documents every command both binaries expose — `package-build`
179
+ and `content-build`, 25 commands between them — with what each reads, what it
180
+ writes, its options and their defaults, its exit codes, and a worked example.
181
+
182
+ Several corners never had a home before this: `content-build pdf`, and the
183
+ options `--coverage`, `--doc`, `--fields`, `--id`, `--references`, `--registry`
184
+ and `--root`.
185
+
186
+ The document is checked against the actual `yargs` definitions in both
187
+ binaries, so an option or an action added to either one and left undocumented
188
+ fails the build.
189
+
190
+ ### Patch Changes
191
+
192
+ - 6e80fbd: **`content-config.mjs`'s own documentation now matches what `defineConfig` accepts**
193
+
194
+ The worked example at the top of `content-config.mjs` — and its `.mjs` twin in
195
+ `CONTENT.md` — authored `stats.systemId`, a key `defineConfig` refuses as
196
+ derived. Both now carry only what loads.
197
+
198
+ The `contentPackage` refusal, and the sibling refusal for a section's
199
+ `listType` / `listSubType`, named the wrong character class — `[A-Za-z0-9]`
200
+ when the enforced charset is lowercase only. Both now say `lowercase
201
+ alphanumeric` and print the pattern actually enforced, so an author who writes
202
+ `contentPackage: PackageBuild` is told what is wrong with it rather than sent
203
+ looking for a character they do not have.
204
+ - bd6c20b: **`docs/configuration.md` now matches `packageKind: documentation`**
205
+
206
+ The configuration reference names all three `packageKind` values —
207
+ `systems`, `modules` and `documentation` — in the summary table and in the
208
+ `packageKind` section itself, and states which keys a `documentation`
209
+ package requires, which it refuses (quoting each located refusal message
210
+ verbatim), and how `foundryPackage`, `assetRoot` and `stats` resolve for it.
211
+ - fb04049: **`content-build docs item-fields --check` reports a stale page in the located form**
212
+
213
+ The stale-page diagnostic now starts with the file's path, unprefixed by a
214
+ timestamp — matching every other located failure this command line emits, and
215
+ readable by the same tools that already parse the rest of them.
216
+ - 46b39ef: **The published types match the code they are generated from**
217
+
218
+ The `.d.mts` files ship with `@heroiclands/package-build` and are generated
219
+ from the JSDoc, so a block that is not the one belonging to a symbol ships as
220
+ that symbol's type. `packRelease` now declares the `pdf` option it accepts and
221
+ the `pdf`, `pdfFindings` and `pdfSkipped` fields it returns; `buildSite` and
222
+ `expandNoteTables` declare `sqlTables`; a compiler's `resolveEmbedded`
223
+ declares `modelPackage`; and `expandContentTables` declares the `warnings` it
224
+ returns and the `column` on every error entry. Type-checking the whole
225
+ published declaration surface is clean.
226
+
227
+ **Every exported symbol carries documentation of its own**
228
+
229
+ `NOTE_VOCABULARY`, `DECLARED_TAGS`, `buildIndexRecord`, `collectContentIndex`,
230
+ `expandContentTables`, `walkMarkdownTree`, `declaredPredecessors` and the seven
231
+ pack compiler classes each describe what they take and what they return, so
232
+ hovering one in an editor answers the question asked of it.
233
+ - de54d45: `docs/commands.md` reads as a manual page. Every command carries the same
234
+ labelled sections — **NAME**, **SYNOPSIS**, **DESCRIPTION**, **OPTIONS**,
235
+ **EXIT STATUS**, **EXAMPLES**, **SEE ALSO** — in the same order, so jumping to
236
+ the right command means jumping to the right label. **SEE ALSO** cross-links
237
+ the commands that answer a related question, and every command that emits
238
+ findings or reads a configuration key now points at _Diagnostics_ or
239
+ _Configuration_ directly.
240
+
241
+ `package-build lang check` / `coverage` / `hardcoded` and
242
+ `content-build content-format schema` / `fields` / `notes` each get their own
243
+ section, rather than sharing one.
244
+ - 40fcc1a: **A frontmatter reference resolves in any package the tree can reach.**
245
+
246
+ A `ref:` field — `parentSkillCode`, `assocSkillCode`, `assocAffiliationCode` —
247
+ holds a shortcode, not an address. The system persists it as written and looks
248
+ it up at runtime among the items embedded on one actor, and an actor assembled
249
+ from several packages carries their items side by side. So the reference check
250
+ now asks only whether _any_ reachable package declares the `type`/`shortcode`
251
+ pair: local notes first, then the fetched dependency indexes, with package and
252
+ system wildcarded.
253
+
254
+ This is the rule for a reference alone. A wikilink is unchanged — its target is
255
+ a document to point at, so an omitted package still means this one, and reaching
256
+ another package still requires the fully qualified form.
257
+
258
+ A tree whose references name a parent in a dependency saw every one of them
259
+ reported:
260
+
261
+ | note | `sohl.parentSkillCode` | before | after |
262
+ | ----------------------- | ---------------------- | ------------ | -------------------------- |
263
+ | a language skill | `lang` | no such note | resolves in the dependency |
264
+ | a spirit specialisation | `spirit` | no such note | resolves in the dependency |
265
+
266
+ A reference naming a shortcode no package declares is still an error, and the
267
+ value a note writes is still the value its document carries.
268
+
269
+ `buildLinkIndex` gains `referenceHit(target)`, which is what performs this
270
+ lookup.
271
+ - a331709: **The address-segment charset is documented as lowercase, matching what it enforces.**
272
+
273
+ Comments, JSDoc and the reference documentation described `contentPackage`,
274
+ `type`, `subType` and `shortcode` as `^[A-Za-z0-9]+$` or plainly "alphanumeric",
275
+ which reads as case-insensitive. The charset every one of them is held to is
276
+ lowercase-only, and the wording now says so — in prose and in the refusal
277
+ messages an author hits when a value breaks it.
278
+
279
+ ## 20.4.0
280
+
281
+ ### Minor Changes
282
+
283
+ - 7b24587: Four rules, all of them about a note being renderable into a book.
284
+
285
+ **A package declares its own icons**, through a new `icons:` configuration key
286
+ validated when the configuration resolves. See the entry below for the shape it
287
+ settled on.
288
+
289
+ **Raw HTML in a note's prose is reported.** There is no route from `<p>` to a
290
+ PDF: the packs and the website pass HTML through, and Typst is handed markdown
291
+ and knows none. A fenced block or a code span is an example and is not
292
+ reported. A warning, like the checks beside it.
293
+
294
+ **A note may not author a key the compiler derives.** `sohl.system.docHtml`
295
+ holds the `@UUID` of the JournalEntry the note's prose compiled into, and the
296
+ compiler writes it unconditionally — so an authored one is overwritten, or ships
297
+ prose where every reader expects a pointer. Each pass declares its own derived
298
+ keys, so the rule is the general one rather than a list of names.
299
+
300
+ **A SQL table selecting nothing renders its header and rule** rather than
301
+ nothing at all. The finding is the point, not withholding the output: a heading
302
+ with an empty table under it says the query ran and matched nothing, where a
303
+ heading with nothing under it reads as a page that failed to build.
304
+ - 7695b06: **The icon registry belongs to the consumer, not to the toolchain.**
305
+
306
+ `DEFAULT_ICONS` and `ICON_FAMILIES` are gone. A package declares both halves —
307
+ the fonts it ships and the names it draws from them — in its own `icons:`
308
+ configuration, and a package that declares neither names no icons at all.
309
+
310
+ A registry entry is a promise that a glyph will render, and only the package
311
+ shipping the font can keep it: the Game-Icons webfont is built by a consumer
312
+ from its own templates, and Font Awesome reaches neither the knowledgebase nor a
313
+ printed page unless somebody puts it there. A shipped table would also be one
314
+ game system's vocabulary — `victory-star-tester` means nothing to another system
315
+ compiled by this same toolchain. What is shared is the mechanism: the `:icon-…:`
316
+ syntax, resolution, rendering, and the checks.
317
+
318
+ The value is either the registry inline or a **path to a file holding it**:
319
+
320
+ ```yaml
321
+ icons: assets/icon-registry.yaml
322
+ ```
323
+
324
+ The file form is what a real package wants, because a registry is derived from
325
+ what the interface actually draws — so it is generated, and a generated document
326
+ inlined into a hand-edited configuration conflicts on every regeneration.
327
+
328
+ A **family** declares its class prefix and the weights it ships. A style is
329
+ checked against that list rather than against Font Awesome's three, so a font
330
+ with five weights or none is describable. An entry may declare `fixedWidth`,
331
+ which emits `fa-fw`: whether a glyph needs a full advance to sit in a column of
332
+ controls is a fact about that glyph, so it belongs to the table rather than to a
333
+ note's use of it.
334
+
335
+ ### Patch Changes
336
+
337
+ - 05fdfa7: Drop history, issue references and hand-counted values from the comments and
338
+ the shipped documentation.
339
+
340
+ A comment citing the issue it came from tells a reader nothing they can act on,
341
+ and a rule explained by narrating the shape it replaced buries what is true now.
342
+ Both are removed throughout `engine/`, `sohl/`, `hm3/`, `bin/`, `ci/`, the test
343
+ suites and the reference docs; the reasoning survives, stated in the present
344
+ tense.
345
+
346
+ `MIGRATING.md` is deleted and drops out of the published `files`. It carried
347
+ upgrade instructions for 15.0.0 down to 3.0.0, and no consumer is below 18.
348
+
349
+ `CHANGELOG.md` and `CHANGELOG-content-build.md` are untouched — history belongs
350
+ in them.
351
+
352
+ No behavior changes.
353
+
3
354
  ## 20.3.1
4
355
 
5
356
  ### Patch Changes