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,375 @@
1
+ -- MODWRIGHT-BRIDGE-DO-NOT-SHIP
2
+ --
3
+ -- ModWrightBridge — the Cyber Engine Tweaks entry point. This is ModWright's author-only
4
+ -- verification bridge. It is never
5
+ -- shipped in a mod: `cp2077.history.bridge-never-ships`
6
+ -- (src/surfaces/cyberpunk2077/validators/bridge.ts) blocks a build whose output carries this
7
+ -- folder or the banner on the first line above.
8
+ --
9
+ -- WHAT THIS MOD DOES, IN ONE PARAGRAPH: at load it feature-detects the sandbox and discovers
10
+ -- where `io.open` can write; every 1 s it looks for an armed request file; when it finds one
11
+ -- whose marker, nonce, protocol version, game and expiry all check out, it runs the probes
12
+ -- that request names and writes a result followed by a `done` marker carrying the result's
13
+ -- byte length. It READS. The single mutating call in the whole bridge
14
+ -- (`Game.AddToInventory`, the one `mutate` row of the probe catalogue) runs only when the request sets
15
+ -- `allowMutate: true`. If no write root exists it runs LOG-ONLY, printing each result as one
16
+ -- `[MODWRIGHT-RESULT] <json>` line for `triage_logs` to recover.
17
+ --
18
+ -- ============================================================================
19
+ -- Registration shape and its citations
20
+ -- ============================================================================
21
+ -- knowledge fact `cp2077.process.cet-mods-sandboxed` (status `verified`, "2.31", observed in game
22
+ -- 2026-08-16): "cet mods run in a sandboxed lua environment; console access is via
23
+ -- `GetMod(\"ModName\")`, and each mod's init.lua must return a table with methods that the
24
+ -- console can call." That is why this file ends in a `return { … }` and why every console
25
+ -- entry point is a field of it.
26
+ --
27
+ -- `registerForEvent("onUpdate", function(dt) … end)` with an accumulator is
28
+ -- the common CET mod pattern:
29
+ -- local timer = 0
30
+ -- registerForEvent("onUpdate", function(dt)
31
+ -- timer = timer + dt
32
+ -- if timer < 3.0 then return end
33
+ -- timer = 0
34
+ -- and it is the ONLY timer attested for CET. `onInit` and `onShutdown` are registered the
35
+ -- same way.
36
+ --
37
+ -- ============================================================================
38
+ -- The module loader ladder (and why it is a ladder)
39
+ -- ============================================================================
40
+ -- The bridge is split into init.lua + protocol.lua + probes.lua. The CET mods surveyed had
41
+ -- no second file, so the routes come from CET's own changelog rather than from a sibling
42
+ -- on disk:
43
+ -- * "All pathing is now relative to mod (breaking change, includes all io functions,
44
+ -- dofile() and such included)", and require paths are separated with "/" rather than "."
45
+ -- (CET Nexus changelog, version 1.10) — so `require("protocol")` resolves inside THIS
46
+ -- mod's folder, and a dotted `require("ModWrightBridge.protocol")` is not a CET spelling.
47
+ -- * `dofile` is deprecated as of 1.9.1 but still present, and mod-relative since 1.10 — so
48
+ -- `dofile("protocol.lua")` is the last resort, and the older routes relative to bin/x64
49
+ -- (`dofile("plugins/cyber_engine_tweaks/mods/.../protocol.lua")`) are gone: they describe
50
+ -- pre-1.10 behaviour that no longer exists.
51
+ -- Each route is still tried in turn inside `pcall`, and the one that worked is reported in the
52
+ -- heartbeat's capability line and by `m.where()`. If every route fails the mod STILL returns a
53
+ -- table — with `status()`, `where()` and `help()` that explain the failure — because a CET mod
54
+ -- that returns nothing is unreachable from the console and cannot even be diagnosed.
55
+
56
+ local BANNER = "MODWRIGHT-BRIDGE-DO-NOT-SHIP"
57
+ local PREFIX = "[ModWrightBridge]"
58
+
59
+ -- `print(...)` is the console output used by shipped CET mods.
60
+ local function say(msg)
61
+ pcall(function() print(PREFIX .. " " .. tostring(msg)) end)
62
+ end
63
+
64
+ local loadErrors = {}
65
+
66
+ --- Try one loader route. Returns the module table or nil.
67
+ local function tryRoute(label, fn)
68
+ local okCall, mod = pcall(fn)
69
+ if okCall and type(mod) == "table" then return mod, label end
70
+ loadErrors[#loadErrors + 1] = label .. " -> " .. tostring(mod)
71
+ return nil, nil
72
+ end
73
+
74
+ --- Load one of this mod's own modules by its base name ("protocol" / "probes").
75
+ local function loadModule(name)
76
+ local routes = {
77
+ -- Mod-relative, "/" not "." (CET Nexus changelog, version 1.10).
78
+ { 'require("' .. name .. '")', function() return require(name) end },
79
+ { 'require("ModWrightBridge/' .. name .. '")', function() return require("ModWrightBridge/" .. name) end },
80
+ -- Deprecated since 1.9.1, still present, mod-relative since 1.10.
81
+ { 'dofile("' .. name .. '.lua")', function() return dofile(name .. ".lua") end },
82
+ }
83
+ for _, route in ipairs(routes) do
84
+ local mod, label = tryRoute(route[1], route[2])
85
+ if mod ~= nil then return mod, label end
86
+ end
87
+ return nil, nil
88
+ end
89
+
90
+ local Protocol, protocolLoader = loadModule("protocol")
91
+ local Probes, probesLoader = nil, nil
92
+ if Protocol ~= nil then
93
+ Probes, probesLoader = loadModule("probes")
94
+ end
95
+
96
+ -- ---------------------------------------------------------------------------
97
+ -- The degraded mod: every loader route failed
98
+ -- ---------------------------------------------------------------------------
99
+ -- Still a table, still console-reachable, and it says exactly what went wrong.
100
+ if Protocol == nil or Probes == nil then
101
+ local missing = (Protocol == nil) and "protocol.lua" or "probes.lua"
102
+ say("FATAL: could not load " .. missing .. ". The bridge is loaded but INERT.")
103
+ for _, e in ipairs(loadErrors) do say(" " .. e) end
104
+ say('Run `GetMod("ModWrightBridge").where()` for this list again, and see the bridge README.')
105
+
106
+ local function report()
107
+ say("INERT: " .. missing .. " never loaded. Routes tried:")
108
+ for _, e in ipairs(loadErrors) do say(" " .. e) end
109
+ say("Fix: confirm all three .lua files are in " ..
110
+ "bin/x64/plugins/cyber_engine_tweaks/mods/ModWrightBridge/ and re-run `deploy --variant withBridge`. " ..
111
+ "Since CET 1.10 every path here is relative to that folder (CET Nexus changelog, version 1.10).")
112
+ return { loaded = false, missing = missing, errors = loadErrors }
113
+ end
114
+
115
+ registerForEvent("onInit", function()
116
+ say("onInit: inert (" .. missing .. " never loaded)")
117
+ end)
118
+
119
+ return {
120
+ banner = BANNER,
121
+ status = report,
122
+ where = report,
123
+ help = report,
124
+ probe = report,
125
+ arm = report,
126
+ run = report,
127
+ }
128
+ end
129
+
130
+ Probes.init(Protocol)
131
+
132
+ -- ---------------------------------------------------------------------------
133
+ -- Events
134
+ -- ---------------------------------------------------------------------------
135
+
136
+ local tickErrors = 0
137
+ local TICK_ERROR_LIMIT = 20
138
+ local loopDisabled = false
139
+
140
+ -- `registerForEvent("onInit", …)` — the standard CET entry event.
141
+ registerForEvent("onInit", function()
142
+ local okInit, e = pcall(function()
143
+ Protocol.init({
144
+ dispatcher = Probes,
145
+ loaderUsed = tostring(protocolLoader) .. " / " .. tostring(probesLoader),
146
+ })
147
+ end)
148
+ if not okInit then
149
+ say("FATAL in onInit: " .. tostring(e))
150
+ return
151
+ end
152
+ -- The banner: what loaded, at which protocol version, with how many
153
+ -- probe kinds, and where it can write.
154
+ say(string.format(
155
+ "loaded — bridge %s, protocolVersion %d, %d probe kinds, transport %s, write root %s",
156
+ Protocol.BRIDGE_VERSION, Protocol.PROTOCOL_VERSION, #Probes.kinds(),
157
+ Protocol.transport, Protocol.writeRoot))
158
+ if Protocol.transport == "file" then
159
+ say(string.format("polling %s every %ss; heartbeat %s every %ss",
160
+ Protocol.path(Protocol.FILES.request), tostring(Protocol.POLL_SECONDS),
161
+ Protocol.path(Protocol.FILES.heartbeat), tostring(Protocol.HEARTBEAT_SECONDS)))
162
+ else
163
+ say("LOG-ONLY MODE: no candidate write root accepted a write, so there is no request file to poll and no " ..
164
+ "heartbeat file to write. Results are printed as " .. Protocol.RESULT_TAG .. " lines and the heartbeat as " ..
165
+ "a " .. Protocol.HEARTBEAT_TAG .. " line every " .. tostring(Protocol.LOG_HEARTBEAT_SECONDS) .. "s. " ..
166
+ "Arm by hand with m.arm(<json string>) or m.probe(kind, paramsJson).")
167
+ end
168
+ say("console: local m = GetMod(\"ModWrightBridge\") — then m.help(), m.where(), m.status()")
169
+ end)
170
+
171
+ -- `registerForEvent("onUpdate", function(dt) … end)` with a dt accumulator —
172
+ -- the common CET pattern. The accumulators themselves live in Protocol.tick.
173
+ registerForEvent("onUpdate", function(dt)
174
+ if loopDisabled then return end
175
+ local okTick, e = pcall(function() Protocol.tick(dt) end)
176
+ if okTick then
177
+ tickErrors = 0
178
+ return
179
+ end
180
+ tickErrors = tickErrors + 1
181
+ say("ERROR in onUpdate (" .. tickErrors .. "/" .. TICK_ERROR_LIMIT .. "): " .. tostring(e))
182
+ if tickErrors >= TICK_ERROR_LIMIT then
183
+ loopDisabled = true
184
+ say("onUpdate disabled after " .. TICK_ERROR_LIMIT .. " consecutive errors, so it cannot flood " ..
185
+ "cyber_engine_tweaks.log. Reload the mod from the CET UI once the cause is fixed.")
186
+ end
187
+ end)
188
+
189
+ -- `registerForEvent("onShutdown", …)` — the standard CET shutdown event.
190
+ registerForEvent("onShutdown", function()
191
+ pcall(function()
192
+ -- A final heartbeat with `state: "unloaded"` would be natural. That word is NOT in
193
+ -- `bridgeHeartbeatStateSchema` (src/core/bridge/types.ts: "idle"|"running"|"disarmed"),
194
+ -- and a heartbeat that fails the strict schema is DISCARDED by poll.ts/status.ts —
195
+ -- ModWright would report "no heartbeat found" and blame the write root. So the state
196
+ -- stays "idle" and the shutdown is recorded in `writeRootErrors`, which is a string
197
+ -- array the schema does accept.
198
+ Protocol.state = "idle"
199
+ Protocol.writeRootErrors[#Protocol.writeRootErrors + 1] =
200
+ "shutdown: the bridge was unloaded at " .. tostring(Protocol.isoNow()) ..
201
+ "; this heartbeat is final and will not advance until the mod loads again"
202
+ Protocol.writeHeartbeat()
203
+ say("onShutdown: final heartbeat written (state idle, shutdown noted in writeRootErrors)")
204
+ end)
205
+ end)
206
+
207
+ -- ---------------------------------------------------------------------------
208
+ -- The console table (drivable by hand via local b = GetMod("ModWrightBridge"))
209
+ -- ---------------------------------------------------------------------------
210
+
211
+ local consoleSeq = 0
212
+
213
+ local function nextConsoleId()
214
+ consoleSeq = consoleSeq + 1
215
+ -- `id` must match ModWright's `[a-z0-9-]{8,64}` and `nonce` its 16 hex characters, so a
216
+ -- console-driven result file is shaped exactly like an armed one.
217
+ return string.format("console-%06d", consoleSeq),
218
+ string.format("%08x%08x", (consoleSeq * 2654435761) % 4294967296, consoleSeq)
219
+ end
220
+
221
+ --- m.status() — the heartbeat, as a table, printed as JSON.
222
+ local function statusFn()
223
+ local hb = Protocol.heartbeat()
224
+ say("status: " .. Protocol.encode(hb))
225
+ return hb
226
+ end
227
+
228
+ --- m.where() — everything about the transport, in words.
229
+ local function whereFn()
230
+ say("transport : " .. Protocol.transport .. (Protocol.transport == "file" and "" or " (LOG-ONLY)"))
231
+ say("write root : " .. tostring(Protocol.writeRoot))
232
+ say("prefix : " .. tostring(Protocol.writeRootPrefix))
233
+ say("candidates :")
234
+ for i, prefix in ipairs(Protocol.WRITE_ROOT_CANDIDATES) do
235
+ local candidate = prefix .. Protocol.FILES.heartbeat
236
+ local mark = (Protocol.writeRoot == candidate) and " <== IN USE" or ""
237
+ say(string.format(" %d. %s%s", i, candidate, mark))
238
+ end
239
+ if #Protocol.writeRootErrors > 0 then
240
+ say("failures :")
241
+ for _, e in ipairs(Protocol.writeRootErrors) do say(" " .. e) end
242
+ end
243
+ say("files : " .. Protocol.path(Protocol.FILES.request) .. ", " ..
244
+ Protocol.path(Protocol.FILES.requestMarker) .. ", " .. Protocol.path(Protocol.resultFile("<id>")) ..
245
+ ", " .. Protocol.path(Protocol.doneFile("<id>")))
246
+ say("loader : " .. tostring(Protocol.loaderUsed))
247
+ say(Protocol.capabilityLine())
248
+ if #loadErrors > 0 then
249
+ say("loader routes that failed:")
250
+ for _, e in ipairs(loadErrors) do say(" " .. e) end
251
+ end
252
+ return {
253
+ transport = Protocol.transport,
254
+ writeRoot = Protocol.writeRoot,
255
+ writeRootPrefix = Protocol.writeRootPrefix,
256
+ writeRootErrors = Protocol.writeRootErrors,
257
+ capabilities = Protocol.caps,
258
+ loader = Protocol.loaderUsed,
259
+ }
260
+ end
261
+
262
+ --- m.probe(kind, paramsJson, settleSeconds) — run ONE probe by hand.
263
+ ---
264
+ --- `paramsJson` is a JSON object as a STRING, e.g.
265
+ --- m.probe("cp2077.item.equipped", '{"slot":"AttachmentSlots.WeaponRight"}', 2)
266
+ --- `settleSeconds` (optional) stages the probe through the normal run machinery so you can
267
+ --- CLOSE THE CONSOLE before it samples — which the console hazard requires for any
268
+ --- pose, animation or equipment read. With no settle it samples immediately, while the
269
+ --- console is open, and the result says so.
270
+ ---
271
+ --- `allowMutate` is always FALSE here: the one mutating row of the probe catalogue is never fired by an
272
+ --- accidental console line. Use m.arm(<json>) with "allowMutate": true when you mean it.
273
+ local function probeFn(kind, paramsJson, settleSeconds)
274
+ if kind == nil then
275
+ say('usage: m.probe("cp2077.player.present") or m.probe("cp2077.tweakdb.record", \'{"id":"Items.Preset_Example"}\', 2)')
276
+ return nil
277
+ end
278
+ local p = {}
279
+ if paramsJson ~= nil and paramsJson ~= "" then
280
+ local decoded = Protocol.decode(tostring(paramsJson))
281
+ if type(decoded) ~= "table" then
282
+ say("could not decode paramsJson — it must be a JSON OBJECT in a string, e.g. '{\"tag\":\"MyModTag\"}'")
283
+ return nil
284
+ end
285
+ p = decoded
286
+ end
287
+
288
+ local id, nonce = nextConsoleId()
289
+ local settle = tonumber(settleSeconds) or 0
290
+ local probe = {
291
+ id = "console",
292
+ kind = tostring(kind),
293
+ context = "cet",
294
+ effect = "read",
295
+ params = p,
296
+ settleSeconds = settle,
297
+ }
298
+ local request = {
299
+ protocolVersion = Protocol.PROTOCOL_VERSION,
300
+ id = id,
301
+ nonce = nonce,
302
+ issuedAt = Protocol.isoNow(),
303
+ armedUntil = Protocol.isoNow(),
304
+ game = "cyberpunk2077",
305
+ allowMutate = false,
306
+ probes = { probe },
307
+ }
308
+
309
+ if settle > 0 then
310
+ Protocol.beginRun(request)
311
+ say("staged: CLOSE THE CONSOLE now — the probe samples in " .. tostring(settle) ..
312
+ "s and the result is written as " .. Protocol.resultFile(id))
313
+ return id
314
+ end
315
+
316
+ local res = Probes.run(probe, request, nil)
317
+ say("probe " .. tostring(kind) .. ": " .. Protocol.encode(res))
318
+ if res.status == "pass" or res.status == "fail" then
319
+ say("NOTE: sampled with the console OPEN. For any pose, animation or equipment read pass a settle, " ..
320
+ "e.g. m.probe(\"" .. tostring(kind) .. "\", " ..
321
+ (paramsJson and ("'" .. tostring(paramsJson) .. "'") or "nil") .. ", 2)")
322
+ end
323
+ return res
324
+ end
325
+
326
+ --- m.arm(jsonString) — hand the bridge a whole request as a JSON string. The only way to
327
+ --- drive a full request in log-only mode, and the way to set `allowMutate`.
328
+ local function armFn(raw)
329
+ if raw == nil then
330
+ say('usage: m.arm(\'{"protocolVersion":1,"id":"by-hand-01","nonce":"0123456789abcdef",' ..
331
+ '"issuedAt":"2026-09-08T12:00:00Z","armedUntil":"2026-09-08T12:10:00Z","game":"cyberpunk2077",' ..
332
+ '"allowMutate":false,"probes":[{"id":"p1","kind":"cp2077.player.present","context":"cet",' ..
333
+ '"effect":"read","params":{}}]}\')')
334
+ return nil
335
+ end
336
+ local okArm, e = Protocol.armFromString(tostring(raw))
337
+ if not okArm then
338
+ say("arm refused: " .. tostring(e))
339
+ return nil
340
+ end
341
+ say("armed by hand; the result will be " .. (Protocol.transport == "file" and "written" or "printed") .. " shortly")
342
+ return true
343
+ end
344
+
345
+ --- m.run() — poll once, right now, instead of waiting for the next accumulator tick.
346
+ local function runFn()
347
+ Protocol.guarded("console-run", Protocol.pollOnce)()
348
+ say("polled " .. Protocol.path(Protocol.FILES.request) .. "; state = " .. Protocol.state)
349
+ return Protocol.state
350
+ end
351
+
352
+ local function helpFn()
353
+ say("ModWrightBridge " .. Protocol.BRIDGE_VERSION .. " (protocolVersion " .. Protocol.PROTOCOL_VERSION .. ")")
354
+ say(" m.status() heartbeat as JSON")
355
+ say(" m.where() transport, write root, candidates, capabilities")
356
+ say(" m.probe(kind, paramsJson, settle) run one probe (never mutates)")
357
+ say(" m.arm(jsonString) hand it a whole request (this is where allowMutate lives)")
358
+ say(" m.run() poll for a request file right now")
359
+ say("probe kinds:")
360
+ for _, k in ipairs(Probes.kinds()) do say(" " .. k) end
361
+ return Probes.kinds()
362
+ end
363
+
364
+ -- knowledge fact cp2077.process.cet-mods-sandboxed: "each mod's init.lua must return a table
365
+ -- with methods that the console can call" (shipped mods return `{}` or a table of
366
+ -- named functions — this is that shape).
367
+ return {
368
+ banner = BANNER,
369
+ status = statusFn,
370
+ where = whereFn,
371
+ probe = probeFn,
372
+ arm = armFn,
373
+ run = runFn,
374
+ help = helpFn,
375
+ }