cerber-core 1.0.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 (67) hide show
  1. package/.cerber-example/BIBLE.md +132 -0
  2. package/.cerber-example/CERBER_LAW.md +200 -0
  3. package/.cerber-example/connections/contracts/booking-to-pricing.json +44 -0
  4. package/.cerber-example/connections/contracts/pricing-to-booking.json +37 -0
  5. package/.cerber-example/modules/booking-calendar/MODULE.md +225 -0
  6. package/.cerber-example/modules/booking-calendar/contract.json +106 -0
  7. package/.cerber-example/modules/booking-calendar/dependencies.json +8 -0
  8. package/.cerber-example/modules/pricing-engine/MODULE.md +160 -0
  9. package/.cerber-example/modules/pricing-engine/contract.json +64 -0
  10. package/.cerber-example/modules/pricing-engine/dependencies.json +8 -0
  11. package/CHANGELOG.md +68 -0
  12. package/LICENSE +21 -0
  13. package/README.md +1379 -0
  14. package/bin/cerber +105 -0
  15. package/bin/cerber-focus +31 -0
  16. package/bin/cerber-guardian +90 -0
  17. package/bin/cerber-health +113 -0
  18. package/bin/cerber-morning +19 -0
  19. package/bin/cerber-repair +21 -0
  20. package/dist/cerber/index.d.ts +47 -0
  21. package/dist/cerber/index.d.ts.map +1 -0
  22. package/dist/cerber/index.js +154 -0
  23. package/dist/cerber/index.js.map +1 -0
  24. package/dist/guardian/index.d.ts +70 -0
  25. package/dist/guardian/index.d.ts.map +1 -0
  26. package/dist/guardian/index.js +271 -0
  27. package/dist/guardian/index.js.map +1 -0
  28. package/dist/index.d.ts +9 -0
  29. package/dist/index.d.ts.map +1 -0
  30. package/dist/index.js +9 -0
  31. package/dist/index.js.map +1 -0
  32. package/dist/types.d.ts +76 -0
  33. package/dist/types.d.ts.map +1 -0
  34. package/dist/types.js +5 -0
  35. package/dist/types.js.map +1 -0
  36. package/examples/backend-schema.ts +72 -0
  37. package/examples/frontend-schema.ts +67 -0
  38. package/examples/health-checks.ts +196 -0
  39. package/examples/solo-integration/README.md +457 -0
  40. package/examples/solo-integration/package.json +47 -0
  41. package/examples/team-integration/README.md +347 -0
  42. package/examples/team-integration/package.json +23 -0
  43. package/package.json +104 -0
  44. package/solo/README.md +258 -0
  45. package/solo/config/performance-budget.json +53 -0
  46. package/solo/config/solo-contract.json +71 -0
  47. package/solo/lib/feature-flags.ts +177 -0
  48. package/solo/scripts/cerber-auto-repair.js +260 -0
  49. package/solo/scripts/cerber-daily-check.js +282 -0
  50. package/solo/scripts/cerber-dashboard.js +191 -0
  51. package/solo/scripts/cerber-deps-health.js +247 -0
  52. package/solo/scripts/cerber-docs-sync.js +304 -0
  53. package/solo/scripts/cerber-flags-check.js +229 -0
  54. package/solo/scripts/cerber-performance-budget.js +271 -0
  55. package/solo/scripts/cerber-rollback.js +229 -0
  56. package/solo/scripts/cerber-snapshot.js +319 -0
  57. package/team/README.md +327 -0
  58. package/team/config/team-contract.json +27 -0
  59. package/team/lib/module-system.ts +157 -0
  60. package/team/scripts/cerber-add-module.sh +195 -0
  61. package/team/scripts/cerber-connections-check.sh +186 -0
  62. package/team/scripts/cerber-focus.sh +170 -0
  63. package/team/scripts/cerber-module-check.sh +165 -0
  64. package/team/scripts/cerber-team-morning.sh +210 -0
  65. package/team/templates/BIBLE_TEMPLATE.md +52 -0
  66. package/team/templates/CONNECTION_TEMPLATE.json +20 -0
  67. package/team/templates/MODULE_TEMPLATE.md +60 -0
@@ -0,0 +1,260 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * Cerber SOLO - Auto-Repair System
5
+ *
6
+ * Extends Cerber Core with automation for solo developers
7
+ *
8
+ * Automatically fixes common issues:
9
+ * - Format package.json (sort scripts and deps)
10
+ * - Sync .env.example (add missing environment variable keys)
11
+ * - Auto-generate CHANGELOG (from git log)
12
+ * - Remove console.logs (with approval system)
13
+ *
14
+ * @author Stefan Pitek
15
+ * @copyright 2026 Stefan Pitek
16
+ * @license MIT
17
+ */
18
+
19
+ const fs = require('fs');
20
+ const path = require('path');
21
+ const { execSync } = require('child_process');
22
+
23
+ // Parse command line arguments
24
+ const args = process.argv.slice(2);
25
+ const isDryRun = args.includes('--dry-run');
26
+ const requiresApproval = args.includes('--approve');
27
+
28
+ console.log('šŸ”§ Cerber SOLO - Auto-Repair System\n');
29
+ console.log(`Mode: ${isDryRun ? 'DRY RUN' : 'LIVE'}\n`);
30
+
31
+ let changesCount = 0;
32
+
33
+ /**
34
+ * Format and sort package.json
35
+ */
36
+ function formatPackageJson() {
37
+ console.log('šŸ“¦ Checking package.json...');
38
+
39
+ const packagePath = path.join(process.cwd(), 'package.json');
40
+
41
+ if (!fs.existsSync(packagePath)) {
42
+ console.log(' āš ļø No package.json found, skipping');
43
+ return;
44
+ }
45
+
46
+ try {
47
+ const packageData = JSON.parse(fs.readFileSync(packagePath, 'utf8'));
48
+
49
+ // Sort scripts alphabetically
50
+ if (packageData.scripts) {
51
+ const sortedScripts = Object.keys(packageData.scripts)
52
+ .sort()
53
+ .reduce((acc, key) => {
54
+ acc[key] = packageData.scripts[key];
55
+ return acc;
56
+ }, {});
57
+ packageData.scripts = sortedScripts;
58
+ }
59
+
60
+ // Sort dependencies
61
+ ['dependencies', 'devDependencies', 'peerDependencies'].forEach(depType => {
62
+ if (packageData[depType]) {
63
+ const sorted = Object.keys(packageData[depType])
64
+ .sort()
65
+ .reduce((acc, key) => {
66
+ acc[key] = packageData[depType][key];
67
+ return acc;
68
+ }, {});
69
+ packageData[depType] = sorted;
70
+ }
71
+ });
72
+
73
+ const formatted = JSON.stringify(packageData, null, 2) + '\n';
74
+
75
+ if (!isDryRun) {
76
+ fs.writeFileSync(packagePath, formatted, 'utf8');
77
+ }
78
+
79
+ console.log(' āœ… Package.json formatted and sorted');
80
+ changesCount++;
81
+ } catch (error) {
82
+ console.log(` āŒ Error formatting package.json: ${error.message}`);
83
+ }
84
+ }
85
+
86
+ /**
87
+ * Sync .env.example with environment variables used in code
88
+ */
89
+ function syncEnvExample() {
90
+ console.log('\nšŸ” Checking .env.example...');
91
+
92
+ const envExamplePath = path.join(process.cwd(), '.env.example');
93
+ const envPath = path.join(process.cwd(), '.env');
94
+
95
+ try {
96
+ // Find all VITE_* and REACT_APP_* variables in source code
97
+ let envVars = new Set();
98
+
99
+ try {
100
+ const grepCommand = 'grep -r "VITE_\\|REACT_APP_\\|NEXT_PUBLIC_" --include="*.ts" --include="*.tsx" --include="*.js" --include="*.jsx" . 2>/dev/null || true';
101
+ const grepOutput = execSync(grepCommand, { encoding: 'utf8', maxBuffer: 10 * 1024 * 1024 });
102
+
103
+ const envRegex = /(VITE_[A-Z_]+|REACT_APP_[A-Z_]+|NEXT_PUBLIC_[A-Z_]+)/g;
104
+ const matches = grepOutput.match(envRegex);
105
+
106
+ if (matches) {
107
+ matches.forEach(v => envVars.add(v));
108
+ }
109
+ } catch (error) {
110
+ // grep may fail if no files found, that's okay
111
+ }
112
+
113
+ if (envVars.size === 0) {
114
+ console.log(' ā„¹ļø No environment variables found in code');
115
+ return;
116
+ }
117
+
118
+ // Read existing .env.example
119
+ let existingVars = new Set();
120
+ if (fs.existsSync(envExamplePath)) {
121
+ const content = fs.readFileSync(envExamplePath, 'utf8');
122
+ content.split('\n').forEach(line => {
123
+ const match = line.match(/^([A-Z_]+)=/);
124
+ if (match) {
125
+ existingVars.add(match[1]);
126
+ }
127
+ });
128
+ }
129
+
130
+ // Find missing variables
131
+ const missingVars = Array.from(envVars).filter(v => !existingVars.has(v));
132
+
133
+ if (missingVars.length === 0) {
134
+ console.log(' āœ… .env.example is up to date');
135
+ return;
136
+ }
137
+
138
+ console.log(` šŸ“ Found ${missingVars.length} missing variables: ${missingVars.join(', ')}`);
139
+
140
+ if (!isDryRun) {
141
+ let content = fs.existsSync(envExamplePath) ?
142
+ fs.readFileSync(envExamplePath, 'utf8') : '';
143
+
144
+ if (content && !content.endsWith('\n')) {
145
+ content += '\n';
146
+ }
147
+
148
+ content += '\n# Auto-added by Cerber SOLO\n';
149
+ missingVars.forEach(varName => {
150
+ content += `${varName}=\n`;
151
+ });
152
+
153
+ fs.writeFileSync(envExamplePath, content, 'utf8');
154
+ console.log(' āœ… Updated .env.example');
155
+ }
156
+
157
+ changesCount++;
158
+ } catch (error) {
159
+ console.log(` āŒ Error syncing .env.example: ${error.message}`);
160
+ }
161
+ }
162
+
163
+ /**
164
+ * Auto-generate CHANGELOG from git log
165
+ */
166
+ function generateChangelog() {
167
+ console.log('\nšŸ“ Checking CHANGELOG...');
168
+
169
+ const changelogPath = path.join(process.cwd(), 'CHANGELOG.md');
170
+
171
+ try {
172
+ // Check if git repo exists
173
+ if (!fs.existsSync(path.join(process.cwd(), '.git'))) {
174
+ console.log(' āš ļø Not a git repository, skipping');
175
+ return;
176
+ }
177
+
178
+ // Get recent commits
179
+ const gitLog = execSync('git log --pretty=format:"%h - %s (%an, %ar)" -20', {
180
+ encoding: 'utf8',
181
+ maxBuffer: 10 * 1024 * 1024
182
+ });
183
+
184
+ if (!gitLog) {
185
+ console.log(' ā„¹ļø No commits found');
186
+ return;
187
+ }
188
+
189
+ const date = new Date().toISOString().split('T')[0];
190
+ const changelog = `# Changelog\n\n## [Unreleased] - ${date}\n\n### Recent Changes\n\n${gitLog.split('\n').map(line => `- ${line}`).join('\n')}\n\n---\n*Generated by Cerber SOLO*\n`;
191
+
192
+ if (!isDryRun) {
193
+ fs.writeFileSync(changelogPath, changelog, 'utf8');
194
+ }
195
+
196
+ console.log(' āœ… CHANGELOG generated from git log');
197
+ changesCount++;
198
+ } catch (error) {
199
+ console.log(` āš ļø Error generating CHANGELOG: ${error.message}`);
200
+ }
201
+ }
202
+
203
+ /**
204
+ * Remove console.logs with approval
205
+ */
206
+ function removeConsoleLogs() {
207
+ console.log('\n🧹 Checking for console.log statements...');
208
+
209
+ if (!requiresApproval) {
210
+ console.log(' ā„¹ļø Use --approve flag to enable console.log removal');
211
+ return;
212
+ }
213
+
214
+ try {
215
+ const grepCommand = 'grep -rn "console\\.log" --include="*.ts" --include="*.tsx" --include="*.js" --include="*.jsx" . 2>/dev/null || true';
216
+ const consoleLogFiles = execSync(grepCommand, {
217
+ encoding: 'utf8',
218
+ maxBuffer: 10 * 1024 * 1024
219
+ });
220
+
221
+ if (!consoleLogFiles) {
222
+ console.log(' āœ… No console.log statements found');
223
+ return;
224
+ }
225
+
226
+ const lines = consoleLogFiles.split('\n').filter(line => line.trim());
227
+ console.log(` šŸ“Š Found ${lines.length} console.log statements`);
228
+
229
+ if (lines.length > 0) {
230
+ console.log(' āš ļø Manual review recommended - showing first 5:');
231
+ lines.slice(0, 5).forEach(line => {
232
+ console.log(` ${line}`);
233
+ });
234
+ }
235
+
236
+ changesCount++;
237
+ } catch (error) {
238
+ // grep may fail if no files found
239
+ }
240
+ }
241
+
242
+ // Run all repairs
243
+ formatPackageJson();
244
+ syncEnvExample();
245
+ generateChangelog();
246
+ removeConsoleLogs();
247
+
248
+ // Summary
249
+ console.log('\n' + '='.repeat(50));
250
+ console.log(`\n✨ Auto-repair complete!`);
251
+ console.log(` Changes detected: ${changesCount}`);
252
+ console.log(` Mode: ${isDryRun ? 'DRY RUN (no files modified)' : 'LIVE (files updated)'}`);
253
+
254
+ if (isDryRun && changesCount > 0) {
255
+ console.log('\nšŸ’” Run without --dry-run to apply changes');
256
+ }
257
+
258
+ console.log('\n' + '='.repeat(50));
259
+
260
+ process.exit(0);
@@ -0,0 +1,282 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * Cerber SOLO - Daily Check (Morning Dashboard)
5
+ *
6
+ * Extends Cerber Core with automation for solo developers
7
+ *
8
+ * Checks:
9
+ * - Backend health (via /api/health)
10
+ * - Guardian validation status
11
+ * - Git status
12
+ * - Yesterday's snapshot
13
+ * - Today's priorities
14
+ *
15
+ * @author Stefan Pitek
16
+ * @copyright 2026 Stefan Pitek
17
+ * @license MIT
18
+ */
19
+
20
+ const { execSync } = require('child_process');
21
+ const fs = require('fs');
22
+ const path = require('path');
23
+
24
+ console.log('ā˜€ļø Cerber SOLO - Morning Dashboard\n');
25
+ console.log('='.repeat(60));
26
+
27
+ const date = new Date().toLocaleDateString('en-US', {
28
+ weekday: 'long',
29
+ year: 'numeric',
30
+ month: 'long',
31
+ day: 'numeric'
32
+ });
33
+
34
+ console.log(`\nšŸ“… ${date}\n`);
35
+
36
+ /**
37
+ * Check backend health
38
+ */
39
+ function checkBackendHealth() {
40
+ console.log('šŸ„ Backend Health Check\n');
41
+
42
+ const healthUrls = [
43
+ 'http://localhost:3000/api/health',
44
+ 'http://localhost:4000/api/health',
45
+ 'http://localhost:5000/api/health'
46
+ ];
47
+
48
+ let healthChecked = false;
49
+
50
+ for (const url of healthUrls) {
51
+ try {
52
+ // Try with curl (available on most systems)
53
+ const response = execSync(`curl -s -m 2 ${url} 2>/dev/null || true`, {
54
+ encoding: 'utf8',
55
+ timeout: 3000
56
+ });
57
+
58
+ if (response && response.includes('status')) {
59
+ const data = JSON.parse(response);
60
+ const status = data.status || 'unknown';
61
+ const emoji = status === 'healthy' ? 'āœ…' : status === 'degraded' ? 'āš ļø' : 'šŸ”“';
62
+
63
+ console.log(` ${emoji} ${url}: ${status}`);
64
+
65
+ if (data.summary) {
66
+ const s = data.summary;
67
+ if (s.criticalIssues > 0) console.log(` šŸ”“ Critical: ${s.criticalIssues}`);
68
+ if (s.errorIssues > 0) console.log(` 🟠 Errors: ${s.errorIssues}`);
69
+ if (s.warningIssues > 0) console.log(` 🟔 Warnings: ${s.warningIssues}`);
70
+ }
71
+
72
+ healthChecked = true;
73
+ break;
74
+ }
75
+ } catch (error) {
76
+ // Continue to next URL
77
+ }
78
+ }
79
+
80
+ if (!healthChecked) {
81
+ console.log(' ā„¹ļø Backend not running or health endpoint not accessible');
82
+ console.log(' šŸ’” Start your server to enable health checks');
83
+ }
84
+
85
+ console.log();
86
+ }
87
+
88
+ /**
89
+ * Check Guardian validation status
90
+ */
91
+ function checkGuardianStatus() {
92
+ console.log('šŸ›”ļø Guardian Status\n');
93
+
94
+ try {
95
+ // Check if Guardian validation script exists
96
+ const guardianPaths = [
97
+ 'scripts/validate-schema.mjs',
98
+ 'scripts/validate-schema.js',
99
+ '.husky/pre-commit'
100
+ ];
101
+
102
+ const guardianExists = guardianPaths.some(p =>
103
+ fs.existsSync(path.join(process.cwd(), p))
104
+ );
105
+
106
+ if (guardianExists) {
107
+ console.log(' āœ… Guardian is installed');
108
+
109
+ // Check recent commits
110
+ try {
111
+ const recentCommits = execSync('git log --oneline -5', { encoding: 'utf8' });
112
+ console.log(' šŸ“ Recent commits passed validation:\n');
113
+ recentCommits.split('\n').slice(0, 3).forEach(commit => {
114
+ if (commit.trim()) {
115
+ console.log(` ${commit}`);
116
+ }
117
+ });
118
+ } catch (error) {
119
+ // Not a git repo
120
+ }
121
+ } else {
122
+ console.log(' āš ļø Guardian not detected');
123
+ console.log(' šŸ’” Consider setting up Guardian for pre-commit validation');
124
+ }
125
+ } catch (error) {
126
+ console.log(` āš ļø Error checking Guardian: ${error.message}`);
127
+ }
128
+
129
+ console.log();
130
+ }
131
+
132
+ /**
133
+ * Check Git status
134
+ */
135
+ function checkGitStatus() {
136
+ console.log('šŸ“‚ Git Status\n');
137
+
138
+ try {
139
+ const status = execSync('git status --short', { encoding: 'utf8' });
140
+
141
+ if (status.trim()) {
142
+ const lines = status.split('\n').filter(l => l.trim());
143
+ console.log(` šŸ“Š ${lines.length} file(s) with changes:\n`);
144
+
145
+ lines.slice(0, 10).forEach(line => {
146
+ const statusCode = line.substring(0, 2).trim();
147
+ const file = line.substring(3);
148
+ const emoji = statusCode.includes('M') ? 'šŸ“' :
149
+ statusCode.includes('A') ? '✨' :
150
+ statusCode.includes('D') ? 'šŸ—‘ļø' :
151
+ statusCode.includes('?') ? 'ā“' : 'šŸ“„';
152
+ console.log(` ${emoji} ${file}`);
153
+ });
154
+
155
+ if (lines.length > 10) {
156
+ console.log(` ... and ${lines.length - 10} more`);
157
+ }
158
+
159
+ // Check branch
160
+ const branch = execSync('git rev-parse --abbrev-ref HEAD', { encoding: 'utf8' }).trim();
161
+ console.log(`\n 🌿 Branch: ${branch}`);
162
+
163
+ // Check unpushed commits
164
+ try {
165
+ const unpushed = execSync('git log @{u}.. --oneline 2>/dev/null || true', { encoding: 'utf8' });
166
+ if (unpushed.trim()) {
167
+ const count = unpushed.split('\n').filter(l => l.trim()).length;
168
+ console.log(` ā¬†ļø ${count} unpushed commit(s)`);
169
+ }
170
+ } catch (error) {
171
+ // No upstream branch
172
+ }
173
+ } else {
174
+ console.log(' āœ… Working directory clean');
175
+
176
+ const branch = execSync('git rev-parse --abbrev-ref HEAD', { encoding: 'utf8' }).trim();
177
+ console.log(` 🌿 Branch: ${branch}`);
178
+ }
179
+ } catch (error) {
180
+ console.log(' ā„¹ļø Not a git repository');
181
+ }
182
+
183
+ console.log();
184
+ }
185
+
186
+ /**
187
+ * Check yesterday's snapshot
188
+ */
189
+ function checkSnapshot() {
190
+ console.log('šŸ“ø Yesterday\'s Snapshot\n');
191
+
192
+ const snapshotDir = path.join(process.cwd(), '.cerber', 'snapshots');
193
+
194
+ if (!fs.existsSync(snapshotDir)) {
195
+ console.log(' ā„¹ļø No snapshots found');
196
+ console.log(' šŸ’” Run: npm run cerber:snapshot (to create daily snapshots)');
197
+ console.log();
198
+ return;
199
+ }
200
+
201
+ try {
202
+ const files = fs.readdirSync(snapshotDir).sort().reverse();
203
+
204
+ if (files.length === 0) {
205
+ console.log(' ā„¹ļø No snapshots found');
206
+ console.log();
207
+ return;
208
+ }
209
+
210
+ // Get most recent snapshot
211
+ const latest = files[0];
212
+ const snapshotPath = path.join(snapshotDir, latest);
213
+ const snapshot = JSON.parse(fs.readFileSync(snapshotPath, 'utf8'));
214
+
215
+ console.log(` šŸ“… Latest snapshot: ${latest.replace('.json', '')}`);
216
+ console.log(` šŸ“Š Commits: ${snapshot.commits || 0}`);
217
+ console.log(` šŸ“ Files changed: ${snapshot.filesChanged || 0}`);
218
+ console.log(` šŸ“ˆ Lines added: ${snapshot.linesAdded || 0}`);
219
+ console.log(` šŸ“‰ Lines removed: ${snapshot.linesRemoved || 0}`);
220
+ } catch (error) {
221
+ console.log(` āš ļø Error reading snapshot: ${error.message}`);
222
+ }
223
+
224
+ console.log();
225
+ }
226
+
227
+ /**
228
+ * Show today's priorities
229
+ */
230
+ function showPriorities() {
231
+ console.log('šŸŽÆ Today\'s Priorities\n');
232
+
233
+ // Check for TODO comments in recently modified files
234
+ try {
235
+ const recentFiles = execSync('git diff --name-only HEAD~1..HEAD 2>/dev/null || true', {
236
+ encoding: 'utf8'
237
+ }).trim();
238
+
239
+ if (recentFiles) {
240
+ console.log(' šŸ“ Recently modified files:');
241
+ recentFiles.split('\n').slice(0, 5).forEach(file => {
242
+ console.log(` - ${file}`);
243
+ });
244
+ }
245
+ } catch (error) {
246
+ // Continue
247
+ }
248
+
249
+ console.log('\n šŸ’” Suggested workflow:');
250
+ console.log(' 1. Review git status');
251
+ console.log(' 2. Run: npm run cerber:repair (auto-fix issues)');
252
+ console.log(' 3. Run: npm run cerber:deps (check dependencies)');
253
+ console.log(' 4. Code your features');
254
+ console.log(' 5. Run: npm run cerber:pre-push (before pushing)');
255
+ console.log(' 6. Run: npm run cerber:snapshot (end of day)\n');
256
+ }
257
+
258
+ /**
259
+ * Quick actions menu
260
+ */
261
+ function showQuickActions() {
262
+ console.log('⚔ Quick Actions\n');
263
+ console.log(' npm run cerber:repair # Auto-fix issues');
264
+ console.log(' npm run cerber:deps # Check dependencies');
265
+ console.log(' npm run cerber:docs # Sync documentation');
266
+ console.log(' npm run cerber:perf # Check performance');
267
+ console.log(' npm run cerber:flags # Check feature flags');
268
+ console.log();
269
+ }
270
+
271
+ // Run all checks
272
+ checkBackendHealth();
273
+ checkGuardianStatus();
274
+ checkGitStatus();
275
+ checkSnapshot();
276
+ showPriorities();
277
+ showQuickActions();
278
+
279
+ console.log('='.repeat(60));
280
+ console.log('\n✨ Have a productive day!\n');
281
+
282
+ process.exit(0);