bmad-plus 0.13.0 → 0.14.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 (104) hide show
  1. package/CHANGELOG.md +22 -0
  2. package/README.md +96 -489
  3. package/package.json +7 -2
  4. package/readme-international/README.de.md +9 -5
  5. package/readme-international/README.es.md +9 -5
  6. package/readme-international/README.fr.md +9 -5
  7. package/src/bmad-plus/agents/agent-orchestrator/SKILL.md +3 -3
  8. package/src/bmad-plus/packs/pack-dev-studio/README.md +133 -141
  9. package/src/bmad-plus/packs/pack-dev-studio/SKILL.md +49 -0
  10. package/src/bmad-plus/packs/pack-dev-studio/categories/analysis/analyst-agent.md +35 -60
  11. package/src/bmad-plus/packs/pack-dev-studio/categories/analysis/document-project.md +59 -59
  12. package/src/bmad-plus/packs/pack-dev-studio/categories/analysis/domain-research.md +55 -93
  13. package/src/bmad-plus/packs/pack-dev-studio/categories/analysis/market-research.md +58 -93
  14. package/src/bmad-plus/packs/pack-dev-studio/categories/analysis/prfaq.md +55 -132
  15. package/src/bmad-plus/packs/pack-dev-studio/categories/analysis/product-brief.md +63 -78
  16. package/src/bmad-plus/packs/pack-dev-studio/categories/analysis/tech-writer-agent.md +54 -69
  17. package/src/bmad-plus/packs/pack-dev-studio/categories/analysis/technical-research.md +54 -93
  18. package/src/bmad-plus/packs/pack-dev-studio/categories/architecture/architect-agent.md +32 -60
  19. package/src/bmad-plus/packs/pack-dev-studio/categories/architecture/create-architecture.md +67 -71
  20. package/src/bmad-plus/packs/pack-dev-studio/categories/architecture/create-epics-stories.md +61 -90
  21. package/src/bmad-plus/packs/pack-dev-studio/categories/architecture/generate-project-context.md +56 -78
  22. package/src/bmad-plus/packs/pack-dev-studio/categories/architecture/implementation-readiness.md +55 -88
  23. package/src/bmad-plus/packs/pack-dev-studio/categories/architecture/steps/step-01-init.md +20 -153
  24. package/src/bmad-plus/packs/pack-dev-studio/categories/architecture/steps/step-01b-continue.md +20 -173
  25. package/src/bmad-plus/packs/pack-dev-studio/categories/architecture/steps/step-02-context.md +14 -220
  26. package/src/bmad-plus/packs/pack-dev-studio/categories/architecture/steps/step-03-starter.md +20 -329
  27. package/src/bmad-plus/packs/pack-dev-studio/categories/architecture/steps/step-04-decisions.md +15 -314
  28. package/src/bmad-plus/packs/pack-dev-studio/categories/architecture/steps/step-05-patterns.md +15 -355
  29. package/src/bmad-plus/packs/pack-dev-studio/categories/architecture/steps/step-06-structure.md +15 -375
  30. package/src/bmad-plus/packs/pack-dev-studio/categories/architecture/steps/step-07-validation.md +14 -357
  31. package/src/bmad-plus/packs/pack-dev-studio/categories/architecture/steps/step-08-complete.md +13 -78
  32. package/src/bmad-plus/packs/pack-dev-studio/categories/implementation/checkpoint-preview.md +52 -65
  33. package/src/bmad-plus/packs/pack-dev-studio/categories/implementation/code-review-steps/step-01-gather-context.md +14 -81
  34. package/src/bmad-plus/packs/pack-dev-studio/categories/implementation/code-review-steps/step-02-review.md +14 -31
  35. package/src/bmad-plus/packs/pack-dev-studio/categories/implementation/code-review-steps/step-03-triage.md +14 -45
  36. package/src/bmad-plus/packs/pack-dev-studio/categories/implementation/code-review-steps/step-04-present.md +13 -128
  37. package/src/bmad-plus/packs/pack-dev-studio/categories/implementation/code-review.md +61 -87
  38. package/src/bmad-plus/packs/pack-dev-studio/categories/implementation/correct-course.md +55 -298
  39. package/src/bmad-plus/packs/pack-dev-studio/categories/implementation/create-story.md +52 -426
  40. package/src/bmad-plus/packs/pack-dev-studio/categories/implementation/dev-agent.md +48 -69
  41. package/src/bmad-plus/packs/pack-dev-studio/categories/implementation/dev-story-checklist.md +22 -80
  42. package/src/bmad-plus/packs/pack-dev-studio/categories/implementation/dev-story.md +60 -482
  43. package/src/bmad-plus/packs/pack-dev-studio/categories/implementation/investigate.md +50 -184
  44. package/src/bmad-plus/packs/pack-dev-studio/categories/implementation/qa-e2e-tests.md +57 -173
  45. package/src/bmad-plus/packs/pack-dev-studio/categories/implementation/quick-dev.md +56 -108
  46. package/src/bmad-plus/packs/pack-dev-studio/categories/implementation/retrospective.md +54 -1509
  47. package/src/bmad-plus/packs/pack-dev-studio/categories/implementation/sprint-planning.md +54 -296
  48. package/src/bmad-plus/packs/pack-dev-studio/categories/implementation/sprint-status.md +41 -283
  49. package/src/bmad-plus/packs/pack-dev-studio/categories/planning/create-prd.md +58 -18
  50. package/src/bmad-plus/packs/pack-dev-studio/categories/planning/create-ux-design.md +103 -72
  51. package/src/bmad-plus/packs/pack-dev-studio/categories/planning/edit-prd.md +55 -27
  52. package/src/bmad-plus/packs/pack-dev-studio/categories/planning/pm-agent.md +34 -60
  53. package/src/bmad-plus/packs/pack-dev-studio/categories/planning/prd.md +46 -87
  54. package/src/bmad-plus/packs/pack-dev-studio/categories/planning/steps/step-01-init.md +10 -0
  55. package/src/bmad-plus/packs/pack-dev-studio/categories/planning/ux-designer-agent.md +30 -60
  56. package/src/bmad-plus/packs/pack-dev-studio/categories/planning/validate-prd.md +57 -27
  57. package/src/bmad-plus/packs/pack-dev-studio/categories/utilities/advanced-elicitation.md +47 -138
  58. package/src/bmad-plus/packs/pack-dev-studio/categories/utilities/adversarial-review.md +48 -34
  59. package/src/bmad-plus/packs/pack-dev-studio/categories/utilities/bmad-help.md +51 -68
  60. package/src/bmad-plus/packs/pack-dev-studio/categories/utilities/brainstorming.md +46 -3
  61. package/src/bmad-plus/packs/pack-dev-studio/categories/utilities/customize.md +68 -109
  62. package/src/bmad-plus/packs/pack-dev-studio/categories/utilities/distillator.md +53 -174
  63. package/src/bmad-plus/packs/pack-dev-studio/categories/utilities/edge-case-hunter.md +39 -53
  64. package/src/bmad-plus/packs/pack-dev-studio/categories/utilities/editorial-review-prose.md +45 -83
  65. package/src/bmad-plus/packs/pack-dev-studio/categories/utilities/editorial-review-structure.md +45 -176
  66. package/src/bmad-plus/packs/pack-dev-studio/categories/utilities/index-docs.md +45 -63
  67. package/src/bmad-plus/packs/pack-dev-studio/categories/utilities/party-mode.md +53 -124
  68. package/src/bmad-plus/packs/pack-dev-studio/categories/utilities/shard-doc.md +44 -100
  69. package/src/bmad-plus/packs/pack-dev-studio/dev-studio-orchestrator.md +56 -116
  70. package/src/bmad-plus/packs/pack-dev-studio/shared/architecture-decision-template.md +49 -12
  71. package/src/bmad-plus/packs/pack-dev-studio/shared/bwml-spec.md +51 -328
  72. package/src/bmad-plus/packs/pack-dev-studio/shared/catalog.json +489 -0
  73. package/src/bmad-plus/packs/pack-dev-studio/shared/execution.md +69 -0
  74. package/src/bmad-plus/packs/pack-dev-studio/shared/module-help.csv +39 -32
  75. package/src/bmad-plus/packs/pack-dev-studio/upstream-sync.yaml +85 -14
  76. package/src/bmad-plus/packs/pack-memory/README.md +6 -0
  77. package/src/bmad-plus/packs/pack-memory/memory-orchestrator.md +12 -5
  78. package/src/bmad-plus/packs/pack-seo/SKILL.md +27 -1
  79. package/src/bmad-plus/packs/pack-seo/seo-chief.md +16 -1
  80. package/src/bmad-plus/packs/pack-seo/seo-judge.md +12 -0
  81. package/src/bmad-plus/packs/pack-seo/seo-scout.md +12 -0
  82. package/src/bmad-plus/skills/bmad-plus-autopilot/SKILL.md +3 -3
  83. package/src/bmad-plus/skills/bmad-plus-sync/SKILL.md +5 -3
  84. package/src/bmad-plus/skills/dev-studio/SKILL.md +19 -0
  85. package/tools/build/check-install-contract.js +165 -13
  86. package/tools/build/generate.js +213 -40
  87. package/tools/build/generated-adapters/.codex/AGENTS.md +1 -1
  88. package/tools/build/generated-adapters/.cursor/rules/bmad-plus.mdc +1 -1
  89. package/tools/build/generated-adapters/.opencode/AGENTS.md +1 -1
  90. package/tools/build/generated-adapters/AGENTS.md +1 -1
  91. package/tools/build/generated-adapters/CLAUDE.md +1 -1
  92. package/tools/build/generated-adapters/CONVENTIONS.md +1 -1
  93. package/tools/build/generated-adapters/GEMINI.md +1 -1
  94. package/tools/build/pack-delivery.js +78 -0
  95. package/tools/cli/bmad-plus-cli.js +1 -1
  96. package/tools/cli/commands/doctor.js +49 -189
  97. package/tools/cli/commands/install.js +1 -1
  98. package/tools/cli/commands/studio.js +68 -0
  99. package/tools/cli/lib/installation-health.js +360 -0
  100. package/tools/cli/lib/packs.js +118 -9
  101. package/tools/cli/lib/python-health.js +233 -0
  102. package/tools/cli/lib/python-provision.js +2 -2
  103. package/tools/cli/lib/studio.js +310 -0
  104. package/tools/release/publication-content.js +901 -0
@@ -1,205 +1,65 @@
1
- /**
2
- * BMAD+ Doctor Command
3
- * Checks installation integrity and reports issues
4
- *
5
- * Author: Laurent Rochetta
6
- */
7
-
8
- const path = require('node:path');
9
- const fs = require('node:fs');
1
+ /** Human and JSON output share one report; runtime execution is explicitly opt-in. */
10
2
  const clack = require('@clack/prompts');
11
3
  const pc = require('picocolors');
12
- const { t } = require('../i18n');
13
- const { EXPECTED_AGENTS } = require('../lib/packs');
14
- const { readInstallManifest } = require('../lib/install-manifest');
4
+ const { collectInstallationHealth } = require('../lib/installation-health');
15
5
 
16
6
  module.exports = {
17
7
  command: 'doctor',
18
- description: 'Check BMAD+ installation integrity',
8
+ description: 'Check BMAD+ installation integrity and declared capabilities',
19
9
  options: [
20
10
  ['-d, --directory <path>', 'Project directory (default: current directory)'],
21
11
  ['-l, --lang <code>', 'Language code: en, fr, es, de, pt-br, ru, zh, he, ja, it'],
12
+ ['--json', 'Print the diagnostic report as JSON (read-only unless a probe is requested)'],
13
+ ['--verify-python', 'Execute installed Python interpreters to verify versions and imports'],
22
14
  ],
23
- action: async (options) => {
24
- const projectDir = path.resolve(options.directory || process.cwd());
25
- const packageJson = require('../../../package.json');
26
-
27
- clack.intro(pc.bgBlue(pc.white(` BMAD+ Doctor v${packageJson.version} `)));
28
-
29
- let checks = 0;
30
- let passed = 0;
31
- let warnings = 0;
32
- let errors = 0;
33
-
34
- // ── Check 1: Installation manifest ──
35
- checks++;
36
- const manifestPath = path.join(projectDir, '_bmad', '.bmad-plus-install.json');
37
- if (!fs.existsSync(manifestPath)) {
38
- clack.log.error('❌ BMAD+ is not installed in this directory');
39
- clack.outro(pc.red('Run `npx bmad-plus install` first.'));
40
- return;
41
- }
42
-
43
- let manifest;
44
- try {
45
- manifest = readInstallManifest(manifestPath);
46
- } catch (err) {
47
- const i = t(options.lang || 'en');
48
- clack.log.error(i.manifest_invalid(err.message));
49
- clack.outro(pc.red(i.manifest_repair));
50
- process.exitCode = 1;
15
+ action: async (options = {}) => {
16
+ const report = collectInstallationHealth({
17
+ projectDir: options.directory,
18
+ verifyPython: Boolean(options.verifyPython),
19
+ });
20
+ process.exitCode = report.summary.errors ? 1 : 0;
21
+ if (options.json) {
22
+ console.log(JSON.stringify(report, null, 2));
51
23
  return;
52
24
  }
53
- clack.log.success(`✅ Manifest found v${manifest.version}`);
54
- passed++;
55
-
56
- // ── Check 2: Version comparison ──
57
- checks++;
58
- if (manifest.version === packageJson.version) {
59
- clack.log.success(`✅ Version up to date (v${manifest.version})`);
60
- passed++;
61
- } else {
62
- clack.log.warn(`⚠️ Version mismatch: installed v${manifest.version} → latest v${packageJson.version}`);
63
- clack.log.info(' Run `npx bmad-plus update` to upgrade');
64
- warnings++;
25
+ clack.intro(pc.bgBlue(pc.white(' BMAD+ Doctor v' + report.versions.cli + ' ')));
26
+ for (const entry of report.checks.filter(
27
+ (item) => item.status !== 'pass' || item.code === 'manifest.valid'
28
+ )) {
29
+ const log =
30
+ entry.status === 'error'
31
+ ? clack.log.error
32
+ : entry.status === 'warning'
33
+ ? clack.log.warn
34
+ : clack.log.success;
35
+ log(
36
+ entry.message +
37
+ (entry.path && !entry.message.includes(entry.path) ? ' (' + entry.path + ')' : '')
38
+ );
65
39
  }
66
-
67
- // ── Check 3: Agent files ──
68
- checks++;
69
- const agentsDir = path.join(projectDir, '.agents', 'skills');
70
- if (fs.existsSync(agentsDir)) {
71
- const agentDirs = fs.readdirSync(agentsDir, { withFileTypes: true })
72
- .filter(d => d.isDirectory())
73
- .map(d => d.name);
74
- clack.log.success(`✅ ${agentDirs.length} agent/skill directories found`);
75
- passed++;
76
-
77
- // Check each expected agent from manifest packs using shared EXPECTED_AGENTS module
78
- for (const pack of (manifest.packs || ['core'])) {
79
- const entry = EXPECTED_AGENTS[pack];
80
- if (!entry) continue;
81
-
82
- // Check individual agent directories
83
- for (const agent of (entry.agents || [])) {
84
- checks++;
85
- const agentPath = path.join(agentsDir, agent);
86
- if (fs.existsSync(agentPath)) {
87
- passed++;
88
- } else {
89
- clack.log.warn(`⚠️ Missing agent: ${agent} (pack: ${pack})`);
90
- warnings++;
91
- }
92
- }
93
-
94
- // Check pack directory if applicable
95
- if (entry.packDir) {
96
- checks++;
97
- const packPath = path.join(agentsDir, entry.packDir);
98
- if (fs.existsSync(packPath)) {
99
- passed++;
100
-
101
- // These packs bundle their agents as files inside packDir — verify
102
- // them there (not as loose directories, which would falsely warn).
103
- for (const agentFile of (entry.packAgents || [])) {
104
- checks++;
105
- if (fs.existsSync(path.join(packPath, agentFile))) {
106
- passed++;
107
- } else {
108
- clack.log.warn(`⚠️ Missing agent: ${agentFile} (pack: ${pack})`);
109
- warnings++;
110
- }
111
- }
112
- } else {
113
- clack.log.warn(`⚠️ Missing pack directory: ${entry.packDir} (pack: ${pack})`);
114
- warnings++;
115
- }
116
- }
117
- }
118
- } else {
119
- clack.log.error('❌ No .agents/skills/ directory found');
120
- errors++;
40
+ if (report.versions.installed) {
41
+ clack.note(
42
+ [
43
+ report.summary.passed + '/' + report.checks.length + ' checks passed',
44
+ report.summary.errors + ' error(s), ' + report.summary.warnings + ' warning(s)',
45
+ 'Installed: v' + report.versions.installed + ' | Executing CLI: v' + report.versions.cli,
46
+ 'Ownership inventory: ' + report.inventory.status,
47
+ 'Integrations use host-managed execution; host capabilities were not probed.',
48
+ ].join('\n'),
49
+ 'BMAD+ Health Report'
50
+ );
121
51
  }
122
-
123
- // ── Check 4: Config files ──
124
- checks++;
125
- const configPath = path.join(projectDir, '_bmad', 'config.yaml');
126
- if (fs.existsSync(configPath)) {
127
- clack.log.success(' config.yaml present');
128
- passed++;
129
- } else {
130
- clack.log.error(' config.yaml missing');
131
- errors++;
132
- }
133
-
134
- // ── Check 5: Module config ──
135
- checks++;
136
- const moduleYaml = path.join(projectDir, '_bmad', 'module.yaml');
137
- if (fs.existsSync(moduleYaml)) {
138
- clack.log.success('✅ module.yaml present');
139
- passed++;
140
- } else {
141
- clack.log.warn('⚠️ module.yaml missing');
142
- warnings++;
143
- }
144
-
145
- // ── Check 6: IDE configs ──
146
- checks++;
147
- const ideFiles = ['CLAUDE.md', 'GEMINI.md', 'AGENTS.md'].filter(f =>
148
- fs.existsSync(path.join(projectDir, f))
52
+ clack.log.info(
53
+ 'Published version is not checked here. Use `bmad-plus update-check --json` to check npm.'
54
+ );
55
+ clack.outro(
56
+ report.status === 'ok'
57
+ ? pc.green('Installation checks passed.')
58
+ : pc.yellow(
59
+ options.verifyPython
60
+ ? 'Review the reported evidence. Python import probes ran; no provisioning was requested.'
61
+ : 'Review the reported evidence before changing files. Doctor did not modify the project.'
62
+ )
149
63
  );
150
- if (ideFiles.length > 0) {
151
- clack.log.success(`✅ ${ideFiles.length} IDE config(s): ${ideFiles.join(', ')}`);
152
- passed++;
153
- } else {
154
- clack.log.warn('⚠️ No IDE config files found');
155
- warnings++;
156
- }
157
-
158
- // ── Check 7: Output directories ──
159
- checks++;
160
- const outputDir = path.join(projectDir, '_bmad-output');
161
- if (fs.existsSync(outputDir)) {
162
- clack.log.success('✅ _bmad-output/ directory exists');
163
- passed++;
164
- } else {
165
- clack.log.warn('⚠️ _bmad-output/ not found');
166
- warnings++;
167
- }
168
-
169
- // ── Check 8: Skills integrity (SKILL.md exists in pack dirs) ──
170
- if (manifest.packs && manifest.packs.includes('seo')) {
171
- checks++;
172
- const seoSkill = path.join(agentsDir, 'pack-seo', 'SKILL.md');
173
- if (fs.existsSync(seoSkill)) {
174
- clack.log.success('✅ SEO Engine SKILL.md present');
175
- passed++;
176
- } else {
177
- clack.log.error('❌ SEO Engine SKILL.md missing — /seo audit will not work');
178
- errors++;
179
- }
180
- }
181
-
182
- // ── Summary ──
183
- const summaryColor = errors > 0 ? pc.red : warnings > 0 ? pc.yellow : pc.green;
184
- const summaryIcon = errors > 0 ? '❌' : warnings > 0 ? '⚠️' : '✅';
185
-
186
- clack.note([
187
- `${summaryIcon} ${passed}/${checks} checks passed`,
188
- errors > 0 ? `❌ ${errors} error(s)` : null,
189
- warnings > 0 ? `⚠️ ${warnings} warning(s)` : null,
190
- '',
191
- `📦 Version: v${manifest.version}`,
192
- `📅 Installed: ${manifest.installed.split('T')[0]}`,
193
- `🗣️ Language: ${manifest.language || 'N/A'}`,
194
- `📦 Packs: ${(manifest.packs || ['core']).join(', ')}`,
195
- ].filter(Boolean).join('\n'), '🩺 BMAD+ Health Report');
196
-
197
- clack.outro(summaryColor(
198
- errors > 0
199
- ? 'Issues found — run `npx bmad-plus install` to fix'
200
- : warnings > 0
201
- ? 'Minor issues found — consider running `npx bmad-plus update`'
202
- : 'Everything looks great! 🎉'
203
- ));
204
64
  },
205
65
  };
@@ -35,7 +35,7 @@ module.exports = {
35
35
  ['-l, --lang <code>', 'Language code: en, fr, es, de, pt-br, ru, zh, he, ja, it (overrides auto-detection)'],
36
36
  ['--tools <tools>', 'Comma-separated IDE IDs, all, or none (default: auto-detect)'],
37
37
  ['--mode <mode>', 'Execution mode: manual, autopilot, hybrid (default: manual)'],
38
- ['--provision-python', 'Provision an isolated Python env for packs that need one (seo, memory)'],
38
+ ['--provision-python', 'Provision isolated environments for selected Python packs'],
39
39
  ],
40
40
  action: async (options) => {
41
41
  // A closed/piped stdin cannot answer prompts. Require explicit defaults
@@ -0,0 +1,68 @@
1
+ /** Inspect installed Dev Studio routes and prepare actual host instructions. */
2
+ const path = require('node:path');
3
+ const { installedPack, validatePack, prepare } = require('../lib/studio');
4
+
5
+ module.exports = {
6
+ command: 'studio <action> [workflow]',
7
+ description: 'List Dev Studio workflows or prepare read-only execution context',
8
+ options: [
9
+ ['-d, --directory <path>', 'Installed project directory'],
10
+ ['--request <text>', 'Task scope for the host assistant'],
11
+ [
12
+ '--input <file>',
13
+ 'Project-relative input file (repeatable)',
14
+ (file, files) => [...files, file],
15
+ [],
16
+ ],
17
+ ['--json', 'Print machine-readable context and evidence'],
18
+ ],
19
+ action: (action, workflow, options = {}) => {
20
+ try {
21
+ const projectDir = path.resolve(options.directory || process.cwd());
22
+ let result;
23
+ if (action === 'list' && !workflow) {
24
+ const { catalog, resources } = validatePack(installedPack(projectDir));
25
+ result = {
26
+ schemaVersion: 1,
27
+ execution: 'host-managed',
28
+ ...catalog,
29
+ validatedResources: resources.length,
30
+ };
31
+ } else if (action === 'prepare' && workflow) {
32
+ result = prepare({ projectDir, workflow, request: options.request, inputs: options.input });
33
+ } else throw new Error('Use studio list or studio prepare WORKFLOW.');
34
+ process.exitCode = result.status === 'needs-input' ? 2 : 0;
35
+ if (options.json) console.log(JSON.stringify(result, null, 2));
36
+ else if (action === 'list')
37
+ console.log(
38
+ result.workflows.map((w) => `${w.id} (${w.agent}; input: ${w.input})`).join('\n')
39
+ );
40
+ else
41
+ console.log(
42
+ [
43
+ `${result.workflow}: ${result.status} — prepared for the host, not executed.`,
44
+ `Project: ${result.projectDir}`,
45
+ `Request: ${result.request || '(none supplied)'}`,
46
+ `Resolved configuration:\n${JSON.stringify(result.config.values, null, 2)}`,
47
+ `Defaulted fields: ${result.config.defaultsUsed.join(', ') || '(none)'}`,
48
+ `Proposed report: ${result.outputPath}`,
49
+ ...result.missingInputs,
50
+ ...result.instructions.map(
51
+ (item) => `\n--- ${item.path} (${item.sha256}) ---\n${item.content}`
52
+ ),
53
+ ...result.inputs.map(
54
+ (item) => `\n--- Project input: ${item.path} (${item.sha256}) ---\n${item.content}`
55
+ ),
56
+ result.previousReport
57
+ ? `\n--- Continue existing report ---\n${result.previousReport.content}`
58
+ : '',
59
+ ].join('\n')
60
+ );
61
+ } catch (error) {
62
+ process.exitCode = 1;
63
+ if (options.json)
64
+ console.log(JSON.stringify({ schemaVersion: 1, status: 'error', error: error.message }));
65
+ else console.error('Dev Studio: ' + error.message);
66
+ }
67
+ },
68
+ };