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,327 @@
1
+ const DEFAULT_LIMIT = 50;
2
+ const MAX_USING_DEPTH = 10;
3
+ function str(v) {
4
+ if (v === undefined)
5
+ return undefined;
6
+ const s = String(v).trim();
7
+ return s.length > 0 ? s : undefined;
8
+ }
9
+ function limitOf(params) {
10
+ const n = Number(params.limit);
11
+ return Number.isFinite(n) && n > 0 ? Math.floor(n) : DEFAULT_LIMIT;
12
+ }
13
+ function page(rows, limit) {
14
+ if (rows.length > limit)
15
+ return { rows: rows.slice(0, limit), truncated: true };
16
+ return { rows, truncated: false };
17
+ }
18
+ function result(kind, params, rows, truncated, note) {
19
+ return { kind, params, count: rows.length, truncated, rows, note };
20
+ }
21
+ function parseAttrsJson(raw) {
22
+ try {
23
+ return JSON.parse(String(raw));
24
+ }
25
+ catch {
26
+ return {};
27
+ }
28
+ }
29
+ function fieldsForStat(store, statId) {
30
+ const fields = {};
31
+ for (const row of store.all(`SELECT field, value FROM stat_field WHERE stat_id = ? ORDER BY field`, [statId])) {
32
+ fields[String(row.field)] = String(row.value);
33
+ }
34
+ return fields;
35
+ }
36
+ function usingChainFor(store, startUsing) {
37
+ const chain = [];
38
+ const seen = new Set();
39
+ let current = startUsing;
40
+ let depth = 0;
41
+ while (current && depth < MAX_USING_DEPTH && !seen.has(current)) {
42
+ seen.add(current);
43
+ const row = store.get(`SELECT name, type, "using" AS parent FROM stat WHERE name = ? LIMIT 1`, [current]);
44
+ if (!row)
45
+ break;
46
+ chain.push({ name: String(row.name), type: String(row.type) });
47
+ current = row.parent === null || row.parent === undefined ? undefined : String(row.parent);
48
+ depth++;
49
+ }
50
+ return chain;
51
+ }
52
+ function queryStat(store, params) {
53
+ const name = str(params.name);
54
+ const prefix = str(params.prefix);
55
+ const type = str(params.type);
56
+ const limit = limitOf(params);
57
+ if (!name && !prefix) {
58
+ return result("stat", params, [], false, "No 'name' or 'prefix' given; nothing searched.");
59
+ }
60
+ let sql = `SELECT id, name, type, "using" AS parent, source_id, file, line FROM stat WHERE `;
61
+ const args = [];
62
+ if (name) {
63
+ sql += `name = ?`;
64
+ args.push(name);
65
+ }
66
+ else {
67
+ sql += `name LIKE ?`;
68
+ args.push(`${prefix}%`);
69
+ }
70
+ if (type) {
71
+ sql += ` AND type = ?`;
72
+ args.push(type);
73
+ }
74
+ sql += ` ORDER BY name LIMIT ?`;
75
+ args.push(limit + 1);
76
+ const rows = store.all(sql, args);
77
+ const { rows: pageRows, truncated } = page(rows, limit);
78
+ const mapped = pageRows.map((row) => {
79
+ const id = Number(row.id);
80
+ const parent = row.parent === null || row.parent === undefined ? undefined : String(row.parent);
81
+ return {
82
+ name: row.name,
83
+ type: row.type,
84
+ using: parent ?? null,
85
+ usingChain: usingChainFor(store, parent),
86
+ fields: fieldsForStat(store, id),
87
+ source: row.source_id,
88
+ file: row.file,
89
+ line: row.line,
90
+ };
91
+ });
92
+ const how = name ? `exact name '${name}'` : `name prefix '${prefix}'`;
93
+ const note = `Searched stat entries by ${how}${type ? ` filtered to type '${type}'` : ""}.`;
94
+ return result("stat", params, mapped, truncated, note);
95
+ }
96
+ function queryField(store, params) {
97
+ const field = str(params.field);
98
+ if (!field)
99
+ return result("field", params, [], false, "No 'field' given; nothing searched.");
100
+ const type = str(params.type);
101
+ const limit = limitOf(params);
102
+ let sql = `SELECT sf.value AS value, COUNT(*) AS n FROM stat_field sf`;
103
+ const args = [];
104
+ if (type) {
105
+ sql += ` JOIN stat s ON s.id = sf.stat_id WHERE sf.field = ? AND s.type = ?`;
106
+ args.push(field, type);
107
+ }
108
+ else {
109
+ sql += ` WHERE sf.field = ?`;
110
+ args.push(field);
111
+ }
112
+ sql += ` GROUP BY sf.value ORDER BY n DESC, sf.value LIMIT ?`;
113
+ args.push(limit + 1);
114
+ const rows = store.all(sql, args);
115
+ const { rows: pageRows, truncated } = page(rows, limit);
116
+ const mapped = pageRows.map((row) => ({ value: row.value, count: Number(row.n) }));
117
+ const note = `Searched values of field '${field}'${type ? ` on type '${type}'` : ""} across all indexed stats.`;
118
+ return result("field", params, mapped, truncated, note);
119
+ }
120
+ function queryPrecedent(store, params) {
121
+ const field = str(params.field);
122
+ const token = str(params.token);
123
+ if (!field || !token) {
124
+ return result("precedent", params, [], false, "Both 'field' and 'token' are required; nothing searched.");
125
+ }
126
+ const type = str(params.type);
127
+ const contextField = str(params.contextField);
128
+ const contextToken = str(params.contextToken);
129
+ const limit = limitOf(params);
130
+ let sql = `SELECT s.name AS name, s.type AS type, sf.value AS value
131
+ FROM stat_field sf JOIN stat s ON s.id = sf.stat_id
132
+ WHERE sf.field = ? AND sf.value LIKE ?`;
133
+ const args = [field, `%${token}%`];
134
+ if (type) {
135
+ sql += ` AND s.type = ?`;
136
+ args.push(type);
137
+ }
138
+ if (contextField && contextToken) {
139
+ sql += ` AND EXISTS (SELECT 1 FROM stat_field cf WHERE cf.stat_id = s.id AND cf.field = ? AND cf.value LIKE ?)`;
140
+ args.push(contextField, `%${contextToken}%`);
141
+ }
142
+ sql += ` ORDER BY s.name LIMIT ?`;
143
+ args.push(limit + 1);
144
+ const rows = store.all(sql, args);
145
+ const { rows: pageRows, truncated } = page(rows, limit);
146
+ const mapped = pageRows.map((row) => ({ name: row.name, type: row.type, field, value: row.value }));
147
+ const contextNote = contextField && contextToken ? ` where '${contextField}' also contains '${contextToken}'` : "";
148
+ const note = `Vanilla precedent census: stats whose '${field}' contains '${token}'${contextNote}${type ? ` (type '${type}')` : ""}.`;
149
+ return result("precedent", params, mapped, truncated, note);
150
+ }
151
+ function queryGuid(store, params) {
152
+ const uuid = str(params.uuid);
153
+ const name = str(params.name);
154
+ if (!uuid && !name) {
155
+ return result("guid", params, [], false, "No 'uuid' or 'name' given; nothing searched.");
156
+ }
157
+ const limit = limitOf(params);
158
+ let sql = `SELECT source_id, file, region, node_id, path, uuid, name, attrs_json FROM node WHERE `;
159
+ const args = [];
160
+ if (uuid) {
161
+ sql += `uuid = ?`;
162
+ args.push(uuid);
163
+ }
164
+ else {
165
+ sql += `name = ?`;
166
+ args.push(name);
167
+ }
168
+ sql += ` ORDER BY node_id, name LIMIT ?`;
169
+ args.push(limit + 1);
170
+ const rows = store.all(sql, args);
171
+ const { rows: pageRows, truncated } = page(rows, limit);
172
+ const mapped = pageRows.map((row) => ({
173
+ kind: row.node_id,
174
+ uuid: row.uuid,
175
+ name: row.name,
176
+ file: row.file,
177
+ region: row.region,
178
+ path: row.path,
179
+ attributes: parseAttrsJson(row.attrs_json),
180
+ }));
181
+ const note = uuid ? `Looked up node(s) by UUID '${uuid}'.` : `Resolved node(s) named '${name}' to their UUID.`;
182
+ return result("guid", params, mapped, truncated, note);
183
+ }
184
+ function queryList(store, params) {
185
+ const uuid = str(params.uuid);
186
+ const name = str(params.name);
187
+ const kindFilter = str(params.kind);
188
+ const limit = limitOf(params);
189
+ let sql;
190
+ const args = [];
191
+ if (kindFilter) {
192
+ sql = `SELECT file, region, node_id, path, uuid, name, attrs_json FROM node WHERE node_id = ?`;
193
+ args.push(kindFilter);
194
+ }
195
+ else {
196
+ sql = `SELECT file, region, node_id, path, uuid, name, attrs_json FROM node WHERE node_id IN ('SpellList', 'Progression')`;
197
+ }
198
+ if (uuid) {
199
+ sql += ` AND uuid = ?`;
200
+ args.push(uuid);
201
+ }
202
+ if (name) {
203
+ sql += ` AND name = ?`;
204
+ args.push(name);
205
+ }
206
+ sql += ` ORDER BY node_id, name LIMIT ?`;
207
+ args.push(limit + 1);
208
+ const rows = store.all(sql, args);
209
+ const { rows: pageRows, truncated } = page(rows, limit);
210
+ const mapped = pageRows.map((row) => {
211
+ const attributes = parseAttrsJson(row.attrs_json);
212
+ const entry = {
213
+ kind: row.node_id,
214
+ uuid: row.uuid,
215
+ name: row.name,
216
+ file: row.file,
217
+ region: row.region,
218
+ path: row.path,
219
+ attributes,
220
+ };
221
+ if (row.node_id === "SpellList") {
222
+ const spells = attributes.Spells?.value ?? "";
223
+ entry.spells = spells.length > 0 ? spells.split(";") : [];
224
+ }
225
+ return entry;
226
+ });
227
+ const how = uuid ? `uuid '${uuid}'` : name ? `name '${name}'` : kindFilter ? `kind '${kindFilter}'` : "all lists/progressions";
228
+ const note = `Searched SpellList/Progression nodes by ${how}.`;
229
+ return result("list", params, mapped, truncated, note);
230
+ }
231
+ function queryHandle(store, params) {
232
+ const handle = str(params.handle);
233
+ const text = str(params.text);
234
+ const limit = limitOf(params);
235
+ if (handle) {
236
+ const row = store.get(`SELECT handle, version, text FROM loca WHERE handle = ?`, [handle]);
237
+ const rows = row ? [row] : [];
238
+ return result("handle", params, rows, false, `Looked up localization handle '${handle}'.`);
239
+ }
240
+ if (text) {
241
+ const rows = store.all(`SELECT l.handle AS handle, l.version AS version, l.text AS text
242
+ FROM loca_fts f JOIN loca l ON l.handle = f.handle
243
+ WHERE loca_fts MATCH ? LIMIT ?`, [text, limit + 1]);
244
+ const { rows: pageRows, truncated } = page(rows, limit);
245
+ return result("handle", params, pageRows, truncated, `Full-text search over localization text for '${text}'.`);
246
+ }
247
+ return result("handle", params, [], false, "No 'handle' or 'text' given; nothing searched.");
248
+ }
249
+ function queryAtlas(store, params) {
250
+ const atlas = str(params.atlas);
251
+ if (!atlas)
252
+ return result("atlas", params, [], false, "No 'atlas' given; nothing searched.");
253
+ const limit = limitOf(params);
254
+ const rows = store.all(`SELECT file, name AS key, attrs_json FROM node WHERE node_id = 'IconUV' AND file LIKE ? ORDER BY name LIMIT ?`, [`%${atlas}%`, limit + 1]);
255
+ const { rows: pageRows, truncated } = page(rows, limit);
256
+ const mapped = pageRows.map((row) => {
257
+ const attrs = parseAttrsJson(row.attrs_json);
258
+ return {
259
+ file: row.file,
260
+ key: row.key,
261
+ u1: attrs.U1?.value,
262
+ u2: attrs.U2?.value,
263
+ v1: attrs.V1?.value,
264
+ v2: attrs.V2?.value,
265
+ };
266
+ });
267
+ return result("atlas", params, mapped, truncated, `IconUV keys in atlas file(s) matching '${atlas}'.`);
268
+ }
269
+ export function queryKinds() {
270
+ return [
271
+ {
272
+ kind: "stat",
273
+ description: "A stat entry by exact or prefix name, with its using-chain (up to 10 levels) and own fields.",
274
+ params: ["name", "prefix", "type", "limit"],
275
+ },
276
+ {
277
+ kind: "field",
278
+ description: "Every distinct value of a field across indexed stats, with counts, optionally filtered by type.",
279
+ params: ["field", "type", "limit"],
280
+ },
281
+ {
282
+ kind: "precedent",
283
+ description: "Vanilla precedent census: every stat whose field value contains a token, optionally filtered by a second field's value (e.g. passives whose BoostContext contains OnCast).",
284
+ params: ["field", "token", "contextField", "contextToken", "type", "limit"],
285
+ },
286
+ {
287
+ kind: "guid",
288
+ description: "LSX nodes by UUID, or resolve a node name to its UUID.",
289
+ params: ["uuid", "name", "limit"],
290
+ },
291
+ {
292
+ kind: "list",
293
+ description: "SpellList/Progression nodes by uuid or name, with their contents (a SpellList's member spells split out).",
294
+ params: ["kind", "uuid", "name", "limit"],
295
+ },
296
+ {
297
+ kind: "handle",
298
+ description: "Localization lookup by handle, or a full-text search over localization text.",
299
+ params: ["handle", "text", "limit"],
300
+ },
301
+ {
302
+ kind: "atlas",
303
+ description: "IconUV keys and UV rects in a GUI atlas, matched against the atlas file's name.",
304
+ params: ["atlas", "limit"],
305
+ },
306
+ ];
307
+ }
308
+ export async function query(store, kind, params) {
309
+ switch (kind) {
310
+ case "stat":
311
+ return queryStat(store, params);
312
+ case "field":
313
+ return queryField(store, params);
314
+ case "precedent":
315
+ return queryPrecedent(store, params);
316
+ case "guid":
317
+ return queryGuid(store, params);
318
+ case "list":
319
+ return queryList(store, params);
320
+ case "handle":
321
+ return queryHandle(store, params);
322
+ case "atlas":
323
+ return queryAtlas(store, params);
324
+ default:
325
+ throw new Error(`Unknown BG3 index query kind: '${kind}'. See queryKinds() for the supported set.`);
326
+ }
327
+ }
@@ -0,0 +1,62 @@
1
+ const SCHEMA_SQL = `
2
+ CREATE TABLE IF NOT EXISTS source (
3
+ id TEXT PRIMARY KEY,
4
+ kind TEXT NOT NULL,
5
+ path TEXT NOT NULL,
6
+ mtime TEXT NOT NULL
7
+ );
8
+
9
+ CREATE TABLE IF NOT EXISTS stat (
10
+ id INTEGER PRIMARY KEY,
11
+ name TEXT NOT NULL COLLATE NOCASE,
12
+ type TEXT NOT NULL,
13
+ "using" TEXT,
14
+ source_id TEXT NOT NULL,
15
+ file TEXT NOT NULL,
16
+ line INTEGER NOT NULL
17
+ );
18
+ CREATE INDEX IF NOT EXISTS idx_stat_name ON stat(name);
19
+ CREATE INDEX IF NOT EXISTS idx_stat_type ON stat(type);
20
+ CREATE INDEX IF NOT EXISTS idx_stat_using ON stat("using");
21
+
22
+ CREATE TABLE IF NOT EXISTS stat_field (
23
+ id INTEGER PRIMARY KEY,
24
+ stat_id INTEGER NOT NULL,
25
+ field TEXT NOT NULL COLLATE NOCASE,
26
+ value TEXT NOT NULL
27
+ );
28
+ CREATE INDEX IF NOT EXISTS idx_stat_field_field ON stat_field(field);
29
+ CREATE INDEX IF NOT EXISTS idx_stat_field_stat_id ON stat_field(stat_id);
30
+
31
+ CREATE VIRTUAL TABLE IF NOT EXISTS stat_field_fts USING fts4(name, field, value);
32
+
33
+ CREATE TABLE IF NOT EXISTS node (
34
+ id INTEGER PRIMARY KEY,
35
+ source_id TEXT NOT NULL,
36
+ file TEXT NOT NULL,
37
+ region TEXT NOT NULL,
38
+ node_id TEXT NOT NULL,
39
+ path TEXT NOT NULL,
40
+ uuid TEXT COLLATE NOCASE,
41
+ name TEXT COLLATE NOCASE,
42
+ attrs_json TEXT NOT NULL
43
+ );
44
+ CREATE INDEX IF NOT EXISTS idx_node_uuid ON node(uuid);
45
+ CREATE INDEX IF NOT EXISTS idx_node_name ON node(name);
46
+ CREATE INDEX IF NOT EXISTS idx_node_node_id ON node(node_id);
47
+
48
+ CREATE TABLE IF NOT EXISTS loca (
49
+ handle TEXT PRIMARY KEY,
50
+ version INTEGER NOT NULL,
51
+ text TEXT NOT NULL
52
+ );
53
+ CREATE VIRTUAL TABLE IF NOT EXISTS loca_fts USING fts4(handle, text);
54
+
55
+ CREATE TABLE IF NOT EXISTS meta (
56
+ key TEXT PRIMARY KEY,
57
+ value TEXT NOT NULL
58
+ );
59
+ `;
60
+ export function createSchema(store) {
61
+ store.exec(SCHEMA_SQL);
62
+ }
@@ -0,0 +1,3 @@
1
+ export { baldursgate3 } from "./surface.js";
2
+ export { SIGNATURES } from "./logs.js";
3
+ export { bg3Index } from "./index/index.js";
@@ -0,0 +1,278 @@
1
+ const GAME = "baldursgate3";
2
+ const SE_VERSION = {
3
+ id: "baldursgate3.se.version",
4
+ game: GAME,
5
+ sources: ["extender"],
6
+ severity: "info",
7
+ category: "success",
8
+ pattern: /^BG3Ext v(?<version>\d+) built on (?<built>.+?)\s*$/,
9
+ explain: "Script Extender started and printed its build banner, so DWrite.dll is loaded and SE " +
10
+ "itself is running.",
11
+ hint: "The version number is SE's own build (v23, v24, ...), not the game patch. SE is " +
12
+ "re-released after nearly every BG3 patch; if the game updated recently, check that " +
13
+ "this build matches the patch before blaming a mod.",
14
+ seenIn: [
15
+ "test/fixtures/logs/bg3/ScriptExtender.synthetic.log",
16
+ "https://github.com/Norbyte/bg3se/issues/508",
17
+ ],
18
+ extract: ["version", "built"],
19
+ };
20
+ const SE_MODULE_LOADED = {
21
+ id: "baldursgate3.se.module-loaded",
22
+ game: GAME,
23
+ sources: ["extender"],
24
+ severity: "info",
25
+ category: "success",
26
+ pattern: /^(?<side>ecl|esv)::ScriptExtender::OnGameStateChanged\(\): Loaded module/,
27
+ explain: "Script Extender saw a module finish loading (ecl = client, esv = server), which is the " +
28
+ "positive confirmation that SE is attached to this session.",
29
+ hint: "Expect one for each side. A client line with no server line means server-side Lua " +
30
+ "(BootstrapServer.lua, Osiris subscribers) never ran.",
31
+ seenIn: [
32
+ "test/fixtures/logs/bg3/ScriptExtender.synthetic.log",
33
+ "https://github.com/Norbyte/bg3se/issues/508",
34
+ ],
35
+ extract: ["side"],
36
+ };
37
+ const SE_MAPPING_NOT_FOUND = {
38
+ id: "baldursgate3.se.mapping-not-found",
39
+ game: GAME,
40
+ sources: ["extender"],
41
+ severity: "warn",
42
+ category: "version",
43
+ pattern: /^No match found for mapping '(?<symbol>[^']+)'/,
44
+ explain: "Script Extender could not locate a game function it hooks, so the feature behind that " +
45
+ "hook is silently inactive this session.",
46
+ hint: "Almost always a version gap: the game patched and this SE build has not caught up. " +
47
+ "Update Script Extender before investigating any mod that depends on the missing feature.",
48
+ seenIn: [
49
+ "test/fixtures/logs/bg3/ScriptExtender.synthetic.log",
50
+ "https://github.com/Norbyte/bg3se/issues/508",
51
+ ],
52
+ extract: ["symbol"],
53
+ };
54
+ const SE_RUNTIME_LOG_PATH = {
55
+ id: "baldursgate3.se.runtime-log-path",
56
+ game: GAME,
57
+ sources: ["extender"],
58
+ severity: "info",
59
+ category: "load",
60
+ pattern: /^Extender runtime log written to '(?<path>[^']+)'/,
61
+ explain: "Script Extender wrote its runtime log to this path — the file that actually carries Lua " +
62
+ "output for this session.",
63
+ hint: "If that path is not one of the candidates ModWright resolves, set LogDirectory in " +
64
+ "ScriptExtenderSettings.json to a stable folder, or read this file directly.",
65
+ seenIn: [
66
+ "test/fixtures/logs/bg3/ScriptExtender.synthetic.log",
67
+ "https://github.com/Norbyte/bg3se/issues/508",
68
+ ],
69
+ extract: ["path"],
70
+ };
71
+ const SE_LUA_ERROR = {
72
+ id: "baldursgate3.se.lua-error",
73
+ game: GAME,
74
+ sources: ["extender"],
75
+ severity: "error",
76
+ category: "script",
77
+ pattern: /(?:Mods[/\\](?<mod>[^/\\:"']+)[/\\])?(?<file>[^\s"']*\.lua):(?<line>\d+):\s*(?<message>\S.*?)\s*$/,
78
+ explain: "A Script Extender Lua script raised a runtime error at this file and line; everything " +
79
+ "after the failing call in that script did not run.",
80
+ hint: "Fix the script, then reload with SE's console rather than a full relaunch — but note " +
81
+ "that a mid-session `reset` degrades Osiris (see baldursgate3.osiris.db-not-available).",
82
+ seenIn: ["unverified: tolerant pattern"],
83
+ extract: ["mod", "file", "line", "message"],
84
+ };
85
+ const OSIRIS_SUBSCRIBER_FAILED = {
86
+ id: "baldursgate3.osiris.subscriber-register-failed",
87
+ game: GAME,
88
+ sources: ["extender", "osiris"],
89
+ severity: "error",
90
+ category: "resource",
91
+ pattern: /Couldn't register Osiris subscriber for (?<event>[^\s/]+)\/(?<arity>\d+)(?:\s*:\s*(?<reason>.+?))?\s*$/,
92
+ explain: "A Lua script subscribed to an Osiris event that the loaded story does not define, so the " +
93
+ "handler will never fire — the mod looks inert with no further error.",
94
+ hint: "Check the event name and arity against the story actually loaded: the name must match a " +
95
+ "story symbol exactly, and the number after the slash is its parameter count. A story " +
96
+ "that failed to compile leaves every symbol missing, so look for compile errors first.",
97
+ seenIn: [
98
+ "test/fixtures/logs/bg3/ScriptExtender.synthetic.log",
99
+ "test/fixtures/logs/bg3/Osiris.synthetic.log",
100
+ "https://github.com/Norbyte/bg3se/issues/420",
101
+ ],
102
+ extract: ["event", "arity", "reason"],
103
+ };
104
+ const OSIRIS_SYMBOL_NOT_FOUND = {
105
+ id: "baldursgate3.osiris.symbol-not-found",
106
+ game: GAME,
107
+ sources: ["extender", "osiris"],
108
+ severity: "error",
109
+ category: "resource",
110
+ pattern: /^(?!.*Couldn't register Osiris subscriber).*Symbol not found in story/,
111
+ explain: "Osiris was asked for a story symbol that does not exist in the compiled story.",
112
+ hint: "Either the symbol is misspelled, or the story it lives in never compiled — a story that " +
113
+ "fails to compile makes every one of its symbols missing at once.",
114
+ seenIn: [
115
+ "https://github.com/Norbyte/bg3se/issues/420",
116
+ "unverified: tolerant pattern (the verified line is the subscriber form above; this " +
117
+ "catches the same wording in any other context)",
118
+ ],
119
+ };
120
+ const OSIRIS_BAD_PREFIX = {
121
+ id: "baldursgate3.osiris.bad-prefix",
122
+ game: GAME,
123
+ sources: ["osiris", "extender"],
124
+ severity: "error",
125
+ category: "compile",
126
+ pattern: /^Osiris fact\/proc\/query (?<symbol>\S+) does not start with 'DB_'\/'PROC_'\/'QRY_'/,
127
+ explain: "An Osiris fact, procedure or query is named without the mandatory DB_ / PROC_ / QRY_ " +
128
+ "prefix, which disables the story component that declares it — silently, at runtime.",
129
+ hint: "Rename the symbol to the prefix matching its kind (DB_ for facts, PROC_ for procedures, " +
130
+ "QRY_ for queries) and update every reference, including Lua-side Osi.* calls.",
131
+ seenIn: [
132
+ "test/fixtures/logs/bg3/Osiris.synthetic.log",
133
+ "https://github.com/Norbyte/bg3se/issues/25",
134
+ ],
135
+ extract: ["symbol"],
136
+ };
137
+ const OSIRIS_DB_NOT_AVAILABLE = {
138
+ id: "baldursgate3.osiris.db-not-available",
139
+ game: GAME,
140
+ sources: ["osiris", "extender"],
141
+ severity: "warn",
142
+ category: "load",
143
+ pattern: /^\s*Not syncing adapters - DB not available/,
144
+ explain: "The Osiris database is not available, so adapters were not synced. After a mid-session SE " +
145
+ "`reset` this is the marker that Osiris is degraded: Lua reloads cleanly while Osi.* " +
146
+ "queries return junk.",
147
+ hint: "Do not trust any Osiris-derived result printed after this line. Relaunch the game rather " +
148
+ "than resetting again, and re-run the check from a fresh session before concluding " +
149
+ "anything about the mod.",
150
+ seenIn: [
151
+ "test/fixtures/logs/bg3/Osiris.synthetic.log",
152
+ "a mod project's own dev notes, via " +
153
+ "test/fixtures/logs/FORMATS.md section 6",
154
+ ],
155
+ };
156
+ const OSIRIS_ERROR_LINE = {
157
+ id: "baldursgate3.osiris.error-line",
158
+ game: GAME,
159
+ sources: ["osiris"],
160
+ severity: "error",
161
+ category: "compile",
162
+ pattern: /^Osiris\b(?=.*\b(?:error|errors|failed|failure)\b).*$/i,
163
+ explain: "Osiris reported an error or failure. Osiris does not attribute errors to the mod that " +
164
+ "caused them, so the line above and below this one are usually more informative than the " +
165
+ "message itself.",
166
+ hint: "Osiris compile failures cascade: one bad goal file leaves every symbol it declares " +
167
+ "missing. Enable LogCompile / LogFailedCompile in ScriptExtenderSettings.json and " +
168
+ "re-launch to get the compile output alongside this line.",
169
+ seenIn: ["unverified: tolerant pattern"],
170
+ };
171
+ const OSIRIS_RULE_FIRED = {
172
+ id: "baldursgate3.osiris.rule-fired",
173
+ game: GAME,
174
+ sources: ["osiris"],
175
+ severity: "info",
176
+ category: "success",
177
+ pattern: /^(?<depth>\d+)-*> RuleActionPart of THEN at line (?<line>\d+) fires\b/,
178
+ explain: "The Osiris story engine executed a rule, so the compiled story is loaded and running. " +
179
+ "The first is reported; `repeats` counts the rest in the scanned window.",
180
+ hint: "A mod's own goals show up as PROC_/DB_ names on the indented lines that follow; searching " +
181
+ "the log for the mod's prefix is the fastest way to see whether its rules ever fire.",
182
+ seenIn: ["test/fixtures/logs/bg3/real/osiris.log"],
183
+ extract: ["depth", "line"],
184
+ };
185
+ const OSIRIS_EVENT = {
186
+ id: "baldursgate3.osiris.event",
187
+ game: GAME,
188
+ sources: ["osiris"],
189
+ severity: "info",
190
+ category: "load",
191
+ pattern: /^>>> event (?<event>\w+)\(/,
192
+ explain: "An engine event reached Osiris. Events are what a story rule's IF part listens for.",
193
+ seenIn: ["test/fixtures/logs/bg3/real/osiris.log"],
194
+ extract: ["event"],
195
+ };
196
+ const NETWORK_STATE_SWAP = {
197
+ id: "baldursgate3.network.state-swap",
198
+ game: GAME,
199
+ sources: ["network"],
200
+ severity: "info",
201
+ category: "load",
202
+ pattern: /\b(?<side>SERVER|CLIENT) STATE SWAP - from: (?<from>[^,]+), to: (?<to>\S+)/,
203
+ explain: "The game state machine advanced. Reported once with the first swap of the scan; " +
204
+ "`repeats` counts the rest, so a low repeat count means the game did not get far.",
205
+ hint: "Read the last swap in the file, not this one: the state it stopped at is where the game " +
206
+ "died. Corroborate with a bin/CrashDump*.dmp written at the same minute.",
207
+ seenIn: [
208
+ "test/fixtures/logs/bg3/network.synthetic.log",
209
+ "https://pastebin.com/x1aQyDxz",
210
+ ],
211
+ extract: ["side", "from", "to"],
212
+ };
213
+ const NETWORK_MODULE_LOAD = {
214
+ id: "baldursgate3.network.module-load",
215
+ game: GAME,
216
+ sources: ["network"],
217
+ severity: "info",
218
+ category: "load",
219
+ pattern: /\b(?:SERVER|CLIENT) STATE SWAP - from: (?<from>[^,]+), to: LoadModule\b/,
220
+ explain: "The game entered LoadModule: modules and assets are being loaded, which is where a bad " +
221
+ "load order or an unresolvable .pak takes the process down.",
222
+ hint: "If this is the last state in the log, treat it as a module-load crash, not a level " +
223
+ "transition: check modsettings.lsx against the paks actually in Mods/, and bisect the " +
224
+ "order rather than the mod's content.",
225
+ seenIn: [
226
+ "test/fixtures/logs/bg3/network.synthetic.log",
227
+ "a mod's own notes on a load-order CTD at LoadModule",
228
+ ],
229
+ extract: ["from"],
230
+ };
231
+ const NETWORK_MAIN_MENU = {
232
+ id: "baldursgate3.network.main-menu",
233
+ game: GAME,
234
+ sources: ["network"],
235
+ severity: "info",
236
+ category: "success",
237
+ pattern: /\b(?:SERVER|CLIENT) STATE SWAP - from: (?<from>[^,]+), to: Menu\s*$/,
238
+ explain: "The client reached the main menu, so module and asset loading completed for this run — " +
239
+ "any crash after this point is not a load-order problem.",
240
+ seenIn: [
241
+ "test/fixtures/logs/bg3/network.synthetic.log",
242
+ "https://pastebin.com/x1aQyDxz",
243
+ ],
244
+ extract: ["from"],
245
+ };
246
+ const NETWORK_STATE_QUEUED = {
247
+ id: "baldursgate3.network.state-queued",
248
+ game: GAME,
249
+ sources: ["network"],
250
+ severity: "info",
251
+ category: "load",
252
+ pattern: /\b(?<side>esv|ecl)::GameStateQueued: (?<state>\S+)/,
253
+ explain: "A state was queued as the next target (esv = server, ecl = client). A queued state with " +
254
+ "no matching STATE SWAP afterwards means the transition was requested but never completed.",
255
+ seenIn: [
256
+ "test/fixtures/logs/bg3/network.synthetic.log",
257
+ "https://pastebin.com/x1aQyDxz",
258
+ ],
259
+ extract: ["side", "state"],
260
+ };
261
+ export const SIGNATURES = [
262
+ SE_VERSION,
263
+ SE_MODULE_LOADED,
264
+ SE_MAPPING_NOT_FOUND,
265
+ SE_RUNTIME_LOG_PATH,
266
+ SE_LUA_ERROR,
267
+ OSIRIS_SUBSCRIBER_FAILED,
268
+ OSIRIS_SYMBOL_NOT_FOUND,
269
+ OSIRIS_BAD_PREFIX,
270
+ OSIRIS_DB_NOT_AVAILABLE,
271
+ OSIRIS_ERROR_LINE,
272
+ OSIRIS_RULE_FIRED,
273
+ OSIRIS_EVENT,
274
+ NETWORK_STATE_SWAP,
275
+ NETWORK_MODULE_LOAD,
276
+ NETWORK_MAIN_MENU,
277
+ NETWORK_STATE_QUEUED,
278
+ ];