takomi 2.0.7 → 2.1.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 (66) hide show
  1. package/.pi/README.md +124 -0
  2. package/.pi/agents/architect.md +16 -0
  3. package/.pi/agents/coder.md +15 -0
  4. package/.pi/agents/designer.md +18 -0
  5. package/.pi/agents/orchestrator.md +23 -0
  6. package/.pi/agents/reviewer.md +17 -0
  7. package/.pi/extensions/oauth-router/README.md +125 -0
  8. package/.pi/extensions/oauth-router/commands.ts +380 -0
  9. package/.pi/extensions/oauth-router/config.ts +200 -0
  10. package/.pi/extensions/oauth-router/index.ts +41 -0
  11. package/.pi/extensions/oauth-router/oauth-flow.ts +154 -0
  12. package/.pi/extensions/oauth-router/oauth-store.ts +121 -0
  13. package/.pi/extensions/oauth-router/package.json +14 -0
  14. package/.pi/extensions/oauth-router/policies.ts +27 -0
  15. package/.pi/extensions/oauth-router/provider.ts +492 -0
  16. package/.pi/extensions/oauth-router/scripts/vibe-verify.py +98 -0
  17. package/.pi/extensions/oauth-router/state.ts +174 -0
  18. package/.pi/extensions/oauth-router/types.ts +153 -0
  19. package/.pi/extensions/takomi-runtime/command-text.ts +130 -0
  20. package/.pi/extensions/takomi-runtime/commands.ts +179 -0
  21. package/.pi/extensions/takomi-runtime/context-panel.ts +282 -0
  22. package/.pi/extensions/takomi-runtime/index.ts +1288 -0
  23. package/.pi/extensions/takomi-runtime/profile.ts +114 -0
  24. package/.pi/extensions/takomi-runtime/routing-policy.ts +105 -0
  25. package/.pi/extensions/takomi-runtime/shared.ts +492 -0
  26. package/.pi/extensions/takomi-runtime/subagent-controller.ts +364 -0
  27. package/.pi/extensions/takomi-runtime/subagent-render.ts +501 -0
  28. package/.pi/extensions/takomi-runtime/subagent-types.ts +83 -0
  29. package/.pi/extensions/takomi-runtime/ui.ts +133 -0
  30. package/.pi/extensions/takomi-subagents/agent-aliases.ts +18 -0
  31. package/.pi/extensions/takomi-subagents/agents.ts +113 -0
  32. package/.pi/extensions/takomi-subagents/delegation-plan.ts +95 -0
  33. package/.pi/extensions/takomi-subagents/dispatch-helpers.ts +26 -0
  34. package/.pi/extensions/takomi-subagents/dispatch.ts +215 -0
  35. package/.pi/extensions/takomi-subagents/index.ts +75 -0
  36. package/.pi/extensions/takomi-subagents/live-updates.ts +83 -0
  37. package/.pi/extensions/takomi-subagents/native-render.ts +174 -0
  38. package/.pi/extensions/takomi-subagents/tool-runner.ts +209 -0
  39. package/.pi/prompts/build-prompt.md +199 -0
  40. package/.pi/prompts/design-prompt.md +134 -0
  41. package/.pi/prompts/genesis-prompt.md +133 -0
  42. package/.pi/prompts/orch-prompt.md +144 -0
  43. package/.pi/prompts/prime-prompt.md +80 -0
  44. package/.pi/prompts/takomi-prompt.md +96 -0
  45. package/.pi/prompts/vibe-primeAgent.md +97 -0
  46. package/.pi/prompts/vibe-spawnTask.md +133 -0
  47. package/.pi/prompts/vibe-syncDocs.md +100 -0
  48. package/.pi/themes/takomi-noir.json +81 -0
  49. package/README.md +28 -2
  50. package/assets/.agent/skills/pr-comment-fix/SKILL.md +182 -0
  51. package/assets/.agent/skills/takomi/SKILL.md +59 -59
  52. package/package.json +58 -45
  53. package/src/cli.js +158 -8
  54. package/src/doctor.js +84 -0
  55. package/src/pi-harness.js +351 -0
  56. package/src/pi-installer.js +171 -0
  57. package/src/pi-takomi-core/index.ts +4 -0
  58. package/src/pi-takomi-core/orchestration.ts +402 -0
  59. package/src/pi-takomi-core/routing.ts +93 -0
  60. package/src/pi-takomi-core/types.ts +173 -0
  61. package/src/pi-takomi-core/workflows.ts +299 -0
  62. package/src/skills-installer.js +101 -0
  63. package/src/utils.js +479 -447
  64. package/assets/.agent/skills/skill-creator/scripts/__pycache__/quick_validate.cpython-311.pyc +0 -0
  65. package/assets/.agent/skills/ui-ux-pro-max/scripts/__pycache__/core.cpython-311.pyc +0 -0
  66. package/assets/.agent/skills/ui-ux-pro-max/scripts/__pycache__/design_system.cpython-311.pyc +0 -0
package/package.json CHANGED
@@ -1,46 +1,59 @@
1
- {
2
- "name": "takomi",
3
- "version": "2.0.7",
4
- "description": "šŸŽÆ Stop wrestling with AI. Start building with purpose. The artisan's toolkit for agent workflows, Codex skills, and original Takomi capabilities like 21st.dev integration.",
5
- "type": "module",
6
- "bin": {
7
- "takomi": "./bin/takomi.js"
8
- },
9
- "files": [
10
- "bin",
11
- "src",
12
- "assets"
13
- ],
14
- "scripts": {
15
- "test": "echo \"Error: no test specified\" && exit 1"
16
- },
17
- "repository": {
18
- "type": "git",
19
- "url": "git+https://github.com/JStaRFilms/VibeCode-Protocol-Suite.git"
20
- },
21
- "keywords": [
22
- "takomi",
23
- "ai",
24
- "skills",
25
- "codex",
26
- "agentic",
27
- "21st.dev",
28
- "vibecode",
29
- "cursor",
30
- "windsurf",
31
- "protocols"
32
- ],
33
- "author": "J StaR Films Studios",
34
- "license": "UNLICENSED",
35
- "dependencies": {
36
- "commander": "^13.1.0",
37
- "figlet": "^1.8.0",
38
- "fs-extra": "^11.3.0",
39
- "picocolors": "^1.1.1",
40
- "prompts": "^2.4.2"
41
- },
42
- "bugs": {
43
- "url": "https://github.com/JStaRFilms/VibeCode-Protocol-Suite/issues"
44
- },
45
- "homepage": "https://github.com/JStaRFilms/VibeCode-Protocol-Suite#readme"
1
+ {
2
+ "name": "takomi",
3
+ "version": "2.1.0",
4
+ "description": "šŸŽÆ Stop wrestling with AI. Start building with purpose. The artisan's toolkit for agent workflows, Codex skills, and original Takomi capabilities like 21st.dev integration.",
5
+ "type": "module",
6
+ "bin": {
7
+ "takomi": "./bin/takomi.js"
8
+ },
9
+ "files": [
10
+ "bin",
11
+ "src",
12
+ "assets",
13
+ ".pi/README.md",
14
+ ".pi/agents",
15
+ ".pi/extensions",
16
+ ".pi/prompts",
17
+ ".pi/themes"
18
+ ],
19
+ "scripts": {
20
+ "test": "echo \"Error: no test specified\" && exit 1"
21
+ },
22
+ "repository": {
23
+ "type": "git",
24
+ "url": "git+https://github.com/JStaRFilms/VibeCode-Protocol-Suite.git"
25
+ },
26
+ "keywords": [
27
+ "takomi",
28
+ "ai",
29
+ "skills",
30
+ "codex",
31
+ "agentic",
32
+ "21st.dev",
33
+ "vibecode",
34
+ "cursor",
35
+ "windsurf",
36
+ "protocols"
37
+ ],
38
+ "author": "J StaR Films Studios",
39
+ "license": "ISC",
40
+ "dependencies": {
41
+ "commander": "^13.1.0",
42
+ "figlet": "^1.8.0",
43
+ "fs-extra": "^11.3.0",
44
+ "pi-subagents": "^0.24.0",
45
+ "picocolors": "^1.1.1",
46
+ "prompts": "^2.4.2"
47
+ },
48
+ "bugs": {
49
+ "url": "https://github.com/JStaRFilms/VibeCode-Protocol-Suite/issues"
50
+ },
51
+ "homepage": "https://github.com/JStaRFilms/VibeCode-Protocol-Suite#readme",
52
+ "devDependencies": {
53
+ "@mariozechner/pi-ai": "^0.70.2",
54
+ "@mariozechner/pi-coding-agent": "^0.70.2",
55
+ "@types/node": "^25.5.2",
56
+ "typebox": "^1.1.33",
57
+ "typescript": "^6.0.2"
58
+ }
46
59
  }
package/src/cli.js CHANGED
@@ -15,6 +15,7 @@ import {
15
15
  copyAgentReadme,
16
16
  copyAgentYamls,
17
17
  copyLegacyManual,
18
+ copyBundledPiAssets,
18
19
  updateWorkflows,
19
20
  updateSkills,
20
21
  updateAgentYamls,
@@ -39,6 +40,10 @@ import {
39
40
  getStoreWorkflows,
40
41
  isStoreInitialized,
41
42
  } from './store.js';
43
+ import { runDoctor } from './doctor.js';
44
+ import { ensurePiInstalled, ensurePiSubagentsInstalled, launchTakomiHarness, printPiInstallResult, printPiSubagentsInstallResult } from './pi-harness.js';
45
+ import { installPiHarnessAssets, printPiInstallSummary, syncPiHarnessAssets, validatePiHarnessInstall } from './pi-installer.js';
46
+ import { installBundledSkills, printSkillsInstallSummary, validateSkillsInstall } from './skills-installer.js';
42
47
 
43
48
  const program = new Command();
44
49
 
@@ -124,6 +129,10 @@ async function init() {
124
129
  // 0. Install from local assets
125
130
  console.log(pc.cyan('šŸ“¦ Installing from local bundle...\n'));
126
131
 
132
+ if (await copyBundledPiAssets(destRoot)) {
133
+ console.log(pc.green('āœ” Installed Pi-native Takomi runtime (.pi).'));
134
+ }
135
+
127
136
  // 1. Handle .agent Folder
128
137
  if (response.components.includes('agent')) {
129
138
  const agentDest = path.join(destRoot, '.agent');
@@ -197,7 +206,8 @@ async function init() {
197
206
  console.log(pc.white(`\nNext steps:`));
198
207
  if (response.components.includes('agent')) {
199
208
  console.log(pc.gray(`1. Your .agent folder is armed and ready.`));
200
- console.log(pc.gray(`2. In Codex, say "use takomi genesis" (slash command optional).`));
209
+ console.log(pc.gray(`2. Your Pi-native .pi Takomi runtime is installed.`));
210
+ console.log(pc.gray(`3. In Codex, say "use takomi genesis" (slash command optional).`));
201
211
  }
202
212
  console.log(pc.dim(`\nšŸ’” Pro tip: Run "takomi install" to sync this toolkit across all your IDEs.\n`));
203
213
 
@@ -206,11 +216,125 @@ async function init() {
206
216
  }
207
217
  }
208
218
 
219
+ async function installSkillsTarget() {
220
+ console.log(pc.magenta('🧰 Takomi Skills Install\n'));
221
+ try {
222
+ const result = await installBundledSkills(program.version());
223
+ const validation = await validateSkillsInstall();
224
+ printSkillsInstallSummary(result, validation);
225
+ console.log(pc.dim('\nGlobal skills are ready for Pi or other supported harnesses.\n'));
226
+ } catch (error) {
227
+ console.log(pc.red('\nSkills install failed.'));
228
+ console.log(pc.dim(String(error?.message || error)));
229
+ }
230
+ }
231
+
232
+ async function installAllTargets() {
233
+ await installPiTarget();
234
+ await installSkillsTarget();
235
+ }
236
+
237
+ async function installPiTarget() {
238
+ console.log(pc.magenta('🧭 Pi Harness Preflight\n'));
239
+ const report = await runDoctor({ version: program.version() });
240
+
241
+ if (!report.pi.installed) {
242
+ console.log(pc.cyan('\nšŸ“¦ Installing Pi...\n'));
243
+ const installResult = await ensurePiInstalled();
244
+ printPiInstallResult(installResult);
245
+ if (!installResult.ok) {
246
+ console.log(pc.yellow('\nPi harness install stopped because Pi could not be installed.'));
247
+ console.log(pc.dim('Retry manually with: npm install -g @mariozechner/pi-coding-agent\n'));
248
+ return;
249
+ }
250
+ }
251
+
252
+ if (!report.piSubagents.localInstalled && !report.piSubagents.globalInstalled) {
253
+ console.log(pc.cyan('\nšŸ“¦ Installing pi-subagents...\n'));
254
+ const installResult = await ensurePiSubagentsInstalled();
255
+ printPiSubagentsInstallResult(installResult);
256
+ if (!installResult.ok) {
257
+ console.log(pc.yellow('\nPi harness install stopped because pi-subagents could not be installed.'));
258
+ console.log(pc.dim('Retry manually with: npm install -g pi-subagents\n'));
259
+ return;
260
+ }
261
+ }
262
+
263
+ console.log(pc.cyan('\nšŸ“¦ Installing Takomi Pi harness assets...\n'));
264
+ try {
265
+ const result = await installPiHarnessAssets(program.version());
266
+ const validation = await validatePiHarnessInstall();
267
+ printPiInstallSummary(result, validation);
268
+ console.log(pc.dim('\nNext: cd <project> && takomi\n'));
269
+ } catch (error) {
270
+ console.log(pc.red('\nPi harness asset install failed.'));
271
+ console.log(pc.dim(String(error?.message || error)));
272
+ }
273
+ }
274
+
275
+ async function syncPiTarget() {
276
+ console.log(pc.magenta('šŸ“” Takomi Pi Sync\n'));
277
+ try {
278
+ const result = await syncPiHarnessAssets(program.version());
279
+ const validation = await validatePiHarnessInstall();
280
+ printPiInstallSummary(result, validation);
281
+ } catch (error) {
282
+ console.log(pc.red('\nPi sync failed.'));
283
+ console.log(pc.dim(String(error?.message || error)));
284
+ }
285
+ }
286
+
287
+ async function syncSkillsTarget() {
288
+ console.log(pc.magenta('šŸ“” Takomi Skills Sync\n'));
289
+ try {
290
+ const result = await installBundledSkills(program.version());
291
+ const validation = await validateSkillsInstall();
292
+ printSkillsInstallSummary(result, validation);
293
+ } catch (error) {
294
+ console.log(pc.red('\nSkills sync failed.'));
295
+ console.log(pc.dim(String(error?.message || error)));
296
+ }
297
+ }
298
+
299
+ async function syncAllTargets() {
300
+ await syncPiTarget();
301
+ await syncSkillsTarget();
302
+ }
303
+
304
+ function printUnsupportedInstallTarget(target) {
305
+ console.log(pc.yellow(`Unsupported install target: ${target}`));
306
+ console.log(pc.dim('Supported targets right now: pi, skills, all'));
307
+ console.log(pc.dim('Use plain "takomi install" for the existing interactive global installer.\n'));
308
+ }
309
+
310
+ function printUnsupportedSyncTarget(target) {
311
+ console.log(pc.yellow(`Unsupported sync target: ${target}`));
312
+ console.log(pc.dim('Supported targets right now: pi, skills, all'));
313
+ console.log(pc.dim('Use plain "takomi sync" for the existing interactive global sync.\n'));
314
+ }
315
+
209
316
  // ─────────────────────────────────────────────────────────────────────────────
210
317
  // takomi install (NEW — Global Setup + Harness Routing)
211
318
  // ─────────────────────────────────────────────────────────────────────────────
212
319
 
213
- async function install() {
320
+ async function install(target) {
321
+ if (target) {
322
+ if (target === 'pi') {
323
+ await installPiTarget();
324
+ return;
325
+ }
326
+ if (target === 'skills') {
327
+ await installSkillsTarget();
328
+ return;
329
+ }
330
+ if (target === 'all') {
331
+ await installAllTargets();
332
+ return;
333
+ }
334
+
335
+ printUnsupportedInstallTarget(target);
336
+ return;
337
+ }
214
338
  console.log(pc.magenta(figlet.textSync('Takomi', { horizontalLayout: 'full' })));
215
339
  console.log(pc.cyan(' 🌐 One install. Every IDE. Zero friction.\n'));
216
340
 
@@ -359,7 +483,23 @@ async function install() {
359
483
  // takomi sync (NEW — Re-sync store to all harnesses)
360
484
  // ─────────────────────────────────────────────────────────────────────────────
361
485
 
362
- async function sync() {
486
+ async function sync(target) {
487
+ if (target) {
488
+ if (target === 'pi') {
489
+ await syncPiTarget();
490
+ return;
491
+ }
492
+ if (target === 'skills') {
493
+ await syncSkillsTarget();
494
+ return;
495
+ }
496
+ if (target === 'all') {
497
+ await syncAllTargets();
498
+ return;
499
+ }
500
+ printUnsupportedSyncTarget(target);
501
+ return;
502
+ }
363
503
  console.log(pc.magenta('šŸ“” Syncing your toolkit to all connected IDEs...\n'));
364
504
 
365
505
  // Check if global store exists
@@ -545,14 +685,14 @@ program
545
685
 
546
686
  // Global installer (NEW)
547
687
  program
548
- .command('install')
549
- .description('Build your global command center')
688
+ .command('install [target]')
689
+ .description('Build your global command center or run a target-specific installer')
550
690
  .action(install);
551
691
 
552
692
  // Re-sync (NEW)
553
693
  program
554
- .command('sync')
555
- .description('Push updates to all connected IDEs')
694
+ .command('sync [target]')
695
+ .description('Push updates to all connected IDEs or sync a target-specific install')
556
696
  .action(sync);
557
697
 
558
698
  // Add remote skills (NEW)
@@ -567,6 +707,11 @@ program
567
707
  .description('See your toolkit status and connected IDEs')
568
708
  .action(harnesses);
569
709
 
710
+ program
711
+ .command('doctor')
712
+ .description('Run Pi/Takomi installation diagnostics')
713
+ .action(() => runDoctor({ version: program.version() }));
714
+
570
715
  // Update from GitHub (EXISTING — enhanced)
571
716
  program
572
717
  .command('update')
@@ -636,4 +781,9 @@ program
636
781
  console.log(pc.magenta('\n✨ Your toolkit is fresh and ready to ship.'));
637
782
  });
638
783
 
639
- program.parse();
784
+ if (process.argv.length <= 2) {
785
+ const exitCode = await launchTakomiHarness(process.cwd());
786
+ process.exitCode = exitCode;
787
+ } else {
788
+ program.parse();
789
+ }
package/src/doctor.js ADDED
@@ -0,0 +1,84 @@
1
+ import fs from 'fs-extra';
2
+ import pc from 'picocolors';
3
+ import { inspectPiHarnessEnvironment } from './pi-harness.js';
4
+ import { getStoreSkills, isStoreInitialized } from './store.js';
5
+ import { PI_MANIFEST_PATH } from './pi-installer.js';
6
+ import { SKILLS_MANIFEST_PATH, SKILLS_ROOT } from './skills-installer.js';
7
+
8
+ function status(ok, label, value) {
9
+ const icon = ok ? pc.green('āœ”') : pc.yellow('āœ—');
10
+ const suffix = value ? ` ${pc.dim(value)}` : '';
11
+ return ` ${icon} ${label}${suffix}`;
12
+ }
13
+
14
+ export async function runDoctor({ version, cwd = process.cwd() } = {}) {
15
+ const report = await inspectPiHarnessEnvironment(cwd);
16
+ const storeReady = await isStoreInitialized();
17
+ const storeSkills = storeReady ? await getStoreSkills() : [];
18
+
19
+ console.log(pc.magenta('🩺 Takomi Doctor\n'));
20
+ console.log(status(true, 'Takomi CLI', version || 'unknown'));
21
+ console.log(status(report.pi.installed, 'Pi command', report.pi.installed ? `${report.pi.path}${report.pi.version ? ` (${report.pi.version})` : ''}` : 'missing'));
22
+ console.log(status(report.bundled.packageReady, 'Bundled .pi assets', report.bundled.targets.root));
23
+ console.log(status(report.bundled.checks.runtime, 'Bundled takomi-runtime', report.bundled.targets.runtime));
24
+ console.log(status(report.bundled.checks.subagents, 'Bundled takomi-subagents', report.bundled.targets.subagents));
25
+ console.log(status(report.bundled.packageIncluded, 'Package includes .pi assets', report.bundled.packageIncluded ? 'yes' : 'no'));
26
+ console.log(status(report.installed.runtimeInstalled, 'Installed takomi-runtime', report.installed.targets.extensions));
27
+ console.log(status(report.installed.subagentsInstalled, 'Installed takomi-subagents', report.installed.targets.extensions));
28
+ console.log(status(await fs.pathExists(`${report.installed.targets.extensions}/oauth-router`), 'Installed oauth-router', `${report.installed.targets.extensions}`));
29
+ console.log(status(report.installed.agentsInstalled, 'Installed agents dir', report.installed.targets.agents));
30
+ console.log(status(report.installed.themesInstalled, 'Installed themes dir', report.installed.targets.themes));
31
+ console.log(status(await fs.pathExists(PI_MANIFEST_PATH), 'Pi install manifest', PI_MANIFEST_PATH));
32
+ console.log(status(report.piSubagents.declaredVersion !== null, 'pi-subagents dependency declared', report.piSubagents.declaredVersion || 'missing'));
33
+ console.log(status(report.piSubagents.localInstalled || report.piSubagents.globalInstalled, 'pi-subagents package available', report.piSubagents.localInstalled
34
+ ? `${report.piSubagents.localPackageJson}${report.piSubagents.localVersion ? ` (${report.piSubagents.localVersion})` : ''}`
35
+ : report.piSubagents.globalInstalled
36
+ ? `${report.piSubagents.globalPackageJson}${report.piSubagents.globalVersion ? ` (${report.piSubagents.globalVersion})` : ''}`
37
+ : 'missing'));
38
+ console.log(status(report.piSubagents.binaryInstalled, 'pi-subagents installer binary', report.piSubagents.binaryPath || 'missing'));
39
+ console.log(status(report.installed.routingPolicyPresent || report.project.routingPolicyPresent, 'Routing policy', report.project.routingPolicyPresent ? report.project.targets.routingPolicy : report.installed.targets.routingPolicy));
40
+ console.log(status(await fs.pathExists(SKILLS_ROOT), 'Installed skills root', SKILLS_ROOT));
41
+ console.log(status(await fs.pathExists(SKILLS_MANIFEST_PATH), 'Skills install manifest', SKILLS_MANIFEST_PATH));
42
+ console.log(status(storeReady, 'Global Takomi store', storeReady ? `${storeSkills.length} skills` : 'missing'));
43
+
44
+ console.log(pc.cyan('\nRecommendations\n'));
45
+
46
+ if (!report.pi.installed) {
47
+ console.log(pc.white(' - Install Pi first: npm install -g @mariozechner/pi-coding-agent'));
48
+ }
49
+
50
+ if (!report.bundled.packageIncluded) {
51
+ console.log(pc.white(' - Package .pi assets before enabling takomi install pi in releases.'));
52
+ }
53
+
54
+ if (!report.installed.runtimeInstalled || !report.installed.subagentsInstalled) {
55
+ console.log(pc.white(' - Run takomi install pi after the package-safe Pi asset layout is finalized.'));
56
+ }
57
+
58
+ if (!report.piSubagents.declaredVersion) {
59
+ console.log(pc.white(' - Add pi-subagents to takomi package dependencies so subagent support is bundled intentionally.'));
60
+ }
61
+
62
+ if (!report.piSubagents.localInstalled && !report.piSubagents.globalInstalled) {
63
+ console.log(pc.white(' - Install pi-subagents: npm install -g pi-subagents'));
64
+ }
65
+
66
+ if (!report.project.routingPolicyPresent && !report.installed.routingPolicyPresent) {
67
+ console.log(pc.white(' - Add a routing policy at .pi/takomi/model-routing.md when ready.'));
68
+ }
69
+
70
+ if (!await fs.pathExists(PI_MANIFEST_PATH) && report.installed.runtimeInstalled) {
71
+ console.log(pc.white(' - Re-run takomi install pi to write the Pi asset manifest.'));
72
+ }
73
+
74
+ if (!await fs.pathExists(SKILLS_ROOT)) {
75
+ console.log(pc.white(' - Run takomi install skills to install the bundled Takomi skills.'));
76
+ }
77
+
78
+ if (!storeReady) {
79
+ console.log(pc.white(' - Legacy global command center is not initialized. Run takomi install for current behavior.'));
80
+ }
81
+
82
+ console.log('');
83
+ return report;
84
+ }