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,14 +1,49 @@
|
|
|
1
1
|
const fs = require('../fs-native');
|
|
2
2
|
const os = require('node:os');
|
|
3
3
|
const path = require('node:path');
|
|
4
|
-
const {
|
|
4
|
+
const { execFileSync } = require('node:child_process');
|
|
5
5
|
const prompts = require('../prompts');
|
|
6
|
+
// Timeout constants + timeout-aware helpers (ACH-01/EXT-01, auditoria
|
|
7
|
+
// 2026-09-11) agora vivem em git-cache-utils.js (item 20, etapa 1) — uma
|
|
8
|
+
// fonte única compartilhada com external-manager.js, que ainda re-exporta os
|
|
9
|
+
// mesmos símbolos para callers/testes antigos.
|
|
10
|
+
const {
|
|
11
|
+
GIT_NETWORK_TIMEOUT_MS,
|
|
12
|
+
GIT_LOCAL_TIMEOUT_MS,
|
|
13
|
+
NPM_INSTALL_TIMEOUT_MS,
|
|
14
|
+
describeGitTimeout,
|
|
15
|
+
validateGitRef: validateCustomRef,
|
|
16
|
+
} = require('./git-cache-utils');
|
|
17
|
+
// Item 8c (auditoria 2026-09-11): TAG@SHA pins for custom modules. The parse
|
|
18
|
+
// lives in pin-spec.js, shared with external-manager.js and surfaced at the
|
|
19
|
+
// CLI gate by channel-plan.js, so all three paths agree on format + errors.
|
|
20
|
+
const { parsePinTagAndSha, resolvePinOverride, buildPinMismatchError } = require('./pin-spec');
|
|
21
|
+
|
|
22
|
+
// validateCustomRef (forma defensiva de ref) agora é validateGitRef em
|
|
23
|
+
// git-cache-utils.js, importado acima com o rótulo antigo preservado.
|
|
24
|
+
|
|
25
|
+
// RFC-1123 hostname: labels of letters/digits/hyphen (no leading/trailing
|
|
26
|
+
// hyphen), joined by dots.
|
|
27
|
+
const SSH_HOST_RE = /^[A-Za-z0-9]([A-Za-z0-9-]*[A-Za-z0-9])?(\.[A-Za-z0-9]([A-Za-z0-9-]*[A-Za-z0-9])?)*$/;
|
|
28
|
+
// Owner/repo path segments: letters, digits, dot, underscore, hyphen only.
|
|
29
|
+
const SSH_PATH_SEGMENT_RE = /^[A-Za-z0-9._-]+$/;
|
|
6
30
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
31
|
+
/**
|
|
32
|
+
* Validate the host/owner/repo captured from a `git@host:owner/repo` SSH URL
|
|
33
|
+
* match. The regex that captures these groups is intentionally permissive
|
|
34
|
+
* (it must accept any self-hosted Git host), so this is the layer that
|
|
35
|
+
* rejects shell metacharacters (quotes, backticks, `$()`, `;`, spaces, etc.)
|
|
36
|
+
* before the value is ever handed to `git`.
|
|
37
|
+
* @param {string} host
|
|
38
|
+
* @param {string} owner - May contain `/` for nested groups (GitLab subgroups).
|
|
39
|
+
* @param {string} repo
|
|
40
|
+
* @returns {boolean}
|
|
41
|
+
*/
|
|
42
|
+
function isValidSshRepoParts(host, owner, repo) {
|
|
43
|
+
if (!SSH_HOST_RE.test(host)) return false;
|
|
44
|
+
if (!repo || !SSH_PATH_SEGMENT_RE.test(repo)) return false;
|
|
45
|
+
const ownerSegments = owner.split('/');
|
|
46
|
+
return ownerSegments.length > 0 && ownerSegments.every((segment) => SSH_PATH_SEGMENT_RE.test(segment));
|
|
12
47
|
}
|
|
13
48
|
|
|
14
49
|
/**
|
|
@@ -118,6 +153,13 @@ class CustomModuleManager {
|
|
|
118
153
|
const sshMatch = trimmed.match(/^git@([^:]+):(.+?)\/([^/.]+?)(?:\.git)?$/);
|
|
119
154
|
if (sshMatch) {
|
|
120
155
|
const [, host, owner, repo] = sshMatch;
|
|
156
|
+
if (!isValidSshRepoParts(host, owner, repo)) {
|
|
157
|
+
throw new Error(
|
|
158
|
+
`URL SSH inválida: "${trimmedRaw}". O host, o owner e o nome do repositório só podem conter letras, ` +
|
|
159
|
+
'números, ponto, hífen, underscore e barra (para subgrupos). Verifique se não há aspas, crase, `$()`, ' +
|
|
160
|
+
'`;` ou espaços na URL.',
|
|
161
|
+
);
|
|
162
|
+
}
|
|
121
163
|
return {
|
|
122
164
|
type: 'url',
|
|
123
165
|
cloneUrl: trimmed,
|
|
@@ -376,12 +418,19 @@ class CustomModuleManager {
|
|
|
376
418
|
const silent = options.silent || false;
|
|
377
419
|
const displayName = parsed.displayName;
|
|
378
420
|
|
|
379
|
-
// Pin override:
|
|
380
|
-
|
|
381
|
-
|
|
421
|
+
// Pin override (bug 8: keyed by displayName — see resolvePinOverride's JSDoc in pin-spec.js) beats any @version suffix in the URL. May be TAG@40-hex-sha — split below; verified against HEAD further down.
|
|
422
|
+
let effectiveVersion = resolvePinOverride(options, parsed.displayName) || parsed.version || null;
|
|
423
|
+
let expectedPinSha = null;
|
|
424
|
+
if (effectiveVersion && effectiveVersion.includes('@')) {
|
|
425
|
+
const parsedPin = parsePinTagAndSha(effectiveVersion);
|
|
426
|
+
effectiveVersion = parsedPin.tag;
|
|
427
|
+
expectedPinSha = parsedPin.expectedSha;
|
|
428
|
+
}
|
|
382
429
|
|
|
383
430
|
await fs.ensureDir(path.dirname(repoCacheDir));
|
|
384
431
|
|
|
432
|
+
let fetchFailed = false; // Bug 4: set on fetch failure below; read by buildPinMismatchError further down.
|
|
433
|
+
|
|
385
434
|
const createSpinner = async () => {
|
|
386
435
|
if (silent) {
|
|
387
436
|
return { start() {}, stop() {}, error() {} };
|
|
@@ -393,12 +442,30 @@ class CustomModuleManager {
|
|
|
393
442
|
// Tracked via .wizz-source.json's recorded version.
|
|
394
443
|
if (await fs.pathExists(repoCacheDir)) {
|
|
395
444
|
let cachedVersion = null;
|
|
445
|
+
let cachedSha = null;
|
|
446
|
+
let cachedExpectedSha = null;
|
|
396
447
|
try {
|
|
397
448
|
const existing = await fs.readJson(path.join(repoCacheDir, '.wizz-source.json'));
|
|
398
449
|
cachedVersion = existing?.version || null;
|
|
450
|
+
cachedSha = existing?.sha || null;
|
|
451
|
+
cachedExpectedSha = existing?.expectedSha || null;
|
|
399
452
|
} catch {
|
|
400
453
|
// no metadata; treat as mismatched to be safe if a version was requested
|
|
401
454
|
}
|
|
455
|
+
// Item 8c: a TAG@SHA pin whose cache was already verified at this exact
|
|
456
|
+
// commit needs no refresh — fetching would only risk pulling a remotely
|
|
457
|
+
// moved tag over a known-good checkout. Same tag under a different
|
|
458
|
+
// expectedSha falls through to the fetch + post-clone check below.
|
|
459
|
+
if (
|
|
460
|
+
expectedPinSha &&
|
|
461
|
+
(cachedVersion || null) === (effectiveVersion || null) &&
|
|
462
|
+
cachedSha &&
|
|
463
|
+
cachedExpectedSha &&
|
|
464
|
+
cachedSha.toLowerCase() === cachedExpectedSha &&
|
|
465
|
+
cachedExpectedSha === expectedPinSha
|
|
466
|
+
) {
|
|
467
|
+
return repoCacheDir;
|
|
468
|
+
}
|
|
402
469
|
if ((effectiveVersion || null) !== (cachedVersion || null)) {
|
|
403
470
|
await fs.remove(repoCacheDir);
|
|
404
471
|
}
|
|
@@ -409,23 +476,30 @@ class CustomModuleManager {
|
|
|
409
476
|
const fetchSpinner = await createSpinner();
|
|
410
477
|
fetchSpinner.start(`Updating ${displayName}...`);
|
|
411
478
|
try {
|
|
412
|
-
|
|
479
|
+
execFileSync('git', ['fetch', 'origin', '--depth', '1'], {
|
|
413
480
|
cwd: repoCacheDir,
|
|
414
481
|
stdio: ['ignore', 'pipe', 'pipe'],
|
|
415
482
|
env: { ...process.env, GIT_TERMINAL_PROMPT: '0' },
|
|
483
|
+
timeout: GIT_NETWORK_TIMEOUT_MS,
|
|
484
|
+
killSignal: 'SIGKILL',
|
|
416
485
|
});
|
|
417
486
|
if (effectiveVersion) {
|
|
418
487
|
// Fetch the ref as either a tag or a branch — `origin <ref>` works
|
|
419
488
|
// for both, whereas `origin tag <ref>` fails for branch refs parsed
|
|
420
489
|
// out of /tree/<branch>/... URLs.
|
|
421
|
-
|
|
490
|
+
validateCustomRef(effectiveVersion);
|
|
491
|
+
execFileSync('git', ['fetch', '--depth', '1', 'origin', effectiveVersion, '--no-tags'], {
|
|
422
492
|
cwd: repoCacheDir,
|
|
423
493
|
stdio: ['ignore', 'pipe', 'pipe'],
|
|
424
494
|
env: { ...process.env, GIT_TERMINAL_PROMPT: '0' },
|
|
495
|
+
timeout: GIT_NETWORK_TIMEOUT_MS,
|
|
496
|
+
killSignal: 'SIGKILL',
|
|
425
497
|
});
|
|
426
|
-
|
|
498
|
+
execFileSync('git', ['checkout', '--quiet', 'FETCH_HEAD'], {
|
|
427
499
|
cwd: repoCacheDir,
|
|
428
500
|
stdio: ['ignore', 'pipe', 'pipe'],
|
|
501
|
+
timeout: GIT_LOCAL_TIMEOUT_MS,
|
|
502
|
+
killSignal: 'SIGKILL',
|
|
429
503
|
});
|
|
430
504
|
} else {
|
|
431
505
|
// Resolve the default branch (origin/HEAD) and fetch it explicitly.
|
|
@@ -433,9 +507,11 @@ class CustomModuleManager {
|
|
|
433
507
|
// origin/HEAD` never picks up new commits on the default branch.
|
|
434
508
|
let defaultBranch = 'main';
|
|
435
509
|
try {
|
|
436
|
-
defaultBranch =
|
|
510
|
+
defaultBranch = execFileSync('git', ['symbolic-ref', 'refs/remotes/origin/HEAD', '--short'], {
|
|
437
511
|
cwd: repoCacheDir,
|
|
438
512
|
stdio: 'pipe',
|
|
513
|
+
timeout: GIT_LOCAL_TIMEOUT_MS,
|
|
514
|
+
killSignal: 'SIGKILL',
|
|
439
515
|
})
|
|
440
516
|
.toString()
|
|
441
517
|
.trim()
|
|
@@ -443,24 +519,33 @@ class CustomModuleManager {
|
|
|
443
519
|
} catch {
|
|
444
520
|
// Fallback if origin/HEAD is not set
|
|
445
521
|
}
|
|
446
|
-
|
|
522
|
+
validateCustomRef(defaultBranch);
|
|
523
|
+
execFileSync('git', ['fetch', '--depth', '1', 'origin', defaultBranch], {
|
|
447
524
|
cwd: repoCacheDir,
|
|
448
525
|
stdio: ['ignore', 'pipe', 'pipe'],
|
|
449
526
|
env: { ...process.env, GIT_TERMINAL_PROMPT: '0' },
|
|
527
|
+
timeout: GIT_NETWORK_TIMEOUT_MS,
|
|
528
|
+
killSignal: 'SIGKILL',
|
|
450
529
|
});
|
|
451
|
-
|
|
530
|
+
execFileSync('git', ['reset', '--hard', `origin/${defaultBranch}`], {
|
|
452
531
|
cwd: repoCacheDir,
|
|
453
532
|
stdio: ['ignore', 'pipe', 'pipe'],
|
|
533
|
+
timeout: GIT_LOCAL_TIMEOUT_MS,
|
|
534
|
+
killSignal: 'SIGKILL',
|
|
454
535
|
});
|
|
455
536
|
}
|
|
456
537
|
fetchSpinner.stop(`Updated ${displayName}`);
|
|
457
|
-
} catch {
|
|
538
|
+
} catch (error_) {
|
|
458
539
|
// Fetch failed against an existing cache — most often the remote is
|
|
459
|
-
// unreachable (network down, repo deleted/moved, auth revoked)
|
|
460
|
-
//
|
|
461
|
-
//
|
|
540
|
+
// unreachable (network down, repo deleted/moved, auth revoked), or our
|
|
541
|
+
// own `timeout` killed a hung git process (ACH-01/EXT-01). Preserve
|
|
542
|
+
// the previous clone so re-deploy still works from cached content;
|
|
543
|
+
// surface a warning so the user knows the cache is stale.
|
|
544
|
+
fetchFailed = true;
|
|
462
545
|
fetchSpinner.error(`Could not refresh ${displayName} — keeping cached copy`);
|
|
463
|
-
await prompts.log.warn(
|
|
546
|
+
await prompts.log.warn(
|
|
547
|
+
`Custom module ${displayName} was not refreshed (remote unreachable). Using cached copy.${describeGitTimeout(error_)}`,
|
|
548
|
+
);
|
|
464
549
|
}
|
|
465
550
|
}
|
|
466
551
|
|
|
@@ -469,39 +554,74 @@ class CustomModuleManager {
|
|
|
469
554
|
fetchSpinner.start(`Cloning ${displayName}${effectiveVersion ? ` @ ${effectiveVersion}` : ''}...`);
|
|
470
555
|
try {
|
|
471
556
|
if (effectiveVersion) {
|
|
472
|
-
|
|
557
|
+
validateCustomRef(effectiveVersion);
|
|
558
|
+
execFileSync('git', ['clone', '--depth', '1', '--branch', effectiveVersion, parsed.cloneUrl, repoCacheDir], {
|
|
473
559
|
stdio: ['ignore', 'pipe', 'pipe'],
|
|
474
560
|
env: { ...process.env, GIT_TERMINAL_PROMPT: '0' },
|
|
561
|
+
timeout: GIT_NETWORK_TIMEOUT_MS,
|
|
562
|
+
killSignal: 'SIGKILL',
|
|
475
563
|
});
|
|
476
564
|
} else {
|
|
477
|
-
|
|
565
|
+
execFileSync('git', ['clone', '--depth', '1', parsed.cloneUrl, repoCacheDir], {
|
|
478
566
|
stdio: ['ignore', 'pipe', 'pipe'],
|
|
479
567
|
env: { ...process.env, GIT_TERMINAL_PROMPT: '0' },
|
|
568
|
+
timeout: GIT_NETWORK_TIMEOUT_MS,
|
|
569
|
+
killSignal: 'SIGKILL',
|
|
480
570
|
});
|
|
481
571
|
}
|
|
482
572
|
fetchSpinner.stop(`Cloned ${displayName}`);
|
|
483
573
|
} catch (error_) {
|
|
484
574
|
fetchSpinner.error(`Failed to clone ${displayName}`);
|
|
485
575
|
const refSuffix = effectiveVersion ? `@${effectiveVersion}` : '';
|
|
486
|
-
throw new Error(`Failed to clone ${parsed.cloneUrl}${refSuffix}: ${error_.message}`);
|
|
576
|
+
throw new Error(`Failed to clone ${parsed.cloneUrl}${refSuffix}: ${error_.message}${describeGitTimeout(error_)}`);
|
|
487
577
|
}
|
|
488
578
|
}
|
|
489
579
|
|
|
490
580
|
// Record the resolved SHA for the manifest writer.
|
|
491
581
|
let resolvedSha = null;
|
|
492
582
|
try {
|
|
493
|
-
resolvedSha =
|
|
583
|
+
resolvedSha = execFileSync('git', ['rev-parse', 'HEAD'], {
|
|
584
|
+
cwd: repoCacheDir,
|
|
585
|
+
stdio: 'pipe',
|
|
586
|
+
timeout: GIT_LOCAL_TIMEOUT_MS,
|
|
587
|
+
killSignal: 'SIGKILL',
|
|
588
|
+
})
|
|
589
|
+
.toString()
|
|
590
|
+
.trim();
|
|
494
591
|
} catch {
|
|
495
592
|
// swallow — a non-git repo (local path) wouldn't reach here anyway
|
|
496
593
|
}
|
|
594
|
+
// Item 8c (auditoria 2026-09-11): with a TAG@SHA pin, verify the commit
|
|
595
|
+
// we actually checked out matches what was requested. A git tag is a
|
|
596
|
+
// mutable ref — nothing stops the remote from force-moving it between
|
|
597
|
+
// installs — so this is a trust check, not a network hiccup: it must run
|
|
598
|
+
// before any metadata/marker/resolution a later run would trust is
|
|
599
|
+
// written, and it must never be retried as transient. On mismatch we
|
|
600
|
+
// remove the whole cache dir rather than leave a "cloned fine but at the
|
|
601
|
+
// wrong commit" checkout indistinguishable from a good one — same
|
|
602
|
+
// posture and error text as external-manager.js (item 8 fase 2). Strict equality per bug 3; buildPinMismatchError (pin-spec.js) picks fetch-failed vs. real-mismatch wording per bug 4.
|
|
603
|
+
if (expectedPinSha && (!resolvedSha || resolvedSha.toLowerCase() !== expectedPinSha)) {
|
|
604
|
+
await fs.remove(repoCacheDir);
|
|
605
|
+
const pinDisplay = `${parsed.displayName}=${effectiveVersion}@${expectedPinSha}`;
|
|
606
|
+
throw buildPinMismatchError({
|
|
607
|
+
displayName,
|
|
608
|
+
tag: effectiveVersion,
|
|
609
|
+
resolvedSha,
|
|
610
|
+
expectedSha: expectedPinSha,
|
|
611
|
+
pinDisplay,
|
|
612
|
+
fetchFailed,
|
|
613
|
+
});
|
|
614
|
+
}
|
|
497
615
|
// Best-effort: capture the remote default branch name so channel marker
|
|
498
616
|
// metadata for "next" reflects the actual tracked ref (not always "main").
|
|
499
617
|
let defaultRef = 'main';
|
|
500
618
|
if (!effectiveVersion) {
|
|
501
619
|
try {
|
|
502
|
-
const symbolic =
|
|
620
|
+
const symbolic = execFileSync('git', ['symbolic-ref', '--short', 'refs/remotes/origin/HEAD'], {
|
|
503
621
|
cwd: repoCacheDir,
|
|
504
622
|
stdio: 'pipe',
|
|
623
|
+
timeout: GIT_LOCAL_TIMEOUT_MS,
|
|
624
|
+
killSignal: 'SIGKILL',
|
|
505
625
|
})
|
|
506
626
|
.toString()
|
|
507
627
|
.trim();
|
|
@@ -530,6 +650,10 @@ class CustomModuleManager {
|
|
|
530
650
|
version: effectiveVersion || null,
|
|
531
651
|
rawInput: parsed.rawInput || sourceInput,
|
|
532
652
|
sha: resolvedSha,
|
|
653
|
+
// Item 8c: recorded so a later cloneRepo with the same TAG@SHA pin can
|
|
654
|
+
// early-return without re-fetching (a fetch could pull a moved tag over
|
|
655
|
+
// a verified checkout).
|
|
656
|
+
expectedSha: expectedPinSha || null,
|
|
533
657
|
clonedAt: new Date().toISOString(),
|
|
534
658
|
});
|
|
535
659
|
// Keep a channel marker in custom cache too so update paths that rely on
|
|
@@ -539,6 +663,7 @@ class CustomModuleManager {
|
|
|
539
663
|
channel: effectiveVersion ? 'pinned' : 'next',
|
|
540
664
|
version: effectiveVersion || defaultRef,
|
|
541
665
|
sha: resolvedSha,
|
|
666
|
+
expectedSha: expectedPinSha || null,
|
|
542
667
|
writtenAt: new Date().toISOString(),
|
|
543
668
|
});
|
|
544
669
|
|
|
@@ -548,10 +673,13 @@ class CustomModuleManager {
|
|
|
548
673
|
const installSpinner = await createSpinner();
|
|
549
674
|
installSpinner.start(`Installing dependencies for ${displayName}...`);
|
|
550
675
|
try {
|
|
551
|
-
|
|
676
|
+
execFileSync('npm', ['install', '--omit=dev', '--no-audit', '--no-fund', '--no-progress', '--legacy-peer-deps'], {
|
|
677
|
+
// npm é npm.cmd no Windows e só roda via shell; os args acima são constantes, sem input do usuário.
|
|
678
|
+
shell: process.platform === 'win32',
|
|
552
679
|
cwd: repoCacheDir,
|
|
553
680
|
stdio: ['ignore', 'pipe', 'pipe'],
|
|
554
|
-
timeout:
|
|
681
|
+
timeout: NPM_INSTALL_TIMEOUT_MS,
|
|
682
|
+
killSignal: 'SIGKILL',
|
|
555
683
|
});
|
|
556
684
|
installSpinner.stop(`Installed dependencies for ${displayName}`);
|
|
557
685
|
} catch (error_) {
|
|
@@ -781,7 +909,12 @@ class CustomModuleManager {
|
|
|
781
909
|
try {
|
|
782
910
|
await this.cloneRepo(metadata.rawInput, {
|
|
783
911
|
silent: true,
|
|
784
|
-
|
|
912
|
+
// Round-trip both halves of a TAG@SHA pin (item 8c): re-passing only
|
|
913
|
+
// metadata.version (the plain tag) would drop the expected-SHA trust
|
|
914
|
+
// check on refresh. metadata.expectedSha is only ever set when the
|
|
915
|
+
// pin carried it, so plain-version caches are unaffected.
|
|
916
|
+
pinOverride:
|
|
917
|
+
metadata.version && metadata.expectedSha ? `${metadata.version}@${metadata.expectedSha}` : metadata.version || undefined,
|
|
785
918
|
});
|
|
786
919
|
CustomModuleManager._refreshedRepoPaths.add(repoPath);
|
|
787
920
|
} catch (error_) {
|
|
@@ -48,6 +48,113 @@ const os = require('node:os');
|
|
|
48
48
|
const fs = require('../fs-native');
|
|
49
49
|
const prompts = require('../prompts');
|
|
50
50
|
|
|
51
|
+
/**
|
|
52
|
+
* Check if a gitignore line/pattern covers `.claude/settings.local.json`.
|
|
53
|
+
* Patterns that match:
|
|
54
|
+
* - `.claude/settings.local.json` (literal)
|
|
55
|
+
* - `settings.local.json` (basename only)
|
|
56
|
+
* - `*.local.json` (extension pattern)
|
|
57
|
+
* - `.claude/*.local.json` (dir + extension)
|
|
58
|
+
* - `.claude/` (entire directory)
|
|
59
|
+
* - `.claude` (directory without trailing /)
|
|
60
|
+
*
|
|
61
|
+
* @param {string} pattern - A line from .gitignore
|
|
62
|
+
* @returns {boolean}
|
|
63
|
+
*/
|
|
64
|
+
function patternCoversSettingsLocal(pattern) {
|
|
65
|
+
if (!pattern || typeof pattern !== 'string') return false;
|
|
66
|
+
const trimmed = pattern.trim();
|
|
67
|
+
if (trimmed.startsWith('#') || trimmed === '') return false;
|
|
68
|
+
|
|
69
|
+
// Normalize: remove leading/trailing whitespace
|
|
70
|
+
const normalized = trimmed.trim();
|
|
71
|
+
|
|
72
|
+
// Exact literal match
|
|
73
|
+
if (normalized === '.claude/settings.local.json' || normalized === '.claude/settings.local.json/') {
|
|
74
|
+
return true;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// Basename only
|
|
78
|
+
if (normalized === 'settings.local.json' || normalized === 'settings.local.json/') {
|
|
79
|
+
return true;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// Extension pattern
|
|
83
|
+
if (normalized === '*.local.json') {
|
|
84
|
+
return true;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// Directory-scoped extension pattern
|
|
88
|
+
if (normalized === '.claude/*.local.json') {
|
|
89
|
+
return true;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// Entire .claude directory
|
|
93
|
+
if (normalized === '.claude/' || normalized === '.claude') {
|
|
94
|
+
return true;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
return false;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Verify that `.claude/settings.local.json` is covered by a pattern in
|
|
102
|
+
* `.gitignore`. If not covered and `.git` exists (repo root), add the line.
|
|
103
|
+
* Pure function (testable without real filesystem, but performs I/O here for simplicity).
|
|
104
|
+
*
|
|
105
|
+
* @param {string} projectRoot - Project root (where `_wizz/`, `.git`, `.gitignore` live)
|
|
106
|
+
* @returns {Promise<{added: boolean, reason: string}>}
|
|
107
|
+
* - `{ added: true, reason: "..." }` if the line was added to .gitignore
|
|
108
|
+
* - `{ added: false, reason: "..." }` if already covered, not a git repo, or error
|
|
109
|
+
*/
|
|
110
|
+
async function ensureSettingsLocalIgnored(projectRoot) {
|
|
111
|
+
if (!projectRoot) {
|
|
112
|
+
return { added: false, reason: 'projectRoot não fornecido' };
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
const gitDir = path.join(projectRoot, '.git');
|
|
116
|
+
const gitignorePath = path.join(projectRoot, '.gitignore');
|
|
117
|
+
|
|
118
|
+
// Check if this is a git repository
|
|
119
|
+
const isGitRepo = await fs.pathExists(gitDir);
|
|
120
|
+
if (!isGitRepo) {
|
|
121
|
+
return { added: false, reason: 'não é um repositório git' };
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// Read .gitignore if it exists
|
|
125
|
+
let content = '';
|
|
126
|
+
if (await fs.pathExists(gitignorePath)) {
|
|
127
|
+
try {
|
|
128
|
+
content = await fs.readFile(gitignorePath, 'utf8');
|
|
129
|
+
} catch {
|
|
130
|
+
return { added: false, reason: 'não foi possível ler .gitignore' };
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// Check if any line already covers .claude/settings.local.json
|
|
135
|
+
const lines = content.split('\n');
|
|
136
|
+
for (const line of lines) {
|
|
137
|
+
if (patternCoversSettingsLocal(line)) {
|
|
138
|
+
return { added: false, reason: '.claude/settings.local.json já está no .gitignore' };
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
// Not covered: add the line (only if .git exists, which we already checked above)
|
|
143
|
+
try {
|
|
144
|
+
// Ensure content ends with newline, then append the new line
|
|
145
|
+
let newContent = content;
|
|
146
|
+
if (newContent && !newContent.endsWith('\n')) {
|
|
147
|
+
newContent += '\n';
|
|
148
|
+
}
|
|
149
|
+
newContent += '.claude/settings.local.json\n';
|
|
150
|
+
|
|
151
|
+
await fs.writeFile(gitignorePath, newContent, 'utf8');
|
|
152
|
+
return { added: true, reason: 'linha adicionada ao .gitignore' };
|
|
153
|
+
} catch {
|
|
154
|
+
return { added: false, reason: 'falha ao escrever em .gitignore' };
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
|
|
51
158
|
// Global key store, read by the INSTALLER only (never by the Claude Code
|
|
52
159
|
// runtime — C7 still holds). A value found here is copied into the project's
|
|
53
160
|
// `.claude/settings.local.json` at install time, which IS what reaches the
|
|
@@ -363,6 +470,16 @@ async function persistProjectEnv(projectDir, envRecord) {
|
|
|
363
470
|
const file = path.join(claudeDir, 'settings.local.json');
|
|
364
471
|
await fs.ensureDir(claudeDir);
|
|
365
472
|
|
|
473
|
+
// Ensure .claude/settings.local.json is in .gitignore before writing secrets
|
|
474
|
+
const gitignoreCheck = await ensureSettingsLocalIgnored(projectDir);
|
|
475
|
+
if (gitignoreCheck.added) {
|
|
476
|
+
await prompts.log.info('.claude/settings.local.json foi adicionado ao .gitignore do projeto (guarda API keys, não deve ir pro git).');
|
|
477
|
+
} else if (gitignoreCheck.reason === 'não é um repositório git') {
|
|
478
|
+
await prompts.log.warn(
|
|
479
|
+
'Este diretório não é um repositório git: garanta que .claude/settings.local.json (API keys) nunca seja versionado.',
|
|
480
|
+
);
|
|
481
|
+
}
|
|
482
|
+
|
|
366
483
|
let settings = {};
|
|
367
484
|
if (await fs.pathExists(file)) {
|
|
368
485
|
try {
|
|
@@ -642,4 +759,6 @@ module.exports = {
|
|
|
642
759
|
createGlobalStoreProvider,
|
|
643
760
|
defaultGlobalEnvPath,
|
|
644
761
|
formatSummary,
|
|
762
|
+
ensureSettingsLocalIgnored,
|
|
763
|
+
patternCoversSettingsLocal,
|
|
645
764
|
};
|