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,7 +1,7 @@
|
|
|
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 yaml = require('yaml');
|
|
6
6
|
const prompts = require('../prompts');
|
|
7
7
|
const { resolveChannel, tagExists, parseGitHubRepo } = require('./channel-resolver');
|
|
@@ -10,37 +10,20 @@ const { getProjectRoot } = require('../project-root');
|
|
|
10
10
|
|
|
11
11
|
const VALID_CHANNELS = new Set(['stable', 'next', 'pinned']);
|
|
12
12
|
|
|
13
|
-
//
|
|
14
|
-
//
|
|
15
|
-
//
|
|
16
|
-
//
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
// Atomics.wait sobre um buffer compartilhado, sem depender de `sleep` de shell.
|
|
28
|
-
function blockingDelay(ms) {
|
|
29
|
-
const sharedBuffer = new Int32Array(new SharedArrayBuffer(4));
|
|
30
|
-
Atomics.wait(sharedBuffer, 0, 0, ms);
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
// Wrapper de execSync com 1 re-tentativa em falha transitória de rede
|
|
34
|
-
// (ver isTransientGitError). Erro não-transitório propaga direto.
|
|
35
|
-
function execSyncWithRetry(command, options) {
|
|
36
|
-
try {
|
|
37
|
-
return execSync(command, options);
|
|
38
|
-
} catch (error) {
|
|
39
|
-
if (!isTransientGitError(error)) throw error;
|
|
40
|
-
blockingDelay(GIT_RETRY_DELAY_MS);
|
|
41
|
-
return execSync(command, options);
|
|
42
|
-
}
|
|
43
|
-
}
|
|
13
|
+
// Timeouts, retry e classificação transitória (ACH-01/EXT-01) moram em
|
|
14
|
+
// git-cache-utils.js (item 20, etapa 1 da auditoria de 2026-09-11) — uma
|
|
15
|
+
// fonte única compartilhada com custom-module-manager.js. Re-exportados daqui
|
|
16
|
+
// para callers/testes que já importavam de external-manager.
|
|
17
|
+
const {
|
|
18
|
+
GIT_NETWORK_TIMEOUT_MS,
|
|
19
|
+
GIT_LOCAL_TIMEOUT_MS,
|
|
20
|
+
NPM_INSTALL_TIMEOUT_MS,
|
|
21
|
+
isTimeoutKillError,
|
|
22
|
+
describeGitTimeout,
|
|
23
|
+
isTransientGitError,
|
|
24
|
+
execSyncWithRetry,
|
|
25
|
+
validateGitRef: validateShellRef,
|
|
26
|
+
} = require('./git-cache-utils');
|
|
44
27
|
|
|
45
28
|
function normalizeChannelName(raw) {
|
|
46
29
|
if (typeof raw !== 'string') return null;
|
|
@@ -48,17 +31,11 @@ function normalizeChannelName(raw) {
|
|
|
48
31
|
return VALID_CHANNELS.has(lower) ? lower : null;
|
|
49
32
|
}
|
|
50
33
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
function quoteShell(ref) {
|
|
57
|
-
if (typeof ref !== 'string' || !/^[\w.\-+/]+$/.test(ref)) {
|
|
58
|
-
throw new Error(`Unsafe ref name: ${JSON.stringify(ref)}`);
|
|
59
|
-
}
|
|
60
|
-
return `"${ref}"`;
|
|
61
|
-
}
|
|
34
|
+
// Item 8b (auditoria 2026-09-11): the TAG@SHA split + validation lives in
|
|
35
|
+
// pin-spec.js, shared with custom-module-manager.js (item 8c) and surfaced at
|
|
36
|
+
// the CLI gate by channel-plan.js — one format, one error message, three
|
|
37
|
+
// consumers. Re-exported here for existing callers/tests.
|
|
38
|
+
const { parsePinTagAndSha } = require('./pin-spec');
|
|
62
39
|
|
|
63
40
|
async function readChannelMarker(markerPath) {
|
|
64
41
|
try {
|
|
@@ -303,6 +280,18 @@ class ExternalModuleManager {
|
|
|
303
280
|
registryDefault: moduleInfo.defaultChannel,
|
|
304
281
|
});
|
|
305
282
|
|
|
283
|
+
// Item 8 fase 2 (auditoria 2026-09-11, EXT-02 / IM-ACH-06): --pin
|
|
284
|
+
// CODE=TAG@SHA. channel-plan.js only knows CODE=<opaque value>, so the
|
|
285
|
+
// TAG@SHA split (and its validation) happens here, before anything else
|
|
286
|
+
// in this function reads `planEntry.pin` as a git ref. From this point
|
|
287
|
+
// on `planEntry.pin` is always a plain tag name.
|
|
288
|
+
let expectedPinSha = null;
|
|
289
|
+
if (planEntry.channel === 'pinned' && planEntry.pin) {
|
|
290
|
+
const parsedPin = parsePinTagAndSha(planEntry.pin);
|
|
291
|
+
planEntry.pin = parsedPin.tag;
|
|
292
|
+
expectedPinSha = parsedPin.expectedSha;
|
|
293
|
+
}
|
|
294
|
+
|
|
306
295
|
// Same-plan short-circuit: a single install calls cloneExternalModule
|
|
307
296
|
// several times (config collection, directory setup, help-catalog rebuild)
|
|
308
297
|
// with the same channelOptions. The first call resolves + clones; later
|
|
@@ -311,7 +300,8 @@ class ExternalModuleManager {
|
|
|
311
300
|
// on flaky networks even though the tagCache dedupes the GitHub API hit).
|
|
312
301
|
if (existingResolution && haveUsableCache && existingResolution.channel === planEntry.channel) {
|
|
313
302
|
const samePin = planEntry.channel !== 'pinned' || existingResolution.version === planEntry.pin;
|
|
314
|
-
|
|
303
|
+
const sameExpectedSha = planEntry.channel !== 'pinned' || (existingResolution.expectedSha || null) === expectedPinSha;
|
|
304
|
+
if (samePin && sameExpectedSha) return moduleCacheDir;
|
|
315
305
|
}
|
|
316
306
|
|
|
317
307
|
let resolved;
|
|
@@ -399,33 +389,56 @@ class ExternalModuleManager {
|
|
|
399
389
|
const fetchSpinner = await createSpinner();
|
|
400
390
|
fetchSpinner.start(`Fetching ${moduleInfo.name}...`);
|
|
401
391
|
try {
|
|
402
|
-
const currentSha =
|
|
392
|
+
const currentSha = execFileSync('git', ['rev-parse', 'HEAD'], {
|
|
393
|
+
cwd: moduleCacheDir,
|
|
394
|
+
stdio: 'pipe',
|
|
395
|
+
timeout: GIT_LOCAL_TIMEOUT_MS,
|
|
396
|
+
killSignal: 'SIGKILL',
|
|
397
|
+
})
|
|
398
|
+
.toString()
|
|
399
|
+
.trim();
|
|
403
400
|
|
|
404
401
|
if (resolved.channel === 'next') {
|
|
405
|
-
execSyncWithRetry('git fetch origin --depth 1', {
|
|
402
|
+
execSyncWithRetry('git', ['fetch', 'origin', '--depth', '1'], {
|
|
406
403
|
cwd: moduleCacheDir,
|
|
407
404
|
stdio: ['ignore', 'pipe', 'pipe'],
|
|
408
405
|
env: { ...process.env, GIT_TERMINAL_PROMPT: '0' },
|
|
406
|
+
timeout: GIT_NETWORK_TIMEOUT_MS,
|
|
407
|
+
killSignal: 'SIGKILL',
|
|
409
408
|
});
|
|
410
|
-
|
|
409
|
+
execFileSync('git', ['reset', '--hard', 'origin/HEAD'], {
|
|
411
410
|
cwd: moduleCacheDir,
|
|
412
411
|
stdio: ['ignore', 'pipe', 'pipe'],
|
|
413
412
|
env: { ...process.env, GIT_TERMINAL_PROMPT: '0' },
|
|
413
|
+
timeout: GIT_LOCAL_TIMEOUT_MS,
|
|
414
|
+
killSignal: 'SIGKILL',
|
|
414
415
|
});
|
|
415
416
|
} else {
|
|
416
417
|
// stable or pinned — fetch the specific tag and check it out.
|
|
417
|
-
|
|
418
|
+
validateShellRef(resolved.ref);
|
|
419
|
+
execSyncWithRetry('git', ['fetch', '--depth', '1', 'origin', 'tag', resolved.ref, '--no-tags'], {
|
|
418
420
|
cwd: moduleCacheDir,
|
|
419
421
|
stdio: ['ignore', 'pipe', 'pipe'],
|
|
420
422
|
env: { ...process.env, GIT_TERMINAL_PROMPT: '0' },
|
|
423
|
+
timeout: GIT_NETWORK_TIMEOUT_MS,
|
|
424
|
+
killSignal: 'SIGKILL',
|
|
421
425
|
});
|
|
422
|
-
|
|
426
|
+
execFileSync('git', ['checkout', '--quiet', 'FETCH_HEAD'], {
|
|
423
427
|
cwd: moduleCacheDir,
|
|
424
428
|
stdio: ['ignore', 'pipe', 'pipe'],
|
|
429
|
+
timeout: GIT_LOCAL_TIMEOUT_MS,
|
|
430
|
+
killSignal: 'SIGKILL',
|
|
425
431
|
});
|
|
426
432
|
}
|
|
427
433
|
|
|
428
|
-
const newSha =
|
|
434
|
+
const newSha = execFileSync('git', ['rev-parse', 'HEAD'], {
|
|
435
|
+
cwd: moduleCacheDir,
|
|
436
|
+
stdio: 'pipe',
|
|
437
|
+
timeout: GIT_LOCAL_TIMEOUT_MS,
|
|
438
|
+
killSignal: 'SIGKILL',
|
|
439
|
+
})
|
|
440
|
+
.toString()
|
|
441
|
+
.trim();
|
|
429
442
|
fetchSpinner.stop(`Fetched ${moduleInfo.name}`);
|
|
430
443
|
if (currentSha !== newSha) needsDependencyInstall = true;
|
|
431
444
|
} catch {
|
|
@@ -442,35 +455,79 @@ class ExternalModuleManager {
|
|
|
442
455
|
fetchSpinner.start(`Fetching ${moduleInfo.name}...`);
|
|
443
456
|
try {
|
|
444
457
|
if (resolved.channel === 'next') {
|
|
445
|
-
execSyncWithRetry(
|
|
458
|
+
execSyncWithRetry('git', ['clone', '--depth', '1', moduleInfo.url, moduleCacheDir], {
|
|
446
459
|
stdio: ['ignore', 'pipe', 'pipe'],
|
|
447
460
|
env: { ...process.env, GIT_TERMINAL_PROMPT: '0' },
|
|
461
|
+
timeout: GIT_NETWORK_TIMEOUT_MS,
|
|
462
|
+
killSignal: 'SIGKILL',
|
|
448
463
|
});
|
|
449
464
|
} else {
|
|
450
|
-
|
|
465
|
+
validateShellRef(resolved.ref);
|
|
466
|
+
execSyncWithRetry('git', ['clone', '--depth', '1', '--branch', resolved.ref, moduleInfo.url, moduleCacheDir], {
|
|
451
467
|
stdio: ['ignore', 'pipe', 'pipe'],
|
|
452
468
|
env: { ...process.env, GIT_TERMINAL_PROMPT: '0' },
|
|
469
|
+
timeout: GIT_NETWORK_TIMEOUT_MS,
|
|
470
|
+
killSignal: 'SIGKILL',
|
|
453
471
|
});
|
|
454
472
|
}
|
|
455
473
|
fetchSpinner.stop(`Fetched ${moduleInfo.name}`);
|
|
456
474
|
} catch (error) {
|
|
457
475
|
fetchSpinner.error(`Failed to fetch ${moduleInfo.name}`);
|
|
458
|
-
throw new Error(
|
|
476
|
+
throw new Error(
|
|
477
|
+
`Failed to clone external module '${moduleCode}' at ${resolved.version}: ${error.message}${describeGitTimeout(error)}`,
|
|
478
|
+
);
|
|
459
479
|
}
|
|
460
480
|
}
|
|
461
481
|
|
|
462
482
|
// Record resolution (channel + tag + SHA) for the manifest writer to pick up.
|
|
463
|
-
const sha =
|
|
483
|
+
const sha = execFileSync('git', ['rev-parse', 'HEAD'], {
|
|
484
|
+
cwd: moduleCacheDir,
|
|
485
|
+
stdio: 'pipe',
|
|
486
|
+
timeout: GIT_LOCAL_TIMEOUT_MS,
|
|
487
|
+
killSignal: 'SIGKILL',
|
|
488
|
+
})
|
|
489
|
+
.toString()
|
|
490
|
+
.trim();
|
|
491
|
+
|
|
492
|
+
// Item 8 fase 2 (auditoria 2026-09-11, EXT-02 / IM-ACH-06): with --pin
|
|
493
|
+
// CODE=TAG@SHA, verify the commit we actually checked out matches what
|
|
494
|
+
// was requested. A git tag is a mutable ref — nothing stops the remote
|
|
495
|
+
// from force-moving it between installs — so this is a trust check, not
|
|
496
|
+
// a network hiccup: it must run before we record any resolution/marker
|
|
497
|
+
// a later run would trust, and it must never be retried as transient
|
|
498
|
+
// (compare isTransientGitError / isTimeoutKillError above, neither of
|
|
499
|
+
// which this error matches). On mismatch we remove the whole cache dir
|
|
500
|
+
// rather than leave a "cloned fine but at the wrong commit" checkout
|
|
501
|
+
// sitting there indistinguishable from a good one on the next run — the
|
|
502
|
+
// simplest safe option, and the same posture as the corrupted-cache
|
|
503
|
+
// cleanup earlier in this function (fetch-failed / EXT-03 branch above).
|
|
504
|
+
//
|
|
505
|
+
// Bug 3 (review da fase 3, 2026-09-11): strict equality, not a prefix
|
|
506
|
+
// compare — expectedSha is always the full 40-hex SHA (parsePinTagAndSha
|
|
507
|
+
// rejects anything shorter) and `sha` here is always a full 40-hex SHA.
|
|
508
|
+
if (expectedPinSha && sha.toLowerCase() !== expectedPinSha) {
|
|
509
|
+
await fs.remove(moduleCacheDir);
|
|
510
|
+
throw new Error(
|
|
511
|
+
`Tag '${planEntry.pin}' aponta para o SHA ${sha}, esperado ${expectedPinSha} (--pin ${moduleCode}=${planEntry.pin}@${expectedPinSha}); a tag pode ter sido movida no repositório remoto.`,
|
|
512
|
+
);
|
|
513
|
+
}
|
|
514
|
+
|
|
464
515
|
ExternalModuleManager._resolutions.set(moduleCode, {
|
|
465
516
|
channel: resolved.channel,
|
|
466
517
|
version: resolved.version,
|
|
467
518
|
ref: resolved.ref,
|
|
468
519
|
sha,
|
|
520
|
+
expectedSha: expectedPinSha,
|
|
469
521
|
repoUrl: moduleInfo.url,
|
|
470
522
|
resolvedFallback: !!resolved.resolvedFallback,
|
|
471
523
|
planSource: planEntry.source,
|
|
472
524
|
});
|
|
473
|
-
await writeChannelMarker(markerPath, {
|
|
525
|
+
await writeChannelMarker(markerPath, {
|
|
526
|
+
channel: resolved.channel,
|
|
527
|
+
version: resolved.version,
|
|
528
|
+
sha,
|
|
529
|
+
expectedSha: expectedPinSha,
|
|
530
|
+
});
|
|
474
531
|
|
|
475
532
|
// Install dependencies if package.json exists
|
|
476
533
|
const packageJsonPath = path.join(moduleCacheDir, 'package.json');
|
|
@@ -484,10 +541,13 @@ class ExternalModuleManager {
|
|
|
484
541
|
const installSpinner = await createSpinner();
|
|
485
542
|
installSpinner.start(`Installing dependencies for ${moduleInfo.name}...`);
|
|
486
543
|
try {
|
|
487
|
-
|
|
544
|
+
execFileSync('npm', ['install', '--omit=dev', '--no-audit', '--no-fund', '--no-progress', '--legacy-peer-deps'], {
|
|
545
|
+
// npm é npm.cmd no Windows e só roda via shell; os args acima são constantes, sem input do usuário.
|
|
546
|
+
shell: process.platform === 'win32',
|
|
488
547
|
cwd: moduleCacheDir,
|
|
489
548
|
stdio: ['ignore', 'pipe', 'pipe'],
|
|
490
|
-
timeout:
|
|
549
|
+
timeout: NPM_INSTALL_TIMEOUT_MS,
|
|
550
|
+
killSignal: 'SIGKILL',
|
|
491
551
|
});
|
|
492
552
|
installSpinner.stop(`Installed dependencies for ${moduleInfo.name}`);
|
|
493
553
|
} catch (error) {
|
|
@@ -510,10 +570,13 @@ class ExternalModuleManager {
|
|
|
510
570
|
const installSpinner = await createSpinner();
|
|
511
571
|
installSpinner.start(`Installing dependencies for ${moduleInfo.name}...`);
|
|
512
572
|
try {
|
|
513
|
-
|
|
573
|
+
execFileSync('npm', ['install', '--omit=dev', '--no-audit', '--no-fund', '--no-progress', '--legacy-peer-deps'], {
|
|
574
|
+
// npm é npm.cmd no Windows e só roda via shell; os args acima são constantes, sem input do usuário.
|
|
575
|
+
shell: process.platform === 'win32',
|
|
514
576
|
cwd: moduleCacheDir,
|
|
515
577
|
stdio: ['ignore', 'pipe', 'pipe'],
|
|
516
|
-
timeout:
|
|
578
|
+
timeout: NPM_INSTALL_TIMEOUT_MS,
|
|
579
|
+
killSignal: 'SIGKILL',
|
|
517
580
|
});
|
|
518
581
|
installSpinner.stop(`Installed dependencies for ${moduleInfo.name}`);
|
|
519
582
|
} catch (error) {
|
|
@@ -696,4 +759,14 @@ class ExternalModuleManager {
|
|
|
696
759
|
cachedModules = null;
|
|
697
760
|
}
|
|
698
761
|
|
|
699
|
-
module.exports = {
|
|
762
|
+
module.exports = {
|
|
763
|
+
ExternalModuleManager,
|
|
764
|
+
isTransientGitError,
|
|
765
|
+
execSyncWithRetry,
|
|
766
|
+
isTimeoutKillError,
|
|
767
|
+
describeGitTimeout,
|
|
768
|
+
GIT_NETWORK_TIMEOUT_MS,
|
|
769
|
+
GIT_LOCAL_TIMEOUT_MS,
|
|
770
|
+
NPM_INSTALL_TIMEOUT_MS,
|
|
771
|
+
parsePinTagAndSha,
|
|
772
|
+
};
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared primitives for the two git downloaders (external-manager.js and
|
|
3
|
+
* custom-module-manager.js) — item 20, etapa 1 (auditoria 2026-09-11).
|
|
4
|
+
*
|
|
5
|
+
* This module owns:
|
|
6
|
+
* - the ACH-01/EXT-01 timeout constants and the WIZZ_GIT_TIMEOUT_MS override
|
|
7
|
+
* - transient-error classification + `execSyncWithRetry` (1 re-tentativa)
|
|
8
|
+
* - the defensive ref-shape check (was duplicated as `validateShellRef` in
|
|
9
|
+
* external-manager.js and `validateCustomRef` in custom-module-manager.js)
|
|
10
|
+
*
|
|
11
|
+
* Policy-level decisions (channels, pins, cache layout, marker files) stay in
|
|
12
|
+
* each manager — this file deliberately knows nothing about them.
|
|
13
|
+
*
|
|
14
|
+
* `execFileSync` blocks Node's main thread with no built-in ceiling: a host
|
|
15
|
+
* that accepts the TCP connection and never responds (no RST — a network
|
|
16
|
+
* black hole) hangs the installer forever, with no message and no way out
|
|
17
|
+
* short of the user killing the process. Every git/npm `execFileSync` call in
|
|
18
|
+
* both managers must pass an explicit `timeout` (+ `killSignal: 'SIGKILL'`,
|
|
19
|
+
* since git can ignore SIGTERM while blocked on a syscall). `WIZZ_GIT_TIMEOUT_MS`
|
|
20
|
+
* lets a user on a slow/high-latency network raise the git timeouts without
|
|
21
|
+
* touching source; npm install's timeout is fixed — dependency install time
|
|
22
|
+
* is bounded by package.json, not by the network path to a single git remote,
|
|
23
|
+
* so it isn't part of the same override.
|
|
24
|
+
*/
|
|
25
|
+
|
|
26
|
+
const { execFileSync } = require('node:child_process');
|
|
27
|
+
|
|
28
|
+
function parseGitTimeoutOverride() {
|
|
29
|
+
const raw = process.env.WIZZ_GIT_TIMEOUT_MS;
|
|
30
|
+
if (raw === undefined || raw === '') return null;
|
|
31
|
+
const parsed = Number.parseInt(raw, 10);
|
|
32
|
+
return Number.isInteger(parsed) && parsed > 0 ? parsed : null;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const GIT_TIMEOUT_OVERRIDE_MS = parseGitTimeoutOverride();
|
|
36
|
+
// Network git ops: clone / fetch.
|
|
37
|
+
const GIT_NETWORK_TIMEOUT_MS = GIT_TIMEOUT_OVERRIDE_MS ?? 120_000;
|
|
38
|
+
// Local git ops: rev-parse, symbolic-ref, checkout, reset. No network
|
|
39
|
+
// round-trip, but still shelled out via execFileSync, so still needs a
|
|
40
|
+
// ceiling (a corrupted/locked local repo can hang git indefinitely too).
|
|
41
|
+
const GIT_LOCAL_TIMEOUT_MS = GIT_TIMEOUT_OVERRIDE_MS ?? 30_000;
|
|
42
|
+
// npm install for a module's own dependencies. Not affected by WIZZ_GIT_TIMEOUT_MS.
|
|
43
|
+
const NPM_INSTALL_TIMEOUT_MS = 300_000;
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* True when an execFileSync error is our own timeout kill: Node reports this
|
|
47
|
+
* via `error.killed`/`error.signal`, not through stdout/stderr text, so the
|
|
48
|
+
* message-pattern checks below never see it.
|
|
49
|
+
*/
|
|
50
|
+
function isTimeoutKillError(error) {
|
|
51
|
+
return !!(error && (error.killed === true || error.signal));
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* PT-BR hint appended to a final thrown/logged error when a git call timed
|
|
56
|
+
* out, pointing the user at the override env var.
|
|
57
|
+
*/
|
|
58
|
+
function describeGitTimeout(error) {
|
|
59
|
+
if (!isTimeoutKillError(error)) return '';
|
|
60
|
+
return ` O comando git estourou o tempo limite (${error.signal || 'timeout'}). Se sua rede é lenta, ajuste com a variável de ambiente WIZZ_GIT_TIMEOUT_MS (em milissegundos).`;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// Retry pontual (1 re-tentativa, backoff curto) para `git clone`/`git fetch`.
|
|
64
|
+
// Para comandos de shell não temos código de erro estruturado como em
|
|
65
|
+
// requisições HTTP; classificamos como transitório por padrões conhecidos na
|
|
66
|
+
// mensagem/stderr do git, OU por ter sido morto pelo nosso próprio `timeout`
|
|
67
|
+
// (error.killed/error.signal — ver isTimeoutKillError). Erro lógico (repo/tag
|
|
68
|
+
// inexistente, permissão negada etc.) não bate em nenhum dos dois e propaga
|
|
69
|
+
// direto, sem retry.
|
|
70
|
+
const GIT_RETRY_DELAY_MS = 300;
|
|
71
|
+
const TRANSIENT_GIT_ERROR_PATTERNS = [/could not resolve host/i, /timed out/i, /early eof/i, /connection reset/i];
|
|
72
|
+
|
|
73
|
+
function isTransientGitError(error) {
|
|
74
|
+
if (isTimeoutKillError(error)) return true;
|
|
75
|
+
const message = `${error?.message || ''}\n${error?.stderr?.toString?.() || ''}`;
|
|
76
|
+
return TRANSIENT_GIT_ERROR_PATTERNS.some((pattern) => pattern.test(message));
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// Sleep síncrono curto (execSync é bloqueante; não há await aqui). Usa
|
|
80
|
+
// Atomics.wait sobre um buffer compartilhado, sem depender de `sleep` de shell.
|
|
81
|
+
function blockingDelay(ms) {
|
|
82
|
+
const sharedBuffer = new Int32Array(new SharedArrayBuffer(4));
|
|
83
|
+
Atomics.wait(sharedBuffer, 0, 0, ms);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// Wrapper de execFileSync com 1 re-tentativa em falha transitória de rede
|
|
87
|
+
// (ver isTransientGitError). Erro não-transitório propaga direto.
|
|
88
|
+
// Assinatura (file, args, options) — array de argumentos, nunca uma string
|
|
89
|
+
// de shell — para que nenhum call site precise (nem consiga) interpolar URL
|
|
90
|
+
// ou ref não sanitizada dentro de um comando de shell (ver EXT-09).
|
|
91
|
+
function execSyncWithRetry(file, args, options) {
|
|
92
|
+
try {
|
|
93
|
+
return execFileSync(file, args, options);
|
|
94
|
+
} catch (error) {
|
|
95
|
+
if (!isTransientGitError(error)) throw error;
|
|
96
|
+
blockingDelay(GIT_RETRY_DELAY_MS);
|
|
97
|
+
return execFileSync(file, args, options);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Conservative validation for tag/branch names passed to git commands. Refs
|
|
103
|
+
* are user-typed (--pin, --next, version from a /tree/ URL) or come from the
|
|
104
|
+
* GitHub API. Refs reach `execFileSync('git', [...])` as a single argv
|
|
105
|
+
* element (no shell), so this isn't shell-quoting anymore — it's a defensive
|
|
106
|
+
* shape check so a malformed ref fails loudly instead of confusing `git`.
|
|
107
|
+
*/
|
|
108
|
+
function validateGitRef(ref) {
|
|
109
|
+
// Ref que começa com '-' viraria opção do git (ex.: --upload-pack): rejeitar.
|
|
110
|
+
if (typeof ref !== 'string' || ref.startsWith('-') || !/^[\w.\-+/]+$/.test(ref)) {
|
|
111
|
+
throw new Error(`Unsafe ref name: ${JSON.stringify(ref)}`);
|
|
112
|
+
}
|
|
113
|
+
return ref;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
module.exports = {
|
|
117
|
+
GIT_NETWORK_TIMEOUT_MS,
|
|
118
|
+
GIT_LOCAL_TIMEOUT_MS,
|
|
119
|
+
NPM_INSTALL_TIMEOUT_MS,
|
|
120
|
+
isTimeoutKillError,
|
|
121
|
+
describeGitTimeout,
|
|
122
|
+
isTransientGitError,
|
|
123
|
+
execSyncWithRetry,
|
|
124
|
+
validateGitRef,
|
|
125
|
+
};
|