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
|
@@ -3,7 +3,6 @@ const https = require('node:https');
|
|
|
3
3
|
const { execFile } = require('node:child_process');
|
|
4
4
|
const { promisify } = require('node:util');
|
|
5
5
|
const fs = require('../fs-native');
|
|
6
|
-
const crypto = require('node:crypto');
|
|
7
6
|
const { resolveModuleVersion } = require('../modules/version-resolver');
|
|
8
7
|
const prompts = require('../prompts');
|
|
9
8
|
|
|
@@ -317,17 +316,14 @@ class Manifest {
|
|
|
317
316
|
}
|
|
318
317
|
|
|
319
318
|
/**
|
|
320
|
-
* Calculate SHA256 hash of a file
|
|
319
|
+
* Calculate SHA256 hash of a file. Delegates to the single canonical
|
|
320
|
+
* implementation in fs-native.js (memoized by path+size+mtime within the
|
|
321
|
+
* same process) — see F06/F10 in the 2026-09-11 audit.
|
|
321
322
|
* @param {string} filePath - Path to file
|
|
322
|
-
* @returns {string} SHA256 hash
|
|
323
|
+
* @returns {string|null} SHA256 hash, or null if the file can't be read
|
|
323
324
|
*/
|
|
324
325
|
async calculateFileHash(filePath) {
|
|
325
|
-
|
|
326
|
-
const content = await fs.readFile(filePath);
|
|
327
|
-
return crypto.createHash('sha256').update(content).digest('hex');
|
|
328
|
-
} catch {
|
|
329
|
-
return null;
|
|
330
|
-
}
|
|
326
|
+
return fs.calculateFileHash(filePath);
|
|
331
327
|
}
|
|
332
328
|
|
|
333
329
|
/**
|
|
@@ -445,33 +441,41 @@ class Manifest {
|
|
|
445
441
|
async checkForUpdates(wizzDir) {
|
|
446
442
|
const semver = require('semver');
|
|
447
443
|
const modules = await this.getAllModuleVersions(wizzDir);
|
|
448
|
-
const updates = [];
|
|
449
444
|
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
445
|
+
// One npm lookup per module (subprocess + HTTPS fallback, 10s timeout
|
|
446
|
+
// each) has no dependency between iterations, so resolve them all
|
|
447
|
+
// concurrently instead of N sequential round-trips (F04). fetchNpmVersion
|
|
448
|
+
// never throws — it already resolves to null on any per-module failure —
|
|
449
|
+
// so a single module's error can't sink the others, and Promise.all
|
|
450
|
+
// preserves `modules` order in `results` regardless of resolution timing.
|
|
451
|
+
const results = await Promise.all(
|
|
452
|
+
modules.map(async (module) => {
|
|
453
|
+
if (!module.npmPackage) {
|
|
454
|
+
return null; // Skip modules without npm package (built-in)
|
|
455
|
+
}
|
|
459
456
|
|
|
460
|
-
|
|
461
|
-
|
|
457
|
+
const latestVersion = await this.fetchNpmVersion(module.npmPackage);
|
|
458
|
+
if (!latestVersion) {
|
|
459
|
+
return null;
|
|
460
|
+
}
|
|
462
461
|
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
462
|
+
const installedVersion = semver.valid(module.version) || semver.valid(semver.coerce(module.version || ''));
|
|
463
|
+
const availableVersion = semver.valid(latestVersion) || semver.valid(semver.coerce(latestVersion));
|
|
464
|
+
|
|
465
|
+
if (installedVersion && availableVersion && semver.gt(availableVersion, installedVersion)) {
|
|
466
|
+
return {
|
|
467
|
+
name: module.name,
|
|
468
|
+
installedVersion: module.version,
|
|
469
|
+
latestVersion: latestVersion,
|
|
470
|
+
npmPackage: module.npmPackage,
|
|
471
|
+
updateAvailable: true,
|
|
472
|
+
};
|
|
473
|
+
}
|
|
474
|
+
return null;
|
|
475
|
+
}),
|
|
476
|
+
);
|
|
473
477
|
|
|
474
|
-
return
|
|
478
|
+
return results.filter(Boolean);
|
|
475
479
|
}
|
|
476
480
|
}
|
|
477
481
|
|
|
@@ -25,7 +25,10 @@ async function generateModuleConfigs(wizzDir, moduleConfigs, { trackFile }) {
|
|
|
25
25
|
|
|
26
26
|
// Get all installed module directories
|
|
27
27
|
const entries = await fs.readdir(wizzDir, { withFileTypes: true });
|
|
28
|
-
|
|
28
|
+
// 'hooks' (RT-C1, tools/hooks/* copied here by Installer#_installHooks) is
|
|
29
|
+
// infra, not a module — without this exclusion this scanner treated it as
|
|
30
|
+
// one and wrote a spurious _wizz/hooks/config.yaml.
|
|
31
|
+
const nonModuleDirs = new Set(['_config', '_memory', 'memory', 'docs', 'scripts', 'custom', 'hooks']);
|
|
29
32
|
const installedModules = entries.filter((entry) => entry.isDirectory() && !nonModuleDirs.has(entry.name)).map((entry) => entry.name);
|
|
30
33
|
|
|
31
34
|
// Generate config.yaml for each installed module
|
|
@@ -1,16 +1,27 @@
|
|
|
1
1
|
const { spawnSync } = require('node:child_process');
|
|
2
2
|
const prompts = require('../prompts');
|
|
3
3
|
|
|
4
|
-
//
|
|
5
|
-
// src/scripts/
|
|
6
|
-
//
|
|
4
|
+
// Since audit item 29 (2026-09-12) Node 20.12+ is the ONLY prerequisite of the
|
|
5
|
+
// Wizz core: memlog is Node (src/scripts/memlog.js), and every TOML merge the
|
|
6
|
+
// core needs is resolved at install time into `_wizz/_resolved/` by the
|
|
7
|
+
// installer's own smol-toml resolver. Python is now optional and belongs to
|
|
8
|
+
// the BMAD skills that ship their own Python scripts.
|
|
9
|
+
//
|
|
10
|
+
// The version bands stay as they are because those skill-owned scripts still
|
|
11
|
+
// read TOML: Python 3.11 added stdlib `tomllib` (PEP 680), and the older
|
|
12
|
+
// scripts run on 3.8+.
|
|
7
13
|
const PYTHON_FULL_SUPPORT = { major: 3, minor: 11 };
|
|
8
14
|
const PYTHON_PARTIAL_SUPPORT = { major: 3, minor: 8 };
|
|
9
15
|
|
|
10
|
-
//
|
|
11
|
-
//
|
|
12
|
-
|
|
13
|
-
|
|
16
|
+
// The skills that stop working without `python3` — named explicitly so the
|
|
17
|
+
// warning says what the user loses instead of a vague "some features".
|
|
18
|
+
const PYTHON_ONLY_SKILLS =
|
|
19
|
+
'wizz-brainstorming, wizz-retrospective, wizz-sprint-planning, wizz-architecture, wizz-party-mode, wizz-forge-idea, wizz-advanced-elicitation, wizz-customize';
|
|
20
|
+
|
|
21
|
+
// Every skill-owned call site invokes a literal `python3`, so only that
|
|
22
|
+
// command's version vouches for those skills. The fallback probes exist to
|
|
23
|
+
// tell the user "Python is installed, but not under the name WIZZ uses"
|
|
24
|
+
// instead of a misleading "No Python found".
|
|
14
25
|
const RUNTIME_COMMAND = 'python3';
|
|
15
26
|
const PROBE_CANDIDATES =
|
|
16
27
|
process.platform === 'win32'
|
|
@@ -108,7 +119,7 @@ function detectPython() {
|
|
|
108
119
|
|
|
109
120
|
function upgradeHints() {
|
|
110
121
|
return [
|
|
111
|
-
'How to get Python 3.11+ (as `python3`):',
|
|
122
|
+
'How to get Python 3.11+ (as `python3`), if you want those skills:',
|
|
112
123
|
' macOS: brew install python3',
|
|
113
124
|
' Windows: winget install Python.Python.3.12 (then ensure `python3` resolves, e.g. enable the python3 alias)',
|
|
114
125
|
' Linux/WSL: sudo apt install python3 (Ubuntu 24.04+ ships 3.12; older distros: use pyenv or deadsnakes)',
|
|
@@ -117,83 +128,69 @@ function upgradeHints() {
|
|
|
117
128
|
}
|
|
118
129
|
|
|
119
130
|
/**
|
|
120
|
-
*
|
|
131
|
+
* One line saying exactly what a degraded Python means, per detection case.
|
|
132
|
+
* @param {'full'|'partial'|'unsupported'|'none'} status
|
|
133
|
+
* @param {Object|null} detected
|
|
134
|
+
* @returns {string}
|
|
135
|
+
*/
|
|
136
|
+
function degradedMessage(status, detected) {
|
|
137
|
+
if (detected && !detected.isRuntimeCommand) {
|
|
138
|
+
return (
|
|
139
|
+
`Python ${detected.version.raw} found via \`${detected.command}\`, but the skill scripts invoke \`python3\`, which is not on PATH.\n` +
|
|
140
|
+
`The Wizz core is unaffected (Node only). These skills stay unavailable until \`python3\` resolves: ${PYTHON_ONLY_SKILLS}.`
|
|
141
|
+
);
|
|
142
|
+
}
|
|
143
|
+
if (status === 'partial') {
|
|
144
|
+
return (
|
|
145
|
+
`Python ${detected.version.raw} detected (${detected.command}) — the skill scripts that read TOML need Python 3.11+ (stdlib tomllib).\n` +
|
|
146
|
+
`The Wizz core is unaffected (Node only). Partially available: ${PYTHON_ONLY_SKILLS}.`
|
|
147
|
+
);
|
|
148
|
+
}
|
|
149
|
+
const found =
|
|
150
|
+
status === 'unsupported' ? `Python ${detected.version.raw} detected (${detected.command}) — too old.` : 'No Python found on PATH.';
|
|
151
|
+
return (
|
|
152
|
+
`${found} That is fine: Node is the only prerequisite of the Wizz core.\n` +
|
|
153
|
+
`Only these skills need Python 3.11+ and stay unavailable until it is: ${PYTHON_ONLY_SKILLS}.`
|
|
154
|
+
);
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* Check the local Python environment and report which skills it costs.
|
|
159
|
+
*
|
|
160
|
+
* Informational only: since item 29 nothing in the core needs Python, so this
|
|
161
|
+
* never blocks, never prompts and never asks for an acknowledgement — it logs
|
|
162
|
+
* one line and the install moves on. The installer runs in the destination
|
|
163
|
+
* environment, so probing PATH here tests the right machine.
|
|
121
164
|
*
|
|
122
|
-
*
|
|
123
|
-
* may proceed — but the user must explicitly acknowledge the warning so it
|
|
124
|
-
* can't scroll past unseen. In non-interactive runs (--yes, or stdin is not
|
|
125
|
-
* a TTY) the warning is logged and the install continues without a prompt.
|
|
165
|
+
* `options.nonInteractive` is kept for call-site compatibility and is not read.
|
|
126
166
|
*
|
|
127
167
|
* @param {Object} [options]
|
|
128
|
-
* @param {boolean} [options.nonInteractive=false] - Skip the ack prompt (--yes, or no TTY)
|
|
129
168
|
* @returns {Promise<{status: string, detected: Object|null}>}
|
|
130
169
|
*/
|
|
131
|
-
async function checkPythonEnvironment(
|
|
170
|
+
async function checkPythonEnvironment() {
|
|
132
171
|
// Called via module.exports so tests can stub detection.
|
|
133
172
|
const detected = module.exports.detectPython();
|
|
134
173
|
const status = classifyPython(detected ? detected.version : null);
|
|
135
174
|
|
|
136
175
|
if (status === 'full' && detected.isRuntimeCommand) {
|
|
137
|
-
await prompts.log.success(
|
|
138
|
-
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
if (detected && !detected.isRuntimeCommand) {
|
|
142
|
-
await prompts.log.warn(
|
|
143
|
-
`Python ${detected.version.raw} found via \`${detected.command}\`, but Wizz scripts invoke \`python3\`, which is not on PATH.\n` +
|
|
144
|
-
`Python-powered features (memlog session memory, TOML config resolution) won't run until \`python3\` resolves —\n` +
|
|
145
|
-
`add a python3 alias/shim, or reinstall Python with the python3 launcher enabled.`,
|
|
146
|
-
);
|
|
147
|
-
} else if (status === 'partial') {
|
|
148
|
-
await prompts.log.warn(
|
|
149
|
-
`Python ${detected.version.raw} detected (${detected.command}) — Wizz's TOML config tools need Python 3.11+ (stdlib tomllib).\n` +
|
|
150
|
-
`Works: memlog session memory. Won't work: config/customization resolution scripts.`,
|
|
151
|
-
);
|
|
152
|
-
} else {
|
|
153
|
-
const found =
|
|
154
|
-
status === 'unsupported' ? `Python ${detected.version.raw} detected (${detected.command}) — too old.` : 'No Python found on PATH.';
|
|
155
|
-
await prompts.log.warn(
|
|
156
|
-
`${found} Wizz installs fine without it, but Python-powered features\n` +
|
|
157
|
-
`(memlog session memory, TOML config resolution) won't run until Python 3.11+ is available.`,
|
|
176
|
+
await prompts.log.success(
|
|
177
|
+
`Python ${detected.version.raw} detected (${detected.command}) — the optional Python-backed skills are available too.`,
|
|
158
178
|
);
|
|
159
|
-
}
|
|
160
|
-
await prompts.note(upgradeHints(), 'Python 3.11+ recommended');
|
|
161
|
-
|
|
162
|
-
if (nonInteractive) {
|
|
163
|
-
await prompts.log.info('Continuing anyway (non-interactive run). You can fix Python later — no reinstall needed.');
|
|
164
179
|
return { status, detected };
|
|
165
180
|
}
|
|
166
181
|
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
choices: [
|
|
170
|
-
{
|
|
171
|
-
name: 'Continue install',
|
|
172
|
-
value: 'continue',
|
|
173
|
-
hint: 'Wizz works without Python — you can fix Python later, no reinstall needed',
|
|
174
|
-
},
|
|
175
|
-
{
|
|
176
|
-
name: 'Quit and fix Python first',
|
|
177
|
-
value: 'quit',
|
|
178
|
-
hint: 'make Python 3.11+ available as python3, then re-run the installer',
|
|
179
|
-
},
|
|
180
|
-
],
|
|
181
|
-
default: 'continue',
|
|
182
|
-
});
|
|
183
|
-
|
|
184
|
-
if (choice === 'quit') {
|
|
185
|
-
await prompts.cancel('Make Python 3.11+ available as `python3` (see hints above), then re-run the installer.');
|
|
186
|
-
process.exit(0);
|
|
187
|
-
}
|
|
188
|
-
|
|
182
|
+
await prompts.log.info(degradedMessage(status, detected));
|
|
183
|
+
await prompts.note(upgradeHints(), 'Python 3.11+ optional');
|
|
189
184
|
return { status, detected };
|
|
190
185
|
}
|
|
191
186
|
|
|
192
187
|
module.exports = {
|
|
193
188
|
checkPythonEnvironment,
|
|
189
|
+
degradedMessage,
|
|
194
190
|
detectPython,
|
|
195
191
|
parsePythonVersion,
|
|
196
192
|
classifyPython,
|
|
197
193
|
PYTHON_FULL_SUPPORT,
|
|
198
194
|
PYTHON_PARTIAL_SUPPORT,
|
|
195
|
+
PYTHON_ONLY_SKILLS,
|
|
199
196
|
};
|
|
@@ -14,6 +14,80 @@ const { OfficialModules } = require('../modules/official-modules');
|
|
|
14
14
|
const { ExistingInstall } = require('./existing-install');
|
|
15
15
|
const { getProjectRoot } = require('../project-root');
|
|
16
16
|
const prompts = require('../prompts');
|
|
17
|
+
// Item 10 (review da fase 3, 2026-09-11): rebuild TAG@SHA pins from a
|
|
18
|
+
// manifest entry's version + shaRequested. pin-spec.js is a leaf module
|
|
19
|
+
// (no requires of its own), safe to pull in at top level here.
|
|
20
|
+
const { formatPinValue } = require('../modules/pin-spec');
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Build channelOptions (pins/nextSet) from the existing manifest's recorded
|
|
24
|
+
* per-module channel, so the config collector and clone steps that follow
|
|
25
|
+
* don't silently redecide a module's channel.
|
|
26
|
+
*
|
|
27
|
+
* Item 10 (review da fase 3, 2026-09-11): rebuilds `TAG@SHA`, not just
|
|
28
|
+
* `TAG`, whenever the manifest entry carries `shaRequested` — the SHA half
|
|
29
|
+
* of the `--pin CODE=TAG@SHA` that produced it (manifest-generator.js).
|
|
30
|
+
* Dropping that half here silently downgraded the pin to tag-only on every
|
|
31
|
+
* quick-update, so a tag force-moved on the remote between installs would
|
|
32
|
+
* pass unnoticed on the single most common reinstall path.
|
|
33
|
+
*
|
|
34
|
+
* Extracted from `quickUpdate` as its own function (rather than inlined) so
|
|
35
|
+
* it can be exercised directly in tests without mocking the whole
|
|
36
|
+
* `Installer` — see test/test-pin-sha.js.
|
|
37
|
+
*
|
|
38
|
+
* @param {Object|null} manifestData - `installer.manifest.read(wizzDir)` result
|
|
39
|
+
* @param {Object} [deps] - Injectable seams for tests
|
|
40
|
+
* @param {Function} [deps.warn] - Defaults to `prompts.log.warn`
|
|
41
|
+
* @param {{fetchStableTags: Function, classifyUpgrade: Function, parseGitHubRepo: Function}} [deps.channelResolver]
|
|
42
|
+
* Defaults to requiring `../modules/channel-resolver` (real GitHub tag lookups).
|
|
43
|
+
* @returns {Promise<{global: null, nextSet: Set<string>, pins: Map<string,string>, warnings: string[]}>}
|
|
44
|
+
*/
|
|
45
|
+
async function buildChannelOptionsFromManifest(manifestData, deps = {}) {
|
|
46
|
+
const warn = deps.warn || prompts.log.warn;
|
|
47
|
+
const channelOptions = { global: null, nextSet: new Set(), pins: new Map(), warnings: [] };
|
|
48
|
+
if (!manifestData?.modulesDetailed) return channelOptions;
|
|
49
|
+
|
|
50
|
+
const { fetchStableTags, classifyUpgrade, parseGitHubRepo } = deps.channelResolver || require('../modules/channel-resolver');
|
|
51
|
+
for (const entry of manifestData.modulesDetailed) {
|
|
52
|
+
if (!entry?.name || !entry?.channel) continue;
|
|
53
|
+
if (entry.channel === 'pinned' && entry.version) {
|
|
54
|
+
channelOptions.pins.set(entry.name, formatPinValue(entry.version, entry.shaRequested));
|
|
55
|
+
continue;
|
|
56
|
+
}
|
|
57
|
+
if (entry.channel === 'next') {
|
|
58
|
+
channelOptions.nextSet.add(entry.name);
|
|
59
|
+
continue;
|
|
60
|
+
}
|
|
61
|
+
// Stable: classify the available upgrade. Patches and minors fall
|
|
62
|
+
// through (stable default picks up the top tag). A major upgrade
|
|
63
|
+
// requires opt-in, so under quick-update's non-interactive semantics
|
|
64
|
+
// we pin to the current version to prevent a silent breaking jump.
|
|
65
|
+
if (entry.channel === 'stable' && entry.version && entry.repoUrl) {
|
|
66
|
+
const parsed = parseGitHubRepo(entry.repoUrl);
|
|
67
|
+
if (!parsed) continue;
|
|
68
|
+
try {
|
|
69
|
+
const tags = await fetchStableTags(parsed.owner, parsed.repo);
|
|
70
|
+
if (tags.length === 0) continue;
|
|
71
|
+
const topTag = tags[0].tag;
|
|
72
|
+
const cls = classifyUpgrade(entry.version, topTag);
|
|
73
|
+
if (cls === 'major') {
|
|
74
|
+
channelOptions.pins.set(entry.name, formatPinValue(entry.version, entry.shaRequested));
|
|
75
|
+
await warn(
|
|
76
|
+
`${entry.name} ${entry.version} → ${topTag} is a new major release; staying on ${entry.version}. ` +
|
|
77
|
+
`Run \`wizz install\` (Modify) with \`--pin ${entry.name}=${topTag}\` to accept.`,
|
|
78
|
+
);
|
|
79
|
+
}
|
|
80
|
+
} catch (error) {
|
|
81
|
+
// Tag lookup failed (offline, rate-limited). Stay on the current
|
|
82
|
+
// version rather than guessing — the existing cache is already
|
|
83
|
+
// at that ref, so re-using it keeps the install stable.
|
|
84
|
+
channelOptions.pins.set(entry.name, formatPinValue(entry.version, entry.shaRequested));
|
|
85
|
+
await warn(`Could not check ${entry.name} for updates (${error.message}); staying on ${entry.version}.`);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
return channelOptions;
|
|
90
|
+
}
|
|
17
91
|
|
|
18
92
|
/**
|
|
19
93
|
* Quick update: preserves all settings and only prompts for new config fields.
|
|
@@ -97,48 +171,7 @@ async function quickUpdate(installer, config) {
|
|
|
97
171
|
// 'pinned' would trigger a stable-channel tag lookup at config-collection
|
|
98
172
|
// time, burning GitHub API quota and potentially failing.
|
|
99
173
|
const manifestData = await installer.manifest.read(wizzDir);
|
|
100
|
-
const channelOptions =
|
|
101
|
-
if (manifestData?.modulesDetailed) {
|
|
102
|
-
const { fetchStableTags, classifyUpgrade, parseGitHubRepo } = require('../modules/channel-resolver');
|
|
103
|
-
for (const entry of manifestData.modulesDetailed) {
|
|
104
|
-
if (!entry?.name || !entry?.channel) continue;
|
|
105
|
-
if (entry.channel === 'pinned' && entry.version) {
|
|
106
|
-
channelOptions.pins.set(entry.name, entry.version);
|
|
107
|
-
continue;
|
|
108
|
-
}
|
|
109
|
-
if (entry.channel === 'next') {
|
|
110
|
-
channelOptions.nextSet.add(entry.name);
|
|
111
|
-
continue;
|
|
112
|
-
}
|
|
113
|
-
// Stable: classify the available upgrade. Patches and minors fall
|
|
114
|
-
// through (stable default picks up the top tag). A major upgrade
|
|
115
|
-
// requires opt-in, so under quick-update's non-interactive semantics
|
|
116
|
-
// we pin to the current version to prevent a silent breaking jump.
|
|
117
|
-
if (entry.channel === 'stable' && entry.version && entry.repoUrl) {
|
|
118
|
-
const parsed = parseGitHubRepo(entry.repoUrl);
|
|
119
|
-
if (!parsed) continue;
|
|
120
|
-
try {
|
|
121
|
-
const tags = await fetchStableTags(parsed.owner, parsed.repo);
|
|
122
|
-
if (tags.length === 0) continue;
|
|
123
|
-
const topTag = tags[0].tag;
|
|
124
|
-
const cls = classifyUpgrade(entry.version, topTag);
|
|
125
|
-
if (cls === 'major') {
|
|
126
|
-
channelOptions.pins.set(entry.name, entry.version);
|
|
127
|
-
await prompts.log.warn(
|
|
128
|
-
`${entry.name} ${entry.version} → ${topTag} is a new major release; staying on ${entry.version}. ` +
|
|
129
|
-
`Run \`wizz install\` (Modify) with \`--pin ${entry.name}=${topTag}\` to accept.`,
|
|
130
|
-
);
|
|
131
|
-
}
|
|
132
|
-
} catch (error) {
|
|
133
|
-
// Tag lookup failed (offline, rate-limited). Stay on the current
|
|
134
|
-
// version rather than guessing — the existing cache is already
|
|
135
|
-
// at that ref, so re-using it keeps the install stable.
|
|
136
|
-
channelOptions.pins.set(entry.name, entry.version);
|
|
137
|
-
await prompts.log.warn(`Could not check ${entry.name} for updates (${error.message}); staying on ${entry.version}.`);
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
}
|
|
141
|
-
}
|
|
174
|
+
const channelOptions = await buildChannelOptionsFromManifest(manifestData);
|
|
142
175
|
|
|
143
176
|
// Load existing configs and collect new fields (if any)
|
|
144
177
|
await prompts.log.info('Checking for new configuration options...');
|
|
@@ -206,4 +239,4 @@ async function quickUpdate(installer, config) {
|
|
|
206
239
|
};
|
|
207
240
|
}
|
|
208
241
|
|
|
209
|
-
module.exports = { quickUpdate };
|
|
242
|
+
module.exports = { quickUpdate, buildChannelOptionsFromManifest };
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resolved central config generator (audit item 29, 2026-09-12).
|
|
3
|
+
*
|
|
4
|
+
* Sibling of `resolved-customizations.js`. Where that one snapshots each
|
|
5
|
+
* skill's `customize.toml`, this one snapshots Wizz's CENTRAL config — the
|
|
6
|
+
* four-layer merge that `src/scripts/resolve_config.py` performs at runtime:
|
|
7
|
+
*
|
|
8
|
+
* 1. `_wizz/config.toml` (installer-owned team)
|
|
9
|
+
* 2. `_wizz/config.user.toml` (installer-owned user)
|
|
10
|
+
* 3. `_wizz/custom/config.toml` (human-authored team, committed)
|
|
11
|
+
* 4. `_wizz/custom/config.user.toml` (human-authored user, gitignored)
|
|
12
|
+
*
|
|
13
|
+
* The merged result is written to `_wizz/_resolved/_config.json`, so a skill
|
|
14
|
+
* that needs `core.user_name`, `core.communication_language` or
|
|
15
|
+
* `core.output_folder` reads ONE json file instead of spawning `python3`.
|
|
16
|
+
* That is what makes Node the only prerequisite for activating an agent:
|
|
17
|
+
* Python stays only for the BMAD skills that ship their own Python scripts.
|
|
18
|
+
*
|
|
19
|
+
* Merge rules are not re-implemented here — `deepMerge` from
|
|
20
|
+
* `resolved-customizations.js` is already the 1:1 port of the Python rules
|
|
21
|
+
* (scalars override, tables deep-merge, arrays of tables keyed by `code`/`id`
|
|
22
|
+
* merge by that key, every other array appends). One motor, one behaviour.
|
|
23
|
+
*
|
|
24
|
+
* Layer sourcing mirrors `resolveAll`: the two base layers come from the
|
|
25
|
+
* freshly written tree (`wizzDir`, possibly the A14 tmp scaffold), the two
|
|
26
|
+
* `custom/` layers from the REAL project root, so a fresh install still sees
|
|
27
|
+
* the user's overrides.
|
|
28
|
+
*
|
|
29
|
+
* Fail-open, like every other generator here: a missing or broken base
|
|
30
|
+
* `config.toml` means NO snapshot (a stale one is removed) and a warning —
|
|
31
|
+
* never a thrown install. Callers that find no `_config.json` fall back to
|
|
32
|
+
* `resolve_config.py` (where Python exists) or to neutral defaults.
|
|
33
|
+
*/
|
|
34
|
+
|
|
35
|
+
const path = require('node:path');
|
|
36
|
+
const nodeFs = require('node:fs');
|
|
37
|
+
const fs = require('../fs-native');
|
|
38
|
+
const { WIZZ_FOLDER_NAME } = require('../ide/shared/path-utils');
|
|
39
|
+
const { deepMerge, loadTomlLayer, computeInputsIndex } = require('./resolved-customizations');
|
|
40
|
+
|
|
41
|
+
// Name of the central-config snapshot inside `_resolved/`. Leading underscore
|
|
42
|
+
// keeps it out of the `<skill-name>.json` namespace (skills are `wizz-*`).
|
|
43
|
+
const CONFIG_SNAPSHOT = '_config.json';
|
|
44
|
+
|
|
45
|
+
const BASE_TEAM = 'config.toml';
|
|
46
|
+
const BASE_USER = 'config.user.toml';
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Absolute paths of the four config layers, in merge order (lowest first).
|
|
50
|
+
* @param {{projectRoot: string, wizzDir: string}} args
|
|
51
|
+
* @returns {string[]}
|
|
52
|
+
*/
|
|
53
|
+
function configLayerPaths({ projectRoot, wizzDir }) {
|
|
54
|
+
const customDir = path.join(projectRoot, WIZZ_FOLDER_NAME, 'custom');
|
|
55
|
+
return [path.join(wizzDir, BASE_TEAM), path.join(wizzDir, BASE_USER), path.join(customDir, BASE_TEAM), path.join(customDir, BASE_USER)];
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Merge the four layers into one object.
|
|
60
|
+
*
|
|
61
|
+
* The base layer (`_wizz/config.toml`) is load-bearing: without it there is
|
|
62
|
+
* no `core` table at all, and a snapshot written from `{}` would look valid
|
|
63
|
+
* while telling every skill the user has no name and no language. So a
|
|
64
|
+
* missing/broken base is reported as `{ config: null }`, not as `{}`.
|
|
65
|
+
*
|
|
66
|
+
* `absent` separates the two reasons, because they deserve different noise:
|
|
67
|
+
* a base that does not exist YET is the normal state during a fresh install
|
|
68
|
+
* (the resolver runs before `writeCentralConfig`) and must stay silent; a
|
|
69
|
+
* base that exists and does not parse is a real problem and warns.
|
|
70
|
+
*
|
|
71
|
+
* @param {{projectRoot: string, wizzDir: string}} args
|
|
72
|
+
* @returns {{config: object|null, absent: boolean, warnings: string[], inputs: string[]}}
|
|
73
|
+
*/
|
|
74
|
+
function resolveCentralConfig({ projectRoot, wizzDir }) {
|
|
75
|
+
const warnings = [];
|
|
76
|
+
const layers = configLayerPaths({ projectRoot, wizzDir });
|
|
77
|
+
const [baseTeamPath] = layers;
|
|
78
|
+
|
|
79
|
+
if (!nodeFs.existsSync(baseTeamPath)) {
|
|
80
|
+
return { config: null, absent: true, warnings, inputs: [] };
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
const baseTeam = loadTomlLayer(baseTeamPath, warnings);
|
|
84
|
+
if (baseTeam === null) {
|
|
85
|
+
warnings.push(`base config not readable (${baseTeamPath}): no _config.json written`);
|
|
86
|
+
return { config: null, absent: false, warnings, inputs: [] };
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
let merged = baseTeam;
|
|
90
|
+
for (const layerPath of layers.slice(1)) {
|
|
91
|
+
const layer = loadTomlLayer(layerPath, warnings);
|
|
92
|
+
if (layer !== null) merged = deepMerge(merged, layer);
|
|
93
|
+
}
|
|
94
|
+
return { config: merged, absent: false, warnings, inputs: layers.filter((p) => nodeFs.existsSync(p)) };
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Write `_resolved/_config.json`, or remove a stale one when the central
|
|
99
|
+
* config cannot be resolved.
|
|
100
|
+
*
|
|
101
|
+
* @param {object} args
|
|
102
|
+
* @param {string} args.projectRoot
|
|
103
|
+
* @param {string} args.wizzDir
|
|
104
|
+
* @param {string} args.resolvedDir - `{wizzDir}/_resolved`, already created
|
|
105
|
+
* @returns {Promise<{written: boolean, absent: boolean, warnings: string[], entry: object|null}>}
|
|
106
|
+
*/
|
|
107
|
+
async function writeResolvedConfig({ projectRoot, wizzDir, resolvedDir }) {
|
|
108
|
+
const snapshotPath = path.join(resolvedDir, CONFIG_SNAPSHOT);
|
|
109
|
+
const { config, absent, warnings, inputs } = resolveCentralConfig({ projectRoot, wizzDir });
|
|
110
|
+
|
|
111
|
+
if (config === null) {
|
|
112
|
+
await fs.remove(snapshotPath);
|
|
113
|
+
return { written: false, absent, warnings, entry: null };
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
await fs.writeFile(snapshotPath, `${JSON.stringify(config, null, 2)}\n`, 'utf8');
|
|
117
|
+
return {
|
|
118
|
+
written: true,
|
|
119
|
+
absent: false,
|
|
120
|
+
warnings,
|
|
121
|
+
entry: { inputs: computeInputsIndex({ projectRoot, wizzDir, inputPaths: inputs }) },
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Second pass for the installer: write `_config.json` AFTER the central
|
|
127
|
+
* config exists, patching only the `config` key of an `.index.json` that is
|
|
128
|
+
* already on disk.
|
|
129
|
+
*
|
|
130
|
+
* Why a second pass at all: on a fresh install the snapshot generator runs
|
|
131
|
+
* inside the tmp scaffold, before `writeCentralConfig` (and before
|
|
132
|
+
* `--set` overrides) have produced `_wizz/config.toml`. Resolving the
|
|
133
|
+
* central config there would snapshot a file that does not exist yet. So
|
|
134
|
+
* the installer calls this once more on the REAL `_wizz/`, after the swap
|
|
135
|
+
* and after the overrides, and only the central-config half is redone —
|
|
136
|
+
* the skill snapshots are already correct and are not touched.
|
|
137
|
+
*
|
|
138
|
+
* Fail-open like everything else here: any failure returns `written: false`
|
|
139
|
+
* with the reason, and the caller degrades to `wizz resolve` later.
|
|
140
|
+
*
|
|
141
|
+
* @param {object} args
|
|
142
|
+
* @param {string} args.projectRoot
|
|
143
|
+
* @param {string} args.wizzDir - the REAL `_wizz/`, post-swap
|
|
144
|
+
* @returns {Promise<{written: boolean, absent: boolean, warnings: string[]}>}
|
|
145
|
+
*/
|
|
146
|
+
async function refreshResolvedConfig({ projectRoot, wizzDir }) {
|
|
147
|
+
const resolvedDir = path.join(wizzDir, '_resolved');
|
|
148
|
+
await fs.mkdir(resolvedDir, { recursive: true });
|
|
149
|
+
const result = await writeResolvedConfig({ projectRoot, wizzDir, resolvedDir });
|
|
150
|
+
|
|
151
|
+
// Patch the index in place: `skills` was written by the first pass and is
|
|
152
|
+
// still valid, so re-deriving it here would be wasted work and a chance to
|
|
153
|
+
// get it wrong.
|
|
154
|
+
const { readIndex, writeResolvedIndex } = require('./resolved-customizations');
|
|
155
|
+
const index = readIndex(resolvedDir);
|
|
156
|
+
if (index && index.skills) {
|
|
157
|
+
await writeResolvedIndex(resolvedDir, index.skills, result.entry);
|
|
158
|
+
}
|
|
159
|
+
return { written: result.written, absent: result.absent, warnings: result.warnings };
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
module.exports = {
|
|
163
|
+
resolveCentralConfig,
|
|
164
|
+
writeResolvedConfig,
|
|
165
|
+
refreshResolvedConfig,
|
|
166
|
+
configLayerPaths,
|
|
167
|
+
CONFIG_SNAPSHOT,
|
|
168
|
+
};
|