wizz-method 1.0.1 → 1.0.3
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/.claude/settings.local.json +2 -1
- package/.claude-plugin/marketplace.json +9 -9
- package/README.md +4 -4
- package/build/artifacts/llms-full.txt +218 -218
- package/build/artifacts/llms.txt +4 -4
- package/build/site/explanation/advanced-elicitation/index.html +2 -2
- package/build/site/explanation/adversarial-review/index.html +2 -2
- package/build/site/explanation/analysis-phase/index.html +2 -2
- package/build/site/explanation/brainstorming/index.html +2 -2
- package/build/site/explanation/checkpoint-preview/index.html +2 -2
- package/build/site/explanation/established-projects-faq/index.html +2 -2
- package/build/site/explanation/forensic-investigation/index.html +2 -2
- package/build/site/explanation/named-agents/index.html +6 -6
- package/build/site/explanation/party-mode/index.html +3 -3
- package/build/site/explanation/preventing-agent-conflicts/index.html +2 -2
- package/build/site/explanation/project-context/index.html +2 -2
- package/build/site/explanation/quick-dev/index.html +2 -2
- package/build/site/explanation/web-bundles/index.html +2 -2
- package/build/site/explanation/why-solutioning-matters/index.html +2 -2
- package/build/site/how-to/{customize-bmad → customize-wizz}/index.html +6 -6
- package/build/site/how-to/established-projects/index.html +2 -2
- package/build/site/how-to/{expand-bmad-for-your-org → expand-wizz-for-your-org}/index.html +7 -7
- package/build/site/how-to/{get-answers-about-bmad → get-answers-about-wizz}/index.html +3 -3
- package/build/site/how-to/install-custom-modules/index.html +3 -3
- package/build/site/how-to/{install-bmad → install-wizz}/index.html +6 -6
- package/build/site/how-to/non-interactive-installation/index.html +3 -3
- package/build/site/how-to/project-context/index.html +2 -2
- package/build/site/how-to/quick-fixes/index.html +2 -2
- package/build/site/how-to/shard-large-documents/index.html +2 -2
- package/build/site/how-to/upgrade-to-v6/index.html +8 -8
- package/build/site/how-to/use-web-bundles/index.html +2 -2
- package/build/site/index.html +3 -3
- package/build/site/llms-full.txt +218 -218
- package/build/site/llms.txt +4 -4
- package/build/site/pagefind/fragment/en_296ddb9.pf_fragment +0 -0
- package/build/site/pagefind/fragment/en_583316f.pf_fragment +0 -0
- package/build/site/pagefind/fragment/en_67825a4.pf_fragment +0 -0
- package/build/site/pagefind/fragment/{en_41cab15.pf_fragment → en_887ce56.pf_fragment} +0 -0
- package/build/site/pagefind/fragment/en_92d7cc7.pf_fragment +0 -0
- package/build/site/pagefind/fragment/{en_56b1635.pf_fragment → en_9b57d7d.pf_fragment} +0 -0
- package/build/site/pagefind/fragment/en_ba9fb37.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_cdd885c.pf_fragment +0 -0
- package/build/site/pagefind/fragment/en_d890205.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 +1 -1
- package/build/site/pagefind/pagefind.en_4e69d7f053.pf_meta +0 -0
- package/build/site/reference/agents/index.html +2 -2
- package/build/site/reference/commands/index.html +3 -3
- package/build/site/reference/core-tools/index.html +3 -3
- package/build/site/reference/modules/index.html +4 -4
- package/build/site/reference/testing/index.html +2 -2
- package/build/site/reference/workflow-map/index.html +2 -2
- package/build/site/roadmap/index.html +2 -2
- package/build/site/sitemap-0.xml +1 -1
- package/build/site/tutorials/getting-started/index.html +4 -4
- package/build/site/workflow-map-diagram-fr.html +2 -2
- package/package.json +8 -8
- package/removals.txt +46 -46
- package/src/bmm-skills/1-analysis/research/wizz-domain-research/customize.toml +1 -1
- package/src/bmm-skills/1-analysis/research/wizz-market-research/customize.toml +1 -1
- package/src/bmm-skills/1-analysis/research/wizz-technical-research/customize.toml +2 -1
- package/src/bmm-skills/1-analysis/wizz-agent-analyst/customize.toml +2 -2
- package/src/bmm-skills/1-analysis/wizz-agent-tech-writer/customize.toml +2 -2
- package/src/bmm-skills/1-analysis/wizz-document-project/customize.toml +1 -1
- package/src/bmm-skills/1-analysis/wizz-document-project/templates/index-template.md +1 -1
- package/src/bmm-skills/1-analysis/wizz-document-project/templates/project-overview-template.md +1 -1
- package/src/bmm-skills/1-analysis/wizz-document-project/templates/source-tree-template.md +1 -1
- package/src/bmm-skills/1-analysis/wizz-prfaq/customize.toml +1 -1
- package/src/bmm-skills/1-analysis/wizz-product-brief/SKILL.md +1 -1
- package/src/bmm-skills/1-analysis/wizz-product-brief/customize.toml +1 -1
- package/src/bmm-skills/2-plan-workflows/wizz-agent-pm/customize.toml +2 -2
- package/src/bmm-skills/2-plan-workflows/wizz-agent-ux-designer/customize.toml +2 -2
- package/src/bmm-skills/2-plan-workflows/wizz-create-prd/SKILL.md +1 -1
- package/src/bmm-skills/2-plan-workflows/wizz-create-prd/customize.toml +1 -1
- package/src/bmm-skills/2-plan-workflows/wizz-edit-prd/SKILL.md +1 -1
- package/src/bmm-skills/2-plan-workflows/wizz-edit-prd/customize.toml +1 -1
- package/src/bmm-skills/2-plan-workflows/wizz-prd/SKILL.md +3 -3
- package/src/bmm-skills/2-plan-workflows/wizz-prd/customize.toml +2 -2
- package/src/bmm-skills/2-plan-workflows/wizz-ux/SKILL.md +2 -2
- package/src/bmm-skills/2-plan-workflows/wizz-validate-prd/SKILL.md +1 -1
- package/src/bmm-skills/2-plan-workflows/wizz-validate-prd/customize.toml +1 -1
- package/src/bmm-skills/3-solutioning/wizz-agent-architect/customize.toml +2 -2
- package/src/bmm-skills/3-solutioning/wizz-architecture/SKILL.md +2 -2
- package/src/bmm-skills/3-solutioning/wizz-architecture/customize.toml +4 -2
- package/src/bmm-skills/3-solutioning/wizz-check-implementation-readiness/customize.toml +1 -1
- package/src/bmm-skills/3-solutioning/wizz-create-architecture/SKILL.md +1 -1
- package/src/bmm-skills/3-solutioning/wizz-create-architecture/customize.toml +1 -1
- package/src/bmm-skills/3-solutioning/wizz-create-epics-and-stories/customize.toml +1 -1
- package/src/bmm-skills/3-solutioning/wizz-generate-project-context/customize.toml +1 -1
- package/src/bmm-skills/4-implementation/wizz-agent-dev/customize.toml +3 -2
- package/src/bmm-skills/4-implementation/wizz-checkpoint-preview/customize.toml +1 -1
- package/src/bmm-skills/4-implementation/wizz-code-review/customize.toml +1 -1
- package/src/bmm-skills/4-implementation/wizz-correct-course/customize.toml +1 -1
- package/src/bmm-skills/4-implementation/wizz-create-story/SKILL.md +2 -2
- package/src/bmm-skills/4-implementation/wizz-create-story/customize.toml +1 -1
- package/src/bmm-skills/4-implementation/wizz-dev-story/SKILL.md +1 -1
- package/src/bmm-skills/4-implementation/wizz-dev-story/customize.toml +1 -1
- package/src/bmm-skills/4-implementation/wizz-investigate/customize.toml +1 -1
- package/src/bmm-skills/4-implementation/wizz-qa-generate-e2e-tests/customize.toml +1 -1
- package/src/bmm-skills/4-implementation/wizz-quick-dev/customize.toml +1 -1
- package/src/bmm-skills/4-implementation/wizz-quick-dev/step-01-clarify-and-route.md +1 -1
- package/src/bmm-skills/4-implementation/wizz-retrospective/customize.toml +1 -1
- package/src/bmm-skills/4-implementation/wizz-sprint-planning/customize.toml +1 -1
- package/src/bmm-skills/4-implementation/wizz-sprint-status/SKILL.md +5 -5
- package/src/bmm-skills/4-implementation/wizz-sprint-status/customize.toml +1 -1
- package/src/bmm-skills/module-help.csv +32 -32
- package/src/bmm-skills/module.yaml +1 -1
- package/src/core-skills/module-help.csv +3 -3
- package/src/core-skills/module.yaml +4 -4
- package/src/core-skills/wizz-brainstorming/SKILL.md +1 -1
- package/src/core-skills/wizz-brainstorming/analysis/catalog-analysis.md +4 -4
- package/src/core-skills/wizz-brainstorming/assets/brain-selector.html +5 -5
- package/src/core-skills/wizz-brainstorming/customize.toml +1 -1
- package/src/core-skills/wizz-brainstorming/references/finalize.md +1 -1
- package/src/core-skills/wizz-brainstorming/scripts/brain.py +5 -5
- package/src/core-skills/wizz-brainstorming/scripts/tests/test_brain.py +1 -1
- package/src/core-skills/wizz-brainstorming/scripts/tests/test_memlog.py +3 -3
- package/src/core-skills/wizz-customize/SKILL.md +6 -6
- package/src/core-skills/wizz-customize/scripts/list_customizable_skills.py +3 -3
- package/src/core-skills/wizz-customize/scripts/tests/test_list_customizable_skills.py +13 -13
- package/src/core-skills/wizz-editorial-review-structure/SKILL.md +1 -1
- package/src/core-skills/wizz-help/SKILL.md +3 -3
- package/src/core-skills/wizz-party-mode/SKILL.md +5 -3
- package/src/core-skills/wizz-party-mode/customize.toml +2 -2
- package/src/core-skills/wizz-party-mode/scripts/resolve_party.py +2 -2
- package/src/core-skills/wizz-party-mode/scripts/tests/test-resolve_party.py +1 -1
- package/src/core-skills/wizz-spec/SKILL.md +3 -3
- package/src/core-skills/wizz-spec/customize.toml +2 -2
- package/src/modules/wizz/README.md +5 -5
- package/src/modules/wizz/agents/wizz-ads/SKILL.md +1 -1
- package/src/modules/wizz/agents/wizz-copy/SKILL.md +1 -1
- package/src/modules/wizz/agents/wizz-designer/SKILL.md +1 -1
- package/src/modules/wizz/agents/wizz-growth/SKILL.md +1 -1
- package/src/modules/wizz/agents/wizz-maestro/SKILL.md +2 -2
- package/src/modules/wizz/agents/wizz-memoria/SKILL.md +1 -1
- package/src/modules/wizz/agents/wizz-qa/SKILL.md +1 -1
- package/src/modules/wizz/agents/wizz-seo/SKILL.md +1 -1
- package/src/modules/wizz/overrides/{bmad-agent-analyst.toml → wizz-agent-analyst.toml} +1 -1
- package/src/modules/wizz/overrides/{bmad-agent-architect.toml → wizz-agent-architect.toml} +1 -1
- package/src/modules/wizz/overrides/{bmad-agent-dev.toml → wizz-agent-dev.toml} +1 -1
- package/src/modules/wizz/overrides/{bmad-agent-pm.toml → wizz-agent-pm.toml} +1 -1
- package/src/modules/wizz/overrides/{bmad-agent-tech-writer.toml → wizz-agent-tech-writer.toml} +1 -1
- package/src/modules/wizz/overrides/{bmad-agent-ux-designer.toml → wizz-agent-ux-designer.toml} +1 -1
- package/src/modules/wizz/scripts/wizz-init.mjs +7 -7
- package/src/scripts/resolve_config.py +7 -7
- package/src/scripts/resolve_customization.py +2 -2
- package/src/scripts/tests/test_memlog.py +1 -1
- package/tools/bundle-web-bundles.js +1 -1
- package/tools/format-workflow-md.js +2 -2
- package/tools/installer/commands/install.js +1 -1
- package/tools/installer/commands/status.js +9 -9
- package/tools/installer/commands/uninstall.js +5 -5
- package/tools/installer/core/existing-install.js +8 -8
- package/tools/installer/core/install-paths.js +13 -13
- package/tools/installer/core/installer.js +102 -102
- package/tools/installer/core/legacy-warnings.js +16 -16
- package/tools/installer/core/manifest-generator.js +30 -30
- package/tools/installer/core/manifest.js +30 -30
- package/tools/installer/core/python-check.js +7 -7
- package/tools/installer/ide/_config-driven.js +97 -97
- package/tools/installer/ide/manager.js +17 -17
- package/tools/installer/ide/platform-codes.yaml +5 -5
- package/tools/installer/ide/shared/installed-skills.js +13 -13
- package/tools/installer/ide/shared/path-utils.js +46 -46
- package/tools/installer/ide/shared/skill-manifest.js +4 -4
- package/tools/installer/install-messages.yaml +1 -1
- package/tools/installer/list-options.js +3 -3
- package/tools/installer/modules/channel-plan.js +1 -1
- package/tools/installer/modules/channel-resolver.js +1 -1
- package/tools/installer/modules/custom-module-manager.js +16 -16
- package/tools/installer/modules/external-manager.js +6 -6
- package/tools/installer/modules/official-modules.js +58 -46
- package/tools/installer/modules/plugin-resolver.js +3 -3
- package/tools/installer/project-root.js +13 -13
- package/tools/installer/prompts.js +1 -1
- package/tools/installer/set-overrides.js +6 -6
- package/tools/installer/ui.js +29 -29
- package/tools/installer/yaml-format.js +1 -1
- package/tools/migrate-custom-module-paths.js +11 -11
- package/tools/skill-validator.md +6 -6
- package/tools/validate-skills.js +10 -5
- package/web-bundles/README.md +4 -4
- package/web-bundles/brainstorming-coach/INSTRUCTIONS.md +1 -1
- package/web-bundles/bundles.json +6 -6
- package/web-bundles/market-and-industry-research/INSTRUCTIONS.md +1 -1
- package/web-bundles/prd-coach/INSTRUCTIONS.md +3 -3
- package/web-bundles/prfaq-coach/INSTRUCTIONS.md +3 -3
- package/web-bundles/product-brief-coach/INSTRUCTIONS.md +3 -3
- package/web-bundles/ux-coach/INSTRUCTIONS.md +1 -1
- package/{bmad-modules.yaml → wizz-modules.yaml} +15 -15
- package/build/site/pagefind/fragment/en_5ad92a9.pf_fragment +0 -0
- package/build/site/pagefind/fragment/en_7aea5bc.pf_fragment +0 -0
- package/build/site/pagefind/fragment/en_81bcd7f.pf_fragment +0 -0
- package/build/site/pagefind/fragment/en_938e9c4.pf_fragment +0 -0
- package/build/site/pagefind/fragment/en_b51d75b.pf_fragment +0 -0
- package/build/site/pagefind/fragment/en_c9fea21.pf_fragment +0 -0
- package/build/site/pagefind/fragment/en_e07e982.pf_fragment +0 -0
- package/build/site/pagefind/fragment/en_f4389af.pf_fragment +0 -0
- package/build/site/pagefind/fragment/en_f52c9f9.pf_fragment +0 -0
- package/build/site/pagefind/index/en_82c64dc.pf_index +0 -0
- package/build/site/pagefind/index/en_d0dd3c7.pf_index +0 -0
- package/build/site/pagefind/index/en_e890f88.pf_index +0 -0
- package/build/site/pagefind/pagefind.en_ee1b8a17c8.pf_meta +0 -0
- /package/build/site/img/{bmad-dark.png → wizz-dark.png} +0 -0
- /package/build/site/img/{bmad-light.png → wizz-light.png} +0 -0
- /package/src/bmm-skills/1-analysis/wizz-prfaq/{bmad-manifest.json → wizz-manifest.json} +0 -0
- /package/tools/installer/{bmad-cli.js → wizz-cli.js} +0 -0
|
@@ -7,6 +7,18 @@ const { CLIUtils } = require('../cli-utils');
|
|
|
7
7
|
const { ExternalModuleManager } = require('./external-manager');
|
|
8
8
|
|
|
9
9
|
class OfficialModules {
|
|
10
|
+
/**
|
|
11
|
+
* A config field is "missing a default" only when it has no default value at
|
|
12
|
+
* all (undefined/null). An explicit empty string (`default: ""`) is a real
|
|
13
|
+
* default meaning "defaults to blank" — it must NOT force a required prompt.
|
|
14
|
+
* Centralized so the express/customize/skip-prompts paths stay consistent.
|
|
15
|
+
* @param {*} defaultValue - The field's `default` value from module.yaml.
|
|
16
|
+
* @returns {boolean} True when the field has no usable default.
|
|
17
|
+
*/
|
|
18
|
+
static isMissingDefault(defaultValue) {
|
|
19
|
+
return defaultValue === undefined || defaultValue === null;
|
|
20
|
+
}
|
|
21
|
+
|
|
10
22
|
constructor(options = {}) {
|
|
11
23
|
this.externalModuleManager = new ExternalModuleManager();
|
|
12
24
|
// Config collection state (merged from ConfigCollector)
|
|
@@ -252,27 +264,27 @@ class OfficialModules {
|
|
|
252
264
|
/**
|
|
253
265
|
* Install a module
|
|
254
266
|
* @param {string} moduleName - Code of the module to install (from module.yaml)
|
|
255
|
-
* @param {string}
|
|
267
|
+
* @param {string} wizzDir - Target wizz directory
|
|
256
268
|
* @param {Function} fileTrackingCallback - Optional callback to track installed files
|
|
257
269
|
* @param {Object} options - Additional installation options
|
|
258
270
|
* @param {Array<string>} options.installedIDEs - Array of IDE codes that were installed
|
|
259
271
|
* @param {Object} options.moduleConfig - Module configuration from config collector
|
|
260
272
|
* @param {Object} options.logger - Logger instance for output
|
|
261
273
|
*/
|
|
262
|
-
async install(moduleName,
|
|
274
|
+
async install(moduleName, wizzDir, fileTrackingCallback = null, options = {}) {
|
|
263
275
|
// Check if this module has a plugin resolution (custom marketplace install)
|
|
264
276
|
const { CustomModuleManager } = require('./custom-module-manager');
|
|
265
277
|
const customMgr = new CustomModuleManager();
|
|
266
278
|
const resolved = customMgr.getResolution(moduleName);
|
|
267
279
|
if (resolved) {
|
|
268
|
-
return this.installFromResolution(resolved,
|
|
280
|
+
return this.installFromResolution(resolved, wizzDir, fileTrackingCallback, options);
|
|
269
281
|
}
|
|
270
282
|
|
|
271
283
|
const sourcePath = await this.findModuleSource(moduleName, {
|
|
272
284
|
silent: options.silent,
|
|
273
285
|
channelOptions: options.channelOptions,
|
|
274
286
|
});
|
|
275
|
-
const targetPath = path.join(
|
|
287
|
+
const targetPath = path.join(wizzDir, moduleName);
|
|
276
288
|
|
|
277
289
|
if (!sourcePath) {
|
|
278
290
|
throw new Error(
|
|
@@ -287,18 +299,18 @@ class OfficialModules {
|
|
|
287
299
|
await this.copyModuleWithFiltering(sourcePath, targetPath, fileTrackingCallback, options.moduleConfig);
|
|
288
300
|
|
|
289
301
|
if (!options.skipModuleInstaller) {
|
|
290
|
-
await this.createModuleDirectories(moduleName,
|
|
302
|
+
await this.createModuleDirectories(moduleName, wizzDir, options);
|
|
291
303
|
}
|
|
292
304
|
|
|
293
305
|
const { Manifest } = require('../core/manifest');
|
|
294
306
|
const manifestObj = new Manifest();
|
|
295
|
-
const versionInfo = await manifestObj.getModuleVersionInfo(moduleName,
|
|
307
|
+
const versionInfo = await manifestObj.getModuleVersionInfo(moduleName, wizzDir, sourcePath);
|
|
296
308
|
|
|
297
309
|
// Pick up channel resolution recorded by the external manager (the only
|
|
298
310
|
// manager that does pre-clone resolution now that community is retired).
|
|
299
311
|
const resolution = this.externalModuleManager.getResolution(moduleName);
|
|
300
312
|
|
|
301
|
-
await manifestObj.addModule(
|
|
313
|
+
await manifestObj.addModule(wizzDir, moduleName, {
|
|
302
314
|
version: resolution?.version || versionInfo.version,
|
|
303
315
|
source: versionInfo.source,
|
|
304
316
|
npmPackage: versionInfo.npmPackage,
|
|
@@ -314,12 +326,12 @@ class OfficialModules {
|
|
|
314
326
|
* Install a module from a PluginResolver resolution result.
|
|
315
327
|
* Copies specific skill directories and places module-help.csv at the target root.
|
|
316
328
|
* @param {Object} resolved - ResolvedModule from PluginResolver
|
|
317
|
-
* @param {string}
|
|
329
|
+
* @param {string} wizzDir - Target wizz directory
|
|
318
330
|
* @param {Function} fileTrackingCallback - Optional callback to track installed files
|
|
319
331
|
* @param {Object} options - Installation options
|
|
320
332
|
*/
|
|
321
|
-
async installFromResolution(resolved,
|
|
322
|
-
const targetPath = path.join(
|
|
333
|
+
async installFromResolution(resolved, wizzDir, fileTrackingCallback = null, options = {}) {
|
|
334
|
+
const targetPath = path.join(wizzDir, resolved.code);
|
|
323
335
|
|
|
324
336
|
if (await fs.pathExists(targetPath)) {
|
|
325
337
|
await fs.remove(targetPath);
|
|
@@ -349,7 +361,7 @@ class OfficialModules {
|
|
|
349
361
|
|
|
350
362
|
// Create directories declared in module.yaml (strategies 1-4 may have these)
|
|
351
363
|
if (!options.skipModuleInstaller) {
|
|
352
|
-
await this.createModuleDirectories(resolved.code,
|
|
364
|
+
await this.createModuleDirectories(resolved.code, wizzDir, options);
|
|
353
365
|
}
|
|
354
366
|
|
|
355
367
|
// Update manifest. For custom-source installs we derive channel from the
|
|
@@ -370,7 +382,7 @@ class OfficialModules {
|
|
|
370
382
|
if (resolved.rawInput) manifestEntry.rawSource = resolved.rawInput;
|
|
371
383
|
}
|
|
372
384
|
if (resolved.localPath) manifestEntry.localPath = resolved.localPath;
|
|
373
|
-
await manifestObj.addModule(
|
|
385
|
+
await manifestObj.addModule(wizzDir, resolved.code, manifestEntry);
|
|
374
386
|
|
|
375
387
|
return {
|
|
376
388
|
success: true,
|
|
@@ -388,11 +400,11 @@ class OfficialModules {
|
|
|
388
400
|
/**
|
|
389
401
|
* Update an existing module
|
|
390
402
|
* @param {string} moduleName - Name of the module to update
|
|
391
|
-
* @param {string}
|
|
403
|
+
* @param {string} wizzDir - Target wizz directory
|
|
392
404
|
*/
|
|
393
|
-
async update(moduleName,
|
|
405
|
+
async update(moduleName, wizzDir) {
|
|
394
406
|
const sourcePath = await this.findModuleSource(moduleName);
|
|
395
|
-
const targetPath = path.join(
|
|
407
|
+
const targetPath = path.join(wizzDir, moduleName);
|
|
396
408
|
|
|
397
409
|
if (!sourcePath) {
|
|
398
410
|
throw new Error(`Module '${moduleName}' not found in any source location`);
|
|
@@ -414,10 +426,10 @@ class OfficialModules {
|
|
|
414
426
|
/**
|
|
415
427
|
* Remove a module
|
|
416
428
|
* @param {string} moduleName - Name of the module to remove
|
|
417
|
-
* @param {string}
|
|
429
|
+
* @param {string} wizzDir - Target wizz directory
|
|
418
430
|
*/
|
|
419
|
-
async remove(moduleName,
|
|
420
|
-
const targetPath = path.join(
|
|
431
|
+
async remove(moduleName, wizzDir) {
|
|
432
|
+
const targetPath = path.join(wizzDir, moduleName);
|
|
421
433
|
|
|
422
434
|
if (!(await fs.pathExists(targetPath))) {
|
|
423
435
|
throw new Error(`Module '${moduleName}' is not installed`);
|
|
@@ -434,22 +446,22 @@ class OfficialModules {
|
|
|
434
446
|
/**
|
|
435
447
|
* Check if a module is installed
|
|
436
448
|
* @param {string} moduleName - Name of the module
|
|
437
|
-
* @param {string}
|
|
449
|
+
* @param {string} wizzDir - Target wizz directory
|
|
438
450
|
* @returns {boolean} True if module is installed
|
|
439
451
|
*/
|
|
440
|
-
async isInstalled(moduleName,
|
|
441
|
-
const targetPath = path.join(
|
|
452
|
+
async isInstalled(moduleName, wizzDir) {
|
|
453
|
+
const targetPath = path.join(wizzDir, moduleName);
|
|
442
454
|
return await fs.pathExists(targetPath);
|
|
443
455
|
}
|
|
444
456
|
|
|
445
457
|
/**
|
|
446
458
|
* Get installed module info
|
|
447
459
|
* @param {string} moduleName - Name of the module
|
|
448
|
-
* @param {string}
|
|
460
|
+
* @param {string} wizzDir - Target wizz directory
|
|
449
461
|
* @returns {Object|null} Module info or null if not installed
|
|
450
462
|
*/
|
|
451
|
-
async getInstalledInfo(moduleName,
|
|
452
|
-
const targetPath = path.join(
|
|
463
|
+
async getInstalledInfo(moduleName, wizzDir) {
|
|
464
|
+
const targetPath = path.join(wizzDir, moduleName);
|
|
453
465
|
|
|
454
466
|
if (!(await fs.pathExists(targetPath))) {
|
|
455
467
|
return null;
|
|
@@ -545,17 +557,17 @@ class OfficialModules {
|
|
|
545
557
|
* This replaces the security-risky module installer pattern with declarative config
|
|
546
558
|
* During updates, if a directory path changed, moves the old directory to the new path
|
|
547
559
|
* @param {string} moduleName - Name of the module
|
|
548
|
-
* @param {string}
|
|
560
|
+
* @param {string} wizzDir - Target wizz directory
|
|
549
561
|
* @param {Object} options - Installation options
|
|
550
562
|
* @param {Object} options.moduleConfig - Module configuration from config collector
|
|
551
563
|
* @param {Object} options.existingModuleConfig - Previous module config (for detecting path changes during updates)
|
|
552
564
|
* @param {Object} options.coreConfig - Core configuration
|
|
553
565
|
* @returns {Promise<{createdDirs: string[], movedDirs: string[], createdWdsFolders: string[]}>} Created directories info
|
|
554
566
|
*/
|
|
555
|
-
async createModuleDirectories(moduleName,
|
|
567
|
+
async createModuleDirectories(moduleName, wizzDir, options = {}) {
|
|
556
568
|
const moduleConfig = options.moduleConfig || {};
|
|
557
569
|
const existingModuleConfig = options.existingModuleConfig || {};
|
|
558
|
-
const projectRoot = path.dirname(
|
|
570
|
+
const projectRoot = path.dirname(wizzDir);
|
|
559
571
|
const emptyResult = { createdDirs: [], movedDirs: [], createdWdsFolders: [] };
|
|
560
572
|
|
|
561
573
|
// Special handling for core module - it's in src/core-skills not src/modules
|
|
@@ -769,16 +781,16 @@ class OfficialModules {
|
|
|
769
781
|
// ─── Config collection methods (merged from ConfigCollector) ───
|
|
770
782
|
|
|
771
783
|
/**
|
|
772
|
-
* Find the
|
|
784
|
+
* Find the wizz installation directory in a project
|
|
773
785
|
* V6+ installations can use ANY folder name but ALWAYS have _config/manifest.yaml
|
|
774
786
|
* @param {string} projectDir - Project directory
|
|
775
|
-
* @returns {Promise<string>} Path to
|
|
787
|
+
* @returns {Promise<string>} Path to wizz directory
|
|
776
788
|
*/
|
|
777
|
-
async
|
|
789
|
+
async findWizzDir(projectDir) {
|
|
778
790
|
// Check if project directory exists
|
|
779
791
|
if (!(await fs.pathExists(projectDir))) {
|
|
780
792
|
// Project doesn't exist yet, return default
|
|
781
|
-
return path.join(projectDir, '
|
|
793
|
+
return path.join(projectDir, 'wizz');
|
|
782
794
|
}
|
|
783
795
|
|
|
784
796
|
// V6+ strategy: Look for ANY directory with _config/manifest.yaml
|
|
@@ -800,15 +812,15 @@ class OfficialModules {
|
|
|
800
812
|
|
|
801
813
|
// No V6+ installation found, return default
|
|
802
814
|
// This will be used for new installations
|
|
803
|
-
return path.join(projectDir, '
|
|
815
|
+
return path.join(projectDir, 'wizz');
|
|
804
816
|
}
|
|
805
817
|
|
|
806
818
|
/**
|
|
807
|
-
* Detect the existing
|
|
819
|
+
* Detect the existing WIZZ folder name in a project
|
|
808
820
|
* @param {string} projectDir - Project directory
|
|
809
821
|
* @returns {Promise<string|null>} Folder name (just the name, not full path) or null if not found
|
|
810
822
|
*/
|
|
811
|
-
async
|
|
823
|
+
async detectExistingWizzFolder(projectDir) {
|
|
812
824
|
// Check if project directory exists
|
|
813
825
|
if (!(await fs.pathExists(projectDir))) {
|
|
814
826
|
return null;
|
|
@@ -845,11 +857,11 @@ class OfficialModules {
|
|
|
845
857
|
return false;
|
|
846
858
|
}
|
|
847
859
|
|
|
848
|
-
// Find the actual
|
|
849
|
-
const
|
|
860
|
+
// Find the actual wizz directory (handles custom folder names)
|
|
861
|
+
const wizzDir = await this.findWizzDir(projectDir);
|
|
850
862
|
|
|
851
|
-
// Check if
|
|
852
|
-
if (!(await fs.pathExists(
|
|
863
|
+
// Check if wizz directory exists
|
|
864
|
+
if (!(await fs.pathExists(wizzDir))) {
|
|
853
865
|
return false;
|
|
854
866
|
}
|
|
855
867
|
|
|
@@ -859,7 +871,7 @@ class OfficialModules {
|
|
|
859
871
|
// every reinstall.
|
|
860
872
|
let foundAny = false;
|
|
861
873
|
for (const fileName of ['config.toml', 'config.user.toml']) {
|
|
862
|
-
const tomlPath = path.join(
|
|
874
|
+
const tomlPath = path.join(wizzDir, fileName);
|
|
863
875
|
if (!(await fs.pathExists(tomlPath))) continue;
|
|
864
876
|
try {
|
|
865
877
|
const content = await fs.readFile(tomlPath, 'utf8');
|
|
@@ -881,7 +893,7 @@ class OfficialModules {
|
|
|
881
893
|
}
|
|
882
894
|
|
|
883
895
|
// Fallback: legacy per-module config.yaml files (pre-v6 installations).
|
|
884
|
-
const entries = await fs.readdir(
|
|
896
|
+
const entries = await fs.readdir(wizzDir, { withFileTypes: true });
|
|
885
897
|
const nonModuleDirs = new Set(['_config', '_memory', 'memory', 'docs', 'scripts', 'custom']);
|
|
886
898
|
for (const entry of entries) {
|
|
887
899
|
if (entry.isDirectory()) {
|
|
@@ -889,7 +901,7 @@ class OfficialModules {
|
|
|
889
901
|
continue;
|
|
890
902
|
}
|
|
891
903
|
|
|
892
|
-
const moduleConfigPath = path.join(
|
|
904
|
+
const moduleConfigPath = path.join(wizzDir, entry.name, 'config.yaml');
|
|
893
905
|
|
|
894
906
|
if (await fs.pathExists(moduleConfigPath)) {
|
|
895
907
|
try {
|
|
@@ -1003,7 +1015,7 @@ class OfficialModules {
|
|
|
1003
1015
|
|
|
1004
1016
|
const hasFieldsWithoutDefaults = questionKeys.some((key) => {
|
|
1005
1017
|
const item = moduleConfig[key];
|
|
1006
|
-
return
|
|
1018
|
+
return OfficialModules.isMissingDefault(item.default);
|
|
1007
1019
|
});
|
|
1008
1020
|
|
|
1009
1021
|
results.push({
|
|
@@ -1435,7 +1447,7 @@ class OfficialModules {
|
|
|
1435
1447
|
result = username.charAt(0).toUpperCase() + username.slice(1);
|
|
1436
1448
|
}
|
|
1437
1449
|
} catch {
|
|
1438
|
-
// Do nothing, just return '
|
|
1450
|
+
// Do nothing, just return 'Wizz'
|
|
1439
1451
|
}
|
|
1440
1452
|
return result;
|
|
1441
1453
|
}
|
|
@@ -1526,7 +1538,7 @@ class OfficialModules {
|
|
|
1526
1538
|
await prompts.log.info(`Using default configuration for ${moduleDisplayName}`);
|
|
1527
1539
|
// Use defaults for all questions
|
|
1528
1540
|
for (const question of questions) {
|
|
1529
|
-
const hasDefault =
|
|
1541
|
+
const hasDefault = !OfficialModules.isMissingDefault(question.default);
|
|
1530
1542
|
if (hasDefault && typeof question.default !== 'function') {
|
|
1531
1543
|
allAnswers[question.name] = question.default;
|
|
1532
1544
|
}
|
|
@@ -1554,7 +1566,7 @@ class OfficialModules {
|
|
|
1554
1566
|
|
|
1555
1567
|
if (useDefaults && moduleName !== 'core') {
|
|
1556
1568
|
// Accept defaults - only ask questions that have NO default value
|
|
1557
|
-
const questionsWithoutDefaults = questions.filter((q) =>
|
|
1569
|
+
const questionsWithoutDefaults = questions.filter((q) => OfficialModules.isMissingDefault(q.default));
|
|
1558
1570
|
|
|
1559
1571
|
if (questionsWithoutDefaults.length > 0) {
|
|
1560
1572
|
await prompts.log.message(` Asking required questions for ${moduleName.toUpperCase()}...`);
|
|
@@ -1563,7 +1575,7 @@ class OfficialModules {
|
|
|
1563
1575
|
}
|
|
1564
1576
|
|
|
1565
1577
|
// For questions with defaults that weren't asked, we need to process them with their default values
|
|
1566
|
-
const questionsWithDefaults = questions.filter((q) =>
|
|
1578
|
+
const questionsWithDefaults = questions.filter((q) => !OfficialModules.isMissingDefault(q.default));
|
|
1567
1579
|
for (const question of questionsWithDefaults) {
|
|
1568
1580
|
// Skip function defaults - these are dynamic and will be evaluated later
|
|
1569
1581
|
if (typeof question.default === 'function') {
|
|
@@ -354,12 +354,12 @@ class PluginResolver {
|
|
|
354
354
|
|
|
355
355
|
/**
|
|
356
356
|
* Format a kebab-case or snake_case name into a display name.
|
|
357
|
-
* Strips common prefixes like "
|
|
357
|
+
* Strips common prefixes like "wizz-" or "wizz-agent-".
|
|
358
358
|
* @param {string} name - Raw name
|
|
359
359
|
* @returns {string} Formatted display name
|
|
360
360
|
*/
|
|
361
361
|
_formatDisplayName(name) {
|
|
362
|
-
let cleaned = name.replace(/^
|
|
362
|
+
let cleaned = name.replace(/^wizz-agent-/, '').replace(/^wizz-/, '');
|
|
363
363
|
return cleaned
|
|
364
364
|
.split(/[-_]/)
|
|
365
365
|
.map((word) => word.charAt(0).toUpperCase() + word.slice(1))
|
|
@@ -373,7 +373,7 @@ class PluginResolver {
|
|
|
373
373
|
* @returns {string} Menu code (e.g., "CC" for "code-coach")
|
|
374
374
|
*/
|
|
375
375
|
_generateMenuCode(name) {
|
|
376
|
-
const cleaned = name.replace(/^
|
|
376
|
+
const cleaned = name.replace(/^wizz-agent-/, '').replace(/^wizz-/, '');
|
|
377
377
|
const words = cleaned.split(/[-_]/).filter((w) => w.length > 0);
|
|
378
378
|
return words
|
|
379
379
|
.map((w) => w.charAt(0).toUpperCase())
|
|
@@ -4,21 +4,21 @@ const yaml = require('yaml');
|
|
|
4
4
|
const fs = require('./fs-native');
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
|
-
* Find the
|
|
8
|
-
* or specific
|
|
7
|
+
* Find the WIZZ project root directory by looking for package.json
|
|
8
|
+
* or specific WIZZ markers
|
|
9
9
|
*/
|
|
10
10
|
function findProjectRoot(startPath = __dirname) {
|
|
11
11
|
let currentPath = path.resolve(startPath);
|
|
12
12
|
|
|
13
|
-
// Keep going up until we find package.json with
|
|
13
|
+
// Keep going up until we find package.json with wizz-method
|
|
14
14
|
while (currentPath !== path.dirname(currentPath)) {
|
|
15
15
|
const packagePath = path.join(currentPath, 'package.json');
|
|
16
16
|
|
|
17
17
|
if (fs.existsSync(packagePath)) {
|
|
18
18
|
try {
|
|
19
19
|
const pkg = fs.readJsonSync(packagePath);
|
|
20
|
-
// Check if this is the
|
|
21
|
-
if (pkg.name === '
|
|
20
|
+
// Check if this is the WIZZ project
|
|
21
|
+
if (pkg.name === 'wizz-method' || fs.existsSync(path.join(currentPath, 'src', 'core-skills'))) {
|
|
22
22
|
return currentPath;
|
|
23
23
|
}
|
|
24
24
|
} catch {
|
|
@@ -77,7 +77,7 @@ function getModulePath(moduleName, ...segments) {
|
|
|
77
77
|
* by ExternalModuleManager during install and are not copied into <src>/modules/.
|
|
78
78
|
*/
|
|
79
79
|
function getExternalModuleCachePath(moduleName, ...segments) {
|
|
80
|
-
const base = process.env.
|
|
80
|
+
const base = process.env.WIZZ_EXTERNAL_MODULES_CACHE || path.join(os.homedir(), '.wizz', 'cache', 'external-modules');
|
|
81
81
|
return path.join(base, moduleName, ...segments);
|
|
82
82
|
}
|
|
83
83
|
|
|
@@ -85,9 +85,9 @@ function getExternalModuleCachePath(moduleName, ...segments) {
|
|
|
85
85
|
* Locate an installed module's `module.yaml` by filesystem lookup only.
|
|
86
86
|
*
|
|
87
87
|
* Built-in modules (core, bmm) live under <src>. External official modules are
|
|
88
|
-
* cloned into ~/.
|
|
88
|
+
* cloned into ~/.wizz/cache/external-modules/<name>/ with varying internal
|
|
89
89
|
* layouts (some at src/module.yaml, some at skills/module.yaml, some nested).
|
|
90
|
-
* Url-source custom modules are cloned into ~/.
|
|
90
|
+
* Url-source custom modules are cloned into ~/.wizz/cache/custom-modules/<host>/<owner>/<repo>/
|
|
91
91
|
* and are resolved by walking the cache and matching `code` or `name` from the
|
|
92
92
|
* discovered module.yaml. Local custom-source modules are not cached; their
|
|
93
93
|
* path is read from the CustomModuleManager resolution cache set during the
|
|
@@ -155,11 +155,11 @@ async function resolveInstalledModuleYaml(moduleName) {
|
|
|
155
155
|
if (found) return found;
|
|
156
156
|
}
|
|
157
157
|
|
|
158
|
-
// Community modules are cloned to ~/.
|
|
158
|
+
// Community modules are cloned to ~/.wizz/cache/community-modules/<name>/
|
|
159
159
|
// (parallel to the external-modules cache used above). Search there too so
|
|
160
160
|
// collectAgentsFromModuleYaml and writeCentralConfig can locate community
|
|
161
161
|
// module.yaml files regardless of how nested the layout is.
|
|
162
|
-
const communityCacheRoot = path.join(os.homedir(), '.
|
|
162
|
+
const communityCacheRoot = path.join(os.homedir(), '.wizz', 'cache', 'community-modules', moduleName);
|
|
163
163
|
if (await fs.pathExists(communityCacheRoot)) {
|
|
164
164
|
const found = await searchRoot(communityCacheRoot);
|
|
165
165
|
if (found) return found;
|
|
@@ -180,15 +180,15 @@ async function resolveInstalledModuleYaml(moduleName) {
|
|
|
180
180
|
// Resolution cache unavailable — continue
|
|
181
181
|
}
|
|
182
182
|
|
|
183
|
-
// Fallback: url-source custom modules cloned to ~/.
|
|
183
|
+
// Fallback: url-source custom modules cloned to ~/.wizz/cache/custom-modules/.
|
|
184
184
|
// Walk every cached repo, enumerate ALL module.yaml files via searchRootAll
|
|
185
185
|
// (a single repo can host multiple plugins in discovery mode), and match by
|
|
186
186
|
// the yaml's `code` or `name` field. This works on re-install runs where
|
|
187
187
|
// _resolutionCache is empty and covers both discovery-mode (with marketplace.json)
|
|
188
|
-
// and direct-mode modules, since we identify repo roots by .
|
|
188
|
+
// and direct-mode modules, since we identify repo roots by .wizz-source.json
|
|
189
189
|
// (written by cloneRepo) or .claude-plugin/ rather than by marketplace.json.
|
|
190
190
|
try {
|
|
191
|
-
const customCacheDir = path.join(os.homedir(), '.
|
|
191
|
+
const customCacheDir = path.join(os.homedir(), '.wizz', 'cache', 'custom-modules');
|
|
192
192
|
if (await fs.pathExists(customCacheDir)) {
|
|
193
193
|
const { CustomModuleManager } = require('./modules/custom-module-manager');
|
|
194
194
|
const customMgr = new CustomModuleManager();
|
|
@@ -230,16 +230,16 @@ async function tomlHasKey(filePath, section, key) {
|
|
|
230
230
|
* (not in either file yet), team scope is the safe default.
|
|
231
231
|
*
|
|
232
232
|
* @param {Object<string, Object<string, string>>} overrides
|
|
233
|
-
* @param {string}
|
|
233
|
+
* @param {string} wizzDir absolute path to `_wizz/`
|
|
234
234
|
* @returns {Promise<Array<{module:string,key:string,scope:'team'|'user',file:string}>>}
|
|
235
235
|
* a list of applied entries (for caller logging)
|
|
236
236
|
*/
|
|
237
|
-
async function applySetOverrides(overrides,
|
|
237
|
+
async function applySetOverrides(overrides, wizzDir) {
|
|
238
238
|
const applied = [];
|
|
239
239
|
if (!overrides || typeof overrides !== 'object') return applied;
|
|
240
240
|
|
|
241
|
-
const teamPath = path.join(
|
|
242
|
-
const userPath = path.join(
|
|
241
|
+
const teamPath = path.join(wizzDir, 'config.toml');
|
|
242
|
+
const userPath = path.join(wizzDir, 'config.user.toml');
|
|
243
243
|
|
|
244
244
|
for (const moduleCode of Object.keys(overrides)) {
|
|
245
245
|
// Skip overrides for modules not actually installed. The installer writes
|
|
@@ -247,7 +247,7 @@ async function applySetOverrides(overrides, bmadDir) {
|
|
|
247
247
|
// so its presence is a reliable "is this module here?" signal that works
|
|
248
248
|
// for both fresh installs and quick-updates without coupling to caller-
|
|
249
249
|
// supplied module lists.
|
|
250
|
-
const moduleConfigYaml = path.join(
|
|
250
|
+
const moduleConfigYaml = path.join(wizzDir, moduleCode, 'config.yaml');
|
|
251
251
|
if (!(await fs.pathExists(moduleConfigYaml))) {
|
|
252
252
|
continue;
|
|
253
253
|
}
|
|
@@ -291,7 +291,7 @@ async function applySetOverrides(overrides, bmadDir) {
|
|
|
291
291
|
// value lives in the per-module yaml but won't be re-emitted into
|
|
292
292
|
// config.toml on the next install (the schema-strict partition drops
|
|
293
293
|
// it); re-pass `--set` if you need it sticky.
|
|
294
|
-
const moduleYamlPath = path.join(
|
|
294
|
+
const moduleYamlPath = path.join(wizzDir, moduleCode, 'config.yaml');
|
|
295
295
|
if (await fs.pathExists(moduleYamlPath)) {
|
|
296
296
|
try {
|
|
297
297
|
const text = await fs.readFile(moduleYamlPath, 'utf8');
|
package/tools/installer/ui.js
CHANGED
|
@@ -110,7 +110,7 @@ async function getModuleVersion(moduleCode, { repoUrl = null, registryDefault =
|
|
|
110
110
|
* UI utilities for the installer
|
|
111
111
|
*/
|
|
112
112
|
class UI {
|
|
113
|
-
async _retainUnavailableInstalledModules(selectedModules, installedModuleIds,
|
|
113
|
+
async _retainUnavailableInstalledModules(selectedModules, installedModuleIds, wizzDir, options = {}) {
|
|
114
114
|
const { OfficialModules } = require('./modules/official-modules');
|
|
115
115
|
const officialCodes = new Set(['core']);
|
|
116
116
|
|
|
@@ -135,7 +135,7 @@ class UI {
|
|
|
135
135
|
if (!selectedSet.has(moduleId) && !options.preserveUnselected) continue;
|
|
136
136
|
if (officialCodes.has(moduleId)) continue;
|
|
137
137
|
|
|
138
|
-
const customSource = await customMgr.findModuleSourceByCode(moduleId, {
|
|
138
|
+
const customSource = await customMgr.findModuleSourceByCode(moduleId, { wizzDir });
|
|
139
139
|
if (!customSource) {
|
|
140
140
|
preserveModules.push(moduleId);
|
|
141
141
|
}
|
|
@@ -161,7 +161,7 @@ class UI {
|
|
|
161
161
|
const messageLoader = new MessageLoader();
|
|
162
162
|
await messageLoader.displayStartMessage();
|
|
163
163
|
|
|
164
|
-
// Probe the local Python before any other prompts: several
|
|
164
|
+
// Probe the local Python before any other prompts: several WIZZ features
|
|
165
165
|
// (memlog session memory, TOML config resolution) need Python 3.11+ at
|
|
166
166
|
// runtime. Warn-don't-block, but require an explicit ack so the warning
|
|
167
167
|
// can't scroll past unseen. The installer runs in the destination
|
|
@@ -213,10 +213,10 @@ class UI {
|
|
|
213
213
|
|
|
214
214
|
const { Installer } = require('./core/installer');
|
|
215
215
|
const installer = new Installer();
|
|
216
|
-
const {
|
|
216
|
+
const { wizzDir } = await installer.findWizzDir(confirmedDirectory);
|
|
217
217
|
|
|
218
|
-
// Check if there's an existing
|
|
219
|
-
const hasExistingInstall = await fs.pathExists(
|
|
218
|
+
// Check if there's an existing WIZZ installation
|
|
219
|
+
const hasExistingInstall = await fs.pathExists(wizzDir);
|
|
220
220
|
|
|
221
221
|
// Track action type (only set if there's an existing installation)
|
|
222
222
|
let actionType;
|
|
@@ -224,7 +224,7 @@ class UI {
|
|
|
224
224
|
// Only show action menu if there's an existing installation
|
|
225
225
|
if (hasExistingInstall) {
|
|
226
226
|
// Get version information
|
|
227
|
-
const { existingInstall,
|
|
227
|
+
const { existingInstall, wizzDir } = await this.getExistingInstallation(confirmedDirectory);
|
|
228
228
|
|
|
229
229
|
// Build menu choices dynamically
|
|
230
230
|
const choices = [];
|
|
@@ -321,7 +321,7 @@ class UI {
|
|
|
321
321
|
selectedModules.unshift('core');
|
|
322
322
|
}
|
|
323
323
|
|
|
324
|
-
const retainedModuleResult = await this._retainUnavailableInstalledModules(selectedModules, installedModuleIds,
|
|
324
|
+
const retainedModuleResult = await this._retainUnavailableInstalledModules(selectedModules, installedModuleIds, wizzDir, {
|
|
325
325
|
preserveUnselected: options.yes && !options.modules,
|
|
326
326
|
});
|
|
327
327
|
selectedModules = retainedModuleResult.selectedModules;
|
|
@@ -339,7 +339,7 @@ class UI {
|
|
|
339
339
|
// default Y, major default N). Legacy entries with no channel are
|
|
340
340
|
// migrated here too. Mutates channelOptions.pins to lock rejections.
|
|
341
341
|
await this._resolveUpdateChannels({
|
|
342
|
-
|
|
342
|
+
wizzDir,
|
|
343
343
|
selectedModules,
|
|
344
344
|
channelOptions,
|
|
345
345
|
yes: options.yes || false,
|
|
@@ -503,8 +503,8 @@ class UI {
|
|
|
503
503
|
const { ExistingInstall } = require('./core/existing-install');
|
|
504
504
|
const { Installer } = require('./core/installer');
|
|
505
505
|
const installer = new Installer();
|
|
506
|
-
const {
|
|
507
|
-
const existingInstall = await ExistingInstall.detect(
|
|
506
|
+
const { wizzDir } = await installer.findWizzDir(projectDir || process.cwd());
|
|
507
|
+
const existingInstall = await ExistingInstall.detect(wizzDir);
|
|
508
508
|
const configuredIdes = existingInstall.ides;
|
|
509
509
|
|
|
510
510
|
// Get IDE manager to fetch available IDEs dynamically
|
|
@@ -732,17 +732,17 @@ class UI {
|
|
|
732
732
|
/**
|
|
733
733
|
* Get existing installation info and installed modules
|
|
734
734
|
* @param {string} directory - Installation directory
|
|
735
|
-
* @returns {Object} Object with existingInstall, installedModuleIds, installedModuleVersions, and
|
|
735
|
+
* @returns {Object} Object with existingInstall, installedModuleIds, installedModuleVersions, and wizzDir
|
|
736
736
|
*/
|
|
737
737
|
async getExistingInstallation(directory) {
|
|
738
738
|
const { ExistingInstall } = require('./core/existing-install');
|
|
739
739
|
const { Installer } = require('./core/installer');
|
|
740
740
|
const installer = new Installer();
|
|
741
|
-
const {
|
|
742
|
-
const existingInstall = await ExistingInstall.detect(
|
|
741
|
+
const { wizzDir } = await installer.findWizzDir(directory);
|
|
742
|
+
const existingInstall = await ExistingInstall.detect(wizzDir);
|
|
743
743
|
const installedModuleIds = new Set(existingInstall.moduleIds);
|
|
744
744
|
const installedModuleVersions = new Map();
|
|
745
|
-
const manifestModules = await manifest.getAllModuleVersions(
|
|
745
|
+
const manifestModules = await manifest.getAllModuleVersions(wizzDir);
|
|
746
746
|
|
|
747
747
|
for (const module of manifestModules) {
|
|
748
748
|
if (module?.name && module.version) {
|
|
@@ -760,7 +760,7 @@ class UI {
|
|
|
760
760
|
installedModuleVersions.set('core', existingInstall.version);
|
|
761
761
|
}
|
|
762
762
|
|
|
763
|
-
return { existingInstall, installedModuleIds, installedModuleVersions,
|
|
763
|
+
return { existingInstall, installedModuleIds, installedModuleVersions, wizzDir };
|
|
764
764
|
}
|
|
765
765
|
|
|
766
766
|
/**
|
|
@@ -1355,15 +1355,15 @@ class UI {
|
|
|
1355
1355
|
if (stats.isDirectory()) {
|
|
1356
1356
|
const files = await fs.readdir(directory);
|
|
1357
1357
|
if (files.length > 0) {
|
|
1358
|
-
// Check for any
|
|
1358
|
+
// Check for any wizz installation (any folder with _config/manifest.yaml)
|
|
1359
1359
|
const { Installer } = require('./core/installer');
|
|
1360
1360
|
const installer = new Installer();
|
|
1361
|
-
const
|
|
1362
|
-
const
|
|
1363
|
-
(await fs.pathExists(
|
|
1361
|
+
const wizzResult = await installer.findWizzDir(directory);
|
|
1362
|
+
const hasWizzInstall =
|
|
1363
|
+
(await fs.pathExists(wizzResult.wizzDir)) && (await fs.pathExists(path.join(wizzResult.wizzDir, '_config', 'manifest.yaml')));
|
|
1364
1364
|
|
|
1365
|
-
const
|
|
1366
|
-
await prompts.log.message(`Directory exists and contains ${files.length} item(s)${
|
|
1365
|
+
const wizzNote = hasWizzInstall ? ` including existing Wizz installation (${path.basename(wizzResult.wizzDir)})` : '';
|
|
1366
|
+
await prompts.log.message(`Directory exists and contains ${files.length} item(s)${wizzNote}`);
|
|
1367
1367
|
} else {
|
|
1368
1368
|
await prompts.log.message('Directory exists and is empty');
|
|
1369
1369
|
}
|
|
@@ -1601,8 +1601,8 @@ class UI {
|
|
|
1601
1601
|
const { ExistingInstall } = require('./core/existing-install');
|
|
1602
1602
|
const { Installer } = require('./core/installer');
|
|
1603
1603
|
const installer = new Installer();
|
|
1604
|
-
const {
|
|
1605
|
-
const existingInstall = await ExistingInstall.detect(
|
|
1604
|
+
const { wizzDir } = await installer.findWizzDir(directory);
|
|
1605
|
+
const existingInstall = await ExistingInstall.detect(wizzDir);
|
|
1606
1606
|
return existingInstall.ides;
|
|
1607
1607
|
}
|
|
1608
1608
|
|
|
@@ -1695,12 +1695,12 @@ class UI {
|
|
|
1695
1695
|
* @param {Object} statusData - Status data with modules, installation info, and available updates
|
|
1696
1696
|
*/
|
|
1697
1697
|
async displayStatus(statusData) {
|
|
1698
|
-
const { installation, modules, availableUpdates,
|
|
1698
|
+
const { installation, modules, availableUpdates, wizzDir } = statusData;
|
|
1699
1699
|
|
|
1700
1700
|
// Installation info
|
|
1701
1701
|
const infoLines = [
|
|
1702
1702
|
`Version: ${installation.version || 'unknown'}`,
|
|
1703
|
-
`Location: ${
|
|
1703
|
+
`Location: ${wizzDir}`,
|
|
1704
1704
|
`Installed: ${new Date(installation.installDate).toLocaleDateString()}`,
|
|
1705
1705
|
`Last Updated: ${installation.lastUpdated ? new Date(installation.lastUpdated).toLocaleDateString() : 'unknown'}`,
|
|
1706
1706
|
];
|
|
@@ -1855,10 +1855,10 @@ class UI {
|
|
|
1855
1855
|
* Decisions that freeze the current version are applied by adding a pin to
|
|
1856
1856
|
* `channelOptions.pins` so downstream clone logic honors them.
|
|
1857
1857
|
*/
|
|
1858
|
-
async _resolveUpdateChannels({
|
|
1858
|
+
async _resolveUpdateChannels({ wizzDir, selectedModules, channelOptions, yes }) {
|
|
1859
1859
|
const { Manifest } = require('./core/manifest');
|
|
1860
1860
|
const manifestObj = new Manifest();
|
|
1861
|
-
const manifest = await manifestObj.read(
|
|
1861
|
+
const manifest = await manifestObj.read(wizzDir);
|
|
1862
1862
|
const existingByName = new Map();
|
|
1863
1863
|
for (const m of manifest?.modulesDetailed || []) {
|
|
1864
1864
|
if (m?.name) existingByName.set(m.name, m);
|
|
@@ -1899,7 +1899,7 @@ class UI {
|
|
|
1899
1899
|
if (!info) continue;
|
|
1900
1900
|
// Bundled modules (core/bmm) ship with the installer binary itself —
|
|
1901
1901
|
// their version is stapled to the CLI version, not a git tag. Skip
|
|
1902
|
-
// tag-API lookups for them; the "upgrade" mechanism is `npx
|
|
1902
|
+
// tag-API lookups for them; the "upgrade" mechanism is `npx wizz@X install`.
|
|
1903
1903
|
if (info.builtIn) continue;
|
|
1904
1904
|
|
|
1905
1905
|
const repoUrl = info.url;
|