wizz-method 2.0.0 → 2.1.1

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 (311) 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 +70 -38
  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/fetch-assets.js +7 -8
  156. package/tools/installer/commands/install.js +1 -1
  157. package/tools/installer/commands/resolve.js +95 -0
  158. package/tools/installer/core/doctor.js +648 -0
  159. package/tools/installer/core/hash-cache.js +156 -0
  160. package/tools/installer/core/help-catalog.js +4 -1
  161. package/tools/installer/core/hooks-settings.js +178 -0
  162. package/tools/installer/core/installer.js +297 -15
  163. package/tools/installer/core/legacy-warnings.js +0 -4
  164. package/tools/installer/core/manifest-generator.js +121 -43
  165. package/tools/installer/core/manifest.js +36 -32
  166. package/tools/installer/core/module-config-writer.js +4 -1
  167. package/tools/installer/core/python-check.js +60 -63
  168. package/tools/installer/core/quick-update.js +76 -43
  169. package/tools/installer/core/resolved-config.js +168 -0
  170. package/tools/installer/core/resolved-customizations.js +736 -0
  171. package/tools/installer/core/resolved-includes.js +262 -0
  172. package/tools/installer/core/resolved-schema.js +148 -0
  173. package/tools/installer/core/user-file-preservation.js +40 -8
  174. package/tools/installer/core/wizz-dir.js +117 -0
  175. package/tools/installer/core/yaml-cache.js +105 -0
  176. package/tools/installer/fs-native.js +97 -6
  177. package/tools/installer/ide/_config-driven.js +12 -75
  178. package/tools/installer/ide/platform-codes.js +111 -16
  179. package/tools/installer/ide/platform-codes.yaml +45 -100
  180. package/tools/installer/ide/shared/path-utils.js +6 -208
  181. package/tools/installer/install-messages.yaml +4 -14
  182. package/tools/installer/modules/channel-plan.js +15 -2
  183. package/tools/installer/modules/config-collector.js +762 -0
  184. package/tools/installer/modules/config-values.js +352 -0
  185. package/tools/installer/modules/custom-module-manager.js +161 -28
  186. package/tools/installer/modules/env-vars.js +119 -0
  187. package/tools/installer/modules/external-manager.js +133 -60
  188. package/tools/installer/modules/git-cache-utils.js +125 -0
  189. package/tools/installer/modules/module-catalog.js +565 -0
  190. package/tools/installer/modules/module-installer.js +618 -0
  191. package/tools/installer/modules/module-interface.js +86 -0
  192. package/tools/installer/modules/official-modules.js +98 -2172
  193. package/tools/installer/modules/pin-spec.js +125 -0
  194. package/tools/installer/modules/plugin-resolver.js +4 -0
  195. package/tools/installer/modules/skills-lib.js +3 -6
  196. package/tools/installer/prompts.js +0 -3
  197. package/tools/installer/ui.js +89 -54
  198. package/tools/installer/wizz-cli.js +1 -1
  199. package/tools/lib/frontmatter.js +139 -0
  200. package/tools/lib/sync-targets.mjs +49 -0
  201. package/tools/lib/walk.js +93 -0
  202. package/wizz-modules.yaml +9 -0
  203. package/src/scripts/__pycache__/memlog.cpython-313.pyc +0 -0
  204. package/src/scripts/memlog.py +0 -233
  205. package/src/scripts/tests/__pycache__/test_memlog.cpython-313-pytest-9.1.1.pyc +0 -0
  206. package/src/scripts/tests/__pycache__/test_resolve_customization.cpython-313-pytest-9.1.1.pyc +0 -0
  207. package/src/scripts/tests/test_memlog.py +0 -306
  208. package/src/skills-lib/wizz-huashu-design/assets/showcases/INDEX.md +0 -115
  209. package/src/skills-lib/wizz-huashu-design/assets/showcases/cover/cover-build.html +0 -235
  210. package/src/skills-lib/wizz-huashu-design/assets/showcases/cover/cover-build.png +0 -0
  211. package/src/skills-lib/wizz-huashu-design/assets/showcases/cover/cover-pentagram.html +0 -229
  212. package/src/skills-lib/wizz-huashu-design/assets/showcases/cover/cover-pentagram.png +0 -0
  213. package/src/skills-lib/wizz-huashu-design/assets/showcases/cover/cover-takram.html +0 -288
  214. package/src/skills-lib/wizz-huashu-design/assets/showcases/cover/cover-takram.png +0 -0
  215. package/src/skills-lib/wizz-huashu-design/assets/showcases/infographic/infographic-build.html +0 -503
  216. package/src/skills-lib/wizz-huashu-design/assets/showcases/infographic/infographic-build.png +0 -0
  217. package/src/skills-lib/wizz-huashu-design/assets/showcases/infographic/infographic-pentagram.html +0 -600
  218. package/src/skills-lib/wizz-huashu-design/assets/showcases/infographic/infographic-pentagram.png +0 -0
  219. package/src/skills-lib/wizz-huashu-design/assets/showcases/infographic/infographic-takram.html +0 -670
  220. package/src/skills-lib/wizz-huashu-design/assets/showcases/infographic/infographic-takram.png +0 -0
  221. package/src/skills-lib/wizz-huashu-design/assets/showcases/ppt/ppt-build.html +0 -382
  222. package/src/skills-lib/wizz-huashu-design/assets/showcases/ppt/ppt-build.png +0 -0
  223. package/src/skills-lib/wizz-huashu-design/assets/showcases/ppt/ppt-pentagram.html +0 -536
  224. package/src/skills-lib/wizz-huashu-design/assets/showcases/ppt/ppt-pentagram.png +0 -0
  225. package/src/skills-lib/wizz-huashu-design/assets/showcases/ppt/ppt-takram.html +0 -497
  226. package/src/skills-lib/wizz-huashu-design/assets/showcases/ppt/ppt-takram.png +0 -0
  227. package/src/skills-lib/wizz-huashu-design/assets/showcases/website-ai-nav/ainav-build.html +0 -385
  228. package/src/skills-lib/wizz-huashu-design/assets/showcases/website-ai-nav/ainav-build.png +0 -0
  229. package/src/skills-lib/wizz-huashu-design/assets/showcases/website-ai-nav/ainav-pentagram.html +0 -422
  230. package/src/skills-lib/wizz-huashu-design/assets/showcases/website-ai-nav/ainav-pentagram.png +0 -0
  231. package/src/skills-lib/wizz-huashu-design/assets/showcases/website-ai-nav/ainav-takram.html +0 -499
  232. package/src/skills-lib/wizz-huashu-design/assets/showcases/website-ai-nav/ainav-takram.png +0 -0
  233. package/src/skills-lib/wizz-huashu-design/assets/showcases/website-ai-writing/aiwriting-build.html +0 -562
  234. package/src/skills-lib/wizz-huashu-design/assets/showcases/website-ai-writing/aiwriting-build.png +0 -0
  235. package/src/skills-lib/wizz-huashu-design/assets/showcases/website-ai-writing/aiwriting-pentagram.html +0 -548
  236. package/src/skills-lib/wizz-huashu-design/assets/showcases/website-ai-writing/aiwriting-pentagram.png +0 -0
  237. package/src/skills-lib/wizz-huashu-design/assets/showcases/website-ai-writing/aiwriting-takram.html +0 -696
  238. package/src/skills-lib/wizz-huashu-design/assets/showcases/website-ai-writing/aiwriting-takram.png +0 -0
  239. package/src/skills-lib/wizz-huashu-design/assets/showcases/website-devdocs/devdocs-build.html +0 -372
  240. package/src/skills-lib/wizz-huashu-design/assets/showcases/website-devdocs/devdocs-build.png +0 -0
  241. package/src/skills-lib/wizz-huashu-design/assets/showcases/website-devdocs/devdocs-pentagram.html +0 -460
  242. package/src/skills-lib/wizz-huashu-design/assets/showcases/website-devdocs/devdocs-pentagram.png +0 -0
  243. package/src/skills-lib/wizz-huashu-design/assets/showcases/website-devdocs/devdocs-takram.html +0 -494
  244. package/src/skills-lib/wizz-huashu-design/assets/showcases/website-devdocs/devdocs-takram.png +0 -0
  245. package/src/skills-lib/wizz-huashu-design/assets/showcases/website-homepage/homepage-build.html +0 -367
  246. package/src/skills-lib/wizz-huashu-design/assets/showcases/website-homepage/homepage-build.png +0 -0
  247. package/src/skills-lib/wizz-huashu-design/assets/showcases/website-homepage/homepage-pentagram.html +0 -368
  248. package/src/skills-lib/wizz-huashu-design/assets/showcases/website-homepage/homepage-pentagram.png +0 -0
  249. package/src/skills-lib/wizz-huashu-design/assets/showcases/website-homepage/homepage-takram.html +0 -459
  250. package/src/skills-lib/wizz-huashu-design/assets/showcases/website-homepage/homepage-takram.png +0 -0
  251. package/src/skills-lib/wizz-huashu-design/assets/showcases/website-saas/saas-build.html +0 -493
  252. package/src/skills-lib/wizz-huashu-design/assets/showcases/website-saas/saas-build.png +0 -0
  253. package/src/skills-lib/wizz-huashu-design/assets/showcases/website-saas/saas-pentagram.html +0 -556
  254. package/src/skills-lib/wizz-huashu-design/assets/showcases/website-saas/saas-pentagram.png +0 -0
  255. package/src/skills-lib/wizz-huashu-design/assets/showcases/website-saas/saas-takram.html +0 -604
  256. package/src/skills-lib/wizz-huashu-design/assets/showcases/website-saas/saas-takram.png +0 -0
  257. package/tools/installer/file-ops.js +0 -204
  258. package/tools/installer/ide/shared/skill-manifest.js +0 -57
  259. package/tools/installer/yaml-format.js +0 -245
  260. package/web-bundles/README.md +0 -46
  261. package/web-bundles/brainstorming-coach/INSTRUCTIONS.md +0 -86
  262. package/web-bundles/brainstorming-coach/SKILL.md +0 -83
  263. package/web-bundles/brainstorming-coach/brain-methods.csv +0 -62
  264. package/web-bundles/bundles.json +0 -139
  265. package/web-bundles/market-and-industry-research/INSTRUCTIONS.md +0 -88
  266. package/web-bundles/market-and-industry-research/SKILL.md +0 -59
  267. package/web-bundles/prd-coach/INSTRUCTIONS.md +0 -86
  268. package/web-bundles/prd-coach/SKILL.md +0 -101
  269. package/web-bundles/prd-coach/prd-template.md +0 -165
  270. package/web-bundles/prd-coach/prd-validation-checklist.md +0 -135
  271. package/web-bundles/prfaq-coach/INSTRUCTIONS.md +0 -86
  272. package/web-bundles/prfaq-coach/SKILL.md +0 -139
  273. package/web-bundles/product-brief-coach/INSTRUCTIONS.md +0 -86
  274. package/web-bundles/product-brief-coach/SKILL.md +0 -113
  275. package/web-bundles/ux-coach/INSTRUCTIONS.md +0 -92
  276. package/web-bundles/ux-coach/SKILL.md +0 -187
  277. package/web-bundles/ux-coach/ux-validation.md +0 -100
  278. /package/src/modules/lowticket/skills/{lowticket-funil → wizz-lowticket-funil}/references/mapa-do-funil.md +0 -0
  279. /package/src/modules/lowticket/skills/{lowticket-metodologia → wizz-lowticket-metodologia}/CATALOGO.md +0 -0
  280. /package/src/modules/lowticket/skills/{lowticket-metodologia → wizz-lowticket-metodologia}/knowledge/01-principios.md +0 -0
  281. /package/src/modules/lowticket/skills/{lowticket-metodologia → wizz-lowticket-metodologia}/knowledge/02-diagnostico-funil.md +0 -0
  282. /package/src/modules/lowticket/skills/{lowticket-metodologia → wizz-lowticket-metodologia}/knowledge/03-campanha-bidcap.md +0 -0
  283. /package/src/modules/lowticket/skills/{lowticket-metodologia → wizz-lowticket-metodologia}/knowledge/04-criativos.md +0 -0
  284. /package/src/modules/lowticket/skills/{lowticket-metodologia → wizz-lowticket-metodologia}/knowledge/04a-criativos-ia.md +0 -0
  285. /package/src/modules/lowticket/skills/{lowticket-metodologia → wizz-lowticket-metodologia}/knowledge/04b-criativos-formatos.md +0 -0
  286. /package/src/modules/lowticket/skills/{lowticket-metodologia → wizz-lowticket-metodologia}/knowledge/05-oferta.md +0 -0
  287. /package/src/modules/lowticket/skills/{lowticket-metodologia → wizz-lowticket-metodologia}/knowledge/06-pagina-vendas.md +0 -0
  288. /package/src/modules/lowticket/skills/{lowticket-metodologia → wizz-lowticket-metodologia}/knowledge/06a-instagram.md +0 -0
  289. /package/src/modules/lowticket/skills/{lowticket-metodologia → wizz-lowticket-metodologia}/knowledge/06b-player-vsl.md +0 -0
  290. /package/src/modules/lowticket/skills/{lowticket-metodologia → wizz-lowticket-metodologia}/knowledge/07-funil-upsell.md +0 -0
  291. /package/src/modules/lowticket/skills/{lowticket-metodologia → wizz-lowticket-metodologia}/knowledge/07a-copy-humanizacao.md +0 -0
  292. /package/src/modules/lowticket/skills/{lowticket-metodologia → wizz-lowticket-metodologia}/knowledge/08-pesquisa-publico.md +0 -0
  293. /package/src/modules/lowticket/skills/{lowticket-metodologia → wizz-lowticket-metodologia}/knowledge/09-especialista-coproducao.md +0 -0
  294. /package/src/modules/lowticket/skills/{lowticket-metodologia → wizz-lowticket-metodologia}/knowledge/10-levantar-caixa.md +0 -0
  295. /package/src/modules/lowticket/skills/{lowticket-metodologia → wizz-lowticket-metodologia}/knowledge/11-checklist-roi.md +0 -0
  296. /package/src/modules/lowticket/skills/{lowticket-metodologia → wizz-lowticket-metodologia}/knowledge/12-mineracao-ofertas.md +0 -0
  297. /package/src/modules/lowticket/skills/{lowticket-metodologia → wizz-lowticket-metodologia}/knowledge/12a-mineracao-veredito.md +0 -0
  298. /package/src/modules/lowticket/skills/{lowticket-metodologia → wizz-lowticket-metodologia}/knowledge/12b-fabrica-de-ofertas.md +0 -0
  299. /package/src/modules/lowticket/skills/{lowticket-metodologia → wizz-lowticket-metodologia}/knowledge/12c-anatomia-low-ticket.md +0 -0
  300. /package/src/modules/lowticket/skills/{lowticket-metodologia → wizz-lowticket-metodologia}/knowledge/13-benchmarks-vsl.md +0 -0
  301. /package/src/modules/lowticket/skills/{lowticket-metodologia → wizz-lowticket-metodologia}/knowledge/14-vocabulario.md +0 -0
  302. /package/src/modules/lowticket/skills/{lowticket-metodologia → wizz-lowticket-metodologia}/knowledge/15-como-estender.md +0 -0
  303. /package/src/modules/lowticket/skills/{lowticket-metodologia → wizz-lowticket-metodologia}/knowledge/17-rastreamento.md +0 -0
  304. /package/src/modules/lowticket/skills/{lowticket-metodologia → wizz-lowticket-metodologia}/knowledge/18-copy-desejo-oferta.md +0 -0
  305. /package/src/modules/lowticket/skills/{lowticket-metodologia → wizz-lowticket-metodologia}/knowledge/INDEX.md +0 -0
  306. /package/src/modules/lowticket/skills/{lowticket-metodologia → wizz-lowticket-metodologia}/knowledge/guardrails.md +0 -0
  307. /package/src/modules/lowticket/skills/{lowticket-metodologia → wizz-lowticket-metodologia}/knowledge/pontos-em-aberto.md +0 -0
  308. /package/src/modules/lowticket/skills/{lowticket-metodologia → wizz-lowticket-metodologia}/references/swipe-file.md +0 -0
  309. /package/src/modules/lowticket/skills/{lowticket-pagina → wizz-lowticket-pagina}/references/metas-e-medicao.md +0 -0
  310. /package/src/modules/lowticket/skills/{lowticket-pagina → wizz-lowticket-pagina}/references/padroes-de-codigo.md +0 -0
  311. /package/src/modules/lowticket/skills/{lowticket-trafego → wizz-lowticket-trafego}/references/formato-do-diagnostico.md +0 -0
@@ -0,0 +1,565 @@
1
+ /**
2
+ * Catálogo de módulos (leitura pura) — item 20, etapa 2 (auditoria 2026-09-11).
3
+ *
4
+ * Parte do split de official-modules.js: tudo que LÊ módulos (listar,
5
+ * descrever, localizar fonte, localizar _wizz/, ler config existente) sem
6
+ * prompt, sem spinner, sem instalar. Métodos que costumavam viver na classe
7
+ * OfficialModules continuam acessíveis por lá via delegação, para os callers
8
+ * e testes existentes não mudarem.
9
+ *
10
+ * Nada aqui deve importar `prompts` (regra do relatório: o único módulo que
11
+ * importa prompts é o config-collector).
12
+ */
13
+
14
+ const path = require('node:path');
15
+ const fs = require('../fs-native');
16
+ const yaml = require('yaml');
17
+ const { getProjectRoot, getSourcePath, getModulePath } = require('../project-root');
18
+ const { ExternalModuleManager } = require('./external-manager');
19
+ const { loadYamlCached } = require('../core/yaml-cache');
20
+ const { detectWizzDir } = require('../core/wizz-dir');
21
+
22
+ /**
23
+ * Parse a config.toml or config.user.toml written by writeCentralConfig.
24
+ * Only handles the subset of TOML the installer produces: [core],
25
+ * [modules.<code>], string/bool/number scalar values. [agents.*] and other
26
+ * sections are ignored. Returns a plain object keyed by section name where
27
+ * module sections use the bare code (e.g. "bmm"), not the full "modules.bmm".
28
+ */
29
+ function parseCentralToml(content) {
30
+ const result = {};
31
+ let currentSection = null;
32
+
33
+ for (const rawLine of content.split('\n')) {
34
+ const line = rawLine.trim();
35
+ if (!line || line.startsWith('#')) continue;
36
+
37
+ const sectionMatch = line.match(/^\[([^\]]+)\]\s*$/);
38
+ if (sectionMatch) {
39
+ const name = sectionMatch[1];
40
+ if (name === 'core') {
41
+ currentSection = 'core';
42
+ } else if (name.startsWith('modules.')) {
43
+ currentSection = name.slice('modules.'.length);
44
+ } else {
45
+ currentSection = null;
46
+ }
47
+ if (currentSection && !result[currentSection]) {
48
+ result[currentSection] = {};
49
+ }
50
+ continue;
51
+ }
52
+
53
+ if (!currentSection) continue;
54
+
55
+ const kvMatch = line.match(/^([a-zA-Z_][a-zA-Z0-9_]*)\s*=\s*(.+)$/);
56
+ if (!kvMatch) continue;
57
+
58
+ const key = kvMatch[1];
59
+ const raw = kvMatch[2].trim();
60
+ let value;
61
+ if (raw.startsWith('"') && raw.endsWith('"')) {
62
+ value = raw.slice(1, -1).replaceAll(/\\(["\\nrbt])/g, (_, c) => ({ '"': '"', '\\': '\\', n: '\n', r: '\r', b: '\b', t: '\t' })[c]);
63
+ } else if (raw === 'true') {
64
+ value = true;
65
+ } else if (raw === 'false') {
66
+ value = false;
67
+ } else if (raw !== '' && !isNaN(raw)) {
68
+ value = Number(raw);
69
+ } else {
70
+ value = raw;
71
+ }
72
+ result[currentSection][key] = value;
73
+ }
74
+
75
+ return result;
76
+ }
77
+
78
+ /**
79
+ * Localiza o module.yaml de um módulo: caminho padrão (src/modules/<code> ou
80
+ * core/bmm) primeiro, depois findModuleSource (que cobre externo/custom).
81
+ * Extrai a resolução copiada 3x em official-modules.js (OM-02, auditoria
82
+ * 2026-09-11) — scanModuleSchemas, collectModuleConfigQuick e
83
+ * collectModuleConfig tinham blocos idênticos.
84
+ *
85
+ * @param {(moduleCode: string, options?: Object) => Promise<string|null>} findModuleSourceFn
86
+ * A função de busca do dono da chamada (normalmente OfficialModules#findModuleSource).
87
+ * @param {string} moduleName
88
+ * @param {Object} [options] - Opções repassadas a findModuleSourceFn
89
+ * @returns {Promise<string|null>} Caminho absoluto para o module.yaml, ou null
90
+ */
91
+ async function resolveModuleConfigPath(findModuleSourceFn, moduleName, options = {}) {
92
+ const standardPath = path.join(getModulePath(moduleName), 'module.yaml');
93
+ if (await fs.pathExists(standardPath)) {
94
+ return standardPath;
95
+ }
96
+ const moduleSourcePath = await findModuleSourceFn(moduleName, { silent: true, ...options });
97
+ if (moduleSourcePath) {
98
+ return path.join(moduleSourcePath, 'module.yaml');
99
+ }
100
+ return null;
101
+ }
102
+
103
+ // Campos de metadata de module.yaml que não são perguntas de config.
104
+ // interface_version (auditoria 2026-09-11, item 25 — ver module-interface.js)
105
+ // é um escalar de contrato, não uma pergunta: sem essa entrada ele seria
106
+ // contado como "config real" pelo hasNoConfig do config-collector, do
107
+ // mesmo jeito que default_selected precisou entrar aqui antes dele.
108
+ // description e module_version entraram no review da Fase 4 (2026-09-12)
109
+ // pelo mesmo motivo: metadados escalares, não perguntas.
110
+ const MODULE_METADATA_FIELDS = new Set([
111
+ 'code',
112
+ 'name',
113
+ 'header',
114
+ 'subheader',
115
+ 'description',
116
+ 'module_version',
117
+ 'default_selected',
118
+ 'interface_version',
119
+ ]);
120
+
121
+ /**
122
+ * True when a config field has no default value at all. An explicit empty
123
+ * string (`default: ""`) is a real default meaning "defaults to blank" — it
124
+ * must NOT force a required prompt. Centralized so the express/customize/
125
+ * skip-prompts paths stay consistent.
126
+ * @param {*} defaultValue - The field's `default` value from module.yaml.
127
+ * @returns {boolean} True when the field has no usable default.
128
+ */
129
+ function isMissingDefault(defaultValue) {
130
+ return defaultValue === undefined || defaultValue === null;
131
+ }
132
+
133
+ /**
134
+ * Camada de leitura pura do OfficialModules: listar, descrever e localizar
135
+ * módulos. 0 prompts. Os métodos de coleta interativa ficam no restante de
136
+ * official-modules.js (config-collector), que delega aqui.
137
+ */
138
+ class ModuleCatalog {
139
+ /**
140
+ * @param {Object} [options]
141
+ * @param {ExternalModuleManager} [options.externalModuleManager]
142
+ * @param {Object|null} [options.channelOptions]
143
+ * @param {(moduleCode: string, options?: Object) => Promise<string|null>} [options.findModuleSource]
144
+ * Ponto único de resolução de fonte usado INTERNAMENTE pelo catálogo.
145
+ * OfficialModules injeta aqui o próprio wrapper, de modo que stubar
146
+ * `officialModules.findModuleSource` (padrão dos testes) também
147
+ * intercepta listAvailable/getModuleInfo/scanModuleSchemas — antes o
148
+ * catálogo chamava só o seu próprio método e o stub não pegava.
149
+ */
150
+ constructor(options = {}) {
151
+ this.externalModuleManager = options.externalModuleManager || new ExternalModuleManager();
152
+ this.channelOptions = options.channelOptions || null;
153
+ this.resolveModuleSource = options.findModuleSource || ((code, opts) => this.findModuleSource(code, opts));
154
+ /**
155
+ * Erros de leitura acumulados (module.yaml ilegível). O catálogo não
156
+ * importa `prompts` — quem avisa o usuário é OfficialModules, que drena
157
+ * esta lista depois de cada chamada (item 20: o split tinha trocado os
158
+ * `prompts.log.warn` originais por `catch {}` mudos).
159
+ * @type {Array<{module: string, error: Error}>}
160
+ */
161
+ this.loadErrors = [];
162
+ }
163
+
164
+ /**
165
+ * Drena os erros de leitura acumulados desde a última chamada.
166
+ * @returns {Array<{module: string, error: Error}>}
167
+ */
168
+ takeLoadErrors() {
169
+ const errors = this.loadErrors;
170
+ this.loadErrors = [];
171
+ return errors;
172
+ }
173
+
174
+ /**
175
+ * List all available built-in modules (core and bmm) plus bundled src/modules.
176
+ * All other modules come from wizz-modules.yaml
177
+ * @returns {Object} Object with modules array
178
+ */
179
+ async listAvailable() {
180
+ const modules = [];
181
+
182
+ // Add built-in core module (directly under src/core-skills)
183
+ const corePath = getSourcePath('core-skills');
184
+ if (await fs.pathExists(corePath)) {
185
+ const coreInfo = await this.getModuleInfo(corePath, 'core', 'src/core-skills');
186
+ if (coreInfo) {
187
+ modules.push(coreInfo);
188
+ }
189
+ }
190
+
191
+ // Add built-in bmm module (directly under src/bmm-skills)
192
+ const bmmPath = getSourcePath('bmm-skills');
193
+ if (await fs.pathExists(bmmPath)) {
194
+ const bmmInfo = await this.getModuleInfo(bmmPath, 'bmm', 'src/bmm-skills');
195
+ if (bmmInfo) {
196
+ modules.push(bmmInfo);
197
+ }
198
+ }
199
+
200
+ // Add bundled local modules (src/modules/<code>), e.g. wizz. Without this
201
+ // they never appear in the picker nor in the --yes defaults, even with
202
+ // default_selected: true — findModuleSource resolves them, but nothing
203
+ // ever selects them (bug: maestro/agentes de área não instalavam via npx).
204
+ const bundledDir = getSourcePath('modules');
205
+ if (await fs.pathExists(bundledDir)) {
206
+ const entries = await fs.readdir(bundledDir, { withFileTypes: true });
207
+ const seen = new Set(modules.map((m) => m.id));
208
+ for (const entry of entries) {
209
+ if (!entry.isDirectory()) continue;
210
+ const modulePath = path.join(bundledDir, entry.name);
211
+ if (!(await fs.pathExists(path.join(modulePath, 'module.yaml')))) continue;
212
+ const info = await this.getModuleInfo(modulePath, entry.name, `src/modules/${entry.name}`);
213
+ if (info && !seen.has(info.id)) {
214
+ modules.push(info);
215
+ seen.add(info.id);
216
+ }
217
+ }
218
+ }
219
+
220
+ return { modules };
221
+ }
222
+
223
+ /**
224
+ * Get module information from a module path
225
+ * @param {string} modulePath - Path to the module directory
226
+ * @param {string} defaultName - Default name for the module
227
+ * @param {string} sourceDescription - Description of where the module was found
228
+ * @returns {Object|null} Module info or null if not a valid module
229
+ */
230
+ async getModuleInfo(modulePath, defaultName, sourceDescription) {
231
+ const moduleConfigPath = path.join(modulePath, 'module.yaml');
232
+
233
+ if (!(await fs.pathExists(moduleConfigPath))) {
234
+ // Check resolution cache for strategy 5 modules (no module.yaml on disk)
235
+ const { CustomModuleManager } = require('./custom-module-manager');
236
+ const customMgr = new CustomModuleManager();
237
+ const resolved = customMgr.getResolution(defaultName);
238
+ if (resolved && resolved.synthesizedModuleYaml) {
239
+ return {
240
+ id: resolved.code,
241
+ path: modulePath,
242
+ name: resolved.name,
243
+ description: resolved.description,
244
+ version: resolved.version || '1.0.0',
245
+ source: sourceDescription,
246
+ dependencies: [],
247
+ defaultSelected: false,
248
+ };
249
+ }
250
+ return null;
251
+ }
252
+
253
+ const moduleInfo = {
254
+ id: defaultName,
255
+ path: modulePath,
256
+ name: defaultName
257
+ .split('-')
258
+ .map((word) => word.charAt(0).toUpperCase() + word.slice(1))
259
+ .join(' '),
260
+ description: 'Wizz Method Module',
261
+ version: '5.0.0',
262
+ source: sourceDescription,
263
+ };
264
+
265
+ // Read module config for metadata
266
+ try {
267
+ const config = await loadYamlCached(moduleConfigPath);
268
+ if (config) {
269
+ // Use the code property as the id if available
270
+ if (config.code) {
271
+ moduleInfo.id = config.code;
272
+ }
273
+
274
+ moduleInfo.name = config.name || moduleInfo.name;
275
+ moduleInfo.description = config.description || moduleInfo.description;
276
+ moduleInfo.version = config.version || moduleInfo.version;
277
+ moduleInfo.dependencies = config.dependencies || [];
278
+ moduleInfo.defaultSelected = config.default_selected === undefined ? false : config.default_selected;
279
+ }
280
+ } catch (error) {
281
+ // Sem prompts aqui (regra do split): um module.yaml quebrado degrada
282
+ // para os defaults acima em vez de falhar a listagem inteira, mas o
283
+ // erro é registrado para OfficialModules avisar o usuário.
284
+ this.loadErrors.push({ module: defaultName, error });
285
+ }
286
+
287
+ return moduleInfo;
288
+ }
289
+
290
+ /**
291
+ * Find the source path for a module by searching all possible locations
292
+ * @param {string} moduleCode - Code of the module to find (from module.yaml)
293
+ * @returns {string|null} Path to the module source or null if not found
294
+ */
295
+ async findModuleSource(moduleCode, options = {}) {
296
+ // Inherit channelOptions from the install-scoped instance when the caller
297
+ // didn't pass one explicitly. Keeps pre-install config collection and the
298
+ // actual install step looking at the same git ref.
299
+ if (options.channelOptions === undefined && this.channelOptions) {
300
+ options = { ...options, channelOptions: this.channelOptions };
301
+ }
302
+
303
+ // Check for core module (directly under src/core-skills)
304
+ if (moduleCode === 'core') {
305
+ const corePath = getSourcePath('core-skills');
306
+ if (await fs.pathExists(corePath)) {
307
+ return corePath;
308
+ }
309
+ }
310
+
311
+ // Check for built-in bmm module (directly under src/bmm-skills)
312
+ if (moduleCode === 'bmm') {
313
+ const bmmPath = getSourcePath('bmm-skills');
314
+ if (await fs.pathExists(bmmPath)) {
315
+ return bmmPath;
316
+ }
317
+ }
318
+
319
+ // Check bundled local modules (directly under src/modules/<code>), e.g. wizz.
320
+ // These ship inside this repo and are auto-discovered by list-options.js.
321
+ const bundledPath = getSourcePath('modules', moduleCode);
322
+ if (await fs.pathExists(path.join(bundledPath, 'module.yaml'))) {
323
+ return bundledPath;
324
+ }
325
+
326
+ // Check external official modules (pass channelOptions so channel plan applies)
327
+ const externalSource = await this.externalModuleManager.findExternalModuleSource(moduleCode, options);
328
+ if (externalSource) {
329
+ return externalSource;
330
+ }
331
+
332
+ // Check custom modules (from user-provided URLs, already cloned to cache)
333
+ const { CustomModuleManager } = require('./custom-module-manager');
334
+ const customMgr = new CustomModuleManager();
335
+ const customSource = await customMgr.findModuleSourceByCode(moduleCode, options);
336
+ if (customSource) {
337
+ return customSource;
338
+ }
339
+
340
+ return null;
341
+ }
342
+
343
+ /**
344
+ * Find the wizz installation directory in a project
345
+ * V6+ installations can use ANY folder name but ALWAYS have _config/manifest.yaml
346
+ * Delegated to core/wizz-dir.js, the single owner of `_wizz` resolution
347
+ * (item 20, auditoria 2026-09-11) — semântica inalterada.
348
+ * @param {string} projectDir - Project directory
349
+ * @returns {Promise<string>} Path to wizz directory
350
+ */
351
+ async findWizzDir(projectDir) {
352
+ return detectWizzDir(projectDir);
353
+ }
354
+
355
+ /**
356
+ * Load existing config if it exists from module config files.
357
+ * Populates `this.existingConfig` (plain object module → key → value).
358
+ * @param {string} projectDir - Target project directory
359
+ * @returns {Promise<boolean>} True when any prior config was found
360
+ */
361
+ async loadExistingConfig(projectDir) {
362
+ this.existingConfigData = {};
363
+
364
+ // Check if project directory exists first
365
+ if (!(await fs.pathExists(projectDir))) {
366
+ return false;
367
+ }
368
+
369
+ // Find the actual wizz directory (handles custom folder names)
370
+ const wizzDir = await this.findWizzDir(projectDir);
371
+
372
+ // Check if wizz directory exists
373
+ if (!(await fs.pathExists(wizzDir))) {
374
+ return false;
375
+ }
376
+
377
+ // Primary source: installer-written config.toml + config.user.toml (v6+).
378
+ // Both files together hold all install answers; config.user.toml carries
379
+ // user-scoped keys like user_name that would otherwise be re-prompted on
380
+ // every reinstall.
381
+ let foundAny = false;
382
+ for (const fileName of ['config.toml', 'config.user.toml']) {
383
+ const tomlPath = path.join(wizzDir, fileName);
384
+ if (!(await fs.pathExists(tomlPath))) continue;
385
+ try {
386
+ const content = await fs.readFile(tomlPath, 'utf8');
387
+ const parsed = parseCentralToml(content);
388
+ for (const [section, values] of Object.entries(parsed)) {
389
+ if (values && typeof values === 'object' && !Array.isArray(values)) {
390
+ if (!this.existingConfigData[section]) this.existingConfigData[section] = {};
391
+ Object.assign(this.existingConfigData[section], values);
392
+ foundAny = true;
393
+ }
394
+ }
395
+ } catch {
396
+ // Ignore parse errors
397
+ }
398
+ }
399
+
400
+ if (foundAny) {
401
+ return true;
402
+ }
403
+
404
+ // Fallback: legacy per-module config.yaml files (pre-v6 installations).
405
+ const entries = await fs.readdir(wizzDir, { withFileTypes: true });
406
+ const nonModuleDirs = new Set(['_config', '_memory', 'memory', 'docs', 'scripts', 'custom', 'hooks']);
407
+ for (const entry of entries) {
408
+ if (entry.isDirectory()) {
409
+ if (nonModuleDirs.has(entry.name)) {
410
+ continue;
411
+ }
412
+
413
+ const moduleConfigPath = path.join(wizzDir, entry.name, 'config.yaml');
414
+
415
+ if (await fs.pathExists(moduleConfigPath)) {
416
+ try {
417
+ const content = await fs.readFile(moduleConfigPath, 'utf8');
418
+ const moduleConfig = yaml.parse(content);
419
+ // Only keep plain object parses. A corrupt config.yaml that parses
420
+ // to a scalar or array would crash later code that does `key in cfg`
421
+ // / `Object.keys(cfg)`; treat it the same as a parse error.
422
+ if (moduleConfig && typeof moduleConfig === 'object' && !Array.isArray(moduleConfig)) {
423
+ this.existingConfigData[entry.name] = moduleConfig;
424
+ foundAny = true;
425
+ }
426
+ } catch {
427
+ // Ignore parse errors for individual modules
428
+ }
429
+ }
430
+ }
431
+ }
432
+
433
+ if (foundAny) {
434
+ await this._hoistCoreKeysFromLegacyModuleConfigs();
435
+ }
436
+
437
+ return foundAny;
438
+ }
439
+
440
+ /**
441
+ * Migrate prior answers when a key has moved from a non-core module to core
442
+ * (e.g. project_name moving from bmm to core in #2279). Without this, the
443
+ * partition logic in writeCentralConfig drops the value from the bmm bucket
444
+ * (because it's now a core key) without re-homing it under [core], so the
445
+ * user's prior answer silently disappears on the next install/quick-update.
446
+ */
447
+ async _hoistCoreKeysFromLegacyModuleConfigs() {
448
+ const coreSchemaPath = path.join(getSourcePath(), 'core-skills', 'module.yaml');
449
+ if (!(await fs.pathExists(coreSchemaPath))) return;
450
+
451
+ let coreSchema;
452
+ try {
453
+ coreSchema = await loadYamlCached(coreSchemaPath);
454
+ } catch {
455
+ return;
456
+ }
457
+ if (!coreSchema || typeof coreSchema !== 'object') return;
458
+
459
+ const coreKeys = new Set(
460
+ Object.entries(coreSchema)
461
+ .filter(([, v]) => v && typeof v === 'object' && 'prompt' in v)
462
+ .map(([k]) => k),
463
+ );
464
+ if (coreKeys.size === 0) return;
465
+
466
+ // Belt-and-suspenders: loadExistingConfig already filters non-object parses,
467
+ // but anyone calling _hoistCoreKeysFromLegacyModuleConfigs in isolation (or
468
+ // future code paths populating existingConfigData directly) shouldn't be
469
+ // able to crash this with a scalar / array.
470
+ const existingCore = this.existingConfigData.core;
471
+ this.existingConfigData.core = existingCore && typeof existingCore === 'object' && !Array.isArray(existingCore) ? existingCore : {};
472
+
473
+ for (const [moduleName, cfg] of Object.entries(this.existingConfigData)) {
474
+ if (moduleName === 'core' || !cfg || typeof cfg !== 'object' || Array.isArray(cfg)) continue;
475
+ for (const key of Object.keys(cfg)) {
476
+ if (!coreKeys.has(key)) continue;
477
+ if (!(key in this.existingConfigData.core)) {
478
+ this.existingConfigData.core[key] = cfg[key];
479
+ }
480
+ delete cfg[key];
481
+ }
482
+ }
483
+ }
484
+
485
+ /**
486
+ * Pre-scan module schemas to gather metadata for the configuration gateway prompt.
487
+ * Returns info about which modules have configurable options.
488
+ * @param {Array} modules - List of non-core module names
489
+ * @returns {Promise<Array>} Array of {moduleName, displayName, questionCount, hasFieldsWithoutDefaults}
490
+ */
491
+ async scanModuleSchemas(modules) {
492
+ const results = [];
493
+
494
+ for (const moduleName of modules) {
495
+ const moduleConfigPath = await resolveModuleConfigPath(this.resolveModuleSource, moduleName);
496
+ if (!moduleConfigPath) {
497
+ continue;
498
+ }
499
+
500
+ try {
501
+ const moduleConfig = await loadYamlCached(moduleConfigPath);
502
+ if (!moduleConfig) continue;
503
+
504
+ const displayName = moduleConfig.header || `${moduleName.toUpperCase()} Module`;
505
+ const configKeys = Object.keys(moduleConfig).filter((key) => key !== 'prompt');
506
+ const questionKeys = configKeys.filter((key) => {
507
+ if (MODULE_METADATA_FIELDS.has(key)) return false;
508
+ const item = moduleConfig[key];
509
+ return item && typeof item === 'object' && item.prompt;
510
+ });
511
+
512
+ const hasFieldsWithoutDefaults = questionKeys.some((key) => {
513
+ const item = moduleConfig[key];
514
+ return isMissingDefault(item.default);
515
+ });
516
+
517
+ results.push({
518
+ moduleName,
519
+ displayName,
520
+ questionCount: questionKeys.length,
521
+ hasFieldsWithoutDefaults,
522
+ });
523
+ } catch (error) {
524
+ // Sem prompts aqui: uma schema ilegível simplesmente não aparece no
525
+ // gateway de customização. O erro sobe por loadErrors para
526
+ // OfficialModules emitir o warn que existia antes do split.
527
+ this.loadErrors.push({ module: moduleName, error });
528
+ }
529
+ }
530
+
531
+ return results;
532
+ }
533
+
534
+ /**
535
+ * Private: Get list of all files in a directory
536
+ * @param {string} dir - Directory path
537
+ * @param {string} baseDir - Base directory for relative paths
538
+ * @returns {Array} List of relative file paths
539
+ */
540
+ async getFileList(dir, baseDir = dir) {
541
+ const files = [];
542
+ const entries = await fs.readdir(dir, { withFileTypes: true });
543
+
544
+ for (const entry of entries) {
545
+ const fullPath = path.join(dir, entry.name);
546
+
547
+ if (entry.isDirectory()) {
548
+ const subFiles = await this.getFileList(fullPath, baseDir);
549
+ files.push(...subFiles);
550
+ } else {
551
+ files.push(path.relative(baseDir, fullPath));
552
+ }
553
+ }
554
+
555
+ return files;
556
+ }
557
+ }
558
+
559
+ module.exports = {
560
+ ModuleCatalog,
561
+ parseCentralToml,
562
+ resolveModuleConfigPath,
563
+ isMissingDefault,
564
+ MODULE_METADATA_FIELDS,
565
+ };