@vibecheckai/cli 3.0.2 → 3.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (68) hide show
  1. package/package.json +9 -1
  2. package/bin/cli-hygiene.js +0 -241
  3. package/bin/guardrail.js +0 -834
  4. package/bin/runners/cli-utils.js +0 -1070
  5. package/bin/runners/context/ai-task-decomposer.js +0 -337
  6. package/bin/runners/context/analyzer.js +0 -462
  7. package/bin/runners/context/api-contracts.js +0 -427
  8. package/bin/runners/context/context-diff.js +0 -342
  9. package/bin/runners/context/context-pruner.js +0 -291
  10. package/bin/runners/context/dependency-graph.js +0 -414
  11. package/bin/runners/context/generators/claude.js +0 -107
  12. package/bin/runners/context/generators/codex.js +0 -108
  13. package/bin/runners/context/generators/copilot.js +0 -119
  14. package/bin/runners/context/generators/cursor.js +0 -514
  15. package/bin/runners/context/generators/mcp.js +0 -151
  16. package/bin/runners/context/generators/windsurf.js +0 -180
  17. package/bin/runners/context/git-context.js +0 -302
  18. package/bin/runners/context/index.js +0 -1042
  19. package/bin/runners/context/insights.js +0 -173
  20. package/bin/runners/context/mcp-server/generate-rules.js +0 -337
  21. package/bin/runners/context/mcp-server/index.js +0 -1176
  22. package/bin/runners/context/mcp-server/package.json +0 -24
  23. package/bin/runners/context/memory.js +0 -200
  24. package/bin/runners/context/monorepo.js +0 -215
  25. package/bin/runners/context/multi-repo-federation.js +0 -404
  26. package/bin/runners/context/patterns.js +0 -253
  27. package/bin/runners/context/proof-context.js +0 -972
  28. package/bin/runners/context/security-scanner.js +0 -303
  29. package/bin/runners/context/semantic-search.js +0 -350
  30. package/bin/runners/context/shared.js +0 -264
  31. package/bin/runners/context/team-conventions.js +0 -310
  32. package/bin/runners/lib/ai-bridge.js +0 -416
  33. package/bin/runners/lib/analysis-core.js +0 -271
  34. package/bin/runners/lib/analyzers.js +0 -541
  35. package/bin/runners/lib/audit-bridge.js +0 -391
  36. package/bin/runners/lib/auth-truth.js +0 -193
  37. package/bin/runners/lib/auth.js +0 -215
  38. package/bin/runners/lib/backup.js +0 -62
  39. package/bin/runners/lib/billing.js +0 -107
  40. package/bin/runners/lib/claims.js +0 -118
  41. package/bin/runners/lib/cli-ui.js +0 -540
  42. package/bin/runners/lib/compliance-bridge-new.js +0 -0
  43. package/bin/runners/lib/compliance-bridge.js +0 -165
  44. package/bin/runners/lib/contracts/auth-contract.js +0 -194
  45. package/bin/runners/lib/contracts/env-contract.js +0 -178
  46. package/bin/runners/lib/contracts/external-contract.js +0 -198
  47. package/bin/runners/lib/contracts/guard.js +0 -168
  48. package/bin/runners/lib/contracts/index.js +0 -89
  49. package/bin/runners/lib/contracts/plan-validator.js +0 -311
  50. package/bin/runners/lib/contracts/route-contract.js +0 -192
  51. package/bin/runners/lib/detect.js +0 -89
  52. package/bin/runners/lib/doctor/autofix.js +0 -254
  53. package/bin/runners/lib/doctor/index.js +0 -37
  54. package/bin/runners/lib/doctor/modules/dependencies.js +0 -325
  55. package/bin/runners/lib/doctor/modules/index.js +0 -46
  56. package/bin/runners/lib/doctor/modules/network.js +0 -250
  57. package/bin/runners/lib/doctor/modules/project.js +0 -312
  58. package/bin/runners/lib/doctor/modules/runtime.js +0 -224
  59. package/bin/runners/lib/doctor/modules/security.js +0 -348
  60. package/bin/runners/lib/doctor/modules/system.js +0 -213
  61. package/bin/runners/lib/doctor/modules/vibecheck.js +0 -394
  62. package/bin/runners/lib/doctor/reporter.js +0 -262
  63. package/bin/runners/lib/doctor/service.js +0 -262
  64. package/bin/runners/lib/doctor/types.js +0 -113
  65. package/bin/runners/lib/doctor/ui.js +0 -263
  66. package/bin/runners/lib/doctor-enhanced.js +0 -233
  67. package/bin/runners/lib/doctor-v2.js +0 -608
  68. package/bin/runners/lib/enforcement.js +0 -72
@@ -1,264 +0,0 @@
1
- /**
2
- * Shared Context Module
3
- * Cross-project pattern sharing and context registry
4
- */
5
-
6
- const fs = require("fs");
7
- const path = require("path");
8
- const os = require("os");
9
- const crypto = require("crypto");
10
-
11
- const VIBECHECK_HOME = path.join(os.homedir(), ".vibecheck");
12
- const SHARED_CONTEXT_FILE = path.join(VIBECHECK_HOME, "shared-context.json");
13
-
14
- /**
15
- * Initialize shared context file
16
- */
17
- function initializeSharedContext() {
18
- if (!fs.existsSync(VIBECHECK_HOME)) {
19
- fs.mkdirSync(VIBECHECK_HOME, { recursive: true });
20
- }
21
-
22
- if (!fs.existsSync(SHARED_CONTEXT_FILE)) {
23
- fs.writeFileSync(SHARED_CONTEXT_FILE, JSON.stringify({
24
- version: "1.0.0",
25
- projects: {},
26
- sharedPatterns: {},
27
- sharedHooks: {},
28
- sharedComponents: {},
29
- lastUpdated: null,
30
- }, null, 2));
31
- }
32
- }
33
-
34
- /**
35
- * Register project in shared context
36
- */
37
- function registerSharedContext(projectPath, analysis) {
38
- initializeSharedContext();
39
-
40
- let shared;
41
- try {
42
- shared = JSON.parse(fs.readFileSync(SHARED_CONTEXT_FILE, "utf-8"));
43
- } catch {
44
- shared = {
45
- projects: {},
46
- sharedPatterns: {},
47
- sharedHooks: {},
48
- sharedComponents: {},
49
- lastUpdated: null
50
- };
51
- }
52
-
53
- const projectId = crypto.createHash("md5").update(projectPath).digest("hex").slice(0, 8);
54
-
55
- // Store project info
56
- shared.projects[projectId] = {
57
- path: projectPath,
58
- name: analysis.name,
59
- framework: analysis.framework,
60
- language: analysis.language,
61
- hooks: analysis.patterns?.hooks || [],
62
- components: analysis.components?.slice(0, 30) || [],
63
- models: analysis.models?.slice(0, 20) || [],
64
- stateManagement: analysis.patterns?.stateManagement,
65
- validation: analysis.patterns?.validation,
66
- lastUpdated: new Date().toISOString(),
67
- };
68
-
69
- // Build shared hooks index
70
- shared.sharedHooks = {};
71
- for (const [id, proj] of Object.entries(shared.projects)) {
72
- for (const hook of proj.hooks || []) {
73
- shared.sharedHooks[hook] = shared.sharedHooks[hook] || [];
74
- if (!shared.sharedHooks[hook].includes(proj.name)) {
75
- shared.sharedHooks[hook].push(proj.name);
76
- }
77
- }
78
- }
79
-
80
- // Build shared components index
81
- shared.sharedComponents = {};
82
- for (const [id, proj] of Object.entries(shared.projects)) {
83
- for (const component of proj.components || []) {
84
- shared.sharedComponents[component] = shared.sharedComponents[component] || [];
85
- if (!shared.sharedComponents[component].includes(proj.name)) {
86
- shared.sharedComponents[component].push(proj.name);
87
- }
88
- }
89
- }
90
-
91
- // Build shared patterns index
92
- shared.sharedPatterns = {};
93
- for (const [id, proj] of Object.entries(shared.projects)) {
94
- if (proj.stateManagement) {
95
- shared.sharedPatterns[proj.stateManagement] = shared.sharedPatterns[proj.stateManagement] || [];
96
- if (!shared.sharedPatterns[proj.stateManagement].includes(proj.name)) {
97
- shared.sharedPatterns[proj.stateManagement].push(proj.name);
98
- }
99
- }
100
- if (proj.validation) {
101
- shared.sharedPatterns[proj.validation] = shared.sharedPatterns[proj.validation] || [];
102
- if (!shared.sharedPatterns[proj.validation].includes(proj.name)) {
103
- shared.sharedPatterns[proj.validation].push(proj.name);
104
- }
105
- }
106
- }
107
-
108
- shared.lastUpdated = new Date().toISOString();
109
- fs.writeFileSync(SHARED_CONTEXT_FILE, JSON.stringify(shared, null, 2));
110
-
111
- return shared;
112
- }
113
-
114
- /**
115
- * Get patterns shared across projects
116
- */
117
- function getSharedPatterns() {
118
- try {
119
- if (!fs.existsSync(SHARED_CONTEXT_FILE)) return null;
120
- const shared = JSON.parse(fs.readFileSync(SHARED_CONTEXT_FILE, "utf-8"));
121
-
122
- // Find patterns used in multiple projects
123
- const multiProjectPatterns = Object.entries(shared.sharedPatterns || {})
124
- .filter(([_, projects]) => projects.length > 1)
125
- .map(([pattern, projects]) => ({ pattern, projects, count: projects.length }))
126
- .sort((a, b) => b.count - a.count);
127
-
128
- return {
129
- totalProjects: Object.keys(shared.projects || {}).length,
130
- sharedPatterns: multiProjectPatterns.slice(0, 20),
131
- projects: Object.values(shared.projects || {}).map(p => ({
132
- name: p.name,
133
- framework: p.framework,
134
- lastUpdated: p.lastUpdated,
135
- })),
136
- };
137
- } catch {
138
- return null;
139
- }
140
- }
141
-
142
- /**
143
- * Get hooks shared across projects
144
- */
145
- function getSharedHooks() {
146
- try {
147
- if (!fs.existsSync(SHARED_CONTEXT_FILE)) return [];
148
- const shared = JSON.parse(fs.readFileSync(SHARED_CONTEXT_FILE, "utf-8"));
149
-
150
- return Object.entries(shared.sharedHooks || {})
151
- .filter(([_, projects]) => projects.length > 1)
152
- .map(([hook, projects]) => ({ hook, projects, count: projects.length }))
153
- .sort((a, b) => b.count - a.count)
154
- .slice(0, 30);
155
- } catch {
156
- return [];
157
- }
158
- }
159
-
160
- /**
161
- * Get components shared across projects
162
- */
163
- function getSharedComponents() {
164
- try {
165
- if (!fs.existsSync(SHARED_CONTEXT_FILE)) return [];
166
- const shared = JSON.parse(fs.readFileSync(SHARED_CONTEXT_FILE, "utf-8"));
167
-
168
- return Object.entries(shared.sharedComponents || {})
169
- .filter(([_, projects]) => projects.length > 1)
170
- .map(([component, projects]) => ({ component, projects, count: projects.length }))
171
- .sort((a, b) => b.count - a.count)
172
- .slice(0, 30);
173
- } catch {
174
- return [];
175
- }
176
- }
177
-
178
- /**
179
- * Find similar projects based on tech stack
180
- */
181
- function findSimilarProjects(analysis) {
182
- try {
183
- if (!fs.existsSync(SHARED_CONTEXT_FILE)) return [];
184
- const shared = JSON.parse(fs.readFileSync(SHARED_CONTEXT_FILE, "utf-8"));
185
-
186
- const similar = [];
187
- for (const [id, proj] of Object.entries(shared.projects || {})) {
188
- let score = 0;
189
- if (proj.framework === analysis.framework) score += 3;
190
- if (proj.language === analysis.language) score += 2;
191
- if (proj.stateManagement === analysis.patterns?.stateManagement) score += 2;
192
- if (proj.validation === analysis.patterns?.validation) score += 1;
193
-
194
- if (score > 0 && proj.name !== analysis.name) {
195
- similar.push({ ...proj, similarityScore: score });
196
- }
197
- }
198
-
199
- return similar.sort((a, b) => b.similarityScore - a.similarityScore).slice(0, 5);
200
- } catch {
201
- return [];
202
- }
203
- }
204
-
205
- /**
206
- * Get all registered projects
207
- */
208
- function getAllProjects() {
209
- try {
210
- if (!fs.existsSync(SHARED_CONTEXT_FILE)) return [];
211
- const shared = JSON.parse(fs.readFileSync(SHARED_CONTEXT_FILE, "utf-8"));
212
- return Object.values(shared.projects || {});
213
- } catch {
214
- return [];
215
- }
216
- }
217
-
218
- /**
219
- * Remove project from shared context
220
- */
221
- function removeProject(projectPath) {
222
- try {
223
- if (!fs.existsSync(SHARED_CONTEXT_FILE)) return false;
224
- const shared = JSON.parse(fs.readFileSync(SHARED_CONTEXT_FILE, "utf-8"));
225
- const projectId = crypto.createHash("md5").update(projectPath).digest("hex").slice(0, 8);
226
-
227
- if (shared.projects[projectId]) {
228
- delete shared.projects[projectId];
229
- fs.writeFileSync(SHARED_CONTEXT_FILE, JSON.stringify(shared, null, 2));
230
- return true;
231
- }
232
- return false;
233
- } catch {
234
- return false;
235
- }
236
- }
237
-
238
- /**
239
- * Clear all shared context
240
- */
241
- function clearSharedContext() {
242
- const shared = {
243
- version: "1.0.0",
244
- projects: {},
245
- sharedPatterns: {},
246
- sharedHooks: {},
247
- sharedComponents: {},
248
- lastUpdated: new Date().toISOString(),
249
- };
250
- fs.writeFileSync(SHARED_CONTEXT_FILE, JSON.stringify(shared, null, 2));
251
- }
252
-
253
- module.exports = {
254
- SHARED_CONTEXT_FILE,
255
- initializeSharedContext,
256
- registerSharedContext,
257
- getSharedPatterns,
258
- getSharedHooks,
259
- getSharedComponents,
260
- findSimilarProjects,
261
- getAllProjects,
262
- removeProject,
263
- clearSharedContext,
264
- };
@@ -1,310 +0,0 @@
1
- /**
2
- * Team Conventions Learning Module
3
- * Learns individual developer styles from git blame
4
- */
5
-
6
- const fs = require("fs");
7
- const path = require("path");
8
- const { execSync } = require("child_process");
9
-
10
- /**
11
- * Execute git command safely
12
- */
13
- function execGit(command, cwd = process.cwd()) {
14
- try {
15
- return execSync(command, { cwd, encoding: "utf-8" }).trim();
16
- } catch {
17
- return null;
18
- }
19
- }
20
-
21
- /**
22
- * Analyze author's coding style from git blame
23
- */
24
- function analyzeAuthorStyle(author, projectPath, fileLimit = 20) {
25
- // Get files touched by author
26
- const output = execGit(`log --author="${author}" --name-only --pretty=format:"" | sort | uniq`, projectPath);
27
- if (!output) return null;
28
-
29
- const files = output.split("\n")
30
- .filter(f => f && (f.endsWith(".ts") || f.endsWith(".tsx") || f.endsWith(".js") || f.endsWith(".jsx")))
31
- .slice(0, fileLimit);
32
-
33
- const style = {
34
- author,
35
- filesAnalyzed: files.length,
36
- patterns: {
37
- imports: {},
38
- naming: {
39
- components: {},
40
- functions: {},
41
- variables: {},
42
- },
43
- formatting: {
44
- semicolons: 0,
45
- quotes: { single: 0, double: 0 },
46
- trailingCommas: 0,
47
- },
48
- comments: {
49
- jsdoc: 0,
50
- inline: 0,
51
- block: 0,
52
- },
53
- react: {
54
- functional: 0,
55
- class: 0,
56
- hooks: [],
57
- },
58
- typescript: {
59
- explicitTypes: 0,
60
- interfaces: 0,
61
- types: 0,
62
- },
63
- },
64
- };
65
-
66
- for (const file of files) {
67
- try {
68
- const blameOutput = execGit(`blame --line-porcelain "${file}"`, projectPath);
69
- if (!blameOutput) continue;
70
-
71
- const lines = blameOutput.split("\n");
72
- let currentAuthor = null;
73
- let code = "";
74
-
75
- for (const line of lines) {
76
- if (line.startsWith(`author ${author}`)) {
77
- currentAuthor = author;
78
- } else if (line.startsWith("author ") && currentAuthor === author) {
79
- currentAuthor = null;
80
- } else if (line.startsWith("\t") && currentAuthor === author) {
81
- code += line.slice(1) + "\n";
82
- }
83
- }
84
-
85
- // Analyze the collected code
86
- analyzeCodeStyle(code, style);
87
- } catch {}
88
- }
89
-
90
- // Calculate percentages
91
- const totalLines = style.patterns.formatting.semicolons +
92
- style.patterns.formatting.quotes.single +
93
- style.patterns.formatting.quotes.double;
94
-
95
- if (totalLines > 0) {
96
- style.patterns.formatting.semiconPercentage = (style.patterns.formatting.semicolons / totalLines) * 100;
97
- style.patterns.formatting.singleQuotePercentage = (style.patterns.formatting.quotes.single / totalLines) * 100;
98
- }
99
-
100
- return style;
101
- }
102
-
103
- /**
104
- * Analyze code patterns from content
105
- */
106
- function analyzeCodeStyle(content, style) {
107
- const lines = content.split("\n");
108
-
109
- for (const line of lines) {
110
- const trimmed = line.trim();
111
-
112
- // Import patterns
113
- if (trimmed.startsWith("import ")) {
114
- if (trimmed.includes(" { ")) {
115
- style.patterns.imports.named = (style.patterns.imports.named || 0) + 1;
116
- } else if (trimmed.includes(" * as ")) {
117
- style.patterns.imports.namespace = (style.patterns.imports.namespace || 0) + 1;
118
- } else {
119
- style.patterns.imports.default = (style.patterns.imports.default || 0) + 1;
120
- }
121
- }
122
-
123
- // Naming patterns
124
- if (trimmed.includes("function ") || trimmed.includes("const ")) {
125
- if (/^[A-Z]/.test(trimmed)) {
126
- style.patterns.naming.components.pascalCase = (style.patterns.naming.components.pascalCase || 0) + 1;
127
- } else if (/^[a-z][A-Z]/.test(trimmed)) {
128
- style.patterns.naming.functions.camelCase = (style.patterns.naming.functions.camelCase || 0) + 1;
129
- }
130
- }
131
-
132
- // Formatting
133
- if (trimmed.endsWith(";")) {
134
- style.patterns.formatting.semicolons++;
135
- }
136
- if (trimmed.includes("'")) {
137
- style.patterns.formatting.quotes.single++;
138
- }
139
- if (trimmed.includes('"')) {
140
- style.patterns.formatting.quotes.double++;
141
- }
142
- if (trimmed.includes(",") && !trimmed.includes(", ")) {
143
- style.patterns.formatting.trailingCommas++;
144
- }
145
-
146
- // Comments
147
- if (trimmed.startsWith("/**") || trimmed.startsWith(" *")) {
148
- style.patterns.comments.jsdoc++;
149
- } else if (trimmed.startsWith("//")) {
150
- style.patterns.comments.inline++;
151
- } else if (trimmed.startsWith("/*")) {
152
- style.patterns.comments.block++;
153
- }
154
-
155
- // React patterns
156
- if (trimmed.includes("function ") && /^[A-Z]/.test(trimmed)) {
157
- style.patterns.react.functional++;
158
- } else if (trimmed.includes("class ") && trimmed.includes("extends")) {
159
- style.patterns.react.class++;
160
- }
161
-
162
- // Hooks
163
- const hookMatch = trimmed.match(/(use[A-Z]\w+)/);
164
- if (hookMatch) {
165
- if (!style.patterns.react.hooks.includes(hookMatch[1])) {
166
- style.patterns.react.hooks.push(hookMatch[1]);
167
- }
168
- }
169
-
170
- // TypeScript
171
- if (trimmed.includes(": ")) {
172
- style.patterns.typescript.explicitTypes++;
173
- }
174
- if (trimmed.includes("interface ")) {
175
- style.patterns.typescript.interfaces++;
176
- }
177
- if (trimmed.includes("type ")) {
178
- style.patterns.typescript.types++;
179
- }
180
- }
181
- }
182
-
183
- /**
184
- * Get team conventions summary
185
- */
186
- function getTeamConventions(projectPath) {
187
- const authorsOutput = execGit("log --format='%an' | sort | uniq", projectPath);
188
- if (!authorsOutput) return null;
189
-
190
- const authors = authorsOutput.split("\n").filter(a => a && a !== "GitHub Actions");
191
- const conventions = {
192
- authors: [],
193
- commonPatterns: {
194
- imports: {},
195
- formatting: {
196
- semicolons: { with: 0, without: 0 },
197
- quotes: { single: 0, double: 0 },
198
- },
199
- naming: {
200
- components: "PascalCase",
201
- functions: "camelCase",
202
- },
203
- },
204
- recommendations: [],
205
- };
206
-
207
- // Analyze top contributors
208
- for (const author of authors.slice(0, 5)) {
209
- const style = analyzeAuthorStyle(author, projectPath, 10);
210
- if (style) {
211
- conventions.authors.push({
212
- name: author,
213
- filesContributed: style.filesAnalyzed,
214
- patterns: style.patterns,
215
- });
216
- }
217
- }
218
-
219
- // Find common patterns
220
- if (conventions.authors.length > 0) {
221
- // Import preferences
222
- const importCounts = { named: 0, default: 0, namespace: 0 };
223
- for (const author of conventions.authors) {
224
- importCounts.named += author.patterns.imports.named || 0;
225
- importCounts.default += author.patterns.imports.default || 0;
226
- importCounts.namespace += author.patterns.imports.namespace || 0;
227
- }
228
-
229
- const totalImports = importCounts.named + importCounts.default + importCounts.namespace;
230
- if (totalImports > 0) {
231
- if (importCounts.named / totalImports > 0.5) {
232
- conventions.commonPatterns.imports.preferred = "named imports";
233
- } else if (importCounts.default / totalImports > 0.5) {
234
- conventions.commonPatterns.imports.preferred = "default imports";
235
- }
236
- }
237
-
238
- // Formatting preferences
239
- for (const author of conventions.authors) {
240
- if (author.patterns.formatting.semiconPercentage > 70) {
241
- conventions.commonPatterns.formatting.semicons.with++;
242
- } else {
243
- conventions.commonPatterns.formatting.semicons.without++;
244
- }
245
-
246
- if (author.patterns.formatting.singleQuotePercentage > 70) {
247
- conventions.commonPatterns.formatting.quotes.single++;
248
- } else {
249
- conventions.commonPatterns.formatting.quotes.double++;
250
- }
251
- }
252
-
253
- // Generate recommendations
254
- if (conventions.commonPatterns.formatting.semicons.with > conventions.commonPatterns.formatting.semicons.without) {
255
- conventions.recommendations.push("Use semicolons consistently (team preference)");
256
- }
257
-
258
- if (conventions.commonPatterns.formatting.quotes.single > conventions.commonPatterns.formatting.quotes.double) {
259
- conventions.recommendations.push("Use single quotes for strings (team preference)");
260
- }
261
- }
262
-
263
- return conventions;
264
- }
265
-
266
- /**
267
- * Generate team conventions report
268
- */
269
- function generateTeamReport(projectPath) {
270
- const conventions = getTeamConventions(projectPath);
271
- if (!conventions) {
272
- return {
273
- available: false,
274
- message: "No git history found",
275
- };
276
- }
277
-
278
- const report = {
279
- available: true,
280
- summary: {
281
- teamSize: conventions.authors.length,
282
- totalFilesAnalyzed: conventions.authors.reduce((sum, a) => sum + a.filesContributed, 0),
283
- },
284
- conventions: conventions.commonPatterns,
285
- contributors: conventions.authors.map(a => ({
286
- name: a.name,
287
- filesContributed: a.filesContributed,
288
- style: {
289
- imports: a.patterns.imports,
290
- formatting: {
291
- usesSemicolons: a.patterns.formatting.semiconPercentage > 70,
292
- prefersSingleQuotes: a.patterns.formatting.singleQuotePercentage > 70,
293
- },
294
- typescript: {
295
- usesExplicitTypes: a.patterns.typescript.explicitTypes > 0,
296
- prefersInterfaces: a.patterns.typescript.interfaces > a.patterns.typescript.types,
297
- },
298
- },
299
- })),
300
- recommendations: conventions.recommendations,
301
- };
302
-
303
- return report;
304
- }
305
-
306
- module.exports = {
307
- analyzeAuthorStyle,
308
- getTeamConventions,
309
- generateTeamReport,
310
- };