wizz-method 2.0.0 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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 +62 -37
- 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/install.js +1 -1
- package/tools/installer/commands/resolve.js +95 -0
- package/tools/installer/core/doctor.js +648 -0
- package/tools/installer/core/hash-cache.js +156 -0
- package/tools/installer/core/help-catalog.js +4 -1
- package/tools/installer/core/hooks-settings.js +178 -0
- package/tools/installer/core/installer.js +297 -15
- package/tools/installer/core/legacy-warnings.js +0 -4
- package/tools/installer/core/manifest-generator.js +121 -43
- package/tools/installer/core/manifest.js +36 -32
- package/tools/installer/core/module-config-writer.js +4 -1
- package/tools/installer/core/python-check.js +60 -63
- package/tools/installer/core/quick-update.js +76 -43
- package/tools/installer/core/resolved-config.js +168 -0
- package/tools/installer/core/resolved-customizations.js +736 -0
- package/tools/installer/core/resolved-includes.js +262 -0
- package/tools/installer/core/resolved-schema.js +148 -0
- package/tools/installer/core/user-file-preservation.js +40 -8
- package/tools/installer/core/wizz-dir.js +117 -0
- package/tools/installer/core/yaml-cache.js +105 -0
- package/tools/installer/fs-native.js +97 -6
- package/tools/installer/ide/_config-driven.js +12 -75
- package/tools/installer/ide/platform-codes.js +111 -16
- package/tools/installer/ide/platform-codes.yaml +45 -100
- package/tools/installer/ide/shared/path-utils.js +6 -208
- package/tools/installer/install-messages.yaml +4 -14
- package/tools/installer/modules/channel-plan.js +15 -2
- package/tools/installer/modules/config-collector.js +762 -0
- package/tools/installer/modules/config-values.js +352 -0
- package/tools/installer/modules/custom-module-manager.js +161 -28
- package/tools/installer/modules/env-vars.js +119 -0
- package/tools/installer/modules/external-manager.js +133 -60
- package/tools/installer/modules/git-cache-utils.js +125 -0
- package/tools/installer/modules/module-catalog.js +565 -0
- package/tools/installer/modules/module-installer.js +618 -0
- package/tools/installer/modules/module-interface.js +86 -0
- package/tools/installer/modules/official-modules.js +98 -2172
- package/tools/installer/modules/pin-spec.js +125 -0
- package/tools/installer/modules/plugin-resolver.js +4 -0
- package/tools/installer/modules/skills-lib.js +3 -6
- package/tools/installer/prompts.js +0 -3
- package/tools/installer/ui.js +89 -54
- package/tools/installer/wizz-cli.js +1 -1
- package/tools/lib/frontmatter.js +139 -0
- package/tools/lib/sync-targets.mjs +49 -0
- package/tools/lib/walk.js +93 -0
- package/wizz-modules.yaml +9 -0
- package/src/scripts/__pycache__/memlog.cpython-313.pyc +0 -0
- package/src/scripts/memlog.py +0 -233
- package/src/scripts/tests/__pycache__/test_memlog.cpython-313-pytest-9.1.1.pyc +0 -0
- package/src/scripts/tests/__pycache__/test_resolve_customization.cpython-313-pytest-9.1.1.pyc +0 -0
- package/src/scripts/tests/test_memlog.py +0 -306
- package/src/skills-lib/wizz-huashu-design/assets/showcases/INDEX.md +0 -115
- package/src/skills-lib/wizz-huashu-design/assets/showcases/cover/cover-build.html +0 -235
- package/src/skills-lib/wizz-huashu-design/assets/showcases/cover/cover-build.png +0 -0
- package/src/skills-lib/wizz-huashu-design/assets/showcases/cover/cover-pentagram.html +0 -229
- package/src/skills-lib/wizz-huashu-design/assets/showcases/cover/cover-pentagram.png +0 -0
- package/src/skills-lib/wizz-huashu-design/assets/showcases/cover/cover-takram.html +0 -288
- package/src/skills-lib/wizz-huashu-design/assets/showcases/cover/cover-takram.png +0 -0
- package/src/skills-lib/wizz-huashu-design/assets/showcases/infographic/infographic-build.html +0 -503
- package/src/skills-lib/wizz-huashu-design/assets/showcases/infographic/infographic-build.png +0 -0
- package/src/skills-lib/wizz-huashu-design/assets/showcases/infographic/infographic-pentagram.html +0 -600
- package/src/skills-lib/wizz-huashu-design/assets/showcases/infographic/infographic-pentagram.png +0 -0
- package/src/skills-lib/wizz-huashu-design/assets/showcases/infographic/infographic-takram.html +0 -670
- package/src/skills-lib/wizz-huashu-design/assets/showcases/infographic/infographic-takram.png +0 -0
- package/src/skills-lib/wizz-huashu-design/assets/showcases/ppt/ppt-build.html +0 -382
- package/src/skills-lib/wizz-huashu-design/assets/showcases/ppt/ppt-build.png +0 -0
- package/src/skills-lib/wizz-huashu-design/assets/showcases/ppt/ppt-pentagram.html +0 -536
- package/src/skills-lib/wizz-huashu-design/assets/showcases/ppt/ppt-pentagram.png +0 -0
- package/src/skills-lib/wizz-huashu-design/assets/showcases/ppt/ppt-takram.html +0 -497
- package/src/skills-lib/wizz-huashu-design/assets/showcases/ppt/ppt-takram.png +0 -0
- package/src/skills-lib/wizz-huashu-design/assets/showcases/website-ai-nav/ainav-build.html +0 -385
- package/src/skills-lib/wizz-huashu-design/assets/showcases/website-ai-nav/ainav-build.png +0 -0
- package/src/skills-lib/wizz-huashu-design/assets/showcases/website-ai-nav/ainav-pentagram.html +0 -422
- package/src/skills-lib/wizz-huashu-design/assets/showcases/website-ai-nav/ainav-pentagram.png +0 -0
- package/src/skills-lib/wizz-huashu-design/assets/showcases/website-ai-nav/ainav-takram.html +0 -499
- package/src/skills-lib/wizz-huashu-design/assets/showcases/website-ai-nav/ainav-takram.png +0 -0
- package/src/skills-lib/wizz-huashu-design/assets/showcases/website-ai-writing/aiwriting-build.html +0 -562
- package/src/skills-lib/wizz-huashu-design/assets/showcases/website-ai-writing/aiwriting-build.png +0 -0
- package/src/skills-lib/wizz-huashu-design/assets/showcases/website-ai-writing/aiwriting-pentagram.html +0 -548
- package/src/skills-lib/wizz-huashu-design/assets/showcases/website-ai-writing/aiwriting-pentagram.png +0 -0
- package/src/skills-lib/wizz-huashu-design/assets/showcases/website-ai-writing/aiwriting-takram.html +0 -696
- package/src/skills-lib/wizz-huashu-design/assets/showcases/website-ai-writing/aiwriting-takram.png +0 -0
- package/src/skills-lib/wizz-huashu-design/assets/showcases/website-devdocs/devdocs-build.html +0 -372
- package/src/skills-lib/wizz-huashu-design/assets/showcases/website-devdocs/devdocs-build.png +0 -0
- package/src/skills-lib/wizz-huashu-design/assets/showcases/website-devdocs/devdocs-pentagram.html +0 -460
- package/src/skills-lib/wizz-huashu-design/assets/showcases/website-devdocs/devdocs-pentagram.png +0 -0
- package/src/skills-lib/wizz-huashu-design/assets/showcases/website-devdocs/devdocs-takram.html +0 -494
- package/src/skills-lib/wizz-huashu-design/assets/showcases/website-devdocs/devdocs-takram.png +0 -0
- package/src/skills-lib/wizz-huashu-design/assets/showcases/website-homepage/homepage-build.html +0 -367
- package/src/skills-lib/wizz-huashu-design/assets/showcases/website-homepage/homepage-build.png +0 -0
- package/src/skills-lib/wizz-huashu-design/assets/showcases/website-homepage/homepage-pentagram.html +0 -368
- package/src/skills-lib/wizz-huashu-design/assets/showcases/website-homepage/homepage-pentagram.png +0 -0
- package/src/skills-lib/wizz-huashu-design/assets/showcases/website-homepage/homepage-takram.html +0 -459
- package/src/skills-lib/wizz-huashu-design/assets/showcases/website-homepage/homepage-takram.png +0 -0
- package/src/skills-lib/wizz-huashu-design/assets/showcases/website-saas/saas-build.html +0 -493
- package/src/skills-lib/wizz-huashu-design/assets/showcases/website-saas/saas-build.png +0 -0
- package/src/skills-lib/wizz-huashu-design/assets/showcases/website-saas/saas-pentagram.html +0 -556
- package/src/skills-lib/wizz-huashu-design/assets/showcases/website-saas/saas-pentagram.png +0 -0
- package/src/skills-lib/wizz-huashu-design/assets/showcases/website-saas/saas-takram.html +0 -604
- package/src/skills-lib/wizz-huashu-design/assets/showcases/website-saas/saas-takram.png +0 -0
- package/tools/installer/file-ops.js +0 -204
- package/tools/installer/ide/shared/skill-manifest.js +0 -57
- package/tools/installer/yaml-format.js +0 -245
- package/web-bundles/README.md +0 -46
- package/web-bundles/brainstorming-coach/INSTRUCTIONS.md +0 -86
- package/web-bundles/brainstorming-coach/SKILL.md +0 -83
- package/web-bundles/brainstorming-coach/brain-methods.csv +0 -62
- package/web-bundles/bundles.json +0 -139
- package/web-bundles/market-and-industry-research/INSTRUCTIONS.md +0 -88
- package/web-bundles/market-and-industry-research/SKILL.md +0 -59
- package/web-bundles/prd-coach/INSTRUCTIONS.md +0 -86
- package/web-bundles/prd-coach/SKILL.md +0 -101
- package/web-bundles/prd-coach/prd-template.md +0 -165
- package/web-bundles/prd-coach/prd-validation-checklist.md +0 -135
- package/web-bundles/prfaq-coach/INSTRUCTIONS.md +0 -86
- package/web-bundles/prfaq-coach/SKILL.md +0 -139
- package/web-bundles/product-brief-coach/INSTRUCTIONS.md +0 -86
- package/web-bundles/product-brief-coach/SKILL.md +0 -113
- package/web-bundles/ux-coach/INSTRUCTIONS.md +0 -92
- package/web-bundles/ux-coach/SKILL.md +0 -187
- package/web-bundles/ux-coach/ux-validation.md +0 -100
- /package/src/modules/lowticket/skills/{lowticket-funil → wizz-lowticket-funil}/references/mapa-do-funil.md +0 -0
- /package/src/modules/lowticket/skills/{lowticket-metodologia → wizz-lowticket-metodologia}/CATALOGO.md +0 -0
- /package/src/modules/lowticket/skills/{lowticket-metodologia → wizz-lowticket-metodologia}/knowledge/01-principios.md +0 -0
- /package/src/modules/lowticket/skills/{lowticket-metodologia → wizz-lowticket-metodologia}/knowledge/02-diagnostico-funil.md +0 -0
- /package/src/modules/lowticket/skills/{lowticket-metodologia → wizz-lowticket-metodologia}/knowledge/03-campanha-bidcap.md +0 -0
- /package/src/modules/lowticket/skills/{lowticket-metodologia → wizz-lowticket-metodologia}/knowledge/04-criativos.md +0 -0
- /package/src/modules/lowticket/skills/{lowticket-metodologia → wizz-lowticket-metodologia}/knowledge/04a-criativos-ia.md +0 -0
- /package/src/modules/lowticket/skills/{lowticket-metodologia → wizz-lowticket-metodologia}/knowledge/04b-criativos-formatos.md +0 -0
- /package/src/modules/lowticket/skills/{lowticket-metodologia → wizz-lowticket-metodologia}/knowledge/05-oferta.md +0 -0
- /package/src/modules/lowticket/skills/{lowticket-metodologia → wizz-lowticket-metodologia}/knowledge/06-pagina-vendas.md +0 -0
- /package/src/modules/lowticket/skills/{lowticket-metodologia → wizz-lowticket-metodologia}/knowledge/06a-instagram.md +0 -0
- /package/src/modules/lowticket/skills/{lowticket-metodologia → wizz-lowticket-metodologia}/knowledge/06b-player-vsl.md +0 -0
- /package/src/modules/lowticket/skills/{lowticket-metodologia → wizz-lowticket-metodologia}/knowledge/07-funil-upsell.md +0 -0
- /package/src/modules/lowticket/skills/{lowticket-metodologia → wizz-lowticket-metodologia}/knowledge/07a-copy-humanizacao.md +0 -0
- /package/src/modules/lowticket/skills/{lowticket-metodologia → wizz-lowticket-metodologia}/knowledge/08-pesquisa-publico.md +0 -0
- /package/src/modules/lowticket/skills/{lowticket-metodologia → wizz-lowticket-metodologia}/knowledge/09-especialista-coproducao.md +0 -0
- /package/src/modules/lowticket/skills/{lowticket-metodologia → wizz-lowticket-metodologia}/knowledge/10-levantar-caixa.md +0 -0
- /package/src/modules/lowticket/skills/{lowticket-metodologia → wizz-lowticket-metodologia}/knowledge/11-checklist-roi.md +0 -0
- /package/src/modules/lowticket/skills/{lowticket-metodologia → wizz-lowticket-metodologia}/knowledge/12-mineracao-ofertas.md +0 -0
- /package/src/modules/lowticket/skills/{lowticket-metodologia → wizz-lowticket-metodologia}/knowledge/12a-mineracao-veredito.md +0 -0
- /package/src/modules/lowticket/skills/{lowticket-metodologia → wizz-lowticket-metodologia}/knowledge/12b-fabrica-de-ofertas.md +0 -0
- /package/src/modules/lowticket/skills/{lowticket-metodologia → wizz-lowticket-metodologia}/knowledge/12c-anatomia-low-ticket.md +0 -0
- /package/src/modules/lowticket/skills/{lowticket-metodologia → wizz-lowticket-metodologia}/knowledge/13-benchmarks-vsl.md +0 -0
- /package/src/modules/lowticket/skills/{lowticket-metodologia → wizz-lowticket-metodologia}/knowledge/14-vocabulario.md +0 -0
- /package/src/modules/lowticket/skills/{lowticket-metodologia → wizz-lowticket-metodologia}/knowledge/15-como-estender.md +0 -0
- /package/src/modules/lowticket/skills/{lowticket-metodologia → wizz-lowticket-metodologia}/knowledge/17-rastreamento.md +0 -0
- /package/src/modules/lowticket/skills/{lowticket-metodologia → wizz-lowticket-metodologia}/knowledge/18-copy-desejo-oferta.md +0 -0
- /package/src/modules/lowticket/skills/{lowticket-metodologia → wizz-lowticket-metodologia}/knowledge/INDEX.md +0 -0
- /package/src/modules/lowticket/skills/{lowticket-metodologia → wizz-lowticket-metodologia}/knowledge/guardrails.md +0 -0
- /package/src/modules/lowticket/skills/{lowticket-metodologia → wizz-lowticket-metodologia}/knowledge/pontos-em-aberto.md +0 -0
- /package/src/modules/lowticket/skills/{lowticket-metodologia → wizz-lowticket-metodologia}/references/swipe-file.md +0 -0
- /package/src/modules/lowticket/skills/{lowticket-pagina → wizz-lowticket-pagina}/references/metas-e-medicao.md +0 -0
- /package/src/modules/lowticket/skills/{lowticket-pagina → wizz-lowticket-pagina}/references/padroes-de-codigo.md +0 -0
- /package/src/modules/lowticket/skills/{lowticket-trafego → wizz-lowticket-trafego}/references/formato-do-diagnostico.md +0 -0
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Persistent hash cache (audit item 23, 2026-09-11; hardened 2026-09-11
|
|
3
|
+
* fase 3 review — bug 13 + the item 23 gaps: version field, ctime in the
|
|
4
|
+
* key, and actual pruning).
|
|
5
|
+
*
|
|
6
|
+
* The files-manifest.csv hashing pass is I/O-bound: every installed file is
|
|
7
|
+
* read and SHA256-hashed on every install/update, even though almost all of
|
|
8
|
+
* them are unchanged between runs. The in-process memo in fs-native.js
|
|
9
|
+
* (path:size:mtimeMs) only helps within one run; this module persists the
|
|
10
|
+
* mapping across runs so the next update hashes only the delta.
|
|
11
|
+
*
|
|
12
|
+
* Format: `_wizz/_config/hash-cache.json` is
|
|
13
|
+
* `{ "_v": 1, "algo": "sha256", "files": { relPath: { size, mtimeMs, ctimeMs, hash } } }`.
|
|
14
|
+
* A hit requires size AND mtimeMs AND ctimeMs to all match the current
|
|
15
|
+
* stat — ctime can't be set by a user-level copy (only the kernel bumps it,
|
|
16
|
+
* on a metadata or content change), so a `cp -p` or `rsync --times` that
|
|
17
|
+
* preserves mtime alone still forces a miss, because writing to a new
|
|
18
|
+
* inode necessarily bumps ctime. size+mtime alone would have missed
|
|
19
|
+
* exactly that case (a file copied over the installed one, same mtime,
|
|
20
|
+
* different content).
|
|
21
|
+
*
|
|
22
|
+
* Any mismatch on `_v` or `algo`, or a malformed/non-object JSON payload,
|
|
23
|
+
* is treated as a cold start (empty cache) — never a hard error. This also
|
|
24
|
+
* covers a future format change: bumping `_v` invalidates every existing
|
|
25
|
+
* cache file instead of trying to read the old shape.
|
|
26
|
+
*
|
|
27
|
+
* Known limitation: two edits to the same file within the same filesystem
|
|
28
|
+
* timestamp granularity (1s on some filesystems/platforms) that happen to
|
|
29
|
+
* land on the same size can still collide (same size+mtimeMs+ctimeMs,
|
|
30
|
+
* different content) and be reported as unchanged — this is the same trust
|
|
31
|
+
* level files-manifest.csv already accepts elsewhere (mtime as a proxy for
|
|
32
|
+
* content). `wizz doctor` rehashes every file without consulting this
|
|
33
|
+
* cache, so it remains the way to force a full, cache-free verification.
|
|
34
|
+
*
|
|
35
|
+
* Fail-open by design: a missing, corrupt, or stale (wrong `_v`/`algo`)
|
|
36
|
+
* cache is a cache miss, never an error — the file just gets hashed the
|
|
37
|
+
* old way. User-modified files are the caller's concern: the cache stores
|
|
38
|
+
* what the file looked like at last install, so a drifted file's NEW stat
|
|
39
|
+
* mismatches the cache and forces a fresh hash (its cached entry is then
|
|
40
|
+
* refreshed by the writer, which is correct — the manifest must record the
|
|
41
|
+
* current hash).
|
|
42
|
+
*/
|
|
43
|
+
const path = require('node:path');
|
|
44
|
+
const fs = require('../fs-native');
|
|
45
|
+
|
|
46
|
+
const CACHE_FILE = 'hash-cache.json';
|
|
47
|
+
const CACHE_VERSION = 1;
|
|
48
|
+
const CACHE_ALGO = 'sha256';
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Load the previous run's cache. Returns an empty Map on any failure
|
|
52
|
+
* (missing file, corrupt JSON, wrong shape, version/algo mismatch) —
|
|
53
|
+
* fail-open.
|
|
54
|
+
* @param {string} cfgDir - _wizz/_config directory
|
|
55
|
+
* @returns {Promise<Map<string, {size: number, mtimeMs: number, ctimeMs: number, hash: string}>>}
|
|
56
|
+
*/
|
|
57
|
+
async function loadHashCache(cfgDir) {
|
|
58
|
+
const map = new Map();
|
|
59
|
+
try {
|
|
60
|
+
const raw = await fs.readFile(path.join(cfgDir, CACHE_FILE), 'utf8');
|
|
61
|
+
const parsed = JSON.parse(raw);
|
|
62
|
+
if (
|
|
63
|
+
parsed &&
|
|
64
|
+
typeof parsed === 'object' &&
|
|
65
|
+
parsed._v === CACHE_VERSION &&
|
|
66
|
+
parsed.algo === CACHE_ALGO &&
|
|
67
|
+
parsed.files &&
|
|
68
|
+
typeof parsed.files === 'object'
|
|
69
|
+
) {
|
|
70
|
+
for (const [relPath, entry] of Object.entries(parsed.files)) {
|
|
71
|
+
if (
|
|
72
|
+
entry &&
|
|
73
|
+
typeof entry === 'object' &&
|
|
74
|
+
typeof entry.size === 'number' &&
|
|
75
|
+
typeof entry.mtimeMs === 'number' &&
|
|
76
|
+
typeof entry.ctimeMs === 'number' &&
|
|
77
|
+
typeof entry.hash === 'string'
|
|
78
|
+
) {
|
|
79
|
+
map.set(relPath, entry);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
} catch {
|
|
84
|
+
// Missing, corrupt, or wrong-version cache = cold start. Never fatal.
|
|
85
|
+
}
|
|
86
|
+
return map;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Look up a file's cached hash. Only hits when size AND mtimeMs AND
|
|
91
|
+
* ctimeMs all match the current stat — a partial match must be treated as
|
|
92
|
+
* a miss because any of the three could be the only signal that content
|
|
93
|
+
* changed (see the ctime rationale in the module header).
|
|
94
|
+
* @param {Map} cache - From loadHashCache
|
|
95
|
+
* @param {string} relPath - Path relative to _wizz/ (same key space as the CSV)
|
|
96
|
+
* @param {{size: number, mtimeMs: number, ctimeMs: number}} stat - Current file stat
|
|
97
|
+
* @returns {string|null} Cached hash, or null on miss
|
|
98
|
+
*/
|
|
99
|
+
function getCachedHash(cache, relPath, stat) {
|
|
100
|
+
const entry = cache.get(relPath);
|
|
101
|
+
if (!entry) return null;
|
|
102
|
+
if (entry.size !== stat.size || entry.mtimeMs !== stat.mtimeMs || entry.ctimeMs !== stat.ctimeMs) return null;
|
|
103
|
+
return entry.hash;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Build the cache to persist from the files just hashed, pruned to the
|
|
108
|
+
* files actually present in the manifest just written: a relPath that
|
|
109
|
+
* isn't in `currentPaths` (removed module, renamed/deleted file) is
|
|
110
|
+
* dropped, so the cache can't grow forever with entries for files that no
|
|
111
|
+
* longer exist.
|
|
112
|
+
* @param {Map} previousCache - Cache from the previous run (source for
|
|
113
|
+
* files that weren't re-hashed this run but are still installed)
|
|
114
|
+
* @param {Array<{relPath: string, size: number, mtimeMs: number, ctimeMs: number, hash: string}>} hashed - This run's fresh entries (cache misses)
|
|
115
|
+
* @param {Iterable<string>} currentPaths - Every relPath written to files-manifest.csv this run
|
|
116
|
+
* @returns {Object} Plain object ready for JSON.stringify
|
|
117
|
+
*/
|
|
118
|
+
function buildHashCache(previousCache, hashed, currentPaths) {
|
|
119
|
+
const files = {};
|
|
120
|
+
const freshByPath = new Map(hashed.map((h) => [h.relPath, h]));
|
|
121
|
+
for (const relPath of currentPaths) {
|
|
122
|
+
const fresh = freshByPath.get(relPath);
|
|
123
|
+
if (fresh) {
|
|
124
|
+
files[relPath] = { size: fresh.size, mtimeMs: fresh.mtimeMs, ctimeMs: fresh.ctimeMs, hash: fresh.hash };
|
|
125
|
+
continue;
|
|
126
|
+
}
|
|
127
|
+
const prev = previousCache.get(relPath);
|
|
128
|
+
if (prev) files[relPath] = prev;
|
|
129
|
+
}
|
|
130
|
+
return { _v: CACHE_VERSION, algo: CACHE_ALGO, files };
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* Persist the cache atomically next to the files-manifest.csv. Best-effort:
|
|
135
|
+
* a failed write means the next run is a cold start, never an install error.
|
|
136
|
+
* @param {string} cfgDir - _wizz/_config directory
|
|
137
|
+
* @param {Object} data - From buildHashCache
|
|
138
|
+
* @returns {Promise<void>}
|
|
139
|
+
*/
|
|
140
|
+
async function saveHashCache(cfgDir, data) {
|
|
141
|
+
try {
|
|
142
|
+
await fs.writeFile(path.join(cfgDir, CACHE_FILE), JSON.stringify(data) + '\n', 'utf8');
|
|
143
|
+
} catch {
|
|
144
|
+
// Best-effort: cache loss is a perf regression, not a correctness one.
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
module.exports = {
|
|
149
|
+
loadHashCache,
|
|
150
|
+
getCachedHash,
|
|
151
|
+
buildHashCache,
|
|
152
|
+
saveHashCache,
|
|
153
|
+
CACHE_FILE,
|
|
154
|
+
CACHE_VERSION,
|
|
155
|
+
CACHE_ALGO,
|
|
156
|
+
};
|
|
@@ -78,7 +78,10 @@ async function mergeModuleHelpCatalogs(wizzDir, _agentEntries = [], { trackFile
|
|
|
78
78
|
|
|
79
79
|
// Get all installed module directories
|
|
80
80
|
const entries = await fs.readdir(wizzDir, { withFileTypes: true });
|
|
81
|
-
|
|
81
|
+
// 'hooks' (RT-C1, tools/hooks/* copied here by Installer#_installHooks) is
|
|
82
|
+
// infra, not a module — keep it out of the module scan (same reasoning as
|
|
83
|
+
// module-config-writer.js's identical exclusion set).
|
|
84
|
+
const nonModuleDirs = new Set(['_config', '_memory', 'memory', 'docs', 'scripts', 'custom', 'hooks']);
|
|
82
85
|
const installedModules = entries.filter((entry) => entry.isDirectory() && !nonModuleDirs.has(entry.name)).map((entry) => entry.name);
|
|
83
86
|
|
|
84
87
|
// Add core module to scan (it's installed at root level as _config, but we check src/core-skills)
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
// hooks-settings.js — merge PURO dos hooks do Wizz Method em `.claude/settings.json`
|
|
2
|
+
// de um projeto alvo. Sem I/O de disco aqui de propósito: o installer lê/escreve o
|
|
3
|
+
// arquivo (core/installer.js), este módulo só computa o objeto resultante — o que o
|
|
4
|
+
// torna testável sem tocar disco (RT-C1, auditoria 2026-09-11).
|
|
5
|
+
//
|
|
6
|
+
// Contrato do merge:
|
|
7
|
+
// - NÃO destrutivo: toda chave existente do settings.json (permissions, env,
|
|
8
|
+
// model, hooks de outros eventos/matchers) é preservada.
|
|
9
|
+
// - Idempotente: rodar 2x com os mesmos hookEntries não duplica nada
|
|
10
|
+
// (comparação pelo `command` completo).
|
|
11
|
+
// - Update seguro: uma entrada ANTIGA nossa no mesmo evento/matcher
|
|
12
|
+
// (reconhecida pelo path `_wizz/hooks/` + basename do hook) é substituída
|
|
13
|
+
// pela nova, sem mexer em hooks de terceiros que dividem o mesmo evento.
|
|
14
|
+
//
|
|
15
|
+
// filterHooksRegisteredGlobally (decisão do dono, 2026-09-11): quando um hook
|
|
16
|
+
// nosso já está registrado no settings.json GLOBAL do usuário (~/.claude/),
|
|
17
|
+
// o installer pula o registro no projeto para não rodar o mesmo hook 2x.
|
|
18
|
+
|
|
19
|
+
const HOOKS_DIR = '_wizz/hooks';
|
|
20
|
+
|
|
21
|
+
// Definição canônica dos hooks e onde cada um se registra em settings.json.
|
|
22
|
+
// event/matcher/timeout replicam 1:1 o que tools/hooks/README.md documenta e
|
|
23
|
+
// o que já roda hoje na máquina do mantenedor (npm run sync:global + registro
|
|
24
|
+
// manual em ~/.claude/settings.json) — nenhum formato novo foi inventado.
|
|
25
|
+
const HOOK_DEFS = [
|
|
26
|
+
{ id: 'session-rules.js', event: 'SessionStart', kind: 'node' },
|
|
27
|
+
{ id: 'wizz-router-enforce.js', event: 'UserPromptSubmit', kind: 'node' },
|
|
28
|
+
{ id: 'security-defensive-context.js', event: 'PreToolUse', matcher: 'Skill', kind: 'node' },
|
|
29
|
+
// rtk é opcional (item 4 da decisão RT-C1): só entra em hookEntries quando
|
|
30
|
+
// `rtkOnPath` é true — ver buildHookEntries abaixo.
|
|
31
|
+
{ id: 'rtk-rewrite.sh', event: 'PreToolUse', matcher: 'Bash', kind: 'shell', requires: 'rtk' },
|
|
32
|
+
{ id: 'wizz-decision-trace.js', event: 'Stop', kind: 'node' },
|
|
33
|
+
];
|
|
34
|
+
|
|
35
|
+
const DEFAULT_TIMEOUT = 5;
|
|
36
|
+
|
|
37
|
+
function commandFor(def) {
|
|
38
|
+
const target = `$CLAUDE_PROJECT_DIR/${HOOKS_DIR}/${def.id}`;
|
|
39
|
+
return def.kind === 'shell' ? `"${target}"` : `node "${target}"`;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Monta as entradas de hook a registrar em settings.json, a partir dos
|
|
44
|
+
* arquivos de fato copiados para `_wizz/hooks/`. Filtra `rtk-rewrite.sh`
|
|
45
|
+
* quando `rtkOnPath` é false — rtk é opcional (item 4, RT-C1).
|
|
46
|
+
* @param {string[]} installedHookFiles - basenames copiados para _wizz/hooks/
|
|
47
|
+
* @param {{rtkOnPath?: boolean}} [options]
|
|
48
|
+
* @returns {Array<{event: string, matcher?: string, id: string, command: string, timeout: number}>}
|
|
49
|
+
*/
|
|
50
|
+
function buildHookEntries(installedHookFiles, { rtkOnPath = false } = {}) {
|
|
51
|
+
const installed = new Set(installedHookFiles || []);
|
|
52
|
+
return HOOK_DEFS.filter((def) => installed.has(def.id) && (def.requires !== 'rtk' || rtkOnPath)).map((def) => ({
|
|
53
|
+
event: def.event,
|
|
54
|
+
matcher: def.matcher,
|
|
55
|
+
id: def.id,
|
|
56
|
+
command: commandFor(def),
|
|
57
|
+
timeout: DEFAULT_TIMEOUT,
|
|
58
|
+
}));
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Remove de `hookEntries` toda entrada cujo hook (basename, ex.
|
|
63
|
+
* "rtk-rewrite.sh") já esteja registrado no MESMO evento do settings.json
|
|
64
|
+
* GLOBAL do usuário (`~/.claude/settings.json`) — decisão do dono
|
|
65
|
+
* (2026-09-11): evita rodar o mesmo hook 2x (global + projeto) numa máquina
|
|
66
|
+
* onde o mantenedor já registrou os hooks do Wizz globalmente. Compara pelo
|
|
67
|
+
* basename dentro do `command` (qualquer matcher no evento conta — um hook
|
|
68
|
+
* global sem matcher já cobre o Bash inteiro, por exemplo), não por igualdade
|
|
69
|
+
* exata do comando, porque o path do comando global (`~/.claude/hooks/...`)
|
|
70
|
+
* nunca é igual ao path do comando do projeto (`_wizz/hooks/...`).
|
|
71
|
+
* @param {Array<{event: string, matcher?: string, id: string, command: string, timeout?: number}>} hookEntries
|
|
72
|
+
* @param {object} globalSettings - conteúdo de ~/.claude/settings.json (ou {}/null/undefined)
|
|
73
|
+
* @returns {{entries: Array, skipped: string[]}}
|
|
74
|
+
*/
|
|
75
|
+
function filterHooksRegisteredGlobally(hookEntries, globalSettings) {
|
|
76
|
+
const entries = hookEntries || [];
|
|
77
|
+
const globalHooks = globalSettings && typeof globalSettings === 'object' ? globalSettings.hooks : null;
|
|
78
|
+
if (!globalHooks || typeof globalHooks !== 'object') {
|
|
79
|
+
return { entries: [...entries], skipped: [] };
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
const isRegisteredGlobally = (event, id) => {
|
|
83
|
+
const blocks = Array.isArray(globalHooks[event]) ? globalHooks[event] : [];
|
|
84
|
+
return blocks.some(
|
|
85
|
+
(block) => Array.isArray(block.hooks) && block.hooks.some((h) => h && typeof h.command === 'string' && h.command.includes(id)),
|
|
86
|
+
);
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
const skipped = [];
|
|
90
|
+
const kept = entries.filter((entry) => {
|
|
91
|
+
if (isRegisteredGlobally(entry.event, entry.id)) {
|
|
92
|
+
skipped.push(entry.id);
|
|
93
|
+
return false;
|
|
94
|
+
}
|
|
95
|
+
return true;
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
return { entries: kept, skipped };
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
function cloneJson(value) {
|
|
102
|
+
if (value === undefined || value === null) return {};
|
|
103
|
+
return structuredClone(value);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Um comando é "nosso" quando referencia `_wizz/hooks/<id>` — usado tanto
|
|
108
|
+
* para reconhecer uma entrada antiga a substituir (update) quanto para nunca
|
|
109
|
+
* confundir com um hook de terceiro que por acaso caia no mesmo evento.
|
|
110
|
+
* @param {string} command
|
|
111
|
+
* @param {string} id - basename do hook (ex.: "session-rules.js")
|
|
112
|
+
* @returns {boolean}
|
|
113
|
+
*/
|
|
114
|
+
function isOurHookCommand(command, id) {
|
|
115
|
+
return typeof command === 'string' && command.includes(`${HOOKS_DIR}/`) && command.includes(id);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* Merge não destrutivo e idempotente de `hookEntries` num `settings.json` já
|
|
120
|
+
* existente (ou {} quando o projeto ainda não tem um). Função pura — nenhuma
|
|
121
|
+
* leitura/escrita de arquivo acontece aqui.
|
|
122
|
+
* @param {object} existingSettings - conteúdo atual de .claude/settings.json (ou {})
|
|
123
|
+
* @param {Array<{event: string, matcher?: string, id: string, command: string, timeout?: number}>} hookEntries
|
|
124
|
+
* @returns {object} newSettings
|
|
125
|
+
*/
|
|
126
|
+
function mergeHooksIntoSettings(existingSettings, hookEntries) {
|
|
127
|
+
const settings = cloneJson(existingSettings);
|
|
128
|
+
const hooks = cloneJson(settings.hooks);
|
|
129
|
+
|
|
130
|
+
for (const entry of hookEntries || []) {
|
|
131
|
+
const { event, matcher, id, command, timeout } = entry;
|
|
132
|
+
const blocks = Array.isArray(hooks[event]) ? hooks[event] : [];
|
|
133
|
+
const sameMatcher = (block) => (matcher ? block.matcher === matcher : block.matcher === undefined);
|
|
134
|
+
|
|
135
|
+
// 1) Já presente, idêntico — nada a fazer (idempotência).
|
|
136
|
+
const alreadyPresent = blocks.some(
|
|
137
|
+
(block) => sameMatcher(block) && Array.isArray(block.hooks) && block.hooks.some((h) => h && h.command === command),
|
|
138
|
+
);
|
|
139
|
+
if (alreadyPresent) {
|
|
140
|
+
hooks[event] = blocks;
|
|
141
|
+
continue;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
// 2) Versão antiga NOSSA no mesmo evento/matcher — substitui em vez de duplicar.
|
|
145
|
+
const staleIndex = blocks.findIndex(
|
|
146
|
+
(block) => sameMatcher(block) && Array.isArray(block.hooks) && block.hooks.some((h) => isOurHookCommand(h && h.command, id)),
|
|
147
|
+
);
|
|
148
|
+
|
|
149
|
+
if (staleIndex !== -1) {
|
|
150
|
+
const staleBlock = blocks[staleIndex];
|
|
151
|
+
const newBlocks = [...blocks];
|
|
152
|
+
newBlocks[staleIndex] = {
|
|
153
|
+
...staleBlock,
|
|
154
|
+
hooks: staleBlock.hooks.map((h) => (isOurHookCommand(h && h.command, id) ? { type: 'command', command, timeout } : h)),
|
|
155
|
+
};
|
|
156
|
+
hooks[event] = newBlocks;
|
|
157
|
+
continue;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
// 3) Nada nosso ainda neste evento/matcher — adiciona um bloco novo,
|
|
161
|
+
// preservando qualquer bloco de terceiro já presente no mesmo evento.
|
|
162
|
+
const newBlock = matcher
|
|
163
|
+
? { matcher, hooks: [{ type: 'command', command, timeout }] }
|
|
164
|
+
: { hooks: [{ type: 'command', command, timeout }] };
|
|
165
|
+
hooks[event] = [...blocks, newBlock];
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
return { ...settings, hooks };
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
module.exports = {
|
|
172
|
+
HOOKS_DIR,
|
|
173
|
+
HOOK_DEFS,
|
|
174
|
+
buildHookEntries,
|
|
175
|
+
filterHooksRegisteredGlobally,
|
|
176
|
+
mergeHooksIntoSettings,
|
|
177
|
+
isOurHookCommand,
|
|
178
|
+
};
|