mindforge-cc 11.0.0 → 11.2.1

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 (70) hide show
  1. package/.agent/hooks/mindforge-statusline.js +2 -2
  2. package/.mindforge/config.json +14 -4
  3. package/CHANGELOG.md +137 -0
  4. package/MINDFORGE.md +5 -5
  5. package/RELEASENOTES.md +1 -1
  6. package/bin/autonomous/audit-writer.js +108 -86
  7. package/bin/autonomous/auto-runner.js +304 -19
  8. package/bin/autonomous/dependency-dag.js +59 -0
  9. package/bin/autonomous/mesh-self-healer.js +101 -28
  10. package/bin/autonomous/wave-executor.js +20 -1
  11. package/bin/browser/regression-writer.js +45 -3
  12. package/bin/browser/session-manager.js +21 -17
  13. package/bin/council-cli.js +161 -0
  14. package/bin/dashboard/approval-handler.js +3 -1
  15. package/bin/dashboard/server.js +1 -1
  16. package/bin/dashboard/sse-bridge.js +9 -12
  17. package/bin/engine/council-runtime.js +124 -0
  18. package/bin/engine/logic-drift-detector.js +14 -6
  19. package/bin/engine/logic-validator.js +155 -25
  20. package/bin/engine/orbital-guardian.js +56 -10
  21. package/bin/engine/otel-exporter.js +123 -0
  22. package/bin/engine/reason-source-aligner.js +19 -6
  23. package/bin/engine/remediation-engine.js +1 -1
  24. package/bin/engine/self-corrective-synthesizer.js +1 -1
  25. package/bin/engine/sre-manager.js +33 -6
  26. package/bin/engine/temporal-cli.js +4 -2
  27. package/bin/engine/verification-runner.js +131 -0
  28. package/bin/engine/verify-cli.js +34 -0
  29. package/bin/eval/eval-harness.js +82 -0
  30. package/bin/eval/golden-set-retrieval.json +46 -0
  31. package/bin/governance/audit-hash.js +12 -0
  32. package/bin/governance/audit-verifier.js +60 -0
  33. package/bin/governance/policy-engine.js +17 -4
  34. package/bin/governance/quantum-crypto.js +63 -9
  35. package/bin/governance/ztai-archiver.js +74 -9
  36. package/bin/governance/ztai-manager.js +33 -5
  37. package/bin/hindsight-injector.js +5 -6
  38. package/bin/hooks/instinct-capture-hook.js +186 -0
  39. package/bin/installer-core.js +31 -2
  40. package/bin/memory/auto-shadow.js +32 -3
  41. package/bin/memory/eis-client.js +45 -4
  42. package/bin/memory/identity-synthesizer.js +2 -2
  43. package/bin/memory/knowledge-store.js +30 -6
  44. package/bin/memory/retrieval-fusion.js +58 -0
  45. package/bin/memory/semantic-hub.js +2 -2
  46. package/bin/memory/vector-hub.js +143 -6
  47. package/bin/mindforge-cli.js +4 -5
  48. package/bin/models/anthropic-provider.js +13 -4
  49. package/bin/models/cost-tracker.js +3 -1
  50. package/bin/models/difficulty-scorer.js +54 -0
  51. package/bin/models/gemini-provider.js +6 -2
  52. package/bin/models/model-router.js +31 -18
  53. package/bin/models/openai-provider.js +6 -3
  54. package/bin/models/pricing-registry.js +128 -0
  55. package/bin/review/ads-engine.js +1 -1
  56. package/bin/review/finding-synthesizer.js +35 -6
  57. package/bin/security/trust-boundaries.js +194 -0
  58. package/bin/security/trust-gate-hook.js +49 -0
  59. package/bin/skill-registry.js +34 -22
  60. package/bin/skills-builder/marketplace-cli.js +5 -3
  61. package/bin/skills-builder/skill-registrar.js +4 -6
  62. package/bin/sre/sentinel.js +7 -5
  63. package/bin/sre/shadow-mirror.js +90 -40
  64. package/bin/utils/append-queue.js +67 -0
  65. package/bin/utils/file-io.js +29 -80
  66. package/bin/utils/version-check.js +75 -0
  67. package/bin/verify-audit.js +12 -0
  68. package/bin/wizard/theme.js +1 -2
  69. package/package.json +1 -1
  70. package/bin/dashboard/team-tracker.js +0 -0
@@ -1,67 +1,197 @@
1
1
  /**
2
2
  * MindForge v7 — Neural Drift Remediation (NDR)
3
3
  * Component: Logic Validator
4
- *
4
+ *
5
5
  * Performs high-level semantic validation on agent reasoning traces.
6
- * Supports Local Model (Ollama) integration and Self-Reflective Heuristics.
6
+ *
7
+ * Strategy: real-when-available, else honest heuristic.
8
+ * - By DEFAULT this validator uses a local Self-Reflective Heuristic
9
+ * (`_reflectiveHeuristic`). This is the standard path and runs everywhere,
10
+ * with no external dependency.
11
+ * - OPTIONALLY, if a local Ollama model is actually reachable at the
12
+ * configured endpoint, validation is upgraded to a real model call
13
+ * (`_modelValidation`). Reachability is determined by a real, fail-fast
14
+ * network probe — never a hardcoded flag. When Ollama is absent (the
15
+ * normal case) the probe fails fast and we fall back to the heuristic.
16
+ *
17
+ * The return shape is stable: { is_valid, confidence, critique, method }.
18
+ * Consumers (nexus-tracer) read `is_valid` and `critique`.
7
19
  */
8
20
  'use strict';
9
21
 
10
22
  const configManager = require('../governance/config-manager');
11
23
 
24
+ // Fail-fast budget for the reachability probe and the model call. Ollama is
25
+ // usually absent, so this must time out quickly to avoid hanging CI/production.
26
+ const PROBE_TIMEOUT_MS = 400;
27
+ const MODEL_TIMEOUT_MS = 4000;
28
+
12
29
  class LogicValidator {
13
30
  constructor() {
14
31
  this.endpoint = configManager.get('governance.local_model_endpoint', 'localhost:11434');
15
- this.isModelAvailable = false; // Simulated check result
32
+ this.model = configManager.get('governance.local_model_name', 'llama3');
33
+ // Reflects reality: set by probeModel(), not hardcoded. Unknown until probed.
34
+ this.isModelAvailable = false;
35
+ this._probed = false;
36
+ }
37
+
38
+ /**
39
+ * Normalises the configured endpoint into a base URL (adds scheme if absent).
40
+ * @returns {string}
41
+ */
42
+ _baseUrl() {
43
+ const ep = String(this.endpoint || 'localhost:11434').trim();
44
+ return /^https?:\/\//i.test(ep) ? ep.replace(/\/+$/, '') : `http://${ep.replace(/\/+$/, '')}`;
45
+ }
46
+
47
+ /**
48
+ * Resets cached probe state (used by tests to re-probe after changing endpoint).
49
+ */
50
+ resetProbe() {
51
+ this._probed = false;
52
+ this.isModelAvailable = false;
53
+ }
54
+
55
+ /**
56
+ * Real, fail-fast reachability check for a local Ollama instance.
57
+ * Performs a short GET to the Ollama tags endpoint. On ANY error or timeout
58
+ * (the normal case when Ollama is absent) it resolves `false` — never throws,
59
+ * never hangs. Sets `this.isModelAvailable` from the actual result.
60
+ * @returns {Promise<boolean>}
61
+ */
62
+ async probeModel() {
63
+ let reachable = false;
64
+ try {
65
+ const res = await fetch(`${this._baseUrl()}/api/tags`, {
66
+ method: 'GET',
67
+ signal: AbortSignal.timeout(PROBE_TIMEOUT_MS)
68
+ });
69
+ reachable = res.ok;
70
+ } catch {
71
+ // ECONNREFUSED / timeout / DNS / abort — Ollama not reachable. Stay quiet.
72
+ reachable = false;
73
+ }
74
+ this.isModelAvailable = reachable;
75
+ this._probed = true;
76
+ return reachable;
16
77
  }
17
78
 
18
79
  /**
19
80
  * Validates a reasoning trace using the best available method.
81
+ * Probes for a local model on first call (lazy); falls back to the heuristic
82
+ * when unreachable.
20
83
  * @param {string} thought - The agent's thought string
21
84
  * @param {Object} context - Optional metadata (span attributes, etc.)
22
85
  */
23
86
  async validate(thought, context = {}) {
24
- console.log(`[LogicValidator] Validating trace segment (Length: ${thought.length})`);
87
+ const spanTag = context && context.span_id ? ` span=${context.span_id}` : '';
88
+ console.log(`[LogicValidator] Validating trace segment (Length: ${thought.length})${spanTag}`);
89
+
90
+ if (!this._probed) {
91
+ await this.probeModel();
92
+ }
25
93
 
26
- // In a real v7 deployment, we would perform an asynchronous fetch to Ollama/Llama-CPP
27
- // For this simulation, we simulate a "Reflective Heuristic" analysis.
28
-
29
94
  if (this.isModelAvailable) {
30
- return this._modelValidation(thought, context);
31
- } else {
32
- return this._reflectiveHeuristic(thought, context);
95
+ try {
96
+ return await this._modelValidation(thought);
97
+ } catch {
98
+ // Model became unreachable mid-flight — degrade honestly to heuristic.
99
+ this.isModelAvailable = false;
100
+ return this._reflectiveHeuristic(thought);
101
+ }
33
102
  }
103
+ return this._reflectiveHeuristic(thought);
34
104
  }
35
105
 
36
106
  /**
37
- * Simulated Local Model Validation logic.
107
+ * Real Local Model Validation via Ollama's /api/generate.
108
+ * Asks the model whether the thought is logical and grounded, then derives a
109
+ * real is_valid/confidence from the response — no fabricated fixed values.
38
110
  */
39
- async _modelValidation(thought, context) {
40
- // Mocking an LLM callback: "Is this thought logical and grounded?"
41
- const result = {
42
- is_valid: true,
43
- confidence: 0.98,
44
- critique: 'Logic is consistent with project goals.',
45
- method: 'Ollama/Llama-3-8B'
111
+ async _modelValidation(thought) {
112
+ const prompt =
113
+ 'You are a reasoning-trace auditor. Decide whether the following agent ' +
114
+ 'thought is logical and grounded (consistent, on-task, no self-contradiction).\n' +
115
+ 'Reply with ONLY a JSON object: {"valid": <true|false>, "confidence": <0..1>, ' +
116
+ '"critique": "<short reason>"}.\n\n' +
117
+ `Thought: """${thought}"""`;
118
+
119
+ const res = await fetch(`${this._baseUrl()}/api/generate`, {
120
+ method: 'POST',
121
+ headers: { 'Content-Type': 'application/json' },
122
+ body: JSON.stringify({ model: this.model, prompt, stream: false }),
123
+ signal: AbortSignal.timeout(MODEL_TIMEOUT_MS)
124
+ });
125
+
126
+ if (!res.ok) {
127
+ throw new Error(`Ollama responded ${res.status}`);
128
+ }
129
+
130
+ const payload = await res.json();
131
+ const parsed = this._parseModelResponse(payload && payload.response);
132
+
133
+ return {
134
+ is_valid: parsed.valid,
135
+ confidence: parsed.confidence,
136
+ critique: parsed.critique,
137
+ method: `ollama:${this.model}`
138
+ };
139
+ }
140
+
141
+ /**
142
+ * Robustly parses the model's textual response into a verdict. Falls back to
143
+ * conservative defaults derived from the raw text when JSON is unavailable —
144
+ * never invents a fixed high-confidence pass.
145
+ * @param {string} raw
146
+ */
147
+ _parseModelResponse(raw) {
148
+ const text = String(raw || '');
149
+ const match = text.match(/\{[\s\S]*\}/);
150
+ if (match) {
151
+ try {
152
+ const obj = JSON.parse(match[0]);
153
+ const valid = obj.valid === true || obj.valid === 'true';
154
+ let confidence = Number(obj.confidence);
155
+ if (!Number.isFinite(confidence)) confidence = valid ? 0.6 : 0.4;
156
+ confidence = Math.min(1, Math.max(0, confidence));
157
+ const critique = typeof obj.critique === 'string' && obj.critique.trim()
158
+ ? obj.critique.trim()
159
+ : (valid ? 'Model judged the thought logical and grounded.'
160
+ : 'Model flagged the thought as illogical or ungrounded.');
161
+ return { valid, confidence, critique };
162
+ } catch {
163
+ // fall through to text heuristic below
164
+ }
165
+ }
166
+
167
+ // No parseable JSON: derive a conservative verdict from the raw text.
168
+ const lowered = text.toLowerCase();
169
+ const valid = !/(invalid|illogical|not\s+grounded|inconsistent|"valid"\s*:\s*false)/.test(lowered)
170
+ && /(valid|logical|grounded|consistent)/.test(lowered);
171
+ return {
172
+ valid,
173
+ confidence: valid ? 0.55 : 0.45,
174
+ critique: 'Model response was unstructured; verdict derived from text.'
46
175
  };
47
- return result;
48
176
  }
49
177
 
50
178
  /**
51
- * Advanced "Reflective Heuristic" which is more intensive than the DriftDetector.
179
+ * Local Self-Reflective Heuristic the default validation path. More
180
+ * intensive than the DriftDetector; uses self-doubt and goal-misalignment
181
+ * markers. Honestly labelled as a heuristic (no model is involved here).
52
182
  */
53
- async _reflectiveHeuristic(thought, context) {
54
- const t = thought.toLowerCase();
55
-
183
+ async _reflectiveHeuristic(thought) {
184
+ const t = String(thought || '').toLowerCase();
185
+
56
186
  // Check for "Self-Doubt" markers that might indicate drift
57
187
  const doubtMarkers = ['i am not sure', 'maybe i should wait', 'actually, i forgot', 'i will instead try to just'];
58
188
  const doubtCount = doubtMarkers.filter(m => t.includes(m)).length;
59
189
 
60
- // Check for "Goal Misalignment" (Simulated)
190
+ // Check for "Goal Misalignment"
61
191
  const goalMismatch = t.includes('ignoring current goal') || t.includes('outside scope');
62
192
 
63
193
  const score = 1.0 - (doubtCount * 0.2) - (goalMismatch ? 0.5 : 0);
64
-
194
+
65
195
  return {
66
196
  is_valid: score > 0.6,
67
197
  confidence: parseFloat(score.toFixed(2)),
@@ -35,26 +35,43 @@ class OrbitalGuardian {
35
35
  throw new Error(`[ORBITAL-GUARDIAN] DID ${did} has insufficient Trust Tier for Orbital Attestation.`);
36
36
  }
37
37
 
38
- // 1. Sign the attestation payload using the Hardware Enclave provider
39
- const attestationPayload = await ztaiManager.signData(did, JSON.stringify({
38
+ // 1. Build the EXACT canonical message and sign it with the agent's key.
39
+ // UC-22: this canonical string is persisted verbatim alongside the DID so
40
+ // verify() can re-verify the signature later. We must store the precise
41
+ // bytes that were signed — recomputing them (e.g. with a fresh timestamp)
42
+ // would never verify — so capture the message once, here, and reuse it.
43
+ const signedMessage = JSON.stringify({
40
44
  requestId,
41
45
  payload,
42
46
  timestamp: new Date().toISOString()
43
- }));
47
+ });
48
+ const signature = await ztaiManager.signData(did, signedMessage);
44
49
 
45
50
  const attestation = {
46
51
  id: `att_${crypto.randomBytes(4).toString('hex')}`,
47
52
  request_id: requestId,
48
53
  status: 'APPROVED',
49
- attestation_payload: attestationPayload,
54
+ did,
55
+ signed_message: signedMessage,
56
+ attestation_payload: signature,
50
57
  timestamp: new Date().toISOString()
51
58
  };
52
59
 
53
- // 2. Persist to SQLite (Source of truth for v8 Governance Dashboard)
60
+ // 2. Persist to SQLite (Source of truth for v8 Governance Dashboard).
61
+ // did + signed_message + signature together let verify() re-check the
62
+ // cryptographic signature; status='APPROVED' alone is NOT trusted.
54
63
  vectorHub.run(
55
- `INSERT INTO attestations (id, request_id, status, attestation_payload, timestamp)
56
- VALUES (?, ?, ?, ?, ?)`,
57
- [attestation.id, attestation.request_id, attestation.status, attestation.attestation_payload, attestation.timestamp]
64
+ `INSERT INTO attestations (id, request_id, status, did, signed_message, attestation_payload, timestamp)
65
+ VALUES (?, ?, ?, ?, ?, ?, ?)`,
66
+ [
67
+ attestation.id,
68
+ attestation.request_id,
69
+ attestation.status,
70
+ attestation.did,
71
+ attestation.signed_message,
72
+ attestation.attestation_payload,
73
+ attestation.timestamp
74
+ ]
58
75
  );
59
76
 
60
77
  console.log(`[ORBITAL-GUARDIAN] Attestation SUCCESS: ${attestation.id}`);
@@ -63,9 +80,16 @@ class OrbitalGuardian {
63
80
 
64
81
  /**
65
82
  * Verifies if a request has a valid hardware bypass.
83
+ *
84
+ * UC-22 (audit finding #2): an APPROVED row is NOT trusted on its own. The
85
+ * stored signature is re-verified against the signer's registered public key
86
+ * over the EXACT canonical message that attest() signed. Anyone who forges an
87
+ * APPROVED row but cannot produce a valid signature is rejected. The check is
88
+ * fail-closed: a missing field, an unregistered/revoked DID, or any thrown
89
+ * error all resolve to { verified:false }.
66
90
  */
67
91
  async verify(requestId) {
68
- if (!requestId) return { verified: false };
92
+ if (!requestId) return { verified: false, reason: 'missing requestId' };
69
93
  await this.ensureInit();
70
94
 
71
95
  const results = vectorHub.query(
@@ -74,7 +98,29 @@ class OrbitalGuardian {
74
98
  );
75
99
 
76
100
  const record = results[0];
77
- if (!record) return { verified: false };
101
+ if (!record) return { verified: false, reason: 'no APPROVED attestation found' };
102
+
103
+ // Re-verify the cryptographic signature. Without a DID, the canonical signed
104
+ // message, AND a signature we cannot prove the row was produced by attest().
105
+ if (!record.did || !record.signed_message || !record.attestation_payload) {
106
+ return { verified: false, reason: 'attestation missing signature material' };
107
+ }
108
+
109
+ let signatureValid = false;
110
+ try {
111
+ signatureValid = ztaiManager.verifySignature(
112
+ record.did,
113
+ record.signed_message,
114
+ record.attestation_payload
115
+ );
116
+ } catch (err) {
117
+ // Unregistered/revoked DID or malformed signature → fail closed.
118
+ return { verified: false, reason: `signature verification error: ${err.message}` };
119
+ }
120
+
121
+ if (!signatureValid) {
122
+ return { verified: false, reason: 'signature verification failed' };
123
+ }
78
124
 
79
125
  return {
80
126
  verified: true,
@@ -0,0 +1,123 @@
1
+ 'use strict';
2
+ /**
3
+ * MindForge — OTel GenAI Exporter (UC-18).
4
+ * Translates NexusTracer spans to OpenTelemetry GenAI semantic conventions.
5
+ * Active only when OTEL_EXPORTER_OTLP_ENDPOINT is set.
6
+ *
7
+ * NexusTracer span shape (from nexus-tracer.js startSpan/endSpan):
8
+ * {
9
+ * id: 'sp_<hex>',
10
+ * trace_id: 'tr_<hex>',
11
+ * parent_id: string|null,
12
+ * name: string,
13
+ * status: 'active'|'success'|'error',
14
+ * start_time: ISO-8601,
15
+ * end_time: ISO-8601,
16
+ * attributes: {
17
+ * service: string,
18
+ * host: string,
19
+ * pid: number,
20
+ * model_id?: string,
21
+ * skill?: string,
22
+ * input_tokens?: number,
23
+ * output_tokens?: number,
24
+ * ...
25
+ * }
26
+ * }
27
+ *
28
+ * Mapping to OTel GenAI semantic conventions:
29
+ * span.name → name
30
+ * span.attributes.model_id → gen_ai.request.model, gen_ai.response.model
31
+ * span.attributes.input_tokens → gen_ai.usage.input_tokens
32
+ * span.attributes.output_tokens → gen_ai.usage.output_tokens
33
+ * span.name → gen_ai.operation.name
34
+ * 'mindforge' → gen_ai.system (or span.attributes.provider if present)
35
+ */
36
+
37
+ const crypto = require('crypto');
38
+
39
+ /**
40
+ * Check if the OTel exporter is enabled (env var gate).
41
+ * @returns {boolean}
42
+ */
43
+ function isEnabled() {
44
+ return !!process.env.OTEL_EXPORTER_OTLP_ENDPOINT;
45
+ }
46
+
47
+ /**
48
+ * Translate a NexusTracer span to OTel GenAI-compatible format.
49
+ * Produces a valid 16-byte hex traceId and 8-byte hex spanId.
50
+ *
51
+ * @param {object} nexusSpan - A span object from NexusTracer
52
+ * @returns {object} OTel-compatible span object
53
+ */
54
+ function toOtelSpan(nexusSpan) {
55
+ const attrs = nexusSpan.attributes || {};
56
+
57
+ return {
58
+ traceId: crypto.randomBytes(16).toString('hex'),
59
+ spanId: crypto.randomBytes(8).toString('hex'),
60
+ parentSpanId: nexusSpan.parent_id || '',
61
+ name: nexusSpan.name || 'unknown',
62
+ kind: 1, // SPAN_KIND_INTERNAL
63
+ startTimeUnixNano: nexusSpan.start_time
64
+ ? BigInt(new Date(nexusSpan.start_time).getTime()) * 1_000_000n
65
+ : 0n,
66
+ endTimeUnixNano: nexusSpan.end_time
67
+ ? BigInt(new Date(nexusSpan.end_time).getTime()) * 1_000_000n
68
+ : 0n,
69
+ status: nexusSpan.status === 'success' ? { code: 1 } : { code: 2 },
70
+ attributes: {
71
+ 'gen_ai.system': attrs.provider || 'mindforge',
72
+ 'gen_ai.request.model': attrs.model_id || '',
73
+ 'gen_ai.response.model': attrs.model_id || '',
74
+ 'gen_ai.usage.input_tokens': attrs.input_tokens || 0,
75
+ 'gen_ai.usage.output_tokens': attrs.output_tokens || 0,
76
+ 'gen_ai.operation.name': nexusSpan.name || '',
77
+ 'service.name': attrs.service || 'mindforge-nexus',
78
+ },
79
+ };
80
+ }
81
+
82
+ /**
83
+ * Serialize BigInt values to strings for JSON compatibility.
84
+ * @param {object} otelSpan
85
+ * @returns {object}
86
+ */
87
+ function toJsonSafe(otelSpan) {
88
+ return {
89
+ ...otelSpan,
90
+ startTimeUnixNano: String(otelSpan.startTimeUnixNano),
91
+ endTimeUnixNano: String(otelSpan.endTimeUnixNano),
92
+ };
93
+ }
94
+
95
+ /**
96
+ * Export a NexusTracer span to the OTel-compatible local file.
97
+ * In production, this would POST to OTEL_EXPORTER_OTLP_ENDPOINT/v1/traces.
98
+ * For now, appends to .mindforge/metrics/otel-spans.jsonl for verification.
99
+ *
100
+ * @param {object} nexusSpan - A span from NexusTracer
101
+ */
102
+ async function exportSpan(nexusSpan) {
103
+ if (!isEnabled()) return;
104
+
105
+ const otelSpan = toOtelSpan(nexusSpan);
106
+ const jsonSafe = toJsonSafe(otelSpan);
107
+
108
+ const fs = require('fs');
109
+ const path = require('path');
110
+ const outPath = path.join(process.cwd(), '.mindforge', 'metrics', 'otel-spans.jsonl');
111
+
112
+ try {
113
+ const dir = path.dirname(outPath);
114
+ if (!fs.existsSync(dir)) {
115
+ fs.mkdirSync(dir, { recursive: true });
116
+ }
117
+ fs.appendFileSync(outPath, JSON.stringify(jsonSafe) + '\n');
118
+ } catch {
119
+ // Non-fatal: observability export should never break the main flow
120
+ }
121
+ }
122
+
123
+ module.exports = { isEnabled, toOtelSpan, toJsonSafe, exportSpan };
@@ -45,7 +45,17 @@ class ReasonSourceAligner {
45
45
  * @returns {Object} - Alignment results.
46
46
  */
47
47
  checkAlignment(thought) {
48
- if (!this.initialized) return { score: 1.0, reason: 'uninitialized' }; // Fail-safe stable
48
+ // Fail-safe stable: when no requirements are loaded we CANNOT assess
49
+ // alignment, so we honestly decline rather than assert perfect alignment.
50
+ // Returning the SAME shape as the normal branch means the sole caller
51
+ // (auto-runner.checkMissionFidelity) reads a real boolean instead of
52
+ // `undefined`, so the mission-fidelity gate is no longer silently disabled.
53
+ // is_aligned:false is the safe direction — the caller only injects a
54
+ // correction when is_aligned is truthy, so an honest "can't assess" simply
55
+ // does nothing (no false correction, no silent shape mismatch).
56
+ if (!this.initialized) {
57
+ return { is_aligned: false, best_match_id: null, confidence: 0, status: 'uninitialized' };
58
+ }
49
59
 
50
60
  const alignmentScores = this.registry.map(req => {
51
61
  const score = this._calculateSimilarity(thought, req.summary + ' ' + req.description);
@@ -58,6 +68,7 @@ class ReasonSourceAligner {
58
68
  is_aligned: bestMatch ? bestMatch.score > 0.25 : false, // Sparse mapping allowed
59
69
  best_match_id: bestMatch ? bestMatch.id : null,
60
70
  confidence: bestMatch ? parseFloat(bestMatch.score.toFixed(4)) : 0,
71
+ status: 'assessed',
61
72
  };
62
73
  }
63
74
 
@@ -82,19 +93,21 @@ class ReasonSourceAligner {
82
93
  }
83
94
 
84
95
  /**
85
- * Similarity Heuristic (Keyword-based overlap)
96
+ * Keyword-based overlap heuristic (Jaccard similarity).
97
+ * NOTE: This is a token-overlap heuristic, NOT semantic embeddings.
98
+ * Returns |A ∩ B| / |A ∪ B| in [0, 1].
86
99
  */
87
100
  _calculateSimilarity(a, b) {
88
101
  const getTokens = (str) => new Set(str.toLowerCase().replace(/[^\w\s]/g, '').split(/\s+/).filter(t => t.length > 3));
89
102
  const tokensA = getTokens(a);
90
103
  const tokensB = getTokens(b);
91
-
104
+
92
105
  if (tokensA.size === 0 || tokensB.size === 0) return 0;
93
-
106
+
94
107
  const intersection = new Set([...tokensA].filter(x => tokensB.has(x)));
95
108
  const union = new Set([...tokensA, ...tokensB]);
96
-
97
- return intersection.size / tokensA.size; // Weighted by thought coverage
109
+
110
+ return intersection.size / union.size; // Jaccard: overlap over combined vocabulary
98
111
  }
99
112
 
100
113
  /**
@@ -1,5 +1,5 @@
1
1
  /**
2
- * MindForge v11.0.0 — Neural Drift Remediation (NDR)
2
+ * MindForge v11.2.0 — Neural Drift Remediation (NDR)
3
3
  * Component: Remediation Engine (Pillar X)
4
4
  *
5
5
  * Triggers corrective actions when logic drift or reasoning
@@ -1,5 +1,5 @@
1
1
  /**
2
- * MindForge v11.0.0 — Self-Corrective Synthesis (SCS)
2
+ * MindForge v11.2.0 — Self-Corrective Synthesis (SCS)
3
3
  * Component: Self-Corrective Synthesizer (Pillar XII)
4
4
  *
5
5
  * Analyzes mission drift and logic stagnation to synthesize
@@ -47,12 +47,22 @@ class SREManager {
47
47
  }
48
48
 
49
49
  /**
50
- * Sanitizes a thought chain and generates a ZK-Proof Compliance Certificate.
51
- * Ensures that sensitive IP or "zero-visibility" thoughts are isolated while proving audit-eligibility.
50
+ * Sanitizes a thought chain and generates an HMAC integrity certificate.
51
+ *
52
+ * IMPORTANT — HONEST LABELING: This is NOT a zero-knowledge proof. The
53
+ * artifact is an HMAC-SHA256 tag computed with a process-local shared secret
54
+ * (EPHEMERAL_ENCLAVE_KEY). It provides tamper-evidence/integrity over the
55
+ * proof payload, but:
56
+ * - any party holding the key can forge it (symmetric MAC, not asymmetric),
57
+ * - the payload carries the plaintext sha256(thoughtChain) digest, so it is
58
+ * not "zero-visibility".
59
+ * The enclave is simulated (no hardware TEE). Consumers must treat the
60
+ * returned object as an integrity tag, not a cryptographic ZK proof.
61
+ *
52
62
  * @param {string} thoughtChain - The raw agentic thought chain.
53
63
  * @param {string} enclaveId - The active enclave ID.
54
64
  * @param {Object} policyResult - Whether the content passed internal policy checks.
55
- * @returns {Object} - ZK-Proof compliance certificate.
65
+ * @returns {Object} - HMAC integrity certificate (simulated enclave).
56
66
  */
57
67
  sanitizeThoughtChain(thoughtChain, enclaveId, policyResult = { passed: true }) {
58
68
  if (!this.activeEnclaves.has(enclaveId)) {
@@ -64,7 +74,7 @@ class SREManager {
64
74
  const prevHash = enclaveData.cumulativeHash;
65
75
  const digest = crypto.createHash('sha256').update(thoughtChain).digest('hex');
66
76
 
67
- // Generate a simulated ZK-Proof Compliance Certificate
77
+ // Generate a simulated-enclave HMAC integrity certificate (NOT a ZK proof)
68
78
  const proofPayload = {
69
79
  enclaveId: enclaveId,
70
80
  digest: digest,
@@ -85,19 +95,36 @@ class SREManager {
85
95
 
86
96
  const certificate = {
87
97
  status: 'SRE-ISOLATED',
98
+ // Honest labeling: this is a symmetric HMAC integrity tag, not a ZK proof.
99
+ type: 'hmac-integrity-certificate',
100
+ method: 'hmac-sha256-integrity',
101
+ simulated: true,
102
+ zeroKnowledge: false,
103
+ disclosure: 'HMAC integrity tag (simulated enclave; NOT a zero-knowledge proof). '
104
+ + 'Forgeable by any holder of the shared enclave key; payload carries the plaintext sha256(thought) digest.',
88
105
  proof: proofPayload,
89
106
  signature: signature,
90
107
  proofHash: proofHash,
91
108
  verificationDid: SYSTEM_DID,
92
- message: `[SRE-ZK-PROOF] Confidential reasoning (sha256:${digest.substring(0, 8)}...) verified by Enclave Auditor.`
109
+ message: `[SRE-HMAC] HMAC integrity tag for confidential reasoning (sha256:${digest.substring(0, 8)}...) `
110
+ + 'in simulated enclave — NOT a zero-knowledge proof.'
93
111
  };
94
112
 
95
113
  return certificate;
96
114
  }
97
115
 
98
116
  /**
99
- * Verifies an SRE Compliance Certificate without seeing the original content.
117
+ * Verifies an SRE integrity certificate's HMAC tag and policy flag.
118
+ *
119
+ * NOTE — HONEST LABELING: this recomputes the HMAC-SHA256 tag using the
120
+ * shared enclave key and compares it. It is symmetric MAC verification, NOT
121
+ * zero-knowledge verification. The method name is retained for API
122
+ * compatibility with existing callers; see verifyIntegrityCertificate alias.
100
123
  */
124
+ verifyIntegrityCertificate(certificate) {
125
+ return this.verifyZKProof(certificate);
126
+ }
127
+
101
128
  verifyZKProof(certificate) {
102
129
  if (certificate.status !== 'SRE-ISOLATED') return false;
103
130
 
@@ -12,7 +12,7 @@ const SUBCOMMAND = ARGS[0];
12
12
 
13
13
  async function main() {
14
14
  switch (SUBCOMMAND) {
15
- case 'status':
15
+ case 'status': {
16
16
  const history = TemporalHub.getHistory();
17
17
  console.log('\n⏳ MindForge Temporal Status');
18
18
  console.log(` Snapshots: ${history.length}`);
@@ -20,6 +20,7 @@ async function main() {
20
20
  console.log(` Latest: ${history[0].id} (${history[0].timestamp})`);
21
21
  }
22
22
  break;
23
+ }
23
24
 
24
25
  case 'cleanup':
25
26
  console.log('🧹 Cleaning up old temporal snapshots...');
@@ -27,7 +28,7 @@ async function main() {
27
28
  console.log('✅ Cleanup complete.');
28
29
  break;
29
30
 
30
- case 'inject':
31
+ case 'inject': {
31
32
  const auditId = ARGS[1];
32
33
  const fix = ARGS.slice(2).join(' ');
33
34
  if (!auditId || !fix) {
@@ -42,6 +43,7 @@ async function main() {
42
43
  process.exit(1);
43
44
  }
44
45
  break;
46
+ }
45
47
 
46
48
  default:
47
49
  console.log('Usage: /mindforge:temporal <status|cleanup|inject>');