bmad-plus 0.12.2 → 0.13.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.
Files changed (44) hide show
  1. package/CHANGELOG.md +25 -0
  2. package/README.md +36 -8
  3. package/package.json +6 -4
  4. package/readme-international/README.de.md +37 -8
  5. package/readme-international/README.es.md +38 -9
  6. package/readme-international/README.fr.md +37 -8
  7. package/src/bmad-plus/agents/agent-orchestrator/SKILL.md +2 -0
  8. package/src/bmad-plus/module.yaml +270 -220
  9. package/src/bmad-plus/packs/pack-seo/scripts/seo_apis.py +8 -8
  10. package/src/bmad-plus/packs/pack-seo/scripts/seo_fetch.py +1 -2
  11. package/src/bmad-plus/packs/pack-seo/scripts/seo_report.py +0 -1
  12. package/src/bmad-plus/skills/bmad-plus-autopilot/SKILL.md +1 -1
  13. package/tools/bmad-plus-npx.js +4 -2
  14. package/tools/build/adapters.config.js +60 -51
  15. package/tools/build/check-counts.js +52 -54
  16. package/tools/build/check-install-contract.js +298 -0
  17. package/tools/build/generate-adapters.js +252 -56
  18. package/tools/build/generate.js +187 -10
  19. package/tools/build/generated-adapters/.codex/AGENTS.md +20 -7
  20. package/tools/build/generated-adapters/.cursor/rules/bmad-plus.mdc +20 -7
  21. package/tools/build/generated-adapters/.opencode/AGENTS.md +20 -7
  22. package/tools/build/generated-adapters/AGENTS.md +20 -7
  23. package/tools/build/generated-adapters/CLAUDE.md +20 -7
  24. package/tools/build/generated-adapters/CONVENTIONS.md +20 -7
  25. package/tools/build/generated-adapters/GEMINI.md +20 -7
  26. package/tools/build/module.template.yaml +82 -0
  27. package/tools/cli/bmad-plus-cli.js +16 -1
  28. package/tools/cli/commands/doctor.js +12 -40
  29. package/tools/cli/commands/install.js +108 -163
  30. package/tools/cli/commands/uninstall.js +173 -65
  31. package/tools/cli/commands/update-check.js +31 -0
  32. package/tools/cli/commands/update-policy.js +39 -0
  33. package/tools/cli/commands/update.js +102 -113
  34. package/tools/cli/i18n.js +60 -0
  35. package/tools/cli/lib/ide-config.js +4 -261
  36. package/tools/cli/lib/install-manifest.js +17 -0
  37. package/tools/cli/lib/installed-adapters.js +89 -0
  38. package/tools/cli/lib/npm-runner.js +177 -0
  39. package/tools/cli/lib/pack-copy.js +62 -66
  40. package/tools/cli/lib/packs.js +437 -3
  41. package/tools/cli/lib/update-check.js +153 -0
  42. package/tools/cli/lib/update-dispatch.js +182 -0
  43. package/tools/cli/lib/update-policy.js +90 -0
  44. package/tools/cli/lib/update-transaction.js +334 -0
@@ -0,0 +1,31 @@
1
+ /** Report release status without applying updates. */
2
+ const path = require('node:path');
3
+ const { checkForUpdate } = require('../lib/update-check');
4
+
5
+ module.exports = {
6
+ command: 'update-check',
7
+ description: 'Check the published BMAD+ release without applying it',
8
+ options: [
9
+ ['-d, --directory <path>', 'Project directory (default: current directory)'],
10
+ ['--refresh', 'Bypass the release cache and retry backoff'],
11
+ ['--offline', 'Report local state without network access'],
12
+ ['--json', 'Print machine-readable JSON'],
13
+ ],
14
+ action: async (options = {}) => {
15
+ const result = await checkForUpdate({
16
+ projectDir: path.resolve(options.directory || process.cwd()),
17
+ runningVersion: require('../../../package.json').version,
18
+ refresh: Boolean(options.refresh), offline: Boolean(options.offline),
19
+ checkReadiness: ({ projectDir }) => {
20
+ const { evaluateUpdateReadiness } = require('../lib/update-transaction');
21
+ return evaluateUpdateReadiness({ projectDir });
22
+ },
23
+ });
24
+ if (result.status.startsWith('invalid-')) process.exitCode = 1;
25
+ if (options.json) console.log(JSON.stringify(result));
26
+ else {
27
+ console.log(`Installed: ${result.installedVersion || 'unknown'}; running: ${result.runningVersion}; channel ${result.channel || 'unknown'}: ${result.targetVersion || 'unknown'}`);
28
+ console.log(`${result.status}: ${result.reason}${result.stale ? ' (cached result is stale)' : ''}`);
29
+ }
30
+ },
31
+ };
@@ -0,0 +1,39 @@
1
+ /** Show or explicitly configure the local update policy; never updates packages. */
2
+ const path = require('node:path');
3
+ const { readUpdatePolicy, writeUpdatePolicy } = require('../lib/update-policy');
4
+
5
+ module.exports = {
6
+ command: 'update-policy',
7
+ description: 'Show or configure the project update policy',
8
+ options: [
9
+ ['-d, --directory <path>', 'Project directory (default: current directory)'],
10
+ ['--mode <mode>', 'off, notify, or auto (auto requires --range)'],
11
+ ['--range <range>', 'Explicit semantic-version range for automatic updates'],
12
+ ['--channel <tag>', 'npm release tag (default: latest)'],
13
+ ['--allow-prerelease', 'Explicitly allow prerelease targets'],
14
+ ['--stable-only', 'Disable prerelease targets'],
15
+ ['--json', 'Print machine-readable JSON'],
16
+ ],
17
+ action: async (options = {}) => {
18
+ try {
19
+ if (options.allowPrerelease && options.stableOnly) throw new Error('Choose --allow-prerelease or --stable-only.');
20
+ if (options.mode === 'auto' && !options.range) throw new Error('--mode auto requires an explicit --range.');
21
+ const projectDir = path.resolve(options.directory || process.cwd());
22
+ const policy = readUpdatePolicy(projectDir);
23
+ const changing = options.mode !== undefined || options.range !== undefined ||
24
+ options.channel !== undefined || options.allowPrerelease || options.stableOnly;
25
+ if (options.mode !== undefined) policy.mode = options.mode;
26
+ if (options.range !== undefined) policy.allowedRange = options.range;
27
+ if (options.channel !== undefined) policy.channel = options.channel;
28
+ if (options.allowPrerelease) policy.allowPrerelease = true;
29
+ if (options.stableOnly) policy.allowPrerelease = false;
30
+ const saved = changing ? writeUpdatePolicy(projectDir, policy) : policy;
31
+ if (options.json) console.log(JSON.stringify({ policy: saved, changed: Boolean(changing) }));
32
+ else console.log(`Update policy${changing ? ' saved' : ''}: ${saved.mode}; channel=${saved.channel}; range=${saved.allowedRange || 'none'}; prereleases=${saved.allowPrerelease}`);
33
+ } catch (error) {
34
+ process.exitCode = 1;
35
+ if (options.json) console.log(JSON.stringify({ error: error.message }));
36
+ else console.error(error.message);
37
+ }
38
+ },
39
+ };
@@ -1,134 +1,123 @@
1
1
  /**
2
- * BMAD+ Update Command
3
- * Updates agents and skills while preserving user config
4
- *
2
+ * BMAD+ Update Command — planned updates with recoverable backups.
5
3
  * Author: Laurent Rochetta
6
4
  */
7
-
8
5
  const path = require('node:path');
9
6
  const fs = require('node:fs');
10
- const fsExtra = require('fs-extra');
7
+ const semver = require('semver');
11
8
  const clack = require('@clack/prompts');
12
9
  const pc = require('picocolors');
13
10
  const { t } = require('../i18n');
14
- const { PACKS } = require('../lib/packs');
15
- const { copyPackFiles } = require('../lib/pack-copy');
16
-
17
- // Pack definitions imported from shared module: require('../lib/packs').PACKS
11
+ const { safeTarget } = require('../../build/generate-adapters');
12
+ const { readInstallManifest } = require('../lib/install-manifest');
13
+ const { isExactVersion } = require('../lib/update-policy');
14
+ const { planUpdate, applyPlan, restoreUpdate, MANIFEST } = require('../lib/update-transaction');
15
+
16
+ function authorizeAuto(projectDir, version) {
17
+ const { readUpdatePolicy, authorizeTarget } = require('../lib/update-policy');
18
+ const decision = authorizeTarget(readUpdatePolicy(projectDir), version);
19
+ if (!decision.allowed) throw new Error('Automatic update refused: ' + decision.reason);
20
+ }
21
+
22
+ async function confirmAction(options, message, lang = 'en') {
23
+ if (options.yes || options.auto) return true;
24
+ const i = t(lang);
25
+ if (!process.stdin.isTTY) throw new Error(i.noninteractive_requires_yes('update'));
26
+ const confirmed = await clack.confirm({ message });
27
+ if (!confirmed || clack.isCancel(confirmed)) {
28
+ clack.cancel(i.cancelled);
29
+ return false;
30
+ }
31
+ return true;
32
+ }
18
33
 
19
34
  module.exports = {
20
35
  command: 'update',
21
- description: 'Update BMAD+ agents and skills (preserves config)',
36
+ description: 'Update BMAD+ agents and skills (preserves local changes)',
22
37
  options: [
23
38
  ['-d, --directory <path>', 'Project directory (default: current directory)'],
39
+ ['-y, --yes', 'Confirm update without prompting'],
24
40
  ['-l, --lang <code>', 'Language code: en, fr, es, de, pt-br, ru, zh, he, ja, it'],
41
+ ['--latest', 'Resolve and run the exact latest compatible published package'],
42
+ ['--expected-version <version>', 'Require this exact executing package version'],
43
+ ['--auto', 'Apply only when automatic update policy and ownership allow it'],
44
+ ['--restore <receipt-id>', 'Restore files from an update receipt'],
25
45
  ],
26
46
  action: async (options) => {
27
47
  const projectDir = path.resolve(options.directory || process.cwd());
28
- const bmadSrc = path.join(__dirname, '..', '..', '..', 'src', 'bmad-plus');
29
- const packageJson = require('../../../package.json');
30
-
31
- clack.intro(pc.bgMagenta(pc.white(` BMAD+ Updater v${packageJson.version} `)));
32
-
33
- // Check if installed
34
- const manifestPath = path.join(projectDir, '_bmad', '.bmad-plus-install.json');
35
- if (!fs.existsSync(manifestPath)) {
36
- clack.log.error('BMAD+ is not installed in this directory.');
37
- clack.log.info('Run `npx bmad-plus install` first.');
38
- clack.outro(pc.red('Update aborted.'));
39
- return;
40
- }
41
-
42
- let manifest;
48
+ const version = require('../../../package.json').version;
49
+ let spinner;
43
50
  try {
44
- manifest = JSON.parse(fs.readFileSync(manifestPath, 'utf8'));
45
- } catch (err) {
46
- clack.log.error(`Install manifest is unreadable or corrupt: ${err.message}`);
47
- clack.log.info('Re-run `npx bmad-plus install` to repair the installation.');
48
- clack.outro(pc.red('Update aborted.'));
49
- return;
51
+ if (options.restore && (options.latest || options.expectedVersion)) {
52
+ throw new Error('--restore cannot be combined with --latest or --expected-version.');
53
+ }
54
+ // The dispatcher resolves the target package; this local package may be older.
55
+ if (options.latest) {
56
+ const result = await require('../lib/update-dispatch').runLatestUpdate({
57
+ projectDir, auto: Boolean(options.auto), yes: Boolean(options.yes),
58
+ });
59
+ clack.log.info(result.reason || result.status);
60
+ if (result.output) clack.log.info(result.output);
61
+ if (result.targetVersion) clack.log.info('Target: v' + result.targetVersion);
62
+ if (result.reloadInstructions) clack.log.info('Reload your agent instructions or start a new session.');
63
+ return;
64
+ }
65
+
66
+ clack.intro(pc.bgMagenta(pc.white(' BMAD+ Updater v' + version + ' ')));
67
+ if (options.restore) {
68
+ if (options.auto) throw new Error('Recovery requires manual approval.');
69
+ if (!await confirmAction(options, 'Restore the files saved in receipt ' + options.restore + '?', options.lang)) return;
70
+ const restored = restoreUpdate({ projectDir, receiptId: options.restore });
71
+ clack.log.success('Restored BMAD+ v' + restored.restoredVersion);
72
+ clack.log.info('Receipt: ' + restored.receiptPath);
73
+ clack.outro('Reload your agent instructions or start a new session.');
74
+ return;
75
+ }
76
+
77
+ if (options.auto && !options.expectedVersion) throw new Error('Automatic update requires --expected-version.');
78
+ if (options.expectedVersion && options.expectedVersion !== version) {
79
+ throw new Error('Executing package version ' + version + ' does not match expected version ' + options.expectedVersion + '.');
80
+ }
81
+ const manifestPath = safeTarget(projectDir, MANIFEST);
82
+ if (!fs.existsSync(manifestPath)) throw new Error('BMAD+ is not installed in this directory. Run bmad-plus install first.');
83
+ let manifest;
84
+ try { manifest = readInstallManifest(manifestPath); } catch (error) {
85
+ throw new Error('Install manifest is unreadable or corrupt: ' + error.message, { cause: error });
86
+ }
87
+ if (!isExactVersion(version) || !isExactVersion(manifest.version)) throw new Error('Update versions must be strict semantic versions.');
88
+ if (semver.lt(version, manifest.version)) throw new Error('Downgrade refused: ' + manifest.version + ' -> ' + version);
89
+ const lang = options.lang || manifest.uiLanguage || 'en';
90
+ clack.log.info('Installed: v' + manifest.version + ' -> Executing package: v' + version);
91
+ if (manifest.version === version) {
92
+ clack.log.success('The installed version matches this executing package. Use --latest to check the registry.');
93
+ clack.outro(pc.green('Nothing to update.'));
94
+ return;
95
+ }
96
+ const plan = planUpdate({ projectDir, manifest, version, auto: Boolean(options.auto) });
97
+ if (options.auto) {
98
+ authorizeAuto(projectDir, version);
99
+ const fresh = await require('../lib/update-check').checkForUpdate({ projectDir, runningVersion: version, refresh: true });
100
+ if (fresh.source !== 'registry' || fresh.stale || !fresh.versionEligible || fresh.targetVersion !== options.expectedVersion) {
101
+ throw new Error('Automatic update requires a fresh, eligible registry target matching --expected-version.');
102
+ }
103
+ }
104
+
105
+ clack.log.info('Planned changes: ' + (plan.files.length - 1) + ' files; preserved conflicts: ' + plan.conflicts.length + '.');
106
+ if (plan.legacy) clack.log.warn('Legacy installation: original pack files will be backed up before replacement because ownership hashes are unavailable. Review the receipt to recover local edits.');
107
+ for (const conflict of plan.conflicts) clack.log.warn(conflict.file + ': preserved (' + conflict.reason + ').');
108
+ if (!await confirmAction(options, 'Apply this update from v' + manifest.version + ' to v' + version + '?', lang)) return;
109
+
110
+ spinner = clack.spinner();
111
+ spinner.start('Updating managed files...');
112
+ const result = applyPlan(plan, { reauthorize: () => authorizeAuto(projectDir, version) });
113
+ spinner.stop(result.changedFiles.length + ' files updated; ' + result.conflicts.length + ' local conflicts preserved.');
114
+ spinner = null;
115
+ clack.log.info('Receipt and backups: ' + result.receiptPath);
116
+ clack.outro(pc.green('BMAD+ v' + version + (result.conflicts.length ? ' applied partially.' : ' installed.') + ' Reload your agent instructions or start a new session.'));
117
+ } catch (error) {
118
+ if (spinner) spinner.stop('Update failed.');
119
+ clack.log.error(error.message);
120
+ process.exitCode = 1;
50
121
  }
51
- if (!manifest || typeof manifest !== 'object') {
52
- clack.log.error('Install manifest is malformed (not an object).');
53
- clack.log.info('Re-run `npx bmad-plus install` to repair the installation.');
54
- clack.outro(pc.red('Update aborted.'));
55
- return;
56
- }
57
- const lang = options.lang || manifest.uiLanguage || 'en';
58
- const i = t(lang);
59
-
60
- clack.log.info(`📦 Installed: v${manifest.version} → Available: v${packageJson.version}`);
61
-
62
- if (manifest.version === packageJson.version) {
63
- clack.log.success(i.update_current || '✅ Already up to date!');
64
- clack.outro(pc.green('Nothing to update.'));
65
- return;
66
- }
67
-
68
- // Guard against a missing/malformed `packs` field (NODE-04): coerce to an array.
69
- const selectedPacks = Array.isArray(manifest.packs) && manifest.packs.length > 0
70
- ? manifest.packs
71
- : ['core'];
72
- clack.log.info(`${i.selected_packs}: ${selectedPacks.join(', ')}`);
73
-
74
- const confirm = await clack.confirm({
75
- message: i.update_confirm || `Update from v${manifest.version} to v${packageJson.version}?`,
76
- });
77
-
78
- if (!confirm || clack.isCancel(confirm)) {
79
- clack.cancel(i.cancelled);
80
- return;
81
- }
82
-
83
- const spinner = clack.spinner();
84
- spinner.start(i.update_updating || 'Updating agents and skills...');
85
-
86
- const targetAgentsDir = path.join(projectDir, '.agents', 'skills');
87
- const targetDataDir = path.join(projectDir, '.agents', 'data');
88
-
89
- fsExtra.ensureDirSync(targetAgentsDir);
90
- fsExtra.ensureDirSync(targetDataDir);
91
-
92
- let updated = 0;
93
-
94
- const projectRoot = path.join(bmadSrc, '..', '..');
95
-
96
- for (const packId of selectedPacks) {
97
- const pack = PACKS[packId];
98
- if (!pack) continue;
99
-
100
- const result = copyPackFiles({
101
- bmadSrc,
102
- targetAgentsDir,
103
- targetDataDir,
104
- projectRoot,
105
- pack,
106
- });
107
- updated += result.copiedAgents + result.copiedSkills + result.copiedFiles;
108
- }
109
-
110
- // Update module config (always)
111
- const moduleYaml = path.join(bmadSrc, 'module.yaml');
112
- const targetBmadDir = path.join(projectDir, '_bmad');
113
- if (fs.existsSync(moduleYaml)) {
114
- fsExtra.copySync(moduleYaml, path.join(targetBmadDir, 'module.yaml'));
115
- updated++;
116
- }
117
-
118
- const helpCsv = path.join(bmadSrc, 'module-help.csv');
119
- if (fs.existsSync(helpCsv)) {
120
- fsExtra.copySync(helpCsv, path.join(targetBmadDir, 'module-help.csv'));
121
- updated++;
122
- }
123
-
124
- // Update manifest version (preserve everything else)
125
- manifest.version = packageJson.version;
126
- manifest.lastUpdated = new Date().toISOString();
127
- fs.writeFileSync(manifestPath, JSON.stringify(manifest, null, 2), 'utf8');
128
-
129
- spinner.stop(i.update_done ? i.update_done(updated) : `✅ ${updated} files updated to v${packageJson.version}`);
130
-
131
- clack.log.info('📋 Config preserved: config.yaml, IDE configs, output directories');
132
- clack.outro(pc.green(i.update_ready || `BMAD+ v${packageJson.version} is ready! 🚀`));
133
122
  },
134
123
  };
package/tools/cli/i18n.js CHANGED
@@ -58,6 +58,12 @@ const LANGUAGES = {
58
58
  guide_credits: '✨ BMAD+ is created by Laurent Rochetta — github.com/lrochetta/BMAD-PLUS ✨',
59
59
  // Uninstall
60
60
  uninstall_confirm: 'Remove BMAD+ from this project?',
61
+ noninteractive_requires_yes: (command) => "This command requires a terminal. Run `npx bmad-plus " + command + " --yes` to proceed without prompts.",
62
+ manifest_invalid: (error) => "Install manifest is unreadable or corrupt: " + error + "",
63
+ manifest_repair: 'Check _bmad/.bmad-plus-install.json and repair it before retrying.',
64
+ uninstall_not_installed: 'BMAD+ is not installed in this directory.',
65
+ uninstall_aborted: (error) => "Uninstall aborted: " + error + "",
66
+ uninstall_preserved: 'Project memory, settings, and unknown or modified files have been preserved.',
61
67
  uninstall_removing: 'Removing...',
62
68
  uninstall_done: (n) => `✅ BMAD+ removed (${n} items)`,
63
69
  uninstall_output_kept: '📁 _bmad-output/ kept (contains files)',
@@ -139,6 +145,12 @@ const LANGUAGES = {
139
145
  guide_ready: 'BMAD+ est prêt ! Parle à Atlas pour commencer 🚀',
140
146
  guide_credits: '✨ BMAD+ est créé par Laurent Rochetta — github.com/lrochetta/BMAD-PLUS ✨',
141
147
  uninstall_confirm: 'Supprimer BMAD+ de ce projet ?',
148
+ noninteractive_requires_yes: (command) => "Cette commande nécessite un terminal. Lancez `npx bmad-plus " + command + " --yes` pour continuer sans invite.",
149
+ manifest_invalid: (error) => "Le manifeste d’installation est illisible ou corrompu : " + error + "",
150
+ manifest_repair: 'Vérifiez _bmad/.bmad-plus-install.json et réparez-le avant de réessayer.',
151
+ uninstall_not_installed: 'BMAD+ n’est pas installé dans ce répertoire.',
152
+ uninstall_aborted: (error) => "Désinstallation interrompue : " + error + "",
153
+ uninstall_preserved: 'La mémoire, les réglages et les fichiers inconnus ou modifiés ont été conservés.',
142
154
  uninstall_removing: 'Suppression...',
143
155
  uninstall_done: (n) => `✅ BMAD+ supprimé (${n} éléments)`,
144
156
  uninstall_output_kept: '📁 _bmad-output/ conservé (contient des fichiers)',
@@ -219,6 +231,12 @@ const LANGUAGES = {
219
231
  guide_ready: '¡BMAD+ está listo! Habla con Atlas para comenzar 🚀',
220
232
  guide_credits: '✨ BMAD+ es creado por Laurent Rochetta — github.com/lrochetta/BMAD-PLUS ✨',
221
233
  uninstall_confirm: '¿Eliminar BMAD+ de este proyecto?',
234
+ noninteractive_requires_yes: (command) => "Este comando requiere una terminal. Ejecute `npx bmad-plus " + command + " --yes` para continuar sin preguntas.",
235
+ manifest_invalid: (error) => "El manifiesto de instalación no se puede leer o está dañado: " + error + "",
236
+ manifest_repair: 'Revise _bmad/.bmad-plus-install.json y repárelo antes de reintentar.',
237
+ uninstall_not_installed: 'BMAD+ no está instalado en este directorio.',
238
+ uninstall_aborted: (error) => "Desinstalación interrumpida: " + error + "",
239
+ uninstall_preserved: 'Se han conservado la memoria, los ajustes y los archivos desconocidos o modificados.',
222
240
  uninstall_removing: 'Eliminando...',
223
241
  uninstall_done: (n) => `✅ BMAD+ eliminado (${n} elementos)`,
224
242
  uninstall_output_kept: '📁 _bmad-output/ conservado (contiene archivos)',
@@ -299,6 +317,12 @@ const LANGUAGES = {
299
317
  guide_ready: 'BMAD+ ist bereit! Sprich mit Atlas um loszulegen 🚀',
300
318
  guide_credits: '✨ BMAD+ wurde erstellt von Laurent Rochetta — github.com/lrochetta/BMAD-PLUS ✨',
301
319
  uninstall_confirm: 'BMAD+ aus diesem Projekt entfernen?',
320
+ noninteractive_requires_yes: (command) => "Dieser Befehl benötigt ein Terminal. Führen Sie `npx bmad-plus " + command + " --yes` aus, um ohne Rückfragen fortzufahren.",
321
+ manifest_invalid: (error) => "Das Installationsmanifest ist unlesbar oder beschädigt: " + error + "",
322
+ manifest_repair: 'Prüfen und reparieren Sie _bmad/.bmad-plus-install.json vor einem erneuten Versuch.',
323
+ uninstall_not_installed: 'BMAD+ ist in diesem Verzeichnis nicht installiert.',
324
+ uninstall_aborted: (error) => "Deinstallation abgebrochen: " + error + "",
325
+ uninstall_preserved: 'Projektspeicher, Einstellungen sowie unbekannte oder geänderte Dateien wurden erhalten.',
302
326
  uninstall_removing: 'Entfernen...',
303
327
  uninstall_done: (n) => `✅ BMAD+ entfernt (${n} Elemente)`,
304
328
  uninstall_output_kept: '📁 _bmad-output/ beibehalten (enthält Dateien)',
@@ -379,6 +403,12 @@ const LANGUAGES = {
379
403
  guide_ready: 'BMAD+ está pronto! Fale com Atlas para começar 🚀',
380
404
  guide_credits: '✨ BMAD+ foi criado por Laurent Rochetta — github.com/lrochetta/BMAD-PLUS ✨',
381
405
  uninstall_confirm: 'Remover BMAD+ deste projeto?',
406
+ noninteractive_requires_yes: (command) => "Este comando exige um terminal. Execute `npx bmad-plus " + command + " --yes` para continuar sem perguntas.",
407
+ manifest_invalid: (error) => "O manifesto de instalação está ilegível ou corrompido: " + error + "",
408
+ manifest_repair: 'Verifique e repare _bmad/.bmad-plus-install.json antes de tentar novamente.',
409
+ uninstall_not_installed: 'BMAD+ não está instalado neste diretório.',
410
+ uninstall_aborted: (error) => "Desinstalação interrompida: " + error + "",
411
+ uninstall_preserved: 'A memória, as configurações e os arquivos desconhecidos ou modificados foram preservados.',
382
412
  uninstall_removing: 'Removendo...',
383
413
  uninstall_done: (n) => `✅ BMAD+ removido (${n} itens)`,
384
414
  uninstall_output_kept: '📁 _bmad-output/ mantido (contém arquivos)',
@@ -459,6 +489,12 @@ const LANGUAGES = {
459
489
  guide_ready: 'BMAD+ готов! Поговорите с Atlas чтобы начать 🚀',
460
490
  guide_credits: '✨ BMAD+ создан Laurent Rochetta — github.com/lrochetta/BMAD-PLUS ✨',
461
491
  uninstall_confirm: 'Удалить BMAD+ из этого проекта?',
492
+ noninteractive_requires_yes: (command) => "Для этой команды нужен терминал. Запустите `npx bmad-plus " + command + " --yes`, чтобы продолжить без запросов.",
493
+ manifest_invalid: (error) => "Манифест установки недоступен или повреждён: " + error + "",
494
+ manifest_repair: 'Проверьте и исправьте _bmad/.bmad-plus-install.json перед повторной попыткой.',
495
+ uninstall_not_installed: 'BMAD+ не установлен в этом каталоге.',
496
+ uninstall_aborted: (error) => "Удаление прервано: " + error + "",
497
+ uninstall_preserved: 'Память проекта, настройки и неизвестные или изменённые файлы сохранены.',
462
498
  uninstall_removing: 'Удаление...',
463
499
  uninstall_done: (n) => `✅ BMAD+ удалён (${n} элементов)`,
464
500
  uninstall_output_kept: '📁 _bmad-output/ сохранён (содержит файлы)',
@@ -539,6 +575,12 @@ const LANGUAGES = {
539
575
  guide_ready: 'BMAD+ 已就绪!与 Atlas 交谈开始 🚀',
540
576
  guide_credits: '✨ BMAD+ 由 Laurent Rochetta 创建 — github.com/lrochetta/BMAD-PLUS ✨',
541
577
  uninstall_confirm: '从此项目中删除 BMAD+?',
578
+ noninteractive_requires_yes: (command) => "此命令需要终端。运行 `npx bmad-plus " + command + " --yes` 可跳过提示并继续。",
579
+ manifest_invalid: (error) => "安装清单无法读取或已损坏:" + error + "",
580
+ manifest_repair: '请检查并修复 _bmad/.bmad-plus-install.json 后重试。',
581
+ uninstall_not_installed: '此目录未安装 BMAD+。',
582
+ uninstall_aborted: (error) => "卸载已中止:" + error + "",
583
+ uninstall_preserved: '项目记忆、设置以及未知或修改过的文件已保留。',
542
584
  uninstall_removing: '删除中...',
543
585
  uninstall_done: (n) => `✅ BMAD+ 已删除(${n} 项)`,
544
586
  uninstall_output_kept: '📁 _bmad-output/ 已保留(包含文件)',
@@ -619,6 +661,12 @@ const LANGUAGES = {
619
661
  guide_ready: '!BMAD+ מוכן! דבר עם Atlas כדי להתחיל 🚀',
620
662
  guide_credits: '✨ BMAD+ נוצר על ידי Laurent Rochetta — github.com/lrochetta/BMAD-PLUS ✨',
621
663
  uninstall_confirm: 'להסיר את BMAD+ מהפרויקט הזה?',
664
+ noninteractive_requires_yes: (command) => "פקודה זו דורשת מסוף. להרצה ללא שאלות, הפעילו `npx bmad-plus " + command + " --yes`.",
665
+ manifest_invalid: (error) => "קובץ פרטי ההתקנה אינו קריא או פגום: " + error + "",
666
+ manifest_repair: 'בדקו ותקנו את _bmad/.bmad-plus-install.json לפני ניסיון נוסף.',
667
+ uninstall_not_installed: 'BMAD+ אינו מותקן בתיקייה זו.',
668
+ uninstall_aborted: (error) => "ההסרה הופסקה: " + error + "",
669
+ uninstall_preserved: 'זיכרון הפרויקט, ההגדרות וקבצים לא מוכרים או ששונו נשמרו.',
622
670
  uninstall_removing: 'מסיר...',
623
671
  uninstall_done: (n) => `✅ BMAD+ הוסר (${n} פריטים)`,
624
672
  uninstall_output_kept: '📁 _bmad-output/ נשמר (מכיל קבצים)',
@@ -699,6 +747,12 @@ const LANGUAGES = {
699
747
  guide_ready: 'BMAD+ 準備完了!Atlasに話しかけて始めましょう 🚀',
700
748
  guide_credits: '✨ BMAD+ は Laurent Rochetta によって作成されました — github.com/lrochetta/BMAD-PLUS ✨',
701
749
  uninstall_confirm: 'このプロジェクトからBMAD+を削除しますか?',
750
+ noninteractive_requires_yes: (command) => "このコマンドには端末が必要です。確認なしで続行するには `npx bmad-plus " + command + " --yes` を実行してください。",
751
+ manifest_invalid: (error) => "インストール情報を読み込めないか破損しています:" + error + "",
752
+ manifest_repair: '_bmad/.bmad-plus-install.json を確認・修復してから再試行してください。',
753
+ uninstall_not_installed: 'このディレクトリには BMAD+ がインストールされていません。',
754
+ uninstall_aborted: (error) => "アンインストールを中止しました:" + error + "",
755
+ uninstall_preserved: 'プロジェクトの記憶、設定、不明なファイルや変更されたファイルは保持されました。',
702
756
  uninstall_removing: '削除中...',
703
757
  uninstall_done: (n) => `✅ BMAD+を削除しました(${n}項目)`,
704
758
  uninstall_output_kept: '📁 _bmad-output/ は保持されました(ファイルが含まれています)',
@@ -779,6 +833,12 @@ const LANGUAGES = {
779
833
  guide_ready: 'BMAD+ è pronto! Parla con Atlas per iniziare 🚀',
780
834
  guide_credits: '✨ BMAD+ è creato da Laurent Rochetta — github.com/lrochetta/BMAD-PLUS ✨',
781
835
  uninstall_confirm: 'Rimuovere BMAD+ da questo progetto?',
836
+ noninteractive_requires_yes: (command) => "Questo comando richiede un terminale. Eseguire `npx bmad-plus " + command + " --yes` per continuare senza domande.",
837
+ manifest_invalid: (error) => "Il manifesto di installazione è illeggibile o danneggiato: " + error + "",
838
+ manifest_repair: 'Controllare e riparare _bmad/.bmad-plus-install.json prima di riprovare.',
839
+ uninstall_not_installed: 'BMAD+ non è installato in questa directory.',
840
+ uninstall_aborted: (error) => "Disinstallazione interrotta: " + error + "",
841
+ uninstall_preserved: 'La memoria, le impostazioni e i file sconosciuti o modificati sono stati conservati.',
782
842
  uninstall_removing: 'Rimozione...',
783
843
  uninstall_done: (n) => `✅ BMAD+ rimosso (${n} elementi)`,
784
844
  uninstall_output_kept: '📁 _bmad-output/ conservato (contiene file)',