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,255 @@
1
+ # new-entity-patch (Cyberpunk 2077) — observed in game (2026-09).
2
+ #
3
+ # Adds a component to vanilla entity templates through ArchiveXL's
4
+ # `resource.patch`: the same mechanism `new-garment-refit` uses on the two
5
+ # player entities, generalised to a list of targets and a chosen component.
6
+ # The first component kind is the camera an in-game test proved: a
7
+ # `gameCameraComponent` bound to a slot on the target (`Item_Attachment_Slot` / `Head`, read off the one archetype the test
8
+ # read in full — the citizen default male; the other 739 under
9
+ # `base\characters\entities\` were not checked, which is why the two
10
+ # binding names are inputs with those defaults rather than constants) plus
11
+ # the `gameDeviceCameraControlComponent` devices carry. Activated with high
12
+ # priority from a script, that camera takes the game view (observed in game,
13
+ # 2026-09: the spawned citizen's head became the view; the loader logged
14
+ # both components added to the archetype at load). The component ships at
15
+ # identity transform: the test set the orientation (roll 90 about the
16
+ # bone's X) and the offset (0.15 forward, 0.06 up) live through
17
+ # `SetLocalOrientation` and `SetLocalPosition`, so a mod tunes them at
18
+ # take-over time rather than baking one head's numbers into every
19
+ # archetype.
20
+ #
21
+ # What the test did NOT settle, and what this scaffold therefore does not
22
+ # claim: input. `DeviceStartPlayerCameraControlEvent` queued on the
23
+ # patched NPC did not give mouse look of that camera, and movement, aim
24
+ # and fire were not exercised at all — the test drove the camera and
25
+ # nothing else. `gameDeviceCameraControlComponent` is here because it is
26
+ # the component a device carries beside its camera and the pair is what
27
+ # was proven to load and activate, NOT because it was shown to route
28
+ # player input to a puppet. Whatever takes over control is the mod's own
29
+ # system, and it is unwritten. This scaffold places two components and
30
+ # registers them; everything past `Activate` is still open.
31
+ #
32
+ # Why a `type: list` input (engine): one patch entity serves
33
+ # many targets, and ArchiveXL takes the whole list on one manifest key; a
34
+ # scaffold that appended one target per apply would need hundreds of
35
+ # applies for the NPC set.
36
+ id: cyberpunk2077.new-entity-patch
37
+ game: cyberpunk2077
38
+ title: New Cyberpunk 2077 entity patch (a component added to vanilla entities)
39
+ summary: Write a patch entity carrying one chosen component (the camera kind ships a gameCameraComponent bound to a slot plus the device camera-control component), register it in the .archive.xl resource.patch for a list of vanilla entity templates, and add the deserialize build step.
40
+ modTypes: [entity-patch, quickhack, npc]
41
+ needs: {}
42
+ inputs:
43
+ - type: string
44
+ name: modSlug
45
+ prompt: "Lowercase depot folder name for this mod, e.g. mymod (the patch compiles to mod\\\\<slug>\\\\<patchName>.ent)."
46
+ pattern: "^[a-z][a-z0-9_]*$"
47
+ - type: string
48
+ name: patchName
49
+ prompt: "File stem of the patch entity, e.g. npc_camera_patch (source <patchName>.ent.json, compiled <patchName>.ent)."
50
+ pattern: "^[a-z][a-z0-9_]*$"
51
+ - type: enum
52
+ name: component
53
+ prompt: "Which component the patch adds. camera: a gameCameraComponent bound to a slot, plus the device camera-control component."
54
+ values: [camera]
55
+ - type: string
56
+ name: componentName
57
+ prompt: "Name of the added camera component (what a script passes to FindComponentByName)."
58
+ pattern: "^[A-Za-z][A-Za-z0-9_]*$"
59
+ default: "patchCamera"
60
+ - type: string
61
+ name: bindSlotComponent
62
+ prompt: "The target entity's slot component the camera binds to (Item_Attachment_Slot on the one archetype the test read in full; confirm it on yours)."
63
+ pattern: "^[A-Za-z][A-Za-z0-9_]*$"
64
+ default: "Item_Attachment_Slot"
65
+ - type: string
66
+ name: bindSlot
67
+ prompt: "The slot in that component (Head on that archetype)."
68
+ pattern: "^[A-Za-z][A-Za-z0-9_]*$"
69
+ default: "Head"
70
+ - type: list
71
+ name: targets
72
+ prompt: "Vanilla entity templates to patch, one depot path per line (or semicolon-separated), e.g. base\\\\characters\\\\entities\\\\citizen\\\\citizen__default_ma.ent. Backslashes, no leading slash, lowercase, .ent."
73
+ itemPattern: "^[a-z0-9_]+(\\\\[a-z0-9_.]+)+\\.ent$"
74
+ minItems: 1
75
+ - type: path
76
+ name: xlFile
77
+ prompt: "Destination .archive.xl manifest (created with an empty resource.patch skeleton if missing). Put it beside the staged folder, e.g. archive-staging/<Project>.archive.xl, not inside it."
78
+ mustExist: false
79
+ - type: path
80
+ name: patchSourceDir
81
+ prompt: "Directory the patch entity's JSON source is written to, typically sources/<modSlug>."
82
+ mustExist: false
83
+ - type: path
84
+ name: patchCompiledDir
85
+ prompt: "Directory the compiled <patchName>.ent lands in, typically <archive-staging>/<Project>/mod/<modSlug> — the folder the manifest's resource.patch key names."
86
+ mustExist: false
87
+ ids: []
88
+ emits:
89
+ # The whole patch entity in one op, and deliberately so. The earlier
90
+ # draft wrote an empty `components: []` skeleton and appended each
91
+ # component with `insert-xl-entry` at `components.-` (the shape
92
+ # `new-garment-refit` uses, where an input-derived depot path with
93
+ # backslashes in it cannot be substituted into hand-typed JSON text).
94
+ # Nothing that lands inside this body carries a backslash — every input
95
+ # reaching it is `[A-Za-z][A-Za-z0-9_]*` — and `.-` *appends*, so a
96
+ # second apply of this scaffold (exactly the re-run this scaffold is
97
+ # written for: the target list widening from one archetype to the
98
+ # eligible set) grew the file to two cameras and two control
99
+ # components, sharing names and `id`s, with nothing to catch it —
100
+ # `cp2077.vehicles.cr2w-unique-ids` checks `HandleId`/`BufferId`, not
101
+ # `id`. One `write-text` with `ifExists: skip` is idempotent instead,
102
+ # and writes exactly the test's own file.
103
+ #
104
+ # The camera block is the turret's `gameCameraComponent`
105
+ # (`security_turret_1.ent`, extracted and read) — its numeric, name,
106
+ # plane and zoom fields, at identity transform; the eighteen
107
+ # `animParam*` CName defaults it also carries are not copied, matching
108
+ # the test's own file, which compiled and loaded without them. The
109
+ # `parentTransform` binding is the shape the base entity uses for its
110
+ # own `Targeting_Head` component. `HandleId: "0"` is this file's only
111
+ # handle.
112
+ #
113
+ # The two `id`s are fixed, chosen above every component id seen in a
114
+ # vanilla archetype (those observed run 1.7e18 to 3.5e18) so the merged
115
+ # entity cannot collide with one of the target's own. They are fixed,
116
+ # not derived, because these exact values are what the test ran with;
117
+ # a project applying this scaffold a *second* time, for a second patch
118
+ # entity over the same targets, must hand-edit the second file's two
119
+ # ids before both are merged into one entity.
120
+ - op: write-text
121
+ path: "${input.patchSourceDir}/${input.patchName}.ent.json"
122
+ ifExists: skip
123
+ body: |
124
+ {
125
+ "Header": {
126
+ "WolvenKitVersion": "8.20.0",
127
+ "WKitJsonVersion": "0.0.9",
128
+ "GameVersion": 2310,
129
+ "DataType": "CR2W",
130
+ "ArchiveFileName": "${input.patchName}.ent"
131
+ },
132
+ "Data": {
133
+ "Version": 195,
134
+ "BuildVersion": 0,
135
+ "RootChunk": {
136
+ "$type": "entEntityTemplate",
137
+ "components": [
138
+ {
139
+ "$type": "gameCameraComponent",
140
+ "farPlaneOverride": 0,
141
+ "fov": 60,
142
+ "fovOverrideValue": 0,
143
+ "fovOverrideWeight": 0,
144
+ "id": "9010000000000000001",
145
+ "isReplicable": 0,
146
+ "localTransform": {
147
+ "$type": "WorldTransform",
148
+ "Orientation": { "$type": "Quaternion", "i": 0, "j": 0, "k": 0, "r": 1 },
149
+ "Position": {
150
+ "$type": "WorldPosition",
151
+ "x": { "$type": "FixedPoint", "Bits": 0 },
152
+ "y": { "$type": "FixedPoint", "Bits": 0 },
153
+ "z": { "$type": "FixedPoint", "Bits": 0 }
154
+ }
155
+ },
156
+ "motionBlurScale": 1,
157
+ "name": { "$type": "CName", "$storage": "string", "$value": "${input.componentName}" },
158
+ "nearPlaneOverride": 0,
159
+ "parentTransform": {
160
+ "HandleId": "0",
161
+ "Data": {
162
+ "$type": "entHardTransformBinding",
163
+ "bindName": { "$type": "CName", "$storage": "string", "$value": "${input.bindSlotComponent}" },
164
+ "enabled": 1,
165
+ "enableMask": {
166
+ "$type": "entTagMask",
167
+ "excludedTags": { "$type": "redTagList", "tags": [ { "$type": "CName", "$storage": "string", "$value": "NoBinding" } ] },
168
+ "hardTags": { "$type": "redTagList", "tags": [] },
169
+ "softTags": { "$type": "redTagList", "tags": [] }
170
+ },
171
+ "slotName": { "$type": "CName", "$storage": "string", "$value": "${input.bindSlot}" }
172
+ }
173
+ },
174
+ "weaponPlane": { "$type": "SWeaponPlaneParams", "blurIntensity": 0, "weaponNearPlaneCM": 0 },
175
+ "zoom": 1,
176
+ "zoomOverrideValue": 0,
177
+ "zoomOverrideWeight": 0,
178
+ "zoomWeaponOverrideValue": 0,
179
+ "zoomWeaponOverrideWeight": 0
180
+ },
181
+ {
182
+ "$type": "gameDeviceCameraControlComponent",
183
+ "id": "9010000000000000002",
184
+ "isReplicable": 0,
185
+ "name": { "$type": "CName", "$storage": "string", "$value": "${input.componentName}Control" },
186
+ "persistentState": null
187
+ }
188
+ ]
189
+ },
190
+ "EmbeddedFiles": []
191
+ }
192
+ }
193
+ - op: write-text
194
+ path: "${input.xlFile}"
195
+ ifExists: skip
196
+ body: |
197
+ {
198
+ "resource": { "patch": {} }
199
+ }
200
+ - op: insert-xl-entry
201
+ path: "${input.xlFile}"
202
+ pointer: "resource.patch.'mod\\${input.modSlug}\\${input.patchName}.ent'"
203
+ value: "${input.targets}"
204
+ - op: patch-project
205
+ add:
206
+ outDir: "archive-staging"
207
+ sources:
208
+ - id: "xl-${input.modSlug}"
209
+ path: "${input.xlFile}"
210
+ kind: xl
211
+ steps:
212
+ - step: exec
213
+ id: "deserialize-${input.modSlug}-${input.patchName}"
214
+ command: wolvenkit-cli
215
+ args: ["convert", "deserialize", "${input.patchSourceDir}/${input.patchName}.ent.json", "-o", "${input.patchCompiledDir}"]
216
+ expectOutputs: ["${input.patchCompiledDir}/${input.patchName}.ent"]
217
+ before: stage
218
+ deployTargets:
219
+ - rootId: archive
220
+ from: "${input.xlFile}"
221
+ locked: false
222
+ backup: true
223
+ templates: []
224
+ satisfies:
225
+ - cp2077.history.xl-manifest-lint
226
+ - cp2077.vehicles.cr2w-unique-ids
227
+ - cp2077.vehicles.cr2w-resource-path-shape
228
+ - cp2077.vehicles.cr2w-gameversion-header
229
+ # `cp2077.garments.xl-entries-resolve` is deliberately absent. It resolves
230
+ # every `resource.patch` KEY against the staged tree, and this scaffold's
231
+ # key is `mod\<slug>\<patch>.ent` — the compiled output of the deserialize
232
+ # step it adds, which does not exist until the build runs. Claiming that
233
+ # rule would make the scaffold's own post-apply validate report it as
234
+ # unresolved on a clean project. The rule is the right one to run after a
235
+ # build, and the manual checklist says so.
236
+ manual:
237
+ - title: Tune the camera and confirm the patch on every target
238
+ steps:
239
+ - "At take-over time set the camera's local orientation and offset from your script (the test's values on an NPC head slot: roll 90 degrees about the bone's X, 0.15 forward, 0.06 up); the patch ships the component at identity so one block serves every target."
240
+ - "Confirm the targets list covers the entities the mod addresses: mechanical NPCs (drones, mechs, androids) live under other template folders than base\\\\characters\\\\entities, and the index does not yet map a Character record to its template path, so find those paths with a resource prefix lookup and add them."
241
+ - "After a launch, read ArchiveXL.log: one \"Component \\\"${input.componentName}\\\" ... added to <target>\" line per target the game loaded; a missing line means a path in the list did not resolve."
242
+ - "Run validate again after a build, not only after this scaffold: cp2077.garments.xl-entries-resolve checks that the manifest's resource.patch key resolves to a staged file, and mod\\\\${input.modSlug}\\\\${input.patchName}.ent only exists once the deserialize step has run."
243
+ - "Write the control system yourself. The test proved the camera takes the view on Activate and nothing beyond that: DeviceStartPlayerCameraControlEvent queued on the patched NPC gave no mouse look, and movement, aim and fire were never exercised. Do not assume the device camera-control component routes player input to a puppet."
244
+ - "Re-applying this scaffold for a second patch entity over the same targets: hand-edit the second file's two component ids (9010000000000000001/2 are fixed here), or the two patches merge into one entity with colliding component ids."
245
+ expected: "Every listed target carries ${input.componentName} at load, and activating it from a script puts the game view at the bound slot."
246
+ claim:
247
+ idSuffix: "${input.patchName}.applies"
248
+ claim: "ArchiveXL adds ${input.componentName} to each entity in ${input.patchName}'s target list at load, and the component is reachable through FindComponentByName on a spawned instance."
249
+ testRows:
250
+ - gate: P-1
251
+ title: "Patched component present on a spawned target"
252
+ expected: "Through the bridge, spawn one target entity and read FindComponentByName(\"${input.componentName}\") on it: non-nil, and ArchiveXL.log carries the added-component line for that target."
253
+ manual: true
254
+ probeKinds: []
255
+ evidence: ["ModWright research"]
@@ -0,0 +1,279 @@
1
+ # new-garment-refit (Cyberpunk 2077) — registers a body type in ArchiveXL's
2
+ # `player.bodyTypes` with gendered patch `.ent`s supplying the `Body:<Type>`
3
+ # component PuppetStateSystem looks up, and a TweakXL record for the
4
+ # garment item itself.
5
+ #
6
+ # Scope: this scaffold stops at the body-type registration and the TweakXL
7
+ # record — it does NOT author the item's own dynamic-appearance mesh-entity pair (a
8
+ # blank-appearance root `.ent` plus a `{gender}`/`{body}`-substituted mesh
9
+ # entity, the shape `jacket.ok.synthetic` demonstrates). That pair *is* the
10
+ # Blender refit itself: the work splits as "Scaffolded: .xl registration,
11
+ # .ent patch entries, TweakXL record | Human: the Blender refit" — the mesh-entity `.ent`'s own substituted component depotPaths
12
+ # only exist once the refit's actual meshes do. Every garment rule this
13
+ # scaffold's own emits could trigger (dynamicappearance-tag-present,
14
+ # substitution-star-prefix, gendered-appearance-suffix, etc.) is
15
+ # consequently vacuous here — a real pass over the human's own mesh-entity
16
+ # `.ent` once written, not a promise this scaffold's output alone satisfies.
17
+ #
18
+ # Deviations observed in game (2026-09):
19
+ # - the `.archive.xl` `resource.patch` keys were hardcoded to
20
+ # `mod\<slug>\body_patch_male.ent` / `_female.ent` while the `.ent.json`
21
+ # sources were written to whatever free-form `malePatchEntFile` /
22
+ # `femalePatchEntFile` named — so the manifest could point at files
23
+ # nothing produces. Both free-form inputs are replaced with one
24
+ # `archiveStagingDir` input (a project source of kind "archive-staging"),
25
+ # so both ends share one `mod/<slug>/body_patch_<gender>` stem and agree
26
+ # by construction. The editable half was then moved out of the staging
27
+ # tree (2026-09-11): the sources are written to
28
+ # `sources/${modSlug}/body_patch_<gender>.ent.json` and the two
29
+ # `convert deserialize` build steps below compile them to
30
+ # `${archiveStagingDir}/mod/${modSlug}/body_patch_<gender>.ent` — the
31
+ # depot key unchanged, and no CR2W JSON left in the packed archive.
32
+ # - `cp2077.history.xl-manifest-lint` (src/surfaces/cyberpunk2077/
33
+ # validators/xl.ts) rejected the `player:` key this scaffold writes;
34
+ # fixed there — `player` is now a known top-level key with a
35
+ # `bodyTypes` shape check, citing
36
+ # cp2077.archivexl.bodytypes.player-bodytypes-key.
37
+ # - the same lint pass unconditionally required a `localization:`
38
+ # block with an `onscreens` mapping, but this scaffold writes no loca of
39
+ # its own. Fixed here (not in the validator, which stays untouched
40
+ # beyond the `player` key fix) by emitting the documented empty shape,
41
+ # `"localization": { "onscreens": {} }` — matching the skeleton
42
+ # `new-item-chain` already writes for the same reason (`new-project`
43
+ # writes no `.xl` at all).
44
+ id: cyberpunk2077.new-garment-refit
45
+ game: cyberpunk2077
46
+ title: New Cyberpunk 2077 garment body-type refit
47
+ summary: Register a body type in ArchiveXL's player.bodyTypes with gendered patch .ents carrying the Body:<Type> component, plus a TweakXL record for the garment item.
48
+ modTypes: [garment, refit]
49
+ needs: { index: true }
50
+ inputs:
51
+ - type: string
52
+ name: bodyType
53
+ prompt: "Body type name registered in player.bodyTypes, e.g. Adonis."
54
+ pattern: "^[A-Za-z][A-Za-z0-9_]*$"
55
+ - type: index-ref
56
+ name: base
57
+ prompt: "$base TweakDB record this garment item inherits from, e.g. Items.GenericInnerChestClothing."
58
+ lookup: { kind: record, params: { name: "${input.base}" } }
59
+ requires: []
60
+ - type: string
61
+ name: itemName
62
+ prompt: "TweakDB record name / appearanceResourceName for this garment item."
63
+ pattern: "^[A-Za-z][A-Za-z0-9_]*$"
64
+ - type: string
65
+ name: outfitSlot
66
+ prompt: "OutfitSlots.* value this garment's placementSlots should !append."
67
+ default: "OutfitSlots.TorsoInner"
68
+ - type: string
69
+ name: modSlug
70
+ prompt: "Lowercase depot folder name for this garment, e.g. hexweave."
71
+ pattern: "^[a-z][a-z0-9_]*$"
72
+ - type: string
73
+ name: maleMeshPath
74
+ prompt: "Depot path (backslash, lowercase) to the male body-type mesh, e.g. mod\\\\hexweave\\\\meshes\\\\body_ma.mesh."
75
+ pattern: "^[a-z0-9_]+(\\\\[a-z0-9_]+)*\\.mesh$"
76
+ - type: string
77
+ name: femaleMeshPath
78
+ prompt: "Depot path (backslash, lowercase) to the female body-type mesh."
79
+ pattern: "^[a-z0-9_]+(\\\\[a-z0-9_]+)*\\.mesh$"
80
+ - type: path
81
+ name: tweaksFile
82
+ prompt: "Destination .yaml under a project source of kind \"tweaks\" (created if missing)."
83
+ mustExist: false
84
+ - type: path
85
+ name: xlFile
86
+ prompt: "Destination .archive.xl manifest (created with an empty skeleton if missing). Put it beside the staged folder, e.g. archive-staging/<Project>.archive.xl, not inside it; it is registered as a project source and deployed to archive/pc/mod by its file name."
87
+ mustExist: false
88
+ - type: path
89
+ name: archiveStagingDir
90
+ prompt: "Project-relative archive-staging root (a project source of kind \"archive-staging\") this garment's compiled files land under. The male/female patch .ent.json sources are written to sources/<modSlug>/ and deserialized into mod/<modSlug>/body_patch_<gender>.ent within it by the build steps this scaffold adds, so they agree by construction with the mod\\<modSlug>\\body_patch_<gender>.ent depot keys it writes into resource.patch (observed in game, 2026-09-11)."
91
+ mustExist: false
92
+ ids:
93
+ - name: recordName
94
+ slot: "Items.${project.name}_${input.itemName}"
95
+ form: tweak-record
96
+ collision:
97
+ project: true
98
+ index: { kind: record, param: name }
99
+ emits:
100
+ - op: insert-block
101
+ path: "${input.tweaksFile}"
102
+ createIfMissing: ""
103
+ anchor: append
104
+ body: |
105
+ ${ids.recordName}:
106
+ $base: ${input.base}
107
+ appearanceResourceName: ${input.itemName}
108
+ placementSlots:
109
+ - !append ${input.outfitSlot}
110
+ - op: write-text
111
+ path: "${input.xlFile}"
112
+ ifExists: skip
113
+ body: |
114
+ {
115
+ "localization": { "onscreens": {} },
116
+ "player": { "bodyTypes": [] },
117
+ "resource": { "patch": {} }
118
+ }
119
+ - op: insert-xl-entry
120
+ path: "${input.xlFile}"
121
+ pointer: player.bodyTypes.-
122
+ value: "${input.bodyType}"
123
+ # Observed in game (2026-09-11): with `value: []` ArchiveXL
124
+ # logged `[error] Line #N: Patch definition must have at least one
125
+ # target.` for each entry and `Archive extensions are loaded with issues`,
126
+ # so the patch .ents never attached to anything. The targets below are
127
+ # the vanilla player first-person entities, base plus the Phantom Liberty
128
+ # twin per gender: the pair a working project's own shipped manifest patches, which
129
+ # loaded in the same launch with ArchiveXL logging `[ResourcePatch]
130
+ # Component ... added to
131
+ # ep1\characters\entities\player\player_wa_fpp_ep1.ent`, and the pairing
132
+ # cp2077.history.xl-manifest-lint already requires. The base\ pair is in
133
+ # the vanilla index (`player_ma_fpp.ent`, `player_wa_fpp.ent`). Whether the
134
+ # third-person entities (player_XX_tpp.ent, present in the vanilla index)
135
+ # also need the component for a body mesh to show in third person is not
136
+ # yet observed; the ArchiveXL body-mod doc names "player_wa.ent /
137
+ # player_ma.ent" without a full path.
138
+ - op: insert-xl-entry
139
+ path: "${input.xlFile}"
140
+ pointer: "resource.patch.'mod\\${input.modSlug}\\body_patch_male.ent'"
141
+ value:
142
+ - "base\\characters\\entities\\player\\player_ma_fpp.ent"
143
+ - "ep1\\characters\\entities\\player\\player_ma_fpp_ep1.ent"
144
+ - op: insert-xl-entry
145
+ path: "${input.xlFile}"
146
+ pointer: "resource.patch.'mod\\${input.modSlug}\\body_patch_female.ent'"
147
+ value:
148
+ - "base\\characters\\entities\\player\\player_wa_fpp.ent"
149
+ - "ep1\\characters\\entities\\player\\player_wa_fpp_ep1.ent"
150
+ # A hand-typed JSON `write-text` body cannot safely carry a backslash-
151
+ # bearing depot path (`${input.maleMeshPath}`) as a raw string
152
+ # substitution — interpolation is plain text, not JSON-escaping, so an
153
+ # embedded single backslash breaks the JSON it lands in. `insert-xl-entry`
154
+ # sidesteps this: its `value` is a structured object, serialized through
155
+ # `JSON.stringify` (which escapes backslashes correctly), so the skeleton
156
+ # below is written free of any input-derived path text and the mesh
157
+ # component (the one field carrying a depot path) is appended separately.
158
+ - op: write-text
159
+ path: "sources/${input.modSlug}/body_patch_male.ent.json"
160
+ ifExists: skip
161
+ body: |
162
+ {
163
+ "Header": {
164
+ "WolvenKitVersion": "8.20.0",
165
+ "WKitJsonVersion": "0.0.9",
166
+ "GameVersion": 2310,
167
+ "DataType": "CR2W",
168
+ "ArchiveFileName": "body_patch_male.ent"
169
+ },
170
+ "Data": {
171
+ "Version": 195,
172
+ "BuildVersion": 0,
173
+ "RootChunk": { "$type": "entEntityTemplate", "components": [] },
174
+ "EmbeddedFiles": []
175
+ }
176
+ }
177
+ - op: insert-xl-entry
178
+ path: "sources/${input.modSlug}/body_patch_male.ent.json"
179
+ pointer: Data.RootChunk.components.-
180
+ value:
181
+ $type: entMeshComponent
182
+ name: { $type: CName, $storage: string, $value: "Body:${input.bodyType}" }
183
+ mesh:
184
+ DepotPath: { $type: ResourcePath, $storage: string, $value: "${input.maleMeshPath}" }
185
+ Flags: Soft
186
+ - op: write-text
187
+ path: "sources/${input.modSlug}/body_patch_female.ent.json"
188
+ ifExists: skip
189
+ body: |
190
+ {
191
+ "Header": {
192
+ "WolvenKitVersion": "8.20.0",
193
+ "WKitJsonVersion": "0.0.9",
194
+ "GameVersion": 2310,
195
+ "DataType": "CR2W",
196
+ "ArchiveFileName": "body_patch_female.ent"
197
+ },
198
+ "Data": {
199
+ "Version": 195,
200
+ "BuildVersion": 0,
201
+ "RootChunk": { "$type": "entEntityTemplate", "components": [] },
202
+ "EmbeddedFiles": []
203
+ }
204
+ }
205
+ - op: insert-xl-entry
206
+ path: "sources/${input.modSlug}/body_patch_female.ent.json"
207
+ pointer: Data.RootChunk.components.-
208
+ value:
209
+ $type: entMeshComponent
210
+ name: { $type: CName, $storage: string, $value: "Body:${input.bodyType}" }
211
+ mesh:
212
+ DepotPath: { $type: ResourcePath, $storage: string, $value: "${input.femaleMeshPath}" }
213
+ Flags: Soft
214
+ # Design change (2026-09-11): the two patch .ent.json sources used to be
215
+ # written straight into the archive-staging tree, where the pack step
216
+ # would ship them as JSON (a scratch project needed a hand
217
+ # `exclude` for them) and nothing compiled them. They now live under
218
+ # sources/<modSlug>/ and two deserialize steps, placed ahead of the stage
219
+ # step, compile them to the mod\<modSlug>\body_patch_<gender>.ent depot
220
+ # paths the resource.patch entries name. The manifest is registered as a
221
+ # project source and an archive deploy target.
222
+ - op: patch-project
223
+ add:
224
+ outDir: "archive-staging"
225
+ sources:
226
+ - id: "xl-${input.modSlug}"
227
+ path: "${input.xlFile}"
228
+ kind: xl
229
+ steps:
230
+ - step: exec
231
+ id: "deserialize-${input.modSlug}-patch-male"
232
+ command: wolvenkit-cli
233
+ args: ["convert", "deserialize", "sources/${input.modSlug}/body_patch_male.ent.json", "-o", "${input.archiveStagingDir}/mod/${input.modSlug}"]
234
+ expectOutputs: ["${input.archiveStagingDir}/mod/${input.modSlug}/body_patch_male.ent"]
235
+ before: stage
236
+ - step: exec
237
+ id: "deserialize-${input.modSlug}-patch-female"
238
+ command: wolvenkit-cli
239
+ args: ["convert", "deserialize", "sources/${input.modSlug}/body_patch_female.ent.json", "-o", "${input.archiveStagingDir}/mod/${input.modSlug}"]
240
+ expectOutputs: ["${input.archiveStagingDir}/mod/${input.modSlug}/body_patch_female.ent"]
241
+ before: stage
242
+ deployTargets:
243
+ - rootId: archive
244
+ from: "${input.xlFile}"
245
+ locked: false
246
+ backup: true
247
+ templates: []
248
+ satisfies:
249
+ - cp2077.garments.body-tag-registration
250
+ - cp2077.garments.substitution-star-prefix
251
+ - cp2077.garments.placeholder-known
252
+ - cp2077.garments.substitution-combination-resolves
253
+ - cp2077.garments.gendered-appearance-suffix
254
+ - cp2077.garments.dynamicappearance-tag-present
255
+ - cp2077.garments.visual-tags-resolve
256
+ - cp2077.garments.root-entity-blank-appearance
257
+ - cp2077.garments.xl-entries-resolve
258
+ manual:
259
+ - title: The refit itself (Blender) and base_body regression
260
+ steps:
261
+ - "In Blender, refit the garment mesh onto the ${input.bodyType} body shape and export the mesh-entity chain: a blank-appearance root .ent (DynamicAppearance tag) plus a mesh entity .ent whose component depotPath substitutes {gender}/{body}, per the jacket pilot's own shape."
262
+ - "Stage the refitted meshes at the {gender}/{body} combinations the mesh entity's substituted path names, or cp2077.garments.substitution-combination-resolves will block on the real chain once it exists."
263
+ - "Confirm base_body (the unmodified vanilla mesh) still renders correctly for players who have not selected ${input.bodyType} — the acceptance criterion this pilot's own table calls out."
264
+ expected: "The garment renders correctly on both ${input.bodyType} and base_body, with the right mesh for each registered gender."
265
+ claim:
266
+ idSuffix: body-type-registered
267
+ claim: "${input.bodyType} is registered in player.bodyTypes with gendered patch .ents supplying its Body:${input.bodyType} component, and ${ids.recordName} exists with $base ${input.base}."
268
+ testRows:
269
+ - gate: R-1
270
+ title: "TweakXL record and body-type patch load without error"
271
+ expected: "TweakXL-<timestamp>.log and ArchiveXL's own log show no error for ${input.xlFile} or ${input.tweaksFile}."
272
+ manual: true
273
+ probeKinds: []
274
+ - gate: R-2
275
+ title: "Correct mesh for the registered body tag; base_body unaffected"
276
+ expected: "CET spawn-and-inspect confirms the right mesh for ${input.bodyType} and that base_body still renders the vanilla mesh."
277
+ manual: true
278
+ probeKinds: []
279
+ evidence: ["ModWright research"]