mindforge-cc 5.3.0 → 5.6.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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,51 @@
1
1
  # Changelog
2
2
 
3
+ ## [5.6.0] - 2026-03-28
4
+ ### Added
5
+ - **Pillar IV: Supply Chain Trust (Binary Runtime Attestation)**.
6
+ - Cryptographic skill signing in `SkillRegistry` via ZTAIManager Tier 3 Enclaves.
7
+ - JIT Attestation in `SkillValidator` to verify skill integrity before agent execution.
8
+ - `SIGNATURES.json` tracking for all enterprise-grade skills.
9
+
10
+ ## [5.5.0] - 2026-03-28
11
+ ### Added
12
+ - **Pillar III: Predictive Agentic Reliability (Reasoning Entropy Monitoring)**.
13
+ - Reasoning Entropy Scoring (RES) in `NexusTracer` to detect semantic stagnation and loops.
14
+ - Proactive Self-Healing trigger for high-similarity thought sequences.
15
+ - Steering Vector generation in `TemporalHindsight` to break agentic deadlocks.
16
+
17
+ ## [5.4.0] — Beast Mode Hardening — 2026-03-28
18
+
19
+ # Release Notes - MindForge v5.6.0 "Sentinel Execution"
20
+
21
+ MindForge v5.6.0 introduces the final pillars of the Hyper-Enterprise roadmap: Proactive Reliability and Zero-Trust Skill Execution.
22
+
23
+ ## Highlights
24
+ - **Reasoning Entropy Monitoring (PAR)**: Proactively prevents token-burning reasoning loops.
25
+ - **Binary Runtime Attestation (ZTS)**: Cryptographically ensures that skills have not been tampered with before they are loaded by the agent.
26
+
27
+ ---
28
+
29
+ ## [5.6.0] - Sentinel Execution
30
+ - Implemented JIT Attestation for Skill Registry.
31
+ - Added Skill Signing utility in `mindforge-cc sign`.
32
+
33
+ ## [5.5.0] - Predictive Reliability
34
+ - Implemented RES (Reasoning Entropy Scoring) in Nexus Tracer.
35
+ - Added Steering Vector injection for proactive loop breaking.
36
+
37
+ 🚀 **MindForge v5.4.0 — Enterprise Resilience (Hardened Edition)**
38
+
39
+ This update elevates the v5.3.0 "Hyper-Enterprise" features to maximum robustness ("Beast Mode"), implementing critical safety systems and advanced observability.
40
+
41
+ ### 🛡️ Beast Mode Hardening (v5.4.0)
42
+
43
+ - **Circuit Breaker Pattern**: Implemented a stateful `CircuitBreaker` in `federated-sync.js` to prevent network floods. Automatically disables mesh sync for 1 hour after 3 consecutive EIS failures.
44
+ - **Critical-Path Protection**: Automated "Blast Radius" score of 100 in `impact-analyzer.js` for sensitive files (`.env`, `*.pem`, `id_rsa`, `package-lock.json`, etc.).
45
+ - **Recursive Depth Penalty**: Introduced a 1.5x impact multiplier for actions deeper than 5 directory levels, preventing mass-scale silent modifications.
46
+ - **Failure Telemetry**: Added `sync-history.jsonl` and `sync-telemetry.jsonl` for detailed conflict resolution and error auditability.
47
+ - **Resilient Execution**: Raised default scores for `EXECUTE` and `GRANT` actions to increase governance oversight.
48
+
3
49
  ## [5.3.0] — Dynamic Blast Radius — 2026-03-28
4
50
 
5
51
  🚀 **MindForge v5.3.0 — Pillar II Implementation (APO v2)**
package/RELEASENOTES.md CHANGED
@@ -1,3 +1,15 @@
1
+ # MindForge v5.4.0 — Beast Mode Hardening
2
+ ## Top Summary
3
+ The v5.4.0 release elevates the "Hyper-Enterprise" features to maximum robustness ("Beast Mode"), implementing critical safety systems, automated blast-radius protection for sensitive files, and advanced failure telemetry.
4
+
5
+ ## Highlights
6
+ - **Circuit Breaker Pattern**: Stateful resilience in `federated-sync.js` to prevent network floods during outages.
7
+ - **Critical-Path Protection**: Automated "Blast Radius" score of 100 for high-risk files (secrets, locks, audits).
8
+ - **Depth-Aware Governance**: 1.5x impact multiplier for deep directory modifications to prevent mass-scale silent regressions.
9
+ - **Enhanced Observability**: Detailed conflict resolution and sync telemetry logs for enterprise auditing.
10
+
11
+ ---
12
+
1
13
  # MindForge v5.3.0 — Dynamic Blast Radius
2
14
  ## Top Summary
3
15
  The v5.3.0 release introduces real-time impact analysis and automated risk-based guardrails for agentic actions, preventing architectural regressions and accidental deletions.
@@ -21,6 +21,10 @@ class NexusTracer {
21
21
  this.enableZtai = config.enableZtai !== false;
22
22
  this.sreManager = new SREManager();
23
23
 
24
+ // v5 Pillar III: Reasoning Entropy Monitoring (RES)
25
+ this.RES_THRESHOLD = 0.8; // Similarity threshold for stagnation
26
+ this.entropyCache = new Map(); // spanId -> [thoughtHistories]
27
+
24
28
  // v5 Pillar IV: Agentic SBOM
25
29
  this.sbom = {
26
30
  manifest_version: '1.0.0',
@@ -123,12 +127,74 @@ class NexusTracer {
123
127
  sanitizedThought = this.sreManager.sanitizeThoughtChain(thought, span.attributes.enclave_id);
124
128
  }
125
129
 
130
+ // v5 Pillar III: PES (Proactive Equilibrium Scoring)
131
+ const entropy = this.calculateEntropy(spanId, sanitizedThought);
132
+ const isStagnant = entropy > this.RES_THRESHOLD;
133
+
126
134
  this._recordEvent('reasoning_trace', {
127
135
  span_id: spanId,
128
136
  agent,
129
137
  thought: sanitizedThought,
130
- resolution
138
+ resolution,
139
+ entropy: parseFloat(entropy.toFixed(4)),
140
+ is_stagnant: isStagnant
131
141
  });
142
+
143
+ if (isStagnant) {
144
+ const history = this.entropyCache.get(spanId) || [];
145
+ const stagnationCount = history.filter(h => h.entropy > this.RES_THRESHOLD).length;
146
+
147
+ if (stagnationCount >= 3) {
148
+ this._recordEvent('vulnerability_detected', {
149
+ span_id: spanId,
150
+ type: 'REASONING_LOOP',
151
+ severity: 'HIGH',
152
+ description: 'Agent reasoning entropy dropped below threshold (stagnation detected). Triggering proactive RCA.',
153
+ entropy_score: entropy
154
+ });
155
+
156
+ // Signal proactive recovery
157
+ this.recordSelfHeal(spanId, {
158
+ type: 'PROACTIVE_RCA',
159
+ cause: 'REASONING_STAGNATION',
160
+ suggestion: 'Entropy threshold exceeded. Switch reasoning strategy.'
161
+ });
162
+ }
163
+ }
164
+ }
165
+
166
+ /**
167
+ * Calculates "Reasoning Entropy" (Similarity to previous thoughts).
168
+ * Range 0.0 (High Entropy/New) to 1.0 (Low Entropy/Repetitive).
169
+ */
170
+ calculateEntropy(spanId, currentThought) {
171
+ if (!this.entropyCache.has(spanId)) {
172
+ this.entropyCache.set(spanId, []);
173
+ }
174
+ const history = this.entropyCache.get(spanId);
175
+
176
+ if (history.length === 0) {
177
+ history.push({ thought: currentThought, entropy: 0 });
178
+ return 0;
179
+ }
180
+
181
+ // Simple Jaccard Similarity approach for stagnation detection
182
+ const getTokens = (str) => new Set(str.toLowerCase().split(/\s+/).filter(t => t.length > 3));
183
+ const currentTokens = getTokens(currentThought);
184
+
185
+ let maxSimilarity = 0;
186
+ for (const prev of history) {
187
+ const prevTokens = getTokens(prev.thought);
188
+ const intersection = new Set([...currentTokens].filter(x => prevTokens.has(x)));
189
+ const union = new Set([...currentTokens, ...prevTokens]);
190
+ const similarity = union.size === 0 ? 0 : intersection.size / union.size;
191
+ if (similarity > maxSimilarity) maxSimilarity = similarity;
192
+ }
193
+
194
+ history.push({ thought: currentThought, entropy: maxSimilarity });
195
+ if (history.length > 5) history.shift(); // Sliding window of 5 thoughts
196
+
197
+ return maxSimilarity;
132
198
  }
133
199
 
134
200
  /**
@@ -83,6 +83,33 @@ class TemporalHindsight {
83
83
  autoApplyStatus: 'PENDING_SIGNATURE',
84
84
  };
85
85
  }
86
+
87
+ /**
88
+ * v5 Pillar III: Proactive Loop Recovery
89
+ * Generates a "Steering Vector" to break agentic Reasoning Stagnation.
90
+ */
91
+ handleProactiveRecovery(traceId, entropyScore) {
92
+ console.log(`[TemporalHindsight] Proactive Recovery triggered for trace ${traceId} (Entropy: ${entropyScore})`);
93
+
94
+ const steeringVectors = [
95
+ "CRITICAL: Stagnation detected. You have repeated similar reasoning steps 3 times. STOP your current approach and decompose the problem into smaller, independent sub-tasks.",
96
+ "STATIONARY LOOP: Your recent thoughts show high similarity. Change your technical layer—if you were editing code, try running a diagnostic command instead.",
97
+ "REASONING DEADLOCK: Entropy too low. Request human intervention or switch to the 'Architect' persona to re-evaluate the plan.",
98
+ "DIVERGENCE ALERT: Proactive reset. Clear your context window of the last 3 reasoning steps and start fresh from the last successful checkpoint."
99
+ ];
100
+
101
+ // Pick a vector based on entropy severity
102
+ const index = Math.min(Math.floor(entropyScore * steeringVectors.length), steeringVectors.length - 1);
103
+
104
+ return {
105
+ timestamp: new Date().toISOString(),
106
+ trace_id: traceId,
107
+ event: 'STEERING_VECTOR_GENERATED',
108
+ entropy: entropyScore,
109
+ instruction: steeringVectors[index],
110
+ action: 'INJECT_SYSTEM_PROMPT'
111
+ };
112
+ }
86
113
  }
87
114
 
88
115
  module.exports = TemporalHindsight;
@@ -1,15 +1,25 @@
1
1
  /**
2
- * MindForge v5.3.0 — Impact Analyzer (Dynamic Blast Radius)
2
+ * MindForge v5.4.0 — Impact Analyzer (Hardened Edition)
3
3
  * Calculates the 'Blast Radius' score of a proposed intent.
4
4
  */
5
5
  'use strict';
6
6
 
7
7
  class ImpactAnalyzer {
8
+ static CRITICAL_PATHS = [
9
+ '.env',
10
+ 'id_rsa',
11
+ '*.pem',
12
+ 'package-lock.json',
13
+ 'yarn.lock',
14
+ 'AUDIT.jsonl',
15
+ 'STATE.md'
16
+ ];
17
+
8
18
  static SENSITIVE_NAMESPACES = [
9
19
  '.mindforge',
10
20
  'bin/',
11
21
  'config/',
12
- '.env',
22
+ '.agent/',
13
23
  'security/'
14
24
  ];
15
25
 
@@ -17,30 +27,44 @@ class ImpactAnalyzer {
17
27
  'READ': 1,
18
28
  'WRITE': 5,
19
29
  'DELETE': 10,
20
- 'EXECUTE': 8,
21
- 'GRANT': 15
30
+ 'EXECUTE': 15, // Raised from 8
31
+ 'GRANT': 20 // Raised from 15
22
32
  };
23
33
 
24
34
  /**
25
- * Scores an intent based on action type and target path sensitivity.
35
+ * Scores an intent based on action type, target path sensitivity, and recursion depth.
26
36
  * Score Range: 0 - 100
27
37
  */
28
38
  static analyze(intent) {
29
39
  const { action, target, namespace } = intent;
30
40
 
41
+ // 1. Critical Path Protection (Score 100)
42
+ const isCritical = this.CRITICAL_PATHS.some(cp =>
43
+ (target && (target.endsWith(cp) || target.includes(`/${cp}`)))
44
+ );
45
+
46
+ if (isCritical && (action === 'WRITE' || action === 'DELETE')) {
47
+ return 100; // Automatic CRITICAL block
48
+ }
49
+
31
50
  let score = this.ACTION_SCORES[action] || 5;
32
51
 
33
- // Check for sensitive namespace overlap
52
+ // 2. Sensitive Namespace Multiplier
34
53
  const isSensitive = this.SENSITIVE_NAMESPACES.some(ns =>
35
54
  (target && target.includes(ns)) || (namespace && namespace.includes(ns))
36
55
  );
37
56
 
38
57
  if (isSensitive) {
39
- score *= 4; // Quadruple impact for sensitive areas
58
+ score *= 4;
59
+ }
60
+
61
+ // 3. Recursive Depth Penalty (Beast Mode)
62
+ if (target && target.split('/').length > 5) {
63
+ score *= 1.5; // Deeper actions are riskier (mass-scale silent mods)
40
64
  }
41
65
 
42
66
  // Cap the score at 100
43
- return Math.min(score, 100);
67
+ return Math.min(Math.round(score), 100);
44
68
  }
45
69
 
46
70
  /**
@@ -17,6 +17,56 @@ class FederatedSync {
17
17
  this.client = new EISClient(config);
18
18
  this.localStore = Store;
19
19
  this.syncHistoryPath = path.join(Store.getPaths().MEMORY_DIR, 'sync-history.jsonl');
20
+ this.circuitBreakerPath = path.join(Store.getPaths().MEMORY_DIR, 'circuit-breaker.json');
21
+ this.MAX_FAILURES = 3;
22
+ this.COOLDOWN_MS = 3600000; // 1 hour
23
+ }
24
+
25
+ /**
26
+ * [BEAST] Checks if the circuit is open.
27
+ */
28
+ isCircuitOpen() {
29
+ if (!fs.existsSync(this.circuitBreakerPath)) return false;
30
+ try {
31
+ const state = JSON.parse(fs.readFileSync(this.circuitBreakerPath, 'utf8'));
32
+ if (state.status === 'OPEN' && (Date.now() - state.trippedAt < this.COOLDOWN_MS)) {
33
+ return true;
34
+ }
35
+ // Reset if cooldown passed
36
+ if (state.status === 'OPEN') {
37
+ this.resetCircuit();
38
+ }
39
+ return false;
40
+ } catch {
41
+ return false;
42
+ }
43
+ }
44
+
45
+ tripCircuit(reason) {
46
+ console.warn(`[BEAST] ⚠️ Circuit Breaker TRIPPED: ${reason}. Mesh sync disabled for 1hr.`);
47
+ const state = { status: 'OPEN', trippedAt: Date.now(), reason };
48
+ fs.writeFileSync(this.circuitBreakerPath, JSON.stringify(state, null, 2));
49
+ }
50
+
51
+ resetCircuit() {
52
+ if (fs.existsSync(this.circuitBreakerPath)) {
53
+ fs.unlinkSync(this.circuitBreakerPath);
54
+ }
55
+ }
56
+
57
+ handleSyncFailure(err) {
58
+ const statsPath = path.join(this.localStore.getPaths().MEMORY_DIR, 'sync-stats.json');
59
+ let stats = { failures: 0 };
60
+ if (fs.existsSync(statsPath)) {
61
+ stats = JSON.parse(fs.readFileSync(statsPath, 'utf8'));
62
+ }
63
+ stats.failures = (stats.failures || 0) + 1;
64
+ stats.last_error = err.message;
65
+ fs.writeFileSync(statsPath, JSON.stringify(stats, null, 2));
66
+
67
+ if (stats.failures >= this.MAX_FAILURES) {
68
+ this.tripCircuit(err.message);
69
+ }
20
70
  }
21
71
 
22
72
  /**
@@ -24,37 +74,58 @@ class FederatedSync {
24
74
  * This pushes local high-confidence entries and pulls new organizational knowledge.
25
75
  */
26
76
  async fullSync() {
27
- console.log('🔄 Initiating Federated Intelligence Sync (Pillar 1)...');
28
-
29
- // 1. Get promotable entries (Tiers 1-3)
30
- const localEntries = this.localStore.readAll(false).filter(e => e.confidence > 0.8 && !e.deprecated);
31
-
32
- // 2. Filter out already synced entries
33
- const unsynced = localEntries.filter(e => !e.global && !this.isRecentlySynced(e.id));
34
-
35
- // 3. Push to EIS
36
- if (unsynced.length > 0) {
37
- const auth = await this.client.getAuthHeader('push', 'kb/global');
38
- const results = await this.client.push(unsynced, { headers: auth });
39
- this.logSyncEvent(results);
77
+ if (this.isCircuitOpen()) {
78
+ console.warn('🛑 Federated Intelligence Sync: Circuit is OPEN. Skipping network calls.');
79
+ return { status: 'CIRCUIT_OPEN' };
40
80
  }
81
+
82
+ console.log('🔄 Initiating Federated Intelligence Sync (v5.4.0 BEAST)...');
41
83
 
42
- // 4. [HARDEN] Delta Pull from EIS
43
- const lastSync = this.getLastSyncTimestamp();
44
- const authPull = await this.client.getAuthHeader('pull', 'kb/global');
45
- const remoteEntries = await this.client.pull({
46
- orgId: this.client.orgId,
47
- since: lastSync,
48
- headers: authPull
49
- });
84
+ try {
85
+ // 1. Get promotable entries (Tiers 1-3)
86
+ const localEntries = this.localStore.readAll(false).filter(e => e.confidence > 0.8 && !e.deprecated);
87
+
88
+ // 2. Filter out already synced entries
89
+ const unsynced = localEntries.filter(e => !e.global && !this.isRecentlySynced(e.id));
90
+
91
+ // 3. Push to EIS
92
+ if (unsynced.length > 0) {
93
+ const auth = await this.client.getAuthHeader('push', 'kb/global');
94
+ const results = await this.client.push(unsynced, { headers: auth });
95
+ this.logSyncEvent(results);
96
+ }
97
+
98
+ // 4. [HARDEN] Delta Pull from EIS
99
+ const lastSync = this.getLastSyncTimestamp();
100
+ const authPull = await this.client.getAuthHeader('pull', 'kb/global');
101
+ const remoteEntries = await this.client.pull({
102
+ orgId: this.client.orgId,
103
+ since: lastSync,
104
+ headers: authPull
105
+ });
50
106
 
51
- if (remoteEntries.length > 0) {
52
- this.mergeRemoteKnowledge(remoteEntries);
107
+ if (remoteEntries.length > 0) {
108
+ this.mergeRemoteKnowledge(remoteEntries);
109
+ }
110
+
111
+ this.updateLastSyncTimestamp();
112
+ this.resetFailures(); // Reset on success
113
+ console.log(`✅ Federated Intelligence Mesh: Sync complete. (Delta since ${lastSync})`);
114
+ return { pushed: unsynced.length, pulled: remoteEntries.length };
115
+ } catch (err) {
116
+ console.error('❌ Federated Intelligence Sync FAILED:', err.message);
117
+ this.handleSyncFailure(err);
118
+ throw err;
119
+ }
120
+ }
121
+
122
+ resetFailures() {
123
+ const statsPath = path.join(this.localStore.getPaths().MEMORY_DIR, 'sync-stats.json');
124
+ if (fs.existsSync(statsPath)) {
125
+ const stats = JSON.parse(fs.readFileSync(statsPath, 'utf8'));
126
+ stats.failures = 0;
127
+ fs.writeFileSync(statsPath, JSON.stringify(stats, null, 2));
53
128
  }
54
-
55
- this.updateLastSyncTimestamp();
56
- console.log(`✅ Federated Intelligence Mesh: Sync complete. (Delta since ${lastSync})`);
57
- return { pushed: unsynced.length, pulled: remoteEntries.length };
58
129
  }
59
130
 
60
131
  getLastSyncTimestamp() {
@@ -133,6 +204,7 @@ class FederatedSync {
133
204
  if (similarity > 0.9) {
134
205
  if (new Date(remote.timestamp) > new Date(local.timestamp)) {
135
206
  this.writeToGlobalKB(remote, globalPath);
207
+ this.logConflictTelemetry(local.id, 'LWW', similarity);
136
208
  console.log(` └─ [LWW] Auto-resolved via timestamp.`);
137
209
  }
138
210
  return;
@@ -143,6 +215,7 @@ class FederatedSync {
143
215
  console.log(` └─ [ADS] Triggering Autonomous Knowledge Synthesis...`);
144
216
  const merged = await this.triggerADSMerging(local, remote);
145
217
  this.writeToGlobalKB(merged, globalPath);
218
+ this.logConflictTelemetry(local.id, 'ADS_MERGE', similarity);
146
219
  return;
147
220
  }
148
221
 
@@ -150,12 +223,25 @@ class FederatedSync {
150
223
  if (similarity > 0.6) {
151
224
  console.log(` └─ [DHH] High disagreement. Triggering Nexus Handover...`);
152
225
  this.localStore.markConflict(local.id, remote);
226
+ this.logConflictTelemetry(local.id, 'DHH_HANDOVER', similarity);
153
227
  return;
154
228
  }
155
229
 
156
230
  // 4. Collision Isolation (< 0.6) - Topic Mismatch
157
231
  console.log(` └─ [ISO] Semantic collision (Topic mismatch). Isolating entries.`);
158
232
  this.writeToGlobalKB({ ...remote, id: `${remote.id}_collision_${Date.now()}` }, globalPath);
233
+ this.logConflictTelemetry(local.id, 'COLLISION_ISOLATION', similarity);
234
+ }
235
+
236
+ logConflictTelemetry(id, resolution, similarity) {
237
+ const telePath = path.join(this.localStore.getPaths().MEMORY_DIR, 'sync-telemetry.jsonl');
238
+ const entry = JSON.stringify({
239
+ id,
240
+ resolution,
241
+ similarity,
242
+ timestamp: new Date().toISOString()
243
+ }) + '\n';
244
+ fs.appendFileSync(telePath, entry);
159
245
  }
160
246
 
161
247
  async triggerADSMerging(local, remote) {
@@ -19,7 +19,7 @@ function main() {
19
19
  }
20
20
 
21
21
  // Handle cases where the action might be missing if called incorrectly
22
- const validActions = ['install', 'register', 'audit'];
22
+ const validActions = ['install', 'register', 'audit', 'sign'];
23
23
  if (!validActions.includes(ACTION)) {
24
24
  console.error(`❌ Invalid or missing action: ${ACTION}`);
25
25
  console.error(` Expected one of: ${validActions.join(', ')}`);
@@ -36,12 +36,77 @@ function main() {
36
36
  case 'audit':
37
37
  handleAudit();
38
38
  break;
39
+ case 'sign':
40
+ handleSign();
41
+ break;
39
42
  default:
40
43
  console.error(`❌ Unknown action: ${ACTION}`);
41
44
  process.exit(1);
42
45
  }
43
46
  }
44
47
 
48
+ async function handleSign() {
49
+ const skillName = ARGS[1];
50
+ const ztai = require('./governance/ztai-manager');
51
+ const crypto = require('node:crypto');
52
+
53
+ if (!skillName) {
54
+ console.error('❌ Missing skill name to sign');
55
+ process.exit(1);
56
+ }
57
+
58
+ // Find the skill file
59
+ const bases = [
60
+ '.mindforge/skills',
61
+ '.mindforge/org/skills',
62
+ '.mindforge/project-skills'
63
+ ];
64
+
65
+ let targetPath = null;
66
+ for (const base of bases) {
67
+ const p = path.join(process.cwd(), base, skillName, 'SKILL.md');
68
+ if (fs.existsSync(p)) {
69
+ targetPath = p;
70
+ break;
71
+ }
72
+ }
73
+
74
+ if (!targetPath) {
75
+ console.error(`❌ Skill ${skillName} not found in any registry path.`);
76
+ process.exit(1);
77
+ }
78
+
79
+ console.log(`🛡️ Signing skill: ${skillName}...`);
80
+ const content = fs.readFileSync(targetPath, 'utf8');
81
+ const hash = crypto.createHash('sha256').update(content).digest('hex');
82
+
83
+ try {
84
+ // We use a dedicated System DID for skill signing (Tier 3)
85
+ const systemDid = await ztai.registerAgent('MindForge-System-Secretary', 3);
86
+ const signature = await ztai.signData(systemDid, hash);
87
+
88
+ const sigPath = path.join(process.cwd(), '.mindforge', 'org', 'skills', 'SIGNATURES.json');
89
+ let signatures = {};
90
+ if (fs.existsSync(sigPath)) {
91
+ signatures = JSON.parse(fs.readFileSync(sigPath, 'utf8'));
92
+ }
93
+
94
+ signatures[skillName] = {
95
+ hash,
96
+ signature,
97
+ did: systemDid,
98
+ timestamp: new Date().toISOString()
99
+ };
100
+
101
+ fs.writeFileSync(sigPath, JSON.stringify(signatures, null, 2));
102
+ console.log(`✅ Skill ${skillName} signed and registered in SIGNATURES.json`);
103
+ process.exit(0);
104
+ } catch (err) {
105
+ console.error(`❌ Signing failed: ${err.message}`);
106
+ process.exit(1);
107
+ }
108
+ }
109
+
45
110
  function handleInstall() {
46
111
  const skillName = ARGS[1];
47
112
  const tierFlag = ARGS.indexOf('--tier');
@@ -38,7 +38,33 @@ function main() {
38
38
  console.log('─'.repeat(60));
39
39
 
40
40
  const content = fs.readFileSync(filePath, 'utf8');
41
- const results = { schema: [], content: [], quality: [], valid: true };
41
+ const results = { schema: [], content: [], quality: [], valid: true, attestation: { ok: true, msg: 'No signature found (optional)' } };
42
+
43
+ // ── Level 0: Binary Runtime Attestation (v5 Pillar IV) ──────────────────────
44
+ const sigPath = path.join(process.cwd(), '.mindforge', 'org', 'skills', 'SIGNATURES.json');
45
+ if (fs.existsSync(sigPath)) {
46
+ const crypto = require('node:crypto');
47
+ const ztai = require('./governance/ztai-manager');
48
+ const signatures = JSON.parse(fs.readFileSync(sigPath, 'utf8'));
49
+ const skillNameCandidate = path.basename(path.dirname(filePath));
50
+ const sigRecord = signatures[skillNameCandidate];
51
+
52
+ if (sigRecord) {
53
+ const currentHash = crypto.createHash('sha256').update(content).digest('hex');
54
+ const isHashValid = currentHash === sigRecord.hash;
55
+ const isSigValid = ztai.verifySignature(sigRecord.did, currentHash, sigRecord.signature);
56
+
57
+ if (!isHashValid || !isSigValid) {
58
+ results.attestation = { ok: false, msg: `INTEGRITY FAILURE: Signature mismatch [Hash: ${isHashValid}, Sig: ${isSigValid}]` };
59
+ results.valid = false;
60
+ } else {
61
+ results.attestation = { ok: true, msg: `VERIFIED: Signed by ${sigRecord.did}` };
62
+ }
63
+ } else if (ARGS.includes('--enterprise')) {
64
+ results.attestation = { ok: false, msg: 'REQUIRED: No signature found for this skill in Enterprise Mode' };
65
+ results.valid = false;
66
+ }
67
+ }
42
68
 
43
69
  // ── Level 1: Schema ─────────────────────────────────────────────────────────
44
70
  const fmMatch = content.match(/^---\n([\s\S]*?)\n---/);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mindforge-cc",
3
- "version": "5.3.0",
3
+ "version": "5.6.0",
4
4
  "description": "MindForge - Enterprise Agentic Framework for Claude Code and Antigravity",
5
5
  "bin": {
6
6
  "mindforge-cc": "bin/install.js"