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
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
const os = require('node:os');
|
|
1
2
|
const path = require('node:path');
|
|
2
3
|
const fs = require('../fs-native');
|
|
3
4
|
const { Manifest } = require('./manifest');
|
|
@@ -8,7 +9,6 @@ const { promptMissingEnvVars, mcpsWithMissingRequiredEnv } = require('../modules
|
|
|
8
9
|
const { installClis, renderInstallCommand } = require('../modules/cli-config');
|
|
9
10
|
const { writeDepsCache, readPreviousMcpPins } = require('../modules/deps-cache');
|
|
10
11
|
const { IdeManager } = require('../ide/manager');
|
|
11
|
-
const { FileOps } = require('../file-ops');
|
|
12
12
|
const { Config } = require('./config');
|
|
13
13
|
const { ManifestGenerator } = require('./manifest-generator');
|
|
14
14
|
const prompts = require('../prompts');
|
|
@@ -16,6 +16,7 @@ const { WIZZ_FOLDER_NAME } = require('../ide/shared/path-utils');
|
|
|
16
16
|
const { InstallPaths } = require('./install-paths');
|
|
17
17
|
const { ExternalModuleManager } = require('../modules/external-manager');
|
|
18
18
|
const { resolveModuleVersion } = require('../modules/version-resolver');
|
|
19
|
+
const { buildHookEntries, filterHooksRegisteredGlobally, mergeHooksIntoSettings } = require('./hooks-settings');
|
|
19
20
|
|
|
20
21
|
const { ExistingInstall } = require('./existing-install');
|
|
21
22
|
const { warnPreNativeSkillsLegacy } = require('./legacy-warnings');
|
|
@@ -24,12 +25,15 @@ const moduleConfigWriter = require('./module-config-writer');
|
|
|
24
25
|
const helpCatalog = require('./help-catalog');
|
|
25
26
|
const quickUpdateModule = require('./quick-update');
|
|
26
27
|
|
|
28
|
+
// `findWizzDir` lives in core/wizz-dir.js (single owner of `_wizz` resolution,
|
|
29
|
+
// item 20 of the 2026-09-11 audit). Re-exported below for existing callers.
|
|
30
|
+
const { findWizzDir } = require('./wizz-dir');
|
|
31
|
+
|
|
27
32
|
class Installer {
|
|
28
33
|
constructor() {
|
|
29
34
|
this.externalModuleManager = new ExternalModuleManager();
|
|
30
35
|
this.manifest = new Manifest();
|
|
31
36
|
this.ideManager = new IdeManager();
|
|
32
|
-
this.fileOps = new FileOps();
|
|
33
37
|
this.installedFiles = new Set(); // Track all installed files
|
|
34
38
|
this.wizzFolderName = WIZZ_FOLDER_NAME;
|
|
35
39
|
}
|
|
@@ -294,17 +298,43 @@ class Installer {
|
|
|
294
298
|
// failure — never inferred from path shape (updates and fresh-but-
|
|
295
299
|
// never-swapped both have `paths.isTmp === false` for different reasons).
|
|
296
300
|
let swapped = false;
|
|
301
|
+
// Populated by the "Installing hooks" task below; read inside configTask
|
|
302
|
+
// to build the settings.json entries once the copy has actually happened.
|
|
303
|
+
let installedHookFiles = [];
|
|
297
304
|
|
|
298
305
|
const installTasks = [];
|
|
299
306
|
|
|
300
|
-
installTasks.push(
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
307
|
+
installTasks.push(
|
|
308
|
+
{
|
|
309
|
+
title: 'Installing shared scripts',
|
|
310
|
+
task: async () => {
|
|
311
|
+
await this._installSharedScripts(paths);
|
|
312
|
+
addResult('Shared scripts', 'ok');
|
|
313
|
+
return 'Shared scripts installed';
|
|
314
|
+
},
|
|
306
315
|
},
|
|
307
|
-
|
|
316
|
+
// RT-C1: copia tools/hooks/* → _wizz/hooks/. Runs against
|
|
317
|
+
// `paths.wizzDir` (the A14 tmp scaffold on a fresh install) so it moves
|
|
318
|
+
// with the rest of the scaffold on the atomic swap below — same
|
|
319
|
+
// reasoning as shared scripts. The actual settings.json registration
|
|
320
|
+
// happens later, inside configTask, deferred until AFTER the swap
|
|
321
|
+
// (same treatment as .mcp.json): it lives outside `_wizz/`, so writing
|
|
322
|
+
// it before a fresh install fully succeeds would leave it mutated even
|
|
323
|
+
// if the install as a whole later fails. `installedHookFiles` (outer
|
|
324
|
+
// scope) carries the basenames actually copied over to that later step.
|
|
325
|
+
{
|
|
326
|
+
title: 'Installing hooks',
|
|
327
|
+
task: async () => {
|
|
328
|
+
installedHookFiles = await this._installHooks(paths);
|
|
329
|
+
const detail =
|
|
330
|
+
installedHookFiles.length > 0
|
|
331
|
+
? `${installedHookFiles.length} hook file(s) → _wizz/hooks/`
|
|
332
|
+
: 'nenhum hook encontrado em tools/hooks/';
|
|
333
|
+
addResult('Hooks', installedHookFiles.length > 0 ? 'ok' : 'warn', detail);
|
|
334
|
+
return detail;
|
|
335
|
+
},
|
|
336
|
+
},
|
|
337
|
+
);
|
|
308
338
|
|
|
309
339
|
if (allModules.length > 0) {
|
|
310
340
|
installTasks.push({
|
|
@@ -375,6 +405,30 @@ class Installer {
|
|
|
375
405
|
await this.generateModuleConfigs(paths.wizzDir, moduleConfigs);
|
|
376
406
|
addResult('Configurations', 'ok', 'generated');
|
|
377
407
|
|
|
408
|
+
// Audit item 19: snapshot every skill's resolved customization
|
|
409
|
+
// (base + team/user layers merged) into `_wizz/_resolved/`, so agent
|
|
410
|
+
// activation is a single file read instead of a Python spawn or a
|
|
411
|
+
// 3-layer TOML walk. Runs inside the tmp scaffold on a fresh install
|
|
412
|
+
// so the snapshots ride the A14 atomic swap; team/user layers are
|
|
413
|
+
// read from the REAL project's `_wizz/custom/` (user customizations
|
|
414
|
+
// survive a fresh install). Fail-open: a broken customize.toml
|
|
415
|
+
// warns and never blocks the install.
|
|
416
|
+
try {
|
|
417
|
+
const { generateResolvedCustomizations } = require('./resolved-customizations');
|
|
418
|
+
const resolvedCount = await generateResolvedCustomizations({
|
|
419
|
+
wizzDir: paths.wizzDir,
|
|
420
|
+
projectRoot: paths.projectRoot,
|
|
421
|
+
trackFile: (p) => this.installedFiles.add(p),
|
|
422
|
+
warn: async (msg) => await prompts.log.warn(msg),
|
|
423
|
+
});
|
|
424
|
+
if (resolvedCount > 0) {
|
|
425
|
+
addResult('Resolved customizations', 'ok', `${resolvedCount} snapshot(s) → _wizz/_resolved/`);
|
|
426
|
+
}
|
|
427
|
+
} catch (error) {
|
|
428
|
+
await prompts.log.warn(`Falha ao gerar _wizz/_resolved/ (fail-open): ${error.message}`);
|
|
429
|
+
addResult('Resolved customizations', 'warn', error.message);
|
|
430
|
+
}
|
|
431
|
+
|
|
378
432
|
this.installedFiles.add(paths.manifestFile());
|
|
379
433
|
this.installedFiles.add(paths.centralConfig());
|
|
380
434
|
this.installedFiles.add(paths.centralUserConfig());
|
|
@@ -612,6 +666,76 @@ class Installer {
|
|
|
612
666
|
);
|
|
613
667
|
}
|
|
614
668
|
|
|
669
|
+
// RT-C1 (item 3): registra os hooks copiados acima em
|
|
670
|
+
// `.claude/settings.json` do projeto — merge puro (hooks-settings.js),
|
|
671
|
+
// NUNCA em settings.local.json. `.claude/settings.json` vive fora de
|
|
672
|
+
// `_wizz/`, então — mesmo motivo do .mcp.json/pendingMcpWrite acima —
|
|
673
|
+
// a escrita real fica adiada para depois do swap A14 num fresh
|
|
674
|
+
// install (senão um install que falha depois daqui deixaria o
|
|
675
|
+
// settings.json mutado sem nenhum `_wizz/` correspondente).
|
|
676
|
+
let pendingHooksSettingsWrite = null;
|
|
677
|
+
try {
|
|
678
|
+
const rtkOnPath = this._isCommandOnPath('rtk');
|
|
679
|
+
const allHookEntries = buildHookEntries(installedHookFiles, { rtkOnPath });
|
|
680
|
+
|
|
681
|
+
// Decisão do dono (2026-09-11): pula qualquer hook nosso que já
|
|
682
|
+
// esteja registrado no settings.json GLOBAL do usuário
|
|
683
|
+
// (~/.claude/settings.json) — evita o mesmo hook rodar 2x (global +
|
|
684
|
+
// projeto) numa máquina onde o mantenedor já fez o registro global.
|
|
685
|
+
// JSON global inválido/ausente = `{}`, o que faz o filtro não
|
|
686
|
+
// remover nada (mesmo comportamento de "não sei, então registra").
|
|
687
|
+
const { settings: globalSettings } = await this._readSettingsJson(this._globalSettingsFile());
|
|
688
|
+
const { entries: hookEntries, skipped: skippedGlobalHooks } = filterHooksRegisteredGlobally(allHookEntries, globalSettings);
|
|
689
|
+
if (skippedGlobalHooks.length > 0) {
|
|
690
|
+
await prompts.log.info(
|
|
691
|
+
`Hook(s) já registrados no settings.json global (~/.claude/settings.json), pulando no projeto para não rodar 2x: ${skippedGlobalHooks.join(', ')}.`,
|
|
692
|
+
);
|
|
693
|
+
}
|
|
694
|
+
|
|
695
|
+
if (hookEntries.length > 0) {
|
|
696
|
+
const settingsFile = path.join(paths.projectRoot, '.claude', 'settings.json');
|
|
697
|
+
const { settings: existingSettings, invalidJson } = await this._readSettingsJson(settingsFile);
|
|
698
|
+
if (invalidJson) {
|
|
699
|
+
await prompts.log.warn(
|
|
700
|
+
`${settingsFile} existe mas não é JSON válido — hooks copiados para _wizz/hooks/, mas NÃO registrados em settings.json. Corrija o arquivo e rode o install de novo.`,
|
|
701
|
+
);
|
|
702
|
+
addResult('Hooks settings', 'warn', 'settings.json inválido, hooks não registrados');
|
|
703
|
+
} else {
|
|
704
|
+
const newSettings = mergeHooksIntoSettings(existingSettings, hookEntries);
|
|
705
|
+
pendingHooksSettingsWrite = {
|
|
706
|
+
file: settingsFile,
|
|
707
|
+
settings: newSettings,
|
|
708
|
+
count: hookEntries.length,
|
|
709
|
+
skipped: skippedGlobalHooks,
|
|
710
|
+
};
|
|
711
|
+
if (!paths.isTmp) {
|
|
712
|
+
// Update (or an install with no tmp scaffold): no swap will
|
|
713
|
+
// happen below, so write immediately.
|
|
714
|
+
await this._writeSettingsJson(settingsFile, newSettings);
|
|
715
|
+
const skippedDetail =
|
|
716
|
+
skippedGlobalHooks.length > 0 ? `, ${skippedGlobalHooks.length} pulado(s) por já estar no global` : '';
|
|
717
|
+
addResult('Hooks settings', 'ok', `${hookEntries.length} hook(s) → .claude/settings.json${skippedDetail}`);
|
|
718
|
+
pendingHooksSettingsWrite = null;
|
|
719
|
+
}
|
|
720
|
+
}
|
|
721
|
+
} else if (skippedGlobalHooks.length > 0) {
|
|
722
|
+
addResult(
|
|
723
|
+
'Hooks settings',
|
|
724
|
+
'ok',
|
|
725
|
+
`0 hook(s) → .claude/settings.json (${skippedGlobalHooks.length} pulado(s) por já estar no global)`,
|
|
726
|
+
);
|
|
727
|
+
}
|
|
728
|
+
if (!rtkOnPath && installedHookFiles.includes('rtk-rewrite.sh')) {
|
|
729
|
+
addResult('Hooks settings', 'warn', 'rtk não encontrado no PATH: rtk-rewrite.sh copiado mas não registrado (opcional)');
|
|
730
|
+
await prompts.log.info(
|
|
731
|
+
'rtk não encontrado no PATH: rtk-rewrite.sh foi copiado para _wizz/hooks/ mas NÃO registrado em settings.json (rtk é opcional). Instale rtk e rode o install de novo para ativá-lo.',
|
|
732
|
+
);
|
|
733
|
+
}
|
|
734
|
+
} catch (error) {
|
|
735
|
+
await prompts.log.warn(`Falha ao registrar hooks em .claude/settings.json: ${error.message}`);
|
|
736
|
+
addResult('Hooks settings', 'warn', error.message);
|
|
737
|
+
}
|
|
738
|
+
|
|
615
739
|
message('Generating manifests...');
|
|
616
740
|
const manifestGen = new ManifestGenerator();
|
|
617
741
|
const preservedModules = originalConfig._preserveModules || [];
|
|
@@ -673,6 +797,17 @@ class Installer {
|
|
|
673
797
|
});
|
|
674
798
|
}
|
|
675
799
|
|
|
800
|
+
// Perform the .claude/settings.json hooks write deferred above (RT-C1,
|
|
801
|
+
// item 3), same reasoning as the .mcp.json deferral right above.
|
|
802
|
+
if (pendingHooksSettingsWrite) {
|
|
803
|
+
await this._writeSettingsJson(pendingHooksSettingsWrite.file, pendingHooksSettingsWrite.settings);
|
|
804
|
+
const skippedDetail =
|
|
805
|
+
pendingHooksSettingsWrite.skipped.length > 0
|
|
806
|
+
? `, ${pendingHooksSettingsWrite.skipped.length} pulado(s) por já estar no global`
|
|
807
|
+
: '';
|
|
808
|
+
addResult('Hooks settings', 'ok', `${pendingHooksSettingsWrite.count} hook(s) → .claude/settings.json${skippedDetail}`);
|
|
809
|
+
}
|
|
810
|
+
|
|
676
811
|
await this._appendPreservedSkillManifestRows(paths.wizzDir, previousSkillManifestRows, preservedModules);
|
|
677
812
|
|
|
678
813
|
// Apply post-install --set TOML patches. Runs after writeCentralConfig
|
|
@@ -688,6 +823,25 @@ class Installer {
|
|
|
688
823
|
}
|
|
689
824
|
}
|
|
690
825
|
|
|
826
|
+
// Audit item 29: `_wizz/_resolved/_config.json`, the central config
|
|
827
|
+
// already merged across its four layers, so a skill reads one JSON
|
|
828
|
+
// instead of spawning `python3 resolve_config.py`. It has to run
|
|
829
|
+
// HERE, not with the skill snapshots above: on a fresh install those
|
|
830
|
+
// are generated inside the tmp scaffold, before writeCentralConfig
|
|
831
|
+
// wrote `_wizz/config.toml` at all — and before the `--set` patches
|
|
832
|
+
// just applied. Only the central-config half is redone; the skill
|
|
833
|
+
// snapshots and their index entries stay as they are. Fail-open: a
|
|
834
|
+
// miss here degrades to `wizz resolve`, never to a broken install.
|
|
835
|
+
try {
|
|
836
|
+
const { refreshResolvedConfig } = require('./resolved-config');
|
|
837
|
+
const centralConfig = await refreshResolvedConfig({ projectRoot: paths.projectRoot, wizzDir: paths.wizzDir });
|
|
838
|
+
for (const warning of centralConfig.warnings) {
|
|
839
|
+
await prompts.log.warn(`_resolved/_config.json: ${warning}`);
|
|
840
|
+
}
|
|
841
|
+
} catch (error) {
|
|
842
|
+
await prompts.log.warn(`Falha ao gerar _wizz/_resolved/_config.json (fail-open): ${error.message}`);
|
|
843
|
+
}
|
|
844
|
+
|
|
691
845
|
message('Generating help catalog...');
|
|
692
846
|
await this.mergeModuleHelpCatalogs(paths.wizzDir, manifestGen.agents);
|
|
693
847
|
addResult('Help catalog', 'ok');
|
|
@@ -930,8 +1084,10 @@ class Installer {
|
|
|
930
1084
|
* Excludes dev-only tests and Python caches so they don't ship to users.
|
|
931
1085
|
* Wipes the destination first so files removed or renamed in source
|
|
932
1086
|
* don't linger and get recorded as installed. Also seeds
|
|
933
|
-
* _wizz/custom/.gitignore
|
|
934
|
-
*
|
|
1087
|
+
* _wizz/custom/.gitignore (so *.user.toml overrides stay out of version
|
|
1088
|
+
* control) and _wizz/_config/.gitignore (so hash-cache.json, a local
|
|
1089
|
+
* perf cache with no reason to be committed, item 23/bug 13 fase3
|
|
1090
|
+
* review, stays out too).
|
|
935
1091
|
*/
|
|
936
1092
|
async _installSharedScripts(paths) {
|
|
937
1093
|
const srcScriptsDir = path.join(paths.srcDir, 'src', 'scripts');
|
|
@@ -954,6 +1110,133 @@ class Installer {
|
|
|
954
1110
|
await fs.writeFile(customGitignore, '*.user.toml\n', 'utf8');
|
|
955
1111
|
this.installedFiles.add(customGitignore);
|
|
956
1112
|
}
|
|
1113
|
+
|
|
1114
|
+
await this._seedGitignoreLine(paths.configDir, 'hash-cache.json');
|
|
1115
|
+
}
|
|
1116
|
+
|
|
1117
|
+
/**
|
|
1118
|
+
* Idempotently make sure a .gitignore in `dir` contains `line`, without
|
|
1119
|
+
* clobbering any user content already there (bug 13/item 23 gap, fase3
|
|
1120
|
+
* review 2026-09-11: hash-cache.json in _wizz/_config/ is committed by
|
|
1121
|
+
* default because that directory otherwise holds only tracked config).
|
|
1122
|
+
* Creates the file if absent; appends the line if the file exists but is
|
|
1123
|
+
* missing it; does nothing if the line is already present.
|
|
1124
|
+
* @param {string} dir - Directory whose .gitignore should list `line`
|
|
1125
|
+
* @param {string} line - Pattern to ensure is present
|
|
1126
|
+
*/
|
|
1127
|
+
async _seedGitignoreLine(dir, line) {
|
|
1128
|
+
const gitignorePath = path.join(dir, '.gitignore');
|
|
1129
|
+
if (!(await fs.pathExists(gitignorePath))) {
|
|
1130
|
+
await fs.writeFile(gitignorePath, `${line}\n`, 'utf8');
|
|
1131
|
+
this.installedFiles.add(gitignorePath);
|
|
1132
|
+
return;
|
|
1133
|
+
}
|
|
1134
|
+
const existing = await fs.readFile(gitignorePath, 'utf8');
|
|
1135
|
+
const hasLine = existing.split('\n').some((l) => l.trim() === line);
|
|
1136
|
+
if (!hasLine) {
|
|
1137
|
+
const withNewline = existing.endsWith('\n') ? existing : `${existing}\n`;
|
|
1138
|
+
await fs.writeFile(gitignorePath, `${withNewline}${line}\n`, 'utf8');
|
|
1139
|
+
this.installedFiles.add(gitignorePath);
|
|
1140
|
+
}
|
|
1141
|
+
}
|
|
1142
|
+
|
|
1143
|
+
/**
|
|
1144
|
+
* RT-C1 (auditoria 2026-09-11): sem isto, `tools/hooks/*` nunca chegava ao
|
|
1145
|
+
* usuário final do pacote publicado — só existiam na máquina do
|
|
1146
|
+
* mantenedor via `npm run sync:global`. Copia os 5 hooks de
|
|
1147
|
+
* `tools/hooks/` (fonte de verdade única — mesma lista que
|
|
1148
|
+
* `tools/sync-global.mjs` usa para `~/.claude/hooks/`, via
|
|
1149
|
+
* `tools/lib/sync-targets.mjs`, para as duas rotas nunca driftarem) para
|
|
1150
|
+
* `_wizz/hooks/` dentro do projeto alvo. Wipes o destino primeiro (mesmo
|
|
1151
|
+
* padrão de `_installSharedScripts`) e preserva o bit de execução do
|
|
1152
|
+
* `.sh` — ele é invocado direto por path em settings.json, não via
|
|
1153
|
+
* `bash file.sh`, então perder +x quebraria silenciosamente.
|
|
1154
|
+
* @param {import('./install-paths').InstallPaths} paths
|
|
1155
|
+
* @returns {Promise<string[]>} basenames copiados (vazio se a fonte não existir)
|
|
1156
|
+
*/
|
|
1157
|
+
async _installHooks(paths) {
|
|
1158
|
+
// tools/lib/sync-targets.mjs é ESM; installer.js é CJS — dynamic import
|
|
1159
|
+
// é o jeito padrão de consumir um módulo ESM de dentro de CJS no Node.
|
|
1160
|
+
const { hooksSrcDir, listHookFiles } = await import('../../lib/sync-targets.mjs');
|
|
1161
|
+
const srcDir = hooksSrcDir(paths.srcDir);
|
|
1162
|
+
const hookFiles = listHookFiles(paths.srcDir);
|
|
1163
|
+
if (hookFiles.length === 0) return [];
|
|
1164
|
+
|
|
1165
|
+
const destDir = path.join(paths.wizzDir, 'hooks');
|
|
1166
|
+
await fs.remove(destDir);
|
|
1167
|
+
await fs.ensureDir(destDir);
|
|
1168
|
+
for (const file of hookFiles) {
|
|
1169
|
+
const from = path.join(srcDir, file);
|
|
1170
|
+
const to = path.join(destDir, file);
|
|
1171
|
+
await fs.copyFile(from, to);
|
|
1172
|
+
const stat = await fs.stat(from);
|
|
1173
|
+
await fs.chmod(to, stat.mode);
|
|
1174
|
+
}
|
|
1175
|
+
await this._trackFilesRecursive(destDir);
|
|
1176
|
+
return hookFiles;
|
|
1177
|
+
}
|
|
1178
|
+
|
|
1179
|
+
/**
|
|
1180
|
+
* Detecção síncrona, sem subprocesso, de um binário no PATH — usada para o
|
|
1181
|
+
* gate "só registra rtk-rewrite.sh se rtk estiver instalado" (item 4,
|
|
1182
|
+
* RT-C1: rtk é opcional). Varre `process.env.PATH` procurando um arquivo
|
|
1183
|
+
* executável com esse nome, igual ao que `command -v` faria em shells
|
|
1184
|
+
* POSIX, mas sem pagar o custo/risco de um `exec`.
|
|
1185
|
+
* @param {string} cmd
|
|
1186
|
+
* @returns {boolean}
|
|
1187
|
+
*/
|
|
1188
|
+
_isCommandOnPath(cmd) {
|
|
1189
|
+
const pathEnv = process.env.PATH || process.env.Path || '';
|
|
1190
|
+
if (!pathEnv) return false;
|
|
1191
|
+
const dirs = pathEnv.split(path.delimiter).filter(Boolean);
|
|
1192
|
+
const exts = process.platform === 'win32' ? (process.env.PATHEXT || '.EXE;.CMD;.BAT;.COM').split(';') : [''];
|
|
1193
|
+
for (const dir of dirs) {
|
|
1194
|
+
for (const ext of exts) {
|
|
1195
|
+
try {
|
|
1196
|
+
fs.accessSync(path.join(dir, cmd + ext), fs.constants.X_OK);
|
|
1197
|
+
return true;
|
|
1198
|
+
} catch {
|
|
1199
|
+
// não está aqui — segue procurando
|
|
1200
|
+
}
|
|
1201
|
+
}
|
|
1202
|
+
}
|
|
1203
|
+
return false;
|
|
1204
|
+
}
|
|
1205
|
+
|
|
1206
|
+
/**
|
|
1207
|
+
* Path do settings.json GLOBAL do usuário, usado só para o gate "pula hook
|
|
1208
|
+
* já registrado globalmente" (decisão do dono, 2026-09-11). Mesmo padrão de
|
|
1209
|
+
* override que `WIZZ_GLOBAL_SKILLS_DIR` usa em `tools/hooks/wizz-router-
|
|
1210
|
+
* enforce.js`: a env var existe para os testes injetarem um arquivo
|
|
1211
|
+
* temporário em vez de tocar o `~/.claude/settings.json` real da máquina
|
|
1212
|
+
* rodando os testes.
|
|
1213
|
+
* @returns {string}
|
|
1214
|
+
*/
|
|
1215
|
+
_globalSettingsFile() {
|
|
1216
|
+
return process.env.WIZZ_GLOBAL_SETTINGS_FILE || path.join(os.homedir(), '.claude', 'settings.json');
|
|
1217
|
+
}
|
|
1218
|
+
|
|
1219
|
+
/**
|
|
1220
|
+
* Lê `.claude/settings.json` do projeto alvo. Arquivo ausente vira `{}`
|
|
1221
|
+
* (nada a preservar). JSON inválido nunca é sobrescrito — devolve
|
|
1222
|
+
* `invalidJson: true` para o chamador avisar e pular (item 3, RT-C1).
|
|
1223
|
+
* @param {string} file
|
|
1224
|
+
* @returns {Promise<{settings: object, invalidJson: boolean}>}
|
|
1225
|
+
*/
|
|
1226
|
+
async _readSettingsJson(file) {
|
|
1227
|
+
if (!(await fs.pathExists(file))) return { settings: {}, invalidJson: false };
|
|
1228
|
+
try {
|
|
1229
|
+
const raw = await fs.readFile(file, 'utf8');
|
|
1230
|
+
if (!raw.trim()) return { settings: {}, invalidJson: false };
|
|
1231
|
+
return { settings: JSON.parse(raw), invalidJson: false };
|
|
1232
|
+
} catch {
|
|
1233
|
+
return { settings: {}, invalidJson: true };
|
|
1234
|
+
}
|
|
1235
|
+
}
|
|
1236
|
+
|
|
1237
|
+
async _writeSettingsJson(file, settings) {
|
|
1238
|
+
await fs.ensureDir(path.dirname(file));
|
|
1239
|
+
await fs.writeJson(file, settings, { spaces: 2 });
|
|
957
1240
|
}
|
|
958
1241
|
|
|
959
1242
|
async _trackFilesRecursive(dir) {
|
|
@@ -1221,7 +1504,7 @@ class Installer {
|
|
|
1221
1504
|
` 2. Not sure what to do? Invoke the ${color.cyan('wizz-help')} skill and ask it what to do!`,
|
|
1222
1505
|
'',
|
|
1223
1506
|
` Docs and Guides: ${color.blue('https://method.wizzcomms.com/')}`,
|
|
1224
|
-
`
|
|
1507
|
+
` Support: ${color.blue('support@wizzcomms.com')}`,
|
|
1225
1508
|
);
|
|
1226
1509
|
|
|
1227
1510
|
await prompts.box(lines.join('\n'), 'Wizz Method is ready to use!', {
|
|
@@ -1417,8 +1700,7 @@ class Installer {
|
|
|
1417
1700
|
* @returns {Promise<Object>} { wizzDir: string }
|
|
1418
1701
|
*/
|
|
1419
1702
|
async findWizzDir(projectDir) {
|
|
1420
|
-
|
|
1421
|
-
return { wizzDir };
|
|
1703
|
+
return findWizzDir(projectDir);
|
|
1422
1704
|
}
|
|
1423
1705
|
|
|
1424
1706
|
/**
|
|
@@ -1495,4 +1777,4 @@ class Installer {
|
|
|
1495
1777
|
}
|
|
1496
1778
|
}
|
|
1497
1779
|
|
|
1498
|
-
module.exports = { Installer };
|
|
1780
|
+
module.exports = { Installer, findWizzDir };
|
|
@@ -1,13 +1,20 @@
|
|
|
1
1
|
const path = require('node:path');
|
|
2
2
|
const fs = require('../fs-native');
|
|
3
3
|
const yaml = require('yaml');
|
|
4
|
-
const crypto = require('node:crypto');
|
|
5
4
|
const { resolveInstalledModuleYaml } = require('../project-root');
|
|
6
5
|
const prompts = require('../prompts');
|
|
7
6
|
|
|
8
7
|
// Load package.json for version info
|
|
9
8
|
const packageJson = require('../../../package.json');
|
|
10
9
|
|
|
10
|
+
// Concurrency cap for the files-manifest hashing pass (F05 in the
|
|
11
|
+
// 2026-09-11 audit): hundreds/thousands of installed files hashed one at a
|
|
12
|
+
// time was the dominant cost of "Generating manifests" on large trees
|
|
13
|
+
// (e.g. src/skills-lib/). Batched via fs.batchMap, which also memoizes
|
|
14
|
+
// (path+size+mtime) so a file already hashed elsewhere in this same process
|
|
15
|
+
// (e.g. user-file-preservation's "before" pass, F10) isn't re-read.
|
|
16
|
+
const HASH_BATCH_SIZE = 32;
|
|
17
|
+
|
|
11
18
|
/**
|
|
12
19
|
* Generates manifest files for installed skills and agents
|
|
13
20
|
*/
|
|
@@ -345,6 +352,14 @@ class ManifestGenerator {
|
|
|
345
352
|
|
|
346
353
|
// Fetch fresh version info for all modules
|
|
347
354
|
const { Manifest } = require('./manifest');
|
|
355
|
+
// Item 8 fase 2 (auditoria 2026-09-11, EXT-02 / IM-ACH-06): the SHA the
|
|
356
|
+
// user requested via `--pin CODE=TAG@SHA` isn't part of
|
|
357
|
+
// Manifest#getModuleVersionInfo's return shape (that lives in
|
|
358
|
+
// manifest.js, out of scope for this change) — read it straight from
|
|
359
|
+
// ExternalModuleManager's in-process resolution cache instead, the same
|
|
360
|
+
// source getModuleVersionInfo itself reads `sha`/`channel` from.
|
|
361
|
+
const { ExternalModuleManager } = require('../modules/external-manager');
|
|
362
|
+
const externalModuleManager = new ExternalModuleManager();
|
|
348
363
|
const manifestObj = new Manifest();
|
|
349
364
|
const updatedModules = [];
|
|
350
365
|
|
|
@@ -370,6 +385,12 @@ class ManifestGenerator {
|
|
|
370
385
|
const sha = versionInfo.sha ?? existing?.sha;
|
|
371
386
|
if (channel) moduleEntry.channel = channel;
|
|
372
387
|
if (sha) moduleEntry.sha = sha;
|
|
388
|
+
// shaRequested: the SHA half of a `--pin CODE=TAG@SHA`, when the user
|
|
389
|
+
// supplied one. Absent for modules pinned by tag alone (or not pinned
|
|
390
|
+
// at all) — never written in that case, so older manifests without
|
|
391
|
+
// this field stay valid and round-trip unchanged.
|
|
392
|
+
const shaRequested = externalModuleManager.getResolution(moduleName)?.expectedSha ?? existing?.shaRequested;
|
|
393
|
+
if (shaRequested) moduleEntry.shaRequested = shaRequested;
|
|
373
394
|
if (versionInfo.localPath || existing?.localPath) {
|
|
374
395
|
moduleEntry.localPath = versionInfo.localPath || existing.localPath;
|
|
375
396
|
}
|
|
@@ -677,17 +698,17 @@ class ManifestGenerator {
|
|
|
677
698
|
* Write files manifest CSV
|
|
678
699
|
*/
|
|
679
700
|
/**
|
|
680
|
-
* Calculate SHA256 hash of a file
|
|
701
|
+
* Calculate SHA256 hash of a file. Delegates to the single canonical
|
|
702
|
+
* implementation in fs-native.js (memoized by path+size+mtime within the
|
|
703
|
+
* same process) — see F06/F10 in the 2026-09-11 audit. This wrapper keeps
|
|
704
|
+
* this class's historical contract of resolving to '' (not null) when the
|
|
705
|
+
* file can't be read, since that's the value written into files-manifest.csv.
|
|
681
706
|
* @param {string} filePath - Path to file
|
|
682
|
-
* @returns {string} SHA256 hash
|
|
707
|
+
* @returns {string} SHA256 hash, or '' if the file can't be read
|
|
683
708
|
*/
|
|
684
709
|
async calculateFileHash(filePath) {
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
return crypto.createHash('sha256').update(content).digest('hex');
|
|
688
|
-
} catch {
|
|
689
|
-
return '';
|
|
690
|
-
}
|
|
710
|
+
const hash = await fs.calculateFileHash(filePath);
|
|
711
|
+
return hash ?? '';
|
|
691
712
|
}
|
|
692
713
|
|
|
693
714
|
/**
|
|
@@ -696,49 +717,106 @@ class ManifestGenerator {
|
|
|
696
717
|
async writeFilesManifest(cfgDir) {
|
|
697
718
|
const csvPath = path.join(cfgDir, 'files-manifest.csv');
|
|
698
719
|
|
|
720
|
+
// Incremental hashing (audit item 23): load the previous run's
|
|
721
|
+
// size+mtime → hash cache; files whose stat matches skip the read+hash
|
|
722
|
+
// entirely. Fail-open: missing/corrupt cache = cold start.
|
|
723
|
+
const { loadHashCache, getCachedHash, buildHashCache, saveHashCache } = require('./hash-cache');
|
|
724
|
+
const previousCache = await loadHashCache(cfgDir);
|
|
725
|
+
const freshHashes = [];
|
|
726
|
+
|
|
699
727
|
// Create CSV header with hash column
|
|
700
728
|
let csv = 'type,name,module,path,hash\n';
|
|
701
729
|
|
|
702
730
|
// If we have ALL installed files, use those instead of just workflows/agents/tasks
|
|
703
|
-
|
|
731
|
+
// Hashing every installed file is I/O-bound and independent per file, so
|
|
732
|
+
// batch it with bounded concurrency (F05) instead of one file at a time.
|
|
733
|
+
// The final list is sorted below regardless of resolution order, so the
|
|
734
|
+
// written CSV stays byte-for-byte identical to the sequential version.
|
|
735
|
+
let allFiles;
|
|
704
736
|
if (this.allInstalledFiles && this.allInstalledFiles.length > 0) {
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
737
|
+
allFiles = await fs.batchMap(
|
|
738
|
+
[...this.allInstalledFiles],
|
|
739
|
+
async (filePath) => {
|
|
740
|
+
// Store paths relative to wizzDir (no folder prefix)
|
|
741
|
+
const relativePath = filePath.replace(this.wizzDir, '').replaceAll('\\', '/').replace(/^\//, '');
|
|
742
|
+
const ext = path.extname(filePath).toLowerCase();
|
|
743
|
+
const fileName = path.basename(filePath, ext);
|
|
744
|
+
|
|
745
|
+
// Determine module from path (first directory component)
|
|
746
|
+
const pathParts = relativePath.split('/');
|
|
747
|
+
const module = pathParts.length > 0 ? pathParts[0] : 'unknown';
|
|
748
|
+
|
|
749
|
+
// Incremental (item 23): reuse the cached hash when size+mtime
|
|
750
|
+
// match the previous run, else hash and record the new stat.
|
|
751
|
+
let hash = null;
|
|
752
|
+
try {
|
|
753
|
+
const stat = await fs.stat(filePath);
|
|
754
|
+
hash = getCachedHash(previousCache, relativePath, stat);
|
|
755
|
+
if (hash === null) {
|
|
756
|
+
hash = await this.calculateFileHash(filePath);
|
|
757
|
+
if (hash)
|
|
758
|
+
freshHashes.push({
|
|
759
|
+
relPath: relativePath,
|
|
760
|
+
size: stat.size,
|
|
761
|
+
mtimeMs: stat.mtimeMs,
|
|
762
|
+
ctimeMs: stat.ctimeMs,
|
|
763
|
+
hash,
|
|
764
|
+
});
|
|
765
|
+
}
|
|
766
|
+
} catch {
|
|
767
|
+
hash = await this.calculateFileHash(filePath);
|
|
768
|
+
}
|
|
769
|
+
|
|
770
|
+
return {
|
|
771
|
+
type: ext.slice(1) || 'file',
|
|
772
|
+
name: fileName,
|
|
773
|
+
module: module,
|
|
774
|
+
path: relativePath,
|
|
775
|
+
hash: hash,
|
|
776
|
+
};
|
|
777
|
+
},
|
|
778
|
+
HASH_BATCH_SIZE,
|
|
779
|
+
);
|
|
727
780
|
} else {
|
|
728
781
|
// Fallback: use the collected workflows/agents/tasks
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
hash
|
|
738
|
-
|
|
739
|
-
|
|
782
|
+
allFiles = await fs.batchMap(
|
|
783
|
+
this.files,
|
|
784
|
+
async (file) => {
|
|
785
|
+
// Strip the folder prefix if present (for consistency)
|
|
786
|
+
const relPath = file.path.replace(this.wizzFolderName + '/', '');
|
|
787
|
+
const filePath = path.join(this.wizzDir, relPath);
|
|
788
|
+
|
|
789
|
+
// Incremental (item 23): same cache shortcut as the full path above.
|
|
790
|
+
let hash = null;
|
|
791
|
+
try {
|
|
792
|
+
const stat = await fs.stat(filePath);
|
|
793
|
+
hash = getCachedHash(previousCache, relPath, stat);
|
|
794
|
+
if (hash === null) {
|
|
795
|
+
hash = await this.calculateFileHash(filePath);
|
|
796
|
+
if (hash) freshHashes.push({ relPath, size: stat.size, mtimeMs: stat.mtimeMs, ctimeMs: stat.ctimeMs, hash });
|
|
797
|
+
}
|
|
798
|
+
} catch {
|
|
799
|
+
hash = await this.calculateFileHash(filePath);
|
|
800
|
+
}
|
|
801
|
+
return {
|
|
802
|
+
...file,
|
|
803
|
+
path: relPath,
|
|
804
|
+
hash: hash,
|
|
805
|
+
};
|
|
806
|
+
},
|
|
807
|
+
HASH_BATCH_SIZE,
|
|
808
|
+
);
|
|
740
809
|
}
|
|
741
810
|
|
|
811
|
+
// Persist the cache next to the CSV (best-effort), pruned to exactly the
|
|
812
|
+
// paths this run wrote — a file dropped from the install (removed
|
|
813
|
+
// module, rename) drops out of the cache too instead of lingering.
|
|
814
|
+
// Fresh installs (A14) call this while wizzDir is still the tmp
|
|
815
|
+
// scaffold, so the cache lands inside the scaffold and is renamed into
|
|
816
|
+
// place with the swap — the next update starts warm.
|
|
817
|
+
const currentPaths = allFiles.map((file) => file.path);
|
|
818
|
+
await saveHashCache(cfgDir, buildHashCache(previousCache, freshHashes, currentPaths));
|
|
819
|
+
|
|
742
820
|
// Sort files by module, then type, then name
|
|
743
821
|
allFiles.sort((a, b) => {
|
|
744
822
|
if (a.module !== b.module) return a.module.localeCompare(b.module);
|