wizz-method 1.4.1 → 1.5.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 (574) hide show
  1. package/README.md +6 -4
  2. package/package.json +39 -3
  3. package/skills-registry.yaml +102 -7
  4. package/src/bmm-skills/4-implementation/wizz-code-review/SKILL.md +2 -0
  5. package/src/bmm-skills/4-implementation/wizz-quick-dev/SKILL.md +5 -2
  6. package/src/core-skills/_shared/handoff-protocol.md +61 -0
  7. package/src/core-skills/wizz-customize/SKILL.md +2 -2
  8. package/src/core-skills/wizz-party-mode/references/mode-agent-team.md +1 -1
  9. package/src/core-skills/wizz-party-mode/references/mode-subagent.md +1 -1
  10. package/src/core-skills/wizz-review-adversarial-general/SKILL.md +2 -0
  11. package/src/modules/wizz/README.md +3 -3
  12. package/src/modules/wizz/_shared/communication-rules.md +13 -0
  13. package/src/modules/wizz/_shared/encerramento.md +2 -2
  14. package/src/modules/wizz/agents/wizz-ads/customize.toml +5 -3
  15. package/src/modules/wizz/agents/wizz-copy/customize.toml +5 -3
  16. package/src/modules/wizz/agents/wizz-designer/SKILL.md +2 -2
  17. package/src/modules/wizz/agents/wizz-designer/customize.toml +6 -4
  18. package/src/modules/wizz/agents/wizz-growth/customize.toml +11 -3
  19. package/src/modules/wizz/agents/wizz-maestro/SKILL.md +9 -5
  20. package/src/modules/wizz/agents/wizz-maestro/customize.toml +5 -7
  21. package/src/modules/wizz/agents/wizz-memoria/customize.toml +2 -4
  22. package/src/modules/wizz/agents/wizz-qa/SKILL.md +5 -5
  23. package/src/modules/wizz/agents/wizz-qa/customize.toml +9 -7
  24. package/src/modules/wizz/agents/wizz-seo/customize.toml +5 -3
  25. package/src/modules/wizz/agents/wizz-social/customize.toml +9 -8
  26. package/src/modules/wizz/module.yaml +1 -1
  27. package/src/modules/wizz/overrides/wizz-agent-analyst.toml +4 -5
  28. package/src/modules/wizz/overrides/wizz-agent-architect.toml +11 -3
  29. package/src/modules/wizz/overrides/wizz-agent-dev.toml +6 -4
  30. package/src/modules/wizz/overrides/wizz-agent-pm.toml +4 -2
  31. package/src/modules/wizz/overrides/wizz-agent-tech-writer.toml +3 -5
  32. package/src/modules/wizz/overrides/wizz-agent-ux-designer.toml +4 -2
  33. package/src/modules/wizz/scripts/wizz-init.mjs +3 -1
  34. package/src/scripts/__pycache__/resolve_customization.cpython-314.pyc +0 -0
  35. package/src/scripts/memlog.py +9 -0
  36. package/src/scripts/resolve_customization.py +93 -3
  37. package/src/skills-lib/adversarial-reviewer/SKILL.md +2 -0
  38. package/src/skills-lib/algorithmic-art/SKILL.md +29 -369
  39. package/src/skills-lib/algorithmic-art/references/interactive-artifact.md +139 -0
  40. package/src/skills-lib/algorithmic-art/references/p5js-implementation.md +121 -0
  41. package/src/skills-lib/algorithmic-art/references/philosophy-creation.md +88 -0
  42. package/src/skills-lib/canvas-design/SKILL.md +9 -38
  43. package/src/skills-lib/canvas-design/references/canvas-execution.md +21 -0
  44. package/src/skills-lib/canvas-design/references/philosophy-examples.md +25 -0
  45. package/src/skills-lib/cerebro/SKILL.md +8 -273
  46. package/src/skills-lib/cerebro/references/comandos-pesquisa-e-sync.md +44 -0
  47. package/src/skills-lib/cerebro/references/comandos-rotina-e-captura.md +94 -0
  48. package/src/skills-lib/cerebro/references/comandos-sessao.md +122 -0
  49. package/src/skills-lib/content-strategy/SKILL.md +12 -316
  50. package/src/skills-lib/content-strategy/references/content-types.md +52 -0
  51. package/src/skills-lib/content-strategy/references/ideation-sources.md +78 -0
  52. package/src/skills-lib/content-strategy/references/pillars-and-keywords.md +78 -0
  53. package/src/skills-lib/content-strategy/references/prioritization-and-output.md +57 -0
  54. package/src/skills-lib/decision-maker/SKILL.md +13 -466
  55. package/src/skills-lib/decision-maker/references/commands-and-edge-cases.md +40 -0
  56. package/src/skills-lib/decision-maker/references/output-format.md +161 -0
  57. package/src/skills-lib/decision-maker/references/references-and-extraction.md +129 -0
  58. package/src/skills-lib/decision-maker/references/six-decisions.md +122 -0
  59. package/src/skills-lib/decision-maker/references/wizz-method-handoff.md +22 -0
  60. package/src/skills-lib/find-skills/SKILL.md +9 -6
  61. package/src/skills-lib/form-cro/SKILL.md +12 -390
  62. package/src/skills-lib/form-cro/references/experiments.md +73 -0
  63. package/src/skills-lib/form-cro/references/field-optimization.md +92 -0
  64. package/src/skills-lib/form-cro/references/flow-and-errors.md +71 -0
  65. package/src/skills-lib/form-cro/references/measurement-output.md +41 -0
  66. package/src/skills-lib/form-cro/references/trust-and-form-types.md +54 -0
  67. package/src/skills-lib/graphify/SKILL.md +2 -20
  68. package/src/skills-lib/huashu-design/SKILL.md +42 -596
  69. package/src/skills-lib/huashu-design/references/anti-slop-principles.md +62 -0
  70. package/src/skills-lib/huashu-design/references/audio-design-rules.md +1 -1
  71. package/src/skills-lib/huashu-design/references/cross-agent-adaptation.md +14 -0
  72. package/src/skills-lib/huashu-design/references/design-direction-fallback.md +113 -0
  73. package/src/skills-lib/huashu-design/references/exception-handling.md +18 -0
  74. package/src/skills-lib/huashu-design/references/fact-verification.md +36 -0
  75. package/src/skills-lib/huashu-design/references/ios-prototype.md +146 -0
  76. package/src/skills-lib/huashu-design/references/sfx-library.md +7 -0
  77. package/src/skills-lib/huashu-design/references/starter-components.md +24 -0
  78. package/src/skills-lib/huashu-design/references/video-export.md +1 -1
  79. package/src/skills-lib/huashu-design/references/watermark-policy.md +23 -0
  80. package/src/skills-lib/huashu-design/scripts/add-music.sh +12 -1
  81. package/src/skills-lib/huashu-design/scripts/mix-voiceover.sh +11 -0
  82. package/src/skills-lib/humanizer/SKILL.md +23 -431
  83. package/src/skills-lib/humanizer/references/ai-writing-patterns.md +314 -0
  84. package/src/skills-lib/humanizer/references/full-example.md +72 -0
  85. package/src/skills-lib/humanizer/references/personality-and-soul.md +36 -0
  86. package/src/skills-lib/impeccable/SKILL.md +37 -153
  87. package/src/skills-lib/impeccable/references/design-rules.md +95 -0
  88. package/src/skills-lib/impeccable/references/pin-unpin-and-hooks.md +17 -0
  89. package/src/skills-lib/impeccable/references/routing-rules.md +28 -0
  90. package/src/skills-lib/implementation-planner/SKILL.md +22 -529
  91. package/src/skills-lib/implementation-planner/references/folder-structure-and-dependencies.md +132 -0
  92. package/src/skills-lib/implementation-planner/references/handoff-template.md +34 -0
  93. package/src/skills-lib/implementation-planner/references/implementation-phases.md +54 -0
  94. package/src/skills-lib/implementation-planner/references/implementation-types.md +28 -0
  95. package/src/skills-lib/implementation-planner/references/motion-path-implementation.md +57 -0
  96. package/src/skills-lib/implementation-planner/references/output-templates.md +92 -0
  97. package/src/skills-lib/implementation-planner/references/performance-plan.md +52 -0
  98. package/src/skills-lib/inicio-de-projeto/SKILL.md +4 -224
  99. package/src/skills-lib/inicio-de-projeto/references/implementacao-api-forms.md +112 -0
  100. package/src/skills-lib/inicio-de-projeto/references/padroes-arquiteturais-e-pastas.md +71 -0
  101. package/src/skills-lib/inicio-de-projeto/references/seguranca-e-regras-codigo.md +26 -0
  102. package/src/skills-lib/launch-strategy/SKILL.md +9 -311
  103. package/src/skills-lib/launch-strategy/references/five-phase-approach.md +76 -0
  104. package/src/skills-lib/launch-strategy/references/launch-checklist.md +34 -0
  105. package/src/skills-lib/launch-strategy/references/orb-framework.md +76 -0
  106. package/src/skills-lib/launch-strategy/references/post-launch-and-ongoing.md +64 -0
  107. package/src/skills-lib/launch-strategy/references/product-hunt-strategy.md +52 -0
  108. package/src/skills-lib/marketing-psychology/SKILL.md +18 -401
  109. package/src/skills-lib/marketing-psychology/references/design-and-delivery-models.md +56 -0
  110. package/src/skills-lib/marketing-psychology/references/foundational-thinking-models.md +76 -0
  111. package/src/skills-lib/marketing-psychology/references/growth-and-scaling-models.md +46 -0
  112. package/src/skills-lib/marketing-psychology/references/influencing-behavior.md +71 -0
  113. package/src/skills-lib/marketing-psychology/references/pricing-psychology.md +31 -0
  114. package/src/skills-lib/marketing-psychology/references/understanding-buyers.md +116 -0
  115. package/src/skills-lib/motion-3d-director/SKILL.md +23 -370
  116. package/src/skills-lib/motion-3d-director/references/image-to-video-workflow.md +166 -0
  117. package/src/skills-lib/motion-3d-director/references/motion-paths.md +119 -0
  118. package/src/skills-lib/motion-3d-director/references/performance-and-handoff.md +51 -0
  119. package/src/skills-lib/popup-cro/SKILL.md +11 -414
  120. package/src/skills-lib/popup-cro/references/design-copy-compliance.md +81 -0
  121. package/src/skills-lib/popup-cro/references/experiments.md +82 -0
  122. package/src/skills-lib/popup-cro/references/rules-measurement-output.md +87 -0
  123. package/src/skills-lib/popup-cro/references/triggers-and-popup-types.md +108 -0
  124. package/src/skills-lib/signup-flow-cro/SKILL.md +13 -321
  125. package/src/skills-lib/signup-flow-cro/references/experiments.md +72 -0
  126. package/src/skills-lib/signup-flow-cro/references/field-optimization.md +49 -0
  127. package/src/skills-lib/signup-flow-cro/references/flow-structure.md +38 -0
  128. package/src/skills-lib/signup-flow-cro/references/measurement-output-patterns.md +62 -0
  129. package/src/skills-lib/signup-flow-cro/references/trust-and-post-submit.md +40 -0
  130. package/src/skills-lib/taste-redesign/SKILL.md +10 -146
  131. package/src/skills-lib/taste-redesign/references/design-audit.md +120 -0
  132. package/src/skills-lib/taste-redesign/references/upgrade-techniques.md +31 -0
  133. package/src/skills-lib/ui-ux-pro-max/SKILL.md +9 -353
  134. package/src/skills-lib/ui-ux-pro-max/references/common-rules-checklist.md +76 -0
  135. package/src/skills-lib/ui-ux-pro-max/references/rules-quick-reference.md +70 -0
  136. package/src/skills-lib/ui-ux-pro-max/references/search-reference.md +45 -0
  137. package/src/skills-lib/ui-ux-pro-max/references/workflow-guide.md +157 -0
  138. package/src/skills-lib/web-security/SKILL.md +13 -187
  139. package/src/skills-lib/web-security/references/checklist-deploy.md +52 -0
  140. package/src/skills-lib/web-security/references/headers-rate-limit-cors.md +78 -0
  141. package/src/skills-lib/web-security/references/owasp-top5-detalhado.md +51 -0
  142. package/src/skills-lib/wizz-router/SKILL.md +20 -9
  143. package/src/skills-lib/wizz-router/references/auditoria-360.md +4 -4
  144. package/src/skills-lib/wizz-router/references/routing-table-flat.md +15 -15
  145. package/tools/fetch-assets.mjs +277 -0
  146. package/tools/installer/commands/fetch-assets.js +71 -0
  147. package/tools/installer/commands/install.js +35 -3
  148. package/tools/installer/commands/trace-report.js +131 -0
  149. package/tools/installer/core/config.js +9 -0
  150. package/tools/installer/core/help-catalog.js +181 -0
  151. package/tools/installer/core/install-paths.js +48 -3
  152. package/tools/installer/core/installer.js +253 -618
  153. package/tools/installer/core/manifest-generator.js +8 -1
  154. package/tools/installer/core/manifest.js +67 -22
  155. package/tools/installer/core/module-config-writer.js +110 -0
  156. package/tools/installer/core/preflight-tools-check.js +82 -0
  157. package/tools/installer/core/quick-update.js +209 -0
  158. package/tools/installer/core/user-file-preservation.js +250 -0
  159. package/tools/installer/modules/channel-resolver.js +34 -2
  160. package/tools/installer/modules/cli-config.js +127 -34
  161. package/tools/installer/modules/deps-cache.js +28 -1
  162. package/tools/installer/modules/env-vars.js +446 -0
  163. package/tools/installer/modules/external-manager.js +40 -6
  164. package/tools/installer/modules/mcp-config.js +180 -37
  165. package/tools/installer/modules/module-help-schema.js +2 -1
  166. package/tools/installer/modules/official-modules.js +1 -1
  167. package/tools/installer/modules/registry-resolve.js +74 -0
  168. package/tools/installer/modules/skills-lib.js +11 -15
  169. package/tools/installer/ui.js +71 -5
  170. package/wizz-modules.yaml +15 -5
  171. package/.claude-plugin/marketplace.json +0 -80
  172. package/AGENTS.md +0 -12
  173. package/build/artifacts/llms-full.txt +0 -4049
  174. package/build/artifacts/llms.txt +0 -28
  175. package/build/site/404.html +0 -55
  176. package/build/site/_astro/MobileTableOfContents.astro_astro_type_script_index_0_lang.hwBsy0Mo.js +0 -1
  177. package/build/site/_astro/Search.astro_astro_type_script_index_0_lang.cjYDvRdi.js +0 -1
  178. package/build/site/_astro/TableOfContents.astro_astro_type_script_index_0_lang.FuRcXuRY.js +0 -1
  179. package/build/site/_astro/ec.0vx5m.js +0 -3
  180. package/build/site/_astro/ec.v4551.css +0 -1
  181. package/build/site/_astro/index.DdjI3lF_.css +0 -1
  182. package/build/site/_astro/page.B1D-nYk3.js +0 -1
  183. package/build/site/_astro/print.DNXP8c50.css +0 -1
  184. package/build/site/_astro/ui-core.D_Lfcn_I.js +0 -2
  185. package/build/site/diagrams/checkpoint-preview-diagram-fr.webp +0 -0
  186. package/build/site/diagrams/checkpoint-preview-diagram.png +0 -0
  187. package/build/site/diagrams/quick-dev-diagram-fr.webp +0 -0
  188. package/build/site/diagrams/quick-dev-diagram.png +0 -0
  189. package/build/site/explanation/advanced-elicitation/index.html +0 -105
  190. package/build/site/explanation/adversarial-review/index.html +0 -109
  191. package/build/site/explanation/analysis-phase/index.html +0 -129
  192. package/build/site/explanation/brainstorming/index.html +0 -92
  193. package/build/site/explanation/checkpoint-preview/index.html +0 -121
  194. package/build/site/explanation/established-projects-faq/index.html +0 -107
  195. package/build/site/explanation/forensic-investigation/index.html +0 -167
  196. package/build/site/explanation/named-agents/index.html +0 -187
  197. package/build/site/explanation/party-mode/index.html +0 -256
  198. package/build/site/explanation/preventing-agent-conflicts/index.html +0 -185
  199. package/build/site/explanation/project-context/index.html +0 -198
  200. package/build/site/explanation/quick-dev/index.html +0 -113
  201. package/build/site/explanation/web-bundles/index.html +0 -178
  202. package/build/site/explanation/why-solutioning-matters/index.html +0 -168
  203. package/build/site/how-to/customize-wizz/index.html +0 -277
  204. package/build/site/how-to/established-projects/index.html +0 -165
  205. package/build/site/how-to/expand-wizz-for-your-org/index.html +0 -245
  206. package/build/site/how-to/get-answers-about-wizz/index.html +0 -129
  207. package/build/site/how-to/install-custom-modules/index.html +0 -197
  208. package/build/site/how-to/install-wizz/index.html +0 -330
  209. package/build/site/how-to/non-interactive-installation/index.html +0 -73
  210. package/build/site/how-to/project-context/index.html +0 -141
  211. package/build/site/how-to/quick-fixes/index.html +0 -122
  212. package/build/site/how-to/shard-large-documents/index.html +0 -103
  213. package/build/site/how-to/upgrade-to-v6/index.html +0 -185
  214. package/build/site/how-to/use-web-bundles/index.html +0 -99
  215. package/build/site/img/wizz-dark.png +0 -0
  216. package/build/site/img/wizz-light.png +0 -0
  217. package/build/site/index.html +0 -128
  218. package/build/site/llms-full.txt +0 -4049
  219. package/build/site/llms.txt +0 -28
  220. package/build/site/pagefind/fragment/en_175de32.pf_fragment +0 -0
  221. package/build/site/pagefind/fragment/en_24258fb.pf_fragment +0 -0
  222. package/build/site/pagefind/fragment/en_24f53a6.pf_fragment +0 -0
  223. package/build/site/pagefind/fragment/en_27ba8f9.pf_fragment +0 -0
  224. package/build/site/pagefind/fragment/en_296ddb9.pf_fragment +0 -0
  225. package/build/site/pagefind/fragment/en_2b5aa5c.pf_fragment +0 -0
  226. package/build/site/pagefind/fragment/en_49047e0.pf_fragment +0 -0
  227. package/build/site/pagefind/fragment/en_4a187d2.pf_fragment +0 -0
  228. package/build/site/pagefind/fragment/en_514725b.pf_fragment +0 -0
  229. package/build/site/pagefind/fragment/en_583316f.pf_fragment +0 -0
  230. package/build/site/pagefind/fragment/en_6465dfb.pf_fragment +0 -0
  231. package/build/site/pagefind/fragment/en_67825a4.pf_fragment +0 -0
  232. package/build/site/pagefind/fragment/en_82aec61.pf_fragment +0 -0
  233. package/build/site/pagefind/fragment/en_85dcebf.pf_fragment +0 -0
  234. package/build/site/pagefind/fragment/en_887ce56.pf_fragment +0 -0
  235. package/build/site/pagefind/fragment/en_89a1a7a.pf_fragment +0 -0
  236. package/build/site/pagefind/fragment/en_8ade291.pf_fragment +0 -0
  237. package/build/site/pagefind/fragment/en_8c11f8a.pf_fragment +0 -0
  238. package/build/site/pagefind/fragment/en_8c1bde3.pf_fragment +0 -0
  239. package/build/site/pagefind/fragment/en_92d7cc7.pf_fragment +0 -0
  240. package/build/site/pagefind/fragment/en_94bfc21.pf_fragment +0 -0
  241. package/build/site/pagefind/fragment/en_9b57d7d.pf_fragment +0 -0
  242. package/build/site/pagefind/fragment/en_ab62b53.pf_fragment +0 -0
  243. package/build/site/pagefind/fragment/en_b0d23ee.pf_fragment +0 -0
  244. package/build/site/pagefind/fragment/en_ba9fb37.pf_fragment +0 -0
  245. package/build/site/pagefind/fragment/en_bb113eb.pf_fragment +0 -0
  246. package/build/site/pagefind/fragment/en_bfc56b6.pf_fragment +0 -0
  247. package/build/site/pagefind/fragment/en_c6d9e48.pf_fragment +0 -0
  248. package/build/site/pagefind/fragment/en_cdd772f.pf_fragment +0 -0
  249. package/build/site/pagefind/fragment/en_cdd885c.pf_fragment +0 -0
  250. package/build/site/pagefind/fragment/en_cefed6a.pf_fragment +0 -0
  251. package/build/site/pagefind/fragment/en_d890205.pf_fragment +0 -0
  252. package/build/site/pagefind/fragment/en_da351b7.pf_fragment +0 -0
  253. package/build/site/pagefind/fragment/en_ea289f9.pf_fragment +0 -0
  254. package/build/site/pagefind/fragment/en_f1c3711.pf_fragment +0 -0
  255. package/build/site/pagefind/index/en_5b9d8c6.pf_index +0 -0
  256. package/build/site/pagefind/index/en_868614c.pf_index +0 -0
  257. package/build/site/pagefind/index/en_e4f9bff.pf_index +0 -0
  258. package/build/site/pagefind/pagefind-entry.json +0 -1
  259. package/build/site/pagefind/pagefind-highlight.js +0 -1064
  260. package/build/site/pagefind/pagefind-modular-ui.css +0 -214
  261. package/build/site/pagefind/pagefind-modular-ui.js +0 -8
  262. package/build/site/pagefind/pagefind-ui.css +0 -1
  263. package/build/site/pagefind/pagefind-ui.js +0 -2
  264. package/build/site/pagefind/pagefind.en_4e69d7f053.pf_meta +0 -0
  265. package/build/site/pagefind/pagefind.js +0 -6
  266. package/build/site/pagefind/wasm.en.pagefind +0 -0
  267. package/build/site/pagefind/wasm.unknown.pagefind +0 -0
  268. package/build/site/reference/agents/index.html +0 -168
  269. package/build/site/reference/commands/index.html +0 -254
  270. package/build/site/reference/core-tools/index.html +0 -384
  271. package/build/site/reference/modules/index.html +0 -132
  272. package/build/site/reference/testing/index.html +0 -218
  273. package/build/site/reference/workflow-map/index.html +0 -266
  274. package/build/site/roadmap/index.html +0 -77
  275. package/build/site/robots.txt +0 -37
  276. package/build/site/sitemap-0.xml +0 -1
  277. package/build/site/sitemap-index.xml +0 -1
  278. package/build/site/tutorials/getting-started/index.html +0 -386
  279. package/build/site/wizz-icon-orange.svg +0 -7
  280. package/build/site/workflow-map-diagram-fr.html +0 -375
  281. package/build/site/workflow-map-diagram.html +0 -375
  282. package/evals/bmm-skills/wizz-product-brief/evals.json +0 -237
  283. package/evals/bmm-skills/wizz-product-brief/files/branfield-memo.md +0 -46
  284. package/evals/bmm-skills/wizz-product-brief/files/forkbird-brief/addendum.md +0 -40
  285. package/evals/bmm-skills/wizz-product-brief/files/forkbird-brief/brief.md +0 -56
  286. package/evals/bmm-skills/wizz-product-brief/files/forkbird-brief/decision-log.md +0 -27
  287. package/evals/bmm-skills/wizz-product-brief/files/meridian-mobility-report.md +0 -116
  288. package/evals/bmm-skills/wizz-product-brief/files/mossridge-brief/addendum.md +0 -41
  289. package/evals/bmm-skills/wizz-product-brief/files/mossridge-brief/brief.md +0 -57
  290. package/evals/bmm-skills/wizz-product-brief/files/mossridge-brief/decision-log.md +0 -29
  291. package/evals/bmm-skills/wizz-product-brief/files/pantry-bridge-interviews.md +0 -90
  292. package/evals/bmm-skills/wizz-product-brief/files/q2-brainstorm.md +0 -101
  293. package/evals/bmm-skills/wizz-product-brief/triggers.json +0 -18
  294. package/evals/routing/dataset.json +0 -290
  295. package/evals/routing/run-routing-eval.mjs +0 -89
  296. package/src/skills-lib/canvas-design/canvas-fonts/ArsenalSC-Regular.ttf +0 -0
  297. package/src/skills-lib/canvas-design/canvas-fonts/BigShoulders-Bold.ttf +0 -0
  298. package/src/skills-lib/canvas-design/canvas-fonts/BigShoulders-Regular.ttf +0 -0
  299. package/src/skills-lib/canvas-design/canvas-fonts/Boldonse-Regular.ttf +0 -0
  300. package/src/skills-lib/canvas-design/canvas-fonts/BricolageGrotesque-Bold.ttf +0 -0
  301. package/src/skills-lib/canvas-design/canvas-fonts/BricolageGrotesque-Regular.ttf +0 -0
  302. package/src/skills-lib/canvas-design/canvas-fonts/CrimsonPro-Bold.ttf +0 -0
  303. package/src/skills-lib/canvas-design/canvas-fonts/CrimsonPro-Italic.ttf +0 -0
  304. package/src/skills-lib/canvas-design/canvas-fonts/CrimsonPro-Regular.ttf +0 -0
  305. package/src/skills-lib/canvas-design/canvas-fonts/DMMono-Regular.ttf +0 -0
  306. package/src/skills-lib/canvas-design/canvas-fonts/EricaOne-Regular.ttf +0 -0
  307. package/src/skills-lib/canvas-design/canvas-fonts/GeistMono-Bold.ttf +0 -0
  308. package/src/skills-lib/canvas-design/canvas-fonts/GeistMono-Regular.ttf +0 -0
  309. package/src/skills-lib/canvas-design/canvas-fonts/Gloock-Regular.ttf +0 -0
  310. package/src/skills-lib/canvas-design/canvas-fonts/IBMPlexMono-Bold.ttf +0 -0
  311. package/src/skills-lib/canvas-design/canvas-fonts/IBMPlexMono-Regular.ttf +0 -0
  312. package/src/skills-lib/canvas-design/canvas-fonts/IBMPlexSerif-Bold.ttf +0 -0
  313. package/src/skills-lib/canvas-design/canvas-fonts/IBMPlexSerif-BoldItalic.ttf +0 -0
  314. package/src/skills-lib/canvas-design/canvas-fonts/IBMPlexSerif-Italic.ttf +0 -0
  315. package/src/skills-lib/canvas-design/canvas-fonts/IBMPlexSerif-Regular.ttf +0 -0
  316. package/src/skills-lib/canvas-design/canvas-fonts/InstrumentSans-Bold.ttf +0 -0
  317. package/src/skills-lib/canvas-design/canvas-fonts/InstrumentSans-BoldItalic.ttf +0 -0
  318. package/src/skills-lib/canvas-design/canvas-fonts/InstrumentSans-Italic.ttf +0 -0
  319. package/src/skills-lib/canvas-design/canvas-fonts/InstrumentSans-Regular.ttf +0 -0
  320. package/src/skills-lib/canvas-design/canvas-fonts/InstrumentSerif-Italic.ttf +0 -0
  321. package/src/skills-lib/canvas-design/canvas-fonts/InstrumentSerif-Regular.ttf +0 -0
  322. package/src/skills-lib/canvas-design/canvas-fonts/Italiana-Regular.ttf +0 -0
  323. package/src/skills-lib/canvas-design/canvas-fonts/JetBrainsMono-Bold.ttf +0 -0
  324. package/src/skills-lib/canvas-design/canvas-fonts/JetBrainsMono-Regular.ttf +0 -0
  325. package/src/skills-lib/canvas-design/canvas-fonts/Jura-Light.ttf +0 -0
  326. package/src/skills-lib/canvas-design/canvas-fonts/Jura-Medium.ttf +0 -0
  327. package/src/skills-lib/canvas-design/canvas-fonts/LibreBaskerville-Regular.ttf +0 -0
  328. package/src/skills-lib/canvas-design/canvas-fonts/Lora-Bold.ttf +0 -0
  329. package/src/skills-lib/canvas-design/canvas-fonts/Lora-BoldItalic.ttf +0 -0
  330. package/src/skills-lib/canvas-design/canvas-fonts/Lora-Italic.ttf +0 -0
  331. package/src/skills-lib/canvas-design/canvas-fonts/Lora-Regular.ttf +0 -0
  332. package/src/skills-lib/canvas-design/canvas-fonts/NationalPark-Bold.ttf +0 -0
  333. package/src/skills-lib/canvas-design/canvas-fonts/NationalPark-Regular.ttf +0 -0
  334. package/src/skills-lib/canvas-design/canvas-fonts/NothingYouCouldDo-Regular.ttf +0 -0
  335. package/src/skills-lib/canvas-design/canvas-fonts/Outfit-Bold.ttf +0 -0
  336. package/src/skills-lib/canvas-design/canvas-fonts/Outfit-Regular.ttf +0 -0
  337. package/src/skills-lib/canvas-design/canvas-fonts/PixelifySans-Medium.ttf +0 -0
  338. package/src/skills-lib/canvas-design/canvas-fonts/PoiretOne-Regular.ttf +0 -0
  339. package/src/skills-lib/canvas-design/canvas-fonts/RedHatMono-Bold.ttf +0 -0
  340. package/src/skills-lib/canvas-design/canvas-fonts/RedHatMono-Regular.ttf +0 -0
  341. package/src/skills-lib/canvas-design/canvas-fonts/Silkscreen-Regular.ttf +0 -0
  342. package/src/skills-lib/canvas-design/canvas-fonts/SmoochSans-Medium.ttf +0 -0
  343. package/src/skills-lib/canvas-design/canvas-fonts/Tektur-Medium.ttf +0 -0
  344. package/src/skills-lib/canvas-design/canvas-fonts/Tektur-Regular.ttf +0 -0
  345. package/src/skills-lib/canvas-design/canvas-fonts/WorkSans-Bold.ttf +0 -0
  346. package/src/skills-lib/canvas-design/canvas-fonts/WorkSans-BoldItalic.ttf +0 -0
  347. package/src/skills-lib/canvas-design/canvas-fonts/WorkSans-Italic.ttf +0 -0
  348. package/src/skills-lib/canvas-design/canvas-fonts/WorkSans-Regular.ttf +0 -0
  349. package/src/skills-lib/canvas-design/canvas-fonts/YoungSerif-Regular.ttf +0 -0
  350. package/src/skills-lib/huashu-design/assets/bgm-ad.mp3 +0 -0
  351. package/src/skills-lib/huashu-design/assets/bgm-educational-alt.mp3 +0 -0
  352. package/src/skills-lib/huashu-design/assets/bgm-educational.mp3 +0 -0
  353. package/src/skills-lib/huashu-design/assets/bgm-tech.mp3 +0 -0
  354. package/src/skills-lib/huashu-design/assets/bgm-tutorial-alt.mp3 +0 -0
  355. package/src/skills-lib/huashu-design/assets/bgm-tutorial.mp3 +0 -0
  356. package/src/skills-lib/huashu-design/assets/sfx/container/card-flip.mp3 +0 -0
  357. package/src/skills-lib/huashu-design/assets/sfx/container/card-snap.mp3 +0 -0
  358. package/src/skills-lib/huashu-design/assets/sfx/container/modal-open.mp3 +0 -0
  359. package/src/skills-lib/huashu-design/assets/sfx/container/stack-collapse.mp3 +0 -0
  360. package/src/skills-lib/huashu-design/assets/sfx/feedback/achievement.mp3 +0 -0
  361. package/src/skills-lib/huashu-design/assets/sfx/feedback/error-tone.mp3 +0 -0
  362. package/src/skills-lib/huashu-design/assets/sfx/feedback/notification-pop.mp3 +0 -0
  363. package/src/skills-lib/huashu-design/assets/sfx/feedback/success-chime.mp3 +0 -0
  364. package/src/skills-lib/huashu-design/assets/sfx/impact/brand-stamp.mp3 +0 -0
  365. package/src/skills-lib/huashu-design/assets/sfx/impact/drop-thud.mp3 +0 -0
  366. package/src/skills-lib/huashu-design/assets/sfx/impact/logo-reveal-v2.mp3 +0 -0
  367. package/src/skills-lib/huashu-design/assets/sfx/impact/logo-reveal.mp3 +0 -0
  368. package/src/skills-lib/huashu-design/assets/sfx/keyboard/delete-key.mp3 +0 -0
  369. package/src/skills-lib/huashu-design/assets/sfx/keyboard/enter.mp3 +0 -0
  370. package/src/skills-lib/huashu-design/assets/sfx/keyboard/space-tap.mp3 +0 -0
  371. package/src/skills-lib/huashu-design/assets/sfx/keyboard/type-fast.mp3 +0 -0
  372. package/src/skills-lib/huashu-design/assets/sfx/keyboard/type.mp3 +0 -0
  373. package/src/skills-lib/huashu-design/assets/sfx/magic/ai-process.mp3 +0 -0
  374. package/src/skills-lib/huashu-design/assets/sfx/magic/sparkle.mp3 +0 -0
  375. package/src/skills-lib/huashu-design/assets/sfx/magic/transform.mp3 +0 -0
  376. package/src/skills-lib/huashu-design/assets/sfx/progress/complete-done.mp3 +0 -0
  377. package/src/skills-lib/huashu-design/assets/sfx/progress/generate-start.mp3 +0 -0
  378. package/src/skills-lib/huashu-design/assets/sfx/progress/loading-tick.mp3 +0 -0
  379. package/src/skills-lib/huashu-design/assets/sfx/terminal/command-execute.mp3 +0 -0
  380. package/src/skills-lib/huashu-design/assets/sfx/terminal/cursor-blink.mp3 +0 -0
  381. package/src/skills-lib/huashu-design/assets/sfx/terminal/output-appear.mp3 +0 -0
  382. package/src/skills-lib/huashu-design/assets/sfx/transition/dissolve.mp3 +0 -0
  383. package/src/skills-lib/huashu-design/assets/sfx/transition/slide-in.mp3 +0 -0
  384. package/src/skills-lib/huashu-design/assets/sfx/transition/swipe-horizontal.mp3 +0 -0
  385. package/src/skills-lib/huashu-design/assets/sfx/transition/whoosh-fast.mp3 +0 -0
  386. package/src/skills-lib/huashu-design/assets/sfx/transition/whoosh.mp3 +0 -0
  387. package/src/skills-lib/huashu-design/assets/sfx/ui/click-soft.mp3 +0 -0
  388. package/src/skills-lib/huashu-design/assets/sfx/ui/click.mp3 +0 -0
  389. package/src/skills-lib/huashu-design/assets/sfx/ui/focus.mp3 +0 -0
  390. package/src/skills-lib/huashu-design/assets/sfx/ui/hover-subtle.mp3 +0 -0
  391. package/src/skills-lib/huashu-design/assets/sfx/ui/tap-finger.mp3 +0 -0
  392. package/src/skills-lib/huashu-design/assets/sfx/ui/toggle-on.mp3 +0 -0
  393. package/src/squads/README.md +0 -39
  394. package/src/squads/advisory-board/README.md +0 -34
  395. package/src/squads/advisory-board/agents/board-chair.md +0 -161
  396. package/src/squads/advisory-board/agents/brene-brown.md +0 -296
  397. package/src/squads/advisory-board/agents/charlie-munger.md +0 -590
  398. package/src/squads/advisory-board/agents/derek-sivers.md +0 -268
  399. package/src/squads/advisory-board/agents/naval-ravikant.md +0 -251
  400. package/src/squads/advisory-board/agents/patrick-lencioni.md +0 -394
  401. package/src/squads/advisory-board/agents/peter-thiel.md +0 -269
  402. package/src/squads/advisory-board/agents/ray-dalio.md +0 -567
  403. package/src/squads/advisory-board/agents/reid-hoffman.md +0 -278
  404. package/src/squads/advisory-board/agents/simon-sinek.md +0 -291
  405. package/src/squads/advisory-board/agents/yvon-chouinard.md +0 -275
  406. package/src/squads/advisory-board/squad.yaml +0 -50
  407. package/src/squads/brand-squad/README.md +0 -60
  408. package/src/squads/brand-squad/agents/al-ries.md +0 -175
  409. package/src/squads/brand-squad/agents/alina-wheeler.md +0 -184
  410. package/src/squads/brand-squad/agents/archetype-consultant.md +0 -215
  411. package/src/squads/brand-squad/agents/brand-chief.md +0 -158
  412. package/src/squads/brand-squad/agents/byron-sharp.md +0 -169
  413. package/src/squads/brand-squad/agents/david-aaker.md +0 -166
  414. package/src/squads/brand-squad/agents/denise-yohn.md +0 -172
  415. package/src/squads/brand-squad/agents/domain-scout.md +0 -135
  416. package/src/squads/brand-squad/agents/donald-miller.md +0 -179
  417. package/src/squads/brand-squad/agents/emily-heyward.md +0 -147
  418. package/src/squads/brand-squad/agents/jean-noel-kapferer.md +0 -189
  419. package/src/squads/brand-squad/agents/kevin-keller.md +0 -199
  420. package/src/squads/brand-squad/agents/marty-neumeier.md +0 -170
  421. package/src/squads/brand-squad/agents/miller-sticky-brand.md +0 -180
  422. package/src/squads/brand-squad/agents/naming-strategist.md +0 -171
  423. package/src/squads/brand-squad/squad.yaml +0 -117
  424. package/src/squads/c-level-squad/README.md +0 -29
  425. package/src/squads/c-level-squad/agents/caio-architect.md +0 -235
  426. package/src/squads/c-level-squad/agents/cio-engineer.md +0 -209
  427. package/src/squads/c-level-squad/agents/cmo-architect.md +0 -208
  428. package/src/squads/c-level-squad/agents/coo-orchestrator.md +0 -193
  429. package/src/squads/c-level-squad/agents/cto-architect.md +0 -194
  430. package/src/squads/c-level-squad/agents/vision-chief.md +0 -201
  431. package/src/squads/c-level-squad/squad.yaml +0 -45
  432. package/src/squads/claude-code-mastery/README.md +0 -146
  433. package/src/squads/claude-code-mastery/agents/claude-mastery-chief.md +0 -554
  434. package/src/squads/claude-code-mastery/agents/config-engineer.md +0 -865
  435. package/src/squads/claude-code-mastery/agents/hooks-architect.md +0 -1013
  436. package/src/squads/claude-code-mastery/agents/mcp-integrator.md +0 -791
  437. package/src/squads/claude-code-mastery/agents/project-integrator.md +0 -1196
  438. package/src/squads/claude-code-mastery/agents/roadmap-sentinel.md +0 -931
  439. package/src/squads/claude-code-mastery/agents/skill-craftsman.md +0 -1250
  440. package/src/squads/claude-code-mastery/agents/swarm-orchestrator.md +0 -1008
  441. package/src/squads/copy-squad/README.md +0 -65
  442. package/src/squads/copy-squad/agents/andre-chaperon.md +0 -206
  443. package/src/squads/copy-squad/agents/ben-settle.md +0 -194
  444. package/src/squads/copy-squad/agents/claude-hopkins.md +0 -182
  445. package/src/squads/copy-squad/agents/clayton-makepeace.md +0 -225
  446. package/src/squads/copy-squad/agents/copy-chief.md +0 -166
  447. package/src/squads/copy-squad/agents/dan-kennedy.md +0 -202
  448. package/src/squads/copy-squad/agents/dan-koe.md +0 -223
  449. package/src/squads/copy-squad/agents/david-deutsch.md +0 -197
  450. package/src/squads/copy-squad/agents/david-ogilvy.md +0 -198
  451. package/src/squads/copy-squad/agents/eugene-schwartz.md +0 -238
  452. package/src/squads/copy-squad/agents/frank-kern.md +0 -195
  453. package/src/squads/copy-squad/agents/gary-bencivenga.md +0 -197
  454. package/src/squads/copy-squad/agents/gary-halbert.md +0 -219
  455. package/src/squads/copy-squad/agents/jim-rutz.md +0 -193
  456. package/src/squads/copy-squad/agents/joe-sugarman.md +0 -234
  457. package/src/squads/copy-squad/agents/john-carlton.md +0 -203
  458. package/src/squads/copy-squad/agents/jon-benson.md +0 -196
  459. package/src/squads/copy-squad/agents/parris-lampropoulos.md +0 -188
  460. package/src/squads/copy-squad/agents/robert-collier.md +0 -183
  461. package/src/squads/copy-squad/agents/russell-brunson.md +0 -229
  462. package/src/squads/copy-squad/agents/ry-schwartz.md +0 -185
  463. package/src/squads/copy-squad/agents/stefan-georgi.md +0 -188
  464. package/src/squads/copy-squad/agents/todd-brown.md +0 -171
  465. package/src/squads/copy-squad/squad.yaml +0 -87
  466. package/src/squads/cybersecurity/README.md +0 -38
  467. package/src/squads/cybersecurity/agents/busterer.md +0 -108
  468. package/src/squads/cybersecurity/agents/cartographer.md +0 -114
  469. package/src/squads/cybersecurity/agents/chris-sanders.md +0 -205
  470. package/src/squads/cybersecurity/agents/command-generator.md +0 -121
  471. package/src/squads/cybersecurity/agents/cyber-chief.md +0 -120
  472. package/src/squads/cybersecurity/agents/dirber.md +0 -111
  473. package/src/squads/cybersecurity/agents/fuzzer.md +0 -121
  474. package/src/squads/cybersecurity/agents/georgia-weidman.md +0 -178
  475. package/src/squads/cybersecurity/agents/jim-manico.md +0 -182
  476. package/src/squads/cybersecurity/agents/marcus-carey.md +0 -200
  477. package/src/squads/cybersecurity/agents/omar-santos.md +0 -206
  478. package/src/squads/cybersecurity/agents/peter-kim.md +0 -179
  479. package/src/squads/cybersecurity/agents/ripper.md +0 -121
  480. package/src/squads/cybersecurity/agents/rogue.md +0 -116
  481. package/src/squads/cybersecurity/agents/shannon-runner.md +0 -108
  482. package/src/squads/cybersecurity/squad.yaml +0 -56
  483. package/src/squads/data-squad/README.md +0 -30
  484. package/src/squads/data-squad/agents/avinash-kaushik.md +0 -268
  485. package/src/squads/data-squad/agents/data-chief.md +0 -167
  486. package/src/squads/data-squad/agents/david-spinks.md +0 -277
  487. package/src/squads/data-squad/agents/nick-mehta.md +0 -294
  488. package/src/squads/data-squad/agents/peter-fader.md +0 -246
  489. package/src/squads/data-squad/agents/sean-ellis.md +0 -303
  490. package/src/squads/data-squad/agents/wes-kao.md +0 -268
  491. package/src/squads/data-squad/squad.yaml +0 -46
  492. package/src/squads/design-squad/README.md +0 -31
  493. package/src/squads/design-squad/agents/brad-frost.md +0 -185
  494. package/src/squads/design-squad/agents/dan-mall.md +0 -178
  495. package/src/squads/design-squad/agents/dave-malouf.md +0 -198
  496. package/src/squads/design-squad/agents/design-chief.md +0 -109
  497. package/src/squads/design-squad/agents/design-system-architect.md +0 -109
  498. package/src/squads/design-squad/agents/ui-engineer.md +0 -102
  499. package/src/squads/design-squad/agents/ux-designer.md +0 -105
  500. package/src/squads/design-squad/agents/visual-generator.md +0 -108
  501. package/src/squads/design-squad/squad.yaml +0 -48
  502. package/src/squads/hormozi-squad/README.md +0 -39
  503. package/src/squads/hormozi-squad/agents/hormozi-ads.md +0 -159
  504. package/src/squads/hormozi-squad/agents/hormozi-advisor.md +0 -178
  505. package/src/squads/hormozi-squad/agents/hormozi-audit.md +0 -178
  506. package/src/squads/hormozi-squad/agents/hormozi-chief.md +0 -111
  507. package/src/squads/hormozi-squad/agents/hormozi-closer.md +0 -179
  508. package/src/squads/hormozi-squad/agents/hormozi-content.md +0 -166
  509. package/src/squads/hormozi-squad/agents/hormozi-copy.md +0 -152
  510. package/src/squads/hormozi-squad/agents/hormozi-hooks.md +0 -177
  511. package/src/squads/hormozi-squad/agents/hormozi-launch.md +0 -160
  512. package/src/squads/hormozi-squad/agents/hormozi-leads.md +0 -198
  513. package/src/squads/hormozi-squad/agents/hormozi-models.md +0 -191
  514. package/src/squads/hormozi-squad/agents/hormozi-offers.md +0 -197
  515. package/src/squads/hormozi-squad/agents/hormozi-pricing.md +0 -151
  516. package/src/squads/hormozi-squad/agents/hormozi-retention.md +0 -166
  517. package/src/squads/hormozi-squad/agents/hormozi-scale.md +0 -175
  518. package/src/squads/hormozi-squad/agents/hormozi-workshop.md +0 -160
  519. package/src/squads/hormozi-squad/squad.yaml +0 -60
  520. package/src/squads/movement/README.md +0 -29
  521. package/src/squads/movement/agents/analista-de-impacto.md +0 -350
  522. package/src/squads/movement/agents/estrategista-de-ciclo.md +0 -301
  523. package/src/squads/movement/agents/fenomenologo.md +0 -169
  524. package/src/squads/movement/agents/identitario.md +0 -265
  525. package/src/squads/movement/agents/manifestador.md +0 -279
  526. package/src/squads/movement/agents/movement-architect.md +0 -210
  527. package/src/squads/movement/agents/movement-chief.md +0 -135
  528. package/src/squads/movement/squad.yaml +0 -45
  529. package/src/squads/storytelling/README.md +0 -35
  530. package/src/squads/storytelling/agents/blake-snyder.md +0 -225
  531. package/src/squads/storytelling/agents/dan-harmon.md +0 -167
  532. package/src/squads/storytelling/agents/joseph-campbell.md +0 -184
  533. package/src/squads/storytelling/agents/keith-johnstone.md +0 -157
  534. package/src/squads/storytelling/agents/kindra-hall.md +0 -162
  535. package/src/squads/storytelling/agents/marshall-ganz.md +0 -167
  536. package/src/squads/storytelling/agents/matthew-dicks.md +0 -152
  537. package/src/squads/storytelling/agents/nancy-duarte.md +0 -154
  538. package/src/squads/storytelling/agents/oren-klaff.md +0 -166
  539. package/src/squads/storytelling/agents/park-howell.md +0 -152
  540. package/src/squads/storytelling/agents/shawn-coyne.md +0 -208
  541. package/src/squads/storytelling/agents/story-chief.md +0 -155
  542. package/src/squads/storytelling/squad.yaml +0 -52
  543. package/src/squads/traffic-masters/README.md +0 -39
  544. package/src/squads/traffic-masters/agents/ad-midas.md +0 -149
  545. package/src/squads/traffic-masters/agents/ads-analyst.md +0 -135
  546. package/src/squads/traffic-masters/agents/creative-analyst.md +0 -142
  547. package/src/squads/traffic-masters/agents/depesh-mandalia.md +0 -174
  548. package/src/squads/traffic-masters/agents/fiscal.md +0 -144
  549. package/src/squads/traffic-masters/agents/kasim-aslam.md +0 -158
  550. package/src/squads/traffic-masters/agents/media-buyer.md +0 -159
  551. package/src/squads/traffic-masters/agents/molly-pittman.md +0 -185
  552. package/src/squads/traffic-masters/agents/nicholas-kusmich.md +0 -157
  553. package/src/squads/traffic-masters/agents/pedro-sobral.md +0 -158
  554. package/src/squads/traffic-masters/agents/performance-analyst.md +0 -135
  555. package/src/squads/traffic-masters/agents/pixel-specialist.md +0 -144
  556. package/src/squads/traffic-masters/agents/ralph-burns.md +0 -163
  557. package/src/squads/traffic-masters/agents/scale-optimizer.md +0 -144
  558. package/src/squads/traffic-masters/agents/tom-breeze.md +0 -175
  559. package/src/squads/traffic-masters/agents/traffic-chief.md +0 -97
  560. package/src/squads/traffic-masters/squad.yaml +0 -59
  561. package/tools/bundle-web-bundles.js +0 -117
  562. package/tools/format-workflow-md.js +0 -263
  563. package/tools/hooks/README.md +0 -17
  564. package/tools/hooks/security-defensive-context.js +0 -70
  565. package/tools/hooks/session-rules.js +0 -38
  566. package/tools/hooks/wizz-router-enforce.js +0 -188
  567. package/tools/javascript-conventions.md +0 -5
  568. package/tools/migrate-custom-module-paths.js +0 -124
  569. package/tools/skill-validator.md +0 -368
  570. package/tools/sync-global.mjs +0 -84
  571. package/tools/validate-sidebar-order.js +0 -388
  572. package/tools/validate-skills.js +0 -708
  573. package/tools/validate-svg-changes.sh +0 -356
  574. /package/tools/installer/{cli-utils.js → banner.js} +0 -0
@@ -0,0 +1,250 @@
1
+ /**
2
+ * User file preservation: scan → backup → restore.
3
+ *
4
+ * Extracted from `Installer` (installer god-object breakup, A15/A17,
5
+ * auditoria 2026-07-07, item 3.1). These three functions form one coherent
6
+ * unit around updates: `detectCustomFiles` scans an existing `_wizz/` for
7
+ * files the user added or modified since the last install, `backupUserFiles`
8
+ * copies them out of the way before the update overwrites `_wizz/`, and
9
+ * `restoreUserFiles` copies them back afterwards. All state that the
10
+ * original methods read off `this` (the `Manifest` instance for hashing) is
11
+ * now an explicit parameter — no class, no shared mutable state between
12
+ * calls.
13
+ */
14
+ const path = require('node:path');
15
+ const fs = require('../fs-native');
16
+ const prompts = require('../prompts');
17
+
18
+ /**
19
+ * Detect custom and modified files.
20
+ * @param {string} wizzDir - WIZZ installation directory
21
+ * @param {Array} existingFilesManifest - Previous files from files-manifest.csv
22
+ * @param {Object} deps - Injected dependencies
23
+ * @param {Object} deps.manifest - Manifest instance (used for calculateFileHash)
24
+ * @returns {Object} Object with customFiles and modifiedFiles arrays
25
+ */
26
+ async function detectCustomFiles(wizzDir, existingFilesManifest, { manifest }) {
27
+ const customFiles = [];
28
+ const modifiedFiles = [];
29
+
30
+ // Memory subtrees (v6.1: _wizz/_memory, current: _wizz/memory) hold
31
+ // per-user runtime data generated by agents with sidecars. These files
32
+ // aren't installer-managed and must never be reported as "custom" or
33
+ // "modified" — they're user state, not user overrides.
34
+ const wizzMemoryPaths = ['_memory', 'memory'];
35
+
36
+ // Check if the manifest has hashes - if not, we can't detect modifications
37
+ let manifestHasHashes = false;
38
+ if (existingFilesManifest && existingFilesManifest.length > 0) {
39
+ manifestHasHashes = existingFilesManifest.some((f) => f.hash);
40
+ }
41
+
42
+ // Build map of previously installed files from files-manifest.csv with their hashes
43
+ const installedFilesMap = new Map();
44
+ for (const fileEntry of existingFilesManifest) {
45
+ if (fileEntry.path) {
46
+ const absolutePath = path.join(wizzDir, fileEntry.path);
47
+ installedFilesMap.set(path.normalize(absolutePath), {
48
+ hash: fileEntry.hash,
49
+ relativePath: fileEntry.path,
50
+ });
51
+ }
52
+ }
53
+
54
+ // Recursively scan wizzDir for all files
55
+ const scanDirectory = async (dir) => {
56
+ try {
57
+ const entries = await fs.readdir(dir, { withFileTypes: true });
58
+ for (const entry of entries) {
59
+ const fullPath = path.join(dir, entry.name);
60
+
61
+ if (entry.isDirectory()) {
62
+ // Skip certain directories
63
+ if (entry.name === 'node_modules' || entry.name === '.git') {
64
+ continue;
65
+ }
66
+ await scanDirectory(fullPath);
67
+ } else if (entry.isFile()) {
68
+ const normalizedPath = path.normalize(fullPath);
69
+ const fileInfo = installedFilesMap.get(normalizedPath);
70
+
71
+ // Skip certain system files that are auto-generated
72
+ const relativePath = path.relative(wizzDir, fullPath);
73
+ const fileName = path.basename(fullPath);
74
+
75
+ // Skip _config directory EXCEPT for modified agent customizations
76
+ if (relativePath.startsWith('_config/') || relativePath.startsWith('_config\\')) {
77
+ // Special handling for .customize.yaml files - only preserve if modified
78
+ if (relativePath.includes('/agents/') && fileName.endsWith('.customize.yaml')) {
79
+ // Check if the customization file has been modified from manifest
80
+ const manifestPath = path.join(wizzDir, '_config', 'manifest.yaml');
81
+ if (await fs.pathExists(manifestPath)) {
82
+ const crypto = require('node:crypto');
83
+ const currentContent = await fs.readFile(fullPath, 'utf8');
84
+ const currentHash = crypto.createHash('sha256').update(currentContent).digest('hex');
85
+
86
+ const yaml = require('yaml');
87
+ const manifestContent = await fs.readFile(manifestPath, 'utf8');
88
+ const manifestData = yaml.parse(manifestContent);
89
+ const originalHash = manifestData.agentCustomizations?.[relativePath];
90
+
91
+ // Only add to customFiles if hash differs (user modified)
92
+ if (originalHash && currentHash !== originalHash) {
93
+ customFiles.push(fullPath);
94
+ }
95
+ }
96
+ }
97
+ continue;
98
+ }
99
+
100
+ if (wizzMemoryPaths.some((mp) => relativePath === mp || relativePath.startsWith(mp + '/'))) {
101
+ continue;
102
+ }
103
+
104
+ // Skip config.yaml files - these are regenerated on each install/update
105
+ if (fileName === 'config.yaml') {
106
+ continue;
107
+ }
108
+
109
+ if (!fileInfo) {
110
+ // File not in manifest = custom file
111
+ // EXCEPT: Agent .md files in module folders are generated files, not custom
112
+ // Only treat .md files under _config/agents/ as custom
113
+ if (!(fileName.endsWith('.md') && relativePath.includes('/agents/') && !relativePath.startsWith('_config/'))) {
114
+ customFiles.push(fullPath);
115
+ }
116
+ } else if (manifestHasHashes && fileInfo.hash) {
117
+ // File in manifest with hash - check if it was modified
118
+ const currentHash = await manifest.calculateFileHash(fullPath);
119
+ if (currentHash && currentHash !== fileInfo.hash) {
120
+ // Hash changed = file was modified
121
+ modifiedFiles.push({
122
+ path: fullPath,
123
+ relativePath: fileInfo.relativePath,
124
+ });
125
+ }
126
+ }
127
+ }
128
+ }
129
+ } catch (error) {
130
+ // Best-effort: a permission error mid-scan must not silently decide
131
+ // what gets preserved on the next update (this scan is what
132
+ // detects custom/modified files), so warn instead of swallowing it.
133
+ await prompts.log.warn(`Warning: could not scan ${dir} for custom/modified files: ${error.message}`);
134
+ }
135
+ };
136
+
137
+ await scanDirectory(wizzDir);
138
+ return { customFiles, modifiedFiles };
139
+ }
140
+
141
+ /**
142
+ * Back up custom and modified files to temp directories before overwriting.
143
+ * Returns the temp directory paths (or undefined if no files to back up).
144
+ * @param {Object} paths - InstallPaths instance
145
+ * @param {string[]} customFiles - Absolute paths of custom (user-added) files
146
+ * @param {Object[]} modifiedFiles - Array of { path, relativePath } for modified files
147
+ * @returns {Object} { tempBackupDir, tempModifiedBackupDir } — undefined if no files
148
+ */
149
+ async function backupUserFiles(paths, customFiles, modifiedFiles) {
150
+ let tempBackupDir;
151
+ let tempModifiedBackupDir;
152
+
153
+ if (customFiles.length > 0) {
154
+ tempBackupDir = path.join(paths.projectRoot, '_wizz-custom-backup-temp');
155
+ await fs.ensureDir(tempBackupDir);
156
+
157
+ for (const customFile of customFiles) {
158
+ const relativePath = path.relative(paths.wizzDir, customFile);
159
+ const backupPath = path.join(tempBackupDir, relativePath);
160
+ await fs.ensureDir(path.dirname(backupPath));
161
+ await fs.copy(customFile, backupPath);
162
+ }
163
+ }
164
+
165
+ if (modifiedFiles.length > 0) {
166
+ tempModifiedBackupDir = path.join(paths.projectRoot, '_wizz-modified-backup-temp');
167
+ await fs.ensureDir(tempModifiedBackupDir);
168
+
169
+ for (const modifiedFile of modifiedFiles) {
170
+ const relativePath = path.relative(paths.wizzDir, modifiedFile.path);
171
+ const tempBackupPath = path.join(tempModifiedBackupDir, relativePath);
172
+ await fs.ensureDir(path.dirname(tempBackupPath));
173
+ await fs.copy(modifiedFile.path, tempBackupPath, { overwrite: true });
174
+ }
175
+ }
176
+
177
+ return { tempBackupDir, tempModifiedBackupDir };
178
+ }
179
+
180
+ /**
181
+ * Restore custom and modified files that were backed up before the update.
182
+ * No-op for fresh installs (updateState is null).
183
+ * @param {Object} paths - InstallPaths instance
184
+ * @param {Object|null} updateState - From _prepareUpdateState, or null for fresh installs
185
+ * @returns {Object} { customFiles, modifiedFiles } — lists of restored files
186
+ */
187
+ async function restoreUserFiles(paths, updateState) {
188
+ const noFiles = { customFiles: [], modifiedFiles: [] };
189
+
190
+ if (!updateState || (updateState.customFiles.length === 0 && updateState.modifiedFiles.length === 0)) {
191
+ return noFiles;
192
+ }
193
+
194
+ let restoredCustomFiles = [];
195
+ let restoredModifiedFiles = [];
196
+
197
+ await prompts.tasks([
198
+ {
199
+ title: 'Finalizing installation',
200
+ task: async (message) => {
201
+ if (updateState.customFiles.length > 0) {
202
+ message(`Restoring ${updateState.customFiles.length} custom files...`);
203
+
204
+ for (const originalPath of updateState.customFiles) {
205
+ const relativePath = path.relative(paths.wizzDir, originalPath);
206
+ const backupPath = path.join(updateState.tempBackupDir, relativePath);
207
+
208
+ if (await fs.pathExists(backupPath)) {
209
+ await fs.ensureDir(path.dirname(originalPath));
210
+ await fs.copy(backupPath, originalPath, { overwrite: true });
211
+ }
212
+ }
213
+
214
+ if (updateState.tempBackupDir && (await fs.pathExists(updateState.tempBackupDir))) {
215
+ await fs.remove(updateState.tempBackupDir);
216
+ }
217
+
218
+ restoredCustomFiles = updateState.customFiles;
219
+ }
220
+
221
+ if (updateState.modifiedFiles.length > 0) {
222
+ restoredModifiedFiles = updateState.modifiedFiles;
223
+
224
+ if (updateState.tempModifiedBackupDir && (await fs.pathExists(updateState.tempModifiedBackupDir))) {
225
+ message(`Restoring ${restoredModifiedFiles.length} modified files as .bak...`);
226
+
227
+ for (const modifiedFile of restoredModifiedFiles) {
228
+ const relativePath = path.relative(paths.wizzDir, modifiedFile.path);
229
+ const tempBackupPath = path.join(updateState.tempModifiedBackupDir, relativePath);
230
+ const bakPath = modifiedFile.path + '.bak';
231
+
232
+ if (await fs.pathExists(tempBackupPath)) {
233
+ await fs.ensureDir(path.dirname(bakPath));
234
+ await fs.copy(tempBackupPath, bakPath, { overwrite: true });
235
+ }
236
+ }
237
+
238
+ await fs.remove(updateState.tempModifiedBackupDir);
239
+ }
240
+ }
241
+
242
+ return 'Installation finalized';
243
+ },
244
+ },
245
+ ]);
246
+
247
+ return { customFiles: restoredCustomFiles, modifiedFiles: restoredModifiedFiles };
248
+ }
249
+
250
+ module.exports = { detectCustomFiles, backupUserFiles, restoreUserFiles };
@@ -22,6 +22,24 @@ const USER_AGENT = 'wizz-method-installer';
22
22
  // Per-process cache: { 'owner/repo' => string[] sorted desc } of pure-semver tags.
23
23
  const tagCache = new Map();
24
24
 
25
+ // Retry pontual (1 re-tentativa, backoff curto) para chamadas à API do
26
+ // GitHub. Só re-tenta em erro de rede transitório (timeout, ECONNRESET,
27
+ // ENOTFOUND, EAI_AGAIN, 5xx). Erros lógicos (4xx, ex.: 404 de tag inexistente)
28
+ // nunca são re-tentados — propagam direto.
29
+ const FETCH_RETRY_DELAY_MS = 300;
30
+ const TRANSIENT_ERROR_CODES = new Set(['ECONNRESET', 'ENOTFOUND', 'EAI_AGAIN', 'ETIMEDOUT']);
31
+
32
+ function isTransientError(error) {
33
+ if (!error) return false;
34
+ if (typeof error.statusCode === 'number') return error.statusCode >= 500;
35
+ if (error.code && TRANSIENT_ERROR_CODES.has(error.code)) return true;
36
+ return /timed out/i.test(error.message || '');
37
+ }
38
+
39
+ function delay(ms) {
40
+ return new Promise((resolve) => setTimeout(resolve, ms));
41
+ }
42
+
25
43
  /**
26
44
  * Parse a GitHub repo URL into { owner, repo }. Returns null if the URL is
27
45
  * not a GitHub URL the resolver can handle.
@@ -44,7 +62,7 @@ function parseGitHubRepo(url) {
44
62
  return null;
45
63
  }
46
64
 
47
- function fetchJson(url, { timeout = DEFAULT_TIMEOUT_MS } = {}) {
65
+ function fetchJsonOnce(url, { timeout = DEFAULT_TIMEOUT_MS } = {}) {
48
66
  const headers = {
49
67
  'User-Agent': USER_AGENT,
50
68
  Accept: 'application/vnd.github+json',
@@ -74,11 +92,25 @@ function fetchJson(url, { timeout = DEFAULT_TIMEOUT_MS } = {}) {
74
92
  req.on('error', reject);
75
93
  req.on('timeout', () => {
76
94
  req.destroy();
77
- reject(new Error(`GitHub API request timed out: ${url}`));
95
+ const err = new Error(`GitHub API request timed out: ${url}`);
96
+ err.code = 'ETIMEDOUT';
97
+ reject(err);
78
98
  });
79
99
  });
80
100
  }
81
101
 
102
+ // Wrapper com 1 re-tentativa em erro transitório (ver isTransientError acima).
103
+ // Erro não-transitório (404 de tag, JSON malformado etc.) propaga direto.
104
+ async function fetchJson(url, options = {}) {
105
+ try {
106
+ return await fetchJsonOnce(url, options);
107
+ } catch (error) {
108
+ if (!isTransientError(error)) throw error;
109
+ await delay(FETCH_RETRY_DELAY_MS);
110
+ return fetchJsonOnce(url, options);
111
+ }
112
+ }
113
+
82
114
  /**
83
115
  * Strip a leading 'v' and return a valid semver string, or null if the tag
84
116
  * is not valid semver or is a prerelease (contains -alpha/-beta/-rc/etc.).
@@ -26,6 +26,7 @@
26
26
 
27
27
  const { exec } = require('node:child_process');
28
28
  const { promisify } = require('node:util');
29
+ const { resolveAreaEntries } = require('./registry-resolve');
29
30
 
30
31
  const execAsync = promisify(exec);
31
32
 
@@ -79,42 +80,33 @@ function matchesPlatform(cli, tag) {
79
80
  * `platform:` gate does not match the current OS/arch are dropped too, so a
80
81
  * Mac-only tool is never even suggested on Linux/Windows.
81
82
  *
83
+ * Wrapper fino sobre `resolveAreaEntries` (A16): a resolução por área em si
84
+ * vive em `registry-resolve.js`; aqui só ficam a forma da entrada de CLI e o
85
+ * filtro de elegibilidade (precisa de `install` + bater o gate de plataforma).
86
+ *
82
87
  * @param {Object} registry - Parsed skills-registry.yaml
83
88
  * @param {string[]} [selectedAreas] - Area keys to resolve
84
89
  * @param {string} [platformTag] - Current "<platform>-<arch>" (injectable for tests)
85
- * @returns {Array<{id: string, when: string, check: string, install: string, platform: (string|string[]|undefined), areas: string[]}>}
90
+ * @returns {Array<{id: string, when: string, check: string, install: string, platform: (string|string[]|undefined), min_version: (string|undefined), verify: (string|undefined), areas: string[]}>}
86
91
  */
87
92
  function resolveClis(registry, selectedAreas, platformTag = currentPlatformTag()) {
88
- const byId = new Map();
89
- const areas = (registry && registry.areas) || {};
90
- const wantAll = !selectedAreas || selectedAreas.length === 0 || selectedAreas.includes('all');
91
- const chosen = wantAll ? Object.keys(areas) : selectedAreas;
92
-
93
- const add = (cli, areaKey) => {
94
- if (!cli || !cli.id || !cli.install) return; // not actionable without an install command
95
- if (!matchesPlatform(cli, platformTag)) return; // gated to another OS/arch
96
- const existing = byId.get(cli.id);
97
- if (existing) {
98
- if (areaKey && !existing.areas.includes(areaKey)) existing.areas.push(areaKey);
99
- return;
100
- }
101
- byId.set(cli.id, {
102
- id: cli.id,
93
+ return resolveAreaEntries(registry, selectedAreas, {
94
+ listKey: 'clis',
95
+ utilityKey: 'cli_utility',
96
+ isActionable: (cli) => !!cli.install && matchesPlatform(cli, platformTag),
97
+ mapEntry: (cli) => ({
103
98
  when: cli.when || '',
104
99
  check: cli.check || '',
105
100
  install: cli.install,
106
101
  platform: cli.platform,
107
- areas: areaKey ? [areaKey] : [],
108
- });
109
- };
110
-
111
- for (const area of chosen) {
112
- for (const cli of (areas[area] && areas[area].clis) || []) add(cli, area);
113
- }
114
- // Cross-cutting tools are offered regardless of area selection.
115
- for (const cli of (registry && registry.cli_utility) || []) add(cli, null);
116
-
117
- return [...byId.values()];
102
+ // M27: pin below which `detectClis` reports the entry as needing an
103
+ // upgrade instead of `installed: true`.
104
+ min_version: cli.min_version,
105
+ // M14: post-check/post-install probe for minimal runtime deps (e.g.
106
+ // clone-and-run tools where `check` only proves the clone exists).
107
+ verify: cli.verify,
108
+ }),
109
+ });
118
110
  }
119
111
 
120
112
  /**
@@ -127,12 +119,58 @@ function renderInstallCommand(cli) {
127
119
  return (cli && cli.install) || '';
128
120
  }
129
121
 
122
+ /**
123
+ * Extract the first "x.y.z" version number found in a command's output.
124
+ * @param {string} text
125
+ * @returns {string|null}
126
+ */
127
+ function extractVersion(text) {
128
+ const m = String(text || '').match(/\d+\.\d+\.\d+/);
129
+ return m ? m[0] : null;
130
+ }
131
+
132
+ /**
133
+ * Compare two "x.y.z" version strings numerically, segment by segment (no
134
+ * external semver dependency needed for this simple 3-part comparison).
135
+ * @param {string} a
136
+ * @param {string} b
137
+ * @returns {number} negative if a<b, 0 if equal, positive if a>b
138
+ */
139
+ function compareSemver(a, b) {
140
+ const pa = String(a)
141
+ .split('.')
142
+ .map((n) => Number(n) || 0);
143
+ const pb = String(b)
144
+ .split('.')
145
+ .map((n) => Number(n) || 0);
146
+ for (let i = 0; i < Math.max(pa.length, pb.length); i++) {
147
+ const diff = (pa[i] || 0) - (pb[i] || 0);
148
+ if (diff !== 0) return diff;
149
+ }
150
+ return 0;
151
+ }
152
+
130
153
  /**
131
154
  * Annotate each CLI with `installed: boolean` by running its `check` command.
132
155
  * Immutable: returns new objects, never mutates the input. An entry without a
133
156
  * `check` cannot be verified, so it is reported as not installed (we offer it
134
157
  * rather than silently assume it is present).
135
158
  *
159
+ * M27 (drift do RTK, 0.30.1 rodando com pin v0.43.0): when the entry declares
160
+ * `min_version`, a passing `check` is not enough — we also parse the version
161
+ * out of the check's output and compare it against the pin. Below the pin,
162
+ * the entry comes back `installed: false` (so the caller's existing "missing
163
+ * => offer install" path naturally becomes "offer upgrade") plus an
164
+ * `upgradeMessage` the caller can surface. A version that cannot be parsed
165
+ * falls back to the old ok-only behavior (nothing to compare against).
166
+ *
167
+ * M14 (assimetria MCP vs CLI): when the entry declares `verify` (a check of
168
+ * minimal runtime deps, e.g. `command -v ffmpeg`, for clone-and-run tools
169
+ * where `check` only proves "the clone exists"), it also runs AFTER `check`
170
+ * passes. A failing `verify` means the tool is not genuinely usable, so the
171
+ * entry is reported `installed: false` with a `verifyWarning` — never an
172
+ * abort, just a clearer "not really installed yet" signal (CLIs stay opt-in).
173
+ *
136
174
  * @param {Array<Object>} clis - Resolved CLI entries
137
175
  * @param {Function} [exec] - Injected runner (command, opts) => {ok,...}
138
176
  * @returns {Promise<Array<Object>>} Copies with an added `installed` flag.
@@ -142,7 +180,32 @@ async function detectClis(clis, exec = defaultExec) {
142
180
  (clis || []).map(async (cli) => {
143
181
  if (!cli.check) return { ...cli, installed: false };
144
182
  const res = await exec(cli.check, { timeoutMs: 5000 });
145
- return { ...cli, installed: !!res.ok };
183
+ if (!res.ok) return { ...cli, installed: false };
184
+
185
+ if (cli.min_version) {
186
+ const installedVersion = extractVersion(res.stdout) || extractVersion(res.stderr);
187
+ if (installedVersion && compareSemver(installedVersion, cli.min_version) < 0) {
188
+ return {
189
+ ...cli,
190
+ installed: false,
191
+ installedVersion,
192
+ upgradeMessage: `atualizando ${cli.id} ${installedVersion} → ${cli.min_version}`,
193
+ };
194
+ }
195
+ }
196
+
197
+ if (cli.verify) {
198
+ const verified = await exec(cli.verify, { timeoutMs: 15_000 });
199
+ if (!verified.ok) {
200
+ return {
201
+ ...cli,
202
+ installed: false,
203
+ verifyWarning: `${cli.id}: presente, mas a verificação de dependências falhou (${(verified.stderr || 'erro desconhecido').trim()}) — não considerado plenamente instalado`,
204
+ };
205
+ }
206
+ }
207
+
208
+ return { ...cli, installed: true };
146
209
  }),
147
210
  );
148
211
  }
@@ -152,24 +215,54 @@ async function detectClis(clis, exec = defaultExec) {
152
215
  * a failed install (network, EACCES, missing command) lands in `failed` with
153
216
  * its error so the caller can warn and continue the broader install.
154
217
  *
218
+ * M14: when the entry declares `verify`, it runs once the install succeeds
219
+ * (mirrors mcp-config's post-install VERIFY step). A failing verify does NOT
220
+ * move the entry to `failed` — the install itself worked (e.g. `git clone`
221
+ * for a clone-and-run tool) — it only adds a `warnings` entry so the caller
222
+ * can tell the user their runtime deps (ffmpeg, Ruby, Python...) still need
223
+ * attention. CLIs are opt-in and fail-open: a warning, never an abort.
224
+ *
155
225
  * @param {Object} args
156
- * @param {Array<{id: string, install?: string}>} args.clis - Entries to install
226
+ * @param {Array<{id: string, install?: string, verify?: string}>} args.clis - Entries to install
157
227
  * @param {Function} [args.exec] - Injected runner (command, opts) => {ok,...}
158
- * @returns {Promise<{installed: string[], failed: Array<{id: string, error: string}>}>}
228
+ * @returns {Promise<{installed: string[], failed: Array<{id: string, error: string}>, warnings: Array<{id: string, warning: string}>}>}
159
229
  */
160
230
  async function installClis({ clis, exec = defaultExec }) {
161
231
  const installed = [];
162
232
  const failed = [];
233
+ const warnings = [];
163
234
  for (const cli of clis || []) {
164
235
  if (!cli.install) {
165
236
  failed.push({ id: cli.id, error: 'sem comando de instalação no registry' });
166
237
  continue;
167
238
  }
168
239
  const res = await exec(cli.install, { timeoutMs: 300_000 });
169
- if (res.ok) installed.push(cli.id);
170
- else failed.push({ id: cli.id, error: (res.stderr || 'falha desconhecida').trim() });
240
+ if (!res.ok) {
241
+ failed.push({ id: cli.id, error: (res.stderr || 'falha desconhecida').trim() });
242
+ continue;
243
+ }
244
+ installed.push(cli.id);
245
+ if (cli.verify) {
246
+ const verified = await exec(cli.verify, { timeoutMs: 60_000 });
247
+ if (!verified.ok) {
248
+ warnings.push({
249
+ id: cli.id,
250
+ warning: `verificação pós-install falhou, dependência mínima pode estar ausente: ${(verified.stderr || 'erro desconhecido').trim()}`,
251
+ });
252
+ }
253
+ }
171
254
  }
172
- return { installed, failed };
255
+ return { installed, failed, warnings };
173
256
  }
174
257
 
175
- module.exports = { resolveClis, renderInstallCommand, detectClis, installClis, defaultExec, matchesPlatform, currentPlatformTag };
258
+ module.exports = {
259
+ resolveClis,
260
+ renderInstallCommand,
261
+ detectClis,
262
+ installClis,
263
+ defaultExec,
264
+ matchesPlatform,
265
+ currentPlatformTag,
266
+ extractVersion,
267
+ compareSemver,
268
+ };
@@ -59,7 +59,11 @@ function shapeMcp(mcp) {
59
59
  * @param {Object} args
60
60
  * @param {string[]} [args.selectedAreas] - Chosen area keys ([] => all areas)
61
61
  * @param {{toInstall?: Object[], toRecommend?: Object[], alreadyInstalled?: Object[]}} [args.cliPlan]
62
- * @param {{toWrite?: Object[], toRecommend?: Object[]}} [args.mcpPlan]
62
+ * @param {{toWrite?: Object[], toRecommend?: Object[], pinHashes?: Record<string,string>}} [args.mcpPlan]
63
+ * `pinHashes` (A13) is `writeMcpConfig`'s `pinHashes` result: id => content
64
+ * hash of the server block as it now stands on disk. Persisted here as
65
+ * `mcps.pins` so the NEXT install can tell an untouched block (safe to
66
+ * auto-update the pin) from a user-customized one (never overwritten).
63
67
  * @returns {Object} The manifest to be written.
64
68
  */
65
69
  function buildDepsCache({ selectedAreas, cliPlan = {}, mcpPlan = {} }) {
@@ -75,6 +79,7 @@ function buildDepsCache({ selectedAreas, cliPlan = {}, mcpPlan = {} }) {
75
79
  mcps: {
76
80
  written: (mcpPlan.toWrite || []).map(shapeMcp),
77
81
  recommended: (mcpPlan.toRecommend || []).map(shapeMcp),
82
+ pins: mcpPlan.pinHashes && typeof mcpPlan.pinHashes === 'object' ? { ...mcpPlan.pinHashes } : {},
78
83
  },
79
84
  };
80
85
  }
@@ -130,10 +135,32 @@ async function writeDepsCache({ wizzDir, selectedAreas, cliPlan, mcpPlan, trackF
130
135
  return { wrote: true, file, counts };
131
136
  }
132
137
 
138
+ /**
139
+ * Read the MCP pin hashes recorded by the LAST install (A13), if any. Used
140
+ * before the next `writeMcpConfig` call so it can tell an untouched block
141
+ * (safe to auto-update the pin) from a user-customized one. Never throws: a
142
+ * missing or corrupt cache (or a pre-A13 cache with no `mcps.pins` key) is
143
+ * simply "no history", which downstream treats the same as "customized" —
144
+ * the conservative, never-overwrite default.
145
+ * @param {string} wizzDir - Installed `_wizz` directory
146
+ * @returns {Promise<Record<string,string>>} Map of mcp id => sha256 hash
147
+ */
148
+ async function readPreviousMcpPins(wizzDir) {
149
+ const file = path.join(wizzDir, '_config', CACHE_BASENAME);
150
+ if (!(await fs.pathExists(file))) return {};
151
+ try {
152
+ const cache = JSON.parse(await fs.readFile(file, 'utf8'));
153
+ return (cache && cache.mcps && cache.mcps.pins && typeof cache.mcps.pins === 'object' && cache.mcps.pins) || {};
154
+ } catch {
155
+ return {};
156
+ }
157
+ }
158
+
133
159
  module.exports = {
134
160
  buildDepsCache,
135
161
  isEmptyDepsCache,
136
162
  writeDepsCache,
163
+ readPreviousMcpPins,
137
164
  shapeCli,
138
165
  shapeMcp,
139
166
  CACHE_BASENAME,