thuban 0.3.3 → 0.3.4

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/dist/LICENSE +21 -0
  2. package/dist/README.md +185 -0
  3. package/dist/cli.js +2 -0
  4. package/dist/packages/scanner/ai-confidence-scorer.js +1 -0
  5. package/dist/packages/scanner/alert-manager.js +1 -0
  6. package/dist/packages/scanner/baseline-manager.js +1 -0
  7. package/dist/packages/scanner/code-scanner.js +1 -0
  8. package/dist/packages/scanner/codebase-passport.js +1 -0
  9. package/dist/packages/scanner/copy-paste-detector.js +1 -0
  10. package/dist/packages/scanner/dependency-graph.js +1 -0
  11. package/dist/packages/scanner/drift-detector.js +1 -0
  12. package/dist/packages/scanner/executive-report.js +1 -0
  13. package/dist/packages/scanner/file-collector.js +1 -0
  14. package/dist/packages/scanner/file-watcher.js +1 -0
  15. package/dist/packages/scanner/ghost-code-detector.js +1 -0
  16. package/dist/packages/scanner/hallucination-detector.js +1 -0
  17. package/dist/packages/scanner/health-checker.js +1 -0
  18. package/dist/packages/scanner/html-report.js +1 -0
  19. package/dist/packages/scanner/index.js +1 -0
  20. package/dist/packages/scanner/license-manager.js +1 -0
  21. package/dist/packages/scanner/master-health-checker.js +1 -0
  22. package/dist/packages/scanner/monitor-notifier.js +1 -0
  23. package/dist/packages/scanner/monitor-service.js +1 -0
  24. package/dist/packages/scanner/monitor-store.js +1 -0
  25. package/dist/packages/scanner/pre-commit-gate.js +1 -0
  26. package/dist/packages/scanner/scan-diff.js +1 -0
  27. package/dist/packages/scanner/scan-runner.js +1 -0
  28. package/dist/packages/scanner/secret-scanner.js +1 -0
  29. package/dist/packages/scanner/sentinel-core.js +1 -0
  30. package/dist/packages/scanner/sentinel-knowledge.js +1 -0
  31. package/dist/packages/scanner/tech-debt-analyzer.js +1 -0
  32. package/dist/packages/scanner/tech-debt-cost.js +1 -0
  33. package/dist/packages/scanner/widget-generator.js +1 -0
  34. package/package.json +12 -7
  35. package/cli.js +0 -2627
  36. package/packages/scanner/ai-confidence-scorer.js +0 -260
  37. package/packages/scanner/alert-manager.js +0 -398
  38. package/packages/scanner/baseline-manager.js +0 -109
  39. package/packages/scanner/code-scanner.js +0 -758
  40. package/packages/scanner/codebase-passport.js +0 -299
  41. package/packages/scanner/copy-paste-detector.js +0 -276
  42. package/packages/scanner/dependency-graph.js +0 -541
  43. package/packages/scanner/drift-detector.js +0 -423
  44. package/packages/scanner/executive-report.js +0 -774
  45. package/packages/scanner/file-collector.js +0 -64
  46. package/packages/scanner/file-watcher.js +0 -323
  47. package/packages/scanner/ghost-code-detector.js +0 -301
  48. package/packages/scanner/hallucination-detector.js +0 -822
  49. package/packages/scanner/health-checker.js +0 -586
  50. package/packages/scanner/html-report.js +0 -634
  51. package/packages/scanner/index.js +0 -100
  52. package/packages/scanner/license-manager.js +0 -331
  53. package/packages/scanner/master-health-checker.js +0 -513
  54. package/packages/scanner/monitor-notifier.js +0 -64
  55. package/packages/scanner/monitor-service.js +0 -103
  56. package/packages/scanner/monitor-store.js +0 -117
  57. package/packages/scanner/pre-commit-gate.js +0 -216
  58. package/packages/scanner/scan-diff.js +0 -50
  59. package/packages/scanner/scan-runner.js +0 -172
  60. package/packages/scanner/secret-scanner.js +0 -612
  61. package/packages/scanner/secret-scanner.test.js +0 -103
  62. package/packages/scanner/sentinel-core.js +0 -616
  63. package/packages/scanner/sentinel-knowledge.js +0 -322
  64. package/packages/scanner/tech-debt-analyzer.js +0 -583
  65. package/packages/scanner/tech-debt-cost.js +0 -194
  66. package/packages/scanner/widget-generator.js +0 -415
@@ -1,586 +0,0 @@
1
- /**
2
- * Health Checker
3
- *
4
- * @purpose Event-driven HealthChecker component
5
- * @module sentinel
6
- * @layer application
7
- * @imports-from fs, path, events
8
- * @exports-to sentinel
9
- * @side-effects File system reads, Console output, Event emission
10
- * @critical-for sentinel
11
- */
12
-
13
- /**
14
- * Sentinel Health Checker
15
- *
16
- * Monitors the health of all Orion systems.
17
- * Checks: Senate, Citadel, Forge, OCEE, Handoff, Shadow Realm, Knowledge
18
- */
19
-
20
- const fs = require('fs');
21
- const path = require('path');
22
- const EventEmitter = require('events');
23
-
24
- class HealthChecker extends EventEmitter {
25
- constructor(config = {}) {
26
- super();
27
-
28
- this.config = {
29
- rootPath: config.rootPath || process.cwd(),
30
- serverPath: config.serverPath || path.join(config.rootPath || process.cwd(), 'server'),
31
- checkTimeout: config.checkTimeout || 5000,
32
- ...config
33
- };
34
-
35
- // Define system health checks
36
- this.systemChecks = [
37
- {
38
- id: 'senate',
39
- name: 'Senate',
40
- description: 'Multi-model orchestration',
41
- check: () => this._checkSenate()
42
- },
43
- {
44
- id: 'citadel',
45
- name: 'Citadel',
46
- description: '5-layer safety system',
47
- check: () => this._checkCitadel()
48
- },
49
- {
50
- id: 'forge',
51
- name: 'Forge',
52
- description: 'Build system',
53
- check: () => this._checkForge()
54
- },
55
- {
56
- id: 'ocee',
57
- name: 'OCEE',
58
- description: 'Orchestrated continuous execution',
59
- check: () => this._checkOCEE()
60
- },
61
- {
62
- id: 'handoff',
63
- name: 'Handoff',
64
- description: 'Human-AI collaboration',
65
- check: () => this._checkHandoff()
66
- },
67
- {
68
- id: 'shadow_realm',
69
- name: 'Shadow Realm',
70
- description: 'Validation sandbox',
71
- check: () => this._checkShadowRealm()
72
- },
73
- {
74
- id: 'knowledge',
75
- name: 'Knowledge Manager',
76
- description: 'Build tracking and learning',
77
- check: () => this._checkKnowledge()
78
- },
79
- {
80
- id: 'server',
81
- name: 'Express Server',
82
- description: 'API server health',
83
- check: () => this._checkServer()
84
- }
85
- ];
86
- }
87
-
88
- /**
89
- * Check health of all systems
90
- */
91
- async checkAll() {
92
- console.log('[HEALTH-CHECKER] Running full health check...');
93
- const startTime = Date.now();
94
-
95
- const result = {
96
- timestamp: new Date().toISOString(),
97
- duration: 0,
98
- overall: 'healthy',
99
- systems: [],
100
- healthySystems: [],
101
- unhealthySystems: [],
102
- summary: {}
103
- };
104
-
105
- for (const systemCheck of this.systemChecks) {
106
- try {
107
- const checkResult = await Promise.race([
108
- systemCheck.check(),
109
- this._timeout(this.config.checkTimeout)
110
- ]);
111
-
112
- const systemResult = {
113
- id: systemCheck.id,
114
- name: systemCheck.name,
115
- description: systemCheck.description,
116
- status: checkResult.healthy ? 'healthy' : 'unhealthy',
117
- healthy: checkResult.healthy,
118
- details: checkResult.details || {},
119
- issues: checkResult.issues || [],
120
- lastChecked: new Date().toISOString()
121
- };
122
-
123
- result.systems.push(systemResult);
124
-
125
- if (systemResult.healthy) {
126
- result.healthySystems.push(systemCheck.id);
127
- } else {
128
- result.unhealthySystems.push(systemCheck.id);
129
- }
130
- } catch (error) {
131
- result.systems.push({
132
- id: systemCheck.id,
133
- name: systemCheck.name,
134
- description: systemCheck.description,
135
- status: 'error',
136
- healthy: false,
137
- error: error.message,
138
- lastChecked: new Date().toISOString()
139
- });
140
- result.unhealthySystems.push(systemCheck.id);
141
- }
142
- }
143
-
144
- // Determine overall health
145
- if (result.unhealthySystems.length === 0) {
146
- result.overall = 'healthy';
147
- } else if (result.unhealthySystems.length <= 2) {
148
- result.overall = 'degraded';
149
- } else {
150
- result.overall = 'unhealthy';
151
- }
152
-
153
- result.duration = Date.now() - startTime;
154
- result.summary = {
155
- total: this.systemChecks.length,
156
- healthy: result.healthySystems.length,
157
- unhealthy: result.unhealthySystems.length
158
- };
159
-
160
- console.log(`[HEALTH-CHECKER] Health check complete: ${result.overall} (${result.summary.healthy}/${result.summary.total} systems healthy)`);
161
- this.emit('checkComplete', result);
162
-
163
- return result;
164
- }
165
-
166
- /**
167
- * Check health of a specific system
168
- */
169
- async checkSystem(systemId) {
170
- const systemCheck = this.systemChecks.find(s => s.id === systemId);
171
- if (!systemCheck) {
172
- return { error: `Unknown system: ${systemId}` };
173
- }
174
-
175
- try {
176
- const result = await systemCheck.check();
177
- return {
178
- id: systemCheck.id,
179
- name: systemCheck.name,
180
- ...result,
181
- lastChecked: new Date().toISOString()
182
- };
183
- } catch (error) {
184
- return {
185
- id: systemCheck.id,
186
- name: systemCheck.name,
187
- healthy: false,
188
- error: error.message,
189
- lastChecked: new Date().toISOString()
190
- };
191
- }
192
- }
193
-
194
- /**
195
- * Get list of available system checks
196
- */
197
- getAvailableChecks() {
198
- return this.systemChecks.map(s => ({
199
- id: s.id,
200
- name: s.name,
201
- description: s.description
202
- }));
203
- }
204
-
205
- // Individual system checks
206
-
207
- async _checkSenate() {
208
- const result = {
209
- healthy: true,
210
- details: {},
211
- issues: []
212
- };
213
-
214
- try {
215
- // Check if senate files exist
216
- const senateFiles = [
217
- path.join(this.config.serverPath, 'senate.js'),
218
- path.join(this.config.serverPath, 'senate-v2.js'),
219
- path.join(this.config.serverPath, 'data', 'model-registry.json'),
220
- path.join(this.config.serverPath, 'data', 'senate-weights-v2.json')
221
- ];
222
-
223
- let filesFound = 0;
224
- for (const file of senateFiles) {
225
- if (fs.existsSync(file)) {
226
- filesFound++;
227
- }
228
- }
229
-
230
- result.details.filesFound = filesFound;
231
- result.details.totalFiles = senateFiles.length;
232
-
233
- // Check model registry
234
- const registryPath = path.join(this.config.serverPath, 'data', 'model-registry.json');
235
- if (fs.existsSync(registryPath)) {
236
- const registry = JSON.parse(fs.readFileSync(registryPath, 'utf8'));
237
- result.details.providersConfigured = Object.keys(registry.providers || {}).length;
238
- result.details.modelsRegistered = Object.values(registry.providers || {})
239
- .reduce((sum, p) => sum + (p.models?.length || 0), 0);
240
- }
241
-
242
- if (filesFound < 2) {
243
- result.healthy = false;
244
- result.issues.push('Core Senate files missing');
245
- }
246
-
247
- } catch (error) {
248
- result.healthy = false;
249
- result.issues.push(`Senate check failed: ${error.message}`);
250
- }
251
-
252
- return result;
253
- }
254
-
255
- async _checkCitadel() {
256
- const result = {
257
- healthy: true,
258
- details: {},
259
- issues: []
260
- };
261
-
262
- try {
263
- // Check if citadel files exist
264
- const citadelPath = path.join(this.config.rootPath, 'citadel');
265
- const citadelFiles = [
266
- 'enforcer.js',
267
- 'watchers.js',
268
- 'constitution-loader.js',
269
- 'file-guard.js'
270
- ];
271
-
272
- let filesFound = 0;
273
- for (const file of citadelFiles) {
274
- if (fs.existsSync(path.join(citadelPath, file))) {
275
- filesFound++;
276
- }
277
- }
278
-
279
- result.details.filesFound = filesFound;
280
- result.details.totalFiles = citadelFiles.length;
281
-
282
- // Check audit logs
283
- const auditPath = path.join(citadelPath, 'audit');
284
- if (fs.existsSync(auditPath)) {
285
- const auditFiles = fs.readdirSync(auditPath).filter(f => f.endsWith('.json'));
286
- result.details.auditFilesCount = auditFiles.length;
287
-
288
- // Check most recent audit
289
- if (auditFiles.length > 0) {
290
- const latestAudit = auditFiles.sort().pop();
291
- const latestPath = path.join(auditPath, latestAudit);
292
- const auditStat = fs.statSync(latestPath);
293
- result.details.lastAudit = auditStat.mtime.toISOString();
294
-
295
- // Warn if no audit in 24 hours
296
- const hoursSinceAudit = (Date.now() - auditStat.mtime.getTime()) / (1000 * 60 * 60);
297
- if (hoursSinceAudit > 24) {
298
- result.issues.push(`No audit activity in ${Math.round(hoursSinceAudit)} hours`);
299
- }
300
- }
301
- }
302
-
303
- if (filesFound < 3) {
304
- result.healthy = false;
305
- result.issues.push('Core Citadel files missing');
306
- }
307
-
308
- } catch (error) {
309
- result.healthy = false;
310
- result.issues.push(`Citadel check failed: ${error.message}`);
311
- }
312
-
313
- return result;
314
- }
315
-
316
- async _checkForge() {
317
- const result = {
318
- healthy: true,
319
- details: {},
320
- issues: []
321
- };
322
-
323
- try {
324
- const forgePath = path.join(this.config.rootPath, 'forge');
325
- const forgeFiles = [
326
- 'forge-core.js',
327
- 'task-decomposer.js',
328
- 'intent-matcher.js',
329
- 'diagnostician-v2.js',
330
- 'prescriber.js',
331
- 'forge-loop.js'
332
- ];
333
-
334
- let filesFound = 0;
335
- for (const file of forgeFiles) {
336
- if (fs.existsSync(path.join(forgePath, file))) {
337
- filesFound++;
338
- }
339
- }
340
-
341
- result.details.filesFound = filesFound;
342
- result.details.totalFiles = forgeFiles.length;
343
- result.details.completeness = Math.round((filesFound / forgeFiles.length) * 100) + '%';
344
-
345
- if (filesFound < 4) {
346
- result.healthy = false;
347
- result.issues.push('Core Forge components missing');
348
- }
349
-
350
- } catch (error) {
351
- result.healthy = false;
352
- result.issues.push(`Forge check failed: ${error.message}`);
353
- }
354
-
355
- return result;
356
- }
357
-
358
- async _checkOCEE() {
359
- const result = {
360
- healthy: true,
361
- details: {},
362
- issues: []
363
- };
364
-
365
- try {
366
- const oceePath = path.join(this.config.serverPath, 'ocee');
367
- const oceeFiles = [
368
- 'ocee-core.js',
369
- 'persistent-task-queue.js',
370
- 'checkpoint-manager.js',
371
- 'build-session-manager.js',
372
- 'build-graph-generator.js'
373
- ];
374
-
375
- let filesFound = 0;
376
- for (const file of oceeFiles) {
377
- if (fs.existsSync(path.join(oceePath, file))) {
378
- filesFound++;
379
- }
380
- }
381
-
382
- result.details.filesFound = filesFound;
383
- result.details.totalFiles = oceeFiles.length;
384
-
385
- // Check for active tasks
386
- const taskQueuePath = path.join(oceePath, 'queue');
387
- if (fs.existsSync(taskQueuePath)) {
388
- try {
389
- const queueFiles = fs.readdirSync(taskQueuePath);
390
- result.details.pendingTasks = queueFiles.length;
391
- } catch (e) {
392
- result.details.pendingTasks = 'unknown';
393
- }
394
- }
395
-
396
- if (filesFound < 3) {
397
- result.healthy = false;
398
- result.issues.push('Core OCEE components missing');
399
- }
400
-
401
- } catch (error) {
402
- result.healthy = false;
403
- result.issues.push(`OCEE check failed: ${error.message}`);
404
- }
405
-
406
- return result;
407
- }
408
-
409
- async _checkHandoff() {
410
- const result = {
411
- healthy: true,
412
- details: {},
413
- issues: []
414
- };
415
-
416
- try {
417
- const handoffPath = path.join(this.config.serverPath, 'handoff');
418
- const handoffFiles = [
419
- 'index.js',
420
- 'risk-scorer.js',
421
- 'gate-checker.js',
422
- 'mission-state.js',
423
- 'audit-logger.js',
424
- 'evidence-bundle.js',
425
- 'cost-tracker.js'
426
- ];
427
-
428
- let filesFound = 0;
429
- for (const file of handoffFiles) {
430
- if (fs.existsSync(path.join(handoffPath, file))) {
431
- filesFound++;
432
- }
433
- }
434
-
435
- result.details.filesFound = filesFound;
436
- result.details.totalFiles = handoffFiles.length;
437
-
438
- if (filesFound < 5) {
439
- result.healthy = false;
440
- result.issues.push('Core Handoff components missing');
441
- }
442
-
443
- } catch (error) {
444
- result.healthy = false;
445
- result.issues.push(`Handoff check failed: ${error.message}`);
446
- }
447
-
448
- return result;
449
- }
450
-
451
- async _checkShadowRealm() {
452
- const result = {
453
- healthy: true,
454
- details: {},
455
- issues: []
456
- };
457
-
458
- try {
459
- const shadowPath = path.join(this.config.rootPath, 'build-engine', 'orion-core');
460
- const shadowFiles = [
461
- 'shadow-realm-v2.js',
462
- 'foreman.js',
463
- 'healing-loop.js'
464
- ];
465
-
466
- let filesFound = 0;
467
- for (const file of shadowFiles) {
468
- if (fs.existsSync(path.join(shadowPath, file))) {
469
- filesFound++;
470
- }
471
- }
472
-
473
- result.details.filesFound = filesFound;
474
- result.details.totalFiles = shadowFiles.length;
475
-
476
- // Test shadow realm validation
477
- try {
478
- const shadowRealm = require(path.join(shadowPath, 'shadow-realm-v2.js'));
479
- const testResult = shadowRealm.validateInSandbox('console.log("test");', 'test.js');
480
- result.details.validationWorking = testResult.syntaxValid === true;
481
- } catch (e) {
482
- result.details.validationWorking = false;
483
- result.issues.push(`Shadow Realm validation test failed: ${e.message}`);
484
- }
485
-
486
- if (filesFound < 2) {
487
- result.healthy = false;
488
- result.issues.push('Core Shadow Realm components missing');
489
- }
490
-
491
- } catch (error) {
492
- result.healthy = false;
493
- result.issues.push(`Shadow Realm check failed: ${error.message}`);
494
- }
495
-
496
- return result;
497
- }
498
-
499
- async _checkKnowledge() {
500
- const result = {
501
- healthy: true,
502
- details: {},
503
- issues: []
504
- };
505
-
506
- try {
507
- const knowledgePath = path.join(this.config.rootPath, 'orion-knowledge.json');
508
-
509
- if (fs.existsSync(knowledgePath)) {
510
- const knowledge = JSON.parse(fs.readFileSync(knowledgePath, 'utf8'));
511
- result.details.buildsTracked = knowledge.builds?.length || 0;
512
- result.details.capabilitiesTracked = knowledge.capabilities?.length || 0;
513
-
514
- // Check for recent activity
515
- if (knowledge.builds && knowledge.builds.length > 0) {
516
- const latestBuild = knowledge.builds[knowledge.builds.length - 1];
517
- result.details.lastBuild = latestBuild.timestamp || latestBuild.date;
518
- }
519
- } else {
520
- result.healthy = false;
521
- result.issues.push('orion-knowledge.json not found');
522
- }
523
-
524
- } catch (error) {
525
- result.healthy = false;
526
- result.issues.push(`Knowledge check failed: ${error.message}`);
527
- }
528
-
529
- return result;
530
- }
531
-
532
- async _checkServer() {
533
- const result = {
534
- healthy: true,
535
- details: {},
536
- issues: []
537
- };
538
-
539
- try {
540
- // Check if server files exist
541
- const serverFiles = [
542
- path.join(this.config.serverPath, 'package.json'),
543
- path.join(this.config.serverPath, 'index.js')
544
- ];
545
-
546
- let filesFound = 0;
547
- for (const file of serverFiles) {
548
- if (fs.existsSync(file)) {
549
- filesFound++;
550
- }
551
- }
552
-
553
- result.details.filesFound = filesFound;
554
-
555
- // Check package.json for dependencies
556
- const pkgPath = path.join(this.config.serverPath, 'package.json');
557
- if (fs.existsSync(pkgPath)) {
558
- const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf8'));
559
- result.details.dependencies = Object.keys(pkg.dependencies || {}).length;
560
- result.details.nodeVersion = pkg.engines?.node || 'not specified';
561
- }
562
-
563
- // Check node_modules exists
564
- const nodeModulesPath = path.join(this.config.serverPath, 'node_modules');
565
- result.details.nodeModulesInstalled = fs.existsSync(nodeModulesPath);
566
-
567
- if (!result.details.nodeModulesInstalled) {
568
- result.issues.push('node_modules not installed - run npm install');
569
- }
570
-
571
- } catch (error) {
572
- result.healthy = false;
573
- result.issues.push(`Server check failed: ${error.message}`);
574
- }
575
-
576
- return result;
577
- }
578
-
579
- _timeout(ms) {
580
- return new Promise((_, reject) =>
581
- setTimeout(() => reject(new Error('Health check timeout')), ms)
582
- );
583
- }
584
- }
585
-
586
- module.exports = HealthChecker;