wize-dev-kit 0.11.0 → 0.12.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (92) hide show
  1. package/AGENTS.md +3 -3
  2. package/CHANGELOG.md +37 -0
  3. package/README.es.md +3 -1
  4. package/README.md +3 -1
  5. package/README.pt-BR.md +3 -1
  6. package/package.json +1 -1
  7. package/src/app-overlay/wize-app-release-channels/workflow.md +2 -0
  8. package/src/app-overlay/wize-app-scaffold/workflow.md +2 -0
  9. package/src/app-overlay/wize-app-store-listing/workflow.md +2 -0
  10. package/src/builder-skills/wize-create-agent/workflow.md +2 -0
  11. package/src/builder-skills/wize-create-skill/workflow.md +2 -0
  12. package/src/builder-skills/wize-create-workflow/workflow.md +2 -0
  13. package/src/core-skills/module.yaml +3 -0
  14. package/src/core-skills/wize-advanced-elicitation/skill.md +2 -0
  15. package/src/core-skills/wize-brainstorming/skill.md +2 -0
  16. package/src/core-skills/wize-customize/skill.md +2 -0
  17. package/src/core-skills/wize-editorial-review-prose/skill.md +2 -0
  18. package/src/core-skills/wize-editorial-review-structure/skill.md +2 -0
  19. package/src/core-skills/wize-grill/skill.md +3 -1
  20. package/src/core-skills/wize-index-docs/skill.md +3 -1
  21. package/src/core-skills/wize-pre-pr-check/skill.md +134 -0
  22. package/src/core-skills/wize-review-adversarial/skill.md +2 -0
  23. package/src/core-skills/wize-review-edge-case-hunter/skill.md +2 -0
  24. package/src/core-skills/wize-shard-doc/skill.md +2 -0
  25. package/src/core-skills/wize-spec/skill.md +2 -0
  26. package/src/method-skills/1-analysis/wize-agent-analyst/agent.yaml +3 -0
  27. package/src/method-skills/1-analysis/wize-document-project/workflow.md +2 -0
  28. package/src/method-skills/1-analysis/wize-domain-research/workflow.md +7 -0
  29. package/src/method-skills/1-analysis/wize-market-research/workflow.md +7 -0
  30. package/src/method-skills/1-analysis/wize-prfaq/workflow.md +2 -0
  31. package/src/method-skills/1-analysis/wize-product-brief/workflow.md +2 -0
  32. package/src/method-skills/1-analysis/wize-refresh-knowledge/workflow.md +3 -1
  33. package/src/method-skills/1-analysis/wize-research/workflow.md +24 -89
  34. package/src/method-skills/1-analysis/wize-technical-research/workflow.md +7 -0
  35. package/src/method-skills/1-analysis/wize-trigger-map/workflow.md +2 -0
  36. package/src/method-skills/2-plan-workflows/wize-create-prd/workflow.md +2 -0
  37. package/src/method-skills/2-plan-workflows/wize-edit-prd/workflow.md +3 -1
  38. package/src/method-skills/2-plan-workflows/wize-ux-design/workflow.md +2 -0
  39. package/src/method-skills/2-plan-workflows/wize-ux-scenarios/workflow.md +2 -0
  40. package/src/method-skills/2-plan-workflows/wize-validate-prd/workflow.md +2 -0
  41. package/src/method-skills/3-solutioning/wize-check-implementation-readiness/workflow.md +2 -0
  42. package/src/method-skills/3-solutioning/wize-create-architecture/steps/step-08-complete.md +1 -1
  43. package/src/method-skills/3-solutioning/wize-create-architecture/workflow.md +2 -0
  44. package/src/method-skills/3-solutioning/wize-create-epics-and-stories/workflow.md +2 -0
  45. package/src/method-skills/3-solutioning/wize-design-system/workflow.md +2 -0
  46. package/src/method-skills/3-solutioning/wize-nfr-principles/workflow.md +3 -1
  47. package/src/method-skills/3-solutioning/wize-project-context/workflow.md +3 -1
  48. package/src/method-skills/3-solutioning/wize-tech-vision/workflow.md +3 -1
  49. package/src/method-skills/4-implementation/wize-changelog/workflow.md +184 -0
  50. package/src/method-skills/4-implementation/wize-checkpoint-preview/workflow.md +2 -0
  51. package/src/method-skills/4-implementation/wize-code-review/workflow.md +2 -0
  52. package/src/method-skills/4-implementation/wize-correct-course/workflow.md +2 -0
  53. package/src/method-skills/4-implementation/wize-create-story/workflow.md +2 -0
  54. package/src/method-skills/4-implementation/wize-dev-story/workflow.md +3 -1
  55. package/src/method-skills/4-implementation/wize-investigate/workflow.md +2 -0
  56. package/src/method-skills/4-implementation/wize-quick-dev/workflow.md +2 -0
  57. package/src/method-skills/4-implementation/wize-release/workflow.md +162 -0
  58. package/src/method-skills/4-implementation/wize-retrospective/workflow.md +2 -0
  59. package/src/method-skills/4-implementation/wize-sprint-planning/workflow.md +2 -0
  60. package/src/method-skills/4-implementation/wize-sprint-status/workflow.md +2 -0
  61. package/src/method-skills/module.yaml +12 -3
  62. package/src/orchestrator-skills/module.yaml +4 -1
  63. package/src/orchestrator-skills/wize/skill.md +164 -0
  64. package/src/orchestrator-skills/wize-help/skill.md +126 -5
  65. package/src/orchestrator-skills/wize-onboarding/workflow.md +3 -1
  66. package/src/orchestrator-skills/wize-orchestrator/agent.yaml +1 -0
  67. package/src/orchestrator-skills/wize-orchestrator/persona.md +29 -4
  68. package/src/orchestrator-skills/wize-party-mode/workflow.md +2 -0
  69. package/src/security-overlay/_shared/scope-parser.js +27 -0
  70. package/src/security-overlay/agents/red-teamer/agent.yaml +2 -0
  71. package/src/security-overlay/agents/red-teamer/persona.md +6 -0
  72. package/src/security-overlay/skills/wize-sec-enumerate/skill.md +2 -0
  73. package/src/security-overlay/skills/wize-sec-pentest/scripts/run-pipeline.js +18 -1
  74. package/src/security-overlay/skills/wize-sec-pentest/skill.md +2 -0
  75. package/src/security-overlay/skills/wize-sec-recon/skill.md +2 -0
  76. package/src/security-overlay/skills/wize-sec-scope/scripts/generate-scope.js +106 -0
  77. package/src/security-overlay/skills/wize-sec-scope/skill.md +52 -0
  78. package/src/tea-skills/wize-qa-generate-e2e-tests/workflow.md +2 -0
  79. package/src/tea-skills/wize-tea-design/workflow.md +3 -0
  80. package/src/tea-skills/wize-tea-gate/workflow.md +3 -0
  81. package/src/tea-skills/wize-tea-nfr/workflow.md +3 -0
  82. package/src/tea-skills/wize-tea-review/workflow.md +3 -0
  83. package/src/tea-skills/wize-tea-risk/workflow.md +3 -0
  84. package/src/tea-skills/wize-tea-trace/workflow.md +3 -0
  85. package/src/web-overlay/wize-web-deploy/workflow.md +2 -0
  86. package/src/web-overlay/wize-web-scaffold/workflow.md +2 -0
  87. package/src/web-overlay/wize-web-seo-audit/workflow.md +2 -0
  88. package/tools/installer/commands/doctor.js +2 -2
  89. package/tools/installer/onboarding.js +14 -21
  90. package/tools/installer/render-shared.js +50 -28
  91. package/tools/installer/validators/run-all.js +3 -2
  92. package/tools/installer/wize-cli.js +323 -77
@@ -13,7 +13,7 @@ const { walkAgents, walkWorkflows, walkSkills } = require('./walk.js');
13
13
  function checkAgent(file) {
14
14
  const content = fs.readFileSync(file, 'utf-8');
15
15
  const errs = [];
16
- if (!/^code:\s+wize-/m.test(content)) errs.push('missing or invalid "code:" prefix');
16
+ if (!/^code:\s+wize(-|$)/m.test(content)) errs.push('missing or invalid "code:" prefix');
17
17
  if (!/^name:/m.test(content)) errs.push('missing "name:"');
18
18
  if (!/^title:/m.test(content)) errs.push('missing "title:"');
19
19
  if (!/^description:/m.test(content)) errs.push('missing "description:"');
@@ -24,9 +24,10 @@ function checkWorkflow(file) {
24
24
  const content = fs.readFileSync(file, 'utf-8');
25
25
  const errs = [];
26
26
  if (!/^---\s*$/m.test(content)) errs.push('missing YAML frontmatter');
27
- if (!/^code:\s+wize-/m.test(content)) errs.push('missing or invalid "code:" prefix');
27
+ if (!/^code:\s+wize(-|$)/m.test(content)) errs.push('missing or invalid "code:" prefix');
28
28
  if (!/^name:/m.test(content)) errs.push('missing "name:"');
29
29
  if (!/^owner:/m.test(content) && !/^module:/m.test(content)) errs.push('missing "owner:" or "module:"');
30
+ if (!/^description:/m.test(content)) errs.push('missing "description:"');
30
31
  return errs;
31
32
  }
32
33
 
@@ -3,9 +3,9 @@
3
3
  * wize-dev-kit — CLI entry point
4
4
  * Subcommands: install, update, uninstall, list, sync, agent, workflow, help
5
5
  *
6
- * This is a v0.1 scaffold. The interactive prompt logic and adapter rendering
7
- * are stubs; the dispatcher and basic install/uninstall create the .wize/
8
- * folder layout so downstream agents can be activated.
6
+ * v0.12.1 — Full-lifecycle CLI with install, update, uninstall, list, sync,
7
+ * agent, workflow, validate, doctor, and document-project commands. Adapters
8
+ * render for 9 IDE targets. Security overlay ships with 8 tools.
9
9
  */
10
10
  'use strict';
11
11
 
@@ -13,13 +13,14 @@ const fs = require('node:fs');
13
13
  const os = require('node:os');
14
14
  const path = require('node:path');
15
15
  const readline = require('node:readline');
16
+ const { execSync } = require('node:child_process');
16
17
  const prompts = require('prompts');
17
18
  const { applyGitignore, generateUserToml } = require('./setup-helpers.js');
18
- const { cmdUpdate } = require('./commands/update.js');
19
+ const { cmdUpdate, loadProjectConfig } = require('./commands/update.js');
19
20
  const { printUpdateHintIfAny } = require('./version-check.js');
20
21
  const { cmdSync: cmdSyncReal } = require('./commands/sync.js');
21
22
  const { cmdAgentList, cmdAgentCreate, cmdAgentEdit } = require('./commands/agent.js');
22
- const { cmdDoctor } = require('./commands/doctor.js');
23
+ const { cmdDoctor, adapterTargetPath } = require('./commands/doctor.js');
23
24
  const { cmdDocumentProject } = require('./commands/document-project.js');
24
25
  const { compose: composeOnboarding } = require('./onboarding.js');
25
26
 
@@ -425,52 +426,167 @@ function renderAdapters({ kitRoot, projectRoot, targets, profiles }) {
425
426
  return results;
426
427
  }
427
428
 
429
+ // Parse --key value and --flag from an argv slice. Returns { flags, positional }.
430
+ function parseArgs(args) {
431
+ const flags = {};
432
+ const positional = [];
433
+ for (let i = 0; i < args.length; i++) {
434
+ const a = args[i];
435
+ if (a.startsWith('--')) {
436
+ const key = a.slice(2);
437
+ if (key.includes('=')) {
438
+ const [k, v] = key.split('=', 2);
439
+ flags[k] = v;
440
+ } else if (i + 1 < args.length && !args[i + 1].startsWith('--')) {
441
+ flags[key] = args[++i];
442
+ } else {
443
+ flags[key] = true;
444
+ }
445
+ } else {
446
+ positional.push(a);
447
+ }
448
+ }
449
+ return { flags, positional };
450
+ }
451
+
452
+ function resolveProfiles(flags) {
453
+ if (!flags.profiles) return null;
454
+ const codes = flags.profiles.split(',').map(s => s.trim()).filter(Boolean);
455
+ const resolved = [];
456
+ for (const c of codes) {
457
+ const p = PROFILES.find(p => p.code === c);
458
+ if (p) resolved.push(p);
459
+ else console.log(`⚠ perfil desconhecido: "${c}" — ignorado`);
460
+ }
461
+ if (resolved.length === 0) return null;
462
+ return resolved;
463
+ }
464
+
465
+ function resolveTargets(flags) {
466
+ if (!flags.targets) return null;
467
+ const codes = flags.targets.split(',').map(s => s.trim()).filter(Boolean);
468
+ const resolved = [];
469
+ for (const c of codes) {
470
+ const t = TARGETS.find(t => t.code === c);
471
+ if (t) resolved.push(t);
472
+ else console.log(`⚠ target desconhecido: "${c}" — ignorado`);
473
+ }
474
+ if (resolved.length === 0) return null;
475
+ return resolved;
476
+ }
477
+
478
+ function resolveLang(flags) {
479
+ if (!flags.lang) return null;
480
+ const code = flags.lang.trim();
481
+ if (/^[A-Za-z]{2,3}(-[A-Za-z0-9]{2,8})?$/.test(code)) return code;
482
+ console.log(`⚠ código de idioma inválido: "${code}" — usando pt-BR`);
483
+ return null;
484
+ }
485
+
486
+ function resolveName(flags) {
487
+ if (flags.name) return flags.name.trim();
488
+ if (flags.yes) {
489
+ try { return execSync('git config user.name', { encoding: 'utf-8' }).trim(); } catch (_) {}
490
+ return process.env.USER || process.env.USERNAME || 'Developer';
491
+ }
492
+ return null;
493
+ }
494
+
495
+ function defaultProfiles() {
496
+ return PROFILES.filter(p => p.required || p.code === 'core');
497
+ }
498
+
499
+ function defaultTargets() {
500
+ return TARGETS.filter(t => t.default);
501
+ }
502
+
428
503
  async function cmdInstall(args) {
429
504
  const cwd = process.cwd();
505
+ const { flags } = parseArgs(args);
506
+ const dryRun = !!flags['dry-run'];
507
+ const nonInteractive = !!flags.yes;
508
+
430
509
  console.log(logo());
431
- console.log('Installing Wize Development Kit into:', cwd);
510
+ if (dryRun) console.log('[DRY-RUN] Nenhum arquivo será modificado.\n');
511
+ console.log('Instalando Wize Development Kit em:', cwd);
512
+
432
513
  if (!isGitRepo(cwd)) {
433
- console.log('\n⚠ not a git repo. Initialize git first or proceed at your own risk.');
434
- const ok = await confirm('Continue anyway?', false);
514
+ console.log('\n⚠ não é um repositório git. Inicialize o git primeiro ou prossiga por sua conta e risco.');
515
+ if (nonInteractive) {
516
+ console.log('Modo não-interativo: abortando. Use --yes apenas em repositórios git.');
517
+ process.exit(1);
518
+ }
519
+ const ok = await confirm('Continuar mesmo assim?', false);
435
520
  if (!ok) process.exit(1);
436
521
  }
437
522
 
438
523
  const detection = detectBrownfield(cwd);
439
524
  if (detection.brownfield) {
440
- console.log(`\nBrownfield signals detected: ${detection.signals.join(', ')}`);
525
+ console.log(`\nSinais de brownfield detectados: ${detection.signals.join(', ')}`);
441
526
  } else {
442
- console.log('\nGreenfield repo detected.');
443
- }
444
-
445
- const project_name = (await promptText(`Project name`, path.basename(cwd))) || path.basename(cwd);
446
- const profiles = await multiSelect('Select profile(s) to install', PROFILES);
447
- const targets = await multiSelect('Select IDE target(s)', TARGETS);
448
-
449
- const communication_language = await selectLanguage(
450
- 'Communication language (how agents will talk to you in chat)',
451
- 'en'
452
- );
453
- const document_output_language = await selectLanguage(
454
- `Document output language (language used in generated files; ENTER for "${communication_language}")`,
455
- communication_language
456
- );
457
-
458
- // Personal touch — the user_name lands in .wize/config/user.toml (per-developer).
459
- // Always ask; do not silently accept the OS username, because the install must
460
- // feel personal and avoid misnaming the user in agent conversations.
461
- const defaultName = (os.userInfo().username || '').trim();
462
- const user_name = await promptTextMandatory(
463
- 'How should the agents call you?',
464
- defaultName
465
- );
466
-
467
- // Gitignore — opt-in, idempotent.
468
- const wantsGitignore = await confirm(
469
- 'Add the suggested entries to .gitignore (user.toml + scratch + generated adapter outputs)?',
470
- true
471
- );
472
-
473
- console.log('\nCreating .wize/ skeleton...');
527
+ console.log('\nRepositório greenfield detectado.');
528
+ }
529
+
530
+ // Resolve flags or fall back to interactive prompts.
531
+ let project_name, profiles, targets, communication_language, document_output_language, user_name, wantsGitignore;
532
+
533
+ if (nonInteractive) {
534
+ project_name = flags.name ? resolveName(flags) : (path.basename(cwd));
535
+ profiles = resolveProfiles(flags) || defaultProfiles();
536
+ targets = resolveTargets(flags) || defaultTargets();
537
+ communication_language = resolveLang(flags) || 'pt-BR';
538
+ document_output_language = resolveLang(flags) || communication_language;
539
+ user_name = resolveName(flags);
540
+ wantsGitignore = true;
541
+ } else {
542
+ project_name = (await promptText(`Nome do projeto`, path.basename(cwd))) || path.basename(cwd);
543
+ profiles = await multiSelect('Selecione o(s) perfil(is) para instalar', PROFILES);
544
+ targets = await multiSelect('Selecione o(s) IDE target(s)', TARGETS);
545
+
546
+ communication_language = await selectLanguage(
547
+ 'Idioma de comunicação (como os agentes vão falar com você no chat)',
548
+ 'pt-BR'
549
+ );
550
+ document_output_language = await selectLanguage(
551
+ `Idioma dos documentos (idioma usado nos arquivos gerados; ENTER para "${communication_language}")`,
552
+ communication_language
553
+ );
554
+
555
+ const defaultName = (os.userInfo().username || '').trim();
556
+ user_name = await promptTextMandatory(
557
+ 'Como os agentes devem te chamar?',
558
+ defaultName
559
+ );
560
+
561
+ wantsGitignore = await confirm(
562
+ 'Adicionar as entradas sugeridas ao .gitignore (user.toml + scratch + outputs de adapters)?',
563
+ true
564
+ );
565
+ }
566
+
567
+ // Show resolved config.
568
+ console.log(`\nConfiguração:`);
569
+ console.log(` Projeto: ${project_name}`);
570
+ console.log(` Perfis: ${profiles.map(p => p.code).join(', ')}`);
571
+ console.log(` IDE targets: ${targets.map(t => t.code).join(', ')}`);
572
+ console.log(` Idioma comm: ${communication_language}`);
573
+ console.log(` Idioma docs: ${document_output_language}`);
574
+ if (user_name) console.log(` Nome: ${user_name}`);
575
+ if (dryRun) console.log(` Modo: dry-run`);
576
+
577
+ if (dryRun) {
578
+ console.log('\n[DRY-RUN] Criaria estrutura .wize/:');
579
+ for (const dir of WIZE_DIRS) console.log(` - ${dir}/`);
580
+ console.log(`[DRY-RUN] Escreveria .wize/config/project.toml`);
581
+ console.log(`[DRY-RUN] Escreveria .wize/config/user.toml`);
582
+ console.log(`[DRY-RUN] Escreveria .wize/config/tea.toml`);
583
+ if (wantsGitignore) console.log(`[DRY-RUN] Atualizaria .gitignore`);
584
+ console.log(`\n[DRY-RUN] Geraria adapters para: ${targets.map(t => t.code).join(', ')}`);
585
+ console.log('\n[DRY-RUN] Concluído. Nenhum arquivo foi modificado.');
586
+ return;
587
+ }
588
+
589
+ console.log('\nCriando estrutura .wize/...');
474
590
  for (const dir of WIZE_DIRS) mkdirp(path.join(cwd, dir));
475
591
 
476
592
  writeIfMissing(path.join(cwd, '.wize/config/project.toml'), projectToml({
@@ -479,26 +595,26 @@ async function cmdInstall(args) {
479
595
  writeIfMissing(path.join(cwd, '.wize/config/user.toml'), generateUserToml({ name: user_name }));
480
596
  writeIfMissing(path.join(cwd, '.wize/config/tea.toml'), teaToml());
481
597
 
482
- console.log('✓ .wize/ created');
483
- console.log(`✓ profiles: ${profiles.map(p => p.code).join(', ')}`);
598
+ console.log('✓ .wize/ criado');
599
+ console.log(`✓ perfis: ${profiles.map(p => p.code).join(', ')}`);
484
600
  console.log(`✓ ide targets: ${targets.map(t => t.code).join(', ')}`);
485
- if (user_name) console.log(`✓ user.toml: agents will call you "${user_name}"`);
601
+ if (user_name) console.log(`✓ user.toml: agentes vão te chamar de "${user_name}"`);
486
602
 
487
603
  if (profiles.some(p => p.code === 'security-overlay')) {
488
- console.log('\n⚠ security-overlay selected — authorized use only.');
604
+ console.log('\n⚠ security-overlay selecionado — uso autorizado apenas.');
489
605
  console.log(' Uso autorizado. Você é responsável por obter permissão antes de testar alvos que não são seus.');
490
606
  console.log(' O kit detecta alvos fora do scope.md e recusa automaticamente; ainda assim, use com responsabilidade.');
491
607
  }
492
608
 
493
609
  if (wantsGitignore) {
494
610
  const r = applyGitignore(cwd);
495
- if (r.changed) console.log(`✓ .gitignore ${r.mode} with the wize-dev-kit block`);
496
- else console.log(`= .gitignore already up to date`);
611
+ if (r.changed) console.log(`✓ .gitignore ${r.mode} com o bloco wize-dev-kit`);
612
+ else console.log(`= .gitignore já está atualizado`);
497
613
  } else {
498
- console.log('= .gitignore untouched (you opted out of suggested entries)');
614
+ console.log('= .gitignore não modificado (você optou por não adicionar as entradas sugeridas)');
499
615
  }
500
616
 
501
- console.log('\nGenerating IDE adapters...');
617
+ console.log('\nGerando adapters IDE...');
502
618
  const renderResults = renderAdapters({
503
619
  kitRoot: KIT_ROOT,
504
620
  projectRoot: cwd,
@@ -506,61 +622,191 @@ async function cmdInstall(args) {
506
622
  profiles
507
623
  });
508
624
  for (const r of renderResults) {
509
- if (r.skipped) console.log(` - ${r.code}: skipped (${r.reason})`);
510
- else if (r.written) console.log(` ✓ ${r.code}: ${r.written} skill(s) emitted`);
625
+ if (r.skipped) console.log(` - ${r.code}: pulado (${r.reason})`);
626
+ else if (r.written) console.log(` ✓ ${r.code}: ${r.written} skill(s) emitidas`);
511
627
  else if (r.error) console.log(` ✖ ${r.code}: ${r.error}`);
512
628
  }
513
629
 
514
630
  if (detection.brownfield) {
515
631
  if (process.env.WIZE_SKIP_BASELINE === '1') {
516
- console.log('\nWIZE_SKIP_BASELINE=1 — not running the baseline.');
517
- } else if (!INTERACTIVE) {
518
- console.log('\nNon-interactive install detected; running quick baseline...');
632
+ console.log('\nWIZE_SKIP_BASELINE=1 — baseline não será executado.');
633
+ } else if (!INTERACTIVE || nonInteractive) {
634
+ console.log('\nInstalação não-interativa detectada; executando baseline rápido...');
519
635
  cmdDocumentProject({ kitRoot: KIT_ROOT, projectRoot: cwd, args: ['quick'], opts: { log: console.log } });
520
636
  } else {
521
637
  const mode = await select(
522
- 'Document the existing repo now?',
638
+ 'Documentar o repositório existente agora?',
523
639
  [
524
- { title: 'Quick baseline (default, 6 files)', value: 'quick' },
525
- { title: 'Initial scan (pattern + conditional docs)', value: 'initial_scan' },
526
- { title: 'Full rescan (archive old state, re-run)', value: 'full_rescan' },
527
- { title: 'Skip documentation for now', value: 'skip' }
640
+ { title: 'Baseline rápido (padrão, 6 arquivos)', value: 'quick' },
641
+ { title: 'Scan inicial (documentos de padrão + condicionais)', value: 'initial_scan' },
642
+ { title: 'Rescan completo (arquiva estado anterior, re-executa)', value: 'full_rescan' },
643
+ { title: 'Pular documentação por enquanto', value: 'skip' }
528
644
  ],
529
645
  'quick'
530
646
  );
531
647
  if (mode !== 'skip') {
532
648
  cmdDocumentProject({ kitRoot: KIT_ROOT, projectRoot: cwd, args: [mode], opts: { log: console.log } });
533
649
  } else {
534
- console.log('\nSkipped documentation. Run `wize-dev-kit document-project` later.');
650
+ console.log('\nDocumentação pulada. Execute `wize-dev-kit document-project` depois.');
535
651
  }
536
652
  }
537
653
  }
538
654
 
539
655
  console.log('\n──────────────────────────────────────────────────────────────');
540
- console.log('Done.');
656
+ console.log('Concluído.');
541
657
  console.log('');
542
- console.log('⚠ Restart your IDE — many harnesses load skills only at startup.');
658
+ console.log('⚠ Reinicie seu IDE — muitos harnesses carregam skills apenas na inicialização.');
543
659
  console.log(composeOnboarding(detection, profiles));
544
660
  console.log('');
545
- console.log('Keep the kit in sync over time:');
546
- console.log(' • `npx wize-dev-kit update` refresh adapters after a new kit version');
547
- console.log(' • `npx wize-dev-kit sync` re-render adapters after editing config');
548
- console.log(' • `npx wize-dev-kit agent list | create | edit <code>` manage agents');
661
+ console.log('Mantenha o kit sincronizado:');
662
+ console.log(' • `npx wize-dev-kit update` atualizar adapters após nova versão do kit');
663
+ console.log(' • `npx wize-dev-kit sync` re-renderizar adapters após editar config');
664
+ console.log(' • `npx wize-dev-kit agent list | create | edit <code>` gerenciar agentes');
549
665
  console.log('──────────────────────────────────────────────────────────────');
550
666
  }
551
667
 
552
- async function cmdUninstall() {
668
+ // AGENTS.md signature — used to detect whether the file was generated by the kit.
669
+ const AGENTS_SIGNATURE = '# Agents — Wize Development Kit';
670
+
671
+ function isKitAgentsMd(filePath) {
672
+ if (!fs.existsSync(filePath)) return false;
673
+ try {
674
+ const head = fs.readFileSync(filePath, 'utf-8').slice(0, 200);
675
+ return head.includes(AGENTS_SIGNATURE);
676
+ } catch { return false; }
677
+ }
678
+
679
+ // Delete wize-* entries from an adapter target directory. Returns count of
680
+ // removed items (files + dirs). Safe: only deletes entries whose name starts
681
+ // with "wize-".
682
+ function cleanAdapterTarget(targetDir) {
683
+ if (!fs.existsSync(targetDir)) return 0;
684
+ let count = 0;
685
+ let entries;
686
+ try { entries = fs.readdirSync(targetDir); } catch { return 0; }
687
+ for (const name of entries) {
688
+ if (!name.startsWith('wize-')) continue;
689
+ const full = path.join(targetDir, name);
690
+ try {
691
+ fs.rmSync(full, { recursive: true, force: true });
692
+ count++;
693
+ } catch { /* skip permission errors */ }
694
+ }
695
+ return count;
696
+ }
697
+
698
+ async function cmdUninstall(args) {
553
699
  const cwd = process.cwd();
554
- const dir = path.join(cwd, '.wize');
555
- if (!fs.existsSync(dir)) {
556
- console.log('No .wize/ folder found here.');
700
+ const { flags } = parseArgs(args || []);
701
+ const dryRun = !!flags['dry-run'];
702
+
703
+ if (dryRun) console.log('[DRY-RUN] Nenhum arquivo será removido.\n');
704
+
705
+ const wizeDir = path.join(cwd, '.wize');
706
+ if (!fs.existsSync(wizeDir)) {
707
+ console.log('Nenhuma pasta .wize/ encontrada aqui.');
557
708
  return;
558
709
  }
559
- const ok = await confirm(`Remove ${dir}? Your project source code is not touched.`, false);
560
- if (!ok) return;
561
- fs.rmSync(dir, { recursive: true, force: true });
562
- console.log('Removed .wize/.');
563
- console.log('(stub) IDE adapter files (.claude/skills/wize-*, .cursor/rules/wize-*) would be cleaned here.');
710
+
711
+ // Read project.toml to discover which IDE targets were configured.
712
+ let ideTargets = [];
713
+ try {
714
+ const cfg = loadProjectConfig(cwd);
715
+ ideTargets = (cfg.install && cfg.install.ide_targets) || [];
716
+ } catch { /* project.toml may be missing or corrupt */ }
717
+
718
+ // Build the list of what would be removed.
719
+ const toRemove = [];
720
+
721
+ // 1. Adapter target dirs (wize-* entries).
722
+ const adapterDirs = [];
723
+ for (const code of ideTargets) {
724
+ const dir = adapterTargetPath(code, cwd);
725
+ if (!dir) continue;
726
+ if (!fs.existsSync(dir)) continue;
727
+ let entries;
728
+ try { entries = fs.readdirSync(dir); } catch { continue; }
729
+ for (const name of entries) {
730
+ if (!name.startsWith('wize-')) continue;
731
+ adapterDirs.push({ target: code, dir, name, full: path.join(dir, name) });
732
+ }
733
+ }
734
+
735
+ // 2. .wize/ directory.
736
+ toRemove.push({ kind: 'diretório', path: wizeDir, label: '.wize/' });
737
+
738
+ // 3. AGENTS.md if kit-generated.
739
+ const agentsMd = path.join(cwd, 'AGENTS.md');
740
+ if (isKitAgentsMd(agentsMd)) {
741
+ toRemove.push({ kind: 'arquivo', path: agentsMd, label: 'AGENTS.md' });
742
+ }
743
+
744
+ // Show what will be removed.
745
+ if (adapterDirs.length > 0) {
746
+ console.log('Arquivos de adapter que serão removidos:');
747
+ const byTarget = {};
748
+ for (const a of adapterDirs) {
749
+ byTarget[a.target] = byTarget[a.target] || [];
750
+ byTarget[a.target].push(a.name);
751
+ }
752
+ for (const [code, names] of Object.entries(byTarget)) {
753
+ console.log(` ${code}: ${names.length} entrada(s) (${names.slice(0, 5).join(', ')}${names.length > 5 ? '...' : ''})`);
754
+ }
755
+ } else {
756
+ console.log('Nenhum arquivo de adapter wize-* encontrado.');
757
+ }
758
+
759
+ console.log(`\nSerá removido:`);
760
+ for (const item of toRemove) {
761
+ console.log(` - ${item.label} (${item.kind})`);
762
+ }
763
+ if (adapterDirs.length > 0) {
764
+ console.log(` - ${adapterDirs.length} entrada(s) wize-* nos diretórios de adapter`);
765
+ }
766
+
767
+ if (dryRun) {
768
+ console.log('\n[DRY-RUN] Concluído. Nenhum arquivo foi removido.');
769
+ return;
770
+ }
771
+
772
+ const totalItems = toRemove.length + adapterDirs.length;
773
+ if (totalItems === 0) {
774
+ console.log('\nNada para remover.');
775
+ return;
776
+ }
777
+
778
+ const ok = await confirm(`\nRemover ${totalItems} item(ns)? O código-fonte do seu projeto não será afetado.`, false);
779
+ if (!ok) {
780
+ console.log('Cancelado.');
781
+ return;
782
+ }
783
+
784
+ // Capture AGENTS.md status before deletion.
785
+ const hadAgentsMd = isKitAgentsMd(agentsMd);
786
+
787
+ // Delete adapter entries first.
788
+ let adapterCount = 0;
789
+ for (const a of adapterDirs) {
790
+ try {
791
+ fs.rmSync(a.full, { recursive: true, force: true });
792
+ adapterCount++;
793
+ } catch (err) {
794
+ console.log(` ✖ erro ao remover ${a.name}: ${err.message}`);
795
+ }
796
+ }
797
+
798
+ // Delete .wize/ and AGENTS.md.
799
+ for (const item of toRemove) {
800
+ try {
801
+ fs.rmSync(item.path, { recursive: true, force: true });
802
+ } catch (err) {
803
+ console.log(` ✖ erro ao remover ${item.label}: ${err.message}`);
804
+ }
805
+ }
806
+
807
+ console.log(`\n✓ Removido: .wize/ + ${adapterCount} entrada(s) de adapter`);
808
+ if (hadAgentsMd) console.log('✓ AGENTS.md removido');
809
+ console.log('\nO código-fonte do seu projeto não foi alterado.');
564
810
  }
565
811
 
566
812
  function cmdList() {
@@ -581,7 +827,7 @@ function cmdList() {
581
827
  console.log(` ${'wize-sec-red-teamer'.padEnd(36)} Natasha Romanoff (security-overlay, opt-in)`);
582
828
 
583
829
  console.log('\nWorkflows directories:');
584
- const phases = ['1-analysis', '2-plan-workflows', '3-solutioning', '4-implementation'];
830
+ const phases = ['1-analysis', '2-plan', '3-solutioning', '4-implementation'];
585
831
  for (const phase of phases) {
586
832
  const dir = path.join(KIT_ROOT, 'src/method-skills', phase);
587
833
  if (!fs.existsSync(dir)) continue;
@@ -640,7 +886,7 @@ async function main() {
640
886
  switch (cmd) {
641
887
  case 'install': return cmdInstall(rest);
642
888
  case 'update': return cmdUpdate({ kitRoot: KIT_ROOT, projectRoot: process.cwd() });
643
- case 'uninstall': return cmdUninstall();
889
+ case 'uninstall': return cmdUninstall(rest);
644
890
  case 'list': return cmdList();
645
891
  case 'sync': return cmdSync();
646
892
  case 'agent': return cmdAgent(rest);