@theihtisham/agent-shadow-brain 6.3.0 → 7.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 (43) hide show
  1. package/CHANGELOG.md +411 -391
  2. package/LICENSE +21 -21
  3. package/README.md +428 -438
  4. package/dist/adapters/aider.js +13 -13
  5. package/dist/adapters/base-adapter.js +14 -14
  6. package/dist/adapters/codex.js +8 -8
  7. package/dist/adapters/roo-code.js +18 -18
  8. package/dist/brain/adr-engine.js +11 -11
  9. package/dist/brain/analyzer.js +30 -30
  10. package/dist/brain/auto-update.js +1 -1
  11. package/dist/brain/global-brain.d.ts +52 -63
  12. package/dist/brain/global-brain.d.ts.map +1 -1
  13. package/dist/brain/global-brain.js +577 -339
  14. package/dist/brain/global-brain.js.map +1 -1
  15. package/dist/brain/health-score.js +19 -19
  16. package/dist/brain/learning-engine.js +59 -59
  17. package/dist/brain/mcp-server.d.ts +1 -0
  18. package/dist/brain/mcp-server.d.ts.map +1 -1
  19. package/dist/brain/mcp-server.js +16 -6
  20. package/dist/brain/mcp-server.js.map +1 -1
  21. package/dist/brain/plugin-system.js +23 -23
  22. package/dist/brain/pr-generator.js +19 -19
  23. package/dist/brain/project-context.js +1 -1
  24. package/dist/brain/project-context.js.map +1 -1
  25. package/dist/brain/report-generator.js +270 -270
  26. package/dist/cli.js +105 -34
  27. package/dist/cli.js.map +1 -1
  28. package/dist/dashboard/v6-dashboard-html.d.ts +1 -1
  29. package/dist/dashboard/v6-dashboard-html.d.ts.map +1 -1
  30. package/dist/dashboard/v6-dashboard-html.js +5 -5
  31. package/dist/index.d.ts +2 -0
  32. package/dist/index.d.ts.map +1 -1
  33. package/dist/index.js +2 -0
  34. package/dist/index.js.map +1 -1
  35. package/dist/types.d.ts +28 -10
  36. package/dist/types.d.ts.map +1 -1
  37. package/dist/watchers/git-watcher.d.ts.map +1 -1
  38. package/dist/watchers/git-watcher.js +1 -1
  39. package/dist/watchers/git-watcher.js.map +1 -1
  40. package/docs/launch/RELEASE_CHECKLIST_v7.0.0.md +24 -0
  41. package/docs/launch/RELEASE_NOTES_v7.0.0.md +44 -0
  42. package/package.json +17 -14
  43. package/docs/launch/README.md +0 -61
@@ -26,130 +26,130 @@ export class ReportGenerator {
26
26
  const highCount = insights.filter(i => i.priority === 'high').length;
27
27
  const mediumCount = insights.filter(i => i.priority === 'medium').length;
28
28
  const gradeColor = health ? (health.overall >= 85 ? '#22c55e' : health.overall >= 70 ? '#eab308' : health.overall >= 50 ? '#f97316' : '#ef4444') : '#6b7280';
29
- return `<!DOCTYPE html>
30
- <html lang="en">
31
- <head>
32
- <meta charset="UTF-8">
33
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
34
- <title>Shadow Brain Report — ${context.name}</title>
35
- <style>
36
- * { margin:0; padding:0; box-sizing:border-box; }
37
- body { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; background:#0f0f1a; color:#e2e8f0; min-height:100vh; }
38
- .header { background:linear-gradient(135deg, #1e1b4b 0%, #312e81 50%, #1e1b4b 100%); padding:32px 48px; border-bottom:1px solid #312e81; }
39
- .header h1 { font-size:28px; font-weight:700; color:#a5b4fc; display:flex; align-items:center; gap:12px; }
40
- .header .meta { color:#6b7280; font-size:14px; margin-top:8px; }
41
- .container { max-width:1100px; margin:0 auto; padding:32px 48px; }
42
- .score-card { background:linear-gradient(135deg, #1a1a2e 0%, #16213e 100%); border:1px solid #312e81; border-radius:16px; padding:28px; margin-bottom:32px; display:grid; grid-template-columns:200px 1fr; gap:28px; }
43
- .score-circle { width:140px; height:140px; border-radius:50%; border:6px solid ${gradeColor}; display:flex; flex-direction:column; align-items:center; justify-content:center; box-shadow:0 0 30px ${gradeColor}33; }
44
- .score-number { font-size:42px; font-weight:800; color:${gradeColor}; line-height:1; }
45
- .score-label { font-size:13px; color:#6b7280; margin-top:4px; }
46
- .score-grade { font-size:22px; font-weight:700; color:${gradeColor}; margin-top:4px; }
47
- .score-dims { display:grid; gap:12px; }
48
- .dim-row { display:grid; grid-template-columns:120px 1fr 50px; align-items:center; gap:12px; }
49
- .dim-name { font-size:13px; color:#94a3b8; }
50
- .dim-bar { height:8px; background:#1e293b; border-radius:4px; overflow:hidden; }
51
- .dim-fill { height:100%; border-radius:4px; transition:width .3s ease; }
52
- .dim-val { font-size:13px; color:#94a3b8; text-align:right; }
53
- .stats { display:grid; grid-template-columns:repeat(4, 1fr); gap:16px; margin-bottom:32px; }
54
- .stat { background:#1a1a2e; border:1px solid #312e81; border-radius:12px; padding:20px; text-align:center; }
55
- .stat-num { font-size:32px; font-weight:800; }
56
- .stat-label { font-size:12px; color:#6b7280; margin-top:4px; }
57
- .critical { color:#f87171; } .high { color:#fb923c; } .medium { color:#facc15; } .low { color:#4ade80; }
58
- .section-title { font-size:18px; font-weight:600; color:#a5b4fc; margin-bottom:16px; display:flex; align-items:center; gap:8px; }
59
- .insight-card { background:#1a1a2e; border:1px solid #1e293b; border-radius:12px; padding:20px; margin-bottom:12px; border-left:4px solid; }
60
- .insight-card.critical { border-left-color:#f87171; }
61
- .insight-card.high { border-left-color:#fb923c; }
62
- .insight-card.medium { border-left-color:#facc15; }
63
- .insight-card.low { border-left-color:#4ade80; }
64
- .insight-header { display:flex; align-items:center; gap:10px; margin-bottom:10px; }
65
- .badge { font-size:11px; font-weight:600; padding:3px 8px; border-radius:20px; text-transform:uppercase; }
66
- .badge-critical { background:#7f1d1d; color:#fca5a5; }
67
- .badge-high { background:#7c2d12; color:#fdba74; }
68
- .badge-medium { background:#713f12; color:#fde047; }
69
- .badge-low { background:#14532d; color:#86efac; }
70
- .insight-title { font-size:15px; font-weight:600; color:#e2e8f0; }
71
- .insight-content { color:#94a3b8; font-size:14px; line-height:1.6; }
72
- .insight-files { margin-top:8px; display:flex; flex-wrap:wrap; gap:6px; }
73
- .file-tag { background:#0f172a; border:1px solid #1e293b; border-radius:6px; padding:2px 8px; font-size:11px; font-family:monospace; color:#64748b; }
74
- .fix-card { background:#0d1b0d; border:1px solid #14532d; border-radius:12px; padding:20px; margin-bottom:12px; }
75
- .fix-label { font-size:11px; font-weight:600; color:#4ade80; text-transform:uppercase; margin-bottom:4px; }
76
- pre { background:#0f0f1a; border:1px solid #1e293b; border-radius:8px; padding:14px; font-size:13px; overflow-x:auto; white-space:pre-wrap; }
77
- pre.before { border-color:#7f1d1d; background:#1a0000; color:#fca5a5; }
78
- pre.after { border-color:#14532d; background:#001a00; color:#86efac; }
79
- .explanation { color:#64748b; font-size:13px; margin-top:10px; font-style:italic; }
80
- .trend { font-size:13px; color:#6b7280; }
81
- .trend.improving { color:#4ade80; }
82
- .trend.declining { color:#f87171; }
83
- footer { text-align:center; padding:32px; color:#374151; font-size:12px; border-top:1px solid #1e293b; margin-top:40px; }
84
- </style>
85
- </head>
86
- <body>
87
- <div class="header">
88
- <h1>🧠 Shadow Brain Report</h1>
89
- <div class="meta">Project: <strong>${context.name}</strong> &nbsp;Ā·&nbsp; ${new Date().toLocaleString()} &nbsp;Ā·&nbsp; Branch: ${context.gitBranch || 'N/A'}</div>
90
- </div>
91
- <div class="container">
92
-
93
- ${health ? `
94
- <div class="score-card">
95
- <div class="score-circle">
96
- <div class="score-number">${health.overall}</div>
97
- <div class="score-label">out of 100</div>
98
- <div class="score-grade">${health.grade}</div>
99
- </div>
100
- <div>
101
- <div style="font-size:16px; font-weight:600; color:#e2e8f0; margin-bottom:4px;">Code Health Score</div>
102
- <div class="trend ${health.trend}">Trend: ${health.trend === 'improving' ? '↑ Improving' : health.trend === 'declining' ? '↓ Declining' : '→ Stable'}</div>
103
- <div class="score-dims" style="margin-top:16px;">
29
+ return `<!DOCTYPE html>
30
+ <html lang="en">
31
+ <head>
32
+ <meta charset="UTF-8">
33
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
34
+ <title>Shadow Brain Report — ${context.name}</title>
35
+ <style>
36
+ * { margin:0; padding:0; box-sizing:border-box; }
37
+ body { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; background:#0f0f1a; color:#e2e8f0; min-height:100vh; }
38
+ .header { background:linear-gradient(135deg, #1e1b4b 0%, #312e81 50%, #1e1b4b 100%); padding:32px 48px; border-bottom:1px solid #312e81; }
39
+ .header h1 { font-size:28px; font-weight:700; color:#a5b4fc; display:flex; align-items:center; gap:12px; }
40
+ .header .meta { color:#6b7280; font-size:14px; margin-top:8px; }
41
+ .container { max-width:1100px; margin:0 auto; padding:32px 48px; }
42
+ .score-card { background:linear-gradient(135deg, #1a1a2e 0%, #16213e 100%); border:1px solid #312e81; border-radius:16px; padding:28px; margin-bottom:32px; display:grid; grid-template-columns:200px 1fr; gap:28px; }
43
+ .score-circle { width:140px; height:140px; border-radius:50%; border:6px solid ${gradeColor}; display:flex; flex-direction:column; align-items:center; justify-content:center; box-shadow:0 0 30px ${gradeColor}33; }
44
+ .score-number { font-size:42px; font-weight:800; color:${gradeColor}; line-height:1; }
45
+ .score-label { font-size:13px; color:#6b7280; margin-top:4px; }
46
+ .score-grade { font-size:22px; font-weight:700; color:${gradeColor}; margin-top:4px; }
47
+ .score-dims { display:grid; gap:12px; }
48
+ .dim-row { display:grid; grid-template-columns:120px 1fr 50px; align-items:center; gap:12px; }
49
+ .dim-name { font-size:13px; color:#94a3b8; }
50
+ .dim-bar { height:8px; background:#1e293b; border-radius:4px; overflow:hidden; }
51
+ .dim-fill { height:100%; border-radius:4px; transition:width .3s ease; }
52
+ .dim-val { font-size:13px; color:#94a3b8; text-align:right; }
53
+ .stats { display:grid; grid-template-columns:repeat(4, 1fr); gap:16px; margin-bottom:32px; }
54
+ .stat { background:#1a1a2e; border:1px solid #312e81; border-radius:12px; padding:20px; text-align:center; }
55
+ .stat-num { font-size:32px; font-weight:800; }
56
+ .stat-label { font-size:12px; color:#6b7280; margin-top:4px; }
57
+ .critical { color:#f87171; } .high { color:#fb923c; } .medium { color:#facc15; } .low { color:#4ade80; }
58
+ .section-title { font-size:18px; font-weight:600; color:#a5b4fc; margin-bottom:16px; display:flex; align-items:center; gap:8px; }
59
+ .insight-card { background:#1a1a2e; border:1px solid #1e293b; border-radius:12px; padding:20px; margin-bottom:12px; border-left:4px solid; }
60
+ .insight-card.critical { border-left-color:#f87171; }
61
+ .insight-card.high { border-left-color:#fb923c; }
62
+ .insight-card.medium { border-left-color:#facc15; }
63
+ .insight-card.low { border-left-color:#4ade80; }
64
+ .insight-header { display:flex; align-items:center; gap:10px; margin-bottom:10px; }
65
+ .badge { font-size:11px; font-weight:600; padding:3px 8px; border-radius:20px; text-transform:uppercase; }
66
+ .badge-critical { background:#7f1d1d; color:#fca5a5; }
67
+ .badge-high { background:#7c2d12; color:#fdba74; }
68
+ .badge-medium { background:#713f12; color:#fde047; }
69
+ .badge-low { background:#14532d; color:#86efac; }
70
+ .insight-title { font-size:15px; font-weight:600; color:#e2e8f0; }
71
+ .insight-content { color:#94a3b8; font-size:14px; line-height:1.6; }
72
+ .insight-files { margin-top:8px; display:flex; flex-wrap:wrap; gap:6px; }
73
+ .file-tag { background:#0f172a; border:1px solid #1e293b; border-radius:6px; padding:2px 8px; font-size:11px; font-family:monospace; color:#64748b; }
74
+ .fix-card { background:#0d1b0d; border:1px solid #14532d; border-radius:12px; padding:20px; margin-bottom:12px; }
75
+ .fix-label { font-size:11px; font-weight:600; color:#4ade80; text-transform:uppercase; margin-bottom:4px; }
76
+ pre { background:#0f0f1a; border:1px solid #1e293b; border-radius:8px; padding:14px; font-size:13px; overflow-x:auto; white-space:pre-wrap; }
77
+ pre.before { border-color:#7f1d1d; background:#1a0000; color:#fca5a5; }
78
+ pre.after { border-color:#14532d; background:#001a00; color:#86efac; }
79
+ .explanation { color:#64748b; font-size:13px; margin-top:10px; font-style:italic; }
80
+ .trend { font-size:13px; color:#6b7280; }
81
+ .trend.improving { color:#4ade80; }
82
+ .trend.declining { color:#f87171; }
83
+ footer { text-align:center; padding:32px; color:#374151; font-size:12px; border-top:1px solid #1e293b; margin-top:40px; }
84
+ </style>
85
+ </head>
86
+ <body>
87
+ <div class="header">
88
+ <h1>🧠 Shadow Brain Report</h1>
89
+ <div class="meta">Project: <strong>${context.name}</strong> &nbsp;Ā·&nbsp; ${new Date().toLocaleString()} &nbsp;Ā·&nbsp; Branch: ${context.gitBranch || 'N/A'}</div>
90
+ </div>
91
+ <div class="container">
92
+
93
+ ${health ? `
94
+ <div class="score-card">
95
+ <div class="score-circle">
96
+ <div class="score-number">${health.overall}</div>
97
+ <div class="score-label">out of 100</div>
98
+ <div class="score-grade">${health.grade}</div>
99
+ </div>
100
+ <div>
101
+ <div style="font-size:16px; font-weight:600; color:#e2e8f0; margin-bottom:4px;">Code Health Score</div>
102
+ <div class="trend ${health.trend}">Trend: ${health.trend === 'improving' ? '↑ Improving' : health.trend === 'declining' ? '↓ Declining' : '→ Stable'}</div>
103
+ <div class="score-dims" style="margin-top:16px;">
104
104
  ${health.dimensions.map(d => {
105
105
  const fillColor = d.score >= 90 ? '#22c55e' : d.score >= 75 ? '#3b82f6' : d.score >= 55 ? '#eab308' : '#ef4444';
106
- return `<div class="dim-row">
107
- <div class="dim-name">${d.name}</div>
108
- <div class="dim-bar"><div class="dim-fill" style="width:${d.score}%; background:${fillColor};"></div></div>
109
- <div class="dim-val">${d.score}%</div>
106
+ return `<div class="dim-row">
107
+ <div class="dim-name">${d.name}</div>
108
+ <div class="dim-bar"><div class="dim-fill" style="width:${d.score}%; background:${fillColor};"></div></div>
109
+ <div class="dim-val">${d.score}%</div>
110
110
  </div>`;
111
- }).join('')}
112
- </div>
113
- </div>
114
- </div>` : ''}
115
-
116
- <div class="stats">
117
- <div class="stat"><div class="stat-num critical">${criticalCount}</div><div class="stat-label">Critical</div></div>
118
- <div class="stat"><div class="stat-num high">${highCount}</div><div class="stat-label">High Priority</div></div>
119
- <div class="stat"><div class="stat-num medium">${mediumCount}</div><div class="stat-label">Medium</div></div>
120
- <div class="stat"><div class="stat-num" style="color:#a5b4fc;">${insights.length}</div><div class="stat-label">Total Insights</div></div>
121
- </div>
122
-
123
- <div class="section-title">šŸ” Insights</div>
111
+ }).join('')}
112
+ </div>
113
+ </div>
114
+ </div>` : ''}
115
+
116
+ <div class="stats">
117
+ <div class="stat"><div class="stat-num critical">${criticalCount}</div><div class="stat-label">Critical</div></div>
118
+ <div class="stat"><div class="stat-num high">${highCount}</div><div class="stat-label">High Priority</div></div>
119
+ <div class="stat"><div class="stat-num medium">${mediumCount}</div><div class="stat-label">Medium</div></div>
120
+ <div class="stat"><div class="stat-num" style="color:#a5b4fc;">${insights.length}</div><div class="stat-label">Total Insights</div></div>
121
+ </div>
122
+
123
+ <div class="section-title">šŸ” Insights</div>
124
124
  ${insights.sort((a, b) => {
125
125
  const order = { critical: 0, high: 1, medium: 2, low: 3 };
126
126
  return order[a.priority] - order[b.priority];
127
- }).map(i => `
128
- <div class="insight-card ${i.priority}">
129
- <div class="insight-header">
130
- <span class="badge badge-${i.priority}">${i.priority}</span>
131
- <span class="badge" style="background:#1e293b;color:#64748b;">${i.type}</span>
132
- <span class="insight-title">${i.title}</span>
133
- </div>
134
- <div class="insight-content">${i.content.replace(/\n/g, '<br>')}</div>
135
- ${i.files && i.files.length > 0 ? `<div class="insight-files">${i.files.map(f => `<span class="file-tag">${f}</span>`).join('')}</div>` : ''}
136
- </div>`).join('')}
137
-
138
- ${fixes && fixes.length > 0 ? `
139
- <div class="section-title" style="margin-top:32px;">šŸ”§ Smart Fix Suggestions</div>
140
- ${fixes.map(f => `
141
- <div class="fix-card">
142
- <div style="font-size:15px; font-weight:600; color:#86efac; margin-bottom:12px;">${f.issue}</div>
143
- <div style="display:grid; grid-template-columns:1fr 1fr; gap:16px;">
144
- <div><div class="fix-label">Before</div><pre class="before">${f.before}</pre></div>
145
- <div><div class="fix-label">After</div><pre class="after">${f.after}</pre></div>
146
- </div>
147
- <div class="explanation">šŸ’” ${f.explanation}</div>
148
- </div>`).join('')}` : ''}
149
-
150
- </div>
151
- <footer>Generated by <strong>Agent Shadow Brain</strong> Ā· @theihtisham/agent-shadow-brain Ā· <a href="https://github.com/theihtisham/agent-shadow-brain" style="color:#4ade80;">GitHub</a></footer>
152
- </body>
127
+ }).map(i => `
128
+ <div class="insight-card ${i.priority}">
129
+ <div class="insight-header">
130
+ <span class="badge badge-${i.priority}">${i.priority}</span>
131
+ <span class="badge" style="background:#1e293b;color:#64748b;">${i.type}</span>
132
+ <span class="insight-title">${i.title}</span>
133
+ </div>
134
+ <div class="insight-content">${i.content.replace(/\n/g, '<br>')}</div>
135
+ ${i.files && i.files.length > 0 ? `<div class="insight-files">${i.files.map(f => `<span class="file-tag">${f}</span>`).join('')}</div>` : ''}
136
+ </div>`).join('')}
137
+
138
+ ${fixes && fixes.length > 0 ? `
139
+ <div class="section-title" style="margin-top:32px;">šŸ”§ Smart Fix Suggestions</div>
140
+ ${fixes.map(f => `
141
+ <div class="fix-card">
142
+ <div style="font-size:15px; font-weight:600; color:#86efac; margin-bottom:12px;">${f.issue}</div>
143
+ <div style="display:grid; grid-template-columns:1fr 1fr; gap:16px;">
144
+ <div><div class="fix-label">Before</div><pre class="before">${f.before}</pre></div>
145
+ <div><div class="fix-label">After</div><pre class="after">${f.after}</pre></div>
146
+ </div>
147
+ <div class="explanation">šŸ’” ${f.explanation}</div>
148
+ </div>`).join('')}` : ''}
149
+
150
+ </div>
151
+ <footer>Generated by <strong>Agent Shadow Brain</strong> Ā· @theihtisham/agent-shadow-brain Ā· <a href="https://github.com/theihtisham/agent-shadow-brain" style="color:#4ade80;">GitHub</a></footer>
152
+ </body>
153
153
  </html>`;
154
154
  }
155
155
  // ─── Markdown ────────────────────────────────────────────────────────────────
@@ -225,161 +225,161 @@ export class ReportGenerator {
225
225
  const hasPython = context.language?.some(l => l === 'Python');
226
226
  const hasGo = context.language?.some(l => l === 'Go');
227
227
  const hasRust = context.language?.some(l => l === 'Rust');
228
- return `# .github/workflows/shadow-brain.yml
229
- # Auto-generated by Agent Shadow Brain — https://github.com/theihtisham/agent-shadow-brain
230
- name: Shadow Brain CI
231
-
232
- on:
233
- push:
234
- branches: [main, master, develop]
235
- pull_request:
236
- branches: [main, master]
237
-
238
- permissions:
239
- contents: read
240
- pull-requests: write
241
-
242
- jobs:
243
- shadow-brain-review:
244
- name: AI Code Review
245
- runs-on: ubuntu-latest
246
- steps:
247
- - name: Checkout
248
- uses: actions/checkout@v4
249
- with:
250
- fetch-depth: 0 # Need full history for git diff
251
-
252
- - name: Setup Node.js
253
- uses: actions/setup-node@v4
254
- with:
255
- node-version: '20'
256
-
257
- - name: Install Shadow Brain
258
- run: npm install -g @theihtisham/agent-shadow-brain
259
-
260
- - name: Run Shadow Brain Review
261
- run: |
262
- shadow-brain review . \\
263
- --provider ollama \\
264
- --depth standard \\
265
- --output json > shadow-brain-report.json
266
- continue-on-error: true
267
-
268
- - name: Upload Report
269
- uses: actions/upload-artifact@v4
270
- with:
271
- name: shadow-brain-report
272
- path: shadow-brain-report.json
273
-
274
- - name: Comment PR
275
- if: github.event_name == 'pull_request'
276
- uses: actions/github-script@v7
277
- with:
278
- script: |
279
- const fs = require('fs');
280
- let report = {};
281
- try { report = JSON.parse(fs.readFileSync('shadow-brain-report.json', 'utf8')); } catch {}
282
-
283
- const critical = report.summary?.critical || 0;
284
- const high = report.summary?.high || 0;
285
- const score = report.health?.overall || 'N/A';
286
- const grade = report.health?.grade || '';
287
- const insightsText = (report.insights || []).slice(0, 5).map(i =>
288
- \`- **[\${i.priority.toUpperCase()}]** \${i.title}\`
289
- ).join('\\n');
290
-
291
- const body = \`## 🧠 Shadow Brain Review
292
-
293
- | Metric | Value |
294
- |--------|-------|
295
- | Health Score | \${score}/100 (\${grade}) |
296
- | Critical Issues | \${critical} |
297
- | High Priority | \${high} |
298
-
299
- **Top Insights:**
300
- \${insightsText || 'No issues found!'}
301
-
302
- _Generated by [Agent Shadow Brain](https://github.com/theihtisham/agent-shadow-brain)_\`;
303
-
304
- github.rest.issues.createComment({
305
- issue_number: context.issue.number,
306
- owner: context.repo.owner,
307
- repo: context.repo.repo,
308
- body,
309
- });
310
-
311
- ${hasNode ? `
312
- lint-and-type-check:
313
- name: Lint & Type Check
314
- runs-on: ubuntu-latest
315
- steps:
316
- - uses: actions/checkout@v4
317
- - uses: actions/setup-node@v4
318
- with:
319
- node-version: '20'
320
- cache: 'npm'
321
- - run: npm ci
322
- - run: npm run build --if-present
323
- - run: npm test --if-present
324
- ` : ''}${hasPython ? `
325
- python-checks:
326
- name: Python Checks
327
- runs-on: ubuntu-latest
328
- steps:
329
- - uses: actions/checkout@v4
330
- - uses: actions/setup-python@v5
331
- with:
332
- python-version: '3.12'
333
- - run: pip install ruff mypy pytest
334
- - run: ruff check .
335
- - run: pytest --tb=short
336
- ` : ''}${hasGo ? `
337
- go-checks:
338
- name: Go Checks
339
- runs-on: ubuntu-latest
340
- steps:
341
- - uses: actions/checkout@v4
342
- - uses: actions/setup-go@v5
343
- with:
344
- go-version: '1.22'
345
- - run: go vet ./...
346
- - run: go test ./...
347
- ` : ''}${hasRust ? `
348
- rust-checks:
349
- name: Rust Checks
350
- runs-on: ubuntu-latest
351
- steps:
352
- - uses: actions/checkout@v4
353
- - uses: dtolnay/rust-toolchain@stable
354
- with:
355
- components: clippy
356
- - run: cargo clippy -- -D warnings
357
- - run: cargo test
228
+ return `# .github/workflows/shadow-brain.yml
229
+ # Auto-generated by Agent Shadow Brain — https://github.com/theihtisham/agent-shadow-brain
230
+ name: Shadow Brain CI
231
+
232
+ on:
233
+ push:
234
+ branches: [main, master, develop]
235
+ pull_request:
236
+ branches: [main, master]
237
+
238
+ permissions:
239
+ contents: read
240
+ pull-requests: write
241
+
242
+ jobs:
243
+ shadow-brain-review:
244
+ name: AI Code Review
245
+ runs-on: ubuntu-latest
246
+ steps:
247
+ - name: Checkout
248
+ uses: actions/checkout@v4
249
+ with:
250
+ fetch-depth: 0 # Need full history for git diff
251
+
252
+ - name: Setup Node.js
253
+ uses: actions/setup-node@v4
254
+ with:
255
+ node-version: '20'
256
+
257
+ - name: Install Shadow Brain
258
+ run: npm install -g @theihtisham/agent-shadow-brain
259
+
260
+ - name: Run Shadow Brain Review
261
+ run: |
262
+ shadow-brain review . \\
263
+ --provider ollama \\
264
+ --depth standard \\
265
+ --output json > shadow-brain-report.json
266
+ continue-on-error: true
267
+
268
+ - name: Upload Report
269
+ uses: actions/upload-artifact@v4
270
+ with:
271
+ name: shadow-brain-report
272
+ path: shadow-brain-report.json
273
+
274
+ - name: Comment PR
275
+ if: github.event_name == 'pull_request'
276
+ uses: actions/github-script@v7
277
+ with:
278
+ script: |
279
+ const fs = require('fs');
280
+ let report = {};
281
+ try { report = JSON.parse(fs.readFileSync('shadow-brain-report.json', 'utf8')); } catch {}
282
+
283
+ const critical = report.summary?.critical || 0;
284
+ const high = report.summary?.high || 0;
285
+ const score = report.health?.overall || 'N/A';
286
+ const grade = report.health?.grade || '';
287
+ const insightsText = (report.insights || []).slice(0, 5).map(i =>
288
+ \`- **[\${i.priority.toUpperCase()}]** \${i.title}\`
289
+ ).join('\\n');
290
+
291
+ const body = \`## 🧠 Shadow Brain Review
292
+
293
+ | Metric | Value |
294
+ |--------|-------|
295
+ | Health Score | \${score}/100 (\${grade}) |
296
+ | Critical Issues | \${critical} |
297
+ | High Priority | \${high} |
298
+
299
+ **Top Insights:**
300
+ \${insightsText || 'No issues found!'}
301
+
302
+ _Generated by [Agent Shadow Brain](https://github.com/theihtisham/agent-shadow-brain)_\`;
303
+
304
+ github.rest.issues.createComment({
305
+ issue_number: context.issue.number,
306
+ owner: context.repo.owner,
307
+ repo: context.repo.repo,
308
+ body,
309
+ });
310
+
311
+ ${hasNode ? `
312
+ lint-and-type-check:
313
+ name: Lint & Type Check
314
+ runs-on: ubuntu-latest
315
+ steps:
316
+ - uses: actions/checkout@v4
317
+ - uses: actions/setup-node@v4
318
+ with:
319
+ node-version: '20'
320
+ cache: 'npm'
321
+ - run: npm ci
322
+ - run: npm run build --if-present
323
+ - run: npm test --if-present
324
+ ` : ''}${hasPython ? `
325
+ python-checks:
326
+ name: Python Checks
327
+ runs-on: ubuntu-latest
328
+ steps:
329
+ - uses: actions/checkout@v4
330
+ - uses: actions/setup-python@v5
331
+ with:
332
+ python-version: '3.12'
333
+ - run: pip install ruff mypy pytest
334
+ - run: ruff check .
335
+ - run: pytest --tb=short
336
+ ` : ''}${hasGo ? `
337
+ go-checks:
338
+ name: Go Checks
339
+ runs-on: ubuntu-latest
340
+ steps:
341
+ - uses: actions/checkout@v4
342
+ - uses: actions/setup-go@v5
343
+ with:
344
+ go-version: '1.22'
345
+ - run: go vet ./...
346
+ - run: go test ./...
347
+ ` : ''}${hasRust ? `
348
+ rust-checks:
349
+ name: Rust Checks
350
+ runs-on: ubuntu-latest
351
+ steps:
352
+ - uses: actions/checkout@v4
353
+ - uses: dtolnay/rust-toolchain@stable
354
+ with:
355
+ components: clippy
356
+ - run: cargo clippy -- -D warnings
357
+ - run: cargo test
358
358
  ` : ''}`;
359
359
  }
360
360
  generatePreCommitHook() {
361
- return `#!/bin/sh
362
- # .git/hooks/pre-commit — Auto-generated by Shadow Brain
363
- # Install: chmod +x .git/hooks/pre-commit
364
-
365
- echo "\\n🧠 Shadow Brain pre-commit review...\\n"
366
-
367
- # Run shadow brain quick review
368
- shadow-brain review . --depth quick --output text
369
-
370
- # Ask if review found critical issues
371
- CRITICAL=$(shadow-brain review . --depth quick --output json 2>/dev/null | node -e "try{const d=JSON.parse(require('fs').readFileSync('/dev/stdin','utf8'));console.log(d.summary?.critical||0)}catch{console.log(0)}")
372
-
373
- if [ "$CRITICAL" -gt "0" ]; then
374
- echo "\\n🚨 Shadow Brain found $CRITICAL critical issue(s). Commit anyway? [y/N]"
375
- read -r answer
376
- if [ "$answer" != "y" ] && [ "$answer" != "Y" ]; then
377
- echo "Commit aborted."
378
- exit 1
379
- fi
380
- fi
381
-
382
- echo "āœ“ Shadow Brain check complete\\n"
361
+ return `#!/bin/sh
362
+ # .git/hooks/pre-commit — Auto-generated by Shadow Brain
363
+ # Install: chmod +x .git/hooks/pre-commit
364
+
365
+ echo "\\n🧠 Shadow Brain pre-commit review...\\n"
366
+
367
+ # Run shadow brain quick review
368
+ shadow-brain review . --depth quick --output text
369
+
370
+ # Ask if review found critical issues
371
+ CRITICAL=$(shadow-brain review . --depth quick --output json 2>/dev/null | node -e "try{const d=JSON.parse(require('fs').readFileSync('/dev/stdin','utf8'));console.log(d.summary?.critical||0)}catch{console.log(0)}")
372
+
373
+ if [ "$CRITICAL" -gt "0" ]; then
374
+ echo "\\n🚨 Shadow Brain found $CRITICAL critical issue(s). Commit anyway? [y/N]"
375
+ read -r answer
376
+ if [ "$answer" != "y" ] && [ "$answer" != "Y" ]; then
377
+ echo "Commit aborted."
378
+ exit 1
379
+ fi
380
+ fi
381
+
382
+ echo "āœ“ Shadow Brain check complete\\n"
383
383
  `;
384
384
  }
385
385
  }