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,157 @@
1
+ # new-project (Cyberpunk 2077). Mirrors the BG3 new-project scaffold: writes
2
+ # the skeleton every other CP2077 scaffold assumes. tests/authored.yaml and
3
+ # ledger/claims.yaml come from the engine's own automatic per-apply steps,
4
+ # not an emit here.
5
+ #
6
+ # It also writes the build and deploy configuration a working project
7
+ # needs (2026-09-11: scratch projects had to be configured by hand while
8
+ # this scaffold wrote sources only): stage the archive-staging source under
9
+ # the mod's name, pack it with WolvenKit, verify no CR2W JSON leaked into
10
+ # the archive, and deploy the archive, the tweaks folder and the scripts
11
+ # folder. The content scaffolds (new-item-chain, new-garment-refit,
12
+ # new-sector-node) put their deserialize steps ahead of the stage step and
13
+ # register the manifests they write as a project source and a deploy
14
+ # target. A build on a project with nothing staged yet fails at the stage
15
+ # step ("staged zero files"), which is the honest result until a content
16
+ # scaffold has run.
17
+ id: cyberpunk2077.new-project
18
+ game: cyberpunk2077
19
+ title: New Cyberpunk 2077 mod project
20
+ summary: Scaffold a fresh ModWright project for a Cyberpunk 2077 mod — modwright.json (schemaVersion 2), the tweaks/scripts source trees, .gitignore, and ledger/decisions.yaml.
21
+ modTypes: [packaging]
22
+ needs: {}
23
+ inputs:
24
+ - type: string
25
+ name: name
26
+ prompt: Mod name (also used as the r6/tweaks/<name> and scripts/<name> folder name).
27
+ pattern: "^[A-Za-z][A-Za-z0-9_]*$"
28
+ - type: string
29
+ name: version
30
+ prompt: Initial version (semver-ish, major.minor.revision).
31
+ default: "0.1.0"
32
+ - type: string
33
+ name: author
34
+ prompt: Author name.
35
+ default: "Unknown"
36
+ # Observed in practice (2026-09-12): the WolvenKit CLI override had to be
37
+ # added to a fresh project by hand because the locator does not find a CLI
38
+ # installed outside the usual places. The path is machine-specific and
39
+ # lives in modwright.json's `toolchain` block; empty means "the locator's
40
+ # own candidates" and writes nothing.
41
+ - type: string
42
+ name: wolvenkitCli
43
+ prompt: "Absolute path to WolvenKit.CLI.exe when it is not where check_toolchain looks (written as the project's toolchain override; leave empty to rely on the locator)."
44
+ default: ""
45
+ ids: []
46
+ emits:
47
+ - op: ensure-dir
48
+ path: "r6/tweaks/${input.name}"
49
+ - op: ensure-dir
50
+ path: "scripts/${input.name}"
51
+ - op: ensure-dir
52
+ path: "archive-staging/${input.name}"
53
+ # Every other Cyberpunk scaffold that writes an editable JSON source
54
+ # (new-item-chain's .ent.json/localization, new-sector-node's
55
+ # .streamingsector.json, new-vehicle-livery's .mlsetup.json) writes it
56
+ # under "sources/...", and a working project declares exactly this as a
57
+ # project source of kind "sources". Without it here, those files sit
58
+ # outside every declared project source, so `core/validate/context.ts`'s
59
+ # `listFiles()` (which walks `project.sources`, not the whole tree) never
60
+ # lists them: the reason `cp2077.vehicles.cr2w-unique-ids`/
61
+ # `cr2w-enums-are-strings`/`cr2w-resource-path-shape` skipped "no file
62
+ # matched" against a scaffold that plainly does write a JSON
63
+ # `.mlsetup`/`.ent`/`.streamingsector` source, confirmed against a fresh
64
+ # project. Declaring it here is the root-cause fix: it makes those rules
65
+ # genuinely run (and check real content) instead of quietly moving them to
66
+ # `manual` for every scaffold that writes under sources/.
67
+ - op: ensure-dir
68
+ path: "sources"
69
+ - op: write-text
70
+ path: ".gitignore"
71
+ ifExists: skip
72
+ # Two files under .modwright should be tracked, so a reviewer reads them
73
+ # in a clean checkout: suppressions.json and templates/manifest.json. A
74
+ # bare `.modwright/` hides both (observed 2026-09-12). git cannot
75
+ # re-include a file inside an ignored directory, so the templates folder
76
+ # is re-included and its other contents ignored again.
77
+ body: |
78
+ .modwright/*
79
+ !.modwright/suppressions.json
80
+ !.modwright/templates/
81
+ .modwright/templates/*
82
+ !.modwright/templates/manifest.json
83
+ build/
84
+ *.archive
85
+ .modwright-build-manifest.json
86
+ - op: write-text
87
+ path: "ledger/decisions.yaml"
88
+ body: |
89
+ decisions: []
90
+ - op: write-text
91
+ path: "modwright.json"
92
+ body: |
93
+ {
94
+ "schemaVersion": 2,
95
+ "name": "${input.name}",
96
+ "game": "cyberpunk2077",
97
+ "version": "${input.version}",
98
+ "authors": ["${input.author}"],
99
+ "identity": {
100
+ "name": "${input.name}"
101
+ },
102
+ "sources": [
103
+ { "id": "tweaks", "path": "r6/tweaks/${input.name}", "kind": "tweaks" },
104
+ { "id": "scripts", "path": "scripts/${input.name}", "kind": "scripts" },
105
+ { "id": "archive-staging", "path": "archive-staging/${input.name}", "kind": "archive-staging" },
106
+ { "id": "sources", "path": "sources", "kind": "sources" }
107
+ ],
108
+ "build": {
109
+ "outDir": "archive-staging",
110
+ "steps": [
111
+ { "step": "stage", "id": "pack", "sources": ["archive-staging"], "into": "${input.name}" },
112
+ { "step": "wolvenkit-pack", "from": "${stage}/pack/${input.name}", "out": "${input.name}.archive" },
113
+ { "step": "verify-listing", "of": "${input.name}.archive", "forbid": ["**/*.json", "!**/en-us.json"] }
114
+ ]
115
+ },
116
+ "deploy": {
117
+ "waitMinutes": 0,
118
+ "targets": [
119
+ { "rootId": "archive", "from": "${input.name}.archive", "locked": true, "backup": true },
120
+ { "rootId": "tweaks", "from": "tweaks", "into": "${input.name}", "locked": false, "backup": true },
121
+ { "rootId": "redscript", "from": "scripts", "into": "${input.name}", "locked": false, "backup": true }
122
+ ]
123
+ },
124
+ "dependencies": [
125
+ { "id": "red4ext", "kind": "loader", "url": "https://www.nexusmods.com/cyberpunk2077/mods/2380" },
126
+ { "id": "archivexl", "kind": "framework", "url": "https://www.nexusmods.com/cyberpunk2077/mods/4198" },
127
+ { "id": "tweakxl", "kind": "framework", "url": "https://www.nexusmods.com/cyberpunk2077/mods/4197" },
128
+ { "id": "wolvenkit-cli", "kind": "tool", "minVersion": "8.20", "notes": "Packs archive-staging/${input.name} into ${input.name}.archive and deserializes the CR2W JSON sources the content scaffolds write." }
129
+ ]
130
+ }
131
+ # The override merges into the modwright.json written just above (the
132
+ # engine patches the pending copy); an empty input adds no key at all.
133
+ - op: patch-project
134
+ add:
135
+ toolchain:
136
+ wolvenkit-cli: "${input.wolvenkitCli}"
137
+ templates: []
138
+ # No rule applies directly, same reasoning as the BG3 twin: pick a
139
+ # project-target, project-only-needs rule so the postcondition is "ran,
140
+ # clean" against the still-empty tree rather than "skipped".
141
+ satisfies: [cp2077.tweaks.dotted-path-same-file]
142
+ manual:
143
+ - title: Populate the mod
144
+ steps:
145
+ - "Add tweak YAML under r6/tweaks/<name>, redscript under scripts/<name>."
146
+ - "Run the new-tweak scaffold next to add the first TweakDB record."
147
+ expected: "validate reports the project's own structural rules clean once real content exists."
148
+ claim:
149
+ idSuffix: scaffolded
150
+ claim: "${input.name} is scaffolded as a ModWright project with a schemaVersion 2 modwright.json."
151
+ testRows:
152
+ - gate: S-0
153
+ title: "Project loads"
154
+ expected: "validate loads modwright.json with no schema errors and no unmet-needs skip among project-only rules."
155
+ manual: true
156
+ probeKinds: []
157
+ evidence: ["ModWright research"]
@@ -0,0 +1,156 @@
1
+ # new-sector-node (Cyberpunk 2077) — the scaffold writes the JSON source and
2
+ # appends a `convert deserialize` build step (via patch-project) rather than
3
+ # invoking WolvenKit itself. HandleId/BufferId are renumbered into document-
4
+ # encounter order automatically by the engine's `insert-xl-entry` handling —
5
+ # the literal placeholder below is arbitrary on purpose.
6
+ #
7
+ # Deviations observed in game (2026-09):
8
+ # - this scaffold's own patch-project op now supplies
9
+ # `add.outDir: "archive-staging"` — the convention a working project
10
+ # ships (`build.outDir: "archive-staging"` holding
11
+ # `archive-staging/<ModName>`) — so a project with no `build` block yet
12
+ # (fresh off `new-project`) does not end up with one missing `outDir`.
13
+ # It only fills the gap: a project that already has `build.outDir` set
14
+ # keeps its own value (engine.ts's own merge). Fixed at the engine level
15
+ # too: a patch-project op that would leave modwright.json invalid now
16
+ # refuses instead of writing (engine.ts).
17
+ # - the emitted build step used `wolvenkit-cli convert deserialize
18
+ # -i <src> -o <dst>`, but WolvenKit.CLI's `convert` subcommands take the
19
+ # input path positionally and `-o` names an output *directory*, not a
20
+ # file (`-i` is silently swallowed as noise and the run exits 161 —
21
+ # confirmed by hand in game). Fixed to `convert deserialize
22
+ # <input file> -o <output directory>` via a new `outputDir` input
23
+ # (smaller than teaching the engine a "directory of this path" derived
24
+ # value for the one caller that needs it — see new-item-chain.yaml's
25
+ # matching note). `expectOutputs` still names `outputPath`, the file
26
+ # WolvenKit is expected to actually write there — inferred from the
27
+ # serialize direction (it strips the trailing `.json` off the source
28
+ # file's own name) and NOT yet confirmed against a real `deserialize`
29
+ # run; `outputPath` and `outputDir` are both given by the caller and
30
+ # must agree (outputPath's directory should equal outputDir) — nothing
31
+ # here derives one from the other.
32
+ # - `satisfies` is trimmed to the rules that genuinely run against
33
+ # the `.streamingsector` JSON this scaffold writes (checked with a
34
+ # `ran`-membership assertion in the scaffold's tests) — `cp2077.history.
35
+ # xl-manifest-lint` only applies to `.xl` files and never matches a bare
36
+ # sector JSON, so it is dropped.
37
+ #
38
+ # Re-audited against a truly fresh new-project output, not a hand-built
39
+ # fixture (observed 2026-09): `${input.file}` typically lands under
40
+ # `sources/sector/...`, which only resolves to a file the validation context
41
+ # can see because `cyberpunk2077.new-project`
42
+ # now declares a `sources`-kind project source (fixed there, at the root,
43
+ # once for every scaffold that writes under `sources/...`). No change to
44
+ # this file's own satisfies[] was needed once that fix landed.
45
+ id: cyberpunk2077.new-sector-node
46
+ game: cyberpunk2077
47
+ title: New Cyberpunk 2077 sector node
48
+ summary: Append a worldEntityNode to an existing .streamingsector JSON source at a given position, and add the convert-deserialize build step for it.
49
+ modTypes: [world-sector]
50
+ needs: {}
51
+ inputs:
52
+ - type: path
53
+ name: file
54
+ prompt: "The mod's own .streamingsector JSON source to append the node to (must already exist)."
55
+ mustExist: true
56
+ - type: path
57
+ name: outputPath
58
+ prompt: "Where the compiled .streamingsector binary should land (project-relative), for the build step this scaffold appends. Its directory must equal outputDir."
59
+ mustExist: false
60
+ - type: path
61
+ name: outputDir
62
+ prompt: "Directory the compiled .streamingsector binary should land in (project-relative) — passed to WolvenKit.CLI's convert deserialize -o, which takes a directory, not a file. Must be outputPath's own directory."
63
+ mustExist: false
64
+ - type: string
65
+ name: entityTemplatePath
66
+ prompt: "Depot path (backslash, lowercase) to the .ent this node spawns, e.g. mod\\\\mymod\\\\newprop.ent."
67
+ pattern: "^[a-z0-9_]+(\\\\[a-z0-9_]+)*\\.ent$"
68
+ - type: string
69
+ name: appearanceName
70
+ prompt: "Appearance name to use (must be one the .ent actually declares, once staged)."
71
+ default: "default"
72
+ - type: number
73
+ name: positionX
74
+ prompt: "World position X."
75
+ - type: number
76
+ name: positionY
77
+ prompt: "World position Y."
78
+ - type: number
79
+ name: positionZ
80
+ prompt: "World position Z."
81
+ ids: []
82
+ emits:
83
+ - op: insert-xl-entry
84
+ path: "${input.file}"
85
+ pointer: Data.RootChunk.nodes.-
86
+ value:
87
+ HandleId: "new-node"
88
+ Data:
89
+ $type: worldEntityNode
90
+ appearanceName: { $type: CName, $storage: string, $value: "${input.appearanceName}" }
91
+ debugName: { $type: CName, $storage: string, $value: "[ModWright] ${input.entityTemplatePath}" }
92
+ entityLod: 0
93
+ entityTemplate:
94
+ DepotPath: { $type: ResourcePath, $storage: string, $value: "${input.entityTemplatePath}" }
95
+ Flags: Soft
96
+ ioPriority: Immediate
97
+ isHostOnly: 0
98
+ isVisibleInGame: 1
99
+ sourcePrefabHash: "0"
100
+ tag: None
101
+ tagExt: None
102
+ - op: insert-xl-entry
103
+ path: "${input.file}"
104
+ pointer: Data.RootChunk.nodeData.Data.-
105
+ value:
106
+ Id: "1"
107
+ NodeIndex: 1
108
+ Position: { $type: Vector4, W: 0, X: "${input.positionX}", Y: "${input.positionY}", Z: "${input.positionZ}" }
109
+ Orientation: { $type: Quaternion, i: 0.0, j: 0.0, k: 0.0, r: 1.0 }
110
+ Scale: { $type: Vector3, X: 1, Y: 1, Z: 1 }
111
+ - op: patch-project
112
+ add:
113
+ outDir: "archive-staging"
114
+ steps:
115
+ - step: exec
116
+ id: "deserialize-sector"
117
+ command: wolvenkit-cli
118
+ args: ["convert", "deserialize", "${input.file}", "-o", "${input.outputDir}"]
119
+ expectOutputs: ["${input.outputPath}"]
120
+ # Ordering (2026-09-11): ahead of the project's stage step, or
121
+ # the compiled sector lands after the archive was packed.
122
+ before: stage
123
+ templates: []
124
+ satisfies:
125
+ - cp2077.vehicles.cr2w-unique-ids
126
+ - cp2077.vehicles.cr2w-enums-are-strings
127
+ - cp2077.vehicles.cr2w-resource-path-shape
128
+ - cp2077.vehicles.cr2w-gameversion-header
129
+ - cp2077.vehicles.appearance-name-resolution
130
+ manual:
131
+ - title: Confirm placement in-game
132
+ steps:
133
+ - "Stage the referenced .ent (${input.entityTemplatePath}) so appearance-name-resolution can actually check ${input.appearanceName}."
134
+ - "Load a save near the placed coordinates and confirm the entity spawns and renders."
135
+ expected: "The entity is visible at the given position with the expected appearance."
136
+ claim:
137
+ idSuffix: placed
138
+ claim: "A worldEntityNode referencing ${input.entityTemplatePath} (appearance ${input.appearanceName}) is placed at (${input.positionX}, ${input.positionY}, ${input.positionZ})."
139
+ testRows:
140
+ - gate: N-1
141
+ title: "Entity located in-game"
142
+ # cp2077.entity.tagged only finds legacy dev-spawn duplicates, not a
143
+ # sector-placed static prop (observed in game, 2026-09,
144
+ # taggedCount: 0 against a real placed prop) — this scaffold's own node is
145
+ # exactly that case, so the tag mechanism does not apply to it at all. cp2077.entity.transform
146
+ # is itself only `unverified` for a sector-placed prop (same citation).
147
+ # Neither kind is usable here; a human confirms placement by eye instead.
148
+ expected: "A human loads near (${input.positionX}, ${input.positionY}, ${input.positionZ}) and confirms the entity is present at that position — cp2077.entity.tagged/cp2077.entity.transform do not apply to a sector-placed static prop (see this row's own note)."
149
+ manual: true
150
+ probeKinds: [cp2077.entity.tagged, cp2077.entity.transform]
151
+ - gate: N-2
152
+ title: "Visual inspection"
153
+ expected: "A human confirms the entity renders with the correct mesh/appearance from two camera angles."
154
+ manual: true
155
+ probeKinds: []
156
+ evidence: ["ModWright research"]
@@ -0,0 +1,121 @@
1
+ # new-tweak (Cyberpunk 2077) — writes one TweakXL record from a vanilla (or
2
+ # project) $base into a .yaml file under a project source of kind "tweaks".
3
+ # `file` is a `path` input rather than a fixed convention, because projects
4
+ # lay their tweaks trees out differently (r6/tweaks/<Mod>/*.yaml in one,
5
+ # tweaks/*.yaml deployed to r6/tweaks/ in another) — the caller (a `lookup`
6
+ # call, or the person running the scaffold) names the destination, this
7
+ # scaffold does not guess it.
8
+ #
9
+ # Observed while authoring a quickhack (2026-09-19): a record either
10
+ # clones a vanilla/project `$base` OR declares a fresh engine `$type` with no
11
+ # base — the quickhack chain's `ObjectActionPrereq` prereq wrapper is the
12
+ # latter, and this scaffold could not write it while `base` was required.
13
+ # `base` and `type` are now a `oneOf` group (exactly one, engine.ts): each is
14
+ # optional, and the two record blocks below gate on which was given
15
+ # (`when.inputDefined`), so `${ids.recordName}` gets exactly one occurrence in
16
+ # the file — the same mutual-exclusion discipline new-item-chain's two record
17
+ # blocks follow. The `$type` path leans on the tweaks validators already
18
+ # handling a base-less record (`base-exists` skips `!rec.base`; `type-known`
19
+ # checks `rec.type`; `flat-name-exists` is out of scope "unless the record
20
+ # declares its own $type").
21
+ id: cyberpunk2077.new-tweak
22
+ game: cyberpunk2077
23
+ title: New Cyberpunk 2077 TweakDB record
24
+ summary: Append one TweakXL record (with a $base and hand-authored flats) into an existing .yaml under a project's "tweaks" source.
25
+ modTypes: [gameplay-tweak, weapon, item, loot]
26
+ needs: { index: true }
27
+ inputs:
28
+ - type: path
29
+ name: file
30
+ prompt: "Destination .yaml under a project source of kind \"tweaks\" (created if it does not yet exist)."
31
+ mustExist: false
32
+ - type: string
33
+ name: recordName
34
+ prompt: "Full TweakDB record name, e.g. Items.Preset_MyGun."
35
+ pattern: "^[A-Za-z][A-Za-z0-9_]*(\\.[A-Za-z0-9_]+)+$"
36
+ - type: index-ref
37
+ name: base
38
+ prompt: "$base record this inherits from (provide this OR type, not both)."
39
+ lookup: { kind: record, params: { name: "${input.base}" } }
40
+ requires: []
41
+ - type: string
42
+ name: type
43
+ prompt: "$type engine record type for a fresh record with no vanilla $base, e.g. ObjectActionPrereq (provide this OR base, not both)."
44
+ pattern: "^[A-Za-z][A-Za-z0-9_]*$"
45
+ - type: string
46
+ name: flats
47
+ prompt: "Hand-authored flat lines as YAML (e.g. \"displayName: LocKey#Foo-Name\\nprice: 500\"). Indentation is normalized to nest under the record, so write it at any consistent base indent — a sequence step can fix this as a natural block scalar."
48
+ default: ""
49
+ reindent: 2
50
+ ids:
51
+ - name: recordName
52
+ slot: "${input.recordName}"
53
+ form: tweak-record
54
+ collision:
55
+ project: true
56
+ index: { kind: record, param: name }
57
+ oneOf:
58
+ - [base, type]
59
+ emits:
60
+ # Exactly one of these two fires (oneOf: [base, type], enforced by the
61
+ # engine): a $base clone, or a fresh $type declaration. Both append the
62
+ # record name once, then the hand-authored flats.
63
+ - op: insert-block
64
+ path: "${input.file}"
65
+ when: { inputDefined: base }
66
+ createIfMissing: ""
67
+ anchor: append
68
+ body: |
69
+ ${ids.recordName}:
70
+ $base: ${input.base}
71
+ ${input.flats}
72
+ - op: insert-block
73
+ path: "${input.file}"
74
+ when: { inputDefined: type }
75
+ createIfMissing: ""
76
+ anchor: append
77
+ body: |
78
+ ${ids.recordName}:
79
+ $type: ${input.type}
80
+ ${input.flats}
81
+ templates: []
82
+ satisfies:
83
+ - cp2077.tweaks.yaml-lint
84
+ - cp2077.tweaks.base-exists
85
+ - cp2077.tweaks.type-known
86
+ - cp2077.tweaks.flat-name-exists
87
+ - cp2077.tweaks.record-name-exists
88
+ - cp2077.tweaks.append-on-list-flat
89
+ - cp2077.tweaks.dotted-path-same-file
90
+ - cp2077.tweaks.instances-resolve
91
+ manual:
92
+ - title: Confirm in-game
93
+ steps:
94
+ - "Load a save with the mod active and confirm the TweakXL log shows no error for ${input.file}."
95
+ - "Spawn/inspect ${ids.recordName} and confirm the copied flats read as expected."
96
+ expected: "TweakXL-<timestamp>.log carries no error for this file, and the record's flats match the $base plus overrides."
97
+ claim:
98
+ idSuffix: spawns-with-stats
99
+ # Not "$base ${input.base}": a $type-only record has no base, and an
100
+ # unguarded ${input.base} would fail to interpolate in that mode.
101
+ claim: "${ids.recordName} exists in TweakDB with its declared $base or $type and the hand-authored flat overrides applied."
102
+ testRows:
103
+ - gate: T-1
104
+ title: "Record exists with the right base and flats"
105
+ # cp2077.tweakdb.flat needs one concrete <record>.<flat> id, but
106
+ # ${input.flats} is hand-authored free text (no free-form
107
+ # name is trusted to happen to match) — no flat name is fixed
108
+ # here to probe, so only the record's own existence is automated; the
109
+ # flat values themselves stay on the manual checklist above
110
+ # ("confirm the copied flats read as expected").
111
+ expected: "cp2077.tweakdb.record confirms ${ids.recordName} exists."
112
+ manual: false
113
+ probes:
114
+ - kind: cp2077.tweakdb.record
115
+ params: { id: "${ids.recordName}" }
116
+ - gate: T-2
117
+ title: "TweakXL log clean"
118
+ expected: "TweakXL-<timestamp>.log shows no error for this file after a fresh load."
119
+ manual: true
120
+ probeKinds: []
121
+ evidence: ["ModWright research"]
@@ -0,0 +1,148 @@
1
+ # new-vehicle-livery (Cyberpunk 2077) — clones a vehicle's `.mlsetup`
2
+ # material with a renamed base material/texture pair, and a TweakXL vehicle
3
+ # record inheriting the base vehicle's own entityTemplate through its `$base`
4
+ # chain (so no new `.ent` is needed for a pure recolor).
5
+ #
6
+ # Observed in game (2026-09): the `baseVehicle` index-ref's `requires`
7
+ # checked `type` against `^gamedataVehicle`, but `chain`'s own `type` field is
8
+ # the record's bare RTTI-derived type name (queries.ts's `latestPointer`), and
9
+ # for every real vehicle record that name is the literal string `Vehicle` —
10
+ # WolvenKit's own naming rule drops both the `gamedata` prefix and `_Record`
11
+ # suffix (`gamedataVehicle_Record` -> `Vehicle`), confirmed in
12
+ # cp2077.wolvenkit.cli.tweak-type-name-drops-gamedata-and-record-suffix.
13
+ # The requirement matches that literal value.
14
+ #
15
+ # `cp2077.vehicles.tweak-name-from-ent` and `cp2077.vehicles.inkatlas-uv-range`
16
+ # are not in `satisfies`: both are file-extension-gated (`v_*.ent.json`,
17
+ # `*.inkatlas.json` respectively) and this scaffold clones only a `.mlsetup`
18
+ # and a tweak record, never an `.ent` or an `.inkatlas`.
19
+ # `cp2077.vehicles.ent-app-resolution`/`appearance-name-resolution`/
20
+ # `inkatlas-part-resolves` stay: all three are project-scoped
21
+ # (`appliesTo: project`), so they genuinely run every time.
22
+ #
23
+ # Observed in game (2026-09): a fresh project reported `clean: false` with
24
+ # `findings: []` — only benign `(listed in satisfies) skipped` reasons. The
25
+ # real offenders were `cp2077.vehicles.cr2w-unique-ids`/`cr2w-enums-are-strings`/
26
+ # `cr2w-resource-path-shape` skipping "no file matched", because this
27
+ # scaffold's `.mlsetup.json` source landed under `sources/...`, which
28
+ # `cyberpunk2077.new-project` declared no project source for, so the
29
+ # validation context never saw it. `new-project` now declares a
30
+ # `sources`-kind project source; every satisfies rule here concerns a file
31
+ # this scaffold writes, once that file is visible at all.
32
+ #
33
+ # The catalog also lists an "`.xl` substitution entry". There is no
34
+ # confirmed shape for how ArchiveXL wires a recolored `.mlsetup` into a
35
+ # vehicle's paint job (`resource.patch`'s own sub-shape, per
36
+ # `cp2077.history.xl-manifest-lint`, is `.ent`-keyed-to-`.ent` only, which a
37
+ # material swap does not fit). Inventing an unconfirmed manifest shape would
38
+ # be guessing; the manual checklist calls out confirming the real mechanism
39
+ # against current ArchiveXL docs instead of shipping a shape nobody has
40
+ # verified.
41
+ id: cyberpunk2077.new-vehicle-livery
42
+ game: cyberpunk2077
43
+ title: New Cyberpunk 2077 vehicle livery
44
+ summary: Clone a vehicle's .mlsetup material with a renamed base material and texture, plus a TweakXL vehicle record inheriting the base vehicle's own entityTemplate.
45
+ modTypes: [vehicle]
46
+ needs: { index: true }
47
+ inputs:
48
+ - type: string
49
+ name: vehicleName
50
+ prompt: "Suffix for the new TweakDB Vehicle.* record, e.g. TestQuartzRecolor."
51
+ pattern: "^[A-Za-z][A-Za-z0-9_]*$"
52
+ - type: index-ref
53
+ name: baseVehicle
54
+ prompt: "$base Vehicle.* TweakDB record this livery inherits from (its entityTemplate is inherited, not restated)."
55
+ lookup: { kind: chain, params: { name: "${input.baseVehicle}" } }
56
+ requires:
57
+ - path: type
58
+ matches: "^Vehicle$"
59
+ reason: "the base's resolved type must be the literal record type \"Vehicle\" — how RTTI type gamedataVehicle_Record is written in .tweak yaml (cp2077.wolvenkit.cli.tweak-type-name-drops-gamedata-and-record-suffix) and what the chain lookup's own type field actually holds for every real vehicle record — or this livery would inherit fields from the wrong record family."
60
+ - type: string
61
+ name: baseMaterialPath
62
+ prompt: "Depot path (backslash, lowercase) to the vanilla/project base .mt this livery's material inherits, e.g. base\\\\materials\\\\metal_painted.mt."
63
+ pattern: "^[a-z0-9_]+(\\\\[a-z0-9_]+)*\\.mt$"
64
+ - type: string
65
+ name: textureBaseColorPath
66
+ prompt: "Depot path (backslash, lowercase) to this livery's own basecolor texture."
67
+ pattern: "^[a-z0-9_]+(\\\\[a-z0-9_]+)*\\.xbm$"
68
+ - type: path
69
+ name: tweaksFile
70
+ prompt: "Destination .yaml under a project source of kind \"tweaks\" (created if missing)."
71
+ mustExist: false
72
+ - type: path
73
+ name: mlsetupOutputFile
74
+ prompt: "Destination for the cloned .mlsetup JSON source."
75
+ mustExist: false
76
+ - type: template-record
77
+ name: mlsetupTemplate
78
+ prompt: "Cached template-record directory (record.json + content.mlsetup) for the .mlsetup this livery clones."
79
+ ids:
80
+ - name: recordName
81
+ slot: "Vehicle.${project.name}_${input.vehicleName}"
82
+ form: tweak-record
83
+ collision:
84
+ project: true
85
+ index: { kind: record, param: name }
86
+ emits:
87
+ - op: insert-block
88
+ path: "${input.tweaksFile}"
89
+ createIfMissing: ""
90
+ anchor: append
91
+ body: |
92
+ ${ids.recordName}:
93
+ $base: ${input.baseVehicle}
94
+ - op: write-json-from-template
95
+ path: "${input.mlsetupOutputFile}"
96
+ template: mlsetupTemplate
97
+ rewrite:
98
+ - path: Data.BaseMaterial.DepotPath.$value
99
+ value: "${input.baseMaterialPath}"
100
+ - path: Data.Values.0.v.DepotPath.$value
101
+ value: "${input.textureBaseColorPath}"
102
+ strip: []
103
+ # .mlsetup carries no HandleId/BufferId at all (unlike .ent/.app) — the
104
+ # renumber pass would be a harmless no-op either way, but disabling it
105
+ # names that explicitly rather than relying on it silently doing nothing.
106
+ renumberHandles: false
107
+ templates:
108
+ - ref: mlsetupTemplate
109
+ from: "${template.mlsetupTemplate.contentPath}"
110
+ provenanceFrom: mlsetupTemplate
111
+ satisfies:
112
+ - cp2077.tweaks.yaml-lint
113
+ - cp2077.tweaks.base-exists
114
+ - cp2077.tweaks.type-known
115
+ - cp2077.tweaks.dotted-path-same-file
116
+ - cp2077.tweaks.instances-resolve
117
+ - cp2077.vehicles.ent-app-resolution
118
+ - cp2077.vehicles.appearance-name-resolution
119
+ - cp2077.vehicles.inkatlas-part-resolves
120
+ - cp2077.vehicles.cr2w-unique-ids
121
+ - cp2077.vehicles.cr2w-enums-are-strings
122
+ - cp2077.vehicles.cr2w-resource-path-shape
123
+ - cp2077.vehicles.cr2w-gameversion-header
124
+ - cp2077.history.xl-manifest-lint
125
+ manual:
126
+ - title: Wire the recolor in and paint the texture
127
+ steps:
128
+ - "Confirm, against ArchiveXL's current docs, the real mechanism for pointing ${input.baseVehicle}'s paint job at ${input.mlsetupOutputFile}'s compiled .mlsetup — this scaffold deliberately does not guess at an .xl manifest shape nobody has confirmed (see this file's own header note)."
129
+ - "Paint the basecolor (and normal/roughness, if this material needs them) texture(s) referenced by ${input.textureBaseColorPath}."
130
+ - "Build and deploy, then confirm the vehicle is drivable and the livery is visible from two camera angles."
131
+ expected: "The vehicle spawns drivable with the new livery visible from at least two camera angles, and the base vehicle's own paint jobs are unaffected."
132
+ claim:
133
+ idSuffix: livery-applied
134
+ claim: "${ids.recordName} (based on ${input.baseVehicle}) renders with the ${input.mlsetupOutputFile}-derived livery."
135
+ testRows:
136
+ - gate: L-1
137
+ title: "Vehicle record exists with the right base"
138
+ expected: "cp2077.tweakdb.record confirms ${ids.recordName} exists with $base ${input.baseVehicle}."
139
+ manual: false
140
+ probes:
141
+ - kind: cp2077.tweakdb.record
142
+ params: { id: "${ids.recordName}" }
143
+ - gate: L-2
144
+ title: "Drivable with the livery visible"
145
+ expected: "CET spawn probe confirms the vehicle is drivable and the livery is visible from two camera angles."
146
+ manual: true
147
+ probeKinds: []
148
+ evidence: ["ModWright research"]