modwright 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (455) hide show
  1. package/LICENSE +35 -0
  2. package/README.md +212 -0
  3. package/assets/claude/agents/mw-explore.md +46 -0
  4. package/assets/claude/agents/mw-fixture.md +33 -0
  5. package/assets/claude/agents/mw-rule-author.md +51 -0
  6. package/assets/claude/agents/mw-scaffold-author.md +48 -0
  7. package/assets/claude/skills/mw-author.md +59 -0
  8. package/assets/claude/skills/mw-new-item.md +51 -0
  9. package/assets/claude/skills/mw-new-spell.md +50 -0
  10. package/assets/claude/skills/mw-scaffold.md +59 -0
  11. package/assets/claude/skills/mw-ship.md +57 -0
  12. package/assets/claude/skills/mw-validate.md +51 -0
  13. package/assets/claude/skills/mw-verify.md +59 -0
  14. package/assets/nivalisnights/extract_resources.py +177 -0
  15. package/bridges/bg3-se/Mods/ModWrightBridge/ScriptExtender/Config.json +5 -0
  16. package/bridges/bg3-se/Mods/ModWrightBridge/ScriptExtender/Lua/BootstrapClient.lua +55 -0
  17. package/bridges/bg3-se/Mods/ModWrightBridge/ScriptExtender/Lua/BootstrapServer.lua +81 -0
  18. package/bridges/bg3-se/Mods/ModWrightBridge/ScriptExtender/Lua/ModWrightBridge/Log.lua +96 -0
  19. package/bridges/bg3-se/Mods/ModWrightBridge/ScriptExtender/Lua/ModWrightBridge/Probes.lua +1038 -0
  20. package/bridges/bg3-se/Mods/ModWrightBridge/ScriptExtender/Lua/ModWrightBridge/ProbesClient.lua +74 -0
  21. package/bridges/bg3-se/Mods/ModWrightBridge/ScriptExtender/Lua/ModWrightBridge/Protocol.lua +985 -0
  22. package/bridges/bg3-se/Mods/ModWrightBridge/ScriptExtender/Lua/ModWrightBridge/Watch.lua +175 -0
  23. package/bridges/bg3-se/Mods/ModWrightBridge/meta.lsx +45 -0
  24. package/bridges/bg3-se/README.md +99 -0
  25. package/bridges/bg3-se/bridge.json +68 -0
  26. package/bridges/cp2077-cet/ModWrightBridge/init.lua +375 -0
  27. package/bridges/cp2077-cet/ModWrightBridge/probes.lua +1104 -0
  28. package/bridges/cp2077-cet/ModWrightBridge/protocol.lua +1306 -0
  29. package/bridges/cp2077-cet/README.md +165 -0
  30. package/bridges/cp2077-cet/bridge.json +53 -0
  31. package/dist/core/bridge/arm.js +175 -0
  32. package/dist/core/bridge/cet-console.js +26 -0
  33. package/dist/core/bridge/cet-log.js +362 -0
  34. package/dist/core/bridge/index.js +11 -0
  35. package/dist/core/bridge/locate.js +35 -0
  36. package/dist/core/bridge/paths.js +34 -0
  37. package/dist/core/bridge/pending.js +89 -0
  38. package/dist/core/bridge/poll.js +155 -0
  39. package/dist/core/bridge/stage.js +100 -0
  40. package/dist/core/bridge/status.js +97 -0
  41. package/dist/core/bridge/types.js +145 -0
  42. package/dist/core/bridge/validate.js +107 -0
  43. package/dist/core/build/index.js +6 -0
  44. package/dist/core/build/manifest.js +47 -0
  45. package/dist/core/build/paths.js +32 -0
  46. package/dist/core/build/run.js +342 -0
  47. package/dist/core/build/stage.js +265 -0
  48. package/dist/core/build/steps/bg3.js +129 -0
  49. package/dist/core/build/steps/core.js +195 -0
  50. package/dist/core/build/steps/cyberpunk.js +95 -0
  51. package/dist/core/build/steps/listing.js +35 -0
  52. package/dist/core/build/types.js +13 -0
  53. package/dist/core/build/zip.js +148 -0
  54. package/dist/core/compat/check.js +113 -0
  55. package/dist/core/compat/pe.js +220 -0
  56. package/dist/core/compat/types.js +1 -0
  57. package/dist/core/compat/version.js +70 -0
  58. package/dist/core/deploy/guards.js +292 -0
  59. package/dist/core/deploy/index.js +5 -0
  60. package/dist/core/deploy/plan.js +696 -0
  61. package/dist/core/deploy/reload-apply.js +361 -0
  62. package/dist/core/deploy/reload.js +358 -0
  63. package/dist/core/deploy/sources.js +169 -0
  64. package/dist/core/deploy/types.js +1 -0
  65. package/dist/core/epic.js +54 -0
  66. package/dist/core/fsutil.js +191 -0
  67. package/dist/core/home.js +70 -0
  68. package/dist/core/knowledge/facts.js +229 -0
  69. package/dist/core/knowledge/index.js +4 -0
  70. package/dist/core/knowledge/search.js +112 -0
  71. package/dist/core/knowledge/store.js +123 -0
  72. package/dist/core/knowledge/types.js +1 -0
  73. package/dist/core/ledger/check.js +42 -0
  74. package/dist/core/ledger/hooks.js +80 -0
  75. package/dist/core/ledger/index.js +7 -0
  76. package/dist/core/ledger/query.js +17 -0
  77. package/dist/core/ledger/record.js +84 -0
  78. package/dist/core/ledger/status.js +53 -0
  79. package/dist/core/ledger/store.js +98 -0
  80. package/dist/core/ledger/types.js +108 -0
  81. package/dist/core/logs/index.js +4 -0
  82. package/dist/core/logs/registry.js +50 -0
  83. package/dist/core/logs/scan.js +195 -0
  84. package/dist/core/logs/triage.js +160 -0
  85. package/dist/core/logs/types.js +1 -0
  86. package/dist/core/lsx.js +10 -0
  87. package/dist/core/lz4.js +66 -0
  88. package/dist/core/mods.js +229 -0
  89. package/dist/core/process.js +49 -0
  90. package/dist/core/project/build-steps.js +83 -0
  91. package/dist/core/project/describe.js +74 -0
  92. package/dist/core/project/index.js +5 -0
  93. package/dist/core/project/load.js +146 -0
  94. package/dist/core/project/schema.js +264 -0
  95. package/dist/core/project/types.js +3 -0
  96. package/dist/core/prompts.js +72 -0
  97. package/dist/core/registry.js +35 -0
  98. package/dist/core/safety/backup.js +206 -0
  99. package/dist/core/safety/execute.js +188 -0
  100. package/dist/core/safety/index.js +5 -0
  101. package/dist/core/safety/plan.js +122 -0
  102. package/dist/core/safety/restore.js +172 -0
  103. package/dist/core/safety/types.js +1 -0
  104. package/dist/core/scaffold/bootstrap.js +7 -0
  105. package/dist/core/scaffold/catalog.js +28 -0
  106. package/dist/core/scaffold/claude-assets.js +271 -0
  107. package/dist/core/scaffold/collisions.js +64 -0
  108. package/dist/core/scaffold/emit.js +356 -0
  109. package/dist/core/scaffold/engine.js +680 -0
  110. package/dist/core/scaffold/ids.js +78 -0
  111. package/dist/core/scaffold/index.js +10 -0
  112. package/dist/core/scaffold/jsonpath.js +121 -0
  113. package/dist/core/scaffold/load.js +81 -0
  114. package/dist/core/scaffold/render.js +85 -0
  115. package/dist/core/scaffold/sequence.js +396 -0
  116. package/dist/core/scaffold/types.js +309 -0
  117. package/dist/core/steam.js +63 -0
  118. package/dist/core/surfaceutil.js +36 -0
  119. package/dist/core/testplan/check.js +67 -0
  120. package/dist/core/testplan/index.js +5 -0
  121. package/dist/core/testplan/load.js +100 -0
  122. package/dist/core/testplan/registry.js +317 -0
  123. package/dist/core/testplan/run.js +389 -0
  124. package/dist/core/testplan/types.js +82 -0
  125. package/dist/core/text/converters/bg3.js +50 -0
  126. package/dist/core/text/converters/cyberpunk.js +36 -0
  127. package/dist/core/text/converters/index.js +261 -0
  128. package/dist/core/text/diff/cr2w.js +180 -0
  129. package/dist/core/text/diff/index.js +16 -0
  130. package/dist/core/text/diff/loca.js +43 -0
  131. package/dist/core/text/diff/lsx.js +126 -0
  132. package/dist/core/text/handles.js +86 -0
  133. package/dist/core/text/index.js +6 -0
  134. package/dist/core/text/json.js +46 -0
  135. package/dist/core/text/templates/cache.js +71 -0
  136. package/dist/core/text/templates/index.js +3 -0
  137. package/dist/core/text/templates/library.js +245 -0
  138. package/dist/core/text/templates/types.js +51 -0
  139. package/dist/core/text/toolchain.js +16 -0
  140. package/dist/core/text/types.js +1 -0
  141. package/dist/core/text/validate.js +149 -0
  142. package/dist/core/text/xml.js +58 -0
  143. package/dist/core/toolchain/datafetch.js +151 -0
  144. package/dist/core/toolchain/env.js +63 -0
  145. package/dist/core/toolchain/features.js +170 -0
  146. package/dist/core/toolchain/index.js +8 -0
  147. package/dist/core/toolchain/install.js +191 -0
  148. package/dist/core/toolchain/locate.js +275 -0
  149. package/dist/core/toolchain/remember.js +84 -0
  150. package/dist/core/toolchain/run.js +318 -0
  151. package/dist/core/toolchain/specs.js +351 -0
  152. package/dist/core/toolchain/types.js +1 -0
  153. package/dist/core/types.js +1 -0
  154. package/dist/core/userconfig.js +66 -0
  155. package/dist/core/validate/context.js +139 -0
  156. package/dist/core/validate/index.js +5 -0
  157. package/dist/core/validate/registry.js +58 -0
  158. package/dist/core/validate/run.js +131 -0
  159. package/dist/core/validate/suppressions.js +91 -0
  160. package/dist/core/validate/types.js +2 -0
  161. package/dist/core/yamledit.js +51 -0
  162. package/dist/index.js +389 -0
  163. package/dist/server.js +1914 -0
  164. package/dist/surfaces/baldursgate3/compat.js +164 -0
  165. package/dist/surfaces/baldursgate3/identity.js +110 -0
  166. package/dist/surfaces/baldursgate3/index/build.js +331 -0
  167. package/dist/surfaces/baldursgate3/index/index.js +17 -0
  168. package/dist/surfaces/baldursgate3/index/info.js +40 -0
  169. package/dist/surfaces/baldursgate3/index/parsers/loca.js +41 -0
  170. package/dist/surfaces/baldursgate3/index/parsers/lsx.js +137 -0
  171. package/dist/surfaces/baldursgate3/index/parsers/stats.js +45 -0
  172. package/dist/surfaces/baldursgate3/index/parsers/treasuretable.js +57 -0
  173. package/dist/surfaces/baldursgate3/index/parsers/xmlutil.js +142 -0
  174. package/dist/surfaces/baldursgate3/index/queries.js +327 -0
  175. package/dist/surfaces/baldursgate3/index/schema.js +62 -0
  176. package/dist/surfaces/baldursgate3/index.js +3 -0
  177. package/dist/surfaces/baldursgate3/logs.js +278 -0
  178. package/dist/surfaces/baldursgate3/modsettings.js +115 -0
  179. package/dist/surfaces/baldursgate3/pak.js +153 -0
  180. package/dist/surfaces/baldursgate3/settings.js +49 -0
  181. package/dist/surfaces/baldursgate3/surface.js +232 -0
  182. package/dist/surfaces/baldursgate3/validators/bridge.js +7 -0
  183. package/dist/surfaces/baldursgate3/validators/files.js +476 -0
  184. package/dist/surfaces/baldursgate3/validators/items.js +1001 -0
  185. package/dist/surfaces/baldursgate3/validators/progression.js +734 -0
  186. package/dist/surfaces/baldursgate3/validators/stats.js +1076 -0
  187. package/dist/surfaces/baldursgate3/validators/story.js +790 -0
  188. package/dist/surfaces/baldursgate3/validators/templates.js +7 -0
  189. package/dist/surfaces/cyberpunk2077/compat.js +223 -0
  190. package/dist/surfaces/cyberpunk2077/index/build.js +231 -0
  191. package/dist/surfaces/cyberpunk2077/index/index.js +17 -0
  192. package/dist/surfaces/cyberpunk2077/index/info.js +51 -0
  193. package/dist/surfaces/cyberpunk2077/index/model.js +52 -0
  194. package/dist/surfaces/cyberpunk2077/index/parsers/tweak.js +483 -0
  195. package/dist/surfaces/cyberpunk2077/index/parsers/tweakxl-yaml.js +183 -0
  196. package/dist/surfaces/cyberpunk2077/index/queries.js +504 -0
  197. package/dist/surfaces/cyberpunk2077/index/resource.js +135 -0
  198. package/dist/surfaces/cyberpunk2077/index/schema.js +90 -0
  199. package/dist/surfaces/cyberpunk2077/index.js +3 -0
  200. package/dist/surfaces/cyberpunk2077/logs.js +742 -0
  201. package/dist/surfaces/cyberpunk2077/paths.js +12 -0
  202. package/dist/surfaces/cyberpunk2077/surface.js +218 -0
  203. package/dist/surfaces/cyberpunk2077/validators/bridge.js +7 -0
  204. package/dist/surfaces/cyberpunk2077/validators/cr2w.js +349 -0
  205. package/dist/surfaces/cyberpunk2077/validators/garments.js +1181 -0
  206. package/dist/surfaces/cyberpunk2077/validators/mesh.js +338 -0
  207. package/dist/surfaces/cyberpunk2077/validators/modsettings.js +120 -0
  208. package/dist/surfaces/cyberpunk2077/validators/packaging.js +463 -0
  209. package/dist/surfaces/cyberpunk2077/validators/red4ext.js +318 -0
  210. package/dist/surfaces/cyberpunk2077/validators/redscript.js +193 -0
  211. package/dist/surfaces/cyberpunk2077/validators/templates.js +7 -0
  212. package/dist/surfaces/cyberpunk2077/validators/tweaks.js +768 -0
  213. package/dist/surfaces/cyberpunk2077/validators/vehicles.js +531 -0
  214. package/dist/surfaces/cyberpunk2077/validators/xl.js +308 -0
  215. package/dist/surfaces/eldenring/binders.js +111 -0
  216. package/dist/surfaces/eldenring/compat.js +166 -0
  217. package/dist/surfaces/eldenring/dcx.js +49 -0
  218. package/dist/surfaces/eldenring/index.js +13 -0
  219. package/dist/surfaces/eldenring/loaders.js +132 -0
  220. package/dist/surfaces/eldenring/logs.js +67 -0
  221. package/dist/surfaces/eldenring/paramdef.js +256 -0
  222. package/dist/surfaces/eldenring/params.js +129 -0
  223. package/dist/surfaces/eldenring/surface.js +121 -0
  224. package/dist/surfaces/eldenring/tools.js +52 -0
  225. package/dist/surfaces/eldenring/validators/binders.js +193 -0
  226. package/dist/surfaces/eldenring/validators/packages.js +159 -0
  227. package/dist/surfaces/eldenring/validators/params.js +334 -0
  228. package/dist/surfaces/eldenring/validators/profiles.js +287 -0
  229. package/dist/surfaces/index.js +34 -0
  230. package/dist/surfaces/nivalisnights/compat.js +229 -0
  231. package/dist/surfaces/nivalisnights/index/build.js +310 -0
  232. package/dist/surfaces/nivalisnights/index/index.js +5 -0
  233. package/dist/surfaces/nivalisnights/index/queries.js +231 -0
  234. package/dist/surfaces/nivalisnights/index.js +4 -0
  235. package/dist/surfaces/nivalisnights/logs.js +473 -0
  236. package/dist/surfaces/nivalisnights/surface.js +195 -0
  237. package/dist/surfaces/skyrimse/archives.js +229 -0
  238. package/dist/surfaces/skyrimse/compat.js +163 -0
  239. package/dist/surfaces/skyrimse/index.js +12 -0
  240. package/dist/surfaces/skyrimse/loadorder.js +174 -0
  241. package/dist/surfaces/skyrimse/logs.js +241 -0
  242. package/dist/surfaces/skyrimse/plugins.js +149 -0
  243. package/dist/surfaces/skyrimse/records.js +94 -0
  244. package/dist/surfaces/skyrimse/surface.js +240 -0
  245. package/dist/surfaces/skyrimse/validators/archive-records.js +165 -0
  246. package/dist/surfaces/skyrimse/validators/archives.js +110 -0
  247. package/dist/surfaces/skyrimse/validators/plugins.js +374 -0
  248. package/dist/surfaces/skyrimse/validators/records.js +117 -0
  249. package/dist/surfaces/stardewvalley/compat.js +190 -0
  250. package/dist/surfaces/stardewvalley/config.js +42 -0
  251. package/dist/surfaces/stardewvalley/contentpatcher.js +203 -0
  252. package/dist/surfaces/stardewvalley/index/index.js +229 -0
  253. package/dist/surfaces/stardewvalley/index/wiki.js +190 -0
  254. package/dist/surfaces/stardewvalley/index.js +12 -0
  255. package/dist/surfaces/stardewvalley/logs.js +307 -0
  256. package/dist/surfaces/stardewvalley/mods.js +182 -0
  257. package/dist/surfaces/stardewvalley/surface.js +244 -0
  258. package/dist/surfaces/stardewvalley/validators/content.js +321 -0
  259. package/dist/surfaces/stardewvalley/validators/fields.js +147 -0
  260. package/dist/surfaces/stardewvalley/validators/loadorder.js +69 -0
  261. package/dist/surfaces/stardewvalley/validators/manifest.js +221 -0
  262. package/dist/surfaces/subnautica2/compat.js +138 -0
  263. package/dist/surfaces/subnautica2/index.js +5 -0
  264. package/dist/surfaces/subnautica2/logs.js +129 -0
  265. package/dist/surfaces/subnautica2/paks.js +173 -0
  266. package/dist/surfaces/subnautica2/surface.js +151 -0
  267. package/dist/surfaces/subnautica2/validators/packaging.js +298 -0
  268. package/dist/surfaces/valheim/compat.js +171 -0
  269. package/dist/surfaces/valheim/index/index.js +301 -0
  270. package/dist/surfaces/valheim/index/tables.js +103 -0
  271. package/dist/surfaces/valheim/index.js +11 -0
  272. package/dist/surfaces/valheim/logs.js +197 -0
  273. package/dist/surfaces/valheim/packaging.js +131 -0
  274. package/dist/surfaces/valheim/plugins.js +270 -0
  275. package/dist/surfaces/valheim/references.js +121 -0
  276. package/dist/surfaces/valheim/surface.js +223 -0
  277. package/dist/surfaces/valheim/validators/packaging.js +218 -0
  278. package/dist/surfaces/valheim/validators/plugins.js +287 -0
  279. package/dist/surfaces/valheim/validators/references.js +169 -0
  280. package/knowledge/baldursgate3/animations.gr2.yaml +166 -0
  281. package/knowledge/baldursgate3/audio.voice.yaml +182 -0
  282. package/knowledge/baldursgate3/audio.wwise.yaml +104 -0
  283. package/knowledge/baldursgate3/charactercreation.heads-hair.yaml +193 -0
  284. package/knowledge/baldursgate3/communitylibrary.shared-content.yaml +129 -0
  285. package/knowledge/baldursgate3/compatibilityframework.api.yaml +176 -0
  286. package/knowledge/baldursgate3/crash.causes.yaml +90 -0
  287. package/knowledge/baldursgate3/dialogue.dialogbank.yaml +120 -0
  288. package/knowledge/baldursgate3/dialogue.files.yaml +236 -0
  289. package/knowledge/baldursgate3/dialogue.osiris-goals.yaml +386 -0
  290. package/knowledge/baldursgate3/dialogue.yaml +122 -0
  291. package/knowledge/baldursgate3/feats.classes.yaml +164 -0
  292. package/knowledge/baldursgate3/items.cloth-physics.yaml +167 -0
  293. package/knowledge/baldursgate3/items.roottemplates.yaml +320 -0
  294. package/knowledge/baldursgate3/items.visualbank.yaml +628 -0
  295. package/knowledge/baldursgate3/journal.quests.yaml +214 -0
  296. package/knowledge/baldursgate3/loadorder.modsettings.yaml +128 -0
  297. package/knowledge/baldursgate3/localization.handles.yaml +92 -0
  298. package/knowledge/baldursgate3/misc.encoding-and-practice.yaml +111 -0
  299. package/knowledge/baldursgate3/origins.companions.yaml +144 -0
  300. package/knowledge/baldursgate3/osiris.signatures.yaml +211 -0
  301. package/knowledge/baldursgate3/packaging.meta.yaml +155 -0
  302. package/knowledge/baldursgate3/packaging.paks.yaml +79 -0
  303. package/knowledge/baldursgate3/process.launch.yaml +34 -0
  304. package/knowledge/baldursgate3/progressions.yaml +92 -0
  305. package/knowledge/baldursgate3/publishing.modio-nexus.yaml +170 -0
  306. package/knowledge/baldursgate3/publishing.toolkit-modio.yaml +135 -0
  307. package/knowledge/baldursgate3/races.progression.yaml +228 -0
  308. package/knowledge/baldursgate3/scriptextender.console.yaml +257 -0
  309. package/knowledge/baldursgate3/scriptextender.yaml +252 -0
  310. package/knowledge/baldursgate3/stats.boosts.yaml +293 -0
  311. package/knowledge/baldursgate3/stats.equipment-kits.yaml +69 -0
  312. package/knowledge/baldursgate3/stats.interrupts.yaml +45 -0
  313. package/knowledge/baldursgate3/stats.itemcombos.yaml +65 -0
  314. package/knowledge/baldursgate3/stats.spells.yaml +293 -0
  315. package/knowledge/baldursgate3/stats.weapons.yaml +210 -0
  316. package/knowledge/baldursgate3/toolchain.divine.yaml +179 -0
  317. package/knowledge/baldursgate3/toolchain.lslib-formats.yaml +242 -0
  318. package/knowledge/baldursgate3/toolkit.levels.yaml +177 -0
  319. package/knowledge/baldursgate3/ui.icons-atlas.yaml +78 -0
  320. package/knowledge/baldursgate3/ui.icons.yaml +412 -0
  321. package/knowledge/baldursgate3/ui.mcm.yaml +161 -0
  322. package/knowledge/baldursgate3/vfx.materials.yaml +174 -0
  323. package/knowledge/baldursgate3/visuals.characterfix.yaml +73 -0
  324. package/knowledge/cyberpunk2077/animations.anims.yaml +118 -0
  325. package/knowledge/cyberpunk2077/anims.archivexl.yaml +163 -0
  326. package/knowledge/cyberpunk2077/anims.authoring.yaml +579 -0
  327. package/knowledge/cyberpunk2077/anims.encoder.yaml +156 -0
  328. package/knowledge/cyberpunk2077/anims.graph.yaml +629 -0
  329. package/knowledge/cyberpunk2077/anims.method.yaml +360 -0
  330. package/knowledge/cyberpunk2077/anims.pipeline.yaml +352 -0
  331. package/knowledge/cyberpunk2077/anims.roundtrip.yaml +222 -0
  332. package/knowledge/cyberpunk2077/anims.sets.yaml +176 -0
  333. package/knowledge/cyberpunk2077/archivexl.bodytypes.yaml +149 -0
  334. package/knowledge/cyberpunk2077/archivexl.dynamic-appearances.yaml +218 -0
  335. package/knowledge/cyberpunk2077/archivexl.manifest.yaml +214 -0
  336. package/knowledge/cyberpunk2077/audio.events.yaml +168 -0
  337. package/knowledge/cyberpunk2077/audio.sounds.yaml +164 -0
  338. package/knowledge/cyberpunk2077/audio.voicesets.yaml +146 -0
  339. package/knowledge/cyberpunk2077/cet.sandbox.yaml +219 -0
  340. package/knowledge/cyberpunk2077/clothing.garments.yaml +283 -0
  341. package/knowledge/cyberpunk2077/clothing.refits.yaml +215 -0
  342. package/knowledge/cyberpunk2077/codeware.overview.yaml +111 -0
  343. package/knowledge/cyberpunk2077/codeware.systems.yaml +192 -0
  344. package/knowledge/cyberpunk2077/drones.combat.yaml +416 -0
  345. package/knowledge/cyberpunk2077/drones.control.yaml +552 -0
  346. package/knowledge/cyberpunk2077/entities.appearance.yaml +166 -0
  347. package/knowledge/cyberpunk2077/equipmentex.slots.yaml +151 -0
  348. package/knowledge/cyberpunk2077/fx.effects.yaml +246 -0
  349. package/knowledge/cyberpunk2077/fx.lights.yaml +171 -0
  350. package/knowledge/cyberpunk2077/hair.modding.yaml +145 -0
  351. package/knowledge/cyberpunk2077/items.wiring.yaml +246 -0
  352. package/knowledge/cyberpunk2077/loadorder.archives.yaml +71 -0
  353. package/knowledge/cyberpunk2077/mesh.blender.yaml +209 -0
  354. package/knowledge/cyberpunk2077/nativedb.dump.yaml +98 -0
  355. package/knowledge/cyberpunk2077/npc.appearance.yaml +275 -0
  356. package/knowledge/cyberpunk2077/npc.behaviour.yaml +128 -0
  357. package/knowledge/cyberpunk2077/npc.locomotion.yaml +490 -0
  358. package/knowledge/cyberpunk2077/packaging.deploy.yaml +175 -0
  359. package/knowledge/cyberpunk2077/packaging.variants.yaml +176 -0
  360. package/knowledge/cyberpunk2077/player.control.yaml +918 -0
  361. package/knowledge/cyberpunk2077/process.assetbuild.yaml +154 -0
  362. package/knowledge/cyberpunk2077/process.lessons.yaml +276 -0
  363. package/knowledge/cyberpunk2077/quests.minor.yaml +46 -0
  364. package/knowledge/cyberpunk2077/quests.scenes.yaml +282 -0
  365. package/knowledge/cyberpunk2077/quickhacks.tiers.yaml +41 -0
  366. package/knowledge/cyberpunk2077/red4ext.api.yaml +645 -0
  367. package/knowledge/cyberpunk2077/red4ext.plugins.yaml +124 -0
  368. package/knowledge/cyberpunk2077/redhottools.hotreload.yaml +245 -0
  369. package/knowledge/cyberpunk2077/redscript.compile-log.yaml +76 -0
  370. package/knowledge/cyberpunk2077/redscript.modules.yaml +118 -0
  371. package/knowledge/cyberpunk2077/toolchain.wolvenkit.yaml +163 -0
  372. package/knowledge/cyberpunk2077/tweakdb.loot-recipes.yaml +184 -0
  373. package/knowledge/cyberpunk2077/tweakdb.melee.yaml +352 -0
  374. package/knowledge/cyberpunk2077/tweakdb.weapons.yaml +325 -0
  375. package/knowledge/cyberpunk2077/tweakxl.hotreload.yaml +151 -0
  376. package/knowledge/cyberpunk2077/tweakxl.yaml-syntax.yaml +208 -0
  377. package/knowledge/cyberpunk2077/ui.icons.yaml +259 -0
  378. package/knowledge/cyberpunk2077/ui.inkatlas.yaml +81 -0
  379. package/knowledge/cyberpunk2077/ui.modsettings.yaml +204 -0
  380. package/knowledge/cyberpunk2077/vehicles.control.yaml +475 -0
  381. package/knowledge/cyberpunk2077/vehicles.dashboard-ui.yaml +203 -0
  382. package/knowledge/cyberpunk2077/vehicles.entities.yaml +195 -0
  383. package/knowledge/cyberpunk2077/vehicles.wiring.yaml +137 -0
  384. package/knowledge/cyberpunk2077/wolvenkit.cli.yaml +167 -0
  385. package/knowledge/cyberpunk2077/workspot.system.yaml +55 -0
  386. package/knowledge/cyberpunk2077/world.interactions.yaml +41 -0
  387. package/knowledge/cyberpunk2077/world.loot-container.yaml +167 -0
  388. package/knowledge/cyberpunk2077/world.sectors.yaml +233 -0
  389. package/knowledge/eldenring/formats.binders.yaml +237 -0
  390. package/knowledge/eldenring/launcher.me3.yaml +230 -0
  391. package/knowledge/eldenring/launcher.modengine2.yaml +119 -0
  392. package/knowledge/eldenring/params.paramdef.yaml +149 -0
  393. package/knowledge/eldenring/params.regulation.yaml +142 -0
  394. package/knowledge/eldenring/saves.online.yaml +118 -0
  395. package/knowledge/eldenring/toolchain.cli.yaml +256 -0
  396. package/knowledge/nivalisnights/modding.runtime.yaml +157 -0
  397. package/knowledge/skyrimse/archives.bsa.yaml +212 -0
  398. package/knowledge/skyrimse/install.detection.yaml +41 -0
  399. package/knowledge/skyrimse/loadorder.files.yaml +242 -0
  400. package/knowledge/skyrimse/plugins.esl.yaml +189 -0
  401. package/knowledge/skyrimse/plugins.format.yaml +224 -0
  402. package/knowledge/skyrimse/skse.runtime.yaml +283 -0
  403. package/knowledge/skyrimse/toolchain.xedit-spriggit.yaml +336 -0
  404. package/knowledge/stardewvalley/contentpatcher.format.yaml +338 -0
  405. package/knowledge/stardewvalley/distribution.channels.yaml +236 -0
  406. package/knowledge/stardewvalley/game.versions.yaml +202 -0
  407. package/knowledge/stardewvalley/install.layout.yaml +277 -0
  408. package/knowledge/stardewvalley/smapi.loader.yaml +284 -0
  409. package/knowledge/stardewvalley/smapi.logs.yaml +329 -0
  410. package/knowledge/stardewvalley/smapi.manifest.yaml +293 -0
  411. package/knowledge/stardewvalley/toolchain.build.yaml +261 -0
  412. package/knowledge/stardewvalley/wiki.dataformat.yaml +130 -0
  413. package/knowledge/subnautica2/game.build.yaml +331 -0
  414. package/knowledge/subnautica2/modding.state.yaml +210 -0
  415. package/knowledge/subnautica2/ue5.containers.yaml +72 -0
  416. package/knowledge/subnautica2/ue5.paks.yaml +203 -0
  417. package/knowledge/subnautica2/ue5.tooling.yaml +175 -0
  418. package/knowledge/subnautica2/ue5.ue4ss.yaml +203 -0
  419. package/knowledge/valheim/bepinex.loader.yaml +247 -0
  420. package/knowledge/valheim/bepinex.plugins.yaml +251 -0
  421. package/knowledge/valheim/game.versions.yaml +321 -0
  422. package/knowledge/valheim/install.layout.yaml +216 -0
  423. package/knowledge/valheim/jotunn.library.yaml +334 -0
  424. package/knowledge/valheim/thunderstore.packaging.yaml +217 -0
  425. package/knowledge/valheim/toolchain.build.yaml +111 -0
  426. package/package.json +29 -0
  427. package/scaffolds/baldursgate3/new-class-injection.yaml +148 -0
  428. package/scaffolds/baldursgate3/new-item.yaml +264 -0
  429. package/scaffolds/baldursgate3/new-mod.yaml +174 -0
  430. package/scaffolds/baldursgate3/new-passive.yaml +100 -0
  431. package/scaffolds/baldursgate3/new-project.yaml +118 -0
  432. package/scaffolds/baldursgate3/new-quest-stub.yaml +159 -0
  433. package/scaffolds/baldursgate3/new-spell.yaml +102 -0
  434. package/scaffolds/baldursgate3/new-status.yaml +119 -0
  435. package/scaffolds/baldursgate3/sequences/subclass-kit.yaml +50 -0
  436. package/scaffolds/cyberpunk2077/edit-tweak.yaml +70 -0
  437. package/scaffolds/cyberpunk2077/mesh-export-preset.yaml +170 -0
  438. package/scaffolds/cyberpunk2077/new-entity-patch.yaml +255 -0
  439. package/scaffolds/cyberpunk2077/new-garment-refit.yaml +279 -0
  440. package/scaffolds/cyberpunk2077/new-item-chain.yaml +548 -0
  441. package/scaffolds/cyberpunk2077/new-localization.yaml +130 -0
  442. package/scaffolds/cyberpunk2077/new-mod-settings.yaml +133 -0
  443. package/scaffolds/cyberpunk2077/new-player-replacer.yaml +1003 -0
  444. package/scaffolds/cyberpunk2077/new-project.yaml +157 -0
  445. package/scaffolds/cyberpunk2077/new-sector-node.yaml +156 -0
  446. package/scaffolds/cyberpunk2077/new-tweak.yaml +121 -0
  447. package/scaffolds/cyberpunk2077/new-vehicle-livery.yaml +148 -0
  448. package/scaffolds/cyberpunk2077/new-workspot-entity.yaml +177 -0
  449. package/scaffolds/cyberpunk2077/sequences/iconic-weapon.yaml +72 -0
  450. package/scaffolds/cyberpunk2077/sequences/quickhack-takeover.yaml +213 -0
  451. package/scaffolds/stardewvalley/new-cp-patch.yaml +106 -0
  452. package/scaffolds/stardewvalley/new-csharp-mod.yaml +195 -0
  453. package/scaffolds/stardewvalley/new-project.yaml +184 -0
  454. package/scaffolds/stardewvalley/sequences/content-pack.yaml +31 -0
  455. package/scripts/mw-tool.mjs +184 -0
@@ -0,0 +1,264 @@
1
+ # new-item (BG3, armor/weapon). Writes the stat -> RootTemplate -> VisualBank
2
+ # triangle: a stats entry that `using`s a
3
+ # vanilla parent, a RootTemplate GameObjects node with a fresh MapKey, a
4
+ # TreasureTable row, and DisplayName/Description loca rows.
5
+ #
6
+ # Design note: this
7
+ # scaffold REUSES an existing (project or vanilla) VisualBank Resource id
8
+ # directly — RootTemplate's VisualTemplate points straight at the id the
9
+ # author names — rather than writing a *new* VisualBank/MaterialBank/
10
+ # TextureBank Resource chain of its own. Two reasons: the vanilla index's `guid` query
11
+ # answers only a Resource node's own top-level attributes (`ID`, `Name`),
12
+ # never its `Objects`/`Texture2DParameters` children (those node ids are not
13
+ # in `INDEXED_NODE_IDS` — see build.ts), so a chosen visual's own MaterialID
14
+ # cannot be read back through the index to build a faithful copy; and LSX has
15
+ # no "insert a child node into an existing region's children" emit op in this
16
+ # engine (only line-oriented text, loca and CR2W-json have dedicated insert
17
+ # ops). Recoloring — writing a mod-owned bank chain and repointing
18
+ # VisualTemplate at it — is the manual, optional creative step ("recolor art, optional").
19
+ #
20
+ # Observed in game: a loose `.lsx` under `Public/<Mod>/RootTemplates` is never
21
+ # loaded by the game — `Ext.Template.GetTemplate` and `Osi.CreateAt` both
22
+ # returned nothing for it live, while the identical node converted to a
23
+ # `.lsf` of its own name (beside `_merged.lsf`, not merged into it) loaded,
24
+ # resolved and spawned (knowledge fact
25
+ # bg3.items.roottemplates.loose-lsx-in-roottemplates-is-not-loaded-a-separate-lsf-is).
26
+ # The one-RootTemplate-per-file choice above still stands — only the file
27
+ # *type* this scaffold shipped was wrong. Fixed by the `patch-project` emit
28
+ # below, which ensures a `divine-lsx-to-lsf` build step exists (idempotent —
29
+ # reapplying this scaffold never adds a second one) covering
30
+ # `Public/**/RootTemplates/*.lsx`, with `deleteSource: true` and positioned
31
+ # before `divine-create-package` (`engine.ts`'s `before:` convention) so the
32
+ # item's own written `.lsx` reaches the pak as a `.lsf` and the stale `.lsx`
33
+ # does not reach it at all. The narrow glob matters: only `RootTemplates` is
34
+ # affected, and the rest of `Public/<Mod>` (Lists, Progressions,
35
+ # ClassDescriptions, GUI atlases) keeps shipping as the `.lsx` the game
36
+ # reads.
37
+ id: baldursgate3.new-item
38
+ game: baldursgate3
39
+ title: New BG3 item (armor/weapon with a visual bank)
40
+ summary: Append an Armor/Weapon stats entry with a vanilla `using` parent, a RootTemplate reusing an existing VisualBank visual, a TreasureTable row, and loca rows.
41
+ modTypes: [armor, weapon, accessory]
42
+ needs: { index: true }
43
+ inputs:
44
+ - type: string
45
+ name: itemName
46
+ prompt: "Full stats entry name, e.g. HWV_TestBreastplate."
47
+ pattern: "^[A-Za-z][A-Za-z0-9_]*$"
48
+ - type: enum
49
+ name: entryKind
50
+ prompt: "Stats file this entry belongs in (also its `type`)."
51
+ values: [Armor, Weapon]
52
+ - type: string
53
+ name: slot
54
+ prompt: "data \"Slot\" value, e.g. Breast, Shield, Melee Main Weapon."
55
+ - type: index-ref
56
+ name: parentStat
57
+ prompt: "Vanilla (or project) Armor/Weapon entry to `using`."
58
+ lookup: { kind: stat, params: { name: "${input.parentStat}" } }
59
+ requires:
60
+ - path: type
61
+ matches: "^(Armor|Weapon)$"
62
+ reason: "the parent must be an Armor or Weapon entry, or `using` inherits fields from the wrong stat family."
63
+ # Observed in game (2026-09-11): a GameObjects node carrying
64
+ # only MapKey/Name/VisualTemplate reached the pak as an .lsf and the
65
+ # engine still did not load it (`Ext.Template.GetTemplate` nil,
66
+ # `bg3.template.exists` fail), while every template the engine has been
67
+ # seen to load — the vanilla dagger, the 2026-09-10 chest repro, the
68
+ # summoned-weapon recipe — carries Type, Stats and a ParentTemplateId.
69
+ # The parent stat's own RootTemplate becomes this template's
70
+ # ParentTemplateId, so the item inherits physics, equipment type and
71
+ # icon handling from the vanilla template its stats already `using`.
72
+ - path: fields.RootTemplate
73
+ matches: "^[0-9a-fA-F-]{36}$"
74
+ reason: "the parent must carry its own RootTemplate (a UUID) — it becomes the new template's ParentTemplateId, which the engine needs to load the node at all."
75
+ expose: parentRootTemplate
76
+ - type: index-ref
77
+ name: visualBankId
78
+ prompt: "Existing (project or vanilla) VisualBank Resource ID this item's RootTemplate should reuse."
79
+ lookup: { kind: guid, params: { uuid: "${input.visualBankId}" } }
80
+ requires:
81
+ - path: kind
82
+ matches: "^Resource$"
83
+ reason: "the given UUID must resolve to a Resource node, or the RootTemplate's VisualTemplate would point at a non-visual LSX node."
84
+ - path: region
85
+ matches: "^VisualBank$"
86
+ reason: "the given UUID must be a VisualBank Resource (region VisualBank), not a MaterialBank/TextureBank one, or the RootTemplate's VisualTemplate would point at the wrong bank kind."
87
+ - type: string
88
+ name: displayName
89
+ prompt: "Player-facing item name."
90
+ - type: string
91
+ name: description
92
+ prompt: "Tooltip description text."
93
+ ids:
94
+ - name: rootTemplateUuid
95
+ slot: "roottemplate:${input.itemName}"
96
+ form: uuid
97
+ collision:
98
+ project: true
99
+ index: { kind: guid, param: uuid }
100
+ - name: display
101
+ slot: "display:${input.itemName}"
102
+ form: bg3-handle
103
+ - name: description
104
+ slot: "description:${input.itemName}"
105
+ form: bg3-handle
106
+ # The same two handles without the `;1` suffix, for the RootTemplate's
107
+ # TranslatedString attributes (same slot => same digest => same loca row).
108
+ - name: displayHandle
109
+ slot: "display:${input.itemName}"
110
+ form: bg3-handle-bare
111
+ - name: descriptionHandle
112
+ slot: "description:${input.itemName}"
113
+ form: bg3-handle-bare
114
+ emits:
115
+ - op: ensure-dir
116
+ path: "Public/${project.identity.folder}/Stats/Generated/Data"
117
+ - op: ensure-dir
118
+ path: "Public/${project.identity.folder}/RootTemplates"
119
+ - op: insert-block
120
+ path: "Public/${project.identity.folder}/Stats/Generated/Data/${input.entryKind}.txt"
121
+ createIfMissing: "// ModWright-scaffolded ${input.entryKind} file.\n"
122
+ anchor: append
123
+ body: |
124
+ // ${project.today} - ModWright scaffold: ${input.itemName}, using parent ${input.parentStat}.
125
+ new entry "${input.itemName}"
126
+ type "${input.entryKind}"
127
+ using "${input.parentStat}"
128
+ data "RootTemplate" "${ids.rootTemplateUuid}"
129
+ data "Slot" "${input.slot}"
130
+ # One RootTemplate per file (not a shared _merged.lsx) sidesteps the
131
+ # missing "insert into an existing LSX region" op — see this file's header.
132
+ - op: write-text
133
+ path: "Public/${project.identity.folder}/RootTemplates/${input.itemName}.lsx"
134
+ body: |
135
+ <?xml version="1.0" encoding="UTF-8"?>
136
+ <save>
137
+ <version major="4" minor="8" revision="0" build="10"/>
138
+ <region id="Templates">
139
+ <node id="Templates">
140
+ <children>
141
+ <node id="GameObjects">
142
+ <attribute id="MapKey" type="FixedString" value="${ids.rootTemplateUuid}"/>
143
+ <attribute id="Name" type="LSString" value="${input.itemName}"/>
144
+ <attribute id="Type" type="FixedString" value="item"/>
145
+ <attribute id="ParentTemplateId" type="FixedString" value="${template.parentRootTemplate}"/>
146
+ <attribute id="Stats" type="FixedString" value="${input.itemName}"/>
147
+ <attribute id="VisualTemplate" type="FixedString" value="${input.visualBankId}"/>
148
+ <attribute id="Icon" type="FixedString" value="${input.itemName}_Icon"/>
149
+ <attribute id="DisplayName" type="TranslatedString" handle="${ids.displayHandle}" version="1"/>
150
+ <attribute id="Description" type="TranslatedString" handle="${ids.descriptionHandle}" version="1"/>
151
+ </node>
152
+ </children>
153
+ </node>
154
+ </region>
155
+ </save>
156
+ # Ensures the pak's build actually converts RootTemplates .lsx -> .lsf
157
+ # (this file's header note above); idempotent (`engine.ts`'s
158
+ # `mergeBuildSteps`), so scaffolding a second item never adds a second
159
+ # copy of this step, and `before` lands it ahead of
160
+ # `divine-create-package` (or a bare-string shorthand that expands to it,
161
+ # e.g. "pack-pak") whichever form the project's build
162
+ # already uses.
163
+ #
164
+ # `in: "${stage}"` is the *whole* stage root, not one stage id's own
165
+ # subtree (core/build/paths.ts's own header comment: `in` on this step
166
+ # normally names a bare stage id, resolved as `${stage}/<id>`; the bare
167
+ # `${stage}` token alone resolves to the stage root with no id segment at
168
+ # all) — deliberate, because a `patch-project` addition is static YAML and
169
+ # cannot know which id the project's own `stage` step happens to use
170
+ # (a real project may use "pack"; the schemaVersion-1 shorthand
171
+ # uses "stage"). `walk()` (core/fsutil.ts) recurses the whole tree either
172
+ # way, so the glob below is written `**/Public/**/...` — tolerant of
173
+ # whatever stage-id segment precedes `Public/` in the staged copy — rather
174
+ # than anchored to `Public/` the way a per-id `in` value could afford to
175
+ # be.
176
+ #
177
+ # `deleteSource: true` is set here and nowhere else. The step's own default
178
+ # is false (it converts in place, as it always has), because its default
179
+ # glob is the whole-stage `**/*.lsx` and every other `Public/<Mod>` folder's
180
+ # `.lsx` — Lists, Progressions, ClassDescriptions, GUI atlases — is read by
181
+ # the game as `.lsx`. This step's glob is narrowed to `RootTemplates`, the
182
+ # one folder where the loose `.lsx` is dead weight, so removing the staged
183
+ # copy matches exactly the configuration verified in game (convert,
184
+ # remove the `.lsx`, rebuild) and keeps the stale copy out of the pak.
185
+ - op: patch-project
186
+ add:
187
+ steps:
188
+ - step: divine-lsx-to-lsf
189
+ id: roottemplates-lsx-to-lsf
190
+ in: "${stage}"
191
+ glob: "**/Public/**/RootTemplates/*.lsx"
192
+ deleteSource: true
193
+ before: divine-create-package
194
+ - op: insert-block
195
+ path: "Public/${project.identity.folder}/Stats/Generated/TreasureTable.txt"
196
+ createIfMissing: "// ModWright TreasureTable, ModWright-scaffolded.\n"
197
+ anchor: append
198
+ body: |
199
+ new treasuretable "${project.identity.folder}_Treasure"
200
+ CanMerge 1
201
+ object category "I_${input.itemName}",1,0,0,0,0,0,0,0
202
+ - op: insert-loca-row
203
+ path: "Mods/${project.identity.folder}/Localization/English/${project.identity.folder}.xml"
204
+ handle: "${ids.display}"
205
+ text: "${input.displayName}"
206
+ - op: insert-loca-row
207
+ path: "Mods/${project.identity.folder}/Localization/English/${project.identity.folder}.xml"
208
+ handle: "${ids.description}"
209
+ text: "${input.description}"
210
+ templates: []
211
+ satisfies:
212
+ - bg3.items.stats-roottemplate-link
213
+ - bg3.items.roottemplate-visual-link
214
+ - bg3.items.visual-material-texture-chain
215
+ - bg3.items.parenttemplateid-type-match
216
+ - bg3.items.armor-weapon-fields
217
+ - bg3.items.treasuretable-i-prefix
218
+ - bg3.items.icon-mapkey-resolves
219
+ - bg3.items.dds-extension-case
220
+ - bg3.items.texturebank-srgb
221
+ - bg3.items.roottemplate-guid-attribute-type
222
+ - bg3.history.handle-form-per-field
223
+ - bg3.history.handle-defined-in-loca
224
+ manual:
225
+ - title: Icon, visual and (for a Weapon) proficiency fields
226
+ steps:
227
+ - "Draw the ${input.itemName}_Icon art and register it in the item atlas (bg3.items.icon-mapkey-resolves warns until then)."
228
+ - "For a Weapon entry (this one is ${input.entryKind}), also add data \"Proficiency Group\" and data \"Weapon Properties\" to the new entry (bg3.items.armor-weapon-fields warns without them; there is no new base weapon type, so fake one by combining an existing group with Weapon Properties)."
229
+ - "To give ${input.itemName} its own recolor instead of reusing VisualBank ${input.visualBankId}'s appearance, add a mod-owned VisualBank/MaterialBank/TextureBank Resource chain under Content/Assets/Characters and repoint this RootTemplate's VisualTemplate at your new VisualBank ID."
230
+ expected: "The item spawns with a real icon, its own visual (recolored or reused), and (if a Weapon) a valid proficiency/properties pair."
231
+ claim:
232
+ idSuffix: spawns-with-stats
233
+ claim: "${input.itemName} (using parent ${input.parentStat}) spawns with stats from its RootTemplate, a visible visual reused from VisualBank ${input.visualBankId}, and a treasure-table entry."
234
+ testRows:
235
+ - gate: S-1
236
+ title: "Stat entry loads with expected fields"
237
+ expected: "bg3.stat.exists finds ${input.itemName}; bg3.stat.fields confirms RootTemplate/Slot match this scaffold's output (an Armor/Weapon stats object has no DisplayName/Description attribute — observed in game 2026-09-11; those live on the RootTemplate)."
238
+ manual: false
239
+ probes:
240
+ - kind: bg3.stat.exists
241
+ params: { name: "${input.itemName}" }
242
+ - kind: bg3.stat.fields
243
+ params: { name: "${input.itemName}", fields: [RootTemplate, Slot] }
244
+ # A separate row, not a third probe on S-1. The kind is attested (its own
245
+ # bridge run, 2026-09-10), so the row is automated, but
246
+ # it stays its own row because bg3.stat.exists alone cannot tell a real
247
+ # RootTemplate from a loose, engine-ignored `.lsx` (this file's header
248
+ # note) and a template verdict should not drag the stats verdict down with
249
+ # it — exactly what was observed in game (2026-09-11): this row failed
250
+ # (`present: false`) while bg3.stat.exists passed on the same item.
251
+ - gate: S-1.1
252
+ title: "RootTemplate resolves in the engine"
253
+ expected: "bg3.template.exists confirms Ext.Template.GetTemplate(\"${ids.rootTemplateUuid}\") returns the template (present: true, name ${input.itemName}), not nil — a bg3.stat.exists pass alone does not prove the template this scaffold wrote actually reached the engine (it does not, unless the divine-lsx-to-lsf step this scaffold adds converts it)."
254
+ manual: false
255
+ probes:
256
+ - kind: bg3.template.exists
257
+ params:
258
+ mapKey: "${ids.rootTemplateUuid}"
259
+ - gate: S-2
260
+ title: "Visual renders, not the default fallback"
261
+ expected: "A human confirms TemplateAddTo/spawn shows the reused VisualBank ${input.visualBankId} visual, not the invisible/default fallback, and the icon/tooltip render."
262
+ manual: true
263
+ probeKinds: []
264
+ evidence: ["ModWright research"]
@@ -0,0 +1,174 @@
1
+ # new-mod (BG3). Writes the
2
+ # standard skeleton: meta.lsx, ScriptExtender/Config.json,
3
+ # Localization/English/<Mod>.xml, and the Public/<Mod> subtree every stats/
4
+ # progression/item scaffold expects to already exist. Version64 is derived
5
+ # from the project's own declared version (project.version64, computed by
6
+ # the engine — see engine.ts's computeVersion64), not re-specified here, so
7
+ # meta.lsx and modwright.json never disagree on major/minor/revision.
8
+ id: baldursgate3.new-mod
9
+ game: baldursgate3
10
+ title: New BG3 mod (meta.lsx, Config.json, Localization)
11
+ summary: Write meta.lsx, ScriptExtender/Config.json and an empty Localization/English/<Mod>.xml, plus the Public/<Mod> subtree, and declare the BG3 Script Extender dependency.
12
+ modTypes: [packaging]
13
+ needs: {}
14
+ inputs:
15
+ - type: string
16
+ name: folder
17
+ prompt: Module folder name (Mods/<folder>, Public/<folder>).
18
+ pattern: "^[A-Za-z][A-Za-z0-9_]*$"
19
+ - type: string
20
+ name: displayName
21
+ prompt: Display name shown in the in-game mod manager.
22
+ - type: string
23
+ name: author
24
+ prompt: Author name.
25
+ default: "Unknown"
26
+ - type: string
27
+ name: description
28
+ prompt: One-line mod description.
29
+ default: ""
30
+ - type: string
31
+ name: tags
32
+ prompt: Comma-separated Larian tag(s), e.g. "Class".
33
+ default: "Adventure"
34
+ ids:
35
+ - name: moduleUuid
36
+ slot: "module-uuid:${input.folder}"
37
+ form: uuid
38
+ collision:
39
+ project: true
40
+ loadOrder: true
41
+ index: { kind: guid, param: uuid }
42
+ emits:
43
+ - op: ensure-dir
44
+ path: "Mods/${input.folder}/ScriptExtender"
45
+ - op: ensure-dir
46
+ path: "Mods/${input.folder}/Localization/English"
47
+ - op: ensure-dir
48
+ path: "Public/${input.folder}/ActionResourceDefinitions"
49
+ - op: ensure-dir
50
+ path: "Public/${input.folder}/ClassDescriptions"
51
+ - op: ensure-dir
52
+ path: "Public/${input.folder}/Lists"
53
+ - op: ensure-dir
54
+ path: "Public/${input.folder}/Progressions"
55
+ - op: ensure-dir
56
+ path: "Public/${input.folder}/RootTemplates"
57
+ - op: ensure-dir
58
+ path: "Public/${input.folder}/Stats/Generated/Data"
59
+ - op: ensure-dir
60
+ path: "Public/${input.folder}/Tags"
61
+ - op: ensure-dir
62
+ path: "Public/${input.folder}/GUI"
63
+ # meta.lsx: BOM (bg3.history.no-bom exempts it by name — Larian's own
64
+ # Toolkit writes one), Version64 from the project's own declared version.
65
+ - op: write-text
66
+ path: "Mods/${input.folder}/meta.lsx"
67
+ bom: true
68
+ body: |
69
+ <?xml version="1.0" encoding="utf-8"?>
70
+ <save>
71
+ <version major="4" minor="8" revision="0" build="500" />
72
+ <region id="Config">
73
+ <node id="root">
74
+ <children>
75
+ <node id="Conflicts" />
76
+ <node id="Dependencies" />
77
+ <node id="ModuleInfo">
78
+ <attribute id="Author" type="LSString" value="${input.author}" />
79
+ <attribute id="CharacterCreationLevelName" type="FixedString" value="" />
80
+ <attribute id="Description" type="LSString" value="${input.description}" />
81
+ <attribute id="FileSize" type="uint64" value="0" />
82
+ <attribute id="Folder" type="LSString" value="${input.folder}" />
83
+ <attribute id="LobbyLevelName" type="FixedString" value="" />
84
+ <attribute id="MD5" type="LSString" value="" />
85
+ <attribute id="MainMenuBackgroundVideo" type="FixedString" value="" />
86
+ <attribute id="MenuLevelName" type="FixedString" value="" />
87
+ <attribute id="Name" type="FixedString" value="${input.displayName}" />
88
+ <attribute id="NumPlayers" type="uint8" value="4" />
89
+ <attribute id="PhotoBooth" type="FixedString" value="" />
90
+ <attribute id="PublishHandle" type="uint64" value="0" />
91
+ <attribute id="StartupLevelName" type="FixedString" value="" />
92
+ <attribute id="Tags" type="LSString" value="${input.tags}" />
93
+ <attribute id="Type" type="FixedString" value="Add-on" />
94
+ <attribute id="UUID" type="FixedString" value="${ids.moduleUuid}" />
95
+ <attribute id="Version64" type="int64" value="${project.version64}" />
96
+ <children>
97
+ <node id="PublishVersion">
98
+ <attribute id="Version64" type="int64" value="${project.version64}" />
99
+ </node>
100
+ <node id="Scripts" />
101
+ <node id="TargetModes">
102
+ <children>
103
+ <node id="Target">
104
+ <attribute id="Object" type="FixedString" value="Story" />
105
+ </node>
106
+ </children>
107
+ </node>
108
+ </children>
109
+ </node>
110
+ </children>
111
+ </node>
112
+ </region>
113
+ </save>
114
+ - op: write-text
115
+ path: "Mods/${input.folder}/ScriptExtender/Config.json"
116
+ body: |
117
+ {
118
+ "RequiredVersion": 21,
119
+ "ModTable": "${input.folder}",
120
+ "FeatureFlags": ["Lua"]
121
+ }
122
+ - op: write-text
123
+ path: "Mods/${input.folder}/Localization/English/${input.folder}.xml"
124
+ body: |
125
+ <?xml version="1.0" encoding="utf-8"?>
126
+ <contentList>
127
+ </contentList>
128
+ - op: insert-xl-entry
129
+ path: "modwright.json"
130
+ pointer: identity.uuid
131
+ value: "${ids.moduleUuid}"
132
+ - op: insert-xl-entry
133
+ path: "modwright.json"
134
+ pointer: identity.folder
135
+ value: "${input.folder}"
136
+ - op: patch-project
137
+ add:
138
+ dependencies:
139
+ - id: bg3-script-extender
140
+ kind: loader
141
+ minVersion: "21"
142
+ url: "https://github.com/Norbyte/bg3se"
143
+ notes: "RequiredVersion 21 pinned in ScriptExtender/Config.json."
144
+ templates: []
145
+ satisfies:
146
+ - bg3.progression.meta-version64
147
+ - bg3.history.no-bom
148
+ - bg3.history.se-config-shape
149
+ - bg3.history.stale-same-uuid-pak
150
+ - bg3.history.external-guid-load-order
151
+ - bg3.history.loca-no-xml-comments
152
+ manual:
153
+ - title: Add real content
154
+ steps:
155
+ - "Run new-spell/new-passive/new-status to fill Stats/Generated/Data."
156
+ - "Register the module in the game's modsettings.lsx load order once tested."
157
+ expected: "The module loads in-game and passes validate with no blocking findings."
158
+ claim:
159
+ idSuffix: mod-loads
160
+ claim: "${input.folder} (UUID ${ids.moduleUuid}) is a loadable BG3 module with a valid meta.lsx and Script Extender config."
161
+ testRows:
162
+ - gate: S-1
163
+ title: "Module enumerates and loads"
164
+ expected: "bg3.mod.active reports the module UUID loaded, matching the declared Version64."
165
+ manual: false
166
+ probes:
167
+ - kind: bg3.mod.active
168
+ params: { uuid: "${ids.moduleUuid}" }
169
+ - gate: S-2
170
+ title: "Menu enumeration"
171
+ expected: "The mod appears in the in-game mod manager under its display name."
172
+ manual: true
173
+ probeKinds: [bg3.client.loaded]
174
+ evidence: ["ModWright research"]
@@ -0,0 +1,100 @@
1
+ # new-passive (BG3). Same
2
+ # shape as new-spell, but PassiveData carries
3
+ # BoostContext including OnCreate, so the
4
+ # `bg3.history.boostcontext-initial-event` "initial-event" failure mode is
5
+ # a passive-specific concern, unlike SpellData.
6
+ id: baldursgate3.new-passive
7
+ game: baldursgate3
8
+ title: New BG3 passive (PassiveData entry)
9
+ summary: Append a PassiveData entry to Passive.txt with a vanilla `using` parent, BoostContext including OnCreate, and DisplayName/Description loca rows.
10
+ modTypes: [dialogue]
11
+ needs: { index: true }
12
+ inputs:
13
+ - type: string
14
+ name: entryName
15
+ prompt: "Full stats entry name, e.g. MyMod_QuickReflexes."
16
+ pattern: "^[A-Za-z][A-Za-z0-9_]*$"
17
+ - type: index-ref
18
+ name: parent
19
+ prompt: "Vanilla (or project) PassiveData entry to `using`."
20
+ lookup: { kind: stat, params: { name: "${input.parent}" } }
21
+ requires:
22
+ - path: type
23
+ matches: "^PassiveData$"
24
+ reason: "the parent must be a PassiveData entry, or `using` inherits fields from the wrong stat family."
25
+ - type: string
26
+ name: displayName
27
+ prompt: "Player-facing passive name."
28
+ - type: string
29
+ name: description
30
+ prompt: "Tooltip description text."
31
+ - type: string
32
+ name: boosts
33
+ prompt: "Boosts string (semicolon-separated boost functors), or leave blank for a display-only passive."
34
+ default: ""
35
+ ids:
36
+ - name: display
37
+ slot: "display:${input.entryName}"
38
+ form: bg3-handle
39
+ - name: description
40
+ slot: "description:${input.entryName}"
41
+ form: bg3-handle
42
+ emits:
43
+ - op: insert-block
44
+ path: "Public/${project.identity.folder}/Stats/Generated/Data/Passive.txt"
45
+ createIfMissing: "// ModWright-scaffolded passive file.\n"
46
+ anchor: append
47
+ body: |
48
+ // ${project.today} - ModWright scaffold: ${input.entryName}, using parent ${input.parent}.
49
+ new entry "${input.entryName}"
50
+ type "PassiveData"
51
+ using "${input.parent}"
52
+ data "Icon" "${input.entryName}_Icon"
53
+ data "DisplayName" "${ids.display}"
54
+ data "Description" "${ids.description}"
55
+ data "Boosts" "${input.boosts}"
56
+ data "BoostContext" "OnCreate"
57
+ - op: insert-loca-row
58
+ path: "Mods/${project.identity.folder}/Localization/English/${project.identity.folder}.xml"
59
+ handle: "${ids.display}"
60
+ text: "${input.displayName}"
61
+ - op: insert-loca-row
62
+ path: "Mods/${project.identity.folder}/Localization/English/${project.identity.folder}.xml"
63
+ handle: "${ids.description}"
64
+ text: "${input.description}"
65
+ templates: []
66
+ satisfies:
67
+ - bg3.history.spellanimation-present
68
+ - bg3.history.boostcontext-initial-event
69
+ - bg3.history.context-qualifier-validity
70
+ - bg3.history.reference-integrity
71
+ - bg3.history.handle-form-per-field
72
+ - bg3.history.handle-defined-in-loca
73
+ - bg3.history.islinkedspellcontainer-links
74
+ - bg3.history.spellid-enumeration-drift
75
+ - bg3.history.loca-no-xml-comments
76
+ manual:
77
+ - title: Icon and progression
78
+ steps:
79
+ - "Draw the ${input.entryName}_Icon art and register it in the spell atlas."
80
+ - "Grant ${input.entryName} via a Progression's PassivesAdded if it should be automatic."
81
+ expected: "The passive shows a real icon and its boost is observable in-game."
82
+ claim:
83
+ idSuffix: applies
84
+ claim: "${input.entryName} applies its boost(s) once granted, inheriting fields from ${input.parent}."
85
+ testRows:
86
+ - gate: S-1
87
+ title: "Stat entry loads with expected fields"
88
+ expected: "bg3.stat.exists finds ${input.entryName}; bg3.stat.fields confirms BoostContext/Boosts/DisplayName/Description."
89
+ manual: false
90
+ probes:
91
+ - kind: bg3.stat.exists
92
+ params: { name: "${input.entryName}" }
93
+ - kind: bg3.stat.fields
94
+ params: { name: "${input.entryName}", fields: [BoostContext, Boosts, DisplayName, Description] }
95
+ - gate: S-2
96
+ title: "Icon and tooltip render"
97
+ expected: "The passive's card shows the drawn icon and correct tooltip text in-game."
98
+ manual: true
99
+ probeKinds: []
100
+ evidence: ["ModWright research"]
@@ -0,0 +1,118 @@
1
+ # new-project (Baldur's Gate 3).
2
+ # The one scaffold that runs before a modwright.json exists: writes the
3
+ # skeleton every other BG3 scaffold assumes (the two source trees, the v2
4
+ # project file, ledger/decisions.yaml). tests/authored.yaml and
5
+ # ledger/claims.yaml are written by the engine's own automatic per-apply
6
+ # steps, not by an emit here.
7
+ id: baldursgate3.new-project
8
+ game: baldursgate3
9
+ title: New BG3 mod project
10
+ summary: Scaffold a fresh ModWright project for a Baldur's Gate 3 mod — modwright.json (schemaVersion 2), the Mods/Public source trees, .gitignore, and ledger/decisions.yaml.
11
+ modTypes: [packaging]
12
+ needs: {}
13
+ inputs:
14
+ - type: string
15
+ name: name
16
+ prompt: Mod name (also used as the Mods/<name> and Public/<name> folder name).
17
+ pattern: "^[A-Za-z][A-Za-z0-9_]*$"
18
+ - type: string
19
+ name: version
20
+ prompt: Initial version (semver-ish, major.minor.revision).
21
+ default: "0.1.0"
22
+ - type: string
23
+ name: author
24
+ prompt: Author name.
25
+ default: "Unknown"
26
+ # A project can keep its
27
+ # LSLib divine path as a toolchain override in modwright.json; a fresh
28
+ # project on the same machine needs the same line or its first build
29
+ # cannot find the tool. Empty means "the locator's own candidates" and
30
+ # writes nothing.
31
+ - type: string
32
+ name: divine
33
+ prompt: "Absolute path to LSLib's Divine.exe when it is not where check_toolchain looks (written as the project's toolchain override; leave empty to rely on the locator)."
34
+ default: ""
35
+ ids:
36
+ - name: moduleUuid
37
+ slot: "module-uuid:${input.name}"
38
+ form: uuid
39
+ collision:
40
+ project: true
41
+ index: { kind: guid, param: uuid }
42
+ emits:
43
+ - op: ensure-dir
44
+ path: "Mods/${input.name}"
45
+ - op: ensure-dir
46
+ path: "Public/${input.name}/Stats/Generated/Data"
47
+ - op: ensure-dir
48
+ path: "Public/${input.name}/Localization/English"
49
+ - op: write-text
50
+ path: ".gitignore"
51
+ ifExists: skip
52
+ # Two files under .modwright are worth tracking, so a reviewer
53
+ # reads them in a clean checkout: suppressions.json and
54
+ # templates/manifest.json. A bare `.modwright/` hides both (a
55
+ # hand-written ignore often un-hides only the first). git cannot re-include
56
+ # a file inside an ignored directory, so the templates folder is
57
+ # re-included and its other contents ignored again.
58
+ body: |
59
+ .modwright/*
60
+ !.modwright/suppressions.json
61
+ !.modwright/templates/
62
+ .modwright/templates/*
63
+ !.modwright/templates/manifest.json
64
+ build/
65
+ *.pak
66
+ .modwright-build-manifest.json
67
+ - op: write-text
68
+ path: "ledger/decisions.yaml"
69
+ body: |
70
+ decisions: []
71
+ - op: write-text
72
+ path: "modwright.json"
73
+ body: |
74
+ {
75
+ "schemaVersion": 2,
76
+ "name": "${input.name}",
77
+ "game": "baldursgate3",
78
+ "version": "${input.version}",
79
+ "authors": ["${input.author}"],
80
+ "identity": {
81
+ "uuid": "${ids.moduleUuid}",
82
+ "folder": "${input.name}"
83
+ },
84
+ "sources": [
85
+ { "id": "mods", "path": "Mods/${input.name}", "kind": "mods" },
86
+ { "id": "public", "path": "Public/${input.name}", "kind": "public" }
87
+ ]
88
+ }
89
+ # The LSLib divine override, written the way a project keeps
90
+ # its own; the engine merges it into the modwright.json written just above, and an
91
+ # empty input adds no key at all.
92
+ - op: patch-project
93
+ add:
94
+ toolchain:
95
+ divine: "${input.divine}"
96
+ templates: []
97
+ # Nothing is satisfied directly: the one real postcondition is that
98
+ # validate reports no *unmet-needs* skip among project-only rules. A
99
+ # project-target rule with needs:{project:true} always evaluates (the
100
+ # {kind:"project"} target always exists), so this trivially "ran" with zero
101
+ # findings against the still-empty source trees.
102
+ satisfies: [bg3.progression.meta-version64]
103
+ manual:
104
+ - title: Populate the mod
105
+ steps:
106
+ - "Add real content under Mods/<name> (meta.lsx, ScriptExtender, Localization) and Public/<name> (Stats, RootTemplates)."
107
+ - "Run the new-mod scaffold next to fill in meta.lsx and ScriptExtender/Config.json."
108
+ expected: "validate reports the project's own structural rules clean once real content exists."
109
+ claim:
110
+ idSuffix: scaffolded
111
+ claim: "${input.name} is scaffolded as a ModWright project with a schemaVersion 2 modwright.json and a fresh module UUID."
112
+ testRows:
113
+ - gate: S-0
114
+ title: "Project loads"
115
+ expected: "validate loads modwright.json with no schema errors and no unmet-needs skip among project-only rules."
116
+ manual: true
117
+ probeKinds: []
118
+ evidence: ["ModWright research"]