tonus 0.9.1 → 0.10.1

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 (45) hide show
  1. package/CHANGELOG.md +87 -0
  2. package/README.md +1 -1
  3. package/dist/census.d.ts +4 -0
  4. package/dist/census.js +23 -0
  5. package/dist/corpus.d.ts +4 -0
  6. package/dist/corpus.js +17 -0
  7. package/dist/data/am.js +10220 -3006
  8. package/dist/data/attestation.js +38640 -4568
  9. package/dist/data/attestation.json +38639 -4567
  10. package/dist/data/census.d.ts +2 -2
  11. package/dist/data/census.js +4 -4
  12. package/dist/data/corpus-overlap.js +5 -118
  13. package/dist/data/gr.d.ts +29 -2
  14. package/dist/data/gr.js +2436 -6411
  15. package/dist/data/kyriale.d.ts +1 -1
  16. package/dist/data/kyriale.js +38 -38
  17. package/dist/data/la.js +12369 -1103
  18. package/dist/data/lh.js +3139 -158
  19. package/dist/data/lu.js +17332 -2379
  20. package/dist/data/nocturnale-romanum.js +10656 -1899
  21. package/dist/data/psm.js +463 -33
  22. package/dist/data/types.d.ts +1 -0
  23. package/dist/engines/chant/chant.js +60 -13
  24. package/dist/engines/chant/data/masses.js +18 -18
  25. package/dist/engines/chant/ordinary.js +12 -5
  26. package/dist/engines/chant/psalm.js +4 -0
  27. package/dist/engines/chant/syllabify.js +21 -2
  28. package/dist/engines/chant/types.d.ts +32 -4
  29. package/dist/engines/chant/types.js +47 -4
  30. package/dist/engines/score/infer.js +1 -1
  31. package/dist/index.d.ts +5 -9
  32. package/dist/inscriptio.d.ts +5 -0
  33. package/dist/inscriptio.js +23 -0
  34. package/dist/score.d.ts +6 -0
  35. package/dist/score.js +20 -0
  36. package/docs/api/census.md +12 -3
  37. package/docs/api/chant.md +83 -63
  38. package/docs/api/index.md +35 -1
  39. package/package.json +19 -2
  40. package/dist/data/ams.d.ts +0 -5
  41. package/dist/data/ams.js +0 -122
  42. package/dist/data/cot.d.ts +0 -5
  43. package/dist/data/cot.js +0 -172
  44. package/dist/data/cse.d.ts +0 -5
  45. package/dist/data/cse.js +0 -122
package/CHANGELOG.md CHANGED
@@ -2,6 +2,93 @@
2
2
 
3
3
  All notable changes to tonus. Newest first.
4
4
 
5
+ ## 0.10.1 — 2026-08-31
6
+
7
+ A capital ligature is a vowel like any other.
8
+
9
+ ### Fixed
10
+
11
+ - **`Æ` and `Œ` reached the nucleus unexpanded.** `selectVowel` expanded the
12
+ ligatures case-sensitively, and neither has an NFD decomposition (unlike
13
+ `á` → `a`), so a capital survived the scan and was reported AS the vowel:
14
+ `vowel: "æ"`, a two-letter answer to a one-letter promise. Consumers that
15
+ hold tonus to that contract throw on it. 136 chants carry one, every case
16
+ opening a word — 94 at the start of the lyric, the other 42 inside an
17
+ all-capital opening word (`SÆpe`, `PRÆ`, `HÆC`), which is exactly where a
18
+ capital lives. The gated shelf held almost none of them, so 0.10.0's re-cut
19
+ is what surfaced it; the defect is older.
20
+ - **An accented ligature accented the off-glide.** `œ́` is `œ` + combining
21
+ acute, with no precomposed form, so expanding it to `oe` + accent marked the
22
+ `e`: `selectVowel("œ́")` returned nucleus `"e"` where it should return `"o"`.
23
+ The pair is now rebuilt as `o` + accent + `e`. `ǽ`, which IS precomposed,
24
+ was always correct — the two agree now.
25
+
26
+ Note for consumers baking off `vowel`: 136 chants change nucleus, and `Æ`/`Œ`
27
+ now report `diphthong: "ae"`/`"oe"` where they reported `null`. Anything
28
+ derived from the vowel plane wants a re-bake.
29
+
30
+ ## 0.10.0 — 2026-08-31
31
+
32
+ The corpus stores a melody once instead of once per book, the genus labels say
33
+ what GregoBase says, and the root index stops carrying the anatomy of its own
34
+ return values.
35
+
36
+ ### Changed
37
+
38
+ - **BREAKING: the Kyrie's ordinary code is `ke`, not `ky`.** GregoBase files
39
+ every ordinary chant under office-part `ky` = Kyriale, which is the roll-up
40
+ genus, so the Kyrie itself needed a code of its own. `cantus({ ordinary })`
41
+ and `ordinarium({ ordinary })` both take `ke` now, and `ORDINARIA` is keyed
42
+ by it. **A stale `"ky"` throws** rather than returning `[]` — an unknown
43
+ ordinary code is a malformed query, and this is the one most likely to
44
+ arrive stale, so the error names the replacement.
45
+ - **BREAKING: three office genus labels were wrong and are corrected.** They
46
+ were read off the two-letter codes rather than off the source; GregoBase's
47
+ own vocabulary (`include/txt.php`, `$txt['usage']`) is now followed. `or` is
48
+ **Toni Communes** (it read "Ordinarium"), `tp` is **Tropa** (it read "Tonus
49
+ Peregrinus"), and `pa` is **Prosa**. `or` was the costly one: tonus stamped
50
+ an invented genus on a code the database already used for something else,
51
+ and 132 real Toni Communes chants were dropped at the extractor for want of
52
+ a mapping. Anything reading `chant.genus`, or filtering `office: "or"`
53
+ expecting the Mass ordinary, is affected — the ordinary is `ky` (genus) or
54
+ `ordinary` (part).
55
+ - **Two office codes are new: `ky` and `va`.** `ky` is the Mass ordinary's
56
+ roll-up genus; `va` ("Varia") is the catch-all a chant falls to when its
57
+ office-part is unrecognised. It used to fall to `or`, which was harmless
58
+ while `or` was an invented label and is not now that it means a recitation
59
+ formula the census excludes.
60
+ - **BREAKING: type-only names moved off the root entry.** Four subpath entries
61
+ now hold the grain the index was carrying — `tonus/corpus` (the shelf and its
62
+ vocabulary), `tonus/score` (what a `Score` is made of), `tonus/inscriptio`
63
+ (the drawing surface), `tonus/census` (one chant against the corpus). Verbs
64
+ stay on the root namespace, and the types a root signature names stay on the
65
+ root too. **Every value export the root carried is still exported from it**,
66
+ so nothing moved out of a JavaScript consumer's reach — though the code
67
+ renames above do reach one.
68
+ - **A melody printed in several books is stored once.** It was stored once per
69
+ book. `books` now lists every printing and `pages` is keyed by book code, so
70
+ `cantus({ source })` presents a shared chant as the book asked for: that
71
+ book's source record and page numbers, not those of the file the record
72
+ happens to live in. 7840 chants, 9758 listings.
73
+
74
+ ### Added
75
+
76
+ - **Four subpath entries surface types that were reachable but unnameable.**
77
+ `ChantSource`, `OfficeCode`, `OrdinaryCode`, `CanonicalHour`, `Theme`,
78
+ `ThemeColors`, `TrackName`, `TrackData`, and `CENSUS_BLOCK_FLOATS` — each a
79
+ value callers had to spell by hand against a query or an option bag.
80
+ - **The two boundaries are gated instead of described.** `npm run gate` holds
81
+ the rendering boundary (only `inscriptio.ts` and the emitters may import from
82
+ `emitters/`) and the entry map (every `exports` subpath has a source module,
83
+ and every entry module is exported). Prose had already failed to hold the
84
+ rendering boundary once. It runs as part of `npm test`.
85
+
86
+ ### Removed
87
+
88
+ - **`ams`, `cot`, and `cse` are no longer separate data files.** Their contents
89
+ were listings on records the other books already own, and are now reachable
90
+ through `books`/`pages` on those records.
91
+
5
92
  ## 0.9.1 — 2026-08-24
6
93
 
7
94
  Moderna reads the pitch it was given: the whole page had been sitting a sixth
package/README.md CHANGED
@@ -72,7 +72,7 @@ its final, dominant, ambitus, and ethos, with its psalm tones.
72
72
  **The calendar** is Tridentine, resolved against Easter by
73
73
  the Julian or the Gregorian computus.
74
74
 
75
- **The repertoire** is 2,187 chants across ten books, nine Solesmes editions and
75
+ **The repertoire** is 7,840 chants across seven books, six Solesmes editions and
76
76
  the _Nocturnale Romanum_ night office in
77
77
  [GABC](https://gregorio-project.github.io/) notation: Mass propers, the Kyriale,
78
78
  the Office hours, the psalter, and the Matins nocturns.
@@ -0,0 +1,4 @@
1
+ export { getCensus as census } from "./engines/census/census.js";
2
+ export type { Census, CensusQuery, CensusBy, CensusGroup, CensusGroupProfile, CensusNeighbor, } from "./engines/census/types.js";
3
+ export { CENSUS_GROUPS, CENSUS_ORDER, CENSUS_BLOCK_FLOATS, } from "./data/census.js";
4
+ //# sourceMappingURL=census.d.ts.map
package/dist/census.js ADDED
@@ -0,0 +1,23 @@
1
+ // ---------------------------------------------------------------------------
2
+ // tonus/census — one chant measured against the corpus that holds it
3
+ // ---------------------------------------------------------------------------
4
+ // The analysis boundary, made addressable. The library never RUNS a census; it
5
+ // CITES one. Everything here reads a baked table — the blocks the corpus
6
+ // pipeline emits — and does arithmetic over it. No mining lives behind this
7
+ // entry and none may be added: a threshold calibrated across many chants is the
8
+ // corpus repo's business, and re-enters as generated data with provenance.
9
+ //
10
+ // Year-shaped questions ("this season," "this manuscript," a window of the
11
+ // calendar) are not here and do not belong here. `data/census.ts` states the
12
+ // same rule from the data side: this is the only census artifact in the
13
+ // package, and the corpus repo's other outputs stay there. Pooling blocks is
14
+ // the caller's to do, under the rule census.md fixes — cosine per field group,
15
+ // never over the flat 221.
16
+ //
17
+ // CENSUS_BLOCK_FLOATS joins the two constants the root already exported. A
18
+ // caller decoding a block had to know the stride and could get it only by
19
+ // counting CENSUS_GROUPS, which is the transcription the appendix rule exists
20
+ // to prevent.
21
+ export { getCensus as census } from "./engines/census/census.js";
22
+ export { CENSUS_GROUPS, CENSUS_ORDER, CENSUS_BLOCK_FLOATS, } from "./data/census.js";
23
+ //# sourceMappingURL=census.js.map
@@ -0,0 +1,4 @@
1
+ export { getChants as cantus, getCorpus as corpus, SOURCES } from "./engines/chant/chant.js";
2
+ export { HORAE, OFFICIA, ORDINARIA, MODI } from "./engines/chant/types.js";
3
+ export type { Chant, OrdinaryChant, CantusQuery, CorpusQuery, Corpus, CorpusLedger, CorpusFullCount, GenusCount, ModeCount, SharedCount, ChantSource, OfficeCode, OrdinaryCode, CanonicalHour, } from "./engines/chant/types.js";
4
+ //# sourceMappingURL=corpus.d.ts.map
package/dist/corpus.js ADDED
@@ -0,0 +1,17 @@
1
+ // ---------------------------------------------------------------------------
2
+ // tonus/corpus — the shelf: what tonus holds, and how to ask for it
3
+ // ---------------------------------------------------------------------------
4
+ // The repertoire and its vocabulary, separated from the calendar that resolves
5
+ // a DAY. `cantus` and `corpus` ask what is on the shelf; `festum`, `proprium`
6
+ // and `officium` ask what a day calls for. The two questions have been one
7
+ // import since the beginning, which is part of why the shelf reads as though it
8
+ // were a property of the calendar.
9
+ //
10
+ // This entry surfaces four types the root index never exported, each of them a
11
+ // value a caller otherwise had to TYPE OUT against a query: ChantSource (the
12
+ // book codes `cantus({ source })` accepts), OfficeCode and OrdinaryCode (the
13
+ // genus and ordinary codes), and CanonicalHour (what HORAE holds). The appendix
14
+ // rule already admits the tables; the types they range over belong beside them.
15
+ export { getChants as cantus, getCorpus as corpus, SOURCES } from "./engines/chant/chant.js";
16
+ export { HORAE, OFFICIA, ORDINARIA, MODI } from "./engines/chant/types.js";
17
+ //# sourceMappingURL=corpus.js.map