wizz-method 1.4.1 → 1.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +6 -4
- package/package.json +39 -3
- package/skills-registry.yaml +102 -7
- package/src/bmm-skills/4-implementation/wizz-code-review/SKILL.md +2 -0
- package/src/bmm-skills/4-implementation/wizz-quick-dev/SKILL.md +5 -2
- package/src/core-skills/_shared/handoff-protocol.md +61 -0
- package/src/core-skills/wizz-customize/SKILL.md +2 -2
- package/src/core-skills/wizz-party-mode/references/mode-agent-team.md +1 -1
- package/src/core-skills/wizz-party-mode/references/mode-subagent.md +1 -1
- package/src/core-skills/wizz-review-adversarial-general/SKILL.md +2 -0
- package/src/modules/wizz/README.md +3 -3
- package/src/modules/wizz/_shared/communication-rules.md +13 -0
- package/src/modules/wizz/_shared/encerramento.md +2 -2
- package/src/modules/wizz/agents/wizz-ads/customize.toml +5 -3
- package/src/modules/wizz/agents/wizz-copy/customize.toml +5 -3
- package/src/modules/wizz/agents/wizz-designer/SKILL.md +2 -2
- package/src/modules/wizz/agents/wizz-designer/customize.toml +6 -4
- package/src/modules/wizz/agents/wizz-growth/customize.toml +11 -3
- package/src/modules/wizz/agents/wizz-maestro/SKILL.md +9 -5
- package/src/modules/wizz/agents/wizz-maestro/customize.toml +5 -7
- package/src/modules/wizz/agents/wizz-memoria/customize.toml +2 -4
- package/src/modules/wizz/agents/wizz-qa/SKILL.md +5 -5
- package/src/modules/wizz/agents/wizz-qa/customize.toml +9 -7
- package/src/modules/wizz/agents/wizz-seo/customize.toml +5 -3
- package/src/modules/wizz/agents/wizz-social/customize.toml +9 -8
- package/src/modules/wizz/module.yaml +1 -1
- package/src/modules/wizz/overrides/wizz-agent-analyst.toml +4 -5
- package/src/modules/wizz/overrides/wizz-agent-architect.toml +11 -3
- package/src/modules/wizz/overrides/wizz-agent-dev.toml +6 -4
- package/src/modules/wizz/overrides/wizz-agent-pm.toml +4 -2
- package/src/modules/wizz/overrides/wizz-agent-tech-writer.toml +3 -5
- package/src/modules/wizz/overrides/wizz-agent-ux-designer.toml +4 -2
- package/src/modules/wizz/scripts/wizz-init.mjs +3 -1
- package/src/scripts/__pycache__/resolve_customization.cpython-314.pyc +0 -0
- package/src/scripts/memlog.py +9 -0
- package/src/scripts/resolve_customization.py +93 -3
- package/src/skills-lib/adversarial-reviewer/SKILL.md +2 -0
- package/src/skills-lib/algorithmic-art/SKILL.md +29 -369
- package/src/skills-lib/algorithmic-art/references/interactive-artifact.md +139 -0
- package/src/skills-lib/algorithmic-art/references/p5js-implementation.md +121 -0
- package/src/skills-lib/algorithmic-art/references/philosophy-creation.md +88 -0
- package/src/skills-lib/canvas-design/SKILL.md +9 -38
- package/src/skills-lib/canvas-design/references/canvas-execution.md +21 -0
- package/src/skills-lib/canvas-design/references/philosophy-examples.md +25 -0
- package/src/skills-lib/cerebro/SKILL.md +8 -273
- package/src/skills-lib/cerebro/references/comandos-pesquisa-e-sync.md +44 -0
- package/src/skills-lib/cerebro/references/comandos-rotina-e-captura.md +94 -0
- package/src/skills-lib/cerebro/references/comandos-sessao.md +122 -0
- package/src/skills-lib/content-strategy/SKILL.md +12 -316
- package/src/skills-lib/content-strategy/references/content-types.md +52 -0
- package/src/skills-lib/content-strategy/references/ideation-sources.md +78 -0
- package/src/skills-lib/content-strategy/references/pillars-and-keywords.md +78 -0
- package/src/skills-lib/content-strategy/references/prioritization-and-output.md +57 -0
- package/src/skills-lib/decision-maker/SKILL.md +13 -466
- package/src/skills-lib/decision-maker/references/commands-and-edge-cases.md +40 -0
- package/src/skills-lib/decision-maker/references/output-format.md +161 -0
- package/src/skills-lib/decision-maker/references/references-and-extraction.md +129 -0
- package/src/skills-lib/decision-maker/references/six-decisions.md +122 -0
- package/src/skills-lib/decision-maker/references/wizz-method-handoff.md +22 -0
- package/src/skills-lib/find-skills/SKILL.md +9 -6
- package/src/skills-lib/form-cro/SKILL.md +12 -390
- package/src/skills-lib/form-cro/references/experiments.md +73 -0
- package/src/skills-lib/form-cro/references/field-optimization.md +92 -0
- package/src/skills-lib/form-cro/references/flow-and-errors.md +71 -0
- package/src/skills-lib/form-cro/references/measurement-output.md +41 -0
- package/src/skills-lib/form-cro/references/trust-and-form-types.md +54 -0
- package/src/skills-lib/graphify/SKILL.md +2 -20
- package/src/skills-lib/huashu-design/SKILL.md +42 -596
- package/src/skills-lib/huashu-design/references/anti-slop-principles.md +62 -0
- package/src/skills-lib/huashu-design/references/audio-design-rules.md +1 -1
- package/src/skills-lib/huashu-design/references/cross-agent-adaptation.md +14 -0
- package/src/skills-lib/huashu-design/references/design-direction-fallback.md +113 -0
- package/src/skills-lib/huashu-design/references/exception-handling.md +18 -0
- package/src/skills-lib/huashu-design/references/fact-verification.md +36 -0
- package/src/skills-lib/huashu-design/references/ios-prototype.md +146 -0
- package/src/skills-lib/huashu-design/references/sfx-library.md +7 -0
- package/src/skills-lib/huashu-design/references/starter-components.md +24 -0
- package/src/skills-lib/huashu-design/references/video-export.md +1 -1
- package/src/skills-lib/huashu-design/references/watermark-policy.md +23 -0
- package/src/skills-lib/huashu-design/scripts/add-music.sh +12 -1
- package/src/skills-lib/huashu-design/scripts/mix-voiceover.sh +11 -0
- package/src/skills-lib/humanizer/SKILL.md +23 -431
- package/src/skills-lib/humanizer/references/ai-writing-patterns.md +314 -0
- package/src/skills-lib/humanizer/references/full-example.md +72 -0
- package/src/skills-lib/humanizer/references/personality-and-soul.md +36 -0
- package/src/skills-lib/impeccable/SKILL.md +37 -153
- package/src/skills-lib/impeccable/references/design-rules.md +95 -0
- package/src/skills-lib/impeccable/references/pin-unpin-and-hooks.md +17 -0
- package/src/skills-lib/impeccable/references/routing-rules.md +28 -0
- package/src/skills-lib/implementation-planner/SKILL.md +22 -529
- package/src/skills-lib/implementation-planner/references/folder-structure-and-dependencies.md +132 -0
- package/src/skills-lib/implementation-planner/references/handoff-template.md +34 -0
- package/src/skills-lib/implementation-planner/references/implementation-phases.md +54 -0
- package/src/skills-lib/implementation-planner/references/implementation-types.md +28 -0
- package/src/skills-lib/implementation-planner/references/motion-path-implementation.md +57 -0
- package/src/skills-lib/implementation-planner/references/output-templates.md +92 -0
- package/src/skills-lib/implementation-planner/references/performance-plan.md +52 -0
- package/src/skills-lib/inicio-de-projeto/SKILL.md +4 -224
- package/src/skills-lib/inicio-de-projeto/references/implementacao-api-forms.md +112 -0
- package/src/skills-lib/inicio-de-projeto/references/padroes-arquiteturais-e-pastas.md +71 -0
- package/src/skills-lib/inicio-de-projeto/references/seguranca-e-regras-codigo.md +26 -0
- package/src/skills-lib/launch-strategy/SKILL.md +9 -311
- package/src/skills-lib/launch-strategy/references/five-phase-approach.md +76 -0
- package/src/skills-lib/launch-strategy/references/launch-checklist.md +34 -0
- package/src/skills-lib/launch-strategy/references/orb-framework.md +76 -0
- package/src/skills-lib/launch-strategy/references/post-launch-and-ongoing.md +64 -0
- package/src/skills-lib/launch-strategy/references/product-hunt-strategy.md +52 -0
- package/src/skills-lib/marketing-psychology/SKILL.md +18 -401
- package/src/skills-lib/marketing-psychology/references/design-and-delivery-models.md +56 -0
- package/src/skills-lib/marketing-psychology/references/foundational-thinking-models.md +76 -0
- package/src/skills-lib/marketing-psychology/references/growth-and-scaling-models.md +46 -0
- package/src/skills-lib/marketing-psychology/references/influencing-behavior.md +71 -0
- package/src/skills-lib/marketing-psychology/references/pricing-psychology.md +31 -0
- package/src/skills-lib/marketing-psychology/references/understanding-buyers.md +116 -0
- package/src/skills-lib/motion-3d-director/SKILL.md +23 -370
- package/src/skills-lib/motion-3d-director/references/image-to-video-workflow.md +166 -0
- package/src/skills-lib/motion-3d-director/references/motion-paths.md +119 -0
- package/src/skills-lib/motion-3d-director/references/performance-and-handoff.md +51 -0
- package/src/skills-lib/popup-cro/SKILL.md +11 -414
- package/src/skills-lib/popup-cro/references/design-copy-compliance.md +81 -0
- package/src/skills-lib/popup-cro/references/experiments.md +82 -0
- package/src/skills-lib/popup-cro/references/rules-measurement-output.md +87 -0
- package/src/skills-lib/popup-cro/references/triggers-and-popup-types.md +108 -0
- package/src/skills-lib/signup-flow-cro/SKILL.md +13 -321
- package/src/skills-lib/signup-flow-cro/references/experiments.md +72 -0
- package/src/skills-lib/signup-flow-cro/references/field-optimization.md +49 -0
- package/src/skills-lib/signup-flow-cro/references/flow-structure.md +38 -0
- package/src/skills-lib/signup-flow-cro/references/measurement-output-patterns.md +62 -0
- package/src/skills-lib/signup-flow-cro/references/trust-and-post-submit.md +40 -0
- package/src/skills-lib/taste-redesign/SKILL.md +10 -146
- package/src/skills-lib/taste-redesign/references/design-audit.md +120 -0
- package/src/skills-lib/taste-redesign/references/upgrade-techniques.md +31 -0
- package/src/skills-lib/ui-ux-pro-max/SKILL.md +9 -353
- package/src/skills-lib/ui-ux-pro-max/references/common-rules-checklist.md +76 -0
- package/src/skills-lib/ui-ux-pro-max/references/rules-quick-reference.md +70 -0
- package/src/skills-lib/ui-ux-pro-max/references/search-reference.md +45 -0
- package/src/skills-lib/ui-ux-pro-max/references/workflow-guide.md +157 -0
- package/src/skills-lib/web-security/SKILL.md +13 -187
- package/src/skills-lib/web-security/references/checklist-deploy.md +52 -0
- package/src/skills-lib/web-security/references/headers-rate-limit-cors.md +78 -0
- package/src/skills-lib/web-security/references/owasp-top5-detalhado.md +51 -0
- package/src/skills-lib/wizz-router/SKILL.md +20 -9
- package/src/skills-lib/wizz-router/references/auditoria-360.md +4 -4
- package/src/skills-lib/wizz-router/references/routing-table-flat.md +15 -15
- package/tools/fetch-assets.mjs +277 -0
- package/tools/installer/commands/fetch-assets.js +71 -0
- package/tools/installer/commands/install.js +35 -3
- package/tools/installer/commands/trace-report.js +131 -0
- package/tools/installer/core/config.js +9 -0
- package/tools/installer/core/help-catalog.js +181 -0
- package/tools/installer/core/install-paths.js +48 -3
- package/tools/installer/core/installer.js +253 -618
- package/tools/installer/core/manifest-generator.js +8 -1
- package/tools/installer/core/manifest.js +67 -22
- package/tools/installer/core/module-config-writer.js +110 -0
- package/tools/installer/core/preflight-tools-check.js +82 -0
- package/tools/installer/core/quick-update.js +209 -0
- package/tools/installer/core/user-file-preservation.js +250 -0
- package/tools/installer/modules/channel-resolver.js +34 -2
- package/tools/installer/modules/cli-config.js +127 -34
- package/tools/installer/modules/deps-cache.js +28 -1
- package/tools/installer/modules/env-vars.js +446 -0
- package/tools/installer/modules/external-manager.js +40 -6
- package/tools/installer/modules/mcp-config.js +180 -37
- package/tools/installer/modules/module-help-schema.js +2 -1
- package/tools/installer/modules/official-modules.js +1 -1
- package/tools/installer/modules/registry-resolve.js +74 -0
- package/tools/installer/modules/skills-lib.js +11 -15
- package/tools/installer/ui.js +71 -5
- package/wizz-modules.yaml +15 -5
- package/.claude-plugin/marketplace.json +0 -80
- package/AGENTS.md +0 -12
- package/build/artifacts/llms-full.txt +0 -4049
- package/build/artifacts/llms.txt +0 -28
- package/build/site/404.html +0 -55
- package/build/site/_astro/MobileTableOfContents.astro_astro_type_script_index_0_lang.hwBsy0Mo.js +0 -1
- package/build/site/_astro/Search.astro_astro_type_script_index_0_lang.cjYDvRdi.js +0 -1
- package/build/site/_astro/TableOfContents.astro_astro_type_script_index_0_lang.FuRcXuRY.js +0 -1
- package/build/site/_astro/ec.0vx5m.js +0 -3
- package/build/site/_astro/ec.v4551.css +0 -1
- package/build/site/_astro/index.DdjI3lF_.css +0 -1
- package/build/site/_astro/page.B1D-nYk3.js +0 -1
- package/build/site/_astro/print.DNXP8c50.css +0 -1
- package/build/site/_astro/ui-core.D_Lfcn_I.js +0 -2
- package/build/site/diagrams/checkpoint-preview-diagram-fr.webp +0 -0
- package/build/site/diagrams/checkpoint-preview-diagram.png +0 -0
- package/build/site/diagrams/quick-dev-diagram-fr.webp +0 -0
- package/build/site/diagrams/quick-dev-diagram.png +0 -0
- package/build/site/explanation/advanced-elicitation/index.html +0 -105
- package/build/site/explanation/adversarial-review/index.html +0 -109
- package/build/site/explanation/analysis-phase/index.html +0 -129
- package/build/site/explanation/brainstorming/index.html +0 -92
- package/build/site/explanation/checkpoint-preview/index.html +0 -121
- package/build/site/explanation/established-projects-faq/index.html +0 -107
- package/build/site/explanation/forensic-investigation/index.html +0 -167
- package/build/site/explanation/named-agents/index.html +0 -187
- package/build/site/explanation/party-mode/index.html +0 -256
- package/build/site/explanation/preventing-agent-conflicts/index.html +0 -185
- package/build/site/explanation/project-context/index.html +0 -198
- package/build/site/explanation/quick-dev/index.html +0 -113
- package/build/site/explanation/web-bundles/index.html +0 -178
- package/build/site/explanation/why-solutioning-matters/index.html +0 -168
- package/build/site/how-to/customize-wizz/index.html +0 -277
- package/build/site/how-to/established-projects/index.html +0 -165
- package/build/site/how-to/expand-wizz-for-your-org/index.html +0 -245
- package/build/site/how-to/get-answers-about-wizz/index.html +0 -129
- package/build/site/how-to/install-custom-modules/index.html +0 -197
- package/build/site/how-to/install-wizz/index.html +0 -330
- package/build/site/how-to/non-interactive-installation/index.html +0 -73
- package/build/site/how-to/project-context/index.html +0 -141
- package/build/site/how-to/quick-fixes/index.html +0 -122
- package/build/site/how-to/shard-large-documents/index.html +0 -103
- package/build/site/how-to/upgrade-to-v6/index.html +0 -185
- package/build/site/how-to/use-web-bundles/index.html +0 -99
- package/build/site/img/wizz-dark.png +0 -0
- package/build/site/img/wizz-light.png +0 -0
- package/build/site/index.html +0 -128
- package/build/site/llms-full.txt +0 -4049
- package/build/site/llms.txt +0 -28
- package/build/site/pagefind/fragment/en_175de32.pf_fragment +0 -0
- package/build/site/pagefind/fragment/en_24258fb.pf_fragment +0 -0
- package/build/site/pagefind/fragment/en_24f53a6.pf_fragment +0 -0
- package/build/site/pagefind/fragment/en_27ba8f9.pf_fragment +0 -0
- package/build/site/pagefind/fragment/en_296ddb9.pf_fragment +0 -0
- package/build/site/pagefind/fragment/en_2b5aa5c.pf_fragment +0 -0
- package/build/site/pagefind/fragment/en_49047e0.pf_fragment +0 -0
- package/build/site/pagefind/fragment/en_4a187d2.pf_fragment +0 -0
- package/build/site/pagefind/fragment/en_514725b.pf_fragment +0 -0
- package/build/site/pagefind/fragment/en_583316f.pf_fragment +0 -0
- package/build/site/pagefind/fragment/en_6465dfb.pf_fragment +0 -0
- package/build/site/pagefind/fragment/en_67825a4.pf_fragment +0 -0
- package/build/site/pagefind/fragment/en_82aec61.pf_fragment +0 -0
- package/build/site/pagefind/fragment/en_85dcebf.pf_fragment +0 -0
- package/build/site/pagefind/fragment/en_887ce56.pf_fragment +0 -0
- package/build/site/pagefind/fragment/en_89a1a7a.pf_fragment +0 -0
- package/build/site/pagefind/fragment/en_8ade291.pf_fragment +0 -0
- package/build/site/pagefind/fragment/en_8c11f8a.pf_fragment +0 -0
- package/build/site/pagefind/fragment/en_8c1bde3.pf_fragment +0 -0
- package/build/site/pagefind/fragment/en_92d7cc7.pf_fragment +0 -0
- package/build/site/pagefind/fragment/en_94bfc21.pf_fragment +0 -0
- package/build/site/pagefind/fragment/en_9b57d7d.pf_fragment +0 -0
- package/build/site/pagefind/fragment/en_ab62b53.pf_fragment +0 -0
- package/build/site/pagefind/fragment/en_b0d23ee.pf_fragment +0 -0
- package/build/site/pagefind/fragment/en_ba9fb37.pf_fragment +0 -0
- package/build/site/pagefind/fragment/en_bb113eb.pf_fragment +0 -0
- package/build/site/pagefind/fragment/en_bfc56b6.pf_fragment +0 -0
- package/build/site/pagefind/fragment/en_c6d9e48.pf_fragment +0 -0
- package/build/site/pagefind/fragment/en_cdd772f.pf_fragment +0 -0
- package/build/site/pagefind/fragment/en_cdd885c.pf_fragment +0 -0
- package/build/site/pagefind/fragment/en_cefed6a.pf_fragment +0 -0
- package/build/site/pagefind/fragment/en_d890205.pf_fragment +0 -0
- package/build/site/pagefind/fragment/en_da351b7.pf_fragment +0 -0
- package/build/site/pagefind/fragment/en_ea289f9.pf_fragment +0 -0
- package/build/site/pagefind/fragment/en_f1c3711.pf_fragment +0 -0
- package/build/site/pagefind/index/en_5b9d8c6.pf_index +0 -0
- package/build/site/pagefind/index/en_868614c.pf_index +0 -0
- package/build/site/pagefind/index/en_e4f9bff.pf_index +0 -0
- package/build/site/pagefind/pagefind-entry.json +0 -1
- package/build/site/pagefind/pagefind-highlight.js +0 -1064
- package/build/site/pagefind/pagefind-modular-ui.css +0 -214
- package/build/site/pagefind/pagefind-modular-ui.js +0 -8
- package/build/site/pagefind/pagefind-ui.css +0 -1
- package/build/site/pagefind/pagefind-ui.js +0 -2
- package/build/site/pagefind/pagefind.en_4e69d7f053.pf_meta +0 -0
- package/build/site/pagefind/pagefind.js +0 -6
- package/build/site/pagefind/wasm.en.pagefind +0 -0
- package/build/site/pagefind/wasm.unknown.pagefind +0 -0
- package/build/site/reference/agents/index.html +0 -168
- package/build/site/reference/commands/index.html +0 -254
- package/build/site/reference/core-tools/index.html +0 -384
- package/build/site/reference/modules/index.html +0 -132
- package/build/site/reference/testing/index.html +0 -218
- package/build/site/reference/workflow-map/index.html +0 -266
- package/build/site/roadmap/index.html +0 -77
- package/build/site/robots.txt +0 -37
- package/build/site/sitemap-0.xml +0 -1
- package/build/site/sitemap-index.xml +0 -1
- package/build/site/tutorials/getting-started/index.html +0 -386
- package/build/site/wizz-icon-orange.svg +0 -7
- package/build/site/workflow-map-diagram-fr.html +0 -375
- package/build/site/workflow-map-diagram.html +0 -375
- package/evals/bmm-skills/wizz-product-brief/evals.json +0 -237
- package/evals/bmm-skills/wizz-product-brief/files/branfield-memo.md +0 -46
- package/evals/bmm-skills/wizz-product-brief/files/forkbird-brief/addendum.md +0 -40
- package/evals/bmm-skills/wizz-product-brief/files/forkbird-brief/brief.md +0 -56
- package/evals/bmm-skills/wizz-product-brief/files/forkbird-brief/decision-log.md +0 -27
- package/evals/bmm-skills/wizz-product-brief/files/meridian-mobility-report.md +0 -116
- package/evals/bmm-skills/wizz-product-brief/files/mossridge-brief/addendum.md +0 -41
- package/evals/bmm-skills/wizz-product-brief/files/mossridge-brief/brief.md +0 -57
- package/evals/bmm-skills/wizz-product-brief/files/mossridge-brief/decision-log.md +0 -29
- package/evals/bmm-skills/wizz-product-brief/files/pantry-bridge-interviews.md +0 -90
- package/evals/bmm-skills/wizz-product-brief/files/q2-brainstorm.md +0 -101
- package/evals/bmm-skills/wizz-product-brief/triggers.json +0 -18
- package/evals/routing/dataset.json +0 -290
- package/evals/routing/run-routing-eval.mjs +0 -89
- package/src/skills-lib/canvas-design/canvas-fonts/ArsenalSC-Regular.ttf +0 -0
- package/src/skills-lib/canvas-design/canvas-fonts/BigShoulders-Bold.ttf +0 -0
- package/src/skills-lib/canvas-design/canvas-fonts/BigShoulders-Regular.ttf +0 -0
- package/src/skills-lib/canvas-design/canvas-fonts/Boldonse-Regular.ttf +0 -0
- package/src/skills-lib/canvas-design/canvas-fonts/BricolageGrotesque-Bold.ttf +0 -0
- package/src/skills-lib/canvas-design/canvas-fonts/BricolageGrotesque-Regular.ttf +0 -0
- package/src/skills-lib/canvas-design/canvas-fonts/CrimsonPro-Bold.ttf +0 -0
- package/src/skills-lib/canvas-design/canvas-fonts/CrimsonPro-Italic.ttf +0 -0
- package/src/skills-lib/canvas-design/canvas-fonts/CrimsonPro-Regular.ttf +0 -0
- package/src/skills-lib/canvas-design/canvas-fonts/DMMono-Regular.ttf +0 -0
- package/src/skills-lib/canvas-design/canvas-fonts/EricaOne-Regular.ttf +0 -0
- package/src/skills-lib/canvas-design/canvas-fonts/GeistMono-Bold.ttf +0 -0
- package/src/skills-lib/canvas-design/canvas-fonts/GeistMono-Regular.ttf +0 -0
- package/src/skills-lib/canvas-design/canvas-fonts/Gloock-Regular.ttf +0 -0
- package/src/skills-lib/canvas-design/canvas-fonts/IBMPlexMono-Bold.ttf +0 -0
- package/src/skills-lib/canvas-design/canvas-fonts/IBMPlexMono-Regular.ttf +0 -0
- package/src/skills-lib/canvas-design/canvas-fonts/IBMPlexSerif-Bold.ttf +0 -0
- package/src/skills-lib/canvas-design/canvas-fonts/IBMPlexSerif-BoldItalic.ttf +0 -0
- package/src/skills-lib/canvas-design/canvas-fonts/IBMPlexSerif-Italic.ttf +0 -0
- package/src/skills-lib/canvas-design/canvas-fonts/IBMPlexSerif-Regular.ttf +0 -0
- package/src/skills-lib/canvas-design/canvas-fonts/InstrumentSans-Bold.ttf +0 -0
- package/src/skills-lib/canvas-design/canvas-fonts/InstrumentSans-BoldItalic.ttf +0 -0
- package/src/skills-lib/canvas-design/canvas-fonts/InstrumentSans-Italic.ttf +0 -0
- package/src/skills-lib/canvas-design/canvas-fonts/InstrumentSans-Regular.ttf +0 -0
- package/src/skills-lib/canvas-design/canvas-fonts/InstrumentSerif-Italic.ttf +0 -0
- package/src/skills-lib/canvas-design/canvas-fonts/InstrumentSerif-Regular.ttf +0 -0
- package/src/skills-lib/canvas-design/canvas-fonts/Italiana-Regular.ttf +0 -0
- package/src/skills-lib/canvas-design/canvas-fonts/JetBrainsMono-Bold.ttf +0 -0
- package/src/skills-lib/canvas-design/canvas-fonts/JetBrainsMono-Regular.ttf +0 -0
- package/src/skills-lib/canvas-design/canvas-fonts/Jura-Light.ttf +0 -0
- package/src/skills-lib/canvas-design/canvas-fonts/Jura-Medium.ttf +0 -0
- package/src/skills-lib/canvas-design/canvas-fonts/LibreBaskerville-Regular.ttf +0 -0
- package/src/skills-lib/canvas-design/canvas-fonts/Lora-Bold.ttf +0 -0
- package/src/skills-lib/canvas-design/canvas-fonts/Lora-BoldItalic.ttf +0 -0
- package/src/skills-lib/canvas-design/canvas-fonts/Lora-Italic.ttf +0 -0
- package/src/skills-lib/canvas-design/canvas-fonts/Lora-Regular.ttf +0 -0
- package/src/skills-lib/canvas-design/canvas-fonts/NationalPark-Bold.ttf +0 -0
- package/src/skills-lib/canvas-design/canvas-fonts/NationalPark-Regular.ttf +0 -0
- package/src/skills-lib/canvas-design/canvas-fonts/NothingYouCouldDo-Regular.ttf +0 -0
- package/src/skills-lib/canvas-design/canvas-fonts/Outfit-Bold.ttf +0 -0
- package/src/skills-lib/canvas-design/canvas-fonts/Outfit-Regular.ttf +0 -0
- package/src/skills-lib/canvas-design/canvas-fonts/PixelifySans-Medium.ttf +0 -0
- package/src/skills-lib/canvas-design/canvas-fonts/PoiretOne-Regular.ttf +0 -0
- package/src/skills-lib/canvas-design/canvas-fonts/RedHatMono-Bold.ttf +0 -0
- package/src/skills-lib/canvas-design/canvas-fonts/RedHatMono-Regular.ttf +0 -0
- package/src/skills-lib/canvas-design/canvas-fonts/Silkscreen-Regular.ttf +0 -0
- package/src/skills-lib/canvas-design/canvas-fonts/SmoochSans-Medium.ttf +0 -0
- package/src/skills-lib/canvas-design/canvas-fonts/Tektur-Medium.ttf +0 -0
- package/src/skills-lib/canvas-design/canvas-fonts/Tektur-Regular.ttf +0 -0
- package/src/skills-lib/canvas-design/canvas-fonts/WorkSans-Bold.ttf +0 -0
- package/src/skills-lib/canvas-design/canvas-fonts/WorkSans-BoldItalic.ttf +0 -0
- package/src/skills-lib/canvas-design/canvas-fonts/WorkSans-Italic.ttf +0 -0
- package/src/skills-lib/canvas-design/canvas-fonts/WorkSans-Regular.ttf +0 -0
- package/src/skills-lib/canvas-design/canvas-fonts/YoungSerif-Regular.ttf +0 -0
- package/src/skills-lib/huashu-design/assets/bgm-ad.mp3 +0 -0
- package/src/skills-lib/huashu-design/assets/bgm-educational-alt.mp3 +0 -0
- package/src/skills-lib/huashu-design/assets/bgm-educational.mp3 +0 -0
- package/src/skills-lib/huashu-design/assets/bgm-tech.mp3 +0 -0
- package/src/skills-lib/huashu-design/assets/bgm-tutorial-alt.mp3 +0 -0
- package/src/skills-lib/huashu-design/assets/bgm-tutorial.mp3 +0 -0
- package/src/skills-lib/huashu-design/assets/sfx/container/card-flip.mp3 +0 -0
- package/src/skills-lib/huashu-design/assets/sfx/container/card-snap.mp3 +0 -0
- package/src/skills-lib/huashu-design/assets/sfx/container/modal-open.mp3 +0 -0
- package/src/skills-lib/huashu-design/assets/sfx/container/stack-collapse.mp3 +0 -0
- package/src/skills-lib/huashu-design/assets/sfx/feedback/achievement.mp3 +0 -0
- package/src/skills-lib/huashu-design/assets/sfx/feedback/error-tone.mp3 +0 -0
- package/src/skills-lib/huashu-design/assets/sfx/feedback/notification-pop.mp3 +0 -0
- package/src/skills-lib/huashu-design/assets/sfx/feedback/success-chime.mp3 +0 -0
- package/src/skills-lib/huashu-design/assets/sfx/impact/brand-stamp.mp3 +0 -0
- package/src/skills-lib/huashu-design/assets/sfx/impact/drop-thud.mp3 +0 -0
- package/src/skills-lib/huashu-design/assets/sfx/impact/logo-reveal-v2.mp3 +0 -0
- package/src/skills-lib/huashu-design/assets/sfx/impact/logo-reveal.mp3 +0 -0
- package/src/skills-lib/huashu-design/assets/sfx/keyboard/delete-key.mp3 +0 -0
- package/src/skills-lib/huashu-design/assets/sfx/keyboard/enter.mp3 +0 -0
- package/src/skills-lib/huashu-design/assets/sfx/keyboard/space-tap.mp3 +0 -0
- package/src/skills-lib/huashu-design/assets/sfx/keyboard/type-fast.mp3 +0 -0
- package/src/skills-lib/huashu-design/assets/sfx/keyboard/type.mp3 +0 -0
- package/src/skills-lib/huashu-design/assets/sfx/magic/ai-process.mp3 +0 -0
- package/src/skills-lib/huashu-design/assets/sfx/magic/sparkle.mp3 +0 -0
- package/src/skills-lib/huashu-design/assets/sfx/magic/transform.mp3 +0 -0
- package/src/skills-lib/huashu-design/assets/sfx/progress/complete-done.mp3 +0 -0
- package/src/skills-lib/huashu-design/assets/sfx/progress/generate-start.mp3 +0 -0
- package/src/skills-lib/huashu-design/assets/sfx/progress/loading-tick.mp3 +0 -0
- package/src/skills-lib/huashu-design/assets/sfx/terminal/command-execute.mp3 +0 -0
- package/src/skills-lib/huashu-design/assets/sfx/terminal/cursor-blink.mp3 +0 -0
- package/src/skills-lib/huashu-design/assets/sfx/terminal/output-appear.mp3 +0 -0
- package/src/skills-lib/huashu-design/assets/sfx/transition/dissolve.mp3 +0 -0
- package/src/skills-lib/huashu-design/assets/sfx/transition/slide-in.mp3 +0 -0
- package/src/skills-lib/huashu-design/assets/sfx/transition/swipe-horizontal.mp3 +0 -0
- package/src/skills-lib/huashu-design/assets/sfx/transition/whoosh-fast.mp3 +0 -0
- package/src/skills-lib/huashu-design/assets/sfx/transition/whoosh.mp3 +0 -0
- package/src/skills-lib/huashu-design/assets/sfx/ui/click-soft.mp3 +0 -0
- package/src/skills-lib/huashu-design/assets/sfx/ui/click.mp3 +0 -0
- package/src/skills-lib/huashu-design/assets/sfx/ui/focus.mp3 +0 -0
- package/src/skills-lib/huashu-design/assets/sfx/ui/hover-subtle.mp3 +0 -0
- package/src/skills-lib/huashu-design/assets/sfx/ui/tap-finger.mp3 +0 -0
- package/src/skills-lib/huashu-design/assets/sfx/ui/toggle-on.mp3 +0 -0
- package/src/squads/README.md +0 -39
- package/src/squads/advisory-board/README.md +0 -34
- package/src/squads/advisory-board/agents/board-chair.md +0 -161
- package/src/squads/advisory-board/agents/brene-brown.md +0 -296
- package/src/squads/advisory-board/agents/charlie-munger.md +0 -590
- package/src/squads/advisory-board/agents/derek-sivers.md +0 -268
- package/src/squads/advisory-board/agents/naval-ravikant.md +0 -251
- package/src/squads/advisory-board/agents/patrick-lencioni.md +0 -394
- package/src/squads/advisory-board/agents/peter-thiel.md +0 -269
- package/src/squads/advisory-board/agents/ray-dalio.md +0 -567
- package/src/squads/advisory-board/agents/reid-hoffman.md +0 -278
- package/src/squads/advisory-board/agents/simon-sinek.md +0 -291
- package/src/squads/advisory-board/agents/yvon-chouinard.md +0 -275
- package/src/squads/advisory-board/squad.yaml +0 -50
- package/src/squads/brand-squad/README.md +0 -60
- package/src/squads/brand-squad/agents/al-ries.md +0 -175
- package/src/squads/brand-squad/agents/alina-wheeler.md +0 -184
- package/src/squads/brand-squad/agents/archetype-consultant.md +0 -215
- package/src/squads/brand-squad/agents/brand-chief.md +0 -158
- package/src/squads/brand-squad/agents/byron-sharp.md +0 -169
- package/src/squads/brand-squad/agents/david-aaker.md +0 -166
- package/src/squads/brand-squad/agents/denise-yohn.md +0 -172
- package/src/squads/brand-squad/agents/domain-scout.md +0 -135
- package/src/squads/brand-squad/agents/donald-miller.md +0 -179
- package/src/squads/brand-squad/agents/emily-heyward.md +0 -147
- package/src/squads/brand-squad/agents/jean-noel-kapferer.md +0 -189
- package/src/squads/brand-squad/agents/kevin-keller.md +0 -199
- package/src/squads/brand-squad/agents/marty-neumeier.md +0 -170
- package/src/squads/brand-squad/agents/miller-sticky-brand.md +0 -180
- package/src/squads/brand-squad/agents/naming-strategist.md +0 -171
- package/src/squads/brand-squad/squad.yaml +0 -117
- package/src/squads/c-level-squad/README.md +0 -29
- package/src/squads/c-level-squad/agents/caio-architect.md +0 -235
- package/src/squads/c-level-squad/agents/cio-engineer.md +0 -209
- package/src/squads/c-level-squad/agents/cmo-architect.md +0 -208
- package/src/squads/c-level-squad/agents/coo-orchestrator.md +0 -193
- package/src/squads/c-level-squad/agents/cto-architect.md +0 -194
- package/src/squads/c-level-squad/agents/vision-chief.md +0 -201
- package/src/squads/c-level-squad/squad.yaml +0 -45
- package/src/squads/claude-code-mastery/README.md +0 -146
- package/src/squads/claude-code-mastery/agents/claude-mastery-chief.md +0 -554
- package/src/squads/claude-code-mastery/agents/config-engineer.md +0 -865
- package/src/squads/claude-code-mastery/agents/hooks-architect.md +0 -1013
- package/src/squads/claude-code-mastery/agents/mcp-integrator.md +0 -791
- package/src/squads/claude-code-mastery/agents/project-integrator.md +0 -1196
- package/src/squads/claude-code-mastery/agents/roadmap-sentinel.md +0 -931
- package/src/squads/claude-code-mastery/agents/skill-craftsman.md +0 -1250
- package/src/squads/claude-code-mastery/agents/swarm-orchestrator.md +0 -1008
- package/src/squads/copy-squad/README.md +0 -65
- package/src/squads/copy-squad/agents/andre-chaperon.md +0 -206
- package/src/squads/copy-squad/agents/ben-settle.md +0 -194
- package/src/squads/copy-squad/agents/claude-hopkins.md +0 -182
- package/src/squads/copy-squad/agents/clayton-makepeace.md +0 -225
- package/src/squads/copy-squad/agents/copy-chief.md +0 -166
- package/src/squads/copy-squad/agents/dan-kennedy.md +0 -202
- package/src/squads/copy-squad/agents/dan-koe.md +0 -223
- package/src/squads/copy-squad/agents/david-deutsch.md +0 -197
- package/src/squads/copy-squad/agents/david-ogilvy.md +0 -198
- package/src/squads/copy-squad/agents/eugene-schwartz.md +0 -238
- package/src/squads/copy-squad/agents/frank-kern.md +0 -195
- package/src/squads/copy-squad/agents/gary-bencivenga.md +0 -197
- package/src/squads/copy-squad/agents/gary-halbert.md +0 -219
- package/src/squads/copy-squad/agents/jim-rutz.md +0 -193
- package/src/squads/copy-squad/agents/joe-sugarman.md +0 -234
- package/src/squads/copy-squad/agents/john-carlton.md +0 -203
- package/src/squads/copy-squad/agents/jon-benson.md +0 -196
- package/src/squads/copy-squad/agents/parris-lampropoulos.md +0 -188
- package/src/squads/copy-squad/agents/robert-collier.md +0 -183
- package/src/squads/copy-squad/agents/russell-brunson.md +0 -229
- package/src/squads/copy-squad/agents/ry-schwartz.md +0 -185
- package/src/squads/copy-squad/agents/stefan-georgi.md +0 -188
- package/src/squads/copy-squad/agents/todd-brown.md +0 -171
- package/src/squads/copy-squad/squad.yaml +0 -87
- package/src/squads/cybersecurity/README.md +0 -38
- package/src/squads/cybersecurity/agents/busterer.md +0 -108
- package/src/squads/cybersecurity/agents/cartographer.md +0 -114
- package/src/squads/cybersecurity/agents/chris-sanders.md +0 -205
- package/src/squads/cybersecurity/agents/command-generator.md +0 -121
- package/src/squads/cybersecurity/agents/cyber-chief.md +0 -120
- package/src/squads/cybersecurity/agents/dirber.md +0 -111
- package/src/squads/cybersecurity/agents/fuzzer.md +0 -121
- package/src/squads/cybersecurity/agents/georgia-weidman.md +0 -178
- package/src/squads/cybersecurity/agents/jim-manico.md +0 -182
- package/src/squads/cybersecurity/agents/marcus-carey.md +0 -200
- package/src/squads/cybersecurity/agents/omar-santos.md +0 -206
- package/src/squads/cybersecurity/agents/peter-kim.md +0 -179
- package/src/squads/cybersecurity/agents/ripper.md +0 -121
- package/src/squads/cybersecurity/agents/rogue.md +0 -116
- package/src/squads/cybersecurity/agents/shannon-runner.md +0 -108
- package/src/squads/cybersecurity/squad.yaml +0 -56
- package/src/squads/data-squad/README.md +0 -30
- package/src/squads/data-squad/agents/avinash-kaushik.md +0 -268
- package/src/squads/data-squad/agents/data-chief.md +0 -167
- package/src/squads/data-squad/agents/david-spinks.md +0 -277
- package/src/squads/data-squad/agents/nick-mehta.md +0 -294
- package/src/squads/data-squad/agents/peter-fader.md +0 -246
- package/src/squads/data-squad/agents/sean-ellis.md +0 -303
- package/src/squads/data-squad/agents/wes-kao.md +0 -268
- package/src/squads/data-squad/squad.yaml +0 -46
- package/src/squads/design-squad/README.md +0 -31
- package/src/squads/design-squad/agents/brad-frost.md +0 -185
- package/src/squads/design-squad/agents/dan-mall.md +0 -178
- package/src/squads/design-squad/agents/dave-malouf.md +0 -198
- package/src/squads/design-squad/agents/design-chief.md +0 -109
- package/src/squads/design-squad/agents/design-system-architect.md +0 -109
- package/src/squads/design-squad/agents/ui-engineer.md +0 -102
- package/src/squads/design-squad/agents/ux-designer.md +0 -105
- package/src/squads/design-squad/agents/visual-generator.md +0 -108
- package/src/squads/design-squad/squad.yaml +0 -48
- package/src/squads/hormozi-squad/README.md +0 -39
- package/src/squads/hormozi-squad/agents/hormozi-ads.md +0 -159
- package/src/squads/hormozi-squad/agents/hormozi-advisor.md +0 -178
- package/src/squads/hormozi-squad/agents/hormozi-audit.md +0 -178
- package/src/squads/hormozi-squad/agents/hormozi-chief.md +0 -111
- package/src/squads/hormozi-squad/agents/hormozi-closer.md +0 -179
- package/src/squads/hormozi-squad/agents/hormozi-content.md +0 -166
- package/src/squads/hormozi-squad/agents/hormozi-copy.md +0 -152
- package/src/squads/hormozi-squad/agents/hormozi-hooks.md +0 -177
- package/src/squads/hormozi-squad/agents/hormozi-launch.md +0 -160
- package/src/squads/hormozi-squad/agents/hormozi-leads.md +0 -198
- package/src/squads/hormozi-squad/agents/hormozi-models.md +0 -191
- package/src/squads/hormozi-squad/agents/hormozi-offers.md +0 -197
- package/src/squads/hormozi-squad/agents/hormozi-pricing.md +0 -151
- package/src/squads/hormozi-squad/agents/hormozi-retention.md +0 -166
- package/src/squads/hormozi-squad/agents/hormozi-scale.md +0 -175
- package/src/squads/hormozi-squad/agents/hormozi-workshop.md +0 -160
- package/src/squads/hormozi-squad/squad.yaml +0 -60
- package/src/squads/movement/README.md +0 -29
- package/src/squads/movement/agents/analista-de-impacto.md +0 -350
- package/src/squads/movement/agents/estrategista-de-ciclo.md +0 -301
- package/src/squads/movement/agents/fenomenologo.md +0 -169
- package/src/squads/movement/agents/identitario.md +0 -265
- package/src/squads/movement/agents/manifestador.md +0 -279
- package/src/squads/movement/agents/movement-architect.md +0 -210
- package/src/squads/movement/agents/movement-chief.md +0 -135
- package/src/squads/movement/squad.yaml +0 -45
- package/src/squads/storytelling/README.md +0 -35
- package/src/squads/storytelling/agents/blake-snyder.md +0 -225
- package/src/squads/storytelling/agents/dan-harmon.md +0 -167
- package/src/squads/storytelling/agents/joseph-campbell.md +0 -184
- package/src/squads/storytelling/agents/keith-johnstone.md +0 -157
- package/src/squads/storytelling/agents/kindra-hall.md +0 -162
- package/src/squads/storytelling/agents/marshall-ganz.md +0 -167
- package/src/squads/storytelling/agents/matthew-dicks.md +0 -152
- package/src/squads/storytelling/agents/nancy-duarte.md +0 -154
- package/src/squads/storytelling/agents/oren-klaff.md +0 -166
- package/src/squads/storytelling/agents/park-howell.md +0 -152
- package/src/squads/storytelling/agents/shawn-coyne.md +0 -208
- package/src/squads/storytelling/agents/story-chief.md +0 -155
- package/src/squads/storytelling/squad.yaml +0 -52
- package/src/squads/traffic-masters/README.md +0 -39
- package/src/squads/traffic-masters/agents/ad-midas.md +0 -149
- package/src/squads/traffic-masters/agents/ads-analyst.md +0 -135
- package/src/squads/traffic-masters/agents/creative-analyst.md +0 -142
- package/src/squads/traffic-masters/agents/depesh-mandalia.md +0 -174
- package/src/squads/traffic-masters/agents/fiscal.md +0 -144
- package/src/squads/traffic-masters/agents/kasim-aslam.md +0 -158
- package/src/squads/traffic-masters/agents/media-buyer.md +0 -159
- package/src/squads/traffic-masters/agents/molly-pittman.md +0 -185
- package/src/squads/traffic-masters/agents/nicholas-kusmich.md +0 -157
- package/src/squads/traffic-masters/agents/pedro-sobral.md +0 -158
- package/src/squads/traffic-masters/agents/performance-analyst.md +0 -135
- package/src/squads/traffic-masters/agents/pixel-specialist.md +0 -144
- package/src/squads/traffic-masters/agents/ralph-burns.md +0 -163
- package/src/squads/traffic-masters/agents/scale-optimizer.md +0 -144
- package/src/squads/traffic-masters/agents/tom-breeze.md +0 -175
- package/src/squads/traffic-masters/agents/traffic-chief.md +0 -97
- package/src/squads/traffic-masters/squad.yaml +0 -59
- package/tools/bundle-web-bundles.js +0 -117
- package/tools/format-workflow-md.js +0 -263
- package/tools/hooks/README.md +0 -17
- package/tools/hooks/security-defensive-context.js +0 -70
- package/tools/hooks/session-rules.js +0 -38
- package/tools/hooks/wizz-router-enforce.js +0 -188
- package/tools/javascript-conventions.md +0 -5
- package/tools/migrate-custom-module-paths.js +0 -124
- package/tools/skill-validator.md +0 -368
- package/tools/sync-global.mjs +0 -84
- package/tools/validate-sidebar-order.js +0 -388
- package/tools/validate-skills.js +0 -708
- package/tools/validate-svg-changes.sh +0 -356
- /package/tools/installer/{cli-utils.js → banner.js} +0 -0
|
@@ -0,0 +1,446 @@
|
|
|
1
|
+
// Smart env var assistance for MCP `${VAR}` placeholders (Fase 3, item 3.3 da
|
|
2
|
+
// auditoria 360°; design primário em
|
|
3
|
+
// `_audit/2026-07-07-parte3-auditoria-installer-envvars.md`, seção E).
|
|
4
|
+
//
|
|
5
|
+
// PROBLEM: a registry-driven `.mcp.json` entry can declare `env: { KEY:
|
|
6
|
+
// "${SOME_VAR}" }` (or a `${VAR}` inside `args`). If `SOME_VAR` is not set
|
|
7
|
+
// anywhere the MCP subprocess fails at runtime with an opaque error. This
|
|
8
|
+
// module detects those placeholders, tries to resolve them from the
|
|
9
|
+
// environment, and — only when interactive — offers to fill the gap.
|
|
10
|
+
//
|
|
11
|
+
// C7 (the bug this design fixes): the naive version of this feature persists
|
|
12
|
+
// the secret to `.env` or `~/.wizz-env`. Neither is read by the Claude Code
|
|
13
|
+
// runtime that spawns the MCP subprocess, so the secret would never actually
|
|
14
|
+
// reach it — the feature would *look* like it worked and silently not. The
|
|
15
|
+
// ONLY place Claude Code is confirmed to merge into every subprocess's
|
|
16
|
+
// environment for a project is the `env` key of that project's
|
|
17
|
+
// `.claude/settings.local.json`. That is the sole persistence target here.
|
|
18
|
+
//
|
|
19
|
+
// Design rules (deliberately conservative, mirrors mcp-config.js):
|
|
20
|
+
// - NEVER write the real value into `.mcp.json` — it keeps the `${VAR}`
|
|
21
|
+
// placeholder forever; only `.claude/settings.local.json` ever sees the
|
|
22
|
+
// secret.
|
|
23
|
+
// - NEVER overwrite a key the user (or a previous run) already put in
|
|
24
|
+
// `settings.local.json` — additive merge only, same spirit as the
|
|
25
|
+
// `.mcp.json` merge in mcp-config.js.
|
|
26
|
+
// - NEVER echo the secret in a log line, an error message, or the DX
|
|
27
|
+
// summary — only variable names and status are printed.
|
|
28
|
+
// - NEVER fail the install over a var the user chose to skip — the
|
|
29
|
+
// placeholder stays in `.mcp.json`, and the summary explains how to
|
|
30
|
+
// configure it later.
|
|
31
|
+
//
|
|
32
|
+
// API (decomposed per E3 so each piece is unit-testable without a TTY):
|
|
33
|
+
// extractEnvPlaceholders(mcps) — pure
|
|
34
|
+
// resolveEnvVars(vars, opts) — I/O read (providers + prompt)
|
|
35
|
+
// persistEnvValues(toPersist, opts) — I/O write (settings.local.json)
|
|
36
|
+
// persistProjectEnv(projectDir, envRecord) — the actual writer, reusable
|
|
37
|
+
// promptMissingEnvVars(mcps, opts) — thin orchestrator of the above
|
|
38
|
+
|
|
39
|
+
const path = require('node:path');
|
|
40
|
+
const fs = require('../fs-native');
|
|
41
|
+
const prompts = require('../prompts');
|
|
42
|
+
|
|
43
|
+
// Deliberately POSIX-strict (uppercase + underscore only): this both matches
|
|
44
|
+
// standard env var naming and doubles as a defensive filter against false
|
|
45
|
+
// positives like `{bin}` (no `$` prefix at all, so it never matches) or a
|
|
46
|
+
// lowercase template token that isn't meant to be an env var.
|
|
47
|
+
const ENV_VAR_REGEX = /\$\{([A-Z_][A-Z0-9_]*)(?::-([^}]*))?\}/g;
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Scan a list of resolved MCP entries for `${VAR}` / `${VAR:-default}`
|
|
51
|
+
* placeholders in `server.env` values and `server.args` items. Pure: no I/O,
|
|
52
|
+
* no prompting — just extraction + dedup.
|
|
53
|
+
*
|
|
54
|
+
* A var with a default (`${VAR:-default}`) is still returned (`hasDefault:
|
|
55
|
+
* true`) so callers can report it, but `resolveEnvVars` treats it as an
|
|
56
|
+
* automatic skip: the Claude Code runtime resolves `${VAR:-default}` itself,
|
|
57
|
+
* so asking the user for it would be pointless.
|
|
58
|
+
*
|
|
59
|
+
* @param {Array<{id: string, server: {env?: Object, args?: string[]}}>} mcps
|
|
60
|
+
* @returns {Array<{name: string, mcpIds: string[], hasDefault: boolean, default: string|undefined}>}
|
|
61
|
+
*/
|
|
62
|
+
function extractEnvPlaceholders(mcps) {
|
|
63
|
+
const byName = new Map();
|
|
64
|
+
|
|
65
|
+
for (const mcp of mcps || []) {
|
|
66
|
+
const server = mcp && mcp.server;
|
|
67
|
+
if (!server) continue;
|
|
68
|
+
|
|
69
|
+
const haystacks = [...Object.values(server.env || {}), ...(Array.isArray(server.args) ? server.args : [])].filter(
|
|
70
|
+
(value) => typeof value === 'string',
|
|
71
|
+
);
|
|
72
|
+
|
|
73
|
+
for (const value of haystacks) {
|
|
74
|
+
for (const match of value.matchAll(ENV_VAR_REGEX)) {
|
|
75
|
+
const name = match[1];
|
|
76
|
+
const hasDefault = match[2] !== undefined;
|
|
77
|
+
|
|
78
|
+
let entry = byName.get(name);
|
|
79
|
+
if (!entry) {
|
|
80
|
+
entry = { name, mcpIds: new Set(), hasDefault: false, default: undefined };
|
|
81
|
+
byName.set(name, entry);
|
|
82
|
+
}
|
|
83
|
+
if (mcp.id) entry.mcpIds.add(mcp.id);
|
|
84
|
+
// A default seen on ANY occurrence marks the var as having one, even
|
|
85
|
+
// if another occurrence (unlikely, but defensive) omitted it.
|
|
86
|
+
if (hasDefault) {
|
|
87
|
+
entry.hasDefault = true;
|
|
88
|
+
entry.default = match[2];
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
return [...byName.values()].map((entry) => ({ ...entry, mcpIds: [...entry.mcpIds] }));
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* `process.env` as an env var provider (E3 seam: `{ name, available, get }`).
|
|
99
|
+
* @returns {{name: string, available: () => Promise<boolean>, get: (name: string) => Promise<string|undefined>}}
|
|
100
|
+
*/
|
|
101
|
+
function createProcessEnvProvider() {
|
|
102
|
+
return {
|
|
103
|
+
name: 'process.env',
|
|
104
|
+
available: async () => true,
|
|
105
|
+
get: async (name) => process.env[name],
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Minimal `.env` parser: `KEY=value` per line, `#` comments, blank lines
|
|
111
|
+
* skipped, optional matching single/double quotes stripped. Intentionally
|
|
112
|
+
* not a full dotenv implementation (no multiline values, no `export` prefix,
|
|
113
|
+
* no interpolation) — this reads a value that may already exist, it never
|
|
114
|
+
* writes one, and the registry only has 4 single-var MCPs today (E2).
|
|
115
|
+
* @param {string} content
|
|
116
|
+
* @returns {Record<string, string>}
|
|
117
|
+
*/
|
|
118
|
+
function parseDotenv(content) {
|
|
119
|
+
const result = {};
|
|
120
|
+
for (const rawLine of String(content).split('\n')) {
|
|
121
|
+
const line = rawLine.trim();
|
|
122
|
+
if (!line || line.startsWith('#')) continue;
|
|
123
|
+
const eq = line.indexOf('=');
|
|
124
|
+
if (eq === -1) continue;
|
|
125
|
+
const key = line.slice(0, eq).trim();
|
|
126
|
+
if (!key) continue;
|
|
127
|
+
let value = line.slice(eq + 1).trim();
|
|
128
|
+
if (value.length >= 2) {
|
|
129
|
+
const first = value[0];
|
|
130
|
+
const last = value.at(-1);
|
|
131
|
+
if ((first === '"' && last === '"') || (first === "'" && last === "'")) {
|
|
132
|
+
value = value.slice(1, -1);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
result[key] = value;
|
|
136
|
+
}
|
|
137
|
+
return result;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* A `.env` file as an env var provider — read-only, and only consulted if
|
|
142
|
+
* the file exists (E1: "arquivo .env se existir"). Never created, never
|
|
143
|
+
* written; a var found here is classified `existing`, same as `process.env`.
|
|
144
|
+
* @param {string} dotenvPath - Absolute path to the candidate `.env` file
|
|
145
|
+
* @returns {{name: string, available: () => Promise<boolean>, get: (name: string) => Promise<string|undefined>}}
|
|
146
|
+
*/
|
|
147
|
+
function createDotenvFileProvider(dotenvPath) {
|
|
148
|
+
let cache = null;
|
|
149
|
+
|
|
150
|
+
async function load() {
|
|
151
|
+
if (cache) return cache;
|
|
152
|
+
cache = {};
|
|
153
|
+
if (!dotenvPath || !(await fs.pathExists(dotenvPath))) return cache;
|
|
154
|
+
try {
|
|
155
|
+
cache = parseDotenv(await fs.readFile(dotenvPath, 'utf8'));
|
|
156
|
+
} catch {
|
|
157
|
+
// Unreadable .env (permissions, race) — treat as absent, never throw.
|
|
158
|
+
cache = {};
|
|
159
|
+
}
|
|
160
|
+
return cache;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
return {
|
|
164
|
+
name: 'dotenv',
|
|
165
|
+
available: async () => !!dotenvPath && (await fs.pathExists(dotenvPath)),
|
|
166
|
+
get: async (name) => (await load())[name],
|
|
167
|
+
};
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* Try each provider in order, returning the first non-empty value found.
|
|
172
|
+
* A provider throwing or being unavailable is skipped, never fatal — one
|
|
173
|
+
* broken provider must not block the chain (e.g. an unreadable `.env`).
|
|
174
|
+
* @param {string} name - Var name to look up
|
|
175
|
+
* @param {Array<Object>} providers
|
|
176
|
+
* @returns {Promise<string|undefined>}
|
|
177
|
+
*/
|
|
178
|
+
async function findInProviders(name, providers) {
|
|
179
|
+
for (const provider of providers || []) {
|
|
180
|
+
if (!provider) continue;
|
|
181
|
+
try {
|
|
182
|
+
const isAvailable = typeof provider.available === 'function' ? await provider.available() : true;
|
|
183
|
+
if (!isAvailable) continue;
|
|
184
|
+
const value = await provider.get(name);
|
|
185
|
+
if (value !== undefined && value !== null && value !== '') return value;
|
|
186
|
+
} catch {
|
|
187
|
+
continue;
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
return;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
/**
|
|
194
|
+
* Default interactive prompter: masks input via `password()` (never
|
|
195
|
+
* `text()` — E4), never echoes the value anywhere else. An empty submission
|
|
196
|
+
* (plain Enter) is treated as "skip this one", same as a hard cancel.
|
|
197
|
+
* @returns {(entry: {name: string, mcpIds: string[]}) => Promise<string|undefined>}
|
|
198
|
+
*/
|
|
199
|
+
function createDefaultPrompter() {
|
|
200
|
+
return async (entry) => {
|
|
201
|
+
const usedBy = entry.mcpIds && entry.mcpIds.length > 0 ? ` (usada por: ${entry.mcpIds.join(', ')})` : '';
|
|
202
|
+
const value = await prompts.password({
|
|
203
|
+
message: `Valor para ${entry.name}${usedBy} — Enter para pular:`,
|
|
204
|
+
// @clack/prompts requires synchronous validate (prompts.js:763-765);
|
|
205
|
+
// format is unknown per-var, so we only guard against literal
|
|
206
|
+
// whitespace-only input slipping through as a "value".
|
|
207
|
+
validate: (input) => (typeof input === 'string' && input.trim() !== input ? 'Sem espaços no início/fim' : undefined),
|
|
208
|
+
});
|
|
209
|
+
if (value === undefined || value === null || value === '') return;
|
|
210
|
+
return value;
|
|
211
|
+
};
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
/**
|
|
215
|
+
* Resolve a list of extracted vars against provider chain + optional
|
|
216
|
+
* interactive prompt. Pure I/O, no persistence — that is `persistEnvValues`'s
|
|
217
|
+
* job. Fully testable without a real TTY via the injected `prompter`.
|
|
218
|
+
*
|
|
219
|
+
* @param {Array<{name: string, mcpIds: string[], hasDefault: boolean}>} vars
|
|
220
|
+
* @param {Object} [opts]
|
|
221
|
+
* @param {boolean} [opts.interactive=false] - Whether to prompt for missing vars
|
|
222
|
+
* @param {Array<Object>} [opts.providers] - Provider chain, tried in order
|
|
223
|
+
* @param {(entry) => Promise<string|undefined>} [opts.prompter] - Injectable prompt fn
|
|
224
|
+
* @returns {Promise<{filled: Array, skipped: Array, existing: Array, toPersist: Record<string,string>}>}
|
|
225
|
+
*/
|
|
226
|
+
async function resolveEnvVars(vars, opts = {}) {
|
|
227
|
+
const { interactive = false, providers = [createProcessEnvProvider()], prompter = null } = opts;
|
|
228
|
+
|
|
229
|
+
const filled = [];
|
|
230
|
+
const skipped = [];
|
|
231
|
+
const existing = [];
|
|
232
|
+
const toPersist = {};
|
|
233
|
+
|
|
234
|
+
for (const entry of vars || []) {
|
|
235
|
+
// A default is resolved by the Claude Code runtime itself; asking would
|
|
236
|
+
// be redundant, so this is an unconditional skip regardless of what the
|
|
237
|
+
// providers know (E7: "com default => sempre skipped").
|
|
238
|
+
if (entry.hasDefault) {
|
|
239
|
+
skipped.push(entry);
|
|
240
|
+
continue;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
const found = await findInProviders(entry.name, providers);
|
|
244
|
+
if (found !== undefined) {
|
|
245
|
+
existing.push(entry);
|
|
246
|
+
continue;
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
if (!interactive || !prompter) {
|
|
250
|
+
skipped.push(entry);
|
|
251
|
+
continue;
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
const answer = await prompter(entry);
|
|
255
|
+
if (answer === undefined || answer === null || answer === '') {
|
|
256
|
+
skipped.push(entry);
|
|
257
|
+
continue;
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
filled.push(entry);
|
|
261
|
+
toPersist[entry.name] = answer;
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
return { filled, skipped, existing, toPersist };
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
/**
|
|
268
|
+
* The actual writer: merge `envRecord` into `<projectDir>/.claude/settings.local.json`
|
|
269
|
+
* under the `env` key. Additive only — a key already present in the file is
|
|
270
|
+
* NEVER overwritten (the user, or a previous run, may have hand-edited it).
|
|
271
|
+
* Exported standalone (not just via `persistEnvValues`) because 3.8-E1 (the
|
|
272
|
+
* `WIZZ_TRACE` opt-in) reuses this exact writer for a value that has nothing
|
|
273
|
+
* to do with MCP env vars — one merge implementation, two callers.
|
|
274
|
+
*
|
|
275
|
+
* chmod 600 is applied after a write that actually changed the file (POSIX
|
|
276
|
+
* only; `process.platform === 'win32'` short-circuits to a documented no-op,
|
|
277
|
+
* and any chmod failure is swallowed — a permission tweak must never fail
|
|
278
|
+
* the install).
|
|
279
|
+
*
|
|
280
|
+
* @param {string} projectDir - Project root (settings.local.json lives at
|
|
281
|
+
* `<projectDir>/.claude/settings.local.json`)
|
|
282
|
+
* @param {Record<string,string>} envRecord - Vars to merge into `env`
|
|
283
|
+
* @returns {Promise<string|null>} Absolute path written/merged, or null when
|
|
284
|
+
* `envRecord` is empty (no-op, nothing to persist)
|
|
285
|
+
*/
|
|
286
|
+
async function persistProjectEnv(projectDir, envRecord) {
|
|
287
|
+
if (!envRecord || Object.keys(envRecord).length === 0) return null;
|
|
288
|
+
|
|
289
|
+
const claudeDir = path.join(projectDir, '.claude');
|
|
290
|
+
const file = path.join(claudeDir, 'settings.local.json');
|
|
291
|
+
await fs.ensureDir(claudeDir);
|
|
292
|
+
|
|
293
|
+
let settings = {};
|
|
294
|
+
if (await fs.pathExists(file)) {
|
|
295
|
+
try {
|
|
296
|
+
settings = JSON.parse(await fs.readFile(file, 'utf8'));
|
|
297
|
+
} catch (error) {
|
|
298
|
+
throw new Error(`.claude/settings.local.json existe mas não é JSON válido: ${error.message}`);
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
if (!settings || typeof settings !== 'object' || Array.isArray(settings)) settings = {};
|
|
302
|
+
if (!settings.env || typeof settings.env !== 'object' || Array.isArray(settings.env)) settings.env = {};
|
|
303
|
+
|
|
304
|
+
let changed = false;
|
|
305
|
+
for (const [key, value] of Object.entries(envRecord)) {
|
|
306
|
+
// Never overwrite: a key already present wins, always.
|
|
307
|
+
if (Object.prototype.hasOwnProperty.call(settings.env, key)) continue;
|
|
308
|
+
settings.env[key] = value;
|
|
309
|
+
changed = true;
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
if (changed) {
|
|
313
|
+
await fs.writeJson(file, settings, { spaces: 2 });
|
|
314
|
+
if (process.platform !== 'win32') {
|
|
315
|
+
try {
|
|
316
|
+
await fs.chmod(file, 0o600);
|
|
317
|
+
} catch {
|
|
318
|
+
// Best-effort: some filesystems/CI sandboxes reject chmod. Never
|
|
319
|
+
// fail the install over a permission tweak on a file we just wrote.
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
return file;
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
/**
|
|
328
|
+
* `persistEnvValues(toPersist, { projectDir, target })` — the E3-shaped
|
|
329
|
+
* entry point. Only `target: 'settings-local'` is implemented: writing
|
|
330
|
+
* secrets to a `dotenv` target is exactly the C7 anti-pattern this whole
|
|
331
|
+
* design exists to avoid (the value would never reach the MCP subprocess's
|
|
332
|
+
* environment), so it is rejected rather than silently doing the wrong
|
|
333
|
+
* thing. `target` is still an explicit parameter (vs. hardcoding) so the
|
|
334
|
+
* seam matches the audit's documented shape for future targets.
|
|
335
|
+
*
|
|
336
|
+
* @param {Record<string,string>} toPersist - Vars to persist (from `resolveEnvVars`)
|
|
337
|
+
* @param {Object} opts
|
|
338
|
+
* @param {string} opts.projectDir - Project root
|
|
339
|
+
* @param {string} [opts.target='settings-local'] - Persistence target
|
|
340
|
+
* @returns {Promise<string|null>} Absolute path written, or null when empty
|
|
341
|
+
*/
|
|
342
|
+
async function persistEnvValues(toPersist, opts = {}) {
|
|
343
|
+
const { projectDir, target = 'settings-local' } = opts;
|
|
344
|
+
if (!toPersist || Object.keys(toPersist).length === 0) return null;
|
|
345
|
+
|
|
346
|
+
if (target !== 'settings-local') {
|
|
347
|
+
throw new Error(
|
|
348
|
+
`persistEnvValues: target '${target}' não suportado (só 'settings-local' escreve secrets em local lido pelo runtime — ver C7 na auditoria)`,
|
|
349
|
+
);
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
return persistProjectEnv(projectDir, toPersist);
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
/**
|
|
356
|
+
* Render the DX summary (E6) — the highest-value part of this feature: turn
|
|
357
|
+
* a skipped var from a dead end into a 30-second fix. One line per var,
|
|
358
|
+
* grouped by outcome. Never includes a raw secret value, only names/status.
|
|
359
|
+
* @param {{filled: Array, skipped: Array, existing: Array}} resolved
|
|
360
|
+
* @returns {string|null} Formatted block, or null when there is nothing to say
|
|
361
|
+
*/
|
|
362
|
+
function formatSummary({ filled, skipped, existing }) {
|
|
363
|
+
const total = (filled?.length || 0) + (skipped?.length || 0) + (existing?.length || 0);
|
|
364
|
+
if (total === 0) return null;
|
|
365
|
+
|
|
366
|
+
const lines = [];
|
|
367
|
+
for (const entry of existing || []) {
|
|
368
|
+
lines.push(` ✓ ${entry.name.padEnd(28)} já existia no ambiente`);
|
|
369
|
+
}
|
|
370
|
+
for (const entry of filled || []) {
|
|
371
|
+
lines.push(` ✓ ${entry.name.padEnd(28)} configurada agora (.claude/settings.local.json)`);
|
|
372
|
+
}
|
|
373
|
+
for (const entry of skipped || []) {
|
|
374
|
+
if (entry.hasDefault) {
|
|
375
|
+
lines.push(` ✓ ${entry.name.padEnd(28)} tem default no MCP, nada a configurar`);
|
|
376
|
+
continue;
|
|
377
|
+
}
|
|
378
|
+
const usedBy = entry.mcpIds && entry.mcpIds.length > 0 ? entry.mcpIds.join(', ') : 'desconhecido';
|
|
379
|
+
lines.push(
|
|
380
|
+
` ○ ${entry.name.padEnd(28)} pulada — MCP ${usedBy} fica inativo até configurar`,
|
|
381
|
+
` → adicione em .claude/settings.local.json: { "env": { "${entry.name}": "..." } }`,
|
|
382
|
+
);
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
return `Env vars dos MCPs:\n${lines.join('\n')}`;
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
/**
|
|
389
|
+
* Thin orchestrator: extract → resolve → persist → summarize. Composes the
|
|
390
|
+
* three primitives above; this is what the installer calls.
|
|
391
|
+
*
|
|
392
|
+
* Contract (E1, enforced by the CALLER, not here — this function only does
|
|
393
|
+
* what it's told):
|
|
394
|
+
* - Call with the `ready` subset of `toWrite` (never `toRecommend`).
|
|
395
|
+
* - Call with `interactive: false` whenever `!!options.yes ||
|
|
396
|
+
* !process.stdin.isTTY` — the caller computes that, this module has no
|
|
397
|
+
* opinion on what "interactive" means, only how to behave given it.
|
|
398
|
+
*
|
|
399
|
+
* @param {Array<Object>} mcps - Resolved MCP entries to scan (already
|
|
400
|
+
* filtered by the caller to exclude ids already in `.mcp.json` and to
|
|
401
|
+
* exclude `toRecommend`)
|
|
402
|
+
* @param {Object} [opts]
|
|
403
|
+
* @param {string} opts.projectDir - Project root (for persistence + the
|
|
404
|
+
* default `.env` provider)
|
|
405
|
+
* @param {boolean} [opts.interactive=false]
|
|
406
|
+
* @param {Array<Object>} [opts.providers] - Defaults to `[processEnv, dotenvFile(<projectDir>/.env)]`
|
|
407
|
+
* @param {(entry) => Promise<string|undefined>} [opts.prompter] - Defaults to
|
|
408
|
+
* the masked `password()` prompter
|
|
409
|
+
* @returns {Promise<{filled: Array, skipped: Array, existing: Array, envFile: string|null}>}
|
|
410
|
+
*/
|
|
411
|
+
async function promptMissingEnvVars(mcps, opts = {}) {
|
|
412
|
+
const { projectDir, interactive = false, providers, prompter } = opts;
|
|
413
|
+
|
|
414
|
+
const vars = extractEnvPlaceholders(mcps);
|
|
415
|
+
if (vars.length === 0) return { filled: [], skipped: [], existing: [], envFile: null };
|
|
416
|
+
|
|
417
|
+
const resolvedProviders = providers || [createProcessEnvProvider(), createDotenvFileProvider(path.join(projectDir, '.env'))];
|
|
418
|
+
const resolvedPrompter = interactive ? prompter || createDefaultPrompter() : null;
|
|
419
|
+
|
|
420
|
+
const resolved = await resolveEnvVars(vars, {
|
|
421
|
+
interactive,
|
|
422
|
+
providers: resolvedProviders,
|
|
423
|
+
prompter: resolvedPrompter,
|
|
424
|
+
});
|
|
425
|
+
|
|
426
|
+
let envFile = null;
|
|
427
|
+
if (Object.keys(resolved.toPersist).length > 0) {
|
|
428
|
+
envFile = await persistEnvValues(resolved.toPersist, { projectDir, target: 'settings-local' });
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
const summary = formatSummary(resolved);
|
|
432
|
+
if (summary) await prompts.log.info(summary);
|
|
433
|
+
|
|
434
|
+
return { filled: resolved.filled, skipped: resolved.skipped, existing: resolved.existing, envFile };
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
module.exports = {
|
|
438
|
+
extractEnvPlaceholders,
|
|
439
|
+
resolveEnvVars,
|
|
440
|
+
persistEnvValues,
|
|
441
|
+
persistProjectEnv,
|
|
442
|
+
promptMissingEnvVars,
|
|
443
|
+
createProcessEnvProvider,
|
|
444
|
+
createDotenvFileProvider,
|
|
445
|
+
formatSummary,
|
|
446
|
+
};
|
|
@@ -10,6 +10,38 @@ const { getProjectRoot } = require('../project-root');
|
|
|
10
10
|
|
|
11
11
|
const VALID_CHANNELS = new Set(['stable', 'next', 'pinned']);
|
|
12
12
|
|
|
13
|
+
// Retry pontual (1 re-tentativa, backoff curto) para `git clone`/`git fetch`.
|
|
14
|
+
// Para comandos de shell não temos código de erro estruturado como em
|
|
15
|
+
// requisições HTTP; classificamos como transitório por padrões conhecidos na
|
|
16
|
+
// mensagem/stderr do git. Erro lógico (repo/tag inexistente, permissão
|
|
17
|
+
// negada etc.) não bate nesses padrões e propaga direto, sem retry.
|
|
18
|
+
const GIT_RETRY_DELAY_MS = 300;
|
|
19
|
+
const TRANSIENT_GIT_ERROR_PATTERNS = [/could not resolve host/i, /timed out/i, /early eof/i, /connection reset/i];
|
|
20
|
+
|
|
21
|
+
function isTransientGitError(error) {
|
|
22
|
+
const message = `${error?.message || ''}\n${error?.stderr?.toString?.() || ''}`;
|
|
23
|
+
return TRANSIENT_GIT_ERROR_PATTERNS.some((pattern) => pattern.test(message));
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// Sleep síncrono curto (execSync é bloqueante; não há await aqui). Usa
|
|
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
|
+
}
|
|
44
|
+
|
|
13
45
|
function normalizeChannelName(raw) {
|
|
14
46
|
if (typeof raw !== 'string') return null;
|
|
15
47
|
const lower = raw.trim().toLowerCase();
|
|
@@ -109,7 +141,9 @@ class ExternalModuleManager {
|
|
|
109
141
|
name: mod.display_name || mod.name,
|
|
110
142
|
description: mod.description || '',
|
|
111
143
|
defaultSelected: mod.default_selected === true || mod.defaultSelected === true,
|
|
112
|
-
|
|
144
|
+
// Default 'upstream-org': módulo de org terceira com confiança delegada
|
|
145
|
+
// (decisão 2.10/A4 da auditoria, 2026-07-07; ver wizz-modules.yaml).
|
|
146
|
+
type: mod.type || 'upstream-org',
|
|
113
147
|
npmPackage: mod.npm_package || mod.npmPackage || null,
|
|
114
148
|
pluginName: mod.plugin_name || mod.pluginName || null,
|
|
115
149
|
defaultChannel: normalizeChannelName(mod.default_channel || mod.defaultChannel) || 'stable',
|
|
@@ -330,7 +364,7 @@ class ExternalModuleManager {
|
|
|
330
364
|
const currentSha = execSync('git rev-parse HEAD', { cwd: moduleCacheDir, stdio: 'pipe' }).toString().trim();
|
|
331
365
|
|
|
332
366
|
if (resolved.channel === 'next') {
|
|
333
|
-
|
|
367
|
+
execSyncWithRetry('git fetch origin --depth 1', {
|
|
334
368
|
cwd: moduleCacheDir,
|
|
335
369
|
stdio: ['ignore', 'pipe', 'pipe'],
|
|
336
370
|
env: { ...process.env, GIT_TERMINAL_PROMPT: '0' },
|
|
@@ -342,7 +376,7 @@ class ExternalModuleManager {
|
|
|
342
376
|
});
|
|
343
377
|
} else {
|
|
344
378
|
// stable or pinned — fetch the specific tag and check it out.
|
|
345
|
-
|
|
379
|
+
execSyncWithRetry(`git fetch --depth 1 origin tag ${quoteShell(resolved.ref)} --no-tags`, {
|
|
346
380
|
cwd: moduleCacheDir,
|
|
347
381
|
stdio: ['ignore', 'pipe', 'pipe'],
|
|
348
382
|
env: { ...process.env, GIT_TERMINAL_PROMPT: '0' },
|
|
@@ -370,12 +404,12 @@ class ExternalModuleManager {
|
|
|
370
404
|
fetchSpinner.start(`Fetching ${moduleInfo.name}...`);
|
|
371
405
|
try {
|
|
372
406
|
if (resolved.channel === 'next') {
|
|
373
|
-
|
|
407
|
+
execSyncWithRetry(`git clone --depth 1 "${moduleInfo.url}" "${moduleCacheDir}"`, {
|
|
374
408
|
stdio: ['ignore', 'pipe', 'pipe'],
|
|
375
409
|
env: { ...process.env, GIT_TERMINAL_PROMPT: '0' },
|
|
376
410
|
});
|
|
377
411
|
} else {
|
|
378
|
-
|
|
412
|
+
execSyncWithRetry(`git clone --depth 1 --branch ${quoteShell(resolved.ref)} "${moduleInfo.url}" "${moduleCacheDir}"`, {
|
|
379
413
|
stdio: ['ignore', 'pipe', 'pipe'],
|
|
380
414
|
env: { ...process.env, GIT_TERMINAL_PROMPT: '0' },
|
|
381
415
|
});
|
|
@@ -524,4 +558,4 @@ class ExternalModuleManager {
|
|
|
524
558
|
cachedModules = null;
|
|
525
559
|
}
|
|
526
560
|
|
|
527
|
-
module.exports = { ExternalModuleManager };
|
|
561
|
+
module.exports = { ExternalModuleManager, isTransientGitError, execSyncWithRetry };
|