wizz-method 2.0.0 → 2.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 (310) hide show
  1. package/LICENSE +60 -30
  2. package/README.md +80 -31
  3. package/SECURITY.md +24 -0
  4. package/THIRD-PARTY-NOTICES.md +136 -0
  5. package/package.json +31 -17
  6. package/skills-registry.yaml +128 -7
  7. package/src/bmm-skills/1-analysis/research/wizz-domain-research/SKILL.md +3 -4
  8. package/src/bmm-skills/1-analysis/research/wizz-domain-research/domain-steps/step-06-research-synthesis.md +1 -1
  9. package/src/bmm-skills/1-analysis/research/wizz-market-research/SKILL.md +3 -4
  10. package/src/bmm-skills/1-analysis/research/wizz-market-research/steps/step-06-research-completion.md +1 -1
  11. package/src/bmm-skills/1-analysis/research/wizz-technical-research/SKILL.md +3 -4
  12. package/src/bmm-skills/1-analysis/research/wizz-technical-research/technical-steps/step-06-research-synthesis.md +1 -1
  13. package/src/bmm-skills/1-analysis/wizz-agent-analyst/SKILL.md +3 -4
  14. package/src/bmm-skills/1-analysis/wizz-agent-tech-writer/SKILL.md +3 -4
  15. package/src/bmm-skills/1-analysis/wizz-document-project/SKILL.md +3 -4
  16. package/src/bmm-skills/1-analysis/wizz-document-project/workflows/deep-dive-instructions.md +1 -1
  17. package/src/bmm-skills/1-analysis/wizz-document-project/workflows/full-scan-instructions.md +1 -1
  18. package/src/bmm-skills/1-analysis/wizz-prfaq/SKILL.md +3 -4
  19. package/src/bmm-skills/1-analysis/wizz-prfaq/references/verdict.md +1 -1
  20. package/src/bmm-skills/1-analysis/wizz-product-brief/SKILL.md +1 -1
  21. package/src/bmm-skills/2-plan-workflows/wizz-agent-pm/SKILL.md +3 -4
  22. package/src/bmm-skills/2-plan-workflows/wizz-agent-ux-designer/SKILL.md +3 -4
  23. package/src/bmm-skills/2-plan-workflows/wizz-create-prd/SKILL.md +1 -1
  24. package/src/bmm-skills/2-plan-workflows/wizz-edit-prd/SKILL.md +1 -1
  25. package/src/bmm-skills/2-plan-workflows/wizz-prd/SKILL.md +1 -1
  26. package/src/bmm-skills/2-plan-workflows/wizz-ux/SKILL.md +1 -1
  27. package/src/bmm-skills/2-plan-workflows/wizz-validate-prd/SKILL.md +1 -1
  28. package/src/bmm-skills/3-solutioning/wizz-agent-architect/SKILL.md +3 -4
  29. package/src/bmm-skills/3-solutioning/wizz-architecture/SKILL.md +9 -9
  30. package/src/bmm-skills/3-solutioning/wizz-architecture/references/headless.md +1 -1
  31. package/src/bmm-skills/3-solutioning/wizz-check-implementation-readiness/SKILL.md +3 -4
  32. package/src/bmm-skills/3-solutioning/wizz-check-implementation-readiness/steps/step-06-final-assessment.md +1 -1
  33. package/src/bmm-skills/3-solutioning/wizz-create-architecture/SKILL.md +1 -1
  34. package/src/bmm-skills/3-solutioning/wizz-create-epics-and-stories/SKILL.md +3 -4
  35. package/src/bmm-skills/3-solutioning/wizz-create-epics-and-stories/steps/step-04-final-validation.md +1 -1
  36. package/src/bmm-skills/3-solutioning/wizz-generate-project-context/SKILL.md +3 -4
  37. package/src/bmm-skills/3-solutioning/wizz-generate-project-context/steps/step-03-complete.md +1 -1
  38. package/src/bmm-skills/4-implementation/wizz-agent-dev/SKILL.md +3 -4
  39. package/src/bmm-skills/4-implementation/wizz-checkpoint-preview/SKILL.md +3 -4
  40. package/src/bmm-skills/4-implementation/wizz-checkpoint-preview/step-05-wrapup.md +1 -1
  41. package/src/bmm-skills/4-implementation/wizz-code-review/SKILL.md +3 -4
  42. package/src/bmm-skills/4-implementation/wizz-code-review/customize.toml +3 -8
  43. package/src/bmm-skills/4-implementation/wizz-code-review/review-prompts/blind-hunter.md +20 -0
  44. package/src/bmm-skills/4-implementation/wizz-code-review/steps/step-04-present.md +1 -1
  45. package/src/bmm-skills/4-implementation/wizz-correct-course/SKILL.md +4 -5
  46. package/src/bmm-skills/4-implementation/wizz-create-story/SKILL.md +4 -5
  47. package/src/bmm-skills/4-implementation/wizz-dev-story/SKILL.md +4 -5
  48. package/src/bmm-skills/4-implementation/wizz-investigate/SKILL.md +1 -1
  49. package/src/bmm-skills/4-implementation/wizz-qa-generate-e2e-tests/SKILL.md +4 -5
  50. package/src/bmm-skills/4-implementation/wizz-quick-dev/SKILL.md +4 -5
  51. package/src/bmm-skills/4-implementation/wizz-quick-dev/customize.toml +10 -22
  52. package/src/bmm-skills/4-implementation/wizz-quick-dev/review-prompts/blind-hunter.md +20 -0
  53. package/src/bmm-skills/4-implementation/wizz-quick-dev/step-05-present.md +1 -1
  54. package/src/bmm-skills/4-implementation/wizz-quick-dev/step-oneshot.md +1 -1
  55. package/src/bmm-skills/4-implementation/wizz-retrospective/SKILL.md +1 -2
  56. package/src/bmm-skills/4-implementation/wizz-sprint-planning/SKILL.md +1 -1
  57. package/src/bmm-skills/4-implementation/wizz-sprint-status/SKILL.md +5 -6
  58. package/src/core-skills/_shared/handoff-protocol.md +9 -0
  59. package/src/core-skills/wizz-advanced-elicitation/SKILL.md +2 -2
  60. package/src/core-skills/wizz-brainstorming/SKILL.md +6 -6
  61. package/src/core-skills/wizz-brainstorming/references/converge.md +1 -1
  62. package/src/core-skills/wizz-brainstorming/references/finalize.md +1 -1
  63. package/src/core-skills/wizz-brainstorming/references/headless.md +3 -3
  64. package/src/core-skills/wizz-brainstorming/references/mode-autonomous.md +1 -1
  65. package/src/core-skills/wizz-customize/SKILL.md +13 -10
  66. package/src/core-skills/wizz-forge-idea/SKILL.md +6 -6
  67. package/src/core-skills/wizz-forge-idea/scripts/__pycache__/resolve_personas.cpython-314.pyc +0 -0
  68. package/src/core-skills/wizz-forge-idea/scripts/resolve_personas.py +17 -1
  69. package/src/core-skills/wizz-party-mode/SKILL.md +3 -3
  70. package/src/core-skills/wizz-party-mode/references/create-party.md +1 -1
  71. package/src/core-skills/wizz-party-mode/references/party-memory.md +2 -2
  72. package/src/core-skills/wizz-party-mode/scripts/__pycache__/resolve_party.cpython-314.pyc +0 -0
  73. package/src/core-skills/wizz-party-mode/scripts/resolve_party.py +17 -1
  74. package/src/core-skills/wizz-review-adversarial-general/SKILL.md +1 -1
  75. package/src/core-skills/wizz-spec/SKILL.md +5 -5
  76. package/src/modules/lowticket/README.md +6 -6
  77. package/src/modules/lowticket/module.yaml +4 -1
  78. package/src/modules/lowticket/skills/{lowticket-funil → wizz-lowticket-funil}/SKILL.md +4 -4
  79. package/src/modules/lowticket/skills/{lowticket-funil → wizz-lowticket-funil}/references/copy-das-paginas.md +1 -1
  80. package/src/modules/lowticket/skills/{lowticket-metodologia → wizz-lowticket-metodologia}/SKILL.md +1 -1
  81. package/src/modules/lowticket/skills/{lowticket-minerador → wizz-lowticket-minerador}/SKILL.md +3 -3
  82. package/src/modules/lowticket/skills/{lowticket-minerador → wizz-lowticket-minerador}/references/rubrica.md +1 -1
  83. package/src/modules/lowticket/skills/{lowticket-pagina → wizz-lowticket-pagina}/SKILL.md +4 -4
  84. package/src/modules/lowticket/skills/{lowticket-trafego → wizz-lowticket-trafego}/SKILL.md +3 -3
  85. package/src/modules/lowticket/skills/{lowticket-trafego → wizz-lowticket-trafego}/references/reguas.md +1 -1
  86. package/src/modules/wizz/_shared/communication-rules.md +1 -1
  87. package/src/modules/wizz/_shared/despacho-barato.md +9 -0
  88. package/src/modules/wizz/_shared/token-economy.md +7 -0
  89. package/src/modules/wizz/agents/wizz-ads/SKILL.md +1 -1
  90. package/src/modules/wizz/agents/wizz-ads/customize.toml +1 -2
  91. package/src/modules/wizz/agents/wizz-copy/SKILL.md +1 -1
  92. package/src/modules/wizz/agents/wizz-copy/customize.toml +1 -2
  93. package/src/modules/wizz/agents/wizz-designer/SKILL.md +1 -1
  94. package/src/modules/wizz/agents/wizz-designer/customize.toml +1 -2
  95. package/src/modules/wizz/agents/wizz-growth/SKILL.md +1 -1
  96. package/src/modules/wizz/agents/wizz-growth/customize.toml +1 -2
  97. package/src/modules/wizz/agents/wizz-maestro/SKILL.md +5 -5
  98. package/src/modules/wizz/agents/wizz-maestro/customize.toml +4 -8
  99. package/src/modules/wizz/agents/wizz-memoria/SKILL.md +1 -1
  100. package/src/modules/wizz/agents/wizz-memoria/customize.toml +1 -2
  101. package/src/modules/wizz/agents/wizz-qa/SKILL.md +1 -1
  102. package/src/modules/wizz/agents/wizz-qa/customize.toml +1 -2
  103. package/src/modules/wizz/agents/wizz-seo/SKILL.md +1 -1
  104. package/src/modules/wizz/agents/wizz-seo/customize.toml +1 -2
  105. package/src/modules/wizz/agents/wizz-social/SKILL.md +1 -1
  106. package/src/modules/wizz/agents/wizz-social/customize.toml +1 -2
  107. package/src/modules/wizz/module.yaml +3 -0
  108. package/src/modules/wizz/overrides/wizz-agent-analyst.toml +1 -2
  109. package/src/modules/wizz/overrides/wizz-agent-architect.toml +1 -2
  110. package/src/modules/wizz/overrides/wizz-agent-dev.toml +1 -2
  111. package/src/modules/wizz/overrides/wizz-agent-pm.toml +1 -2
  112. package/src/modules/wizz/overrides/wizz-agent-tech-writer.toml +1 -2
  113. package/src/modules/wizz/overrides/wizz-agent-ux-designer.toml +1 -2
  114. package/src/modules/wizz/subagents/codex/wizz-exec-haiku.toml +2 -0
  115. package/src/modules/wizz/subagents/codex/wizz-exec-opus.toml +2 -0
  116. package/src/modules/wizz/subagents/codex/wizz-exec-review.toml +2 -0
  117. package/src/modules/wizz/subagents/codex/wizz-exec-sonnet.toml +2 -0
  118. package/src/modules/wizz/subagents/gemini/wizz-exec-haiku.md +4 -1
  119. package/src/modules/wizz/subagents/gemini/wizz-exec-opus.md +4 -1
  120. package/src/modules/wizz/subagents/gemini/wizz-exec-review.md +4 -1
  121. package/src/modules/wizz/subagents/gemini/wizz-exec-sonnet.md +4 -1
  122. package/src/modules/wizz/subagents/opencode/wizz-exec-haiku.md +4 -1
  123. package/src/modules/wizz/subagents/opencode/wizz-exec-opus.md +4 -1
  124. package/src/modules/wizz/subagents/opencode/wizz-exec-review.md +4 -1
  125. package/src/modules/wizz/subagents/opencode/wizz-exec-sonnet.md +4 -1
  126. package/src/modules/wizz/subagents/spec.yaml +148 -0
  127. package/src/modules/wizz/subagents/wizz-exec-haiku.md +4 -1
  128. package/src/modules/wizz/subagents/wizz-exec-opus.md +4 -1
  129. package/src/modules/wizz/subagents/wizz-exec-review.md +4 -1
  130. package/src/modules/wizz/subagents/wizz-exec-sonnet.md +4 -1
  131. package/src/scripts/__pycache__/resolve_customization.cpython-314.pyc +0 -0
  132. package/src/scripts/memlog.js +368 -0
  133. package/src/scripts/resolve_customization.py +124 -15
  134. package/src/skills-lib/_shared/complexity-signal.md +14 -0
  135. package/src/skills-lib/wizz-canvas-design/canvas-fonts/InstrumentSerif-OFL.txt +93 -0
  136. package/src/skills-lib/wizz-huashu-design/references/sfx-library.md +1 -1
  137. package/src/skills-lib/wizz-huashu-design/scripts/add-music.sh +1 -1
  138. package/src/skills-lib/wizz-huashu-design/scripts/mix-voiceover.sh +1 -1
  139. package/src/skills-lib/wizz-impeccable/LICENSE.txt +202 -0
  140. package/src/skills-lib/wizz-offer-forge/SKILL.md +1 -1
  141. package/src/skills-lib/wizz-react-components/LICENSE.txt +202 -0
  142. package/src/skills-lib/wizz-router/SKILL.md +2 -2
  143. package/src/skills-lib/wizz-supabase-postgres-best-practices/LICENSE +21 -0
  144. package/src/skills-lib/wizz-taste-skill/SKILL.md +1 -1
  145. package/src/skills-lib/wizz-tracking-audit/SKILL.md +1 -1
  146. package/tools/fetch-assets.mjs +62 -37
  147. package/tools/hooks/README.md +22 -0
  148. package/tools/hooks/rtk-rewrite.sh +280 -0
  149. package/tools/hooks/security-defensive-context.js +70 -0
  150. package/tools/hooks/session-rules.js +368 -0
  151. package/tools/hooks/wizz-decision-trace.js +389 -0
  152. package/tools/hooks/wizz-router-enforce.js +258 -0
  153. package/tools/installer/banner.js +1 -1
  154. package/tools/installer/commands/doctor.js +124 -0
  155. package/tools/installer/commands/install.js +1 -1
  156. package/tools/installer/commands/resolve.js +95 -0
  157. package/tools/installer/core/doctor.js +648 -0
  158. package/tools/installer/core/hash-cache.js +156 -0
  159. package/tools/installer/core/help-catalog.js +4 -1
  160. package/tools/installer/core/hooks-settings.js +178 -0
  161. package/tools/installer/core/installer.js +297 -15
  162. package/tools/installer/core/legacy-warnings.js +0 -4
  163. package/tools/installer/core/manifest-generator.js +121 -43
  164. package/tools/installer/core/manifest.js +36 -32
  165. package/tools/installer/core/module-config-writer.js +4 -1
  166. package/tools/installer/core/python-check.js +60 -63
  167. package/tools/installer/core/quick-update.js +76 -43
  168. package/tools/installer/core/resolved-config.js +168 -0
  169. package/tools/installer/core/resolved-customizations.js +736 -0
  170. package/tools/installer/core/resolved-includes.js +262 -0
  171. package/tools/installer/core/resolved-schema.js +148 -0
  172. package/tools/installer/core/user-file-preservation.js +40 -8
  173. package/tools/installer/core/wizz-dir.js +117 -0
  174. package/tools/installer/core/yaml-cache.js +105 -0
  175. package/tools/installer/fs-native.js +97 -6
  176. package/tools/installer/ide/_config-driven.js +12 -75
  177. package/tools/installer/ide/platform-codes.js +111 -16
  178. package/tools/installer/ide/platform-codes.yaml +45 -100
  179. package/tools/installer/ide/shared/path-utils.js +6 -208
  180. package/tools/installer/install-messages.yaml +4 -14
  181. package/tools/installer/modules/channel-plan.js +15 -2
  182. package/tools/installer/modules/config-collector.js +762 -0
  183. package/tools/installer/modules/config-values.js +352 -0
  184. package/tools/installer/modules/custom-module-manager.js +161 -28
  185. package/tools/installer/modules/env-vars.js +119 -0
  186. package/tools/installer/modules/external-manager.js +133 -60
  187. package/tools/installer/modules/git-cache-utils.js +125 -0
  188. package/tools/installer/modules/module-catalog.js +565 -0
  189. package/tools/installer/modules/module-installer.js +618 -0
  190. package/tools/installer/modules/module-interface.js +86 -0
  191. package/tools/installer/modules/official-modules.js +98 -2172
  192. package/tools/installer/modules/pin-spec.js +125 -0
  193. package/tools/installer/modules/plugin-resolver.js +4 -0
  194. package/tools/installer/modules/skills-lib.js +3 -6
  195. package/tools/installer/prompts.js +0 -3
  196. package/tools/installer/ui.js +89 -54
  197. package/tools/installer/wizz-cli.js +1 -1
  198. package/tools/lib/frontmatter.js +139 -0
  199. package/tools/lib/sync-targets.mjs +49 -0
  200. package/tools/lib/walk.js +93 -0
  201. package/wizz-modules.yaml +9 -0
  202. package/src/scripts/__pycache__/memlog.cpython-313.pyc +0 -0
  203. package/src/scripts/memlog.py +0 -233
  204. package/src/scripts/tests/__pycache__/test_memlog.cpython-313-pytest-9.1.1.pyc +0 -0
  205. package/src/scripts/tests/__pycache__/test_resolve_customization.cpython-313-pytest-9.1.1.pyc +0 -0
  206. package/src/scripts/tests/test_memlog.py +0 -306
  207. package/src/skills-lib/wizz-huashu-design/assets/showcases/INDEX.md +0 -115
  208. package/src/skills-lib/wizz-huashu-design/assets/showcases/cover/cover-build.html +0 -235
  209. package/src/skills-lib/wizz-huashu-design/assets/showcases/cover/cover-build.png +0 -0
  210. package/src/skills-lib/wizz-huashu-design/assets/showcases/cover/cover-pentagram.html +0 -229
  211. package/src/skills-lib/wizz-huashu-design/assets/showcases/cover/cover-pentagram.png +0 -0
  212. package/src/skills-lib/wizz-huashu-design/assets/showcases/cover/cover-takram.html +0 -288
  213. package/src/skills-lib/wizz-huashu-design/assets/showcases/cover/cover-takram.png +0 -0
  214. package/src/skills-lib/wizz-huashu-design/assets/showcases/infographic/infographic-build.html +0 -503
  215. package/src/skills-lib/wizz-huashu-design/assets/showcases/infographic/infographic-build.png +0 -0
  216. package/src/skills-lib/wizz-huashu-design/assets/showcases/infographic/infographic-pentagram.html +0 -600
  217. package/src/skills-lib/wizz-huashu-design/assets/showcases/infographic/infographic-pentagram.png +0 -0
  218. package/src/skills-lib/wizz-huashu-design/assets/showcases/infographic/infographic-takram.html +0 -670
  219. package/src/skills-lib/wizz-huashu-design/assets/showcases/infographic/infographic-takram.png +0 -0
  220. package/src/skills-lib/wizz-huashu-design/assets/showcases/ppt/ppt-build.html +0 -382
  221. package/src/skills-lib/wizz-huashu-design/assets/showcases/ppt/ppt-build.png +0 -0
  222. package/src/skills-lib/wizz-huashu-design/assets/showcases/ppt/ppt-pentagram.html +0 -536
  223. package/src/skills-lib/wizz-huashu-design/assets/showcases/ppt/ppt-pentagram.png +0 -0
  224. package/src/skills-lib/wizz-huashu-design/assets/showcases/ppt/ppt-takram.html +0 -497
  225. package/src/skills-lib/wizz-huashu-design/assets/showcases/ppt/ppt-takram.png +0 -0
  226. package/src/skills-lib/wizz-huashu-design/assets/showcases/website-ai-nav/ainav-build.html +0 -385
  227. package/src/skills-lib/wizz-huashu-design/assets/showcases/website-ai-nav/ainav-build.png +0 -0
  228. package/src/skills-lib/wizz-huashu-design/assets/showcases/website-ai-nav/ainav-pentagram.html +0 -422
  229. package/src/skills-lib/wizz-huashu-design/assets/showcases/website-ai-nav/ainav-pentagram.png +0 -0
  230. package/src/skills-lib/wizz-huashu-design/assets/showcases/website-ai-nav/ainav-takram.html +0 -499
  231. package/src/skills-lib/wizz-huashu-design/assets/showcases/website-ai-nav/ainav-takram.png +0 -0
  232. package/src/skills-lib/wizz-huashu-design/assets/showcases/website-ai-writing/aiwriting-build.html +0 -562
  233. package/src/skills-lib/wizz-huashu-design/assets/showcases/website-ai-writing/aiwriting-build.png +0 -0
  234. package/src/skills-lib/wizz-huashu-design/assets/showcases/website-ai-writing/aiwriting-pentagram.html +0 -548
  235. package/src/skills-lib/wizz-huashu-design/assets/showcases/website-ai-writing/aiwriting-pentagram.png +0 -0
  236. package/src/skills-lib/wizz-huashu-design/assets/showcases/website-ai-writing/aiwriting-takram.html +0 -696
  237. package/src/skills-lib/wizz-huashu-design/assets/showcases/website-ai-writing/aiwriting-takram.png +0 -0
  238. package/src/skills-lib/wizz-huashu-design/assets/showcases/website-devdocs/devdocs-build.html +0 -372
  239. package/src/skills-lib/wizz-huashu-design/assets/showcases/website-devdocs/devdocs-build.png +0 -0
  240. package/src/skills-lib/wizz-huashu-design/assets/showcases/website-devdocs/devdocs-pentagram.html +0 -460
  241. package/src/skills-lib/wizz-huashu-design/assets/showcases/website-devdocs/devdocs-pentagram.png +0 -0
  242. package/src/skills-lib/wizz-huashu-design/assets/showcases/website-devdocs/devdocs-takram.html +0 -494
  243. package/src/skills-lib/wizz-huashu-design/assets/showcases/website-devdocs/devdocs-takram.png +0 -0
  244. package/src/skills-lib/wizz-huashu-design/assets/showcases/website-homepage/homepage-build.html +0 -367
  245. package/src/skills-lib/wizz-huashu-design/assets/showcases/website-homepage/homepage-build.png +0 -0
  246. package/src/skills-lib/wizz-huashu-design/assets/showcases/website-homepage/homepage-pentagram.html +0 -368
  247. package/src/skills-lib/wizz-huashu-design/assets/showcases/website-homepage/homepage-pentagram.png +0 -0
  248. package/src/skills-lib/wizz-huashu-design/assets/showcases/website-homepage/homepage-takram.html +0 -459
  249. package/src/skills-lib/wizz-huashu-design/assets/showcases/website-homepage/homepage-takram.png +0 -0
  250. package/src/skills-lib/wizz-huashu-design/assets/showcases/website-saas/saas-build.html +0 -493
  251. package/src/skills-lib/wizz-huashu-design/assets/showcases/website-saas/saas-build.png +0 -0
  252. package/src/skills-lib/wizz-huashu-design/assets/showcases/website-saas/saas-pentagram.html +0 -556
  253. package/src/skills-lib/wizz-huashu-design/assets/showcases/website-saas/saas-pentagram.png +0 -0
  254. package/src/skills-lib/wizz-huashu-design/assets/showcases/website-saas/saas-takram.html +0 -604
  255. package/src/skills-lib/wizz-huashu-design/assets/showcases/website-saas/saas-takram.png +0 -0
  256. package/tools/installer/file-ops.js +0 -204
  257. package/tools/installer/ide/shared/skill-manifest.js +0 -57
  258. package/tools/installer/yaml-format.js +0 -245
  259. package/web-bundles/README.md +0 -46
  260. package/web-bundles/brainstorming-coach/INSTRUCTIONS.md +0 -86
  261. package/web-bundles/brainstorming-coach/SKILL.md +0 -83
  262. package/web-bundles/brainstorming-coach/brain-methods.csv +0 -62
  263. package/web-bundles/bundles.json +0 -139
  264. package/web-bundles/market-and-industry-research/INSTRUCTIONS.md +0 -88
  265. package/web-bundles/market-and-industry-research/SKILL.md +0 -59
  266. package/web-bundles/prd-coach/INSTRUCTIONS.md +0 -86
  267. package/web-bundles/prd-coach/SKILL.md +0 -101
  268. package/web-bundles/prd-coach/prd-template.md +0 -165
  269. package/web-bundles/prd-coach/prd-validation-checklist.md +0 -135
  270. package/web-bundles/prfaq-coach/INSTRUCTIONS.md +0 -86
  271. package/web-bundles/prfaq-coach/SKILL.md +0 -139
  272. package/web-bundles/product-brief-coach/INSTRUCTIONS.md +0 -86
  273. package/web-bundles/product-brief-coach/SKILL.md +0 -113
  274. package/web-bundles/ux-coach/INSTRUCTIONS.md +0 -92
  275. package/web-bundles/ux-coach/SKILL.md +0 -187
  276. package/web-bundles/ux-coach/ux-validation.md +0 -100
  277. /package/src/modules/lowticket/skills/{lowticket-funil → wizz-lowticket-funil}/references/mapa-do-funil.md +0 -0
  278. /package/src/modules/lowticket/skills/{lowticket-metodologia → wizz-lowticket-metodologia}/CATALOGO.md +0 -0
  279. /package/src/modules/lowticket/skills/{lowticket-metodologia → wizz-lowticket-metodologia}/knowledge/01-principios.md +0 -0
  280. /package/src/modules/lowticket/skills/{lowticket-metodologia → wizz-lowticket-metodologia}/knowledge/02-diagnostico-funil.md +0 -0
  281. /package/src/modules/lowticket/skills/{lowticket-metodologia → wizz-lowticket-metodologia}/knowledge/03-campanha-bidcap.md +0 -0
  282. /package/src/modules/lowticket/skills/{lowticket-metodologia → wizz-lowticket-metodologia}/knowledge/04-criativos.md +0 -0
  283. /package/src/modules/lowticket/skills/{lowticket-metodologia → wizz-lowticket-metodologia}/knowledge/04a-criativos-ia.md +0 -0
  284. /package/src/modules/lowticket/skills/{lowticket-metodologia → wizz-lowticket-metodologia}/knowledge/04b-criativos-formatos.md +0 -0
  285. /package/src/modules/lowticket/skills/{lowticket-metodologia → wizz-lowticket-metodologia}/knowledge/05-oferta.md +0 -0
  286. /package/src/modules/lowticket/skills/{lowticket-metodologia → wizz-lowticket-metodologia}/knowledge/06-pagina-vendas.md +0 -0
  287. /package/src/modules/lowticket/skills/{lowticket-metodologia → wizz-lowticket-metodologia}/knowledge/06a-instagram.md +0 -0
  288. /package/src/modules/lowticket/skills/{lowticket-metodologia → wizz-lowticket-metodologia}/knowledge/06b-player-vsl.md +0 -0
  289. /package/src/modules/lowticket/skills/{lowticket-metodologia → wizz-lowticket-metodologia}/knowledge/07-funil-upsell.md +0 -0
  290. /package/src/modules/lowticket/skills/{lowticket-metodologia → wizz-lowticket-metodologia}/knowledge/07a-copy-humanizacao.md +0 -0
  291. /package/src/modules/lowticket/skills/{lowticket-metodologia → wizz-lowticket-metodologia}/knowledge/08-pesquisa-publico.md +0 -0
  292. /package/src/modules/lowticket/skills/{lowticket-metodologia → wizz-lowticket-metodologia}/knowledge/09-especialista-coproducao.md +0 -0
  293. /package/src/modules/lowticket/skills/{lowticket-metodologia → wizz-lowticket-metodologia}/knowledge/10-levantar-caixa.md +0 -0
  294. /package/src/modules/lowticket/skills/{lowticket-metodologia → wizz-lowticket-metodologia}/knowledge/11-checklist-roi.md +0 -0
  295. /package/src/modules/lowticket/skills/{lowticket-metodologia → wizz-lowticket-metodologia}/knowledge/12-mineracao-ofertas.md +0 -0
  296. /package/src/modules/lowticket/skills/{lowticket-metodologia → wizz-lowticket-metodologia}/knowledge/12a-mineracao-veredito.md +0 -0
  297. /package/src/modules/lowticket/skills/{lowticket-metodologia → wizz-lowticket-metodologia}/knowledge/12b-fabrica-de-ofertas.md +0 -0
  298. /package/src/modules/lowticket/skills/{lowticket-metodologia → wizz-lowticket-metodologia}/knowledge/12c-anatomia-low-ticket.md +0 -0
  299. /package/src/modules/lowticket/skills/{lowticket-metodologia → wizz-lowticket-metodologia}/knowledge/13-benchmarks-vsl.md +0 -0
  300. /package/src/modules/lowticket/skills/{lowticket-metodologia → wizz-lowticket-metodologia}/knowledge/14-vocabulario.md +0 -0
  301. /package/src/modules/lowticket/skills/{lowticket-metodologia → wizz-lowticket-metodologia}/knowledge/15-como-estender.md +0 -0
  302. /package/src/modules/lowticket/skills/{lowticket-metodologia → wizz-lowticket-metodologia}/knowledge/17-rastreamento.md +0 -0
  303. /package/src/modules/lowticket/skills/{lowticket-metodologia → wizz-lowticket-metodologia}/knowledge/18-copy-desejo-oferta.md +0 -0
  304. /package/src/modules/lowticket/skills/{lowticket-metodologia → wizz-lowticket-metodologia}/knowledge/INDEX.md +0 -0
  305. /package/src/modules/lowticket/skills/{lowticket-metodologia → wizz-lowticket-metodologia}/knowledge/guardrails.md +0 -0
  306. /package/src/modules/lowticket/skills/{lowticket-metodologia → wizz-lowticket-metodologia}/knowledge/pontos-em-aberto.md +0 -0
  307. /package/src/modules/lowticket/skills/{lowticket-metodologia → wizz-lowticket-metodologia}/references/swipe-file.md +0 -0
  308. /package/src/modules/lowticket/skills/{lowticket-pagina → wizz-lowticket-pagina}/references/metas-e-medicao.md +0 -0
  309. /package/src/modules/lowticket/skills/{lowticket-pagina → wizz-lowticket-pagina}/references/padroes-de-codigo.md +0 -0
  310. /package/src/modules/lowticket/skills/{lowticket-trafego → wizz-lowticket-trafego}/references/formato-do-diagnostico.md +0 -0
@@ -0,0 +1,262 @@
1
+ /**
2
+ * Include expansion for customize.toml layers.
3
+ *
4
+ * Extracted from `resolved-customizations.js` (2026-09-11) to keep that file
5
+ * under the 800-line cap and to give the `_shared/` fallback a home. Kept in
6
+ * lock-step with `src/scripts/resolve_customization.py`: the two resolvers
7
+ * must produce byte-identical JSON, and `test/test-resolved-customizations.js`
8
+ * diffs them on every run.
9
+ *
10
+ * The `_shared/` fallback (bug found 2026-09-11): the verbatim pipeline moves
11
+ * each skill directory OUT of `_wizz/` into the IDE folder, e.g.
12
+ * `.claude/skills/wizz-maestro/customize.toml`, while that file keeps its
13
+ * shipped `include = ["../../_shared/communication-rules.md"]`. From the
14
+ * deployed location that relative path resolves to `.claude/_shared/...`,
15
+ * which does not exist, so every included paragraph was dropped silently.
16
+ * The real shared files live at `<project-root>/_wizz/<module>/_shared/`.
17
+ * So: when the base-relative path is missing AND the include mentions
18
+ * `_shared/`, the segment after the LAST `_shared/` is looked up under
19
+ * `<project-root>/_wizz/<module>/_shared/` for every module that has one,
20
+ * in sorted order, first hit wins. Nothing else is guessed.
21
+ *
22
+ * Containment (hardening, 2026-09-11): when a project root is known, an
23
+ * include whose base-relative path escapes that root (`../../../../x.md`) is
24
+ * refused before it is ever read — a customize.toml must not pull arbitrary
25
+ * files from the user's home or from a sibling checkout into an agent's
26
+ * activation steps. The `_shared/` fallback candidates are built under
27
+ * `<project-root>/_wizz/` by construction, so they always pass. A standalone
28
+ * skill (no project root resolvable) keeps the old unrestricted behaviour —
29
+ * there is no root to be outside of. `resolve_customization.py` implements
30
+ * the identical rule with the identical wording.
31
+ */
32
+
33
+ const path = require('node:path');
34
+ const nodeFs = require('node:fs');
35
+ const { WIZZ_FOLDER_NAME } = require('../ide/shared/path-utils');
36
+
37
+ const INCLUDE_TARGET_FIELD = 'activation_steps_append';
38
+ const SHARED_DIR_NAME = '_shared';
39
+
40
+ // Keys that JavaScript treats specially on assignment: writing
41
+ // `obj.__proto__ = x` walks the Object.prototype setter (mutating the
42
+ // prototype chain) instead of creating an own property, so `[agent.__proto__]`
43
+ // in a customize.toml silently disappeared from the snapshot. smol-toml
44
+ // itself parses into null-prototype objects, so the only unsafe step was
45
+ // ours — every write goes through `safeSet`.
46
+ const DANGEROUS_KEYS = new Set(['__proto__', 'constructor', 'prototype']);
47
+
48
+ /**
49
+ * Define `key` on `target` as a plain own data property, bypassing the
50
+ * `__proto__` setter and any inherited accessor. Parity with Python dicts,
51
+ * where these are ordinary keys.
52
+ */
53
+ function safeSet(target, key, value) {
54
+ if (DANGEROUS_KEYS.has(key)) {
55
+ Object.defineProperty(target, key, { value, writable: true, enumerable: true, configurable: true });
56
+ } else {
57
+ target[key] = value;
58
+ }
59
+ return target;
60
+ }
61
+
62
+ function hasOwn(obj, key) {
63
+ return Object.prototype.hasOwnProperty.call(obj, key);
64
+ }
65
+
66
+ function isPlainObject(value) {
67
+ return value !== null && typeof value === 'object' && !Array.isArray(value);
68
+ }
69
+
70
+ function isFile(absPath) {
71
+ try {
72
+ return nodeFs.statSync(absPath).isFile();
73
+ } catch {
74
+ return false;
75
+ }
76
+ }
77
+
78
+ /**
79
+ * Split an included markdown file into instruction strings: blocks
80
+ * separated by a blank line, internal newlines collapsed to single
81
+ * spaces, blocks made only of `#` lines dropped. Python
82
+ * `_split_include_paragraphs` parity.
83
+ */
84
+ function splitIncludeParagraphs(text) {
85
+ const paragraphs = [];
86
+ for (const block of text.trim().split(/\n\s*\n/)) {
87
+ const lines = block
88
+ .split('\n')
89
+ .map((line) => line.trim())
90
+ .filter((line) => line.length > 0);
91
+ if (lines.every((line) => line.startsWith('#'))) continue;
92
+ paragraphs.push(lines.join(' '));
93
+ }
94
+ return paragraphs;
95
+ }
96
+
97
+ /**
98
+ * Absolute candidates for an include whose base-relative path is missing.
99
+ * Empty unless `relPath` mentions `_shared/` and a project root is known.
100
+ * Deterministic: modules sorted by name, first existing hit wins upstream.
101
+ * Python `_shared_fallback_candidates` parity.
102
+ * @param {string} relPath - the include as written in the TOML
103
+ * @param {string|null} projectRoot
104
+ * @returns {string[]}
105
+ */
106
+ function sharedFallbackCandidates(relPath, projectRoot) {
107
+ if (!projectRoot || typeof relPath !== 'string') return [];
108
+ const posix = relPath.split('\\').join('/');
109
+ const marker = `${SHARED_DIR_NAME}/`;
110
+ const index = posix.lastIndexOf(marker);
111
+ if (index === -1) return [];
112
+ const segment = posix.slice(index + marker.length);
113
+ const parts = segment.split('/');
114
+ if (segment.length === 0 || parts.some((part) => part === '' || part === '..' || part === '.')) return [];
115
+
116
+ const wizzRoot = path.join(projectRoot, WIZZ_FOLDER_NAME);
117
+ let modules;
118
+ try {
119
+ modules = nodeFs
120
+ .readdirSync(wizzRoot, { withFileTypes: true })
121
+ .filter((entry) => entry.isDirectory())
122
+ .map((entry) => entry.name)
123
+ .sort();
124
+ } catch {
125
+ return [];
126
+ }
127
+ const candidates = [];
128
+ for (const name of modules) {
129
+ const sharedDir = path.join(wizzRoot, name, SHARED_DIR_NAME);
130
+ let stat;
131
+ try {
132
+ stat = nodeFs.statSync(sharedDir);
133
+ } catch {
134
+ continue;
135
+ }
136
+ if (!stat.isDirectory()) continue;
137
+ candidates.push(path.join(sharedDir, ...parts));
138
+ }
139
+ return candidates;
140
+ }
141
+
142
+ /**
143
+ * True when the base-relative include escapes the project root. Lexical
144
+ * (`path.resolve` normalizes `..` without touching the filesystem), so a
145
+ * missing file is judged the same way an existing one is. No project root →
146
+ * never outside. Python `_is_outside_project_root` parity.
147
+ * @param {string} baseDir
148
+ * @param {string} relPath
149
+ * @param {string|null} projectRoot
150
+ * @returns {boolean}
151
+ */
152
+ function isOutsideProjectRoot(baseDir, relPath, projectRoot) {
153
+ if (!projectRoot) return false;
154
+ const primary = path.resolve(baseDir, relPath);
155
+ const rel = path.relative(path.resolve(projectRoot), primary);
156
+ if (rel === '') return false;
157
+ return rel === '..' || rel.startsWith(`..${path.sep}`) || path.isAbsolute(rel);
158
+ }
159
+
160
+ /** The one escaped-include sentence, worded identically in both resolvers. */
161
+ function outsideRootMessage(relPath, skillName) {
162
+ return `include outside the project root, skipping: "${relPath}" (skill: ${skillName || '?'})`;
163
+ }
164
+
165
+ /**
166
+ * Absolute path of the file an `include` entry actually points at, or null.
167
+ * Base-relative first, then the `_shared/` fallback. Python
168
+ * `_find_include_file` parity.
169
+ */
170
+ function findIncludeFile(baseDir, relPath, projectRoot) {
171
+ const primary = path.resolve(baseDir, relPath);
172
+ if (isFile(primary)) return primary;
173
+ for (const candidate of sharedFallbackCandidates(relPath, projectRoot)) {
174
+ if (isFile(candidate)) return candidate;
175
+ }
176
+ return null;
177
+ }
178
+
179
+ /** The one missing-include sentence, worded identically in both resolvers. */
180
+ function missingIncludeMessage(relPath, skillName, primary) {
181
+ return `include not found, skipping: "${relPath}" (skill: ${skillName || '?'}; tried ${primary} and every ${WIZZ_FOLDER_NAME}/*/${SHARED_DIR_NAME}/)`;
182
+ }
183
+
184
+ /**
185
+ * Expand `include = [...]` in any table: each referenced file's
186
+ * paragraphs are PREPENDED onto that table's `activation_steps_append`
187
+ * (created if absent), the `include` key itself removed, recursion into
188
+ * nested tables. Paths resolve relative to the declaring TOML's
189
+ * directory, with the `_shared/` fallback above when that misses.
190
+ * Missing/unreadable files warn and are skipped (fail-open).
191
+ * Python `resolve_includes` parity.
192
+ *
193
+ * @param {object} data
194
+ * @param {string} baseDir - directory of the TOML that declared the include
195
+ * @param {string[]} warnings - sink for fail-open warnings
196
+ * @param {string[]} [inputs] - optional sink: every include file actually
197
+ * read is pushed here (absolute path, the FALLBACK path when that is what
198
+ * was used) so the caller can hash it into `_resolved/.index.json`.
199
+ * @param {{projectRoot?: string, skillName?: string}} [context]
200
+ */
201
+ function resolveIncludes(data, baseDir, warnings, inputs, context = {}) {
202
+ if (!isPlainObject(data)) return data;
203
+ const projectRoot = context.projectRoot || null;
204
+ const skillName = context.skillName || '';
205
+
206
+ const includedParagraphs = [];
207
+ if (Array.isArray(data.include)) {
208
+ for (const relPath of data.include) {
209
+ if (typeof relPath !== 'string') {
210
+ warnings.push(`include entries must be strings, got: ${JSON.stringify(relPath)}`);
211
+ continue;
212
+ }
213
+ if (isOutsideProjectRoot(baseDir, relPath, projectRoot)) {
214
+ warnings.push(outsideRootMessage(relPath, skillName));
215
+ continue;
216
+ }
217
+ const fullPath = findIncludeFile(baseDir, relPath, projectRoot);
218
+ let text = null;
219
+ if (fullPath === null) {
220
+ warnings.push(missingIncludeMessage(relPath, skillName, path.resolve(baseDir, relPath)));
221
+ } else {
222
+ try {
223
+ text = nodeFs.readFileSync(fullPath, 'utf8');
224
+ } catch {
225
+ warnings.push(`include not readable, skipping: ${fullPath}`);
226
+ }
227
+ }
228
+ if (text !== null) {
229
+ if (inputs) inputs.push(fullPath);
230
+ includedParagraphs.push(...splitIncludeParagraphs(text));
231
+ }
232
+ }
233
+ } else if ('include' in data) {
234
+ warnings.push(`'include' must be an array of strings, got: ${JSON.stringify(data.include)}`);
235
+ }
236
+
237
+ const result = {};
238
+ for (const [key, value] of Object.entries(data)) {
239
+ if (key === 'include') continue;
240
+ safeSet(result, key, isPlainObject(value) ? resolveIncludes(value, baseDir, warnings, inputs, context) : value);
241
+ }
242
+
243
+ if (includedParagraphs.length > 0) {
244
+ const existing = Array.isArray(result[INCLUDE_TARGET_FIELD]) ? result[INCLUDE_TARGET_FIELD] : [];
245
+ result[INCLUDE_TARGET_FIELD] = [...includedParagraphs, ...existing];
246
+ }
247
+ return result;
248
+ }
249
+
250
+ module.exports = {
251
+ resolveIncludes,
252
+ splitIncludeParagraphs,
253
+ sharedFallbackCandidates,
254
+ findIncludeFile,
255
+ isOutsideProjectRoot,
256
+ outsideRootMessage,
257
+ safeSet,
258
+ hasOwn,
259
+ isPlainObject,
260
+ INCLUDE_TARGET_FIELD,
261
+ SHARED_DIR_NAME,
262
+ };
@@ -0,0 +1,148 @@
1
+ /**
2
+ * Closed key sets for `customize.toml` (audit item 24, 2026-09-11).
3
+ *
4
+ * Extracted from `resolved-customizations.js` (2026-09-11) to keep that file
5
+ * under the 800-line cap. Validation only: nothing here writes, parses or
6
+ * merges — it takes ONE parsed layer and reports the keys no code consumes.
7
+ *
8
+ * "additionalProperties: false" in spirit. The BASE layer (shipped,
9
+ * code-reviewed) is exempt: it may legitimately carry LLM-only fields
10
+ * (door/rel/not_when-style prose the agents read but no code consumes) and
11
+ * new experimental fields. TEAM/USER layers are user-authored, where a typo'd
12
+ * key (`persistant_facts`) merges into silence today — deepMerge applies it,
13
+ * nothing reads it, the user believes the knob turned. Each unknown key there
14
+ * is a warning (not an error: fail-open, the snapshot is still written).
15
+ * `include` is the documented extension point and is validated by
16
+ * `resolveIncludes`.
17
+ */
18
+
19
+ const { isPlainObject } = require('./resolved-includes');
20
+
21
+ const WORKFLOW_KEYS = new Set([
22
+ // steps & facts
23
+ 'activation_steps_prepend',
24
+ 'activation_steps_append',
25
+ 'persistent_facts',
26
+ 'on_complete',
27
+ 'include',
28
+ // output & templates
29
+ 'output_dir',
30
+ 'output_folder_name',
31
+ 'run_folder_pattern',
32
+ 'ux_output_path',
33
+ 'prd_template',
34
+ 'prd_output_path',
35
+ 'validation_report_template',
36
+ 'validation_checklist_template',
37
+ 'spec_template',
38
+ 'spec_filename',
39
+ 'spec_output_path',
40
+ 'spine_template',
41
+ 'spine_output_path',
42
+ 'brief_template',
43
+ 'brief_output_path',
44
+ 'case_file_template',
45
+ 'case_file_subdir',
46
+ 'case_file_filename',
47
+ 'forge_output_path',
48
+ 'methods_file',
49
+ 'brain_methods',
50
+ // examples & handoffs
51
+ 'design_md_examples',
52
+ 'experience_md_examples',
53
+ 'design_handoffs',
54
+ 'external_sources',
55
+ 'external_handoffs',
56
+ 'finalize_reviewers',
57
+ 'creative_tools',
58
+ 'doc_standards',
59
+ // techniques & preferences
60
+ 'favorite_techniques',
61
+ 'additional_techniques',
62
+ 'preferences',
63
+ 'additional_methods',
64
+ // party mode
65
+ 'default_party',
66
+ 'party_mode',
67
+ 'party_memory',
68
+ 'memory_dir',
69
+ 'party_members',
70
+ 'party_groups',
71
+ // review layers (wizz-code-review, wizz-quick-dev): arrays of tables whose
72
+ // item keys are validated against REVIEW_LAYER_KEYS below.
73
+ 'review_layers',
74
+ 'oneshot_review_layers',
75
+ ]);
76
+ const PARTY_MEMBER_KEYS = new Set(['code', 'name', 'icon', 'title', 'persona', 'capabilities', 'model']);
77
+ const PARTY_GROUP_KEYS = new Set(['id', 'name', 'scene', 'members', 'memory']);
78
+ // Exactly the keys the 8 shipped `[[workflow.*review_layers]]` entries use
79
+ // (src/bmm-skills/4-implementation/wizz-code-review + wizz-quick-dev).
80
+ const REVIEW_LAYER_KEYS = new Set(['id', 'name', 'instruction', 'when']);
81
+ // The only top-level keys any of the 47 shipped customize.toml carry. A
82
+ // top-level typo (`[workflw]`) or a stray scalar merged into silence before.
83
+ const TOP_LEVEL_KEYS = new Set(['workflow', 'agent', 'include']);
84
+
85
+ /**
86
+ * Collect unknown keys under `[workflow]`: unknown fields by name, and for
87
+ * the arrays-of-tables we own (party members/groups, review layers) the
88
+ * unknown keys of each item.
89
+ * @returns {string[]} dotted paths
90
+ */
91
+ function findUnknownWorkflowKeys(workflow) {
92
+ const unknown = [];
93
+ for (const [k2, v2] of Object.entries(workflow)) {
94
+ const wfPath = `workflow.${k2}`;
95
+ if (!WORKFLOW_KEYS.has(k2)) {
96
+ unknown.push(wfPath);
97
+ continue;
98
+ }
99
+ if (!Array.isArray(v2) || v2.length === 0 || !v2.every((it) => isPlainObject(it))) continue;
100
+ const allowed =
101
+ k2 === 'party_members'
102
+ ? PARTY_MEMBER_KEYS
103
+ : k2 === 'party_groups'
104
+ ? PARTY_GROUP_KEYS
105
+ : k2.includes('review_layers')
106
+ ? REVIEW_LAYER_KEYS
107
+ : null;
108
+ if (!allowed) continue;
109
+ for (const item of v2) {
110
+ for (const k3 of Object.keys(item)) {
111
+ if (!allowed.has(k3)) unknown.push(`${wfPath}[].${k3}`);
112
+ }
113
+ }
114
+ }
115
+ return unknown;
116
+ }
117
+
118
+ /**
119
+ * Walk a loaded TOML layer and collect unknown keys: unknown TOP-level
120
+ * tables/scalars (anything outside `workflow`, `agent`, `include`) plus the
121
+ * `[workflow]` fields and array-of-table item keys. `[agent]` is prose the
122
+ * LLM reads, not a code-consumed schema, so its keys are open by design;
123
+ * `include` is validated by resolveIncludes.
124
+ * @param {object} data - a single layer, as parsed (never a merged tree)
125
+ * @returns {string[]} dotted paths (caller prefixes with layer info)
126
+ */
127
+ function findUnknownKeys(data) {
128
+ const unknown = [];
129
+ if (!isPlainObject(data)) return unknown;
130
+ for (const [key, value] of Object.entries(data)) {
131
+ if (!TOP_LEVEL_KEYS.has(key)) {
132
+ unknown.push(key);
133
+ continue;
134
+ }
135
+ if (key === 'workflow' && isPlainObject(value)) unknown.push(...findUnknownWorkflowKeys(value));
136
+ }
137
+ return unknown;
138
+ }
139
+
140
+ module.exports = {
141
+ findUnknownKeys,
142
+ findUnknownWorkflowKeys,
143
+ WORKFLOW_KEYS,
144
+ PARTY_MEMBER_KEYS,
145
+ PARTY_GROUP_KEYS,
146
+ REVIEW_LAYER_KEYS,
147
+ TOP_LEVEL_KEYS,
148
+ };
@@ -39,6 +39,13 @@ async function detectCustomFiles(wizzDir, existingFilesManifest, { manifest }) {
39
39
  manifestHasHashes = existingFilesManifest.some((f) => f.hash);
40
40
  }
41
41
 
42
+ // Persistent stat → hash cache (audit item 23, written by
43
+ // manifest-generator alongside files-manifest.csv). Fail-open: absent or
44
+ // corrupt cache = every file falls through to the full hash below.
45
+ const { loadHashCache, getCachedHash } = require('./hash-cache');
46
+ const hashCache = await loadHashCache(path.join(wizzDir, '_config'));
47
+ const relPathOf = (fullPath) => path.relative(wizzDir, fullPath).replaceAll('\\', '/');
48
+
42
49
  // Build map of previously installed files from files-manifest.csv with their hashes
43
50
  const installedFilesMap = new Map();
44
51
  for (const fileEntry of existingFilesManifest) {
@@ -97,6 +104,15 @@ async function detectCustomFiles(wizzDir, existingFilesManifest, { manifest }) {
97
104
  continue;
98
105
  }
99
106
 
107
+ // Skip _resolved/ — generated snapshots of resolved customizations
108
+ // (_wizz/_resolved/<skill>.json + .index.json, item 19), gitignored,
109
+ // not in the manifest, regenerated at update. Same treatment as
110
+ // _config/ above, minus the exception: these are pure build output,
111
+ // never something a user hand-edits.
112
+ if (relativePath.startsWith('_resolved/') || relativePath.startsWith('_resolved\\')) {
113
+ continue;
114
+ }
115
+
100
116
  if (wizzMemoryPaths.some((mp) => relativePath === mp || relativePath.startsWith(mp + '/'))) {
101
117
  continue;
102
118
  }
@@ -114,14 +130,30 @@ async function detectCustomFiles(wizzDir, existingFilesManifest, { manifest }) {
114
130
  customFiles.push(fullPath);
115
131
  }
116
132
  } 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
- });
133
+ // File in manifest with hash - check if it was modified.
134
+ // Incremental (audit item 23): consult the persistent
135
+ // size+mtime → hash cache first; a stat match proves the file
136
+ // is byte-identical to the last install, skipping the read
137
+ // entirely. Cache miss falls through to the full hash.
138
+ let unchangedByCache = false;
139
+ try {
140
+ const stat = await fs.stat(fullPath);
141
+ const cachedHash = getCachedHash(hashCache, relPathOf(fullPath), stat);
142
+ if (cachedHash !== null) {
143
+ unchangedByCache = true;
144
+ }
145
+ } catch {
146
+ // stat failed — hash below will handle the missing file
147
+ }
148
+ if (!unchangedByCache) {
149
+ const currentHash = await manifest.calculateFileHash(fullPath);
150
+ if (currentHash && currentHash !== fileInfo.hash) {
151
+ // Hash changed = file was modified
152
+ modifiedFiles.push({
153
+ path: fullPath,
154
+ relativePath: fileInfo.relativePath,
155
+ });
156
+ }
125
157
  }
126
158
  }
127
159
  }
@@ -0,0 +1,117 @@
1
+ /**
2
+ * Resolução do diretório de instalação `_wizz/` — dono único (item 20,
3
+ * auditoria 2026-09-11).
4
+ *
5
+ * Antes deste módulo havia quatro `findWizzDir` espalhados
6
+ * (core/installer.js, modules/module-catalog.js, ide/_config-driven.js e
7
+ * tools/migrate-custom-module-paths.js) e eles NÃO eram equivalentes: dois
8
+ * devolviam `null` quando o diretório não existe, um varria o projeto atrás
9
+ * de `<dir>/_config/manifest.yaml` (instalação V6+ com nome de pasta
10
+ * customizado) e um era só um `path.join`. Em vez de apagar comportamento, as
11
+ * quatro variantes moram aqui, nomeadas pelo que cada uma promete; os callers
12
+ * passam a importar a que já usavam.
13
+ *
14
+ * Módulo folha de propósito: além de `node:path` só importa `fs-native` e o
15
+ * `path-utils` do IDE (que por sua vez não importa nada), então não pode
16
+ * entrar em ciclo de require.
17
+ */
18
+
19
+ const path = require('node:path');
20
+ const fs = require('../fs-native');
21
+ const { WIZZ_FOLDER_NAME } = require('../ide/shared/path-utils');
22
+
23
+ /**
24
+ * Pure helper: compute the `_wizz` directory path for a project. No I/O, no
25
+ * instance state — callers that only need this path-join should call it
26
+ * directly instead of constructing a full `Installer` (which also builds an
27
+ * ExternalModuleManager, Manifest, IdeManager, ...) just to reach it (audit
28
+ * 2026-09-11, IC-F03).
29
+ * @param {string} projectDir - Project directory
30
+ * @returns {{wizzDir: string}}
31
+ */
32
+ function findWizzDir(projectDir) {
33
+ return { wizzDir: path.join(projectDir, WIZZ_FOLDER_NAME) };
34
+ }
35
+
36
+ /**
37
+ * The same path as `findWizzDir`, unwrapped. For callers that want the string
38
+ * and not the `{ wizzDir }` envelope.
39
+ * @param {string} projectDir - Project directory
40
+ * @returns {string}
41
+ */
42
+ function wizzDirPath(projectDir) {
43
+ return path.join(projectDir, WIZZ_FOLDER_NAME);
44
+ }
45
+
46
+ /**
47
+ * `_wizz/` path when it already exists on disk, else null. Used by the IDE
48
+ * handlers' `detect()`, where "no install here" must stay distinguishable
49
+ * from "install at this path".
50
+ * @param {string} projectDir - Project directory
51
+ * @returns {Promise<string|null>} Path to wizz dir or null
52
+ */
53
+ async function findExistingWizzDir(projectDir) {
54
+ const wizzDir = path.join(projectDir, WIZZ_FOLDER_NAME);
55
+ return (await fs.pathExists(wizzDir)) ? wizzDir : null;
56
+ }
57
+
58
+ /**
59
+ * Synchronous variant of `findExistingWizzDir`, for the one-shot migration
60
+ * scripts that run outside the installer's async pipeline.
61
+ * @param {string} [projectDir] - Project directory (defaults to cwd)
62
+ * @returns {string|null} Path to wizz dir or null
63
+ */
64
+ function findExistingWizzDirSync(projectDir = process.cwd()) {
65
+ const wizzDir = path.join(projectDir, WIZZ_FOLDER_NAME);
66
+ return fs.existsSync(wizzDir) ? wizzDir : null;
67
+ }
68
+
69
+ /**
70
+ * Locate the wizz installation directory of a project by its V6+ marker.
71
+ *
72
+ * V6+ installations can use ANY folder name but ALWAYS have
73
+ * `_config/manifest.yaml`, so this scans the project's direct children for
74
+ * that file instead of assuming `_wizz`. Falls back to `<projectDir>/wizz`
75
+ * (the historical default of this code path — note: no leading underscore,
76
+ * unlike WIZZ_FOLDER_NAME) when nothing is found, which is what new
77
+ * installations get.
78
+ * @param {string} projectDir - Project directory
79
+ * @returns {Promise<string>} Path to wizz directory
80
+ */
81
+ async function detectWizzDir(projectDir) {
82
+ // Check if project directory exists
83
+ if (!(await fs.pathExists(projectDir))) {
84
+ // Project doesn't exist yet, return default
85
+ return path.join(projectDir, 'wizz');
86
+ }
87
+
88
+ // V6+ strategy: Look for ANY directory with _config/manifest.yaml
89
+ // This is the definitive marker of a V6+ installation
90
+ try {
91
+ const entries = await fs.readdir(projectDir, { withFileTypes: true });
92
+ for (const entry of entries) {
93
+ if (entry.isDirectory()) {
94
+ const manifestPath = path.join(projectDir, entry.name, '_config', 'manifest.yaml');
95
+ if (await fs.pathExists(manifestPath)) {
96
+ // Found a V6+ installation
97
+ return path.join(projectDir, entry.name);
98
+ }
99
+ }
100
+ }
101
+ } catch {
102
+ // Ignore errors, fall through to default
103
+ }
104
+
105
+ // No V6+ installation found, return default
106
+ // This will be used for new installations
107
+ return path.join(projectDir, 'wizz');
108
+ }
109
+
110
+ module.exports = {
111
+ WIZZ_FOLDER_NAME,
112
+ findWizzDir,
113
+ wizzDirPath,
114
+ findExistingWizzDir,
115
+ findExistingWizzDirSync,
116
+ detectWizzDir,
117
+ };