@archivist-gg/dnd5e 0.3.11 → 0.3.17

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 (192) hide show
  1. package/LICENSES/SRD.md +38 -3
  2. package/dist/armor/armor.codec.js +3 -3
  3. package/dist/armor/armor.parser.js +2 -2
  4. package/dist/armor/armor.schema.d.ts +1 -0
  5. package/dist/armor/armor.schema.js +1 -1
  6. package/dist/armor/armor.types.d.ts +2 -0
  7. package/dist/background/background.codec.js +5 -5
  8. package/dist/background/background.parser.js +4 -4
  9. package/dist/background/background.schema.js +3 -3
  10. package/dist/{chunk-XTRDCSJB.js → chunk-2JSQE3DD.js} +15 -1
  11. package/dist/chunk-2LULMQTF.js +14 -0
  12. package/dist/{chunk-MAH6DCRI.js → chunk-2UDSN6VW.js} +1 -1
  13. package/dist/chunk-3LWMFYKS.js +57 -0
  14. package/dist/{chunk-JCEV7KYN.js → chunk-3MGQFFNE.js} +1 -1
  15. package/dist/chunk-3VZZDKRA.js +1014 -0
  16. package/dist/{chunk-2DFENQIJ.js → chunk-5GKJAUMX.js} +2 -0
  17. package/dist/{chunk-2M34FLAY.js → chunk-5MXFW4O3.js} +9 -3
  18. package/dist/{chunk-4DOMDEBZ.js → chunk-6EI737IO.js} +1 -1
  19. package/dist/{chunk-G247QXWW.js → chunk-7ATNGKBS.js} +1 -1
  20. package/dist/{chunk-XY6X2APM.js → chunk-7Q2VPKCD.js} +17 -0
  21. package/dist/{chunk-T2SNEJOE.js → chunk-7QN7XSAK.js} +1 -1
  22. package/dist/{chunk-DNAJRMNN.js → chunk-A54HHCWW.js} +6 -7
  23. package/dist/{chunk-7YU4NPKR.js → chunk-AZRGFUSR.js} +1 -1
  24. package/dist/{chunk-PP2UHLBA.js → chunk-B3DP42OM.js} +5 -0
  25. package/dist/chunk-CM5CWO4K.js +735 -0
  26. package/dist/{chunk-MQ747UCR.js → chunk-DOXSFYLH.js} +70 -2
  27. package/dist/chunk-EJP263OP.js +186 -0
  28. package/dist/{chunk-SMLXZUBH.js → chunk-EYX4JMAU.js} +4 -1
  29. package/dist/{chunk-V6LJFP4R.js → chunk-FANQVQ3D.js} +2 -2
  30. package/dist/{chunk-AW3EHF3L.js → chunk-FC4IGH5Y.js} +1 -1
  31. package/dist/{chunk-23LZLBJK.js → chunk-G6MHJDVT.js} +6 -2
  32. package/dist/{chunk-JANNRGJC.js → chunk-G6PBI2BU.js} +1 -1
  33. package/dist/chunk-H5PTKYXL.js +101 -0
  34. package/dist/{chunk-LWFTHJIE.js → chunk-HHBD4SQ6.js} +1 -1
  35. package/dist/{chunk-JC5UNIVM.js → chunk-HS6FIOLP.js} +2 -0
  36. package/dist/chunk-HTYMW5CH.js +228 -0
  37. package/dist/chunk-IHE6KVC3.js +13 -0
  38. package/dist/{chunk-QHMWA3SZ.js → chunk-JCMUVZIK.js} +1 -1
  39. package/dist/{chunk-V373TRJE.js → chunk-JSM6JFZR.js} +198 -125
  40. package/dist/{chunk-LDDCNPHD.js → chunk-K5NJBTE2.js} +1 -1
  41. package/dist/chunk-KR6JF3BF.js +14 -0
  42. package/dist/{chunk-4ISR76DH.js → chunk-KSTV7J2U.js} +9 -3
  43. package/dist/chunk-LBEXLN6I.js +91 -0
  44. package/dist/{chunk-BLRW2UU6.js → chunk-LF5AGJA4.js} +2 -2
  45. package/dist/{chunk-UBBKSYBY.js → chunk-LHZXYFBU.js} +30 -1
  46. package/dist/{chunk-BIA32MQ5.js → chunk-MBX25B6D.js} +1 -1
  47. package/dist/{chunk-R2ZV233X.js → chunk-MYY2C5MB.js} +3 -3
  48. package/dist/{chunk-J77CKYV3.js → chunk-OFCSP6MT.js} +1 -1
  49. package/dist/{chunk-2INMRR3Q.js → chunk-ONTGZR5T.js} +326 -149
  50. package/dist/{chunk-MWCCGPG3.js → chunk-OOSRUJBI.js} +3 -2
  51. package/dist/{chunk-U3BABVJF.js → chunk-PKX6TGRE.js} +2 -2
  52. package/dist/{chunk-PJMG5XV3.js → chunk-PQZ4LM4Z.js} +1 -1
  53. package/dist/chunk-PXVNAY7T.js +84 -0
  54. package/dist/chunk-QH36K2PU.js +158 -0
  55. package/dist/{chunk-R747YKS7.js → chunk-QZSWN2KT.js} +1 -1
  56. package/dist/{chunk-CHUALUIX.js → chunk-RYLXAYIQ.js} +1 -1
  57. package/dist/{chunk-GFZ7PITJ.js → chunk-S3YUXDSC.js} +6 -1
  58. package/dist/{chunk-PZCE7DJM.js → chunk-T6QIF5XR.js} +31 -1
  59. package/dist/{chunk-CBEKVAX4.js → chunk-TULQ4FFX.js} +41 -13
  60. package/dist/{chunk-S56D6B6C.js → chunk-UUBJCNQU.js} +12 -3
  61. package/dist/{chunk-5N2GW72F.js → chunk-UZXG6QSY.js} +2 -1
  62. package/dist/{chunk-4XTNPNQB.js → chunk-VPYBK2MG.js} +1 -1
  63. package/dist/{chunk-3HX5VLWP.js → chunk-VRV3NNTA.js} +2 -2
  64. package/dist/{chunk-HZA7OE7N.js → chunk-XCFC7LGF.js} +2 -1
  65. package/dist/{chunk-BL3VELKP.js → chunk-Y5VVP73C.js} +1 -1
  66. package/dist/{chunk-PI4LLJG4.js → chunk-YD2VAHA6.js} +2 -2
  67. package/dist/{chunk-UIRMA5KM.js → chunk-YDGMBMYI.js} +1 -1
  68. package/dist/{chunk-NWDF5HG3.js → chunk-YKL6SHRJ.js} +1 -1
  69. package/dist/{chunk-6X4KUDMU.js → chunk-ZCTUYGNV.js} +7 -2
  70. package/dist/chunk-ZUQW5VBZ.js +89 -0
  71. package/dist/class/class.codec.js +7 -7
  72. package/dist/class/class.parser.js +6 -6
  73. package/dist/class/class.schema.d.ts +18 -0
  74. package/dist/class/class.schema.js +5 -5
  75. package/dist/class/class.standard-array.d.ts +16 -0
  76. package/dist/class/class.standard-array.js +20 -0
  77. package/dist/class/class.types.d.ts +3 -0
  78. package/dist/dnd/amount-text.d.ts +38 -0
  79. package/dist/dnd/amount-text.js +13 -0
  80. package/dist/dnd/resource-words.d.ts +4 -0
  81. package/dist/dnd/resource-words.js +30 -0
  82. package/dist/entities/base-item-resolver.js +2 -2
  83. package/dist/entities/slug.d.ts +18 -8
  84. package/dist/entities/slug.js +3 -1
  85. package/dist/feat/feat.codec.js +5 -5
  86. package/dist/feat/feat.parser.js +4 -4
  87. package/dist/feat/feat.schema.d.ts +41 -3
  88. package/dist/feat/feat.schema.js +3 -3
  89. package/dist/index.js +7513 -4177
  90. package/dist/item/item.actions-map.d.ts +40 -5
  91. package/dist/item/item.actions-map.js +5 -84
  92. package/dist/item/item.attunement.js +3 -9
  93. package/dist/item/item.bonuses.js +5 -2
  94. package/dist/item/item.codec.js +3 -3
  95. package/dist/item/item.conditions.js +4 -1
  96. package/dist/item/item.conditions.types.d.ts +4 -0
  97. package/dist/item/item.cost.d.ts +3 -0
  98. package/dist/item/item.cost.js +29 -0
  99. package/dist/item/item.icon.d.ts +15 -0
  100. package/dist/item/item.icon.js +211 -0
  101. package/dist/item/item.parser.js +2 -2
  102. package/dist/item/item.schema.d.ts +16 -1
  103. package/dist/item/item.schema.js +3 -1
  104. package/dist/item/item.types.d.ts +9 -2
  105. package/dist/monster/monster.parser.js +5 -5
  106. package/dist/monster/monster.schema.js +4 -4
  107. package/dist/optional-feature/optional-feature.codec.js +5 -4
  108. package/dist/optional-feature/optional-feature.parser.js +4 -3
  109. package/dist/optional-feature/optional-feature.schema.d.ts +255 -3
  110. package/dist/optional-feature/optional-feature.schema.js +7 -2
  111. package/dist/pc/pc.additional-spells.js +3 -3
  112. package/dist/pc/pc.amount-bindings.d.ts +32 -0
  113. package/dist/pc/pc.amount-bindings.js +23 -0
  114. package/dist/pc/pc.asi-flatten.d.ts +62 -1
  115. package/dist/pc/pc.asi-flatten.js +16 -0
  116. package/dist/pc/pc.conditions.js +1 -1
  117. package/dist/pc/pc.containment.d.ts +45 -0
  118. package/dist/pc/pc.containment.js +24 -0
  119. package/dist/pc/pc.decision-engine.d.ts +24 -3
  120. package/dist/pc/pc.decision-engine.js +26 -16
  121. package/dist/pc/pc.entry-overrides.d.ts +79 -0
  122. package/dist/pc/pc.entry-overrides.js +40 -0
  123. package/dist/pc/pc.equipment.d.ts +2 -2
  124. package/dist/pc/pc.equipment.js +19 -7
  125. package/dist/pc/pc.feature-effects.d.ts +12 -0
  126. package/dist/pc/pc.feature-effects.js +2 -2
  127. package/dist/pc/pc.infusions.d.ts +228 -0
  128. package/dist/pc/pc.infusions.js +64 -0
  129. package/dist/pc/pc.member-choices.d.ts +90 -0
  130. package/dist/pc/pc.member-choices.js +32 -0
  131. package/dist/pc/pc.parser.js +18 -1
  132. package/dist/pc/pc.pools.d.ts +8 -1
  133. package/dist/pc/pc.pools.js +13 -3
  134. package/dist/pc/pc.proficiencies.js +23 -15
  135. package/dist/pc/pc.proficiency-query.js +6 -0
  136. package/dist/pc/pc.recalc.d.ts +39 -36
  137. package/dist/pc/pc.recalc.js +115 -70
  138. package/dist/pc/pc.resolver.d.ts +2 -1
  139. package/dist/pc/pc.resolver.js +22 -14
  140. package/dist/pc/pc.resource-seed.js +1 -1
  141. package/dist/pc/pc.resources.d.ts +6 -1
  142. package/dist/pc/pc.resources.js +3 -1
  143. package/dist/pc/pc.rest.d.ts +21 -1
  144. package/dist/pc/pc.rest.js +52 -19
  145. package/dist/pc/pc.schema.d.ts +43 -2
  146. package/dist/pc/pc.schema.js +1 -1
  147. package/dist/pc/pc.slotting.d.ts +36 -3
  148. package/dist/pc/pc.slotting.js +13 -5
  149. package/dist/pc/pc.tool-picks.d.ts +51 -0
  150. package/dist/pc/pc.tool-picks.js +18 -0
  151. package/dist/pc/pc.types.d.ts +115 -14
  152. package/dist/pc/pc.weapon-grant.d.ts +15 -0
  153. package/dist/pc/pool-layout.d.ts +8 -0
  154. package/dist/pc/pool-layout.js +5 -3
  155. package/dist/pc/resource-equivalents.d.ts +44 -0
  156. package/dist/pc/spell-source.js +4 -9
  157. package/dist/race/race.codec.js +6 -6
  158. package/dist/race/race.parser.js +5 -5
  159. package/dist/race/race.schema.js +4 -4
  160. package/dist/schemas/attack-schema.d.ts +1 -1
  161. package/dist/schemas/choice-schema.js +2 -2
  162. package/dist/schemas/feature-effect-schema.d.ts +41 -3
  163. package/dist/schemas/feature-effect-schema.js +1 -1
  164. package/dist/schemas/feature-schema.js +3 -3
  165. package/dist/schemas/selection-pool-schema.d.ts +10 -0
  166. package/dist/schemas/selection-pool-schema.js +1 -1
  167. package/dist/spell/spell.codec.js +2 -2
  168. package/dist/spell/spell.parser.d.ts +6 -1
  169. package/dist/spell/spell.parser.js +5 -3
  170. package/dist/spell/spell.types.d.ts +10 -0
  171. package/dist/srd/retired-items.d.ts +14 -0
  172. package/dist/srd/retired-items.js +11 -0
  173. package/dist/subclass/subclass.codec.js +7 -7
  174. package/dist/subclass/subclass.parser.js +6 -6
  175. package/dist/subclass/subclass.schema.d.ts +10 -0
  176. package/dist/subclass/subclass.schema.js +5 -5
  177. package/dist/types/choice.d.ts +13 -0
  178. package/dist/types/equipment-grant.d.ts +18 -1
  179. package/dist/types/equipment-grant.js +12 -0
  180. package/dist/types/feature-effect.d.ts +12 -1
  181. package/dist/types/optional-feature.types.d.ts +84 -1
  182. package/dist/types/selection-pool.d.ts +18 -3
  183. package/dist/weapon/weapon.classify.d.ts +10 -8
  184. package/dist/weapon/weapon.classify.js +2 -2
  185. package/dist/weapon/weapon.codec.js +3 -3
  186. package/dist/weapon/weapon.parser.js +2 -2
  187. package/dist/weapon/weapon.schema.d.ts +1 -0
  188. package/dist/weapon/weapon.schema.js +1 -1
  189. package/dist/weapon/weapon.types.d.ts +2 -0
  190. package/package.json +1 -1
  191. package/dist/chunk-O4SRD3J5.js +0 -165
  192. package/dist/chunk-WXWPK3LI.js +0 -55
@@ -1,11 +1,12 @@
1
1
  import {
2
2
  optionalFeatureCodec
3
- } from "../chunk-JANNRGJC.js";
4
- import "../chunk-PJMG5XV3.js";
5
- import "../chunk-MQ747UCR.js";
3
+ } from "../chunk-G6PBI2BU.js";
4
+ import "../chunk-PQZ4LM4Z.js";
5
+ import "../chunk-DOXSFYLH.js";
6
6
  import "../chunk-WYGD2UGN.js";
7
7
  import "../chunk-ZJXSXVFP.js";
8
- import "../chunk-XTRDCSJB.js";
8
+ import "../chunk-5MXFW4O3.js";
9
+ import "../chunk-2JSQE3DD.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-PJMG5XV3.js";
4
- import "../chunk-MQ747UCR.js";
3
+ } from "../chunk-PQZ4LM4Z.js";
4
+ import "../chunk-DOXSFYLH.js";
5
5
  import "../chunk-WYGD2UGN.js";
6
6
  import "../chunk-ZJXSXVFP.js";
7
- import "../chunk-XTRDCSJB.js";
7
+ import "../chunk-5MXFW4O3.js";
8
+ import "../chunk-2JSQE3DD.js";
8
9
  import "../chunk-UA5KS2PL.js";
9
10
  export {
10
11
  parseOptionalFeature
@@ -1,4 +1,108 @@
1
1
  import { z } from "zod";
2
+ export declare const optionRowSchema: z.ZodObject<{
3
+ key: z.ZodString;
4
+ name: z.ZodString;
5
+ min_level: z.ZodNumber;
6
+ attunement: z.ZodOptional<z.ZodBoolean>;
7
+ creates: z.ZodObject<{
8
+ item: z.ZodOptional<z.ZodString>;
9
+ variant: z.ZodOptional<z.ZodObject<{
10
+ candidates: z.ZodArray<z.ZodString>;
11
+ }, z.core.$strict>>;
12
+ filter: z.ZodOptional<z.ZodObject<{
13
+ rarity: z.ZodArray<z.ZodString>;
14
+ types: z.ZodOptional<z.ZodArray<z.ZodString>>;
15
+ exclude_types: z.ZodOptional<z.ZodArray<z.ZodString>>;
16
+ cursed: z.ZodOptional<z.ZodLiteral<false>>;
17
+ }, z.core.$strict>>;
18
+ }, z.core.$strict>;
19
+ }, z.core.$strict>;
20
+ export declare const infuseBlockSchema: z.ZodObject<{
21
+ targets: z.ZodArray<z.ZodObject<{
22
+ kind: z.ZodEnum<{
23
+ weapon: "weapon";
24
+ armor: "armor";
25
+ shield: "shield";
26
+ gear: "gear";
27
+ }>;
28
+ category: z.ZodOptional<z.ZodArray<z.ZodString>>;
29
+ property: z.ZodOptional<z.ZodString>;
30
+ name_any: z.ZodOptional<z.ZodArray<z.ZodString>>;
31
+ }, z.core.$strict>>;
32
+ targets_label: z.ZodOptional<z.ZodString>;
33
+ new_object: z.ZodOptional<z.ZodString>;
34
+ rarity: z.ZodOptional<z.ZodString>;
35
+ attunement: z.ZodOptional<z.ZodObject<{
36
+ required: z.ZodLiteral<true>;
37
+ }, z.core.$strict>>;
38
+ choice: z.ZodOptional<z.ZodObject<{
39
+ kind: z.ZodLiteral<"damage-type">;
40
+ options: z.ZodOptional<z.ZodArray<z.ZodString>>;
41
+ }, z.core.$strict>>;
42
+ item: z.ZodOptional<z.ZodObject<{
43
+ bonuses: z.ZodOptional<z.ZodObject<{
44
+ ac: z.ZodOptional<z.ZodNumber>;
45
+ weapon_attack: z.ZodOptional<z.ZodNumber>;
46
+ weapon_damage: z.ZodOptional<z.ZodNumber>;
47
+ spell_attack: z.ZodOptional<z.ZodNumber>;
48
+ saving_throws: z.ZodOptional<z.ZodNumber>;
49
+ speed: z.ZodOptional<z.ZodObject<{
50
+ walk: z.ZodOptional<z.ZodNumber>;
51
+ fly: z.ZodOptional<z.ZodNumber>;
52
+ swim: z.ZodOptional<z.ZodNumber>;
53
+ climb: z.ZodOptional<z.ZodNumber>;
54
+ }, z.core.$strict>>;
55
+ }, z.core.$strict>>;
56
+ resist: z.ZodOptional<z.ZodArray<z.ZodString>>;
57
+ charges: z.ZodOptional<z.ZodObject<{
58
+ max: z.ZodNumber;
59
+ dice: z.ZodOptional<z.ZodString>;
60
+ recharge: z.ZodOptional<z.ZodString>;
61
+ recharge_amount: z.ZodOptional<z.ZodString>;
62
+ }, z.core.$strict>>;
63
+ action: z.ZodOptional<z.ZodEnum<{
64
+ action: "action";
65
+ "bonus-action": "bonus-action";
66
+ reaction: "reaction";
67
+ free: "free";
68
+ special: "special";
69
+ }>>;
70
+ range: z.ZodOptional<z.ZodString>;
71
+ }, z.core.$strict>>;
72
+ scales_at: z.ZodOptional<z.ZodArray<z.ZodObject<{
73
+ level: z.ZodNumber;
74
+ item: z.ZodObject<{
75
+ bonuses: z.ZodOptional<z.ZodObject<{
76
+ ac: z.ZodOptional<z.ZodNumber>;
77
+ weapon_attack: z.ZodOptional<z.ZodNumber>;
78
+ weapon_damage: z.ZodOptional<z.ZodNumber>;
79
+ spell_attack: z.ZodOptional<z.ZodNumber>;
80
+ saving_throws: z.ZodOptional<z.ZodNumber>;
81
+ speed: z.ZodOptional<z.ZodObject<{
82
+ walk: z.ZodOptional<z.ZodNumber>;
83
+ fly: z.ZodOptional<z.ZodNumber>;
84
+ swim: z.ZodOptional<z.ZodNumber>;
85
+ climb: z.ZodOptional<z.ZodNumber>;
86
+ }, z.core.$strict>>;
87
+ }, z.core.$strict>>;
88
+ resist: z.ZodOptional<z.ZodArray<z.ZodString>>;
89
+ charges: z.ZodOptional<z.ZodObject<{
90
+ max: z.ZodNumber;
91
+ dice: z.ZodOptional<z.ZodString>;
92
+ recharge: z.ZodOptional<z.ZodString>;
93
+ recharge_amount: z.ZodOptional<z.ZodString>;
94
+ }, z.core.$strict>>;
95
+ action: z.ZodOptional<z.ZodEnum<{
96
+ action: "action";
97
+ "bonus-action": "bonus-action";
98
+ reaction: "reaction";
99
+ free: "free";
100
+ special: "special";
101
+ }>>;
102
+ range: z.ZodOptional<z.ZodString>;
103
+ }, z.core.$strict>;
104
+ }, z.core.$strict>>>;
105
+ }, z.core.$strict>;
2
106
  export declare const optionalFeatureEntitySchema: z.ZodObject<{
3
107
  slug: z.ZodString;
4
108
  name: z.ZodString;
@@ -79,6 +183,31 @@ export declare const optionalFeatureEntitySchema: z.ZodObject<{
79
183
  minimum: z.ZodOptional<z.ZodNumber>;
80
184
  condition: z.ZodOptional<z.ZodString>;
81
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>;
82
211
  }, z.core.$strip>, z.ZodObject<{
83
212
  kind: z.ZodLiteral<"half-proficiency">;
84
213
  skills: z.ZodOptional<z.ZodArray<z.ZodString>>;
@@ -154,11 +283,24 @@ export declare const optionalFeatureEntitySchema: z.ZodObject<{
154
283
  kind: z.ZodLiteral<"damage-bonus">;
155
284
  damage_type: z.ZodString;
156
285
  amount: z.ZodString;
157
- applies_to: z.ZodOptional<z.ZodEnum<{
158
- weapon: "weapon";
286
+ applies_to: z.ZodOptional<z.ZodUnion<readonly [z.ZodEnum<{
159
287
  spell: "spell";
160
288
  all: "all";
161
- }>>;
289
+ }>, z.ZodEnum<{
290
+ weapon: "weapon";
291
+ melee: "melee";
292
+ ranged: "ranged";
293
+ unarmed: "unarmed";
294
+ finesse: "finesse";
295
+ thrown: "thrown";
296
+ }>, z.ZodArray<z.ZodEnum<{
297
+ weapon: "weapon";
298
+ melee: "melee";
299
+ ranged: "ranged";
300
+ unarmed: "unarmed";
301
+ finesse: "finesse";
302
+ thrown: "thrown";
303
+ }>>]>>;
162
304
  condition: z.ZodOptional<z.ZodString>;
163
305
  subject: z.ZodOptional<z.ZodString>;
164
306
  }, z.core.$strip>, z.ZodObject<{
@@ -463,6 +605,116 @@ export declare const optionalFeatureEntitySchema: z.ZodObject<{
463
605
  required: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodArray<z.ZodString>>>;
464
606
  }, z.core.$strip>>>;
465
607
  image: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]>>;
608
+ repeatable: z.ZodOptional<z.ZodLiteral<true>>;
609
+ item_choice: z.ZodOptional<z.ZodEnum<{
610
+ learn: "learn";
611
+ create: "create";
612
+ }>>;
613
+ options: z.ZodOptional<z.ZodArray<z.ZodObject<{
614
+ key: z.ZodString;
615
+ name: z.ZodString;
616
+ min_level: z.ZodNumber;
617
+ attunement: z.ZodOptional<z.ZodBoolean>;
618
+ creates: z.ZodObject<{
619
+ item: z.ZodOptional<z.ZodString>;
620
+ variant: z.ZodOptional<z.ZodObject<{
621
+ candidates: z.ZodArray<z.ZodString>;
622
+ }, z.core.$strict>>;
623
+ filter: z.ZodOptional<z.ZodObject<{
624
+ rarity: z.ZodArray<z.ZodString>;
625
+ types: z.ZodOptional<z.ZodArray<z.ZodString>>;
626
+ exclude_types: z.ZodOptional<z.ZodArray<z.ZodString>>;
627
+ cursed: z.ZodOptional<z.ZodLiteral<false>>;
628
+ }, z.core.$strict>>;
629
+ }, z.core.$strict>;
630
+ }, z.core.$strict>>>;
631
+ infuse: z.ZodOptional<z.ZodObject<{
632
+ targets: z.ZodArray<z.ZodObject<{
633
+ kind: z.ZodEnum<{
634
+ weapon: "weapon";
635
+ armor: "armor";
636
+ shield: "shield";
637
+ gear: "gear";
638
+ }>;
639
+ category: z.ZodOptional<z.ZodArray<z.ZodString>>;
640
+ property: z.ZodOptional<z.ZodString>;
641
+ name_any: z.ZodOptional<z.ZodArray<z.ZodString>>;
642
+ }, z.core.$strict>>;
643
+ targets_label: z.ZodOptional<z.ZodString>;
644
+ new_object: z.ZodOptional<z.ZodString>;
645
+ rarity: z.ZodOptional<z.ZodString>;
646
+ attunement: z.ZodOptional<z.ZodObject<{
647
+ required: z.ZodLiteral<true>;
648
+ }, z.core.$strict>>;
649
+ choice: z.ZodOptional<z.ZodObject<{
650
+ kind: z.ZodLiteral<"damage-type">;
651
+ options: z.ZodOptional<z.ZodArray<z.ZodString>>;
652
+ }, z.core.$strict>>;
653
+ item: z.ZodOptional<z.ZodObject<{
654
+ bonuses: z.ZodOptional<z.ZodObject<{
655
+ ac: z.ZodOptional<z.ZodNumber>;
656
+ weapon_attack: z.ZodOptional<z.ZodNumber>;
657
+ weapon_damage: z.ZodOptional<z.ZodNumber>;
658
+ spell_attack: z.ZodOptional<z.ZodNumber>;
659
+ saving_throws: z.ZodOptional<z.ZodNumber>;
660
+ speed: z.ZodOptional<z.ZodObject<{
661
+ walk: z.ZodOptional<z.ZodNumber>;
662
+ fly: z.ZodOptional<z.ZodNumber>;
663
+ swim: z.ZodOptional<z.ZodNumber>;
664
+ climb: z.ZodOptional<z.ZodNumber>;
665
+ }, z.core.$strict>>;
666
+ }, z.core.$strict>>;
667
+ resist: z.ZodOptional<z.ZodArray<z.ZodString>>;
668
+ charges: z.ZodOptional<z.ZodObject<{
669
+ max: z.ZodNumber;
670
+ dice: z.ZodOptional<z.ZodString>;
671
+ recharge: z.ZodOptional<z.ZodString>;
672
+ recharge_amount: z.ZodOptional<z.ZodString>;
673
+ }, z.core.$strict>>;
674
+ action: z.ZodOptional<z.ZodEnum<{
675
+ action: "action";
676
+ "bonus-action": "bonus-action";
677
+ reaction: "reaction";
678
+ free: "free";
679
+ special: "special";
680
+ }>>;
681
+ range: z.ZodOptional<z.ZodString>;
682
+ }, z.core.$strict>>;
683
+ scales_at: z.ZodOptional<z.ZodArray<z.ZodObject<{
684
+ level: z.ZodNumber;
685
+ item: z.ZodObject<{
686
+ bonuses: z.ZodOptional<z.ZodObject<{
687
+ ac: z.ZodOptional<z.ZodNumber>;
688
+ weapon_attack: z.ZodOptional<z.ZodNumber>;
689
+ weapon_damage: z.ZodOptional<z.ZodNumber>;
690
+ spell_attack: z.ZodOptional<z.ZodNumber>;
691
+ saving_throws: z.ZodOptional<z.ZodNumber>;
692
+ speed: z.ZodOptional<z.ZodObject<{
693
+ walk: z.ZodOptional<z.ZodNumber>;
694
+ fly: z.ZodOptional<z.ZodNumber>;
695
+ swim: z.ZodOptional<z.ZodNumber>;
696
+ climb: z.ZodOptional<z.ZodNumber>;
697
+ }, z.core.$strict>>;
698
+ }, z.core.$strict>>;
699
+ resist: z.ZodOptional<z.ZodArray<z.ZodString>>;
700
+ charges: z.ZodOptional<z.ZodObject<{
701
+ max: z.ZodNumber;
702
+ dice: z.ZodOptional<z.ZodString>;
703
+ recharge: z.ZodOptional<z.ZodString>;
704
+ recharge_amount: z.ZodOptional<z.ZodString>;
705
+ }, z.core.$strict>>;
706
+ action: z.ZodOptional<z.ZodEnum<{
707
+ action: "action";
708
+ "bonus-action": "bonus-action";
709
+ reaction: "reaction";
710
+ free: "free";
711
+ special: "special";
712
+ }>>;
713
+ range: z.ZodOptional<z.ZodString>;
714
+ }, z.core.$strict>;
715
+ }, z.core.$strict>>>;
716
+ }, z.core.$strict>>;
717
+ choices: z.ZodOptional<z.ZodArray<z.ZodType<import("../index.js").Choice, unknown, z.core.$ZodTypeInternals<import("../index.js").Choice, unknown>>>>;
466
718
  }, z.core.$strip>;
467
719
  export type OptionalFeatureSchemaInput = z.input<typeof optionalFeatureEntitySchema>;
468
720
  export type OptionalFeatureSchemaOutput = z.output<typeof optionalFeatureEntitySchema>;
@@ -1,10 +1,15 @@
1
1
  import {
2
+ infuseBlockSchema,
3
+ optionRowSchema,
2
4
  optionalFeatureEntitySchema
3
- } from "../chunk-MQ747UCR.js";
5
+ } from "../chunk-DOXSFYLH.js";
4
6
  import "../chunk-WYGD2UGN.js";
5
7
  import "../chunk-ZJXSXVFP.js";
6
- import "../chunk-XTRDCSJB.js";
8
+ import "../chunk-5MXFW4O3.js";
9
+ import "../chunk-2JSQE3DD.js";
7
10
  import "../chunk-UA5KS2PL.js";
8
11
  export {
12
+ infuseBlockSchema,
13
+ optionRowSchema,
9
14
  optionalFeatureEntitySchema
10
15
  };
@@ -5,11 +5,11 @@ import {
5
5
  prefixOf,
6
6
  raceIsUngated,
7
7
  resolveSpellByName
8
- } from "../chunk-3HX5VLWP.js";
8
+ } from "../chunk-VRV3NNTA.js";
9
9
  import "../chunk-PVCEA4HZ.js";
10
10
  import "../chunk-LVQLWRCU.js";
11
- import "../chunk-6X4KUDMU.js";
12
- import "../chunk-XY6X2APM.js";
11
+ import "../chunk-ZCTUYGNV.js";
12
+ import "../chunk-7Q2VPKCD.js";
13
13
  import "../chunk-ZDAEGJH4.js";
14
14
  import "../chunk-WELIKLZF.js";
15
15
  import "../chunk-UA5KS2PL.js";
@@ -0,0 +1,32 @@
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 } 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;
@@ -0,0 +1,23 @@
1
+ import {
2
+ amountBindingsFor,
3
+ ownerClassSlug,
4
+ spellAmountBindings,
5
+ spellRollBonus,
6
+ spellcastingFor
7
+ } from "../chunk-PXVNAY7T.js";
8
+ import "../chunk-KR6JF3BF.js";
9
+ import "../chunk-KSTV7J2U.js";
10
+ import "../chunk-DPUJDOKV.js";
11
+ import "../chunk-IUAAXXNO.js";
12
+ import "../chunk-LVQLWRCU.js";
13
+ import "../chunk-EVMUJYUD.js";
14
+ import "../chunk-VTTA2ALZ.js";
15
+ import "../chunk-PDJSUH24.js";
16
+ import "../chunk-WELIKLZF.js";
17
+ export {
18
+ amountBindingsFor,
19
+ ownerClassSlug,
20
+ spellAmountBindings,
21
+ spellRollBonus,
22
+ spellcastingFor
23
+ };
@@ -1,4 +1,5 @@
1
- import type { Choice } from "../types/choice.js";
1
+ import type { RegisteredEntity } from "@archivist-gg/core";
2
+ import type { Choice, Ability } from "../types/choice.js";
2
3
  /**
3
4
  * Normalizes the authored two-step "Ability Score Increase or Feat" decision
4
5
  * into the flat feat pick the product now uses.
@@ -16,3 +17,63 @@ import type { Choice } from "../types/choice.js";
16
17
  * Pure: never mutates its input, never synthesizes a new object.
17
18
  */
18
19
  export declare function flattenAsiOrFeat(choice: Choice): Choice;
20
+ /** The structural registry read `resolveLegacyAsiFeat` makes; the ledger's DecisionRegistry and core's EntityRegistry both
21
+ * satisfy it. */
22
+ type FeatSearch = {
23
+ search(query: string, entityType: string, limit: number): RegisteredEntity[];
24
+ };
25
+ /**
26
+ * The legacy ASI-branch allocation a class level SAVED, or null (H234 H4(2), spec §5.2 item 1): the SHEET's predicate,
27
+ * which `collectClassAsiBranch` (pc.recalc.ts) folds per level, and the base of the Builder's {@link convertibleLegacyAsi}.
28
+ *
29
+ * Non-null exactly when `block` is an object whose `feat` is NOT a string and whose `asi` is a non-array object with at
30
+ * least one numeric ability entry; returns a FRESH object of those entries. It ignores `asi-or-feat`, so an explicit
31
+ * `"feat"` branch with no feat picked still folds on the sheet, as it always has.
32
+ *
33
+ * A string `feat` beside an `asi` is R4-P4 Decision B's orphan (the level took the feat branch and the picker never cleared
34
+ * the abandoned branch's child keys): null. Do NOT loosen the test to `"feat" in block` or a `startsWith("feat")` prefix
35
+ * test: the first strands a non-string `feat` (a legacy hand edit) with no fold at all, the second skips every
36
+ * correctly-flattened block. The `typeof … === "string"` test MIRRORS `collectClassFeatAbilityPoints`' own gate, so the two
37
+ * can never both decline on this predicate (they can both decline when the feat slug resolves to no entity: an
38
+ * unresolvable pick grants nothing, by design).
39
+ */
40
+ export declare function legacyAsiBranch(block: unknown): Partial<Record<Ability, number>> | null;
41
+ /** The BUILDER's predicate (spec §5.2 item 2, Gate 1 M-9): {@link legacyAsiBranch} when `asi-or-feat` is absent or
42
+ * `"asi"`, else null. An explicit `"feat"` branch is a two-step pick in progress (a homebrew non-flattenable two-step keeps
43
+ * `asi-or-feat` as its own row's key), so the Builder neither aliases nor converts it and today's orphan rule applies.
44
+ * The ledger alias and {@link migrateLegacyAsiLevel} both use THIS predicate, so an aliased row never receives an inert
45
+ * write. The sheet's fold keeps the value-agnostic {@link legacyAsiBranch}. */
46
+ export declare function convertibleLegacyAsi(block: unknown): Partial<Record<Ability, number>> | null;
47
+ /** The ASI feat a class answers a legacy level with, deterministically (spec §5.3, Gate 0 M-7). Candidates: the registered
48
+ * feats whose bare slug is `ability-score-improvement` and which carry an `ability-points` choice with a string `id`.
49
+ * Rank: (1) the class entity's slug prefix (the pool collapse's identity rule), (2) the class entity's edition, (3)
50
+ * ascending slug in code-unit order. `childId` is that choice's own `id`, read from the data. Null with no candidate or no
51
+ * class entity. A pure function of (registry, class entity), so the ledger alias and the write path always agree. */
52
+ export declare function resolveLegacyAsiFeat(registry: FeatSearch, classEntity: {
53
+ slug: string;
54
+ edition?: string;
55
+ } | null | undefined): {
56
+ slug: string;
57
+ childId: string;
58
+ } | null;
59
+ /**
60
+ * The level block to store BEFORE a Builder edit applies, or null for "no conversion" (spec §5.2 item 4, §5.5). The plugin's
61
+ * `setChoice` calls it for EVERY write with the edit's key and value (Gate 1 M-8), so the `feat` vocabulary stays here.
62
+ *
63
+ * Null when the key is neither `feat` nor `feat:`-prefixed, when the block is not a convertible legacy level
64
+ * ({@link convertibleLegacyAsi}), or when the class has no ASI feat ({@link resolveLegacyAsiFeat}). Else a NEW object:
65
+ * every key of `block` except `asi-or-feat`, `asi` and `feat:<childId>`, plus `feat: <the ASI slug>`, plus
66
+ * `feat:<childId>: <the legacy allocation>` UNLESS the edit is a SWITCH: `key === "feat"` with any value other than the
67
+ * ASI slug, so a pick of another feat (Gate 1 I-1, ruled option (a)) and the chip removal (null / undefined; final
68
+ * review, Review 3 m6, ruled) both count. A switch writes no `feat:<childId>` at all, so the legacy points and any
69
+ * stale child are dropped and the level's pick stays open (the new feat's own, or the removed ASI's), which is what
70
+ * today's orphan rule does for a switch; a chip removal is therefore not reversible, and re-picking the ASI feat after
71
+ * it starts open. The stepper and a re-pick of the ASI feat keep the full conversion, where the legacy allocation
72
+ * overwrites a stale child. Other keys at the level are kept untouched; the input is never mutated. An over-allocated
73
+ * legacy level is copied verbatim and then clamped by the feat's own rules when the sheet folds it (Gate 1 M-10).
74
+ */
75
+ export declare function migrateLegacyAsiLevel(block: unknown, key: string, value: unknown, registry: FeatSearch, classEntity: {
76
+ slug: string;
77
+ edition?: string;
78
+ } | null | undefined): Record<string, unknown> | null;
79
+ export {};
@@ -0,0 +1,16 @@
1
+ import {
2
+ convertibleLegacyAsi,
3
+ flattenAsiOrFeat,
4
+ legacyAsiBranch,
5
+ migrateLegacyAsiLevel,
6
+ resolveLegacyAsiFeat
7
+ } from "../chunk-LBEXLN6I.js";
8
+ import "../chunk-ZCTUYGNV.js";
9
+ import "../chunk-WELIKLZF.js";
10
+ export {
11
+ convertibleLegacyAsi,
12
+ flattenAsiOrFeat,
13
+ legacyAsiBranch,
14
+ migrateLegacyAsiLevel,
15
+ resolveLegacyAsiFeat
16
+ };
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  computeConditionEffects
3
- } from "../chunk-R2ZV233X.js";
3
+ } from "../chunk-MYY2C5MB.js";
4
4
  export {
5
5
  computeConditionEffects
6
6
  };
@@ -0,0 +1,45 @@
1
+ import type { EntityRegistry } from "@archivist-gg/core";
2
+ import type { EquipmentEntry } from "./pc.types.js";
3
+ /** I2a · containment (spec 2026-09-24-inv-i2a-containment-data-design.md §4). The equipment array stays FLAT; an entry
4
+ * sits inside another through `in: <id>`. What counts as a container is the item's `container` data
5
+ * (isContainerItem), never a name list. */
6
+ export type ContainmentBreak = "equipped" | "missing" | "self" | "unresolved" | "not-container" | "cycle";
7
+ export interface ContainmentView {
8
+ parentOf: ReadonlyArray<number | null>;
9
+ childrenOf: ReadonlyArray<ReadonlyArray<number>>;
10
+ isContainer: ReadonlyArray<boolean>;
11
+ ownerOfId: ReadonlyMap<string, number>;
12
+ duplicateIds: ReadonlyArray<number>;
13
+ broken: ReadonlyArray<{
14
+ index: number;
15
+ reason: ContainmentBreak;
16
+ }>;
17
+ }
18
+ export declare function nonEmptyRef(v: unknown): string | null;
19
+ /** `container.holds_items` decides when present; otherwise a weight or item capacity, or weightless contents, make a
20
+ * container. A pack_contents-only block (a pack) and a volume-only block (a liquid holder) are not containers. */
21
+ export declare function isContainerItem(entity: unknown): boolean;
22
+ export declare function idOwners(equipment: readonly EquipmentEntry[]): {
23
+ ownerOfId: Map<string, number>;
24
+ duplicateIds: number[];
25
+ };
26
+ export declare function entityOfEntry(entry: EquipmentEntry, registry: EntityRegistry | null): unknown;
27
+ export declare function resolveContainment(equipment: readonly EquipmentEntry[], registry: EntityRegistry | null): ContainmentView;
28
+ export type MoveRefusal = "out-of-range" | "equipped" | "self" | "descendant" | "unresolved" | "not-container";
29
+ export type MoveCheck = {
30
+ ok: true;
31
+ } | {
32
+ ok: false;
33
+ reason: MoveRefusal;
34
+ };
35
+ export type MoveResult = {
36
+ ok: true;
37
+ changed: boolean;
38
+ } | {
39
+ ok: false;
40
+ reason: MoveRefusal;
41
+ };
42
+ export declare function ensureEntryId(equipment: EquipmentEntry[], index: number, registry: EntityRegistry | null): string;
43
+ export declare function canMoveInto(equipment: readonly EquipmentEntry[], index: number, target: number | null, registry: EntityRegistry | null): MoveCheck;
44
+ export declare function moveInto(equipment: EquipmentEntry[], index: number, target: number | null, registry: EntityRegistry | null): MoveResult;
45
+ export declare function repairContainment(equipment: EquipmentEntry[], registry: EntityRegistry | null): number;
@@ -0,0 +1,24 @@
1
+ import {
2
+ canMoveInto,
3
+ ensureEntryId,
4
+ entityOfEntry,
5
+ idOwners,
6
+ isContainerItem,
7
+ moveInto,
8
+ nonEmptyRef,
9
+ repairContainment,
10
+ resolveContainment
11
+ } from "../chunk-EJP263OP.js";
12
+ import "../chunk-CM5CWO4K.js";
13
+ import "../chunk-ZCTUYGNV.js";
14
+ export {
15
+ canMoveInto,
16
+ ensureEntryId,
17
+ entityOfEntry,
18
+ idOwners,
19
+ isContainerItem,
20
+ moveInto,
21
+ nonEmptyRef,
22
+ repairContainment,
23
+ resolveContainment
24
+ };
@@ -3,6 +3,7 @@ import type { ResolvedCharacter, ChoiceValue, FeatureSource } from "./pc.types.j
3
3
  import type { RegisteredEntity } from "@archivist-gg/core";
4
4
  import { type ProficiencyEntry } from "./pc.proficiency-grants.js";
5
5
  import { wikilinkTailSlug } from "../entities/slug.js";
6
+ import { type RepeatableMember } from "./pc.infusions.js";
6
7
  export interface DecisionRegistry {
7
8
  search(query: string, entityType: string, limit: number): RegisteredEntity[];
8
9
  getByTypeAndSlug(entityType: string, slug: string): RegisteredEntity | undefined;
@@ -27,6 +28,8 @@ export interface ResolvedOption {
27
28
  /**
28
29
  * Status contract: over-selection (n > need) reports `resolved` — the engine
29
30
  * never reports an error for too many picks; the picker UI owns cap enforcement.
31
+ * A pick that FOLDS into proficiencies never over-selects, though: {@link capAtCount}
32
+ * keeps its first `count` stored values, in the ledger and the fold alike.
30
33
  * Likewise for ability-points `max_per`: the engine only sums total points
31
34
  * allocated, so per-ability caps are picker-enforced, not reflected here.
32
35
  */
@@ -88,6 +91,9 @@ export interface DecisionItem {
88
91
  id: string;
89
92
  anchorLevel: number;
90
93
  };
94
+ /** ART-a (spec §5.1, R20): present ONLY on a synthesized pool item whose pool offers a repeatable member: one entry per
95
+ * such member, with its option rows resolved for the per-copy picker (visible candidates only, U-A). */
96
+ repeatable?: RepeatableMember[];
91
97
  /**
92
98
  * Populated only for the selected branch of a select-inline (the
93
99
  * revealed-on-selection rule): a child decision becomes visible once its
@@ -95,6 +101,9 @@ export interface DecisionItem {
95
101
  * status to "partial".
96
102
  */
97
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;
98
107
  }
99
108
  export interface DecisionLedger {
100
109
  classes: Array<{
@@ -119,9 +128,9 @@ export interface DecisionContext {
119
128
  /** `wikilinkTailSlug` MOVED to `entities/slug.ts` in R4-G5 T1, beside `bareEntitySlug`, so `pc.pools.ts` can
120
129
  * import it without importing this module (this module imports `pc.pools` for `strandedPicks`; the old
121
130
  * direction would be a cycle). The re-export is KEPT because `@archivist-gg/dnd5e/pc/pc.decision-engine` is
122
- * a published subpath with three plugin importers OF THIS SYMBOL (`components/passive/background-block.ts`,
123
- * `components/builder/background-step.ts`, `components/builder/class-step.ts`, all under
124
- * `packages/obsidian/src/modules/pc/`) plus this repo's `pc.resolver.ts` and
131
+ * a published subpath with a plugin importer OF THIS SYMBOL (`components/builder/class-step.ts`, under
132
+ * `packages/obsidian/src/modules/pc/`; the two background surfaces moved to the plugin's `refLabel`, which reads
133
+ * `entities/slug` directly, on 2026-09-25) plus this repo's `pc.resolver.ts` and
125
134
  * `tests/wikilink-tail-slug.test.ts`: a public
126
135
  * surface, not a migration shim, so the standing "retire every shim" rule does not reach it (spec §17 names the
127
136
  * re-export explicitly). */
@@ -129,6 +138,18 @@ export { wikilinkTailSlug };
129
138
  declare function matchesFilter(e: RegisteredEntity, where: EntityFilter, ownerBare: string): boolean;
130
139
  /** Test-only export of {@link matchesFilter} (Task B2). */
131
140
  export declare const __matchesFilterForTest: typeof matchesFilter;
141
+ /** Map a starting-equipment category grant to a nested select-entity child (vocabulary on
142
+ * {@link parseEquipmentCategory}). Weapons filter by weapon_category; armor by armor_category; `shield` is an armor
143
+ * entity in the shield class; a tool category is a MUNDANE item of the category's `type` (magic instruments carry
144
+ * `type: instrument` too).
145
+ *
146
+ * An UNKNOWN category is never guessed. It used to fall through to `weapon_category: "simple"`, which is how the
147
+ * PHB 2024 Bard's "Choose a musical instrument" listed Club, Dagger and Dart. It now yields `from: []`, the
148
+ * engine's existing zero-option shape (an authored empty pool: the row stays open and the strip prints its
149
+ * "No options available" line), and warns ONCE per distinct category. */
150
+ declare function categoryToEntitySelect(category: string, id: string): Choice;
151
+ /** Test-only export of {@link categoryToEntitySelect}. */
152
+ export declare const __categoryToEntitySelectForTest: typeof categoryToEntitySelect;
132
153
  /** Walk every decision definition + persisted selection and collect chosen
133
154
  * proficiencies. Pure; called by recalc.
134
155
  *