@archivist-gg/dnd5e 0.3.13 → 0.3.19

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 (122) hide show
  1. package/dist/background/background.codec.js +5 -5
  2. package/dist/background/background.parser.js +4 -4
  3. package/dist/background/background.schema.js +3 -3
  4. package/dist/chunk-3LWMFYKS.js +57 -0
  5. package/dist/{chunk-4SLOJXJ4.js → chunk-3SFGWFVQ.js} +1 -1
  6. package/dist/{chunk-Q6UOHCCT.js → chunk-3SIUAFDQ.js} +1 -1
  7. package/dist/chunk-4J6DS3EJ.js +30 -0
  8. package/dist/{chunk-RLGQ5PZZ.js → chunk-5JXFJ5AU.js} +11 -1
  9. package/dist/{chunk-4BZ47YJ4.js → chunk-64VNLMSG.js} +59 -16
  10. package/dist/{chunk-XY6X2APM.js → chunk-7Q2VPKCD.js} +17 -0
  11. package/dist/{chunk-Q5XTEYHD.js → chunk-7XJHI5H5.js} +16 -9
  12. package/dist/{chunk-FPGXFD2M.js → chunk-B2QHP6UF.js} +2 -2
  13. package/dist/{chunk-HJQNK3J5.js → chunk-B3DP42OM.js} +1 -4
  14. package/dist/{chunk-MC5YJ4PB.js → chunk-BJGOSM76.js} +1 -1
  15. package/dist/{chunk-VDPRBUU5.js → chunk-BJWSOQUC.js} +1 -1
  16. package/dist/{chunk-QEO7LYTG.js → chunk-EJD47JHL.js} +181 -93
  17. package/dist/{chunk-X7VZY4ON.js → chunk-FJYBLXV7.js} +2 -2
  18. package/dist/{chunk-QSBJ6NEM.js → chunk-FMUD3LDV.js} +1 -1
  19. package/dist/{chunk-LVX6TQ3R.js → chunk-FMYWORTP.js} +2 -2
  20. package/dist/{chunk-PX25R3DK.js → chunk-FVXLP7P3.js} +1 -1
  21. package/dist/{chunk-XJRNEQPD.js → chunk-GVWEFECG.js} +1 -1
  22. package/dist/{chunk-R2V5LN3I.js → chunk-HY2SRSVM.js} +1 -1
  23. package/dist/{chunk-ZMJQUZQH.js → chunk-JXWNXIIZ.js} +24 -0
  24. package/dist/chunk-KR6JF3BF.js +14 -0
  25. package/dist/{chunk-DPM6V7YX.js → chunk-LICYHPI3.js} +82 -6
  26. package/dist/{chunk-J53ERF6K.js → chunk-LNT64X7C.js} +1 -1
  27. package/dist/{chunk-RQNJXADQ.js → chunk-NKZMQV2C.js} +1 -1
  28. package/dist/{chunk-UE6LKRXQ.js → chunk-NTU2DXNG.js} +24 -1
  29. package/dist/{chunk-T5GZBKIQ.js → chunk-NXUY5XQN.js} +168 -33
  30. package/dist/{chunk-M2OWVAZG.js → chunk-NZO7M5GV.js} +1 -1
  31. package/dist/{chunk-BRGLDWUP.js → chunk-OOL4KMG2.js} +7 -3
  32. package/dist/{chunk-MWCCGPG3.js → chunk-OOSRUJBI.js} +3 -2
  33. package/dist/{chunk-H5PTKYXL.js → chunk-QA3YCOML.js} +1 -1
  34. package/dist/{chunk-MUIU7RZ3.js → chunk-QFWQKS3M.js} +1 -1
  35. package/dist/chunk-RD2MID3M.js +292 -0
  36. package/dist/chunk-TRBGC4ZG.js +112 -0
  37. package/dist/{chunk-PLOSP4XQ.js → chunk-UJCK5IW4.js} +11 -2
  38. package/dist/{chunk-5KGV6TF7.js → chunk-UNYR5GLI.js} +1 -1
  39. package/dist/{chunk-JNNNBEUH.js → chunk-VN5DLURA.js} +7 -2
  40. package/dist/{chunk-EL6QPF6I.js → chunk-VP5TIXDK.js} +1 -1
  41. package/dist/chunk-WOHX7YTH.js +165 -0
  42. package/dist/{chunk-G7ED5H2G.js → chunk-XTEFPUSN.js} +1 -1
  43. package/dist/{chunk-6ZY3U6BQ.js → chunk-ZOWKWMD2.js} +1 -1
  44. package/dist/class/class.codec.js +6 -6
  45. package/dist/class/class.parser.js +5 -5
  46. package/dist/class/class.schema.d.ts +8 -0
  47. package/dist/class/class.schema.js +4 -4
  48. package/dist/class/class.standard-array.d.ts +16 -0
  49. package/dist/class/class.standard-array.js +20 -0
  50. package/dist/class/class.types.d.ts +3 -0
  51. package/dist/dnd/amount-text.d.ts +42 -0
  52. package/dist/dnd/amount-text.js +15 -0
  53. package/dist/dnd/resource-words.d.ts +4 -0
  54. package/dist/dnd/resource-words.js +30 -0
  55. package/dist/entities/registry-revision.d.ts +25 -0
  56. package/dist/entities/registry-revision.js +10 -0
  57. package/dist/feat/feat.codec.js +5 -5
  58. package/dist/feat/feat.parser.js +4 -4
  59. package/dist/feat/feat.schema.d.ts +34 -0
  60. package/dist/feat/feat.schema.js +3 -3
  61. package/dist/index.js +4027 -383
  62. package/dist/monster/monster.parser.js +5 -5
  63. package/dist/monster/monster.schema.js +4 -4
  64. package/dist/optional-feature/optional-feature.codec.js +5 -4
  65. package/dist/optional-feature/optional-feature.parser.js +4 -3
  66. package/dist/optional-feature/optional-feature.schema.d.ts +35 -0
  67. package/dist/optional-feature/optional-feature.schema.js +3 -2
  68. package/dist/pc/pc.additional-spells.d.ts +16 -2
  69. package/dist/pc/pc.additional-spells.js +5 -2
  70. package/dist/pc/pc.amount-bindings.d.ts +41 -0
  71. package/dist/pc/pc.amount-bindings.js +28 -0
  72. package/dist/pc/pc.decision-engine.d.ts +11 -0
  73. package/dist/pc/pc.decision-engine.js +20 -16
  74. package/dist/pc/pc.entry-overrides.js +3 -2
  75. package/dist/pc/pc.equipment.js +7 -5
  76. package/dist/pc/pc.feature-effects.d.ts +21 -2
  77. package/dist/pc/pc.feature-effects.js +15 -2
  78. package/dist/pc/pc.infusions.d.ts +9 -1
  79. package/dist/pc/pc.infusions.js +3 -2
  80. package/dist/pc/pc.member-choices.d.ts +122 -0
  81. package/dist/pc/pc.member-choices.js +39 -0
  82. package/dist/pc/pc.parser.js +1 -1
  83. package/dist/pc/pc.pools.d.ts +7 -0
  84. package/dist/pc/pc.pools.js +5 -2
  85. package/dist/pc/pc.proficiencies.d.ts +14 -0
  86. package/dist/pc/pc.proficiencies.js +72 -22
  87. package/dist/pc/pc.proficiency-normalize.d.ts +14 -0
  88. package/dist/pc/pc.proficiency-normalize.js +9 -3
  89. package/dist/pc/pc.proficiency-query.js +7 -1
  90. package/dist/pc/pc.recalc.js +212 -99
  91. package/dist/pc/pc.resolver.d.ts +6 -2
  92. package/dist/pc/pc.resolver.js +16 -14
  93. package/dist/pc/pc.rest.js +4 -3
  94. package/dist/pc/pc.schema.d.ts +48 -2
  95. package/dist/pc/pc.schema.js +1 -1
  96. package/dist/pc/pc.spell-scope.d.ts +22 -0
  97. package/dist/pc/pc.tool-picks.js +2 -2
  98. package/dist/pc/pc.types.d.ts +110 -6
  99. package/dist/pc/pc.weapon-grant.d.ts +15 -0
  100. package/dist/pc/pool-layout.d.ts +3 -9
  101. package/dist/pc/pool-layout.js +1 -3
  102. package/dist/pc/resource-equivalents.d.ts +44 -0
  103. package/dist/pc/spell-source.js +4 -9
  104. package/dist/race/race.codec.js +6 -6
  105. package/dist/race/race.parser.js +5 -5
  106. package/dist/race/race.schema.js +4 -4
  107. package/dist/schemas/choice-schema.js +2 -2
  108. package/dist/schemas/feature-effect-schema.d.ts +34 -0
  109. package/dist/schemas/feature-effect-schema.js +1 -1
  110. package/dist/schemas/feature-schema.js +3 -3
  111. package/dist/spell/spell.codec.js +2 -2
  112. package/dist/spell/spell.parser.d.ts +6 -1
  113. package/dist/spell/spell.parser.js +5 -3
  114. package/dist/spell/spell.types.d.ts +10 -0
  115. package/dist/subclass/subclass.codec.js +6 -6
  116. package/dist/subclass/subclass.parser.js +5 -5
  117. package/dist/subclass/subclass.schema.js +4 -4
  118. package/dist/types/choice.d.ts +7 -2
  119. package/dist/types/feature-effect.d.ts +24 -0
  120. package/dist/types/optional-feature.types.d.ts +6 -1
  121. package/dist/types/selection-pool.d.ts +2 -2
  122. package/package.json +1 -1
@@ -1,13 +1,13 @@
1
1
  import {
2
2
  migrateLegacy,
3
3
  parseMonster
4
- } from "../chunk-VDPRBUU5.js";
5
- import "../chunk-EL6QPF6I.js";
6
- import "../chunk-FPGXFD2M.js";
4
+ } from "../chunk-BJWSOQUC.js";
5
+ import "../chunk-VP5TIXDK.js";
6
+ import "../chunk-B2QHP6UF.js";
7
7
  import "../chunk-WYGD2UGN.js";
8
8
  import "../chunk-ZJXSXVFP.js";
9
- import "../chunk-BRGLDWUP.js";
10
- import "../chunk-ZMJQUZQH.js";
9
+ import "../chunk-OOL4KMG2.js";
10
+ import "../chunk-JXWNXIIZ.js";
11
11
  import "../chunk-UA5KS2PL.js";
12
12
  export {
13
13
  migrateLegacy,
@@ -11,12 +11,12 @@ import {
11
11
  monsterSpeedSchema,
12
12
  monsterSpellcastingSchema,
13
13
  monsterTypeSchema
14
- } from "../chunk-EL6QPF6I.js";
15
- import "../chunk-FPGXFD2M.js";
14
+ } from "../chunk-VP5TIXDK.js";
15
+ import "../chunk-B2QHP6UF.js";
16
16
  import "../chunk-WYGD2UGN.js";
17
17
  import "../chunk-ZJXSXVFP.js";
18
- import "../chunk-BRGLDWUP.js";
19
- import "../chunk-ZMJQUZQH.js";
18
+ import "../chunk-OOL4KMG2.js";
19
+ import "../chunk-JXWNXIIZ.js";
20
20
  import "../chunk-UA5KS2PL.js";
21
21
  export {
22
22
  MONSTER_KNOWN_KEYS,
@@ -1,11 +1,12 @@
1
1
  import {
2
2
  optionalFeatureCodec
3
- } from "../chunk-PX25R3DK.js";
4
- import "../chunk-QSBJ6NEM.js";
5
- import "../chunk-JNNNBEUH.js";
3
+ } from "../chunk-FVXLP7P3.js";
4
+ import "../chunk-FMUD3LDV.js";
5
+ import "../chunk-VN5DLURA.js";
6
6
  import "../chunk-WYGD2UGN.js";
7
7
  import "../chunk-ZJXSXVFP.js";
8
- import "../chunk-ZMJQUZQH.js";
8
+ import "../chunk-OOL4KMG2.js";
9
+ import "../chunk-JXWNXIIZ.js";
9
10
  import "../chunk-UA5KS2PL.js";
10
11
  export {
11
12
  optionalFeatureCodec
@@ -1,10 +1,11 @@
1
1
  import {
2
2
  parseOptionalFeature
3
- } from "../chunk-QSBJ6NEM.js";
4
- import "../chunk-JNNNBEUH.js";
3
+ } from "../chunk-FMUD3LDV.js";
4
+ import "../chunk-VN5DLURA.js";
5
5
  import "../chunk-WYGD2UGN.js";
6
6
  import "../chunk-ZJXSXVFP.js";
7
- import "../chunk-ZMJQUZQH.js";
7
+ import "../chunk-OOL4KMG2.js";
8
+ import "../chunk-JXWNXIIZ.js";
8
9
  import "../chunk-UA5KS2PL.js";
9
10
  export {
10
11
  parseOptionalFeature
@@ -183,6 +183,31 @@ export declare const optionalFeatureEntitySchema: z.ZodObject<{
183
183
  minimum: z.ZodOptional<z.ZodNumber>;
184
184
  condition: z.ZodOptional<z.ZodString>;
185
185
  subject: z.ZodOptional<z.ZodString>;
186
+ }, z.core.$strip>, z.ZodObject<{
187
+ kind: z.ZodLiteral<"save-bonus">;
188
+ ability: z.ZodEnum<{
189
+ str: "str";
190
+ dex: "dex";
191
+ con: "con";
192
+ int: "int";
193
+ wis: "wis";
194
+ cha: "cha";
195
+ }>;
196
+ minimum: z.ZodOptional<z.ZodNumber>;
197
+ saves: z.ZodOptional<z.ZodArray<z.ZodEnum<{
198
+ str: "str";
199
+ dex: "dex";
200
+ con: "con";
201
+ int: "int";
202
+ wis: "wis";
203
+ cha: "cha";
204
+ }>>>;
205
+ inactive_while: z.ZodOptional<z.ZodEnum<{
206
+ incapacitated: "incapacitated";
207
+ unconscious: "unconscious";
208
+ }>>;
209
+ condition: z.ZodOptional<z.ZodString>;
210
+ subject: z.ZodOptional<z.ZodString>;
186
211
  }, z.core.$strip>, z.ZodObject<{
187
212
  kind: z.ZodLiteral<"half-proficiency">;
188
213
  skills: z.ZodOptional<z.ZodArray<z.ZodString>>;
@@ -276,6 +301,15 @@ export declare const optionalFeatureEntitySchema: z.ZodObject<{
276
301
  finesse: "finesse";
277
302
  thrown: "thrown";
278
303
  }>>]>>;
304
+ spell_scope: z.ZodOptional<z.ZodObject<{
305
+ list: z.ZodOptional<z.ZodString>;
306
+ level: z.ZodOptional<z.ZodNumber>;
307
+ school: z.ZodOptional<z.ZodString>;
308
+ damage_types: z.ZodOptional<z.ZodArray<z.ZodString>>;
309
+ damage_type_pick: z.ZodOptional<z.ZodString>;
310
+ spells: z.ZodOptional<z.ZodArray<z.ZodString>>;
311
+ once: z.ZodOptional<z.ZodBoolean>;
312
+ }, z.core.$strict>>;
279
313
  condition: z.ZodOptional<z.ZodString>;
280
314
  subject: z.ZodOptional<z.ZodString>;
281
315
  }, z.core.$strip>, z.ZodObject<{
@@ -689,6 +723,7 @@ export declare const optionalFeatureEntitySchema: z.ZodObject<{
689
723
  }, z.core.$strict>;
690
724
  }, z.core.$strict>>>;
691
725
  }, z.core.$strict>>;
726
+ choices: z.ZodOptional<z.ZodArray<z.ZodType<import("../index.js").Choice, unknown, z.core.$ZodTypeInternals<import("../index.js").Choice, unknown>>>>;
692
727
  }, z.core.$strip>;
693
728
  export type OptionalFeatureSchemaInput = z.input<typeof optionalFeatureEntitySchema>;
694
729
  export type OptionalFeatureSchemaOutput = z.output<typeof optionalFeatureEntitySchema>;
@@ -2,10 +2,11 @@ import {
2
2
  infuseBlockSchema,
3
3
  optionRowSchema,
4
4
  optionalFeatureEntitySchema
5
- } from "../chunk-JNNNBEUH.js";
5
+ } from "../chunk-VN5DLURA.js";
6
6
  import "../chunk-WYGD2UGN.js";
7
7
  import "../chunk-ZJXSXVFP.js";
8
- import "../chunk-ZMJQUZQH.js";
8
+ import "../chunk-OOL4KMG2.js";
9
+ import "../chunk-JXWNXIIZ.js";
9
10
  import "../chunk-UA5KS2PL.js";
10
11
  export {
11
12
  infuseBlockSchema,
@@ -3,7 +3,7 @@ import type { RaceEntity } from "@archivist-gg/dnd5e/race/race.types";
3
3
  import type { FeatEntity } from "@archivist-gg/dnd5e/feat/feat.types";
4
4
  import type { Spell } from "@archivist-gg/dnd5e/spell/spell.types";
5
5
  import type { Ability } from "@archivist-gg/dnd5e";
6
- import type { ResolvedClass, ResolvedSpell } from "./pc.types.js";
6
+ import type { ChoiceValue, ResolvedClass, ResolvedPool, ResolvedSpell } from "./pc.types.js";
7
7
  export declare const prefixOf: (slug: string) => string;
8
8
  /** §5.2.2 · a raw 5etools / bundle spell ref → the bare NAME slug. The path tail is taken ONLY for a wikilink; a bare
9
9
  * name may legally contain "/" ("blindness/deafness" → "blindnessdeafness", the converter's own slug tail · Gate 0 B1).
@@ -34,7 +34,16 @@ export declare function resolveSpellByName(opts: {
34
34
  /** §5.2.9 · fold a race's entries ONLY when no select-inline on race.choices[] / traits[].choices[] / nested option.choices[]
35
35
  * carries an id outside the structural set (nested: zero carriers, defensive). */
36
36
  export declare function raceIsUngated(race: RaceEntity): boolean;
37
- /** §5.2.1 · the reader. Every object it receives is the RAW registry entity; nothing is mutated. */
37
+ /** SRD-G T4: the slugs (value and label) of every option the character CHOSE on a race's content select-inlines
38
+ * (`race.choices[]` and `traits[].choices[]`, the structural set excluded), read through `read(<choice id>)`. */
39
+ export declare function chosenRaceOptionKeys(race: RaceEntity, read: (id: string) => ChoiceValue | undefined): Set<string>;
40
+ /** §5.2.1 · the reader. Every object it receives is the RAW registry entity; nothing is mutated.
41
+ *
42
+ * SRD-G T4 (audit §3a): the RACE root also reads (1) a race whose lineage select-inline GATES it: the entry NAMED like
43
+ * the option the character chose folds (the SRD 5.2 Tiefling's legacy, the Elf's and Gnome's lineage); an unnamed
44
+ * entry on a gated race still folds nothing (it may belong to any lineage); (2) an `ability: {choose}` entry, when
45
+ * `raceChoice("spellcasting-ability")` answers one of its abilities (unanswered, the entry waits for the pick);
46
+ * (3) the `innate` level spells (the level 3 / 5 once-per-Long-Rest spells), folded always prepared like `known`. */
38
47
  export declare function collectAdditionalSpells(args: {
39
48
  race: RaceEntity | null;
40
49
  feats: FeatEntity[];
@@ -44,4 +53,9 @@ export declare function collectAdditionalSpells(args: {
44
53
  alreadyCollected: ResolvedSpell[];
45
54
  entities: EntityRegistry;
46
55
  warnings: string[];
56
+ /** SRD-G T4: the character's answer to a race choice, by choice id (`origin_choices["race:<id>"]`). */
57
+ raceChoice?: (id: string) => ChoiceValue | undefined;
58
+ /** User report 2026-09-28: the RESOLVED pools. Every member the character has (a pick or a grant; an item-bound one's
59
+ * subject is its item) is a root, read at the owning class's level, its spells that class's. */
60
+ pools?: ReadonlyArray<ResolvedPool>;
47
61
  }): ResolvedSpell[];
@@ -1,20 +1,23 @@
1
1
  import {
2
2
  buildSpellNameIndex,
3
+ chosenRaceOptionKeys,
3
4
  collectAdditionalSpells,
4
5
  normalizeSpellRef,
5
6
  prefixOf,
6
7
  raceIsUngated,
7
8
  resolveSpellByName
8
- } from "../chunk-DPM6V7YX.js";
9
+ } from "../chunk-LICYHPI3.js";
9
10
  import "../chunk-PVCEA4HZ.js";
10
11
  import "../chunk-LVQLWRCU.js";
12
+ import "../chunk-4J6DS3EJ.js";
11
13
  import "../chunk-ZCTUYGNV.js";
12
- import "../chunk-XY6X2APM.js";
14
+ import "../chunk-7Q2VPKCD.js";
13
15
  import "../chunk-ZDAEGJH4.js";
14
16
  import "../chunk-WELIKLZF.js";
15
17
  import "../chunk-UA5KS2PL.js";
16
18
  export {
17
19
  buildSpellNameIndex,
20
+ chosenRaceOptionKeys,
18
21
  collectAdditionalSpells,
19
22
  normalizeSpellRef,
20
23
  prefixOf,
@@ -0,0 +1,41 @@
1
+ /**
2
+ * D2b-A · the numbers an amount resolves against (design §1.2 A). The modifier and the save DC are those of the class
3
+ * that OWNS the feature or grants the spell (multiclass: the granting class, user ruling 2026-09-27).
4
+ */
5
+ import type { Ability } from "@archivist-gg/dnd5e/types/choice";
6
+ import type { Spell } from "@archivist-gg/dnd5e/spell/spell.types";
7
+ import { type AmountBindings } from "@archivist-gg/dnd5e/dnd/amount-text";
8
+ import type { DerivedStats, FeatureSource, ResolvedCharacter, ResolvedSpell, SpellDamageRider } from "./pc.types.js";
9
+ /** The derived fields the bindings read (recalc builds them before its return; the sheet passes `ctx.derived`). */
10
+ export type AmountDerived = Pick<DerivedStats, "proficiencyBonus" | "mods" | "spellcastingClasses"> & Partial<Pick<DerivedStats, "abilitySpellcasting">>;
11
+ /** The class slug that owns `source`: a class by its slug, a subclass by the class that holds it, a feat through the
12
+ * slot it was taken at (`via`), a pool member through its pool's class. Null for race, background and campaign. */
13
+ export declare function ownerClassSlug(source: FeatureSource | undefined, resolved: Pick<ResolvedCharacter, "classes">): string | null;
14
+ /** The bindings an amount owned by `owner` resolves against: `class_level` is the OWNING class's level (the total level
15
+ * for a race, background or unowned source), `spell_mod` / `spell_dc` come from that class's spellcasting row, else
16
+ * the first caster's, else they stay unbound (the amount prints its words or a label). */
17
+ export declare function amountBindingsFor(owner: FeatureSource | undefined, resolved: Pick<ResolvedCharacter, "classes" | "totalLevel">, derived: AmountDerived): AmountBindings;
18
+ /** How a spell is cast: its ability, save DC and attack bonus. A grant that carries its OWN ability (a feat's chosen
19
+ * ability, a race grant, a class-less row) reads `abilitySpellcasting`; every other spell reads its class's row, else
20
+ * the first caster's. The one lookup the Spells tab's DC, attack and effect cells share. */
21
+ export declare function spellcastingFor(spell: Pick<ResolvedSpell, "source" | "classSlug" | "ability">, derived: AmountDerived): {
22
+ ability: Ability;
23
+ saveDC: number;
24
+ attackBonus: number;
25
+ } | null;
26
+ /** The bindings a spell's effect resolves against: its caster's modifier and save DC (see {@link spellcastingFor}). */
27
+ export declare function spellAmountBindings(spell: Pick<ResolvedSpell, "source" | "classSlug" | "ability">, resolved: Pick<ResolvedCharacter, "classes" | "totalLevel">, derived: AmountDerived): AmountBindings;
28
+ /** What a spell adds to its base roll ONCE, in token form: `{spell_mod}` when its text reads "<the base roll> plus (or
29
+ * +) your spellcasting (ability) modifier" (35 vault notes: Healing Word, Cure Wounds, Spiritual Weapon, ...), else
30
+ * null. Read from the note's own words at read time; the roll must be the one the phrase follows, so a spell whose
31
+ * modifier rides a different roll (a heal beside a damage roll) adds nothing. */
32
+ export declare function spellRollBonus(spell: Pick<Spell, "damage_roll" | "description">): string | null;
33
+ /** The spell's printed roll with every spell damage rider that reaches it added INSIDE the one roll (bonus damage prints
34
+ * in the damage cell, user ruling): Agonizing Blast's Charisma on its cantrip reads "1d10+3" (found live 2026-09-28),
35
+ * Potent Spellcasting's Wisdom on Sacred Flame "1d8+3". A conditional rider, or one of another canonical damage type
36
+ * than the spell's own, is not added here: it is a line of its own (`spellDamageRiderLines`). */
37
+ export declare function addSpellDamageRiders(roll: string, spell: Pick<ResolvedSpell, "slug" | "entity">, derived: Partial<Pick<DerivedStats, "spellDamageRiders">>): string;
38
+ /** The spell damage riders that reach `spell` but do not fold into its roll, each its own line in the damage cell, the
39
+ * way a conditional weapon rider is (Power Surge's "+ 5 force" once a surge is spent; Arcane Firearm's "+ 1d8" through
40
+ * the firearm): a `condition`, or another canonical damage type. `spells` and `once` are the engine's, not the line's. */
41
+ export declare function spellDamageRiderLines(spell: Pick<ResolvedSpell, "slug" | "entity">, derived: Partial<Pick<DerivedStats, "spellDamageRiders">>): Array<Pick<SpellDamageRider, "amount" | "damage_type" | "source" | "condition">>;
@@ -0,0 +1,28 @@
1
+ import {
2
+ addSpellDamageRiders,
3
+ amountBindingsFor,
4
+ ownerClassSlug,
5
+ spellAmountBindings,
6
+ spellDamageRiderLines,
7
+ spellRollBonus,
8
+ spellcastingFor
9
+ } from "../chunk-TRBGC4ZG.js";
10
+ import "../chunk-KR6JF3BF.js";
11
+ import "../chunk-KSTV7J2U.js";
12
+ import "../chunk-DPUJDOKV.js";
13
+ import "../chunk-IUAAXXNO.js";
14
+ import "../chunk-LVQLWRCU.js";
15
+ import "../chunk-WOHX7YTH.js";
16
+ import "../chunk-EVMUJYUD.js";
17
+ import "../chunk-VTTA2ALZ.js";
18
+ import "../chunk-PDJSUH24.js";
19
+ import "../chunk-WELIKLZF.js";
20
+ export {
21
+ addSpellDamageRiders,
22
+ amountBindingsFor,
23
+ ownerClassSlug,
24
+ spellAmountBindings,
25
+ spellDamageRiderLines,
26
+ spellRollBonus,
27
+ spellcastingFor
28
+ };
@@ -101,6 +101,9 @@ export interface DecisionItem {
101
101
  * status to "partial".
102
102
  */
103
103
  children?: DecisionItem[];
104
+ /** D2b-A (design §2.2 step 7): on a child of a pool item, the name of the member the choice belongs to ("Lessons of the
105
+ * First Ones"), so the strip reads "Lessons of the First Ones · Origin feat". Absent everywhere else. */
106
+ parentLabel?: string;
104
107
  }
105
108
  export interface DecisionLedger {
106
109
  classes: Array<{
@@ -200,6 +203,14 @@ export declare function computeEffectiveProficiencies(resolved: ResolvedCharacte
200
203
  languages: ProficiencyEntry[];
201
204
  tools: ProficiencyEntry[];
202
205
  };
206
+ /** D4 A: the complement of {@link computeEffectiveProficiencies}: every language and tool the character's grants, picks
207
+ * or adds would hold but `overrides.<domain>.remove` (or a `none` tools tri) suppresses, each entry keeping its
208
+ * `sources` and `origin`. The proficiency picker draws these struck through ("Dwarf · removed"). Both functions read
209
+ * ONE composer, so a row is kept or suppressed, never both and never neither. */
210
+ export declare function computeSuppressedProficiencies(resolved: ResolvedCharacter): {
211
+ languages: ProficiencyEntry[];
212
+ tools: ProficiencyEntry[];
213
+ };
203
214
  export interface OriginAbilityPoints {
204
215
  race: Partial<Record<Ability, number>>;
205
216
  background: Partial<Record<Ability, number>>;
@@ -4,36 +4,39 @@ import {
4
4
  buildDecisionLedger,
5
5
  collectChosenAbilityPoints,
6
6
  collectChosenProficiencies,
7
- computeEffectiveProficiencies
8
- } from "../chunk-QEO7LYTG.js";
7
+ computeEffectiveProficiencies,
8
+ computeSuppressedProficiencies
9
+ } from "../chunk-EJD47JHL.js";
9
10
  import "../chunk-2LULMQTF.js";
10
- import "../chunk-H5PTKYXL.js";
11
- import "../chunk-KSTV7J2U.js";
12
- import "../chunk-DPUJDOKV.js";
13
- import "../chunk-4BZ47YJ4.js";
11
+ import "../chunk-QA3YCOML.js";
12
+ import "../chunk-64VNLMSG.js";
14
13
  import "../chunk-TOM66P2P.js";
15
14
  import "../chunk-KU3YLF6D.js";
16
- import "../chunk-RLGQ5PZZ.js";
17
- import "../chunk-T5GZBKIQ.js";
15
+ import "../chunk-5JXFJ5AU.js";
16
+ import "../chunk-RD2MID3M.js";
17
+ import "../chunk-LICYHPI3.js";
18
+ import "../chunk-PVCEA4HZ.js";
19
+ import "../chunk-KSTV7J2U.js";
20
+ import "../chunk-DPUJDOKV.js";
21
+ import "../chunk-LBEXLN6I.js";
22
+ import "../chunk-NXUY5XQN.js";
18
23
  import "../chunk-W6GC6OKK.js";
19
- import "../chunk-HJQNK3J5.js";
24
+ import "../chunk-B3DP42OM.js";
20
25
  import "../chunk-IUAAXXNO.js";
21
26
  import "../chunk-YHYTW5QA.js";
22
- import "../chunk-DPM6V7YX.js";
23
- import "../chunk-PVCEA4HZ.js";
24
- import "../chunk-LBEXLN6I.js";
25
27
  import "../chunk-ZUQW5VBZ.js";
26
28
  import "../chunk-IHE6KVC3.js";
27
29
  import "../chunk-LHZXYFBU.js";
30
+ import "../chunk-YBLDE5CG.js";
28
31
  import "../chunk-LVQLWRCU.js";
29
32
  import "../chunk-CM5CWO4K.js";
33
+ import "../chunk-4J6DS3EJ.js";
34
+ import "../chunk-EVMUJYUD.js";
35
+ import "../chunk-VTTA2ALZ.js";
30
36
  import {
31
37
  wikilinkTailSlug
32
38
  } from "../chunk-ZCTUYGNV.js";
33
- import "../chunk-YBLDE5CG.js";
34
- import "../chunk-EVMUJYUD.js";
35
- import "../chunk-VTTA2ALZ.js";
36
- import "../chunk-XY6X2APM.js";
39
+ import "../chunk-7Q2VPKCD.js";
37
40
  import "../chunk-ZDAEGJH4.js";
38
41
  import "../chunk-3TM34RSJ.js";
39
42
  import "../chunk-PDJSUH24.js";
@@ -47,5 +50,6 @@ export {
47
50
  collectChosenAbilityPoints,
48
51
  collectChosenProficiencies,
49
52
  computeEffectiveProficiencies,
53
+ computeSuppressedProficiencies,
50
54
  wikilinkTailSlug
51
55
  };
@@ -11,15 +11,16 @@ import {
11
11
  isWeaponLikeEntry,
12
12
  itemChargesMax,
13
13
  scrollSpellCost
14
- } from "../chunk-T5GZBKIQ.js";
14
+ } from "../chunk-NXUY5XQN.js";
15
15
  import "../chunk-W6GC6OKK.js";
16
- import "../chunk-HJQNK3J5.js";
16
+ import "../chunk-B3DP42OM.js";
17
17
  import "../chunk-IUAAXXNO.js";
18
18
  import "../chunk-ZUQW5VBZ.js";
19
19
  import "../chunk-IHE6KVC3.js";
20
20
  import "../chunk-LHZXYFBU.js";
21
21
  import "../chunk-LVQLWRCU.js";
22
22
  import "../chunk-CM5CWO4K.js";
23
+ import "../chunk-4J6DS3EJ.js";
23
24
  import "../chunk-ZCTUYGNV.js";
24
25
  import "../chunk-3TM34RSJ.js";
25
26
  import "../chunk-PDJSUH24.js";
@@ -4,14 +4,15 @@ import {
4
4
  computeSlotsAndAttacks,
5
5
  emptyAppliedBonuses,
6
6
  isWeaponSlugProficient
7
- } from "../chunk-Q5XTEYHD.js";
7
+ } from "../chunk-7XJHI5H5.js";
8
+ import "../chunk-3LWMFYKS.js";
8
9
  import "../chunk-YDGMBMYI.js";
9
- import "../chunk-RLGQ5PZZ.js";
10
- import "../chunk-T5GZBKIQ.js";
10
+ import "../chunk-EJP263OP.js";
11
+ import "../chunk-5JXFJ5AU.js";
12
+ import "../chunk-NXUY5XQN.js";
11
13
  import "../chunk-W6GC6OKK.js";
12
- import "../chunk-HJQNK3J5.js";
14
+ import "../chunk-B3DP42OM.js";
13
15
  import "../chunk-IUAAXXNO.js";
14
- import "../chunk-EJP263OP.js";
15
16
  import "../chunk-ZUQW5VBZ.js";
16
17
  import "../chunk-IHE6KVC3.js";
17
18
  import "../chunk-HHBD4SQ6.js";
@@ -19,6 +20,7 @@ import "../chunk-A54HHCWW.js";
19
20
  import "../chunk-LHZXYFBU.js";
20
21
  import "../chunk-LVQLWRCU.js";
21
22
  import "../chunk-CM5CWO4K.js";
23
+ import "../chunk-4J6DS3EJ.js";
22
24
  import "../chunk-ZCTUYGNV.js";
23
25
  import "../chunk-3TM34RSJ.js";
24
26
  import "../chunk-PDJSUH24.js";
@@ -1,6 +1,6 @@
1
1
  import type { FeatureEffect, SenseType } from "@archivist-gg/dnd5e/types/feature-effect";
2
2
  import type { Ability } from "@archivist-gg/dnd5e";
3
- import type { DamageRider, DefenseGrant, FeatureSource, ResolvedCharacter, ResolvedFeature, RollModifierEntry, SaveOutcomeEntry } from "./pc.types.js";
3
+ import type { DamageRider, DefenseGrant, FeatureSource, ResolvedCharacter, ResolvedFeature, RollModifierEntry, SaveOutcomeEntry, SpellDamageRider } from "./pc.types.js";
4
4
  /**
5
5
  * A melee-attack ability override from a `weapon-ability` effect. `weaponSlugs`
6
6
  * (bare, namespace-stripped) scopes the override to matching weapon types only;
@@ -34,6 +34,15 @@ export interface FeatureEffectTotals {
34
34
  minimum: number;
35
35
  label: string;
36
36
  }[];
37
+ /** SL (spec §11.2): ability-based numeric SAVE bonuses (Aura of Protection), resolved in recalc against final scores and
38
+ * the character's conditions. Empty `saves` = every save; recalc keeps one term per `label`. */
39
+ save_bonus_terms: {
40
+ saves: Ability[];
41
+ ability: Ability;
42
+ minimum: number;
43
+ inactiveWhile?: "incapacitated" | "unconscious";
44
+ label: string;
45
+ }[];
37
46
  /**
38
47
  * Half-proficiency terms (Jack of All Trades, Remarkable Athlete). Resolved in recalc against the
39
48
  * proficiency bonus, and ONLY for a skill whose effective tri is "none" — that gate is the mechanic
@@ -201,11 +210,18 @@ export interface FeatureEffectTotals {
201
210
  attackNotes: string[];
202
211
  /**
203
212
  * Additive on-hit damage riders from `damage-bonus` effects with
204
- * `applies_to` weapon/all (spell-only ignored — no spell surface). Each is
213
+ * `applies_to` weapon/all (spell and all riders also go to `spellDamageBonuses`). Each is
205
214
  * labeled with the owning feature's name. recalc merges these onto every
206
215
  * weapon AttackRow's `damageRiders`.
207
216
  */
208
217
  damageBonuses: DamageRider[];
218
+ /**
219
+ * The `damage-bonus` effects with `applies_to: spell` or `all`, labeled with the owning feature's name and carrying its
220
+ * `spellTargets` and `spell_scope` (found live 2026-09-28: they were dropped here, so Agonizing Blast never reached its
221
+ * cantrip). recalc reads each against the character's spells (`spellsReached`, `spellsInScope`) into
222
+ * `DerivedStats.spellDamageRiders`.
223
+ */
224
+ spellDamageBonuses: SpellDamageRider[];
209
225
  }
210
226
  export declare function emptyFeatureEffectTotals(): FeatureEffectTotals;
211
227
  /**
@@ -226,6 +242,9 @@ export declare function emptyFeatureEffectTotals(): FeatureEffectTotals;
226
242
  export interface FeatureEffectsOpts {
227
243
  activeBuffs?: Set<string>;
228
244
  levelFor?: (source: FeatureSource) => number;
245
+ /** RG: the DICE cell (`1d6`) of column `column` in the table of the class that owns `source`, at `level`; null when that
246
+ * table has no such dice cell. recalc passes it; a caller that passes none leaves every rider at its authored amount. */
247
+ tableDiceFor?: (source: FeatureSource, column: string, level: number) => string | null;
229
248
  }
230
249
  /** Does this feature's effects fold right now? An activatable feature folds ONLY
231
250
  * while its id is in the active set; a buff is off until toggled. Shared by
@@ -7,12 +7,25 @@ import {
7
7
  foldsNow,
8
8
  foldsOnSelf,
9
9
  selfEffectsOf
10
- } from "../chunk-4BZ47YJ4.js";
10
+ } from "../chunk-64VNLMSG.js";
11
11
  import "../chunk-TOM66P2P.js";
12
12
  import "../chunk-KU3YLF6D.js";
13
- import "../chunk-RLGQ5PZZ.js";
13
+ import "../chunk-5JXFJ5AU.js";
14
+ import "../chunk-RD2MID3M.js";
15
+ import "../chunk-NXUY5XQN.js";
16
+ import "../chunk-W6GC6OKK.js";
17
+ import "../chunk-B3DP42OM.js";
18
+ import "../chunk-IUAAXXNO.js";
19
+ import "../chunk-ZUQW5VBZ.js";
20
+ import "../chunk-IHE6KVC3.js";
21
+ import "../chunk-LHZXYFBU.js";
22
+ import "../chunk-YBLDE5CG.js";
14
23
  import "../chunk-LVQLWRCU.js";
24
+ import "../chunk-CM5CWO4K.js";
25
+ import "../chunk-4J6DS3EJ.js";
15
26
  import "../chunk-ZCTUYGNV.js";
27
+ import "../chunk-3TM34RSJ.js";
28
+ import "../chunk-PDJSUH24.js";
16
29
  import "../chunk-WELIKLZF.js";
17
30
  export {
18
31
  assembleEffectFeatures,
@@ -50,7 +50,9 @@ export interface CandidateOptions {
50
50
  isEntityVisible?: (e: RegisteredEntity) => boolean;
51
51
  exclude?: readonly string[];
52
52
  }
53
- /** One option row as the pickers read it (R20): `candidates` are VISIBLE full slugs in the §5.8 order (U-A). */
53
+ /** One option row as the pickers read it (R20): `candidates` are VISIBLE full slugs in the §5.8 order (U-A). PT (spec §4,
54
+ * §6.5): `type` and `rarity` (lower-case) name the row's item, read from its first candidate (else its first installed
55
+ * item, visible or not), a `filter` row from its filter; `charges` are that item's own; null when nothing says. */
54
56
  export interface ResolvedOptionRow {
55
57
  key: string;
56
58
  name: string;
@@ -59,6 +61,12 @@ export interface ResolvedOptionRow {
59
61
  arm: "item" | "variant" | "filter";
60
62
  candidates: string[];
61
63
  availability: "installed" | "hidden-only" | "not-installed";
64
+ type: string | null;
65
+ rarity: string | null;
66
+ charges: {
67
+ max: number;
68
+ recharge?: string;
69
+ } | null;
62
70
  }
63
71
  /** The per-copy picker's data for one repeatable member of a pool (spec §5.1, R20). */
64
72
  export interface RepeatableMember {
@@ -23,15 +23,16 @@ import {
23
23
  scaledInfuseItem,
24
24
  splitOne,
25
25
  withEntryCharges
26
- } from "../chunk-T5GZBKIQ.js";
26
+ } from "../chunk-NXUY5XQN.js";
27
27
  import "../chunk-W6GC6OKK.js";
28
- import "../chunk-HJQNK3J5.js";
28
+ import "../chunk-B3DP42OM.js";
29
29
  import "../chunk-IUAAXXNO.js";
30
30
  import "../chunk-ZUQW5VBZ.js";
31
31
  import "../chunk-IHE6KVC3.js";
32
32
  import "../chunk-LHZXYFBU.js";
33
33
  import "../chunk-LVQLWRCU.js";
34
34
  import "../chunk-CM5CWO4K.js";
35
+ import "../chunk-4J6DS3EJ.js";
35
36
  import "../chunk-ZCTUYGNV.js";
36
37
  import "../chunk-3TM34RSJ.js";
37
38
  import "../chunk-PDJSUH24.js";