@heroiclands/package-build 20.3.0 → 20.4.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.
- package/CHANGELOG.md +97 -0
- package/CONTENT.md +111 -92
- package/README.md +2 -9
- package/bin/content-build.mjs +70 -61
- package/bin/package-build.mjs +2 -2
- package/config.mjs +6 -8
- package/content-config.mjs +187 -64
- package/docs/content-format.md +57 -68
- package/e2e.mjs +4 -4
- package/engine/actor-compiler.mjs +36 -36
- package/engine/address-charset.mjs +6 -6
- package/engine/address-diff.mjs +12 -11
- package/engine/anchored-sections.mjs +1 -1
- package/engine/anchors.mjs +1 -1
- package/engine/base-compiler.mjs +36 -38
- package/engine/bundle-notes.mjs +4 -4
- package/engine/bundles.mjs +8 -8
- package/engine/code-fences.mjs +3 -3
- package/engine/compendiums.mjs +8 -8
- package/engine/compile-corpus.mjs +4 -5
- package/engine/content-address.mjs +15 -15
- package/engine/content-charset.mjs +1 -1
- package/engine/content-format-check.mjs +24 -25
- package/engine/content-format.mjs +8 -8
- package/engine/content-html.mjs +202 -0
- package/engine/content-icons.mjs +225 -98
- package/engine/content-index.mjs +17 -17
- package/engine/content-links.mjs +30 -30
- package/engine/content-lint.mjs +20 -24
- package/engine/content-package.mjs +7 -9
- package/engine/content-slug.mjs +2 -2
- package/engine/content-tables.mjs +7 -8
- package/engine/content-tree.mjs +1 -1
- package/engine/derived-fields.mjs +174 -0
- package/engine/diagnostics.mjs +3 -4
- package/engine/document-subtypes.mjs +6 -7
- package/engine/field-reference.mjs +8 -8
- package/engine/field-spec.mjs +29 -30
- package/engine/folder-notes.mjs +14 -14
- package/engine/foreign-catalog.mjs +8 -9
- package/engine/foundry-entries.mjs +19 -20
- package/engine/frontmatter-lint.mjs +64 -69
- package/engine/frontmatter.mjs +11 -11
- package/engine/generate.mjs +39 -39
- package/engine/helpers.mjs +63 -54
- package/engine/homepage.mjs +20 -22
- package/engine/ids.mjs +15 -15
- package/engine/index-records.mjs +4 -4
- package/engine/index.mjs +14 -8
- package/engine/item-compiler.mjs +54 -29
- package/engine/item-docs.mjs +11 -13
- package/engine/item-registry.mjs +13 -13
- package/engine/journals.mjs +15 -15
- package/engine/macros.mjs +3 -3
- package/engine/map-notes.mjs +6 -6
- package/engine/metadata-index.mjs +5 -5
- package/engine/note-claims.mjs +36 -34
- package/engine/note-ids.mjs +5 -5
- package/engine/note-package.mjs +4 -4
- package/engine/note-renames.mjs +3 -3
- package/engine/note-schemas.mjs +3 -3
- package/engine/note-vocabulary.mjs +27 -26
- package/engine/pack-config.mjs +13 -13
- package/engine/pack-router.mjs +0 -0
- package/engine/prose-config.mjs +9 -9
- package/engine/prose-lint.mjs +12 -13
- package/engine/region-events.mjs +2 -2
- package/engine/retired-fields.mjs +24 -22
- package/engine/runtime-only-fields.mjs +1 -1
- package/engine/scene-levels.mjs +1 -1
- package/engine/scenes.mjs +19 -20
- package/engine/schema-check.mjs +20 -20
- package/engine/schema-extract.mjs +1 -1
- package/engine/site-build.mjs +45 -47
- package/engine/site-index.mjs +17 -18
- package/engine/sql-tables.mjs +21 -13
- package/engine/subtype-registry.mjs +5 -4
- package/engine/system-block.mjs +18 -19
- package/engine/systems.mjs +2 -2
- package/engine/web-wikilinks.mjs +35 -35
- package/engine/wikilink-syntax.mjs +16 -16
- package/engine/wikilinks.mjs +39 -39
- package/hm3/actors.mjs +22 -22
- package/hm3/document-subtypes.mjs +5 -5
- package/hm3/index.mjs +2 -2
- package/hm3/item-builders.mjs +1 -1
- package/hm3/item-fields.mjs +3 -3
- package/hm3/items.mjs +20 -8
- package/hm3/template-priority.mjs +2 -2
- package/lang.mjs +3 -3
- package/manifest.mjs +17 -20
- package/package.json +1 -2
- package/release.mjs +3 -3
- package/sohl/actors.mjs +28 -28
- package/sohl/affiliation-standings.mjs +2 -2
- package/sohl/being-info.mjs +5 -5
- package/sohl/default-item-art.mjs +5 -5
- package/sohl/document-subtypes.mjs +5 -5
- package/sohl/index.mjs +3 -3
- package/sohl/item-builders.mjs +7 -7
- package/sohl/item-fields.mjs +8 -9
- package/sohl/items.mjs +20 -6
- package/sohl/kb-passes.mjs +5 -5
- package/sohl/note-schemas.mjs +7 -7
- package/sohl/skill-base.mjs +1 -1
- package/types/content-config.d.mts +25 -24
- package/types/e2e.d.mts +3 -3
- package/types/engine/actor-compiler.d.mts +14 -13
- package/types/engine/address-charset.d.mts +6 -6
- package/types/engine/address-diff.d.mts +3 -3
- package/types/engine/base-compiler.d.mts +17 -19
- package/types/engine/bundle-notes.d.mts +3 -3
- package/types/engine/bundles.d.mts +1 -1
- package/types/engine/code-fences.d.mts +3 -3
- package/types/engine/compendiums.d.mts +3 -3
- package/types/engine/compile-corpus.d.mts +1 -1
- package/types/engine/content-address.d.mts +11 -11
- package/types/engine/content-format-check.d.mts +6 -6
- package/types/engine/content-format.d.mts +2 -2
- package/types/engine/content-html.d.mts +78 -0
- package/types/engine/content-icons.d.mts +150 -62
- package/types/engine/content-index.d.mts +2 -2
- package/types/engine/content-links.d.mts +8 -8
- package/types/engine/content-lint.d.mts +2 -2
- package/types/engine/content-package.d.mts +6 -8
- package/types/engine/derived-fields.d.mts +101 -0
- package/types/engine/diagnostics.d.mts +2 -2
- package/types/engine/document-subtypes.d.mts +3 -3
- package/types/engine/field-spec.d.mts +37 -39
- package/types/engine/folder-notes.d.mts +4 -5
- package/types/engine/foreign-catalog.d.mts +3 -3
- package/types/engine/foundry-entries.d.mts +6 -7
- package/types/engine/frontmatter-lint.d.mts +7 -7
- package/types/engine/frontmatter.d.mts +7 -7
- package/types/engine/generate.d.mts +7 -7
- package/types/engine/helpers.d.mts +25 -27
- package/types/engine/homepage.d.mts +16 -18
- package/types/engine/ids.d.mts +13 -13
- package/types/engine/index-records.d.mts +3 -3
- package/types/engine/index.d.mts +2 -0
- package/types/engine/item-compiler.d.mts +21 -5
- package/types/engine/item-docs.d.mts +2 -2
- package/types/engine/item-registry.d.mts +6 -6
- package/types/engine/journals.d.mts +3 -3
- package/types/engine/map-notes.d.mts +2 -2
- package/types/engine/metadata-index.d.mts +4 -4
- package/types/engine/note-claims.d.mts +16 -15
- package/types/engine/note-ids.d.mts +4 -4
- package/types/engine/note-package.d.mts +1 -1
- package/types/engine/note-renames.d.mts +3 -3
- package/types/engine/note-vocabulary.d.mts +9 -8
- package/types/engine/pack-config.d.mts +3 -3
- package/types/engine/pack-router.d.mts +1 -1
- package/types/engine/prose-config.d.mts +9 -9
- package/types/engine/prose-lint.d.mts +3 -4
- package/types/engine/region-events.d.mts +2 -2
- package/types/engine/retired-fields.d.mts +10 -9
- package/types/engine/schema-check.d.mts +11 -11
- package/types/engine/site-build.d.mts +18 -19
- package/types/engine/site-index.d.mts +3 -4
- package/types/engine/sql-tables.d.mts +11 -5
- package/types/engine/subtype-registry.d.mts +3 -3
- package/types/engine/system-block.d.mts +3 -3
- package/types/engine/web-wikilinks.d.mts +7 -7
- package/types/engine/wikilink-syntax.d.mts +17 -17
- package/types/engine/wikilinks.d.mts +13 -12
- package/types/hm3/actors.d.mts +1 -1
- package/types/hm3/document-subtypes.d.mts +1 -1
- package/types/hm3/items.d.mts +1 -2
- package/types/hm3/template-priority.d.mts +1 -1
- package/types/manifest.d.mts +8 -8
- package/types/sohl/actors.d.mts +2 -2
- package/types/sohl/affiliation-standings.d.mts +2 -2
- package/types/sohl/being-info.d.mts +2 -2
- package/types/sohl/document-subtypes.d.mts +1 -1
- package/types/sohl/items.d.mts +1 -2
- package/types/sohl/note-schemas.d.mts +1 -1
- package/MIGRATING.md +0 -608
package/CONTENT.md
CHANGED
|
@@ -65,6 +65,35 @@ itemBuilders: sohl
|
|
|
65
65
|
# Directory names the content walk ignores wherever they appear.
|
|
66
66
|
skipDirectories: [Templates]
|
|
67
67
|
|
|
68
|
+
# Optional. The icon fonts this package ships and the names its notes draw from
|
|
69
|
+
# them. Nothing is supplied by default: an entry is a promise that a glyph will
|
|
70
|
+
# render, and only the package shipping the font can keep it.
|
|
71
|
+
#
|
|
72
|
+
# Either the registry itself, or a path to a file holding it — the file form is
|
|
73
|
+
# what a real package wants, because a registry is generated from what the
|
|
74
|
+
# interface draws and a generated document inlined here conflicts on every
|
|
75
|
+
# regeneration.
|
|
76
|
+
icons: assets/icon-registry.yaml
|
|
77
|
+
#
|
|
78
|
+
# The same, written inline:
|
|
79
|
+
#
|
|
80
|
+
# icons:
|
|
81
|
+
# families:
|
|
82
|
+
# # `class` is the stylesheet prefix; `styles` are the weights the font
|
|
83
|
+
# # ships, and `[]` means it has none.
|
|
84
|
+
# fontawesome: { class: fa, styles: [solid, regular, brands], describe: Font Awesome Free }
|
|
85
|
+
# game-icons: { class: ginf, styles: [], describe: the Game-Icons webfont }
|
|
86
|
+
# # Which family an entry with no `family` belongs to. Optional where exactly
|
|
87
|
+
# # one is declared, since then there is nothing to choose between.
|
|
88
|
+
# defaultFamily: fontawesome
|
|
89
|
+
# icons:
|
|
90
|
+
# # A name is what a note writes between the colons, in the charset an
|
|
91
|
+
# # address segment uses. `fixedWidth` asks for a full advance, which a
|
|
92
|
+
# # glyph like an ellipsis needs to sit in a column of controls.
|
|
93
|
+
# being: { style: solid, icon: user, label: being }
|
|
94
|
+
# context-menu: { style: solid, icon: ellipsis-vertical, fixedWidth: true, label: context menu }
|
|
95
|
+
# vehicle: { family: game-icons, icon: old-wagon, label: vehicle }
|
|
96
|
+
|
|
68
97
|
# Optional; each path is relative to this file's directory and defaults to the
|
|
69
98
|
# conventional layout shown here.
|
|
70
99
|
paths:
|
|
@@ -349,7 +378,7 @@ pack: mysteries
|
|
|
349
378
|
that type's default implicitly; a type with several designates one with
|
|
350
379
|
`default: true`. Where several exist and none is marked, a declaration is
|
|
351
380
|
**mandatory** and an undeclared note fails the build.
|
|
352
|
-
- **A default is per system, not merely per type
|
|
381
|
+
- **A default is per system, not merely per type**. The rule above counts
|
|
353
382
|
every pack of a type together, so a tree shipping one Actor pack per system has
|
|
354
383
|
two and would need a flag — except that asked _per system_ the layout is
|
|
355
384
|
unambiguous, one pack each, for the same reason a single-pack type needs no
|
|
@@ -373,11 +402,11 @@ pack: mysteries
|
|
|
373
402
|
it — an item's or a macro's prose, which compiles into a JournalEntry of its
|
|
374
403
|
own — lands in the default pack of _that_ type.
|
|
375
404
|
- **Every document a note produces needs a pack, and one that has none is a
|
|
376
|
-
finding
|
|
405
|
+
finding**. A note produces more than one document as a matter of
|
|
377
406
|
course: an item note an Item and the JournalEntry its prose becomes, a map
|
|
378
407
|
note a Scene and a JournalEntry, an actor note an Actor and a JournalEntry
|
|
379
|
-
|
|
380
|
-
document
|
|
408
|
+
too. Where the configuration declares no pack for one of them, that
|
|
409
|
+
document would be dropped while the rest of the note compiled into a pack
|
|
381
410
|
that does exist — a build that succeeds and ships half of what was written.
|
|
382
411
|
The finding names the note, the class with no pack, and the class that did
|
|
383
412
|
compile, which is what distinguishes it from a note **nothing** claims: that
|
|
@@ -388,7 +417,7 @@ pack: mysteries
|
|
|
388
417
|
no doc — so a tree of deliberately description-less items loses nothing by
|
|
389
418
|
having no JournalEntry pack, and is told nothing. And it names no system, so a
|
|
390
419
|
type one system maps and another does not stays silent for the system that
|
|
391
|
-
declines it
|
|
420
|
+
declines it.
|
|
392
421
|
|
|
393
422
|
**The configuration is found by walking up from the working directory, and from
|
|
394
423
|
the installed package only if that finds nothing.** `engine/pack-config.mjs`
|
|
@@ -402,7 +431,7 @@ with **no `node_modules` of its own** resolves `@heroiclands/package-build` out
|
|
|
402
431
|
of the parent's, because Node's resolution walks parent directories. Climbing
|
|
403
432
|
from the module then landed on the _parent's_ configuration, and the build
|
|
404
433
|
compiled the parent's content tree into the parent's `build/` and exited 0
|
|
405
|
-
|
|
434
|
+
. When both walks find a configuration and they disagree, the working
|
|
406
435
|
directory's is read and the ignored one is named in a warning — that
|
|
407
436
|
disagreement is also the cheapest signal that this tree is building on another
|
|
408
437
|
checkout's `node_modules`. Run `npm ci` in the worktree to give it its own.
|
|
@@ -435,7 +464,7 @@ resolved set at runtime; the compilers and the link-manifest emitter cannot come
|
|
|
435
464
|
to disagree about which notes carry documentation.
|
|
436
465
|
|
|
437
466
|
**Every note compiling into a system-bearing document carries documentation, and
|
|
438
|
-
that includes actors
|
|
467
|
+
that includes actors**. `docEntryTypes` is `itemTypes` plus the actor
|
|
439
468
|
types the shipped subtype maps declare (`ACTOR_TYPES`, derived from them rather
|
|
440
469
|
than listed again), plus `macro` and the map types. Only `doc` is outside it, for
|
|
441
470
|
the reason that actually applies to it: its single document _is_ the prose.
|
|
@@ -487,7 +516,7 @@ than one registry declares, **throws** rather than answering with whichever was
|
|
|
487
516
|
declared first.
|
|
488
517
|
|
|
489
518
|
**`hm3` is a real registry, and the rest of the pipeline follows the same
|
|
490
|
-
field.**
|
|
519
|
+
field.** This package ships two system halves, `sohl/` and `hm3/`,
|
|
491
520
|
each with its own builders, its own default art and its own note-type →
|
|
492
521
|
document-subtype map; they share the engine between them and import nothing from
|
|
493
522
|
each other. A pack's `system:` is what selects among them — the Item and Actor
|
|
@@ -513,10 +542,9 @@ what its documents are stamped `_stats.systemId` and `systemVersion` from, and
|
|
|
513
542
|
the version can only come from that block — or, for a package whose packs are
|
|
514
543
|
all for its own system, from the package-wide stats. A pack naming a system that
|
|
515
544
|
resolves to neither is refused at configuration time, naming the pack and the
|
|
516
|
-
entry to add.
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
configuration says `system: sohl` on the line above.
|
|
545
|
+
entry to add. Falling through and stamping `null` for both is a plausible lie:
|
|
546
|
+
a pack whose configuration says `system: sohl` on the line above ships every
|
|
547
|
+
compiled actor with no system at all.
|
|
520
548
|
|
|
521
549
|
No `default: true` anywhere, because each system has exactly one pack of each
|
|
522
550
|
type and a default is resolved per system. Marking one is still allowed and
|
|
@@ -536,12 +564,12 @@ note says which by writing `hm3.type`. Nothing is inferred from the note's own
|
|
|
536
564
|
`subType`, and a note that says nothing is an error naming the note and listing
|
|
537
565
|
the permitted values.
|
|
538
566
|
|
|
539
|
-
**Configuration is the source, and the manifest is generated from it.**
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
567
|
+
**Configuration is the source, and the manifest is generated from it.** The
|
|
568
|
+
floor is the top-level `compatibility.minimum`, the id is derived from
|
|
569
|
+
`package.json` `name`, and `@heroiclands/package-build` writes the manifest from
|
|
570
|
+
this file. There is no `paths.packageManifest` pointing at a hand-authored
|
|
571
|
+
`system.template.json` for a package-id guard or a `_stats.coreVersion` stamp to
|
|
572
|
+
read out of.
|
|
545
573
|
|
|
546
574
|
### Declaration order is presentation, not compile order
|
|
547
575
|
|
|
@@ -572,11 +600,11 @@ passes that had to move. When the two orders differ the build says so:
|
|
|
572
600
|
another's output compiles after it, whatever order `packs:` declares.
|
|
573
601
|
```
|
|
574
602
|
|
|
575
|
-
This
|
|
603
|
+
This is not the author's problem, and it would be a nasty one: an Actor pack declaring
|
|
576
604
|
first compiled only where an earlier run had already left `build/packs-json`
|
|
577
605
|
populated. `build/` is gitignored, so it was green on every local tree that had
|
|
578
606
|
built once and exit 1 on every fresh checkout and CI runner, over a message that
|
|
579
|
-
named a missing directory rather than the ordering that caused it
|
|
607
|
+
named a missing directory rather than the ordering that caused it. A
|
|
580
608
|
consumer registering a compiler of its own declares its dependencies the same
|
|
581
609
|
way; a type no pack of which is declared is simply not waited for.
|
|
582
610
|
|
|
@@ -654,7 +682,7 @@ address different places — `img:` a file Foundry serves, `banner:` a file the
|
|
|
654
682
|
CDN serves — so they are stated apart rather than reconciled. See the
|
|
655
683
|
[content format specification](docs/content-format.md#banner-addresses-the-cdn-not-the-foundry-install).
|
|
656
684
|
|
|
657
|
-
#### "Names no art" and "wants no art" are different
|
|
685
|
+
#### "Names no art" and "wants no art" are different
|
|
658
686
|
|
|
659
687
|
A note has two ways to leave `img:` empty, and they mean opposite things:
|
|
660
688
|
|
|
@@ -668,7 +696,7 @@ A note has two ways to leave `img:` empty, and they mean opposite things:
|
|
|
668
696
|
`resolveImg` returns `null` for the first two and `""` for the third, and every
|
|
669
697
|
caller pairs its default with **nullish** coalescing — `resolveImg(fm.img) ?? itemArt(type)`.
|
|
670
698
|
Never `||`: that collapses a deliberate blank back into the default and takes the
|
|
671
|
-
distinction away again
|
|
699
|
+
distinction away again.
|
|
672
700
|
|
|
673
701
|
**`portrait` is the same field twice over.** A being carries `img` (its token
|
|
674
702
|
art) and `portrait` (its sheet portrait) independently, and both resolve through
|
|
@@ -681,13 +709,11 @@ rather than two.
|
|
|
681
709
|
> **The rule is `img`'s, and does not extend to `title`.** `title` is not art
|
|
682
710
|
> and never reaches `resolveImg`, so nothing here applies to it.
|
|
683
711
|
>
|
|
684
|
-
> The
|
|
685
|
-
>
|
|
686
|
-
>
|
|
687
|
-
>
|
|
688
|
-
>
|
|
689
|
-
> `"null"`. The field declares `topLevelMeans` now, so the top-level key is no
|
|
690
|
-
> longer a source for it (#218).
|
|
712
|
+
> The field declares `topLevelMeans`, so the top-level key is not a source for
|
|
713
|
+
> an `affiliation` item's `system.title`. Were it one, a single authored key
|
|
714
|
+
> would feed two unrelated destinations that disagree about what empty means,
|
|
715
|
+
> and `title: null` would stringify into the compiled document as the literal
|
|
716
|
+
> `"null"`.
|
|
691
717
|
>
|
|
692
718
|
> So `title: null` is a note declining to state a heading, and the site emitter's
|
|
693
719
|
> `fm.title ?? name` falls back to `name.full`. `title: ""` publishes a
|
|
@@ -699,9 +725,9 @@ rather than two.
|
|
|
699
725
|
> not answer for the page's heading. Twenty-eight `sohl-kethira-basic`
|
|
700
726
|
> affiliations write `sohl.title: ""`, meaning an office with no style of
|
|
701
727
|
> address, and every one of them was reported as publishing a blank heading
|
|
702
|
-
> until the check honoured the declaration
|
|
728
|
+
> until the check honoured the declaration.
|
|
703
729
|
|
|
704
|
-
Because `""`
|
|
730
|
+
Because `""` reads as "unset" elsewhere, a note carrying that spelling has
|
|
705
731
|
quietly changed meaning, and the frontmatter lint says so — for either art
|
|
706
732
|
field:
|
|
707
733
|
|
|
@@ -736,7 +762,7 @@ one failed the build with an error naming a module in someone else's package.
|
|
|
736
762
|
|
|
737
763
|
Widening that map was not the fix. It is deliberately SoHL data, shared with the
|
|
738
764
|
runtime's `SohlItem.getDefaultArtwork` so that the build-time and runtime
|
|
739
|
-
defaults are one list and cannot drift
|
|
765
|
+
defaults are one list and cannot drift. Pairing art with the
|
|
740
766
|
builder instead moves it onto the seam a type is _already_ declared through, and
|
|
741
767
|
costs the `sohl` package nothing: `ITEM_BUILDERS` reads each entry's image out of
|
|
742
768
|
that same map, so there is still exactly one map — and the drift a test used to
|
|
@@ -770,7 +796,7 @@ to be written at.
|
|
|
770
796
|
reaches `sohl.system.templatePriority` and `hm3.flags.hm3.templatePriority` —
|
|
771
797
|
exactly as `portrait` reaches two differently-named fields from one shared
|
|
772
798
|
property. A number is a template at that priority, `null` is not a template, and
|
|
773
|
-
absent is an authoring error
|
|
799
|
+
absent is an authoring error. The legacy in-block and top-level
|
|
774
800
|
positions are still read, in that order after `data:`, so a tree sweeps on its
|
|
775
801
|
own schedule; `archetype` is the retiring spelling of the same field, still read
|
|
776
802
|
last but **refused by the frontmatter linter** — a priority and the `archetypes`
|
|
@@ -809,7 +835,7 @@ system `S` is:
|
|
|
809
835
|
a **dotted path** (`data.portrait`) rather than a sibling key;
|
|
810
836
|
4. the field's own default.
|
|
811
837
|
|
|
812
|
-
`FieldSpec.name` is that declared source.
|
|
838
|
+
`FieldSpec.name` is that declared source. Read as "frontmatter key under
|
|
813
839
|
`sohl:`", which is the degenerate case where source and destination happen to
|
|
814
840
|
share a name.
|
|
815
841
|
|
|
@@ -821,7 +847,7 @@ is _the title of the note_ — the heading its page publishes under, which the
|
|
|
821
847
|
site emitter reads. An `affiliation` item's `system.title` is _the style of
|
|
822
848
|
address the office carries_ — Ajaw, Warden, a person's style within the body.
|
|
823
849
|
They are unrelated quantities, and step 3 used to feed the second from the first
|
|
824
|
-
|
|
850
|
+
.
|
|
825
851
|
|
|
826
852
|
That was not merely untidy, because **step 3 answers without applying
|
|
827
853
|
`field.default`** — only step 2 does — so an authored `title: null` reached the
|
|
@@ -841,7 +867,7 @@ side too.** If the two positions hold unrelated quantities, then the _in-block_
|
|
|
841
867
|
position is not the note-level field either — so a check about a note-level field
|
|
842
868
|
(the page's heading, an art path) reads past a block key the note's own type
|
|
843
869
|
claims for something else. Declaring `topLevelMeans` settles both directions at
|
|
844
|
-
once
|
|
870
|
+
once. Reading it for the emitted field alone is how an
|
|
845
871
|
affiliation's office style came to answer for its page heading.
|
|
846
872
|
|
|
847
873
|
**An exempted field is still authorable**, at the two positions that describe the
|
|
@@ -968,14 +994,14 @@ is exactly what a tree that failed to check out produces.
|
|
|
968
994
|
What that guard reports is an **empty walk**, not an empty set of addresses. A
|
|
969
995
|
note may be keyless — a folder document carries no `shortcode` — so a tree of
|
|
970
996
|
them is populated, correct and unkeyed. That tree passes; a tree holding no
|
|
971
|
-
notes at all still fails. (The homepage
|
|
997
|
+
notes at all still fails. (The homepage is not the headline example, though it was once
|
|
972
998
|
it was addressed by the package rather than by a slug. It carries an address
|
|
973
|
-
like every other note now
|
|
999
|
+
like every other note now; the guard is unchanged, because what it reads
|
|
974
1000
|
was never the key count.)
|
|
975
1001
|
|
|
976
1002
|
### Exactly one homepage
|
|
977
1003
|
|
|
978
|
-
A content tree declares **exactly one** `type: homepage` note
|
|
1004
|
+
A content tree declares **exactly one** `type: homepage` note. Zero is an
|
|
979
1005
|
error and two is an error, at the same severity, because they are one defect: a
|
|
980
1006
|
package whose front page is not the page a person chose.
|
|
981
1007
|
|
|
@@ -983,10 +1009,8 @@ package whose front page is not the page a person chose.
|
|
|
983
1009
|
authored homepage exists to prevent, and a silent one: the site build reports
|
|
984
1010
|
`wrote 0 homepage(s)` and exits 0.
|
|
985
1011
|
- _Two_ and it serves a page nobody chose. **This is a cardinality rule, and
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
enforced it as a side effect. A homepage is written at its own address now, so
|
|
989
|
-
two of them publish two pages and collide over nothing: the duplicate-address
|
|
1012
|
+
only that.** A homepage is written at its own address, so two of them publish
|
|
1013
|
+
two pages and collide over nothing: the duplicate-address
|
|
990
1014
|
check catches only the pair that happen to share a shortcode, and says nothing
|
|
991
1015
|
at all about a `homepage-root` beside a `homepage-front`. Which of the two the
|
|
992
1016
|
redirect at `/<package>/` should name is a question nothing here can answer,
|
|
@@ -1022,7 +1046,7 @@ assets/content/homepage.md:3:7: error: duplicate `type: homepage` note, also dec
|
|
|
1022
1046
|
### Frontmatter, against the schema its type declares
|
|
1023
1047
|
|
|
1024
1048
|
The same command also checks that each note's `sohl:` block is what its **type**
|
|
1025
|
-
allows
|
|
1049
|
+
allows. Five classes, all of them mistakes that were previously reported
|
|
1026
1050
|
somewhere other than where they were made, or not at all:
|
|
1027
1051
|
|
|
1028
1052
|
- **Unknown or retired type** — a note on a retired spelling is told what
|
|
@@ -1055,7 +1079,7 @@ Nothing here writes. A check reports and an author fixes.
|
|
|
1055
1079
|
|
|
1056
1080
|
### The `data:` container is closed; the top level is not
|
|
1057
1081
|
|
|
1058
|
-
A note's frontmatter has three regions, and only one of them is open
|
|
1082
|
+
A note's frontmatter has three regions, and only one of them is open:
|
|
1059
1083
|
|
|
1060
1084
|
| region | describes | an unknown key is |
|
|
1061
1085
|
| ---------------- | -------------------------------------------- | ------------------ |
|
|
@@ -1071,7 +1095,7 @@ the page's description.
|
|
|
1071
1095
|
|
|
1072
1096
|
**`data:` is deliberately closed**, and that is the point of having it. The
|
|
1073
1097
|
type-specific facts about a subject — a weapon's weight, an affliction's
|
|
1074
|
-
transmission, a being's species —
|
|
1098
|
+
transmission, a being's species — do not sit at the top level, where the
|
|
1075
1099
|
pass-through rule applied to them too. So a misspelled `wieght` became a theme
|
|
1076
1100
|
parameter rather than a finding, indistinguishable from a weapon that weighs
|
|
1077
1101
|
nothing. Under `data:` the same key is reported where it was written, with the
|
|
@@ -1082,14 +1106,14 @@ assets/content/Gear/Axe.md:14:5: error: "wieght" is not a `data:` property of a
|
|
|
1082
1106
|
```
|
|
1083
1107
|
|
|
1084
1108
|
**A system block is closed too, and which blocks exist is the configuration's
|
|
1085
|
-
answer
|
|
1109
|
+
answer**. A package is held to the blocks named after the systems it
|
|
1086
1110
|
declares it ships for, read from the three places that already declare them:
|
|
1087
1111
|
`systems:`, a pack's own `system:`, and `stats.systemId` where neither is
|
|
1088
1112
|
written. So a package shipping for HM3 has its `hm3:` block checked and a
|
|
1089
|
-
package shipping for SoHL its `sohl:`.
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1113
|
+
package shipping for SoHL its `sohl:`. Held constant at `sohl`, an `hm3:` block
|
|
1114
|
+
would never be read at all: every key in it would be discarded at compile
|
|
1115
|
+
without a word, while the block that _was_ checked would be named after a system
|
|
1116
|
+
the package does not ship for.
|
|
1093
1117
|
|
|
1094
1118
|
A pack's `system:` counts because it is already authoritative at compile — a
|
|
1095
1119
|
note routed to a pack declaring one and carrying no such block fails the build —
|
|
@@ -1125,12 +1149,12 @@ values. A `weapon` declares none — SoHL distinguishes a weapon's uses by strik
|
|
|
1125
1149
|
mode rather than by kind — so `subType` on one is a finding; a `skill` declares
|
|
1126
1150
|
ten, so `subType: crafte` is a finding naming `craft`.
|
|
1127
1151
|
|
|
1128
|
-
**A `type` and a `subType` are both held to `^[A-Za-z0-9]+$`**
|
|
1152
|
+
**A `type` and a `subType` are both held to `^[A-Za-z0-9]+$`** — the same
|
|
1129
1153
|
constant a `shortcode` is held to, read rather than restated. A type is a
|
|
1130
1154
|
segment of every address — the first of the short form an author writes, the
|
|
1131
1155
|
third of the canonical `package-system-type-shortcode` — so a hyphen in one is
|
|
1132
1156
|
read back as a segment boundary nobody wrote. A `subType` reaches no address
|
|
1133
|
-
|
|
1157
|
+
— sections are retired — and keeps the rule anyway: it is a vocabulary term the toolchain keys
|
|
1134
1158
|
on, and one charset that holds for every term is a rule an author can state. The
|
|
1135
1159
|
rule is checked ahead of the closed-set check, which is what makes it reach a
|
|
1136
1160
|
type whose values are declared but not yet enumerated:
|
|
@@ -1143,7 +1167,7 @@ One declared value broke that rule: a `doc`'s `user-guide`, now **`userguide`**.
|
|
|
1143
1167
|
The old spelling was accepted for one transitional release, as a warning naming
|
|
1144
1168
|
the replacement, because an error would have redded every tree that took the
|
|
1145
1169
|
release before it had a chance to sweep. Every tree has swept, so the acceptance
|
|
1146
|
-
is gone
|
|
1170
|
+
is gone: `user-guide` is refused by the charset check like any other
|
|
1147
1171
|
hyphenated value, and nothing retirement-specific was left to remove.
|
|
1148
1172
|
|
|
1149
1173
|
The vocabulary lives in `engine/note-vocabulary.mjs`, one entry per note type,
|
|
@@ -1151,20 +1175,16 @@ taken from the content-format specification. It is note-format knowledge rather
|
|
|
1151
1175
|
than any system's: `data:` holds what is true of the thing, and what a system
|
|
1152
1176
|
makes of that value is declared in that system's own half.
|
|
1153
1177
|
|
|
1154
|
-
**
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
resolvers parse the hyphen qualifier themselves. The
|
|
1158
|
-
in Obsidian, so the rule cost a line of frontmatter per note for a reader that
|
|
1159
|
-
does not exist. Removing it was verified output-neutral first: across 1,735
|
|
1160
|
-
stripped notes, `package compile` produced byte-identical `build/packs-json` and
|
|
1161
|
-
the site build byte-identical `site/content`.
|
|
1178
|
+
**There is deliberately no third rule** requiring every note to repeat its own
|
|
1179
|
+
`type-shortcode` address in `aliases:`. It would serve one reader — Obsidian, so
|
|
1180
|
+
`[[type-shortcode]]` resolves in the editor — and no build reads it: both
|
|
1181
|
+
resolvers parse the hyphen qualifier themselves. The field is retired.
|
|
1162
1182
|
|
|
1163
|
-
**And the top-level field itself is now retired
|
|
1183
|
+
**And the top-level field itself is now retired.** `aliases:` fed the
|
|
1164
1184
|
alias index, which is what a bare `[[Alias]]` was looked up in. That form
|
|
1165
1185
|
resolved to nothing anywhere in the corpus, while the collision rule guarding it
|
|
1166
1186
|
folded in every note's `name.full` and so decided what a note could be named
|
|
1167
|
-
|
|
1187
|
+
. Both are gone: every wikilink is an address, written
|
|
1168
1188
|
`[[type-shortcode|Text]]`, and declaring `aliases:` is refused naming the file
|
|
1169
1189
|
and the line.
|
|
1170
1190
|
|
|
@@ -1220,12 +1240,12 @@ nothing today will read it.
|
|
|
1220
1240
|
|
|
1221
1241
|
A homepage declares a `shortcode` — conventionally `root` — and publishes at its
|
|
1222
1242
|
address, `/<package>/homepage-root/`, written by the same rule as everything
|
|
1223
|
-
else
|
|
1243
|
+
else. So `[[homepage-root|Read the introduction]]` is an ordinary
|
|
1224
1244
|
wikilink, resolving to the page the build actually writes.
|
|
1225
1245
|
|
|
1226
1246
|
It did not use to be. A page's URL derived from `name.full` while a homepage's
|
|
1227
1247
|
destination was fixed at `_index.md`, so `content-build lint` **refused** `name`
|
|
1228
|
-
and `shortcode` on one
|
|
1248
|
+
and `shortcode` on one — not out of tidiness, but because they were not
|
|
1229
1249
|
inert. A `shortcode` put the note in the address index, so
|
|
1230
1250
|
`[[homepage-<shortcode>]]` resolved _green_ to a page the site build never
|
|
1231
1251
|
wrote, and a build reporting a live link to a 404 is worse than one saying
|
|
@@ -1274,7 +1294,7 @@ is emitted into the published page, so an unrecognised key is a Hugo or theme
|
|
|
1274
1294
|
parameter this build has never heard of and has no standing to reject; a closed
|
|
1275
1295
|
list would make every new theme parameter wait on a package-build release.
|
|
1276
1296
|
`aliases` is not in the class either — it is a retired field now, refused on
|
|
1277
|
-
every note whatever its type
|
|
1297
|
+
every note whatever its type.
|
|
1278
1298
|
|
|
1279
1299
|
**Where it fires: `content-build lint` only.** Unlike a rule about the shape of
|
|
1280
1300
|
the _tree_, which the site build has its own reason to gate on, this is a
|
|
@@ -1348,7 +1368,7 @@ serves.
|
|
|
1348
1368
|
|
|
1349
1369
|
### The homepage's own links
|
|
1350
1370
|
|
|
1351
|
-
The homepage is the page a reader arrives at, and
|
|
1371
|
+
The homepage is the page a reader arrives at, and it is the one page
|
|
1352
1372
|
nothing checked. SoHL's landing pointed at `kb/creature/` and `kb/character/`
|
|
1353
1373
|
from the day those two types merged into `being` — two 404s on the package's
|
|
1354
1374
|
front page, through every build, because a landing's links went through no
|
|
@@ -1484,7 +1504,7 @@ npx content-build markdown --fix # apply the fixes markdownlint can make
|
|
|
1484
1504
|
```
|
|
1485
1505
|
|
|
1486
1506
|
Two conventions every content repository writes to, declared once here so a note
|
|
1487
|
-
formatted in one is formatted the same way in the next
|
|
1507
|
+
formatted in one is formatted the same way in the next:
|
|
1488
1508
|
|
|
1489
1509
|
- **`format`** runs Prettier. Same values SoHL has always used, so a module or a
|
|
1490
1510
|
note moving between repositories does not reformat on arrival.
|
|
@@ -1518,7 +1538,7 @@ alone: a `prettier.config.mjs` that spreads `PRETTIER_BASE` without the `**/*.md
|
|
|
1518
1538
|
override reindents every note at 4, and a partial `.prettierrc` such as
|
|
1519
1539
|
`{"tabWidth": 2}` silently discards `printWidth: 100`, `trailingComma` and the
|
|
1520
1540
|
rest. So every `format` run first names, as warnings, each shared convention this
|
|
1521
|
-
repository resolves differently
|
|
1541
|
+
repository resolves differently:
|
|
1522
1542
|
|
|
1523
1543
|
```text
|
|
1524
1544
|
prettier.config.mjs: warning: markdown `tabWidth` is 4 here; the shared configuration says 2
|
|
@@ -1722,20 +1742,20 @@ names a _document_; a URL names a _page_. So a consumer deriving a page address
|
|
|
1722
1742
|
from a manifest key drops the package **and** the system, not the package
|
|
1723
1743
|
alone.
|
|
1724
1744
|
|
|
1725
|
-
It
|
|
1745
|
+
It does not come from `name.full`. That would make a display name load-bearing three
|
|
1726
1746
|
ways at once — a rename silently 404'd every inbound link, two notes in one
|
|
1727
1747
|
section could derive the same URL so a uniqueness gate had to run, and long names
|
|
1728
1748
|
had to be shortened through a table of 200 abbreviations. The header of the
|
|
1729
1749
|
module doing it justified the cost by promising redirects "every change appends
|
|
1730
1750
|
to the legacy-URL map" — and no such map was ever written, here or in any
|
|
1731
|
-
consumer. All of it is gone
|
|
1751
|
+
consumer. All of it is gone.
|
|
1732
1752
|
|
|
1733
1753
|
The `type-` half earns its place: it keeps every content address clear of the
|
|
1734
1754
|
package's fixed mounts (`/<package>/` for the landing page, `/<package>/api/` for
|
|
1735
1755
|
generated API docs), neither of which contains a hyphen or names a type. So the
|
|
1736
1756
|
namespace is provably disjoint rather than conventionally so.
|
|
1737
1757
|
|
|
1738
|
-
**A page is written flat, named by its address
|
|
1758
|
+
**A page is written flat, named by its address**, not filed
|
|
1739
1759
|
into `<section>/`, because Hugo derives a page's section from where the file is
|
|
1740
1760
|
written and a section gave it a landing page, `.CurrentSection` and a per-section
|
|
1741
1761
|
layout lookup. But a section appears in no address, so the note format was
|
|
@@ -1745,7 +1765,7 @@ order to satisfy a rendering engine's directory semantics. The file is now
|
|
|
1745
1765
|
the package root, one level above.
|
|
1746
1766
|
|
|
1747
1767
|
**A page states its address without the package base; everything pointing _at_
|
|
1748
|
-
it composes one
|
|
1768
|
+
it composes one**. They read as one quantity and are two:
|
|
1749
1769
|
|
|
1750
1770
|
| Written | Form | Because |
|
|
1751
1771
|
| ------------------------------------------- | --------------------------- | --------------------------------------------------------------------------------------- |
|
|
@@ -1754,7 +1774,7 @@ it composes one** (#217). They read as one quantity and are two:
|
|
|
1754
1774
|
| A link-manifest `path` | `<type>-<shortcode>/` | Measured against `site.base` and stripped; a consumer prefixes its own |
|
|
1755
1775
|
|
|
1756
1776
|
`site.base` is the second and third of those and reaches the first not at all.
|
|
1757
|
-
|
|
1777
|
+
Writing it into the `url:` as well makes every consumer's Hugo prefix
|
|
1758
1778
|
its own base to a value that already carried one and published every content
|
|
1759
1779
|
page a segment too deep — `/sohl/sohl/doc-rulesintro/`, 404 at the address the
|
|
1760
1780
|
manifest, the sitemap and every inbound link named.
|
|
@@ -1763,7 +1783,7 @@ manifest, the sitemap and every inbound link named.
|
|
|
1763
1783
|
addressed the section itself; that is retired with the section. A page that
|
|
1764
1784
|
introduces the notes of a type is an ordinary note addressed `doc-<type>`, with
|
|
1765
1785
|
no build path of its own — exactly as the package's own front page is
|
|
1766
|
-
`homepage-root
|
|
1786
|
+
`homepage-root`.
|
|
1767
1787
|
|
|
1768
1788
|
**Sections stay, as configuration.** `site.sections` still writes an `_index.md`
|
|
1769
1789
|
per section, and that is now the _only_ thing that makes one exist — see
|
|
@@ -1794,13 +1814,12 @@ publish:
|
|
|
1794
1814
|
never recorded here.
|
|
1795
1815
|
|
|
1796
1816
|
`prefix` is the whole scheme. The `collection` subtype and the top-level
|
|
1797
|
-
`section:` key are refused by name
|
|
1817
|
+
`section:` key are refused by name.
|
|
1798
1818
|
|
|
1799
1819
|
A note's `subType` is checked against the values its type declares, and only
|
|
1800
1820
|
those. It briefly had a second reading — a `README` landing's `subType` was the
|
|
1801
|
-
_address_ it landed at, so the closed genre list could not answer for it
|
|
1802
|
-
|
|
1803
|
-
vocabulary again.
|
|
1821
|
+
_address_ it landed at, so the closed genre list could not answer for it. The
|
|
1822
|
+
cause is removed rather than the vocabulary widened again.
|
|
1804
1823
|
|
|
1805
1824
|
The only note the scheme yields no address for is one carrying no `shortcode`.
|
|
1806
1825
|
It is **reported and omitted**, never guessed: the command prints one located
|
|
@@ -2046,7 +2065,7 @@ That is the whole envelope. A homepage **compiles into no compendium
|
|
|
2046
2065
|
document**, and so appears in no pack and in no link manifest — which is why it
|
|
2047
2066
|
still refuses `id`. Everything else about its address is ordinary: it declares a
|
|
2048
2067
|
`shortcode`, publishes at `/<contentPackage>/homepage-root/`, and is cited as
|
|
2049
|
-
`[[homepage-root|Text]]` (
|
|
2068
|
+
`[[homepage-root|Text]]` (see
|
|
2050
2069
|
[The homepage is addressed like every other note](#the-homepage-is-addressed-like-every-other-note)).
|
|
2051
2070
|
`/<contentPackage>/` itself is a redirect the package authors, not a page this
|
|
2052
2071
|
build writes. It is dispatched on `type` like every other note, not on a
|
|
@@ -2068,8 +2087,8 @@ note-format knowledge against game-system knowledge, and a homepage carries no
|
|
|
2068
2087
|
| `content` | The homepage plus every page the content tree compiles to, and its extra trees. |
|
|
2069
2088
|
|
|
2070
2089
|
There is no value meaning "no web presence": every package publishes its
|
|
2071
|
-
homepage.
|
|
2072
|
-
|
|
2090
|
+
homepage. A boolean is refused, with a message naming the mode to write
|
|
2091
|
+
instead.
|
|
2073
2092
|
|
|
2074
2093
|
**Homepage-only is a first-class mode, not an accommodation.**
|
|
2075
2094
|
`sohl-kethira-basic` (unofficial Hârn fan material under Keléstia Productions'
|
|
@@ -2094,7 +2113,7 @@ site root, one level above the content mount, which is where
|
|
|
2094
2113
|
`publish.address.prefix` puts everything else — under the name its address gives
|
|
2095
2114
|
it, `homepage-root.md`. As with every other page, the front matter's `url`
|
|
2096
2115
|
decides where it publishes, and states it relative to the site root — `site.base`
|
|
2097
|
-
does not reach it
|
|
2116
|
+
does not reach it.
|
|
2098
2117
|
|
|
2099
2118
|
**What it does not do is decide addresses.** Those come from `publish.address`,
|
|
2100
2119
|
the same setting the content index reads, so a page and its index record cannot
|
|
@@ -2140,7 +2159,7 @@ site:
|
|
|
2140
2159
|
|
|
2141
2160
|
### What a section may declare
|
|
2142
2161
|
|
|
2143
|
-
**`sections` is what a section _is_ now
|
|
2162
|
+
**`sections` is what a section _is_ now**. A content page is addressed
|
|
2144
2163
|
`(type, shortcode)` and written flat under the mount, so no page creates a
|
|
2145
2164
|
directory and nothing else makes `/<package>/<prefix><section>/` answer at all.
|
|
2146
2165
|
A site that wants that address says so here, and this build writes the
|
|
@@ -2209,7 +2228,7 @@ Three things about the spelling, each of them load-bearing:
|
|
|
2209
2228
|
site chose; a type and a subType are addresses. They need not agree, and on
|
|
2210
2229
|
`sohl` they do not: the section is `user-guide`, because that is a published
|
|
2211
2230
|
URL, while the subType is `userguide` because an address segment is
|
|
2212
|
-
alphanumeric
|
|
2231
|
+
alphanumeric. Both values are checked against that charset here, so
|
|
2213
2232
|
copying the section's name in is refused rather than quietly matching nothing.
|
|
2214
2233
|
- **`listSubType` needs a `listType`.** A subType only tells pages apart within
|
|
2215
2234
|
a type — `rules`, `userguide` and `reference` are all `doc` — so alone it
|
|
@@ -2263,8 +2282,8 @@ to a code span.
|
|
|
2263
2282
|
Leaving it unset is the legitimate empty case — every `{@link}` degrades, and
|
|
2264
2283
|
nothing is reported. Setting it to a path that cannot be read, cannot be parsed,
|
|
2265
2284
|
or does not hold a name → page object **fails the build**, naming the file and
|
|
2266
|
-
the reason
|
|
2267
|
-
site
|
|
2285
|
+
the reason. Left unreported they are indistinguishable from "no symbols", and
|
|
2286
|
+
a site publishes dead `{@link}` tags at exit 0. A map that is read reports
|
|
2268
2287
|
its symbol count at info level, which is the only way to tell a map that loaded
|
|
2269
2288
|
from one that loaded empty without reading the emitted HTML.
|
|
2270
2289
|
|
|
@@ -2442,7 +2461,7 @@ affiliation standings. Each has its own entry point —
|
|
|
2442
2461
|
`.../engine/region-events`, `.../sohl/affiliation-standings` — so a client bundle
|
|
2443
2462
|
reaches the constant without importing a barrel that grows to hold compilers
|
|
2444
2463
|
reading the filesystem. Keeping one copy of each is the point: the build-time and
|
|
2445
|
-
runtime values cannot disagree
|
|
2464
|
+
runtime values cannot disagree.
|
|
2446
2465
|
|
|
2447
2466
|
`@heroiclands/package-build/content-config` exposes the configuration contract's own
|
|
2448
2467
|
module, so a consumer can name its types (`ContentBuildConfig`, `PackSpec`) from
|
|
@@ -2479,7 +2498,7 @@ was the system repository, because the package was vendored inside it (#1).
|
|
|
2479
2498
|
shipping side. This package spent its first six changes as a workspace inside
|
|
2480
2499
|
the Song of Heroic Lands repository, where npm hoisted the root's
|
|
2481
2500
|
`devDependencies` into the workspace root: an import this package never declared
|
|
2482
|
-
still resolved, and failed nowhere but a consumer's install
|
|
2501
|
+
still resolved, and failed nowhere but a consumer's install. The test
|
|
2483
2502
|
walks every module named by the `files` field and holds each bare specifier to
|
|
2484
2503
|
one of three cases — a Node builtin, this package addressing itself, or a
|
|
2485
2504
|
declared `dependency` — and checks the converse: nothing shipped may import a
|
|
@@ -2497,7 +2516,7 @@ the copy before the rest run. A module that hoisted a configured value to import
|
|
|
2497
2516
|
time fails there, and only there.
|
|
2498
2517
|
|
|
2499
2518
|
`tests/config-from-working-directory.test.ts` describes the resolution order
|
|
2500
|
-
itself
|
|
2519
|
+
itself. It builds the shape no unit test can fake — a repository with the
|
|
2501
2520
|
toolchain installed under it, and a second checkout nested inside that
|
|
2502
2521
|
repository with its own configuration and no `node_modules` — and asserts which
|
|
2503
2522
|
configuration a build run in each place reads. The nested case is the one that
|
|
@@ -2522,7 +2541,7 @@ bump and the rewritten `CHANGELOG.md`. That pull request _is_ the pending
|
|
|
2522
2541
|
release: as long as something is merged but unpublished, there is an open pull
|
|
2523
2542
|
request saying so. This is the whole point of the pipeline — the previous,
|
|
2524
2543
|
hand-driven process failed by leaving _nothing_ behind when the final step was
|
|
2525
|
-
forgotten, and on 2026-08-21 it did exactly that for two versions
|
|
2544
|
+
forgotten, and on 2026-08-21 it did exactly that for two versions.
|
|
2526
2545
|
|
|
2527
2546
|
**Merging that publishes.** `changeset publish` puts the version on npm through
|
|
2528
2547
|
Trusted Publishing (OIDC — there is no `NPM_TOKEN`), tags the commit `v<version>`
|
package/README.md
CHANGED
|
@@ -14,13 +14,6 @@ The content half is documented separately in **[CONTENT.md](CONTENT.md)** — th
|
|
|
14
14
|
note format, the pack pipeline, and the configuration contract a content tree
|
|
15
15
|
declares itself with.
|
|
16
16
|
|
|
17
|
-
> **This package was two.** Until 3.0.0 the content half shipped as
|
|
18
|
-
> `@heroiclands/content-build`. No consumer ever installed one without the
|
|
19
|
-
> other, and the packaging half depended on the content half besides, so the
|
|
20
|
-
> boundary bought nothing and cost a configuration file with two owners and a
|
|
21
|
-
> two-repository dance for single changes. See
|
|
22
|
-
> [MIGRATING.md](MIGRATING.md) to move a consumer from 1.x.
|
|
23
|
-
|
|
24
17
|
## Install
|
|
25
18
|
|
|
26
19
|
```
|
|
@@ -234,7 +227,7 @@ packageBuild:
|
|
|
234
227
|
### The manifest is generated, not stamped
|
|
235
228
|
|
|
236
229
|
`package-build manifest` writes `system.json` / `module.json` into the stage.
|
|
237
|
-
**There is no template file.** A
|
|
230
|
+
**There is no template file.** A hand-authored JSON manifest is one the
|
|
238
231
|
build stamped a few fields into — the one build input still written by hand, per
|
|
239
232
|
repository, with no schema and nothing checking it. It also declared facts the
|
|
240
233
|
configuration already declared: the pack list twice, in two formats, with
|
|
@@ -495,7 +488,7 @@ own to call a run green. Every way of stopping a runner before it starts — a
|
|
|
495
488
|
corrupt install, a missing browser, a killed process, an `npm ci` racing the
|
|
496
489
|
run and taking `node_modules` with it — produces a run that executed nothing,
|
|
497
490
|
and a harness that reports that as 0 makes the evidence unfalsifiable in the
|
|
498
|
-
one direction that matters
|
|
491
|
+
one direction that matters.
|
|
499
492
|
|
|
500
493
|
So the suite is bracketed rather than trusted:
|
|
501
494
|
|