@archivist-gg/dnd5e 0.3.1 → 0.3.5

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 (259) hide show
  1. package/LICENSES/SRD.md +25 -6
  2. package/dist/armor/armor.codec.js +4 -3
  3. package/dist/armor/armor.parser.js +3 -2
  4. package/dist/armor/armor.schema.d.ts +4 -0
  5. package/dist/armor/armor.schema.js +2 -1
  6. package/dist/armor/armor.types.d.ts +8 -0
  7. package/dist/background/background.codec.js +7 -6
  8. package/dist/background/background.parser.js +6 -5
  9. package/dist/background/background.schema.d.ts +26 -0
  10. package/dist/background/background.schema.js +5 -4
  11. package/dist/background/background.types.d.ts +22 -0
  12. package/dist/{chunk-4TIJKN6O.js → chunk-23LZLBJK.js} +1 -1
  13. package/dist/{chunk-AFKTJXRA.js → chunk-2DFENQIJ.js} +18 -0
  14. package/dist/chunk-2FRUSVZS.js +489 -0
  15. package/dist/chunk-2VDTW7QO.js +1580 -0
  16. package/dist/{chunk-ZZGEVJKX.js → chunk-3JOTQW7A.js} +1 -1
  17. package/dist/{chunk-5ZBE4CWV.js → chunk-3PZHBLFG.js} +1 -1
  18. package/dist/chunk-4U55VNC7.js +22 -0
  19. package/dist/{chunk-4JHOHWBI.js → chunk-4XTNPNQB.js} +1 -1
  20. package/dist/{chunk-HCP3GMHS.js → chunk-5N2GW72F.js} +15 -2
  21. package/dist/{chunk-42Y5IJKT.js → chunk-5RKLL2AD.js} +5 -1
  22. package/dist/{chunk-SE7AZDR3.js → chunk-63XQXPZL.js} +29 -3
  23. package/dist/{chunk-4F6AIZ36.js → chunk-6BFWZW6T.js} +1 -1
  24. package/dist/{chunk-GJOI2GHP.js → chunk-6GNXYAYP.js} +1 -1
  25. package/dist/{chunk-66XXW2Z2.js → chunk-6PXTNCBP.js} +2 -2
  26. package/dist/chunk-6X2NV665.js +33 -0
  27. package/dist/{chunk-LV4SNWZQ.js → chunk-6X4KUDMU.js} +8 -1
  28. package/dist/{chunk-ZMR77DDL.js → chunk-AW3EHF3L.js} +1 -1
  29. package/dist/{chunk-TLYDBT5F.js → chunk-CGRLQ34U.js} +64 -7
  30. package/dist/chunk-CJYCVNW2.js +7 -0
  31. package/dist/{chunk-XLSVNUTK.js → chunk-CV5XDJKU.js} +1 -1
  32. package/dist/{chunk-RAWJTA45.js → chunk-DEEHHLAP.js} +1 -1
  33. package/dist/{chunk-6IRYTM5V.js → chunk-DPUJDOKV.js} +119 -28
  34. package/dist/{chunk-GE4TLPWM.js → chunk-EHDATXP7.js} +1 -1
  35. package/dist/chunk-EVMUJYUD.js +195 -0
  36. package/dist/{chunk-K6Q5OUGK.js → chunk-GFZ7PITJ.js} +86 -10
  37. package/dist/{chunk-6NK2MUD3.js → chunk-HZA7OE7N.js} +9 -2
  38. package/dist/{chunk-TN6ZLTNU.js → chunk-I2NDWFDD.js} +51 -4
  39. package/dist/{chunk-3DZ74AKK.js → chunk-IN4M4X7P.js} +8 -2
  40. package/dist/chunk-IUAAXXNO.js +58 -0
  41. package/dist/{chunk-NXSWH3AE.js → chunk-IWRVOCT5.js} +1 -1
  42. package/dist/{chunk-XJNECUPT.js → chunk-JC5UNIVM.js} +19 -0
  43. package/dist/{chunk-24GFQU7T.js → chunk-JSZ4H6AQ.js} +1 -1
  44. package/dist/{chunk-XTIQWSFM.js → chunk-KADJZGZY.js} +1 -1
  45. package/dist/{chunk-L7E2UT5A.js → chunk-KK33PIDN.js} +5 -1
  46. package/dist/chunk-KPEJMNRD.js +302 -0
  47. package/dist/chunk-KU3YLF6D.js +106 -0
  48. package/dist/{chunk-5INR4NSL.js → chunk-LDDCNPHD.js} +1 -1
  49. package/dist/chunk-LVQLWRCU.js +15 -0
  50. package/dist/chunk-MI7P3NX3.js +161 -0
  51. package/dist/{chunk-PHQRGDRQ.js → chunk-N3A5ICBO.js} +5 -1
  52. package/dist/chunk-O4SRD3J5.js +165 -0
  53. package/dist/chunk-OAXWSVJB.js +81 -0
  54. package/dist/chunk-OZP6JFGT.js +162 -0
  55. package/dist/{chunk-NAEPSZAM.js → chunk-PDJSUH24.js} +24 -2
  56. package/dist/chunk-PP2UHLBA.js +50 -0
  57. package/dist/chunk-PVCEA4HZ.js +6 -0
  58. package/dist/{chunk-RSDRMH54.js → chunk-RF4TYCA2.js} +1 -1
  59. package/dist/chunk-RLGQ5PZZ.js +16 -0
  60. package/dist/chunk-RVXC6ZHY.js +89 -0
  61. package/dist/chunk-S7REMWW4.js +21 -0
  62. package/dist/{chunk-7VJ6BOA5.js → chunk-SMLXZUBH.js} +9 -1
  63. package/dist/chunk-TOM66P2P.js +38 -0
  64. package/dist/chunk-UA5KS2PL.js +26 -0
  65. package/dist/{chunk-N6N74K6X.js → chunk-UBBKSYBY.js} +1 -1
  66. package/dist/{chunk-353WXS6S.js → chunk-UIRMA5KM.js} +1 -1
  67. package/dist/{chunk-BIK4DFWK.js → chunk-ULCQ73LA.js} +1 -1
  68. package/dist/{chunk-2BWAID3Y.js → chunk-UMWIPLLM.js} +29 -3
  69. package/dist/chunk-UQ3ZFCWD.js +178 -0
  70. package/dist/chunk-UXPGW4TI.js +101 -0
  71. package/dist/chunk-V2MJE6NC.js +133 -0
  72. package/dist/{chunk-D3CLOBE3.js → chunk-V373TRJE.js} +48 -10
  73. package/dist/chunk-VQAXTIBW.js +100 -0
  74. package/dist/chunk-W74BCA7V.js +159 -0
  75. package/dist/{chunk-WP2CX2JO.js → chunk-WELIKLZF.js} +22 -1
  76. package/dist/{chunk-MDEJHMKK.js → chunk-WHVLNFTG.js} +26 -5
  77. package/dist/{chunk-GZ46OVGZ.js → chunk-WSVMLNTO.js} +1 -1
  78. package/dist/{chunk-4LZJXJJS.js → chunk-WXWPK3LI.js} +6 -2
  79. package/dist/chunk-X3D6LXUU.js +185 -0
  80. package/dist/chunk-XJ2F2WO6.js +8 -0
  81. package/dist/{chunk-73HOFQQ5.js → chunk-Y4AGLCY6.js} +1 -1
  82. package/dist/chunk-YBLDE5CG.js +42 -0
  83. package/dist/{chunk-JEYQU3JT.js → chunk-YHYTW5QA.js} +2 -18
  84. package/dist/{chunk-PZOWBI3B.js → chunk-YLL2QXY2.js} +7 -2
  85. package/dist/class/class.codec.js +12 -9
  86. package/dist/class/class.parser.js +11 -8
  87. package/dist/class/class.schema.d.ts +55 -3
  88. package/dist/class/class.schema.js +9 -7
  89. package/dist/class/class.types.d.ts +48 -3
  90. package/dist/condition/condition.codec.d.ts +9 -0
  91. package/dist/condition/condition.entity-type.d.ts +2 -0
  92. package/dist/condition/condition.parser.d.ts +13 -0
  93. package/dist/condition/condition.parser.js +7 -0
  94. package/dist/condition/condition.schema.d.ts +29 -0
  95. package/dist/condition/condition.types.d.ts +15 -0
  96. package/dist/condition/condition.types.js +0 -0
  97. package/dist/dnd/constants.d.ts +22 -0
  98. package/dist/dnd/constants.js +9 -3
  99. package/dist/dnd/formula-tags.js +2 -2
  100. package/dist/dnd/math.d.ts +26 -0
  101. package/dist/dnd/math.js +12 -2
  102. package/dist/dnd/prose-tags.js +1 -1
  103. package/dist/dnd/resource-formula.d.ts +36 -10
  104. package/dist/dnd/resource-formula.js +10 -155
  105. package/dist/dnd/srd-tag-converter.js +3 -3
  106. package/dist/dnd/tag-grammar.js +1 -1
  107. package/dist/dnd/warn-once.d.ts +2 -0
  108. package/dist/dnd/warn-once.js +8 -0
  109. package/dist/entities/base-item-resolver.js +2 -2
  110. package/dist/entities/slug.d.ts +13 -0
  111. package/dist/entities/slug.js +5 -3
  112. package/dist/entities/wikilink-display.d.ts +3 -0
  113. package/dist/entities/wikilink-display.js +10 -0
  114. package/dist/feat/feat.category-codes.d.ts +32 -0
  115. package/dist/feat/feat.category-codes.js +14 -0
  116. package/dist/feat/feat.codec.js +7 -5
  117. package/dist/feat/feat.parser.js +6 -4
  118. package/dist/feat/feat.schema.d.ts +239 -0
  119. package/dist/feat/feat.schema.js +5 -3
  120. package/dist/feat/feat.types.d.ts +37 -1
  121. package/dist/index.js +2033 -6907
  122. package/dist/item/item.codec.js +4 -3
  123. package/dist/item/item.enrichment.js +4 -4
  124. package/dist/item/item.parser.js +3 -2
  125. package/dist/item/item.schema.d.ts +69 -3
  126. package/dist/item/item.schema.js +2 -1
  127. package/dist/item/item.types.d.ts +69 -3
  128. package/dist/monster/monster.codec.d.ts +7 -6
  129. package/dist/monster/monster.enrichment.js +4 -4
  130. package/dist/monster/monster.format.d.ts +135 -0
  131. package/dist/monster/monster.format.js +78 -0
  132. package/dist/monster/monster.parser.d.ts +6 -1
  133. package/dist/monster/monster.parser.js +10 -1
  134. package/dist/monster/monster.schema.d.ts +369 -0
  135. package/dist/monster/monster.schema.js +34 -0
  136. package/dist/monster/monster.types.d.ts +200 -14
  137. package/dist/optional-feature/optional-feature.codec.js +6 -5
  138. package/dist/optional-feature/optional-feature.parser.js +5 -4
  139. package/dist/optional-feature/optional-feature.schema.d.ts +185 -0
  140. package/dist/optional-feature/optional-feature.schema.js +4 -3
  141. package/dist/pack.d.ts +1 -1
  142. package/dist/pc/conditions.constants.d.ts +0 -1
  143. package/dist/pc/conditions.constants.js +1 -3
  144. package/dist/pc/decision-recognizer.js +1 -1
  145. package/dist/pc/pc.additional-spells.d.ts +47 -0
  146. package/dist/pc/pc.additional-spells.js +23 -0
  147. package/dist/pc/pc.asi-flatten.d.ts +18 -0
  148. package/dist/pc/pc.decision-engine.d.ts +105 -17
  149. package/dist/pc/pc.decision-engine.js +28 -12
  150. package/dist/pc/pc.defense-normalize.d.ts +11 -0
  151. package/dist/pc/pc.defense-normalize.js +6 -0
  152. package/dist/pc/pc.equipment.d.ts +31 -2
  153. package/dist/pc/pc.equipment.js +12 -8
  154. package/dist/pc/pc.feature-effects.d.ts +234 -11
  155. package/dist/pc/pc.feature-effects.js +21 -5
  156. package/dist/pc/pc.parser.js +2 -2
  157. package/dist/pc/pc.pools.d.ts +11 -3
  158. package/dist/pc/pc.pools.js +9 -13
  159. package/dist/pc/pc.proficiencies.d.ts +54 -29
  160. package/dist/pc/pc.proficiencies.js +74 -95
  161. package/dist/pc/pc.proficiency-grants.d.ts +58 -0
  162. package/dist/pc/pc.proficiency-normalize.d.ts +24 -0
  163. package/dist/pc/pc.proficiency-normalize.js +12 -0
  164. package/dist/pc/pc.proficiency-query.d.ts +13 -0
  165. package/dist/pc/pc.proficiency-query.js +1 -1
  166. package/dist/pc/pc.recalc.d.ts +69 -14
  167. package/dist/pc/pc.recalc.js +261 -122
  168. package/dist/pc/pc.resolver.d.ts +34 -8
  169. package/dist/pc/pc.resolver.js +27 -12
  170. package/dist/pc/pc.resource-seed.d.ts +3 -2
  171. package/dist/pc/pc.resource-seed.js +19 -17
  172. package/dist/pc/pc.resources.d.ts +87 -0
  173. package/dist/pc/pc.resources.js +21 -0
  174. package/dist/pc/pc.rest.d.ts +10 -1
  175. package/dist/pc/pc.rest.js +66 -12
  176. package/dist/pc/pc.schema.d.ts +139 -3
  177. package/dist/pc/pc.schema.js +4 -2
  178. package/dist/pc/pc.slotting.js +3 -3
  179. package/dist/pc/pc.spellcasting.d.ts +75 -6
  180. package/dist/pc/pc.spellcasting.js +16 -6
  181. package/dist/pc/pc.table-column.d.ts +23 -0
  182. package/dist/pc/pc.table-column.js +13 -3
  183. package/dist/pc/pc.types.d.ts +251 -12
  184. package/dist/pc/pool-layout.d.ts +47 -0
  185. package/dist/pc/pool-layout.js +16 -0
  186. package/dist/pc/roll-scope.d.ts +2 -0
  187. package/dist/pc/roll-scope.js +8 -0
  188. package/dist/pc/roll-tag-labels.d.ts +40 -0
  189. package/dist/pc/roll-tag-labels.js +17 -0
  190. package/dist/pc/spell-source.d.ts +21 -0
  191. package/dist/pc/spell-source.js +13 -0
  192. package/dist/race/race.codec.js +9 -7
  193. package/dist/race/race.parser.js +8 -6
  194. package/dist/race/race.schema.d.ts +51 -1
  195. package/dist/race/race.schema.js +8 -5
  196. package/dist/race/race.structural.d.ts +7 -0
  197. package/dist/race/race.structural.js +6 -0
  198. package/dist/race/race.types.d.ts +20 -0
  199. package/dist/schemas/attack-schema.d.ts +5 -0
  200. package/dist/schemas/caster-type-schema.d.ts +14 -0
  201. package/dist/schemas/caster-type-schema.js +6 -0
  202. package/dist/schemas/choice-schema.js +2 -2
  203. package/dist/schemas/entity-extras-schema.d.ts +53 -0
  204. package/dist/schemas/entity-extras-schema.js +10 -0
  205. package/dist/schemas/equipment-grant-schema.d.ts +2 -0
  206. package/dist/schemas/equipment-grant-schema.js +1 -1
  207. package/dist/schemas/feature-alias.d.ts +34 -0
  208. package/dist/schemas/feature-effect-schema.d.ts +133 -0
  209. package/dist/schemas/feature-effect-schema.js +1 -1
  210. package/dist/schemas/feature-schema.d.ts +8 -0
  211. package/dist/schemas/feature-schema.js +6 -4
  212. package/dist/schemas/resource-schema.d.ts +43 -0
  213. package/dist/schemas/resource-schema.js +1 -1
  214. package/dist/schemas/selection-pool-schema.d.ts +2 -0
  215. package/dist/schemas/selection-pool-schema.js +1 -1
  216. package/dist/spell/spell.access.js +23 -3
  217. package/dist/spell/spell.codec.js +4 -3
  218. package/dist/spell/spell.enrichment.js +4 -4
  219. package/dist/spell/spell.parser.d.ts +30 -0
  220. package/dist/spell/spell.parser.js +9 -2
  221. package/dist/spell/spell.scaling.d.ts +27 -6
  222. package/dist/spell/spell.scaling.js +25 -6
  223. package/dist/spell/spell.schema.d.ts +44 -2
  224. package/dist/spell/spell.schema.js +2 -1
  225. package/dist/spell/spell.types.d.ts +14 -0
  226. package/dist/subclass/subclass.codec.d.ts +1 -1
  227. package/dist/subclass/subclass.codec.js +11 -8
  228. package/dist/subclass/subclass.parser.js +10 -7
  229. package/dist/subclass/subclass.schema.d.ts +54 -7
  230. package/dist/subclass/subclass.schema.js +8 -6
  231. package/dist/subclass/subclass.types.d.ts +20 -2
  232. package/dist/types/choice.d.ts +53 -2
  233. package/dist/types/choice.js +13 -1
  234. package/dist/types/equipment-grant.d.ts +8 -1
  235. package/dist/types/feature-effect.d.ts +85 -23
  236. package/dist/types/feature.d.ts +70 -1
  237. package/dist/types/optional-feature.types.d.ts +28 -0
  238. package/dist/types/resource.d.ts +21 -1
  239. package/dist/types/selection-pool.d.ts +17 -2
  240. package/dist/weapon/weapon.classify.js +2 -2
  241. package/dist/weapon/weapon.codec.js +4 -3
  242. package/dist/weapon/weapon.parser.js +3 -2
  243. package/dist/weapon/weapon.schema.d.ts +4 -0
  244. package/dist/weapon/weapon.schema.js +2 -1
  245. package/dist/weapon/weapon.types.d.ts +8 -0
  246. package/package.json +2 -2
  247. package/dist/chunk-5XUXXAQJ.js +0 -30
  248. package/dist/chunk-7P65Q426.js +0 -158
  249. package/dist/chunk-7TEK5KK7.js +0 -49
  250. package/dist/chunk-AIRFC5NQ.js +0 -143
  251. package/dist/chunk-CZPMTQOY.js +0 -68
  252. package/dist/chunk-N2JE7BWL.js +0 -81
  253. package/dist/chunk-NXR3BD2V.js +0 -90
  254. package/dist/chunk-O5EYMKFH.js +0 -6
  255. package/dist/chunk-Q5K6LWBZ.js +0 -45
  256. package/dist/chunk-TNUFPIXI.js +0 -1110
  257. package/dist/chunk-TZK36BU7.js +0 -38
  258. package/dist/chunk-W7HWMMBF.js +0 -46
  259. package/dist/chunk-Y4I74YEG.js +0 -33
@@ -12,6 +12,16 @@ export declare const optionalFeatureEntitySchema: z.ZodObject<{
12
12
  prerequisites: z.ZodArray<z.ZodDiscriminatedUnion<[z.ZodObject<{
13
13
  kind: z.ZodLiteral<"level">;
14
14
  min: z.ZodNumber;
15
+ class: z.ZodOptional<z.ZodObject<{
16
+ name: z.ZodString;
17
+ source: z.ZodOptional<z.ZodString>;
18
+ visible_stats: z.ZodOptional<z.ZodBoolean>;
19
+ }, z.core.$strip>>;
20
+ subclass: z.ZodOptional<z.ZodObject<{
21
+ name: z.ZodString;
22
+ source: z.ZodOptional<z.ZodString>;
23
+ visible_stats: z.ZodOptional<z.ZodBoolean>;
24
+ }, z.core.$strip>>;
15
25
  }, z.core.$strip>, z.ZodObject<{
16
26
  kind: z.ZodLiteral<"spell-known">;
17
27
  spell: z.ZodString;
@@ -40,21 +50,36 @@ export declare const optionalFeatureEntitySchema: z.ZodObject<{
40
50
  }, z.core.$strip>, z.ZodObject<{
41
51
  kind: z.ZodLiteral<"other">;
42
52
  detail: z.ZodString;
53
+ }, z.core.$strip>, z.ZodObject<{
54
+ kind: z.ZodLiteral<"optionalfeature">;
55
+ optionalfeature: z.ZodString;
56
+ }, z.core.$strip>, z.ZodObject<{
57
+ kind: z.ZodLiteral<"spell-choose">;
58
+ choose: z.ZodString;
59
+ entry: z.ZodOptional<z.ZodString>;
60
+ entry_summary: z.ZodOptional<z.ZodString>;
43
61
  }, z.core.$strip>], "kind">>;
44
62
  available_to: z.ZodArray<z.ZodString>;
45
63
  effects: z.ZodArray<z.ZodDiscriminatedUnion<[z.ZodObject<{
46
64
  kind: z.ZodLiteral<"initiative-bonus">;
47
65
  value: z.ZodNumber;
66
+ condition: z.ZodOptional<z.ZodString>;
67
+ subject: z.ZodOptional<z.ZodString>;
48
68
  }, z.core.$strip>, z.ZodObject<{
49
69
  kind: z.ZodLiteral<"immune-condition">;
50
70
  condition: z.ZodString;
51
71
  while: z.ZodOptional<z.ZodString>;
72
+ subject: z.ZodOptional<z.ZodString>;
52
73
  }, z.core.$strip>, z.ZodObject<{
53
74
  kind: z.ZodLiteral<"resistance">;
54
75
  damage_type: z.ZodString;
76
+ condition: z.ZodOptional<z.ZodString>;
77
+ subject: z.ZodOptional<z.ZodString>;
55
78
  }, z.core.$strip>, z.ZodObject<{
56
79
  kind: z.ZodLiteral<"hp-per-level-bonus">;
57
80
  value: z.ZodNumber;
81
+ condition: z.ZodOptional<z.ZodString>;
82
+ subject: z.ZodOptional<z.ZodString>;
58
83
  }, z.core.$strip>, z.ZodObject<{
59
84
  kind: z.ZodLiteral<"speed-bonus">;
60
85
  mode: z.ZodEnum<{
@@ -66,6 +91,21 @@ export declare const optionalFeatureEntitySchema: z.ZodObject<{
66
91
  }>;
67
92
  value: z.ZodNumber;
68
93
  set: z.ZodOptional<z.ZodBoolean>;
94
+ scales_at: z.ZodOptional<z.ZodArray<z.ZodObject<{
95
+ level: z.ZodNumber;
96
+ value: z.ZodNumber;
97
+ }, z.core.$strip>>>;
98
+ condition: z.ZodOptional<z.ZodString>;
99
+ subject: z.ZodOptional<z.ZodString>;
100
+ }, z.core.$strip>, z.ZodObject<{
101
+ kind: z.ZodLiteral<"attunement-limit">;
102
+ value: z.ZodNumber;
103
+ scales_at: z.ZodOptional<z.ZodArray<z.ZodObject<{
104
+ level: z.ZodNumber;
105
+ value: z.ZodNumber;
106
+ }, z.core.$strip>>>;
107
+ condition: z.ZodOptional<z.ZodString>;
108
+ subject: z.ZodOptional<z.ZodString>;
69
109
  }, z.core.$strip>, z.ZodObject<{
70
110
  kind: z.ZodLiteral<"sense">;
71
111
  type: z.ZodEnum<{
@@ -75,6 +115,8 @@ export declare const optionalFeatureEntitySchema: z.ZodObject<{
75
115
  truesight: "truesight";
76
116
  }>;
77
117
  range: z.ZodNumber;
118
+ condition: z.ZodOptional<z.ZodString>;
119
+ subject: z.ZodOptional<z.ZodString>;
78
120
  }, z.core.$strip>, z.ZodObject<{
79
121
  kind: z.ZodLiteral<"apply-condition">;
80
122
  condition: z.ZodString;
@@ -84,6 +126,7 @@ export declare const optionalFeatureEntitySchema: z.ZodObject<{
84
126
  ability: z.ZodString;
85
127
  timing: z.ZodString;
86
128
  }, z.core.$strip>>;
129
+ subject: z.ZodOptional<z.ZodString>;
87
130
  }, z.core.$strip>, z.ZodObject<{
88
131
  kind: z.ZodLiteral<"damage-bonus">;
89
132
  damage_type: z.ZodString;
@@ -94,6 +137,7 @@ export declare const optionalFeatureEntitySchema: z.ZodObject<{
94
137
  all: "all";
95
138
  }>>;
96
139
  condition: z.ZodOptional<z.ZodString>;
140
+ subject: z.ZodOptional<z.ZodString>;
97
141
  }, z.core.$strip>, z.ZodObject<{
98
142
  kind: z.ZodLiteral<"proficiency">;
99
143
  proficiency_type: z.ZodEnum<{
@@ -105,10 +149,15 @@ export declare const optionalFeatureEntitySchema: z.ZodObject<{
105
149
  armor: "armor";
106
150
  }>;
107
151
  value: z.ZodString;
152
+ expertise: z.ZodOptional<z.ZodBoolean>;
153
+ condition: z.ZodOptional<z.ZodString>;
154
+ subject: z.ZodOptional<z.ZodString>;
108
155
  }, z.core.$strip>, z.ZodObject<{
109
156
  kind: z.ZodLiteral<"ac-bonus">;
110
157
  value: z.ZodNumber;
111
158
  requires_armor: z.ZodOptional<z.ZodBoolean>;
159
+ condition: z.ZodOptional<z.ZodString>;
160
+ subject: z.ZodOptional<z.ZodString>;
112
161
  }, z.core.$strip>, z.ZodObject<{
113
162
  kind: z.ZodLiteral<"unarmored-ac">;
114
163
  abilities: z.ZodArray<z.ZodEnum<{
@@ -121,6 +170,23 @@ export declare const optionalFeatureEntitySchema: z.ZodObject<{
121
170
  }>>;
122
171
  base: z.ZodOptional<z.ZodNumber>;
123
172
  allow_shield: z.ZodOptional<z.ZodBoolean>;
173
+ condition: z.ZodOptional<z.ZodString>;
174
+ subject: z.ZodOptional<z.ZodString>;
175
+ }, z.core.$strip>, z.ZodObject<{
176
+ kind: z.ZodLiteral<"unarmed-strike">;
177
+ dice: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodObject<{
178
+ column: z.ZodString;
179
+ }, z.core.$strip>]>>;
180
+ abilities: z.ZodOptional<z.ZodArray<z.ZodEnum<{
181
+ str: "str";
182
+ dex: "dex";
183
+ con: "con";
184
+ int: "int";
185
+ wis: "wis";
186
+ cha: "cha";
187
+ }>>>;
188
+ condition: z.ZodOptional<z.ZodString>;
189
+ subject: z.ZodOptional<z.ZodString>;
124
190
  }, z.core.$strip>, z.ZodObject<{
125
191
  kind: z.ZodLiteral<"weapon-ability">;
126
192
  ability: z.ZodUnion<readonly [z.ZodEnum<{
@@ -132,22 +198,34 @@ export declare const optionalFeatureEntitySchema: z.ZodObject<{
132
198
  cha: "cha";
133
199
  }>, z.ZodLiteral<"spellcasting">]>;
134
200
  weapons: z.ZodOptional<z.ZodUnion<readonly [z.ZodLiteral<"chosen">, z.ZodString, z.ZodArray<z.ZodString>]>>;
201
+ condition: z.ZodOptional<z.ZodString>;
202
+ subject: z.ZodOptional<z.ZodString>;
135
203
  }, z.core.$strip>, z.ZodObject<{
136
204
  kind: z.ZodLiteral<"roll-modifier">;
137
205
  mode: z.ZodEnum<{
138
206
  advantage: "advantage";
139
207
  disadvantage: "disadvantage";
208
+ reroll: "reroll";
209
+ "add-d4": "add-d4";
140
210
  }>;
141
211
  roll: z.ZodEnum<{
142
212
  "saving-throw": "saving-throw";
143
213
  "ability-check": "ability-check";
144
214
  attack: "attack";
215
+ any: "any";
145
216
  }>;
146
217
  scope: z.ZodOptional<z.ZodString>;
147
218
  condition: z.ZodOptional<z.ZodString>;
219
+ subject: z.ZodOptional<z.ZodString>;
148
220
  }, z.core.$strip>, z.ZodObject<{
149
221
  kind: z.ZodLiteral<"extra-attack">;
150
222
  count: z.ZodNumber;
223
+ scales_at: z.ZodOptional<z.ZodArray<z.ZodObject<{
224
+ level: z.ZodNumber;
225
+ count: z.ZodNumber;
226
+ }, z.core.$strip>>>;
227
+ condition: z.ZodOptional<z.ZodString>;
228
+ subject: z.ZodOptional<z.ZodString>;
151
229
  }, z.core.$strip>, z.ZodObject<{
152
230
  kind: z.ZodLiteral<"crit-range">;
153
231
  min_roll: z.ZodNumber;
@@ -157,6 +235,7 @@ export declare const optionalFeatureEntitySchema: z.ZodObject<{
157
235
  all: "all";
158
236
  }>>;
159
237
  condition: z.ZodOptional<z.ZodString>;
238
+ subject: z.ZodOptional<z.ZodString>;
160
239
  }, z.core.$strip>, z.ZodObject<{
161
240
  kind: z.ZodLiteral<"reroll-damage">;
162
241
  max_reroll: z.ZodNumber;
@@ -166,11 +245,83 @@ export declare const optionalFeatureEntitySchema: z.ZodObject<{
166
245
  all: "all";
167
246
  }>>;
168
247
  once_per_die: z.ZodOptional<z.ZodBoolean>;
248
+ condition: z.ZodOptional<z.ZodString>;
249
+ subject: z.ZodOptional<z.ZodString>;
169
250
  }, z.core.$strip>, z.ZodObject<{
170
251
  kind: z.ZodLiteral<"attack-rule">;
171
252
  flag: z.ZodEnum<{
172
253
  "no-ranged-in-melee-disadvantage": "no-ranged-in-melee-disadvantage";
173
254
  }>;
255
+ condition: z.ZodOptional<z.ZodString>;
256
+ subject: z.ZodOptional<z.ZodString>;
257
+ }, z.core.$strip>, z.ZodObject<{
258
+ kind: z.ZodLiteral<"immunity">;
259
+ damage_type: z.ZodString;
260
+ condition: z.ZodOptional<z.ZodString>;
261
+ subject: z.ZodOptional<z.ZodString>;
262
+ }, z.core.$strip>, z.ZodObject<{
263
+ kind: z.ZodLiteral<"vulnerability">;
264
+ damage_type: z.ZodString;
265
+ condition: z.ZodOptional<z.ZodString>;
266
+ subject: z.ZodOptional<z.ZodString>;
267
+ }, z.core.$strip>, z.ZodObject<{
268
+ kind: z.ZodLiteral<"temp-hp">;
269
+ amount: z.ZodString;
270
+ condition: z.ZodOptional<z.ZodString>;
271
+ subject: z.ZodOptional<z.ZodString>;
272
+ }, z.core.$strip>, z.ZodObject<{
273
+ kind: z.ZodLiteral<"heal">;
274
+ amount: z.ZodString;
275
+ condition: z.ZodOptional<z.ZodString>;
276
+ subject: z.ZodOptional<z.ZodString>;
277
+ }, z.core.$strip>, z.ZodObject<{
278
+ kind: z.ZodLiteral<"ability-score-increase">;
279
+ abilities: z.ZodUnion<readonly [z.ZodLiteral<"chosen">, z.ZodArray<z.ZodEnum<{
280
+ str: "str";
281
+ dex: "dex";
282
+ con: "con";
283
+ int: "int";
284
+ wis: "wis";
285
+ cha: "cha";
286
+ }>>]>;
287
+ amount: z.ZodNumber;
288
+ choose: z.ZodNullable<z.ZodNumber>;
289
+ max: z.ZodNullable<z.ZodNumber>;
290
+ condition: z.ZodOptional<z.ZodString>;
291
+ subject: z.ZodOptional<z.ZodString>;
292
+ }, z.core.$strip>, z.ZodObject<{
293
+ kind: z.ZodLiteral<"extra-action">;
294
+ count: z.ZodNumber;
295
+ action_type: z.ZodEnum<{
296
+ action: "action";
297
+ "bonus-action": "bonus-action";
298
+ reaction: "reaction";
299
+ }>;
300
+ condition: z.ZodOptional<z.ZodString>;
301
+ subject: z.ZodOptional<z.ZodString>;
302
+ }, z.core.$strip>, z.ZodObject<{
303
+ kind: z.ZodLiteral<"save-outcome">;
304
+ ability: z.ZodUnion<readonly [z.ZodEnum<{
305
+ str: "str";
306
+ dex: "dex";
307
+ con: "con";
308
+ int: "int";
309
+ wis: "wis";
310
+ cha: "cha";
311
+ }>, z.ZodLiteral<"any">]>;
312
+ on_success: z.ZodEnum<{
313
+ none: "none";
314
+ half: "half";
315
+ full: "full";
316
+ }>;
317
+ on_failure: z.ZodEnum<{
318
+ none: "none";
319
+ half: "half";
320
+ full: "full";
321
+ }>;
322
+ applies_to: z.ZodNullable<z.ZodString>;
323
+ condition: z.ZodOptional<z.ZodString>;
324
+ subject: z.ZodOptional<z.ZodString>;
174
325
  }, z.core.$strip>], "kind">>;
175
326
  action_cost: z.ZodOptional<z.ZodNullable<z.ZodEnum<{
176
327
  action: "action";
@@ -184,6 +335,7 @@ export declare const optionalFeatureEntitySchema: z.ZodObject<{
184
335
  recharge: z.ZodEnum<{
185
336
  "short-rest": "short-rest";
186
337
  "long-rest": "long-rest";
338
+ either: "either";
187
339
  dawn: "dawn";
188
340
  dusk: "dusk";
189
341
  turn: "turn";
@@ -200,6 +352,7 @@ export declare const optionalFeatureEntitySchema: z.ZodObject<{
200
352
  resource: z.ZodOptional<z.ZodString>;
201
353
  column: z.ZodOptional<z.ZodString>;
202
354
  amount: z.ZodNumber;
355
+ amount_max: z.ZodOptional<z.ZodNumber>;
203
356
  expend_condition: z.ZodOptional<z.ZodEnum<{
204
357
  roll_succeeds: "roll_succeeds";
205
358
  roll_fails: "roll_fails";
@@ -211,6 +364,7 @@ export declare const optionalFeatureEntitySchema: z.ZodObject<{
211
364
  reset: z.ZodEnum<{
212
365
  "short-rest": "short-rest";
213
366
  "long-rest": "long-rest";
367
+ either: "either";
214
368
  dawn: "dawn";
215
369
  dusk: "dusk";
216
370
  turn: "turn";
@@ -231,6 +385,37 @@ export declare const optionalFeatureEntitySchema: z.ZodObject<{
231
385
  }, z.core.$strict>]>>>;
232
386
  passive: z.ZodOptional<z.ZodBoolean>;
233
387
  activatable: z.ZodOptional<z.ZodBoolean>;
388
+ rendering_hint: z.ZodOptional<z.ZodString>;
389
+ additional_spells: z.ZodOptional<z.ZodArray<z.ZodObject<{
390
+ name: z.ZodOptional<z.ZodString>;
391
+ ability: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodObject<{
392
+ choose: z.ZodArray<z.ZodString>;
393
+ }, z.core.$strip>]>>;
394
+ known: z.ZodOptional<z.ZodUnknown>;
395
+ innate: z.ZodOptional<z.ZodUnknown>;
396
+ prepared: z.ZodOptional<z.ZodUnknown>;
397
+ expanded: z.ZodOptional<z.ZodUnknown>;
398
+ resourceName: z.ZodOptional<z.ZodString>;
399
+ }, z.core.$strip>>>;
400
+ is_class_feature_variant: z.ZodOptional<z.ZodBoolean>;
401
+ has_fluff_images: z.ZodOptional<z.ZodBoolean>;
402
+ feat_progression: z.ZodOptional<z.ZodArray<z.ZodObject<{
403
+ name: z.ZodString;
404
+ progression: z.ZodUnion<readonly [z.ZodRecord<z.ZodString, z.ZodNumber>, z.ZodArray<z.ZodNumber>]>;
405
+ feature_type: z.ZodOptional<z.ZodArray<z.ZodString>>;
406
+ featureType: z.ZodOptional<z.ZodArray<z.ZodString>>;
407
+ category: z.ZodOptional<z.ZodArray<z.ZodString>>;
408
+ required: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodArray<z.ZodString>>>;
409
+ }, z.core.$strip>>>;
410
+ optionalfeature_progression: z.ZodOptional<z.ZodArray<z.ZodObject<{
411
+ name: z.ZodString;
412
+ progression: z.ZodUnion<readonly [z.ZodRecord<z.ZodString, z.ZodNumber>, z.ZodArray<z.ZodNumber>]>;
413
+ feature_type: z.ZodOptional<z.ZodArray<z.ZodString>>;
414
+ featureType: z.ZodOptional<z.ZodArray<z.ZodString>>;
415
+ category: z.ZodOptional<z.ZodArray<z.ZodString>>;
416
+ required: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodArray<z.ZodString>>>;
417
+ }, z.core.$strip>>>;
418
+ image: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]>>;
234
419
  }, z.core.$strip>;
235
420
  export type OptionalFeatureSchemaInput = z.input<typeof optionalFeatureEntitySchema>;
236
421
  export type OptionalFeatureSchemaOutput = z.output<typeof optionalFeatureEntitySchema>;
@@ -1,9 +1,10 @@
1
1
  import {
2
2
  optionalFeatureEntitySchema
3
- } from "../chunk-MDEJHMKK.js";
3
+ } from "../chunk-WHVLNFTG.js";
4
4
  import "../chunk-WYGD2UGN.js";
5
- import "../chunk-PZOWBI3B.js";
6
- import "../chunk-NXR3BD2V.js";
5
+ import "../chunk-YLL2QXY2.js";
6
+ import "../chunk-X3D6LXUU.js";
7
+ import "../chunk-UA5KS2PL.js";
7
8
  export {
8
9
  optionalFeatureEntitySchema
9
10
  };
package/dist/pack.d.ts CHANGED
@@ -5,7 +5,7 @@ import type { SystemPack } from "@archivist-gg/core";
5
5
  * (renderer/edit/modal) stays in the obsidian package. It is the only pack the
6
6
  * kernel registers.
7
7
  *
8
- * All 11 authored types are ported, plus the two generate-only types (npc and
8
+ * All 12 authored types are ported, plus the two generate-only types (npc and
9
9
  * encounter); a new entity type joins by appending its EntityType here.
10
10
  */
11
11
  export declare const dnd5ePack: SystemPack;
@@ -1,3 +1,2 @@
1
1
  export type ConditionSlug = "blinded" | "charmed" | "deafened" | "frightened" | "grappled" | "incapacitated" | "invisible" | "paralyzed" | "petrified" | "poisoned" | "prone" | "restrained" | "stunned" | "unconscious";
2
2
  export declare const CONDITION_SLUGS: readonly ["blinded", "charmed", "deafened", "frightened", "grappled", "incapacitated", "invisible", "paralyzed", "petrified", "poisoned", "prone", "restrained", "stunned", "unconscious"];
3
- export declare const CONDITION_DISPLAY_NAMES: Record<ConditionSlug, string>;
@@ -1,8 +1,6 @@
1
1
  import {
2
- CONDITION_DISPLAY_NAMES,
3
2
  CONDITION_SLUGS
4
- } from "../chunk-TZK36BU7.js";
3
+ } from "../chunk-S7REMWW4.js";
5
4
  export {
6
- CONDITION_DISPLAY_NAMES,
7
5
  CONDITION_SLUGS
8
6
  };
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  DECISION_SIGNAL,
3
3
  recognizeDecision
4
- } from "../chunk-JEYQU3JT.js";
4
+ } from "../chunk-YHYTW5QA.js";
5
5
  export {
6
6
  DECISION_SIGNAL,
7
7
  recognizeDecision
@@ -0,0 +1,47 @@
1
+ import type { EntityRegistry, RegisteredEntity } from "@archivist-gg/core";
2
+ import type { RaceEntity } from "@archivist-gg/dnd5e/race/race.types";
3
+ import type { FeatEntity } from "@archivist-gg/dnd5e/feat/feat.types";
4
+ import type { Spell } from "@archivist-gg/dnd5e/spell/spell.types";
5
+ import type { Ability } from "@archivist-gg/dnd5e";
6
+ import type { ResolvedClass, ResolvedSpell } from "./pc.types.js";
7
+ export declare const prefixOf: (slug: string) => string;
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
+ * name may legally contain "/" ("blindness/deafness" → "blindnessdeafness", the converter's own slug tail · Gate 0 B1).
10
+ * The "|source" token is DISCARDED (no abbreviation table exists anywhere); "#c"/"#2" are redundant with entity.level. */
11
+ export declare function normalizeSpellRef(ref: unknown): string | null;
12
+ export interface SpellNameIndex {
13
+ byName: Map<string, RegisteredEntity[]>;
14
+ }
15
+ /** At most ONE scan of the spell bucket per resolve(), keyed on slugify(entity name) · NEVER on the slug tail (Gate 0
16
+ * B2: the generators hyphenate "/" where dnd5e's slugify deletes it, so three bundle spells differ). Built LAZILY by
17
+ * its caller, on the first leaf that CALLS `resolveSpellByName` (the argument is evaluated whatever step then
18
+ * resolves it), so a character with no `additional_spells` leaf pays nothing for it. */
19
+ export declare function buildSpellNameIndex(entities: EntityRegistry): SpellNameIndex;
20
+ /** §5.2.3 · deterministic, no minted vocabulary: (0) the character's own copy · (a) the carrier's compendium exactly ·
21
+ * (b) same compendium → same edition (skipped when either side lacks one) → lowest full slug · (c) MISS → null + warnOnce ·
22
+ * (d) ambiguity after (i)+(ii) → (iii) decides AND warnOnce (the decision-engine byBare precedent). */
23
+ export declare function resolveSpellByName(opts: {
24
+ entities: EntityRegistry;
25
+ index: SpellNameIndex;
26
+ nameSlug: string;
27
+ carrierSlug: string;
28
+ carrierEdition?: string;
29
+ alreadyCollected: ResolvedSpell[];
30
+ }): {
31
+ entity: Spell;
32
+ slug: string;
33
+ } | null;
34
+ /** §5.2.9 · fold a race's entries ONLY when no select-inline on race.choices[] / traits[].choices[] / nested option.choices[]
35
+ * carries an id outside the structural set (nested: zero carriers, defensive). */
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. */
38
+ export declare function collectAdditionalSpells(args: {
39
+ race: RaceEntity | null;
40
+ feats: FeatEntity[];
41
+ classes: ResolvedClass[];
42
+ totalLevel: number;
43
+ ownAbility: Ability | null;
44
+ alreadyCollected: ResolvedSpell[];
45
+ entities: EntityRegistry;
46
+ warnings: string[];
47
+ }): ResolvedSpell[];
@@ -0,0 +1,23 @@
1
+ import {
2
+ buildSpellNameIndex,
3
+ collectAdditionalSpells,
4
+ normalizeSpellRef,
5
+ prefixOf,
6
+ raceIsUngated,
7
+ resolveSpellByName
8
+ } from "../chunk-MI7P3NX3.js";
9
+ import "../chunk-PVCEA4HZ.js";
10
+ import "../chunk-LVQLWRCU.js";
11
+ import "../chunk-6X4KUDMU.js";
12
+ import "../chunk-OZP6JFGT.js";
13
+ import "../chunk-VQAXTIBW.js";
14
+ import "../chunk-WELIKLZF.js";
15
+ import "../chunk-UA5KS2PL.js";
16
+ export {
17
+ buildSpellNameIndex,
18
+ collectAdditionalSpells,
19
+ normalizeSpellRef,
20
+ prefixOf,
21
+ raceIsUngated,
22
+ resolveSpellByName
23
+ };
@@ -0,0 +1,18 @@
1
+ import type { Choice } from "../types/choice.js";
2
+ /**
3
+ * Normalizes the authored two-step "Ability Score Increase or Feat" decision
4
+ * into the flat feat pick the product now uses.
5
+ *
6
+ * This is a PERMANENT compatibility layer, not a migration shim: hand-authored
7
+ * homebrew (e.g. `Compendium/MCDM/Classes/Illrigger.md`, which no bundle copy
8
+ * can ever overwrite) keeps emitting the two-step shape, and `choiceSchema`
9
+ * deliberately keeps accepting it.
10
+ *
11
+ * The lifted choice is the AUTHORED inner one, returned verbatim, so a homebrew
12
+ * variant carrying its own `where` / `count` / `label` survives. When the feat
13
+ * branch carries more than one child choice the whole choice is returned
14
+ * untouched, because lifting would silently drop the sibling.
15
+ *
16
+ * Pure: never mutates its input, never synthesizes a new object.
17
+ */
18
+ export declare function flattenAsiOrFeat(choice: Choice): Choice;
@@ -1,6 +1,8 @@
1
1
  import type { Choice, EntityFilter, Ability } from "@archivist-gg/dnd5e/types/choice";
2
2
  import type { ResolvedCharacter, ChoiceValue, FeatureSource } from "./pc.types.js";
3
3
  import type { RegisteredEntity } from "@archivist-gg/core";
4
+ import { type ProficiencyEntry } from "./pc.proficiency-grants.js";
5
+ import { wikilinkTailSlug } from "../entities/slug.js";
4
6
  export interface DecisionRegistry {
5
7
  search(query: string, entityType: string, limit: number): RegisteredEntity[];
6
8
  getByTypeAndSlug(entityType: string, slug: string): RegisteredEntity | undefined;
@@ -14,6 +16,13 @@ export interface ResolvedOption {
14
16
  description?: string;
15
17
  /** True when a `from` slug has no entity behind it — render visible-but-inert. */
16
18
  missing?: boolean;
19
+ /** True when this option is a STORED pick that no longer answers to the pool's collapsed candidate list
20
+ * (R4-G5 §3.2.3): a genuine prerequisite-failing pick, since §9.2.3 already rewrote every collapsed twin to
21
+ * its survivor. Stamped by the pool synth from `strandedPicks`, never by `enumerateOptions`, which stays pure
22
+ * over `(choice, ctx, ownerBare)` and cannot see the character. Both builder arms dress such an option with
23
+ * the unresolved (crimson req) marker and the sheet's "prerequisite unmet" wording; the picker modal still
24
+ * lists it as an ordinary candidate. */
25
+ stranded?: boolean;
17
26
  }
18
27
  /**
19
28
  * Status contract: over-selection (n > need) reports `resolved` — the engine
@@ -45,6 +54,40 @@ export interface DecisionItem {
45
54
  options: ResolvedOption[];
46
55
  selected: ChoiceValue | undefined;
47
56
  status: DecisionStatus;
57
+ /**
58
+ * True when this choice has nothing left to grant: every proficiency it could
59
+ * have offered is one the character ALREADY holds (on an `expertise` skill row,
60
+ * already holds AT EXPERTISE), so the exclusion filter (spec §5, widened to
61
+ * those rows by R4-G3b §7 F4) emptied its pool. Such a row is complete, not an
62
+ * open obligation the user has no way to discharge.
63
+ *
64
+ * Deliberately NOT a bare `options.length === 0`. FOUR other shapes reach
65
+ * zero options and are genuinely still open: a from-LESS `domain:"save"`
66
+ * choice (no pool exists at all · the enumerator's `??` fallback has no save
67
+ * branch, and a save choice that authors `from` does enumerate it), a
68
+ * select-entity whose registry holds no candidates (an empty vault), an
69
+ * authored `from: []`, and a `from_proficient` skill row the R4-G3b §7 F1
70
+ * INCLUSION empties (a fresh L1 Rogue holds no skills yet). Emptied-BY-
71
+ * EXCLUSION is the only one where the character is already whole, so the flag
72
+ * is scoped to select-proficiency in the language and tool domains PLUS
73
+ * `expertise` skill rows (R4-G3b §7 F4; a plain skill row is never excluded
74
+ * and so never satisfied · §14, and saves have no set at all) AND requires the
75
+ * pool to have been non-empty AFTER the F1 INCLUSION ran, not before it ·
76
+ * that fourth shape is the one this clause keeps open, and the next render
77
+ * repopulates it.
78
+ *
79
+ * `false` for every other item, informational ones included.
80
+ */
81
+ satisfied: boolean;
82
+ /** Present ONLY on a synthesized selection-pool item (R4-G5 §3.2.3): that pool's id and anchor level. It is
83
+ * the TYPED marker every writer keys the pool write canon on (the chips arm, the selection table,
84
+ * `renderLongListBrowse` and `DecisionPickModal`): a pool item persists an ARRAY even at count 1, the shape
85
+ * `PoolTab` writes, while a `feat` or any other pick keeps its string shape. Absent on every other item, so
86
+ * a truthiness test on it IS the discriminator. */
87
+ pool?: {
88
+ id: string;
89
+ anchorLevel: number;
90
+ };
48
91
  /**
49
92
  * Populated only for the selected branch of a select-inline (the
50
93
  * revealed-on-selection rule): a child decision becomes visible once its
@@ -65,33 +108,79 @@ export interface DecisionLedger {
65
108
  }
66
109
  export interface DecisionContext {
67
110
  registry: DecisionRegistry;
111
+ /** OPTIONAL visibility predicate. When supplied, ambiguous bare-slug lookups
112
+ * seed VISIBLE entities first, so a hidden compendium can never shadow a
113
+ * visible one that shares a bare slug. Absent (the engine's own tests, any
114
+ * caller that has no notion of hidden compendiums) means deterministic order
115
+ * only — never a behaviour change, because the seeding is total-ordered
116
+ * either way. Threaded plugin-side by the four builder ctx constructors. */
117
+ isEntityVisible?(e: RegisteredEntity): boolean;
68
118
  }
69
- /** "[[SRD 2024/Classes/Fighter]]" → "fighter" (tail segment, slugified). */
70
- export declare function wikilinkTailSlug(link: string): string;
119
+ /** `wikilinkTailSlug` MOVED to `entities/slug.ts` in R4-G5 T1, beside `bareEntitySlug`, so `pc.pools.ts` can
120
+ * import it without importing this module (this module imports `pc.pools` for `strandedPicks`; the old
121
+ * 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
125
+ * `tests/wikilink-tail-slug.test.ts`: a public
126
+ * surface, not a migration shim, so the standing "retire every shim" rule does not reach it (spec §17 names the
127
+ * re-export explicitly). */
128
+ export { wikilinkTailSlug };
71
129
  declare function matchesFilter(e: RegisteredEntity, where: EntityFilter, ownerBare: string): boolean;
72
130
  /** Test-only export of {@link matchesFilter} (Task B2). */
73
131
  export declare const __matchesFilterForTest: typeof matchesFilter;
74
132
  /** Walk every decision definition + persisted selection and collect chosen
75
- * proficiencies. Pure; called by recalc. Values are validated against the
76
- * decision's option pool — stale slugs (outside `from`) are ignored. */
133
+ * proficiencies. Pure; called by recalc.
134
+ *
135
+ * On the `select-proficiency` arms, values are validated against the decision's
136
+ * option pool via filterToPool: slugs outside `from` are ignored, and a pick
137
+ * matching under canon is kept in the POOL's spelling. The `weapons` arm is the
138
+ * one exception · a `select-entity` pick carries ENTITY slugs, not proficiency
139
+ * slugs, and its `from` is a list of entity slugs, so those values are
140
+ * bare-slugged rather than pool-filtered (R4-G3b §7 F5). */
77
141
  export declare function collectChosenProficiencies(resolved: ResolvedCharacter): {
78
142
  skills: string[];
79
143
  expertise: string[];
80
144
  languages: string[];
81
145
  tools: string[];
146
+ weapons: string[];
147
+ saves: Ability[];
82
148
  };
83
- export interface ChoiceStatus {
84
- id: string;
85
- count: number;
86
- selected: number;
87
- }
88
- /** Per-choice status for language/tool select-proficiency decisions, using the
89
- * SAME walk as collectChosenProficiencies so required/selected counts cannot
90
- * diverge from the picks. `selected` counts persisted picks validated against
91
- * the choice's `from` pool (stale slugs ignored, mirroring the pick fold). */
92
- export declare function collectLanguageToolChoiceStatus(resolved: ResolvedCharacter): {
93
- languages: ChoiceStatus[];
94
- tools: ChoiceStatus[];
149
+ /** The single primitive for "what languages/tools does this character actually
150
+ * have": grants + picks + manual adds, MINUS suppressions (spec §4.1).
151
+ *
152
+ * Suppressions are applied INSIDE this function precisely so that no reader can
153
+ * forget them · the sheet panel's display, the builder picker's option
154
+ * exclusion and the "already satisfied" test all read this one function and
155
+ * therefore agree by construction.
156
+ *
157
+ * Built on the grant walk, NEVER on computeProficiencies (spec §4.2): recalc's
158
+ * proficiency fold is missing the race and background grants.
159
+ *
160
+ * ONE argument. `Character.overrides` is non-optional with a schema default, so
161
+ * a second parameter would be redundant and would force an optionality decision
162
+ * at seventeen existing aggregateProficiencies call sites (spec §4.1).
163
+ *
164
+ * SEVENTEEN is a PRE-R4-P3c SNAPSHOT (dnd5e 433cc72 · plugin 90394e9, which this
165
+ * phase never touches), and that is what "existing" means above: the sites that
166
+ * existed when the one-argument decision was taken. It is NOT today's count. Do
167
+ * not re-"correct" it to today's · that number moves on every new test that
168
+ * calls the function, while the cost this sentence is weighing does not.
169
+ *
170
+ * Reproduce the snapshot with `git grep -c "aggregateProficiencies(" <rev>` over
171
+ * *.ts/*.tsx, node_modules and dist excluded: 15 raw lines in dnd5e + 3 in the
172
+ * plugin = 18, minus the DECLARATION in pc.proficiencies.ts = 17 · namely 2
173
+ * production (the plugin's proficiencies-panel and proficiency-edit-modal) + 15
174
+ * in tests (14 in dnd5e, 1 in the plugin's pc-proficiency-edit-modal counting
175
+ * passthrough). Two traps in that census. The plugin's two mock bindings are NOT
176
+ * a subtraction: `aggregateProficiencies:` has no paren, so the pattern never
177
+ * matched them. THIS DOCBLOCK's own backticked mention above IS one, and only
178
+ * from R4-P3c onward · immediately after that phase the same grep returns 20
179
+ * raw, which is 18 call sites once the declaration AND this docblock come off,
180
+ * not the 19 you get by subtracting the declaration alone. */
181
+ export declare function computeEffectiveProficiencies(resolved: ResolvedCharacter): {
182
+ languages: ProficiencyEntry[];
183
+ tools: ProficiencyEntry[];
95
184
  };
96
185
  export interface OriginAbilityPoints {
97
186
  race: Partial<Record<Ability, number>>;
@@ -104,4 +193,3 @@ export interface OriginAbilityPoints {
104
193
  * legacy choices[lvl].asi path recalc already folds — do not double-count. */
105
194
  export declare function collectChosenAbilityPoints(resolved: ResolvedCharacter): OriginAbilityPoints;
106
195
  export declare function buildDecisionLedger(resolved: ResolvedCharacter, ctx: DecisionContext): DecisionLedger;
107
- export {};