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.
- package/LICENSE +60 -30
- package/README.md +80 -31
- package/SECURITY.md +24 -0
- package/THIRD-PARTY-NOTICES.md +136 -0
- package/package.json +31 -17
- package/skills-registry.yaml +128 -7
- package/src/bmm-skills/1-analysis/research/wizz-domain-research/SKILL.md +3 -4
- package/src/bmm-skills/1-analysis/research/wizz-domain-research/domain-steps/step-06-research-synthesis.md +1 -1
- package/src/bmm-skills/1-analysis/research/wizz-market-research/SKILL.md +3 -4
- package/src/bmm-skills/1-analysis/research/wizz-market-research/steps/step-06-research-completion.md +1 -1
- package/src/bmm-skills/1-analysis/research/wizz-technical-research/SKILL.md +3 -4
- package/src/bmm-skills/1-analysis/research/wizz-technical-research/technical-steps/step-06-research-synthesis.md +1 -1
- package/src/bmm-skills/1-analysis/wizz-agent-analyst/SKILL.md +3 -4
- package/src/bmm-skills/1-analysis/wizz-agent-tech-writer/SKILL.md +3 -4
- package/src/bmm-skills/1-analysis/wizz-document-project/SKILL.md +3 -4
- package/src/bmm-skills/1-analysis/wizz-document-project/workflows/deep-dive-instructions.md +1 -1
- package/src/bmm-skills/1-analysis/wizz-document-project/workflows/full-scan-instructions.md +1 -1
- package/src/bmm-skills/1-analysis/wizz-prfaq/SKILL.md +3 -4
- package/src/bmm-skills/1-analysis/wizz-prfaq/references/verdict.md +1 -1
- package/src/bmm-skills/1-analysis/wizz-product-brief/SKILL.md +1 -1
- package/src/bmm-skills/2-plan-workflows/wizz-agent-pm/SKILL.md +3 -4
- package/src/bmm-skills/2-plan-workflows/wizz-agent-ux-designer/SKILL.md +3 -4
- package/src/bmm-skills/2-plan-workflows/wizz-create-prd/SKILL.md +1 -1
- package/src/bmm-skills/2-plan-workflows/wizz-edit-prd/SKILL.md +1 -1
- package/src/bmm-skills/2-plan-workflows/wizz-prd/SKILL.md +1 -1
- package/src/bmm-skills/2-plan-workflows/wizz-ux/SKILL.md +1 -1
- package/src/bmm-skills/2-plan-workflows/wizz-validate-prd/SKILL.md +1 -1
- package/src/bmm-skills/3-solutioning/wizz-agent-architect/SKILL.md +3 -4
- package/src/bmm-skills/3-solutioning/wizz-architecture/SKILL.md +9 -9
- package/src/bmm-skills/3-solutioning/wizz-architecture/references/headless.md +1 -1
- package/src/bmm-skills/3-solutioning/wizz-check-implementation-readiness/SKILL.md +3 -4
- package/src/bmm-skills/3-solutioning/wizz-check-implementation-readiness/steps/step-06-final-assessment.md +1 -1
- package/src/bmm-skills/3-solutioning/wizz-create-architecture/SKILL.md +1 -1
- package/src/bmm-skills/3-solutioning/wizz-create-epics-and-stories/SKILL.md +3 -4
- package/src/bmm-skills/3-solutioning/wizz-create-epics-and-stories/steps/step-04-final-validation.md +1 -1
- package/src/bmm-skills/3-solutioning/wizz-generate-project-context/SKILL.md +3 -4
- package/src/bmm-skills/3-solutioning/wizz-generate-project-context/steps/step-03-complete.md +1 -1
- package/src/bmm-skills/4-implementation/wizz-agent-dev/SKILL.md +3 -4
- package/src/bmm-skills/4-implementation/wizz-checkpoint-preview/SKILL.md +3 -4
- package/src/bmm-skills/4-implementation/wizz-checkpoint-preview/step-05-wrapup.md +1 -1
- package/src/bmm-skills/4-implementation/wizz-code-review/SKILL.md +3 -4
- package/src/bmm-skills/4-implementation/wizz-code-review/customize.toml +3 -8
- package/src/bmm-skills/4-implementation/wizz-code-review/review-prompts/blind-hunter.md +20 -0
- package/src/bmm-skills/4-implementation/wizz-code-review/steps/step-04-present.md +1 -1
- package/src/bmm-skills/4-implementation/wizz-correct-course/SKILL.md +4 -5
- package/src/bmm-skills/4-implementation/wizz-create-story/SKILL.md +4 -5
- package/src/bmm-skills/4-implementation/wizz-dev-story/SKILL.md +4 -5
- package/src/bmm-skills/4-implementation/wizz-investigate/SKILL.md +1 -1
- package/src/bmm-skills/4-implementation/wizz-qa-generate-e2e-tests/SKILL.md +4 -5
- package/src/bmm-skills/4-implementation/wizz-quick-dev/SKILL.md +4 -5
- package/src/bmm-skills/4-implementation/wizz-quick-dev/customize.toml +10 -22
- package/src/bmm-skills/4-implementation/wizz-quick-dev/review-prompts/blind-hunter.md +20 -0
- package/src/bmm-skills/4-implementation/wizz-quick-dev/step-05-present.md +1 -1
- package/src/bmm-skills/4-implementation/wizz-quick-dev/step-oneshot.md +1 -1
- package/src/bmm-skills/4-implementation/wizz-retrospective/SKILL.md +1 -2
- package/src/bmm-skills/4-implementation/wizz-sprint-planning/SKILL.md +1 -1
- package/src/bmm-skills/4-implementation/wizz-sprint-status/SKILL.md +5 -6
- package/src/core-skills/_shared/handoff-protocol.md +9 -0
- package/src/core-skills/wizz-advanced-elicitation/SKILL.md +2 -2
- package/src/core-skills/wizz-brainstorming/SKILL.md +6 -6
- package/src/core-skills/wizz-brainstorming/references/converge.md +1 -1
- package/src/core-skills/wizz-brainstorming/references/finalize.md +1 -1
- package/src/core-skills/wizz-brainstorming/references/headless.md +3 -3
- package/src/core-skills/wizz-brainstorming/references/mode-autonomous.md +1 -1
- package/src/core-skills/wizz-customize/SKILL.md +13 -10
- package/src/core-skills/wizz-forge-idea/SKILL.md +6 -6
- package/src/core-skills/wizz-forge-idea/scripts/__pycache__/resolve_personas.cpython-314.pyc +0 -0
- package/src/core-skills/wizz-forge-idea/scripts/resolve_personas.py +17 -1
- package/src/core-skills/wizz-party-mode/SKILL.md +3 -3
- package/src/core-skills/wizz-party-mode/references/create-party.md +1 -1
- package/src/core-skills/wizz-party-mode/references/party-memory.md +2 -2
- package/src/core-skills/wizz-party-mode/scripts/__pycache__/resolve_party.cpython-314.pyc +0 -0
- package/src/core-skills/wizz-party-mode/scripts/resolve_party.py +17 -1
- package/src/core-skills/wizz-review-adversarial-general/SKILL.md +1 -1
- package/src/core-skills/wizz-spec/SKILL.md +5 -5
- package/src/modules/lowticket/README.md +6 -6
- package/src/modules/lowticket/module.yaml +4 -1
- package/src/modules/lowticket/skills/{lowticket-funil → wizz-lowticket-funil}/SKILL.md +4 -4
- package/src/modules/lowticket/skills/{lowticket-funil → wizz-lowticket-funil}/references/copy-das-paginas.md +1 -1
- package/src/modules/lowticket/skills/{lowticket-metodologia → wizz-lowticket-metodologia}/SKILL.md +1 -1
- package/src/modules/lowticket/skills/{lowticket-minerador → wizz-lowticket-minerador}/SKILL.md +3 -3
- package/src/modules/lowticket/skills/{lowticket-minerador → wizz-lowticket-minerador}/references/rubrica.md +1 -1
- package/src/modules/lowticket/skills/{lowticket-pagina → wizz-lowticket-pagina}/SKILL.md +4 -4
- package/src/modules/lowticket/skills/{lowticket-trafego → wizz-lowticket-trafego}/SKILL.md +3 -3
- package/src/modules/lowticket/skills/{lowticket-trafego → wizz-lowticket-trafego}/references/reguas.md +1 -1
- package/src/modules/wizz/_shared/communication-rules.md +1 -1
- package/src/modules/wizz/_shared/despacho-barato.md +9 -0
- package/src/modules/wizz/_shared/token-economy.md +7 -0
- package/src/modules/wizz/agents/wizz-ads/SKILL.md +1 -1
- package/src/modules/wizz/agents/wizz-ads/customize.toml +1 -2
- package/src/modules/wizz/agents/wizz-copy/SKILL.md +1 -1
- package/src/modules/wizz/agents/wizz-copy/customize.toml +1 -2
- package/src/modules/wizz/agents/wizz-designer/SKILL.md +1 -1
- package/src/modules/wizz/agents/wizz-designer/customize.toml +1 -2
- package/src/modules/wizz/agents/wizz-growth/SKILL.md +1 -1
- package/src/modules/wizz/agents/wizz-growth/customize.toml +1 -2
- package/src/modules/wizz/agents/wizz-maestro/SKILL.md +5 -5
- package/src/modules/wizz/agents/wizz-maestro/customize.toml +4 -8
- package/src/modules/wizz/agents/wizz-memoria/SKILL.md +1 -1
- package/src/modules/wizz/agents/wizz-memoria/customize.toml +1 -2
- package/src/modules/wizz/agents/wizz-qa/SKILL.md +1 -1
- package/src/modules/wizz/agents/wizz-qa/customize.toml +1 -2
- package/src/modules/wizz/agents/wizz-seo/SKILL.md +1 -1
- package/src/modules/wizz/agents/wizz-seo/customize.toml +1 -2
- package/src/modules/wizz/agents/wizz-social/SKILL.md +1 -1
- package/src/modules/wizz/agents/wizz-social/customize.toml +1 -2
- package/src/modules/wizz/module.yaml +3 -0
- package/src/modules/wizz/overrides/wizz-agent-analyst.toml +1 -2
- package/src/modules/wizz/overrides/wizz-agent-architect.toml +1 -2
- package/src/modules/wizz/overrides/wizz-agent-dev.toml +1 -2
- package/src/modules/wizz/overrides/wizz-agent-pm.toml +1 -2
- package/src/modules/wizz/overrides/wizz-agent-tech-writer.toml +1 -2
- package/src/modules/wizz/overrides/wizz-agent-ux-designer.toml +1 -2
- package/src/modules/wizz/subagents/codex/wizz-exec-haiku.toml +2 -0
- package/src/modules/wizz/subagents/codex/wizz-exec-opus.toml +2 -0
- package/src/modules/wizz/subagents/codex/wizz-exec-review.toml +2 -0
- package/src/modules/wizz/subagents/codex/wizz-exec-sonnet.toml +2 -0
- package/src/modules/wizz/subagents/gemini/wizz-exec-haiku.md +4 -1
- package/src/modules/wizz/subagents/gemini/wizz-exec-opus.md +4 -1
- package/src/modules/wizz/subagents/gemini/wizz-exec-review.md +4 -1
- package/src/modules/wizz/subagents/gemini/wizz-exec-sonnet.md +4 -1
- package/src/modules/wizz/subagents/opencode/wizz-exec-haiku.md +4 -1
- package/src/modules/wizz/subagents/opencode/wizz-exec-opus.md +4 -1
- package/src/modules/wizz/subagents/opencode/wizz-exec-review.md +4 -1
- package/src/modules/wizz/subagents/opencode/wizz-exec-sonnet.md +4 -1
- package/src/modules/wizz/subagents/spec.yaml +148 -0
- package/src/modules/wizz/subagents/wizz-exec-haiku.md +4 -1
- package/src/modules/wizz/subagents/wizz-exec-opus.md +4 -1
- package/src/modules/wizz/subagents/wizz-exec-review.md +4 -1
- package/src/modules/wizz/subagents/wizz-exec-sonnet.md +4 -1
- package/src/scripts/__pycache__/resolve_customization.cpython-314.pyc +0 -0
- package/src/scripts/memlog.js +368 -0
- package/src/scripts/resolve_customization.py +124 -15
- package/src/skills-lib/_shared/complexity-signal.md +14 -0
- package/src/skills-lib/wizz-canvas-design/canvas-fonts/InstrumentSerif-OFL.txt +93 -0
- package/src/skills-lib/wizz-huashu-design/references/sfx-library.md +1 -1
- package/src/skills-lib/wizz-huashu-design/scripts/add-music.sh +1 -1
- package/src/skills-lib/wizz-huashu-design/scripts/mix-voiceover.sh +1 -1
- package/src/skills-lib/wizz-impeccable/LICENSE.txt +202 -0
- package/src/skills-lib/wizz-offer-forge/SKILL.md +1 -1
- package/src/skills-lib/wizz-react-components/LICENSE.txt +202 -0
- package/src/skills-lib/wizz-router/SKILL.md +2 -2
- package/src/skills-lib/wizz-supabase-postgres-best-practices/LICENSE +21 -0
- package/src/skills-lib/wizz-taste-skill/SKILL.md +1 -1
- package/src/skills-lib/wizz-tracking-audit/SKILL.md +1 -1
- package/tools/fetch-assets.mjs +70 -38
- package/tools/hooks/README.md +22 -0
- package/tools/hooks/rtk-rewrite.sh +280 -0
- package/tools/hooks/security-defensive-context.js +70 -0
- package/tools/hooks/session-rules.js +368 -0
- package/tools/hooks/wizz-decision-trace.js +389 -0
- package/tools/hooks/wizz-router-enforce.js +258 -0
- package/tools/installer/banner.js +1 -1
- package/tools/installer/commands/doctor.js +124 -0
- package/tools/installer/commands/fetch-assets.js +7 -8
- package/tools/installer/commands/install.js +1 -1
- package/tools/installer/commands/resolve.js +95 -0
- package/tools/installer/core/doctor.js +648 -0
- package/tools/installer/core/hash-cache.js +156 -0
- package/tools/installer/core/help-catalog.js +4 -1
- package/tools/installer/core/hooks-settings.js +178 -0
- package/tools/installer/core/installer.js +297 -15
- package/tools/installer/core/legacy-warnings.js +0 -4
- package/tools/installer/core/manifest-generator.js +121 -43
- package/tools/installer/core/manifest.js +36 -32
- package/tools/installer/core/module-config-writer.js +4 -1
- package/tools/installer/core/python-check.js +60 -63
- package/tools/installer/core/quick-update.js +76 -43
- package/tools/installer/core/resolved-config.js +168 -0
- package/tools/installer/core/resolved-customizations.js +736 -0
- package/tools/installer/core/resolved-includes.js +262 -0
- package/tools/installer/core/resolved-schema.js +148 -0
- package/tools/installer/core/user-file-preservation.js +40 -8
- package/tools/installer/core/wizz-dir.js +117 -0
- package/tools/installer/core/yaml-cache.js +105 -0
- package/tools/installer/fs-native.js +97 -6
- package/tools/installer/ide/_config-driven.js +12 -75
- package/tools/installer/ide/platform-codes.js +111 -16
- package/tools/installer/ide/platform-codes.yaml +45 -100
- package/tools/installer/ide/shared/path-utils.js +6 -208
- package/tools/installer/install-messages.yaml +4 -14
- package/tools/installer/modules/channel-plan.js +15 -2
- package/tools/installer/modules/config-collector.js +762 -0
- package/tools/installer/modules/config-values.js +352 -0
- package/tools/installer/modules/custom-module-manager.js +161 -28
- package/tools/installer/modules/env-vars.js +119 -0
- package/tools/installer/modules/external-manager.js +133 -60
- package/tools/installer/modules/git-cache-utils.js +125 -0
- package/tools/installer/modules/module-catalog.js +565 -0
- package/tools/installer/modules/module-installer.js +618 -0
- package/tools/installer/modules/module-interface.js +86 -0
- package/tools/installer/modules/official-modules.js +98 -2172
- package/tools/installer/modules/pin-spec.js +125 -0
- package/tools/installer/modules/plugin-resolver.js +4 -0
- package/tools/installer/modules/skills-lib.js +3 -6
- package/tools/installer/prompts.js +0 -3
- package/tools/installer/ui.js +89 -54
- package/tools/installer/wizz-cli.js +1 -1
- package/tools/lib/frontmatter.js +139 -0
- package/tools/lib/sync-targets.mjs +49 -0
- package/tools/lib/walk.js +93 -0
- package/wizz-modules.yaml +9 -0
- package/src/scripts/__pycache__/memlog.cpython-313.pyc +0 -0
- package/src/scripts/memlog.py +0 -233
- package/src/scripts/tests/__pycache__/test_memlog.cpython-313-pytest-9.1.1.pyc +0 -0
- package/src/scripts/tests/__pycache__/test_resolve_customization.cpython-313-pytest-9.1.1.pyc +0 -0
- package/src/scripts/tests/test_memlog.py +0 -306
- package/src/skills-lib/wizz-huashu-design/assets/showcases/INDEX.md +0 -115
- package/src/skills-lib/wizz-huashu-design/assets/showcases/cover/cover-build.html +0 -235
- package/src/skills-lib/wizz-huashu-design/assets/showcases/cover/cover-build.png +0 -0
- package/src/skills-lib/wizz-huashu-design/assets/showcases/cover/cover-pentagram.html +0 -229
- package/src/skills-lib/wizz-huashu-design/assets/showcases/cover/cover-pentagram.png +0 -0
- package/src/skills-lib/wizz-huashu-design/assets/showcases/cover/cover-takram.html +0 -288
- package/src/skills-lib/wizz-huashu-design/assets/showcases/cover/cover-takram.png +0 -0
- package/src/skills-lib/wizz-huashu-design/assets/showcases/infographic/infographic-build.html +0 -503
- package/src/skills-lib/wizz-huashu-design/assets/showcases/infographic/infographic-build.png +0 -0
- package/src/skills-lib/wizz-huashu-design/assets/showcases/infographic/infographic-pentagram.html +0 -600
- package/src/skills-lib/wizz-huashu-design/assets/showcases/infographic/infographic-pentagram.png +0 -0
- package/src/skills-lib/wizz-huashu-design/assets/showcases/infographic/infographic-takram.html +0 -670
- package/src/skills-lib/wizz-huashu-design/assets/showcases/infographic/infographic-takram.png +0 -0
- package/src/skills-lib/wizz-huashu-design/assets/showcases/ppt/ppt-build.html +0 -382
- package/src/skills-lib/wizz-huashu-design/assets/showcases/ppt/ppt-build.png +0 -0
- package/src/skills-lib/wizz-huashu-design/assets/showcases/ppt/ppt-pentagram.html +0 -536
- package/src/skills-lib/wizz-huashu-design/assets/showcases/ppt/ppt-pentagram.png +0 -0
- package/src/skills-lib/wizz-huashu-design/assets/showcases/ppt/ppt-takram.html +0 -497
- package/src/skills-lib/wizz-huashu-design/assets/showcases/ppt/ppt-takram.png +0 -0
- package/src/skills-lib/wizz-huashu-design/assets/showcases/website-ai-nav/ainav-build.html +0 -385
- package/src/skills-lib/wizz-huashu-design/assets/showcases/website-ai-nav/ainav-build.png +0 -0
- package/src/skills-lib/wizz-huashu-design/assets/showcases/website-ai-nav/ainav-pentagram.html +0 -422
- package/src/skills-lib/wizz-huashu-design/assets/showcases/website-ai-nav/ainav-pentagram.png +0 -0
- package/src/skills-lib/wizz-huashu-design/assets/showcases/website-ai-nav/ainav-takram.html +0 -499
- package/src/skills-lib/wizz-huashu-design/assets/showcases/website-ai-nav/ainav-takram.png +0 -0
- package/src/skills-lib/wizz-huashu-design/assets/showcases/website-ai-writing/aiwriting-build.html +0 -562
- package/src/skills-lib/wizz-huashu-design/assets/showcases/website-ai-writing/aiwriting-build.png +0 -0
- package/src/skills-lib/wizz-huashu-design/assets/showcases/website-ai-writing/aiwriting-pentagram.html +0 -548
- package/src/skills-lib/wizz-huashu-design/assets/showcases/website-ai-writing/aiwriting-pentagram.png +0 -0
- package/src/skills-lib/wizz-huashu-design/assets/showcases/website-ai-writing/aiwriting-takram.html +0 -696
- package/src/skills-lib/wizz-huashu-design/assets/showcases/website-ai-writing/aiwriting-takram.png +0 -0
- package/src/skills-lib/wizz-huashu-design/assets/showcases/website-devdocs/devdocs-build.html +0 -372
- package/src/skills-lib/wizz-huashu-design/assets/showcases/website-devdocs/devdocs-build.png +0 -0
- package/src/skills-lib/wizz-huashu-design/assets/showcases/website-devdocs/devdocs-pentagram.html +0 -460
- package/src/skills-lib/wizz-huashu-design/assets/showcases/website-devdocs/devdocs-pentagram.png +0 -0
- package/src/skills-lib/wizz-huashu-design/assets/showcases/website-devdocs/devdocs-takram.html +0 -494
- package/src/skills-lib/wizz-huashu-design/assets/showcases/website-devdocs/devdocs-takram.png +0 -0
- package/src/skills-lib/wizz-huashu-design/assets/showcases/website-homepage/homepage-build.html +0 -367
- package/src/skills-lib/wizz-huashu-design/assets/showcases/website-homepage/homepage-build.png +0 -0
- package/src/skills-lib/wizz-huashu-design/assets/showcases/website-homepage/homepage-pentagram.html +0 -368
- package/src/skills-lib/wizz-huashu-design/assets/showcases/website-homepage/homepage-pentagram.png +0 -0
- package/src/skills-lib/wizz-huashu-design/assets/showcases/website-homepage/homepage-takram.html +0 -459
- package/src/skills-lib/wizz-huashu-design/assets/showcases/website-homepage/homepage-takram.png +0 -0
- package/src/skills-lib/wizz-huashu-design/assets/showcases/website-saas/saas-build.html +0 -493
- package/src/skills-lib/wizz-huashu-design/assets/showcases/website-saas/saas-build.png +0 -0
- package/src/skills-lib/wizz-huashu-design/assets/showcases/website-saas/saas-pentagram.html +0 -556
- package/src/skills-lib/wizz-huashu-design/assets/showcases/website-saas/saas-pentagram.png +0 -0
- package/src/skills-lib/wizz-huashu-design/assets/showcases/website-saas/saas-takram.html +0 -604
- package/src/skills-lib/wizz-huashu-design/assets/showcases/website-saas/saas-takram.png +0 -0
- package/tools/installer/file-ops.js +0 -204
- package/tools/installer/ide/shared/skill-manifest.js +0 -57
- package/tools/installer/yaml-format.js +0 -245
- package/web-bundles/README.md +0 -46
- package/web-bundles/brainstorming-coach/INSTRUCTIONS.md +0 -86
- package/web-bundles/brainstorming-coach/SKILL.md +0 -83
- package/web-bundles/brainstorming-coach/brain-methods.csv +0 -62
- package/web-bundles/bundles.json +0 -139
- package/web-bundles/market-and-industry-research/INSTRUCTIONS.md +0 -88
- package/web-bundles/market-and-industry-research/SKILL.md +0 -59
- package/web-bundles/prd-coach/INSTRUCTIONS.md +0 -86
- package/web-bundles/prd-coach/SKILL.md +0 -101
- package/web-bundles/prd-coach/prd-template.md +0 -165
- package/web-bundles/prd-coach/prd-validation-checklist.md +0 -135
- package/web-bundles/prfaq-coach/INSTRUCTIONS.md +0 -86
- package/web-bundles/prfaq-coach/SKILL.md +0 -139
- package/web-bundles/product-brief-coach/INSTRUCTIONS.md +0 -86
- package/web-bundles/product-brief-coach/SKILL.md +0 -113
- package/web-bundles/ux-coach/INSTRUCTIONS.md +0 -92
- package/web-bundles/ux-coach/SKILL.md +0 -187
- package/web-bundles/ux-coach/ux-validation.md +0 -100
- /package/src/modules/lowticket/skills/{lowticket-funil → wizz-lowticket-funil}/references/mapa-do-funil.md +0 -0
- /package/src/modules/lowticket/skills/{lowticket-metodologia → wizz-lowticket-metodologia}/CATALOGO.md +0 -0
- /package/src/modules/lowticket/skills/{lowticket-metodologia → wizz-lowticket-metodologia}/knowledge/01-principios.md +0 -0
- /package/src/modules/lowticket/skills/{lowticket-metodologia → wizz-lowticket-metodologia}/knowledge/02-diagnostico-funil.md +0 -0
- /package/src/modules/lowticket/skills/{lowticket-metodologia → wizz-lowticket-metodologia}/knowledge/03-campanha-bidcap.md +0 -0
- /package/src/modules/lowticket/skills/{lowticket-metodologia → wizz-lowticket-metodologia}/knowledge/04-criativos.md +0 -0
- /package/src/modules/lowticket/skills/{lowticket-metodologia → wizz-lowticket-metodologia}/knowledge/04a-criativos-ia.md +0 -0
- /package/src/modules/lowticket/skills/{lowticket-metodologia → wizz-lowticket-metodologia}/knowledge/04b-criativos-formatos.md +0 -0
- /package/src/modules/lowticket/skills/{lowticket-metodologia → wizz-lowticket-metodologia}/knowledge/05-oferta.md +0 -0
- /package/src/modules/lowticket/skills/{lowticket-metodologia → wizz-lowticket-metodologia}/knowledge/06-pagina-vendas.md +0 -0
- /package/src/modules/lowticket/skills/{lowticket-metodologia → wizz-lowticket-metodologia}/knowledge/06a-instagram.md +0 -0
- /package/src/modules/lowticket/skills/{lowticket-metodologia → wizz-lowticket-metodologia}/knowledge/06b-player-vsl.md +0 -0
- /package/src/modules/lowticket/skills/{lowticket-metodologia → wizz-lowticket-metodologia}/knowledge/07-funil-upsell.md +0 -0
- /package/src/modules/lowticket/skills/{lowticket-metodologia → wizz-lowticket-metodologia}/knowledge/07a-copy-humanizacao.md +0 -0
- /package/src/modules/lowticket/skills/{lowticket-metodologia → wizz-lowticket-metodologia}/knowledge/08-pesquisa-publico.md +0 -0
- /package/src/modules/lowticket/skills/{lowticket-metodologia → wizz-lowticket-metodologia}/knowledge/09-especialista-coproducao.md +0 -0
- /package/src/modules/lowticket/skills/{lowticket-metodologia → wizz-lowticket-metodologia}/knowledge/10-levantar-caixa.md +0 -0
- /package/src/modules/lowticket/skills/{lowticket-metodologia → wizz-lowticket-metodologia}/knowledge/11-checklist-roi.md +0 -0
- /package/src/modules/lowticket/skills/{lowticket-metodologia → wizz-lowticket-metodologia}/knowledge/12-mineracao-ofertas.md +0 -0
- /package/src/modules/lowticket/skills/{lowticket-metodologia → wizz-lowticket-metodologia}/knowledge/12a-mineracao-veredito.md +0 -0
- /package/src/modules/lowticket/skills/{lowticket-metodologia → wizz-lowticket-metodologia}/knowledge/12b-fabrica-de-ofertas.md +0 -0
- /package/src/modules/lowticket/skills/{lowticket-metodologia → wizz-lowticket-metodologia}/knowledge/12c-anatomia-low-ticket.md +0 -0
- /package/src/modules/lowticket/skills/{lowticket-metodologia → wizz-lowticket-metodologia}/knowledge/13-benchmarks-vsl.md +0 -0
- /package/src/modules/lowticket/skills/{lowticket-metodologia → wizz-lowticket-metodologia}/knowledge/14-vocabulario.md +0 -0
- /package/src/modules/lowticket/skills/{lowticket-metodologia → wizz-lowticket-metodologia}/knowledge/15-como-estender.md +0 -0
- /package/src/modules/lowticket/skills/{lowticket-metodologia → wizz-lowticket-metodologia}/knowledge/17-rastreamento.md +0 -0
- /package/src/modules/lowticket/skills/{lowticket-metodologia → wizz-lowticket-metodologia}/knowledge/18-copy-desejo-oferta.md +0 -0
- /package/src/modules/lowticket/skills/{lowticket-metodologia → wizz-lowticket-metodologia}/knowledge/INDEX.md +0 -0
- /package/src/modules/lowticket/skills/{lowticket-metodologia → wizz-lowticket-metodologia}/knowledge/guardrails.md +0 -0
- /package/src/modules/lowticket/skills/{lowticket-metodologia → wizz-lowticket-metodologia}/knowledge/pontos-em-aberto.md +0 -0
- /package/src/modules/lowticket/skills/{lowticket-metodologia → wizz-lowticket-metodologia}/references/swipe-file.md +0 -0
- /package/src/modules/lowticket/skills/{lowticket-pagina → wizz-lowticket-pagina}/references/metas-e-medicao.md +0 -0
- /package/src/modules/lowticket/skills/{lowticket-pagina → wizz-lowticket-pagina}/references/padroes-de-codigo.md +0 -0
- /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
|
+
};
|