mindforge-cc 5.6.0 → 6.0.0-alpha

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 (60) hide show
  1. package/.agent/CLAUDE.md +16 -7
  2. package/.agent/mindforge/health.md +6 -0
  3. package/.agent/mindforge/help.md +6 -0
  4. package/.agent/mindforge/security-scan.md +6 -1
  5. package/.agent/mindforge/status.md +10 -5
  6. package/.claude/CLAUDE.md +14 -12
  7. package/.mindforge/engine/integrity.json +12 -0
  8. package/.mindforge/engine/nexus-tracer.js +7 -111
  9. package/.mindforge/governance/policies/sovereign-default.json +16 -0
  10. package/.mindforge/org/skills/MANIFEST.md +10 -34
  11. package/.planning/RISK-AUDIT.jsonl +48 -0
  12. package/CHANGELOG.md +140 -17
  13. package/MINDFORGE.md +8 -5
  14. package/README.md +67 -7
  15. package/RELEASENOTES.md +54 -1
  16. package/SECURITY.md +38 -0
  17. package/bin/autonomous/auto-runner.js +14 -0
  18. package/bin/autonomous/intent-harvester.js +80 -0
  19. package/bin/autonomous/mesh-self-healer.js +67 -0
  20. package/bin/dashboard/frontend/index.html +241 -1
  21. package/bin/dashboard/revops-api.js +47 -0
  22. package/bin/dashboard/server.js +1 -0
  23. package/bin/engine/feedback-loop.js +36 -1
  24. package/bin/engine/logic-drift-detector.js +97 -0
  25. package/bin/engine/nexus-tracer.js +61 -22
  26. package/bin/engine/remediation-engine.js +72 -0
  27. package/bin/engine/sre-manager.js +63 -9
  28. package/bin/governance/impact-analyzer.js +75 -15
  29. package/bin/governance/policy-engine.js +120 -45
  30. package/bin/governance/quantum-crypto.js +90 -0
  31. package/bin/governance/ztai-manager.js +37 -1
  32. package/bin/installer-core.js +38 -7
  33. package/bin/mindforge-cli.js +30 -0
  34. package/bin/models/cloud-broker.js +89 -11
  35. package/bin/models/performance-stats.json +22 -0
  36. package/bin/revops/debt-monitor.js +60 -0
  37. package/bin/revops/market-evaluator.js +79 -0
  38. package/bin/revops/roi-engine.js +65 -0
  39. package/bin/revops/router-steering-v2.js +73 -0
  40. package/bin/revops/velocity-forecaster.js +59 -0
  41. package/bin/wizard/theme.js +5 -1
  42. package/docs/CAPABILITIES-MANIFEST.md +64 -0
  43. package/docs/INTELLIGENCE-MESH.md +21 -23
  44. package/docs/MIND-FORGE-REFERENCE-V6.md +96 -0
  45. package/docs/architecture/README.md +4 -4
  46. package/docs/architecture/V5-ENTERPRISE.md +51 -34
  47. package/docs/architecture/V6-SOVEREIGN.md +43 -0
  48. package/docs/commands-reference.md +4 -1
  49. package/docs/feature-dashboard.md +9 -3
  50. package/docs/governance-guide.md +78 -40
  51. package/docs/registry/AGENTS.md +37 -0
  52. package/docs/registry/COMMANDS.md +87 -0
  53. package/docs/registry/HOOKS.md +38 -0
  54. package/docs/registry/PERSONAS.md +64 -0
  55. package/docs/registry/README.md +27 -0
  56. package/docs/registry/SKILLS.md +142 -0
  57. package/docs/registry/WORKFLOWS.md +72 -0
  58. package/docs/user-guide.md +36 -6
  59. package/docs/usp-features.md +63 -352
  60. package/package.json +2 -2
@@ -161,6 +161,8 @@
161
161
  <button class="tab active" onclick="showPage('activity')">Activity</button>
162
162
  <button class="tab" onclick="showPage('metrics')">Metrics</button>
163
163
  <button class="tab" onclick="showPage('approvals')">Approvals</button>
164
+ <button class="tab" onclick="showPage('temporal')">Temporal</button>
165
+ <button class="tab" onclick="showPage('revops')">RevOps</button>
164
166
  <button class="tab" onclick="showPage('memory')">Memory</button>
165
167
  <button class="tab" onclick="showPage('team')">Team</button>
166
168
  </nav>
@@ -213,6 +215,116 @@
213
215
  </div>
214
216
  </div>
215
217
 
218
+ <!-- PAGE: TEMPORAL -->
219
+ <div id="temporal" class="page">
220
+ <div class="card">
221
+ <div class="card-header">
222
+ <div class="card-title">Temporal Steering Timeline</div>
223
+ <div id="timeline-count" class="badge">0 Snapshots</div>
224
+ </div>
225
+ <div class="card-body">
226
+ <div style="margin-bottom: 24px;">
227
+ <input type="range" id="temporal-slider" style="width:100%; height:8px; accent-color:var(--accent);" min="0" max="0" step="1" oninput="onSliderChange(this.value)">
228
+ <div style="display:flex; justify-content:space-between; margin-top:8px; font-family:var(--font-mono); font-size:10px; color:var(--muted)">
229
+ <span id="slider-start">Past</span>
230
+ <span id="slider-current">Select Snapshot</span>
231
+ <span id="slider-end">Present</span>
232
+ </div>
233
+ </div>
234
+
235
+ <div class="grid-2">
236
+ <div class="card" style="height:400px; border-style:dashed;">
237
+ <div class="card-header"><div class="card-title">Reasoning Snapshot Inspector</div></div>
238
+ <div id="snapshot-viewer" class="card-body" style="font-family:var(--font-mono); font-size:11px; overflow-y:auto; background:#000; color:#eee;">
239
+ Select a point in space-time to inspect agentic state...
240
+ </div>
241
+ </div>
242
+ <div class="card" style="height:400px;">
243
+ <div class="card-header"><div class="card-title">Hindsight Steering Vector</div></div>
244
+ <div class="card-body">
245
+ <p style="color:var(--muted); margin-bottom:16px;">Injecting a steering vector will rollback the system state to the selected snapshot and re-trigger the optimization loop with the new constraints.</p>
246
+ <div style="margin-bottom:20px;">
247
+ <label style="display:block; font-size:11px; margin-bottom:8px; color:var(--muted); text-transform:uppercase;">Steering Instruction:</label>
248
+ <textarea id="steering-input" class="confirm-input" style="height:120px; resize:none;" placeholder="e.g. 'Rewind to step 2 and ignore the legacy auth module...'"></textarea>
249
+ </div>
250
+ <button id="inject-btn" class="btn btn-approve" style="width:100%; justify-content:center;" onclick="injectHindsight()" disabled>Rewind & Inject Fix</button>
251
+ </div>
252
+ </div>
253
+ </div>
254
+ </div>
255
+ </div>
256
+ </div>
257
+
258
+ <!-- PAGE: REVOPS -->
259
+ <div id="revops" class="page">
260
+ <div class="grid-4">
261
+ <div class="card">
262
+ <div class="card-body">
263
+ <div class="stat-label">Agentic ROI</div>
264
+ <div id="rev-roi" class="stat-value">0%</div>
265
+ </div>
266
+ </div>
267
+ <div class="card">
268
+ <div class="card-body">
269
+ <div class="stat-label">Net Value Synthesis</div>
270
+ <div id="rev-net" class="stat-value">$0.00</div>
271
+ </div>
272
+ </div>
273
+ <div class="card">
274
+ <div class="card-body">
275
+ <div class="stat-label">Project Velocity</div>
276
+ <div id="rev-velocity" class="stat-value">0 <span class="stat-unit">tasks/hr</span></div>
277
+ <div id="rev-eta" style="font-size:10px; margin-top:4px; color:var(--muted)">ETA: N/A</div>
278
+ </div>
279
+ </div>
280
+ <div class="card">
281
+ <div class="card-body">
282
+ <div class="stat-label">Security Health</div>
283
+ <div id="rev-health" class="stat-value">100</div>
284
+ <div id="rev-health-status" class="badge" style="margin-top:4px">STATUS: EXCELLENT</div>
285
+ </div>
286
+ </div>
287
+ </div>
288
+
289
+ <div class="grid-2">
290
+ <div class="card">
291
+ <div class="card-header"><div class="card-title">Financial Flow (ROI Mapping)</div></div>
292
+ <div class="card-body">
293
+ <div id="roi-breakdown" style="font-family:var(--font-mono); font-size:12px;">
294
+ <div style="display:flex; justify-content:space-between; padding:8px 0; border-bottom:1px solid var(--border)">
295
+ <span>Developer Hours Saved:</span> <span id="roi-hours" style="color:var(--green)">0.00h</span>
296
+ </div>
297
+ <div style="display:flex; justify-content:space-between; padding:8px 0; border-bottom:1px solid var(--border)">
298
+ <span>Gross Value Produced:</span> <span id="roi-gross" style="color:var(--green)">$0.00</span>
299
+ </div>
300
+ <div style="display:flex; justify-content:space-between; padding:8px 0; border-bottom:1px solid var(--border)">
301
+ <span>Total Token Burn:</span> <span id="roi-burn" style="color:var(--red)">$0.00</span>
302
+ </div>
303
+ <div style="display:flex; justify-content:space-between; padding:12px 0; font-weight:700; font-size:14px;">
304
+ <span>NET AGENTIC ROI:</span> <span id="roi-total-pct" style="color:var(--accent)">0%</span>
305
+ </div>
306
+ </div>
307
+ </div>
308
+ </div>
309
+ <div class="card">
310
+ <div class="card-header"><div class="card-title">Governance Debt Analysis</div></div>
311
+ <div class="card-body">
312
+ <div id="debt-breakdown" style="font-family:var(--font-mono); font-size:12px;">
313
+ <div style="display:flex; justify-content:space-between; padding:8px 0; border-bottom:1px solid var(--border)">
314
+ <span>Critical Security Findings:</span> <span id="debt-critical">0</span>
315
+ </div>
316
+ <div style="display:flex; justify-content:space-between; padding:8px 0; border-bottom:1px solid var(--border)">
317
+ <span>Tier 3 Policy Bypasses:</span> <span id="debt-tier3">0</span>
318
+ </div>
319
+ <div style="display:flex; justify-content:space-between; padding:8px 0; border-bottom:1px solid var(--border)">
320
+ <span>Active Risk Level:</span> <span id="debt-risk" class="badge">MINIMAL</span>
321
+ </div>
322
+ </div>
323
+ </div>
324
+ </div>
325
+ </div>
326
+ </div>
327
+
216
328
  <!-- PAGE: MEMORY -->
217
329
  <div id="memory" class="page">
218
330
  <div class="grid-2">
@@ -321,9 +433,33 @@
321
433
  refreshApprovals();
322
434
  refreshMemory();
323
435
  refreshTeam();
436
+ refreshRevOps();
437
+ if (document.getElementById('temporal').classList.contains('active')) {
438
+ refreshTemporal();
439
+ }
324
440
  } catch(e) { console.error('Refresh fail', e); }
325
441
  }
326
442
 
443
+ async function refreshRevOps() {
444
+ try {
445
+ const res = await fetch('/api/revops/overview');
446
+ const data = await res.json();
447
+ if (data.success) {
448
+ updateRevOpsUI(data);
449
+ }
450
+ } catch(e) {}
451
+ }
452
+
453
+ let temporalHistory = [];
454
+ async function refreshTemporal() {
455
+ try {
456
+ const res = await fetch('/api/temporal/history');
457
+ const data = await res.json();
458
+ temporalHistory = data;
459
+ renderTemporalTimeline();
460
+ } catch(e) {}
461
+ }
462
+
327
463
  async function refreshApprovals() {
328
464
  try {
329
465
  const res = await fetch('/api/approvals');
@@ -503,8 +639,112 @@
503
639
  ctx.fill();
504
640
  }
505
641
 
642
+ // ── Temporal Steering Logic ────────────────────────────────────────────────
643
+ function renderTemporalTimeline() {
644
+ const slider = document.getElementById('temporal-slider');
645
+ const count = document.getElementById('timeline-count');
646
+
647
+ if (temporalHistory.length === 0) {
648
+ slider.max = 0;
649
+ count.textContent = '0 Snapshots';
650
+ return;
651
+ }
652
+
653
+ slider.max = temporalHistory.length - 1;
654
+ count.textContent = `${temporalHistory.length} Snapshots`;
655
+
656
+ // Default to latest if not touching
657
+ if (slider.value == 0 && temporalHistory.length > 0) {
658
+ onSliderChange(temporalHistory.length - 1);
659
+ slider.value = temporalHistory.length - 1;
660
+ }
661
+ }
662
+
663
+ let selectedSnapshot = null;
664
+ async function onSliderChange(index) {
665
+ const snap = temporalHistory[temporalHistory.length - 1 - index]; // reversed for chronological range
666
+ if (!snap) return;
667
+
668
+ selectedSnapshot = snap;
669
+ document.getElementById('slider-current').textContent = `Point: ${snap.id.slice(0, 8)} (${new Date(snap.timestamp).toLocaleTimeString()})`;
670
+ document.getElementById('inject-btn').disabled = false;
671
+
672
+ // Fetch sample audit file for this snapshot
673
+ try {
674
+ const res = await fetch(`/api/temporal/snapshot/${snap.id}/AUDIT.jsonl`);
675
+ const content = await res.text();
676
+ document.getElementById('snapshot-viewer').textContent = content || 'No audit log available for this point.';
677
+ } catch(e) {
678
+ document.getElementById('snapshot-viewer').textContent = 'Failed to load snapshot details.';
679
+ }
680
+ }
681
+
682
+ async function injectHindsight() {
683
+ if (!selectedSnapshot) return;
684
+ const instruction = document.getElementById('steering-input').value;
685
+ if (!instruction) {
686
+ alert('Please provide a steering instruction for the hindsight injection.');
687
+ return;
688
+ }
689
+
690
+ const btn = document.getElementById('inject-btn');
691
+ btn.disabled = true;
692
+ btn.textContent = 'Injecting Steering Vector...';
693
+
694
+ try {
695
+ const res = await fetch('/api/temporal/inject', {
696
+ method: 'POST',
697
+ headers: { 'Content-Type': 'application/json' },
698
+ body: JSON.stringify({
699
+ auditId: selectedSnapshot.id,
700
+ fixDescription: instruction
701
+ })
702
+ });
703
+ const result = await res.json();
704
+ if (result.success) {
705
+ alert('Hindsight Injection Successful. Agent state rolled back and awaiting re-optimization.');
706
+ showPage('activity');
707
+ } else {
708
+ alert('Injection failed: ' + result.error);
709
+ }
710
+ } catch(e) {
711
+ alert('Failed to connect to temporal engine.');
712
+ } finally {
713
+ btn.disabled = false;
714
+ btn.textContent = 'Rewind & Inject Fix';
715
+ }
716
+ }
717
+
718
+ // ── RevOps Logic ─────────────────────────────────────────────────────────
719
+ function updateRevOpsUI(data) {
720
+ const { roi, velocity, debt } = data;
721
+
722
+ document.getElementById('rev-roi').textContent = `${roi.roi_percentage}%`;
723
+ document.getElementById('rev-net').textContent = `$${roi.net_value}`;
724
+ document.getElementById('rev-velocity').innerHTML = `${velocity.avg_seconds_per_task} <span class="stat-unit">sec/task</span>`;
725
+ document.getElementById('rev-eta').textContent = `ETA: ${velocity.eta}`;
726
+ document.getElementById('rev-health').textContent = debt.security_health_score;
727
+
728
+ const healthStatus = document.getElementById('rev-health-status');
729
+ healthStatus.textContent = `STATUS: ${debt.governance_status.toUpperCase()}`;
730
+ healthStatus.style.background = debt.security_health_score > 80 ? 'rgba(63, 185, 80, 0.15)' : 'rgba(248, 81, 73, 0.15)';
731
+ healthStatus.style.color = debt.security_health_score > 80 ? 'var(--green)' : 'var(--red)';
732
+
733
+ document.getElementById('roi-hours').textContent = `${roi.hours_saved}h`;
734
+ document.getElementById('roi-gross').textContent = `$${roi.gross_value}`;
735
+ document.getElementById('roi-burn').textContent = `$${roi.token_cost}`;
736
+ document.getElementById('roi-total-pct').textContent = `${roi.roi_percentage}%`;
737
+
738
+ document.getElementById('debt-critical').textContent = debt.critical_findings;
739
+ document.getElementById('debt-tier3').textContent = debt.tier3_approvals;
740
+ const riskBadge = document.getElementById('debt-risk');
741
+ riskBadge.textContent = debt.debt_level.toUpperCase();
742
+ riskBadge.className = `badge ${debt.debt_level === 'Minimal' ? 'badge-live' : ''}`;
743
+ if (debt.debt_level !== 'Minimal') riskBadge.style.color = 'var(--yellow)';
744
+ }
745
+
506
746
  window.onresize = drawCharts;
507
- setInterval(refreshData, 30000); // Periodic full refresh
747
+ setInterval(refreshData, 10000); // More frequent refresh for live dashboard
508
748
  showPage('activity');
509
749
  </script>
510
750
  </body>
@@ -0,0 +1,47 @@
1
+ /**
2
+ * MindForge v5.10.0 — AgRevOps API
3
+ * Exposes ROI, Velocity, and Debt monitoring to the dashboard.
4
+ */
5
+ 'use strict';
6
+
7
+ const express = require('express');
8
+ const router = express.Router();
9
+ const roiEngine = require('../revops/roi-engine');
10
+ const velocityForecaster = require('../revops/velocity-forecaster');
11
+ const debtMonitor = require('../revops/debt-monitor');
12
+ const metricsAggregator = require('./metrics-aggregator');
13
+
14
+ /**
15
+ * GET /api/revops/overview
16
+ * Returns a consolidated view of ROI, Velocity, and Governance Debt.
17
+ */
18
+ router.get('/overview', (req, res) => {
19
+ try {
20
+ const metrics = metricsAggregator.getMetrics();
21
+ const status = metricsAggregator.getStatus();
22
+
23
+ // Enrich with current status for forecaster
24
+ const fullMetrics = {
25
+ ...metrics,
26
+ tasks_total: status.tasks_total || 0,
27
+ tasks_completed: status.tasks_completed || 0,
28
+ auditEntries: metricsAggregator.getAuditEntries(500) // need enough history for velocity
29
+ };
30
+
31
+ const roi = roiEngine.calculate(fullMetrics);
32
+ const velocity = velocityForecaster.predict(fullMetrics);
33
+ const debt = debtMonitor.monitor(fullMetrics);
34
+
35
+ res.json({
36
+ success: true,
37
+ roi,
38
+ velocity,
39
+ debt,
40
+ timestamp: new Date().toISOString()
41
+ });
42
+ } catch (err) {
43
+ res.status(500).json({ success: false, error: 'AgRevOps metrics retrieval failed', detail: err.message });
44
+ }
45
+ });
46
+
47
+ module.exports = router;
@@ -34,6 +34,7 @@ try {
34
34
  const SSE = require('./sse-bridge');
35
35
  const API = require('./api-router');
36
36
  const TemporalAPI = require('./temporal-api');
37
+ const RevOpsAPI = require('./revops-api');
37
38
 
38
39
  // ── Express app ───────────────────────────────────────────────────────────────
39
40
  const app = express();
@@ -2,11 +2,14 @@
2
2
  * MindForge — WaveFeedbackLoop (Pillar VI: Proactive Equilibrium)
3
3
  * Monitors divergence during wave execution and triggers self-healing.
4
4
  */
5
+ const fs = require('fs');
6
+ const path = require('path');
5
7
 
6
8
  class WaveFeedbackLoop {
7
9
  constructor(config = {}) {
8
10
  this.failureThreshold = config.failureThreshold || 0.20; // 20% failure rate
9
11
  this.divergenceWeight = config.divergenceWeight || 1.5; // Bias for rapid divergence
12
+ this.statsPath = config.statsPath || path.join(__dirname, '..', 'models', 'performance-stats.json');
10
13
  this.waveState = {
11
14
  completed: 0,
12
15
  failed: 0,
@@ -16,19 +19,51 @@ class WaveFeedbackLoop {
16
19
  }
17
20
 
18
21
  /**
19
- * Updates the feedback loop with a task result.
22
+ * Updates the feedback loop with a task result and records performance stats.
20
23
  */
21
24
  update(result) {
22
25
  this.waveState.total++;
26
+ const provider = result.providerId || 'unknown';
27
+ const taskType = result.taskType || 'default';
28
+
23
29
  if (result.status === 'completed') {
24
30
  this.waveState.completed++;
31
+ this.recordPerformance(provider, taskType, true);
25
32
  } else if (result.status === 'failed') {
26
33
  this.waveState.failed++;
34
+ this.recordPerformance(provider, taskType, false);
27
35
  } else {
28
36
  this.waveState.skipped++;
29
37
  }
30
38
  }
31
39
 
40
+ /**
41
+ * Records performance metrics to persistent storage.
42
+ */
43
+ recordPerformance(provider, taskType, isSuccess) {
44
+ if (provider === 'unknown') return;
45
+
46
+ try {
47
+ let stats = {};
48
+ if (fs.existsSync(this.statsPath)) {
49
+ stats = JSON.parse(fs.readFileSync(this.statsPath, 'utf8'));
50
+ }
51
+
52
+ if (!stats[provider]) stats[provider] = {};
53
+ if (!stats[provider][taskType]) stats[provider][taskType] = { success: 0, failure: 0 };
54
+
55
+ if (isSuccess) {
56
+ stats[provider][taskType].success++;
57
+ } else {
58
+ stats[provider][taskType].failure++;
59
+ }
60
+
61
+ fs.writeFileSync(this.statsPath, JSON.stringify(stats, null, 2));
62
+ } catch (e) {
63
+ console.warn(`[MCA-WARN] Failed to record performance stats: ${e.message}`);
64
+ }
65
+ }
66
+
32
67
  /**
33
68
  * Calculates the current divergence rate.
34
69
  * @returns {number} - 0.0 to 1.0 divergence rate.
@@ -0,0 +1,97 @@
1
+ /**
2
+ * MindForge v6.1.0-alpha — Neural Drift Remediation (NDR)
3
+ * Component: Logic Drift Detector (Pillar X)
4
+ *
5
+ * Analyzes reasoning traces for "Semantic Decay" (repeated failure patterns,
6
+ * hallucination-like markers, or mission drift).
7
+ */
8
+ 'use strict';
9
+
10
+ class LogicDriftDetector {
11
+ constructor() {
12
+ this.sessionDriftHistory = new Map(); // spanId -> [scores]
13
+ this.DRIFT_THRESHOLD = 0.75;
14
+ }
15
+
16
+ /**
17
+ * Analyzes a specific thought for logic drift.
18
+ * @param {string} spanId
19
+ * @param {string} thought
20
+ */
21
+ analyze(spanId, thought) {
22
+ const semanticDensity = this._calculateSemanticDensity(thought);
23
+ const patternScore = this._detectRepetitivePatterns(spanId, thought);
24
+ const contradictionScore = this._checkHeuristicContradictions(thought);
25
+
26
+ // v6.1 Weights: Aggressive on contradictions and patterns
27
+ const driftScore = (semanticDensity * 0.1) + (patternScore * 0.5) + (contradictionScore * 0.4);
28
+
29
+ if (!this.sessionDriftHistory.has(spanId)) {
30
+ this.sessionDriftHistory.set(spanId, []);
31
+ }
32
+ this.sessionDriftHistory.get(spanId).push(driftScore);
33
+
34
+ return {
35
+ span_id: spanId,
36
+ drift_score: parseFloat(driftScore.toFixed(4)),
37
+ status: driftScore > this.DRIFT_THRESHOLD ? 'DRIFT_DETECTED' : 'STABLE',
38
+ markers: {
39
+ density: semanticDensity,
40
+ pattern: patternScore,
41
+ contradiction: contradictionScore
42
+ }
43
+ };
44
+ }
45
+
46
+ /**
47
+ * Internal Heuristic: Detects low semantic density (rambling).
48
+ */
49
+ _calculateSemanticDensity(thought) {
50
+ const words = thought.split(/\s+/).length;
51
+ // Strip punctuation for keyword matching
52
+ const keywords = thought.toLowerCase().replace(/[^\w\s]/g, '').match(/\b(\w{5,})\b/g) || [];
53
+ const uniqueKeywords = new Set(keywords).size;
54
+
55
+ if (words === 0) return 0;
56
+ const ratio = uniqueKeywords / words;
57
+ // v6.1 Hardening: High sensitivity to rambling
58
+ return ratio < 0.25 ? 0.95 : 0.05;
59
+ }
60
+
61
+ /**
62
+ * Internal Heuristic: Detects circular reasoning across a span window
63
+ * and within the thought itself.
64
+ */
65
+ _detectRepetitivePatterns(spanId, currentThought) {
66
+ const history = this.sessionDriftHistory.get(spanId) || [];
67
+
68
+ // Internal Repetition Check (Strip punctuation)
69
+ const normalized = currentThought.toLowerCase().replace(/[^\w\s]/g, '');
70
+ const words = normalized.split(/\s+/).filter(w => w.length > 3);
71
+ const wordCounts = {};
72
+ words.forEach(w => wordCounts[w] = (wordCounts[w] || 0) + 1);
73
+
74
+ const maxRep = Math.max(0, ...Object.values(wordCounts));
75
+ const internalRepFactor = maxRep > 3 ? 0.9 : 0.1; // v6.1: Higher penalty
76
+
77
+ if (history.length < 2) return internalRepFactor;
78
+
79
+ // Window trending check
80
+ const recentScores = history.slice(-3);
81
+ const isTrendingUp = recentScores.length >= 2 && recentScores[recentScores.length-1] > recentScores[0];
82
+
83
+ return Math.max(internalRepFactor, isTrendingUp ? 0.7 : 0.1);
84
+ }
85
+
86
+ /**
87
+ * Internal Heuristic: Detects logic contradiction keywords.
88
+ */
89
+ _checkHeuristicContradictions(thought) {
90
+ const t = thought.toLowerCase();
91
+ const markers = ['nevertheless', 'however, i will instead', 'contradicting', 'error in reasoning', 'failed to', 'restart checking'];
92
+ const hits = markers.filter(m => t.includes(m)).length;
93
+ return Math.min(1.0, hits * 0.35); // v6.1: Higher impact per marker
94
+ }
95
+ }
96
+
97
+ module.exports = new LogicDriftDetector();