mindforge-cc 4.3.0 → 5.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.mindforge/engine/nexus-tracer.js +115 -0
- package/CHANGELOG.md +75 -27
- package/README.md +52 -100
- package/RELEASENOTES.md +12 -0
- package/bin/autonomous/auto-runner.js +154 -4
- package/bin/autonomous/context-refactorer.js +64 -0
- package/bin/autonomous/steer.js +19 -1
- package/bin/autonomous/stuck-monitor.js +43 -0
- package/bin/engine/handover-manager.js +69 -0
- package/bin/engine/nexus-tracer.js +67 -2
- package/bin/engine/sre-manager.js +63 -0
- package/bin/governance/policies/default-policies.jsonl +33 -0
- package/bin/governance/policy-engine.js +106 -0
- package/bin/governance/rbac-manager.js +109 -0
- package/bin/memory/eis-client.js +95 -0
- package/bin/memory/federated-sync.js +127 -0
- package/bin/memory/knowledge-graph.js +37 -0
- package/bin/models/cloud-broker.js +83 -0
- package/bin/models/model-broker.js +68 -49
- package/bin/skill-validator.js +41 -0
- package/docs/INTELLIGENCE-MESH.md +25 -22
- package/docs/architecture/PAR-ZTS-SURVEY.md +43 -0
- package/docs/architecture/README.md +31 -64
- package/docs/architecture/V5-ENTERPRISE.md +113 -0
- package/docs/governance-guide.md +43 -28
- package/docs/security/SECURITY.md +9 -7
- package/docs/user-guide.md +29 -3
- package/docs/usp-features.md +3 -0
- package/package.json +1 -1
- /package/docs/{context → Context}/Master-Context.md +0 -0
- /package/docs/{references → References}/audit-events.md +0 -0
- /package/docs/{references → References}/checkpoints.md +0 -0
- /package/docs/{references → References}/commands.md +0 -0
- /package/docs/{references → References}/config-reference.md +0 -0
- /package/docs/{references → References}/continuation-format.md +0 -0
- /package/docs/{references → References}/decimal-phase-calculation.md +0 -0
- /package/docs/{references → References}/git-integration.md +0 -0
- /package/docs/{references → References}/git-planning-commit.md +0 -0
- /package/docs/{references → References}/model-profile-resolution.md +0 -0
- /package/docs/{references → References}/model-profiles.md +0 -0
- /package/docs/{references → References}/phase-argument-parsing.md +0 -0
- /package/docs/{references → References}/planning-config.md +0 -0
- /package/docs/{references → References}/questioning.md +0 -0
- /package/docs/{references → References}/sdk-api.md +0 -0
- /package/docs/{references → References}/skills-api.md +0 -0
- /package/docs/{references → References}/tdd.md +0 -0
- /package/docs/{references → References}/ui-brand.md +0 -0
- /package/docs/{references → References}/user-profiling.md +0 -0
- /package/docs/{references → References}/verification-patterns.md +0 -0
- /package/docs/{references → References}/workstream-flag.md +0 -0
- /package/docs/{templates → Templates}/Agents/CLAUDE-MD.md +0 -0
- /package/docs/{templates → Templates}/Agents/COPILOT-INSTRUCTIONS.md +0 -0
- /package/docs/{templates → Templates}/Agents/DEBUGGER-PROMPT.md +0 -0
- /package/docs/{templates → Templates}/Agents/PLANNER-PROMPT.md +0 -0
- /package/docs/{templates/codebase → Templates/Codebase}/architecture.md +0 -0
- /package/docs/{templates/codebase → Templates/Codebase}/concerns.md +0 -0
- /package/docs/{templates/codebase → Templates/Codebase}/conventions.md +0 -0
- /package/docs/{templates/codebase → Templates/Codebase}/integrations.md +0 -0
- /package/docs/{templates/codebase → Templates/Codebase}/stack.md +0 -0
- /package/docs/{templates/codebase → Templates/Codebase}/structure.md +0 -0
- /package/docs/{templates/codebase → Templates/Codebase}/testing.md +0 -0
- /package/docs/{templates → Templates}/Execution/CONTINUE-HERE.md +0 -0
- /package/docs/{templates → Templates}/Execution/DISCUSSION-LOG.md +0 -0
- /package/docs/{templates → Templates}/Execution/PHASE-PROMPT.md +0 -0
- /package/docs/{templates → Templates}/Execution/STATE.md +0 -0
- /package/docs/{templates → Templates}/Execution/SUMMARY-COMPLEX.md +0 -0
- /package/docs/{templates → Templates}/Execution/SUMMARY-MINIMAL.md +0 -0
- /package/docs/{templates → Templates}/Execution/SUMMARY-STANDARD.md +0 -0
- /package/docs/{templates → Templates}/Execution/SUMMARY.md +0 -0
- /package/docs/{templates → Templates}/Profile/DEV-PREFERENCES.md +0 -0
- /package/docs/{templates → Templates}/Profile/USER-PROFILE.md +0 -0
- /package/docs/{templates → Templates}/Profile/USER-SETUP.md +0 -0
- /package/docs/{templates → Templates}/Project/DISCOVERY.md +0 -0
- /package/docs/{templates → Templates}/Project/MILESTONE-ARCHIVE.md +0 -0
- /package/docs/{templates → Templates}/Project/MILESTONE.md +0 -0
- /package/docs/{templates → Templates}/Project/PROJECT.md +0 -0
- /package/docs/{templates → Templates}/Project/REQUIREMENTS.md +0 -0
- /package/docs/{templates → Templates}/Project/RETROSPECTIVE.md +0 -0
- /package/docs/{templates → Templates}/Project/ROADMAP.md +0 -0
- /package/docs/{templates → Templates}/Quality/DEBUG.md +0 -0
- /package/docs/{templates → Templates}/Quality/UAT.md +0 -0
- /package/docs/{templates → Templates}/Quality/UI-SPEC.md +0 -0
- /package/docs/{templates → Templates}/Quality/VALIDATION.md +0 -0
- /package/docs/{templates → Templates}/Quality/VERIFICATION-REPORT.md +0 -0
- /package/docs/{templates/research → Templates/Research}/ARCHITECTURE.md +0 -0
- /package/docs/{templates/research → Templates/Research}/FEATURES.md +0 -0
- /package/docs/{templates/research → Templates/Research}/PITFALLS.md +0 -0
- /package/docs/{templates/research → Templates/Research}/STACK.md +0 -0
- /package/docs/{templates/research → Templates/Research}/SUMMARY.md +0 -0
- /package/docs/{templates → Templates}/System/CONFIG.json +0 -0
- /package/docs/{templates → Templates}/System/CONTEXT.md +0 -0
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MindForge — Context Refactorer Engine (v5.0.0-PAR)
|
|
3
|
+
* Monitors context density and triggers proactive summarization/refactoring.
|
|
4
|
+
*/
|
|
5
|
+
'use strict';
|
|
6
|
+
|
|
7
|
+
const fs = require('fs');
|
|
8
|
+
const path = require('path');
|
|
9
|
+
|
|
10
|
+
class ContextRefactorer {
|
|
11
|
+
constructor(options = {}) {
|
|
12
|
+
this.threshold = options.threshold || 0.3; // Min density before refactor
|
|
13
|
+
this.windowSize = options.windowSize || 20;
|
|
14
|
+
this.history = [];
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Analyze the current context density.
|
|
19
|
+
* Density = (Implementation Events) / (Total Events)
|
|
20
|
+
*/
|
|
21
|
+
analyzeDensity(events) {
|
|
22
|
+
this.history = events.slice(-this.windowSize);
|
|
23
|
+
|
|
24
|
+
if (this.history.length < 5) return { density: 1.0, shouldRefactor: false };
|
|
25
|
+
|
|
26
|
+
const implementationEvents = this.history.filter(h =>
|
|
27
|
+
h.tool === 'run_command' ||
|
|
28
|
+
h.tool === 'replace_file_content' ||
|
|
29
|
+
h.tool === 'multi_replace_file_content' ||
|
|
30
|
+
h.event === 'task_completed'
|
|
31
|
+
);
|
|
32
|
+
|
|
33
|
+
const totalEvents = this.history.length;
|
|
34
|
+
const density = implementationEvents.length / totalEvents;
|
|
35
|
+
|
|
36
|
+
return {
|
|
37
|
+
density: parseFloat(density.toFixed(2)),
|
|
38
|
+
shouldRefactor: density < this.threshold
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Generates a "Context Refactor" recommendation.
|
|
44
|
+
*/
|
|
45
|
+
generateRefactorPlan(events, phase) {
|
|
46
|
+
const reasoningChain = events
|
|
47
|
+
.filter(e => e.event === 'reasoning_trace')
|
|
48
|
+
.map(e => `- ${e.thought}`)
|
|
49
|
+
.join('\n');
|
|
50
|
+
|
|
51
|
+
return {
|
|
52
|
+
event: 'context_refactor_triggered',
|
|
53
|
+
phase,
|
|
54
|
+
message: 'Context density low. Initiating proactive refactoring.',
|
|
55
|
+
action: 'SUMMARIZE_AND_RESET',
|
|
56
|
+
payload: {
|
|
57
|
+
summary_prompt: `The current reasoning chain has become dense (${this.threshold}). Summarize the progress for Phase ${phase} and reset the active context window.`,
|
|
58
|
+
trace_sample: reasoningChain.slice(-500) // Last few thoughts for context
|
|
59
|
+
}
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
module.exports = ContextRefactorer;
|
package/bin/autonomous/steer.js
CHANGED
|
@@ -64,8 +64,26 @@ function injectSteering(planContent, guidanceItems) {
|
|
|
64
64
|
});
|
|
65
65
|
}
|
|
66
66
|
|
|
67
|
+
/**
|
|
68
|
+
* Add human steering to the unified queue (v5 Pillar VII).
|
|
69
|
+
*/
|
|
70
|
+
function pushHumanSteering(instruction, bundleId = 'none') {
|
|
71
|
+
const STEER_PATH = path.join(process.cwd(), '.planning', 'STEER.json');
|
|
72
|
+
const item = {
|
|
73
|
+
id: `human-${Date.now()}`,
|
|
74
|
+
timestamp: new Date().toISOString(),
|
|
75
|
+
bundle_id: bundleId,
|
|
76
|
+
type: 'HUMAN_OVERRIDE',
|
|
77
|
+
instruction,
|
|
78
|
+
priority: 'CRITICAL'
|
|
79
|
+
};
|
|
80
|
+
fs.appendFileSync(STEER_PATH, JSON.stringify(item) + '\n');
|
|
81
|
+
return item.id;
|
|
82
|
+
}
|
|
83
|
+
|
|
67
84
|
module.exports = {
|
|
68
85
|
pushGuidance,
|
|
69
86
|
popGuidance,
|
|
70
|
-
injectSteering
|
|
87
|
+
injectSteering,
|
|
88
|
+
pushHumanSteering
|
|
71
89
|
};
|
|
@@ -26,9 +26,52 @@ class StuckMonitor {
|
|
|
26
26
|
// Check S02: Command Loop (Identical failing commands)
|
|
27
27
|
if (this.detectS02(event)) return { pattern: 'S02', message: 'Stuck in command loop: identical failing commands.' };
|
|
28
28
|
|
|
29
|
+
// Check S03: Semantic Mirroring (Reasoning Loop)
|
|
30
|
+
if (this.detectS03(event)) return { pattern: 'S03', message: 'Stuck in reasoning loop: semantic mirroring detected.' };
|
|
31
|
+
|
|
32
|
+
// Check S04: Infinite Decomposition (Planning Paradox)
|
|
33
|
+
if (this.detectS04(event)) return { pattern: 'S04', message: 'Stuck in planning paradox: infinite decomposition detected.' };
|
|
34
|
+
|
|
29
35
|
return null;
|
|
30
36
|
}
|
|
31
37
|
|
|
38
|
+
detectS03(event) {
|
|
39
|
+
if (event.event !== 'reasoning_trace') return false;
|
|
40
|
+
|
|
41
|
+
// Compare with the last 5 thoughts in history
|
|
42
|
+
const reflections = this.history.filter(h => h.event === 'reasoning_trace');
|
|
43
|
+
if (reflections.length < 3) return false;
|
|
44
|
+
|
|
45
|
+
const currentThought = event.thought;
|
|
46
|
+
const previousThoughts = reflections.slice(-4, -1);
|
|
47
|
+
|
|
48
|
+
const isMirroring = previousThoughts.some(p =>
|
|
49
|
+
this.isContentSimilar(p.thought, currentThought)
|
|
50
|
+
);
|
|
51
|
+
|
|
52
|
+
return isMirroring;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
detectS04(event) {
|
|
56
|
+
if (event.event !== 'reasoning_trace') return false;
|
|
57
|
+
|
|
58
|
+
const decompositions = this.history.filter(h =>
|
|
59
|
+
h.event === 'reasoning_trace' &&
|
|
60
|
+
(h.thought?.toLowerCase().includes('break down') || h.thought?.toLowerCase().includes('sub-task'))
|
|
61
|
+
);
|
|
62
|
+
|
|
63
|
+
// If more than 4 consecutive decompositions without a command or edit
|
|
64
|
+
const lastActionIndex = this.history.findLastIndex(h =>
|
|
65
|
+
h.tool === 'run_command' || h.tool === 'replace_file_content' || h.tool === 'multi_replace_file_content'
|
|
66
|
+
);
|
|
67
|
+
|
|
68
|
+
const recentDecomps = decompositions.filter(d =>
|
|
69
|
+
this.history.indexOf(d) > lastActionIndex
|
|
70
|
+
);
|
|
71
|
+
|
|
72
|
+
return recentDecomps.length >= 4;
|
|
73
|
+
}
|
|
74
|
+
|
|
32
75
|
detectS01(event) {
|
|
33
76
|
if (event.tool !== 'multi_replace_file_content') return false;
|
|
34
77
|
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MindForge — HandoverManager (Pillar VII: Dynamic Human-Agent Handover)
|
|
3
|
+
* Packages Nexus State Bundles for bidirectional steering and human escalation.
|
|
4
|
+
*/
|
|
5
|
+
'use strict';
|
|
6
|
+
|
|
7
|
+
const fs = require('fs');
|
|
8
|
+
const path = require('path');
|
|
9
|
+
const crypto = require('crypto');
|
|
10
|
+
|
|
11
|
+
class HandoverManager {
|
|
12
|
+
constructor(config = {}) {
|
|
13
|
+
this.handoffPath = path.join(process.cwd(), '.planning', 'handoffs');
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Packages a Nexus State Bundle for human review.
|
|
18
|
+
* @param {Object} state - Current execution state (audit, memory, goals)
|
|
19
|
+
* @returns {string} - Path to the state bundle.
|
|
20
|
+
*/
|
|
21
|
+
createNexusBundle(state) {
|
|
22
|
+
if (!fs.existsSync(this.handoffPath)) {
|
|
23
|
+
fs.mkdirSync(this.handoffPath, { recursive: true });
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const bundleId = `bundle_${crypto.randomBytes(6).toString('hex')}`;
|
|
27
|
+
const bundle = {
|
|
28
|
+
id: bundleId,
|
|
29
|
+
timestamp: new Date().toISOString(),
|
|
30
|
+
version: '5.0.0-nexus',
|
|
31
|
+
context: {
|
|
32
|
+
phase: state.phase,
|
|
33
|
+
wave: state.wave,
|
|
34
|
+
last_events: state.recentEvents,
|
|
35
|
+
memory_shards: state.memoryShards || []
|
|
36
|
+
},
|
|
37
|
+
reasoning_snapshot: state.reasoningTrace,
|
|
38
|
+
steering_requirements: state.blocks || []
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
const bundlePath = path.join(this.handoffPath, `${bundleId}.json`);
|
|
42
|
+
fs.writeFileSync(bundlePath, JSON.stringify(bundle, null, 2));
|
|
43
|
+
|
|
44
|
+
console.log(`[DHH-BUNDLE] Nexus State Bundle packaged: ${bundlePath}`);
|
|
45
|
+
return bundlePath;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Injects human steering into the agentic flow.
|
|
50
|
+
* @param {string} bundleId - The bundle being steered.
|
|
51
|
+
* @param {Object} steeringRequest - Human instructions/overrides.
|
|
52
|
+
*/
|
|
53
|
+
injectSteering(bundleId, steeringRequest) {
|
|
54
|
+
const steerPath = path.join(process.cwd(), '.planning', 'STEER.json');
|
|
55
|
+
const instruction = {
|
|
56
|
+
id: crypto.randomUUID(),
|
|
57
|
+
timestamp: new Date().toISOString(),
|
|
58
|
+
bundle_id: bundleId,
|
|
59
|
+
type: 'HUMAN_OVERRIDE',
|
|
60
|
+
instruction: steeringRequest.instruction,
|
|
61
|
+
priority: 'CRITICAL'
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
fs.appendFileSync(steerPath, JSON.stringify(instruction) + '\n');
|
|
65
|
+
console.log(`[DHH-STEER] Human instruction injected into autonomous stream [Ref: ${bundleId}]`);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
module.exports = HandoverManager;
|
|
@@ -9,6 +9,7 @@ const fs = require('fs');
|
|
|
9
9
|
const path = require('path');
|
|
10
10
|
const crypto = require('crypto');
|
|
11
11
|
const ztai = require('../governance/ztai-manager');
|
|
12
|
+
const SREManager = require('./sre-manager');
|
|
12
13
|
|
|
13
14
|
class NexusTracer {
|
|
14
15
|
constructor(config = {}) {
|
|
@@ -18,6 +19,15 @@ class NexusTracer {
|
|
|
18
19
|
this.activeSpans = new Map();
|
|
19
20
|
this.did = config.did || null; // Active Agent DID
|
|
20
21
|
this.enableZtai = config.enableZtai !== false;
|
|
22
|
+
this.sreManager = new SREManager();
|
|
23
|
+
|
|
24
|
+
// v5 Pillar IV: Agentic SBOM
|
|
25
|
+
this.sbom = {
|
|
26
|
+
manifest_version: '1.0.0',
|
|
27
|
+
models: new Set(),
|
|
28
|
+
skills: new Set(),
|
|
29
|
+
startTime: new Date().toISOString()
|
|
30
|
+
};
|
|
21
31
|
}
|
|
22
32
|
|
|
23
33
|
/**
|
|
@@ -50,12 +60,29 @@ class NexusTracer {
|
|
|
50
60
|
|
|
51
61
|
this.activeSpans.set(spanId, span);
|
|
52
62
|
|
|
63
|
+
// Track model and skill in SBOM if provided in attributes
|
|
64
|
+
if (attributes.model_id) this.sbom.models.add(attributes.model_id);
|
|
65
|
+
if (attributes.skill) this.sbom.skills.add(attributes.skill);
|
|
66
|
+
|
|
67
|
+
// v5 Pillar VI: Enclave Check
|
|
68
|
+
if (attributes.is_confidential && !attributes.enclave_id) {
|
|
69
|
+
try {
|
|
70
|
+
span.attributes.enclave_id = this.sreManager.initializeEnclave({
|
|
71
|
+
tier: attributes.tier || 1,
|
|
72
|
+
did: this.did
|
|
73
|
+
});
|
|
74
|
+
} catch (err) {
|
|
75
|
+
console.warn(`[NexusTracer] Failed to initialize SRE for confidential span: ${err.message}`);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
53
79
|
// Record span start in AUDIT.jsonl
|
|
54
80
|
this._recordEvent('span_started', {
|
|
55
81
|
span_id: spanId,
|
|
56
82
|
parent_span_id: parentSpanId,
|
|
57
83
|
span_name: name,
|
|
58
|
-
...attributes
|
|
84
|
+
...attributes,
|
|
85
|
+
enclave_id: span.attributes.enclave_id
|
|
59
86
|
});
|
|
60
87
|
|
|
61
88
|
return spanId;
|
|
@@ -71,6 +98,11 @@ class NexusTracer {
|
|
|
71
98
|
span.status = status;
|
|
72
99
|
span.end_time = new Date().toISOString();
|
|
73
100
|
|
|
101
|
+
// v5 Pillar VI: Enclave Termination
|
|
102
|
+
if (span.attributes.enclave_id) {
|
|
103
|
+
this.sreManager.terminateEnclave(span.attributes.enclave_id);
|
|
104
|
+
}
|
|
105
|
+
|
|
74
106
|
this._recordEvent('span_completed', {
|
|
75
107
|
span_id: spanId,
|
|
76
108
|
status,
|
|
@@ -84,10 +116,17 @@ class NexusTracer {
|
|
|
84
116
|
* Record a Reasoning Trace event (ART granularity).
|
|
85
117
|
*/
|
|
86
118
|
recordReasoning(spanId, agent, thought, resolution = 'none') {
|
|
119
|
+
const span = this.activeSpans.get(spanId);
|
|
120
|
+
let sanitizedThought = thought;
|
|
121
|
+
|
|
122
|
+
if (span && span.attributes.enclave_id) {
|
|
123
|
+
sanitizedThought = this.sreManager.sanitizeThoughtChain(thought, span.attributes.enclave_id);
|
|
124
|
+
}
|
|
125
|
+
|
|
87
126
|
this._recordEvent('reasoning_trace', {
|
|
88
127
|
span_id: spanId,
|
|
89
128
|
agent,
|
|
90
|
-
thought,
|
|
129
|
+
thought: sanitizedThought,
|
|
91
130
|
resolution
|
|
92
131
|
});
|
|
93
132
|
}
|
|
@@ -145,6 +184,32 @@ class NexusTracer {
|
|
|
145
184
|
...report
|
|
146
185
|
});
|
|
147
186
|
}
|
|
187
|
+
|
|
188
|
+
/**
|
|
189
|
+
* Finalize and export the Agentic SBOM (Pillar IV).
|
|
190
|
+
*/
|
|
191
|
+
exportSBOM(outputPath = null) {
|
|
192
|
+
const finalPath = outputPath || path.join(process.cwd(), '.planning', 'MANIFEST.sbom.json');
|
|
193
|
+
const manifest = {
|
|
194
|
+
...this.sbom,
|
|
195
|
+
models: Array.from(this.sbom.models),
|
|
196
|
+
skills: Array.from(this.sbom.skills),
|
|
197
|
+
endTime: new Date().toISOString()
|
|
198
|
+
};
|
|
199
|
+
|
|
200
|
+
try {
|
|
201
|
+
if (!fs.existsSync(path.dirname(finalPath))) {
|
|
202
|
+
fs.mkdirSync(path.dirname(finalPath), { recursive: true });
|
|
203
|
+
}
|
|
204
|
+
fs.writeFileSync(finalPath, JSON.stringify(manifest, null, 2));
|
|
205
|
+
|
|
206
|
+
this._recordEvent('sbom_exported', { path: finalPath });
|
|
207
|
+
return finalPath;
|
|
208
|
+
} catch (err) {
|
|
209
|
+
console.error(`[NexusTracer] Failed to export SBOM: ${err.message}`);
|
|
210
|
+
return null;
|
|
211
|
+
}
|
|
212
|
+
}
|
|
148
213
|
}
|
|
149
214
|
|
|
150
215
|
module.exports = NexusTracer;
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MindForge — SREManager (Pillar VI: Sovereign Reason Enclaves)
|
|
3
|
+
* Manages confidential reasoning sessions in simulated Trusted Execution Environments (TEE).
|
|
4
|
+
*/
|
|
5
|
+
'use strict';
|
|
6
|
+
|
|
7
|
+
const crypto = require('crypto');
|
|
8
|
+
|
|
9
|
+
class SREManager {
|
|
10
|
+
constructor() {
|
|
11
|
+
this.activeEnclaves = new Map();
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Initializes a Sovereign Reason Enclave for a task.
|
|
16
|
+
* @param {Object} context - Task context (requires Tier 3 identity)
|
|
17
|
+
* @returns {string} - Enclave ID
|
|
18
|
+
*/
|
|
19
|
+
initializeEnclave(context) {
|
|
20
|
+
if (context.tier < 3) {
|
|
21
|
+
throw new Error(`[SRE-DENY] Tier ${context.tier} principal is not authorized for Sovereign Reason Enclaves.`);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const enclaveId = crypto.randomBytes(12).toString('hex');
|
|
25
|
+
this.activeEnclaves.set(enclaveId, {
|
|
26
|
+
startedAt: new Date().toISOString(),
|
|
27
|
+
principal: context.did,
|
|
28
|
+
hasIP: true,
|
|
29
|
+
isolationLevel: 'Hardware-Enclave (Simulated)'
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
console.log(`[SRE-INIT] Initialized Sovereign Reason Enclave: ${enclaveId} for ${context.did}`);
|
|
33
|
+
return enclaveId;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Sanitizes a thought chain for global audit logging.
|
|
38
|
+
* Ensures that sensitive IP or "zero-visibility" thoughts are isolated.
|
|
39
|
+
* @param {string} thoughtChain - The raw agentic thought chain.
|
|
40
|
+
* @returns {string} - Sanitized/Isolated thought chain.
|
|
41
|
+
*/
|
|
42
|
+
sanitizeThoughtChain(thoughtChain, enclaveId) {
|
|
43
|
+
if (!this.activeEnclaves.has(enclaveId)) return thoughtChain;
|
|
44
|
+
|
|
45
|
+
// Zero-Visibility Protocol: In SRE mode, the global audit log only receives a hash
|
|
46
|
+
// or a redacted summary. The full chain is kept in volatile enclave memory.
|
|
47
|
+
const digest = crypto.createHash('sha256').update(thoughtChain).digest('hex');
|
|
48
|
+
|
|
49
|
+
return `[SRE-ISOLATED] Confidential reasoning executed in enclave ${enclaveId}. Verification Digest: ${digest}. Original trace is isolated from persistence.`;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Finalizes and purges the enclave.
|
|
54
|
+
*/
|
|
55
|
+
terminateEnclave(enclaveId) {
|
|
56
|
+
if (this.activeEnclaves.has(enclaveId)) {
|
|
57
|
+
this.activeEnclaves.delete(enclaveId);
|
|
58
|
+
console.log(`[SRE-PURGE] Sovereign Reason Enclave ${enclaveId} has been securely purged.`);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
module.exports = SREManager;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "policy_enforce_tier_3_security",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"effect": "DENY",
|
|
5
|
+
"description": "Agents with Tier < 3 cannot modify security or governance files.",
|
|
6
|
+
"conditions": {
|
|
7
|
+
"resource": "*/security/*,*/governance/*",
|
|
8
|
+
"min_tier": 3
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
<!-- slide -->
|
|
12
|
+
{
|
|
13
|
+
"id": "policy_permit_developer_src",
|
|
14
|
+
"version": "1.0.0",
|
|
15
|
+
"effect": "PERMIT",
|
|
16
|
+
"description": "Developer agents can write to src and tests.",
|
|
17
|
+
"conditions": {
|
|
18
|
+
"action": "write_file",
|
|
19
|
+
"resource": "*/src/*,*/tests/*",
|
|
20
|
+
"min_tier": 2
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
<!-- slide -->
|
|
24
|
+
{
|
|
25
|
+
"id": "policy_permit_global_sync_lead",
|
|
26
|
+
"version": "1.0.0",
|
|
27
|
+
"effect": "PERMIT",
|
|
28
|
+
"description": "Lead Architects can push to the Federated Intelligence Mesh.",
|
|
29
|
+
"conditions": {
|
|
30
|
+
"action": "federated_sync_push",
|
|
31
|
+
"min_tier": 3
|
|
32
|
+
}
|
|
33
|
+
}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MindForge v5 — Agentic Policy Orchestrator (APO) Engine
|
|
3
|
+
* Evaluates agent intents against organizational security policies.
|
|
4
|
+
*/
|
|
5
|
+
'use strict';
|
|
6
|
+
|
|
7
|
+
const fs = require('node:fs');
|
|
8
|
+
const path = require('node:path');
|
|
9
|
+
|
|
10
|
+
class PolicyEngine {
|
|
11
|
+
constructor(config = {}) {
|
|
12
|
+
this.policiesDir = config.policiesDir || path.join(__dirname, 'policies');
|
|
13
|
+
this.ensurePoliciesDir();
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
ensurePoliciesDir() {
|
|
17
|
+
if (!fs.existsSync(this.policiesDir)) {
|
|
18
|
+
fs.mkdirSync(this.policiesDir, { recursive: true });
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Evaluates an agent's intent against all active policies.
|
|
24
|
+
* @param {Object} intent - The intent to evaluate.
|
|
25
|
+
* @param {string} intent.did - Source agent DID.
|
|
26
|
+
* @param {string} intent.action - Action type (e.g. 'write_file', 'delete_file').
|
|
27
|
+
* @param {string} intent.resource - Target resource (e.g. file path).
|
|
28
|
+
* @param {number} intent.tier - Agent trust tier.
|
|
29
|
+
* @returns {Object} - { verdict: 'PERMIT' | 'DENY', reason: string, requestId: string }
|
|
30
|
+
*/
|
|
31
|
+
evaluate(intent) {
|
|
32
|
+
const requestId = `pol_${Date.now()}_${Math.random().toString(36).slice(2, 7)}`;
|
|
33
|
+
console.log(`[APO-EVAL] [${requestId}] Evaluating intent: ${intent.action} on ${intent.resource} by ${intent.did}`);
|
|
34
|
+
|
|
35
|
+
const policies = this.loadPolicies();
|
|
36
|
+
|
|
37
|
+
// Default Deny if no policies found
|
|
38
|
+
if (policies.length === 0) {
|
|
39
|
+
return { verdict: 'DENY', reason: 'No organizational policies defined (Default Deny)', requestId };
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// 1. Check for explicit DENY rules first
|
|
43
|
+
for (const policy of policies) {
|
|
44
|
+
if (policy.effect === 'DENY' && this.matches(policy, intent)) {
|
|
45
|
+
return { verdict: 'DENY', reason: `Violation: ${policy.description || policy.id}`, requestId };
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// 2. Check for explicit PERMIT rules
|
|
50
|
+
for (const policy of policies) {
|
|
51
|
+
if (policy.effect === 'PERMIT' && this.matches(policy, intent)) {
|
|
52
|
+
return { verdict: 'PERMIT', reason: `Authorized by ${policy.id}`, requestId };
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
return { verdict: 'DENY', reason: 'No matching PERMIT policy found (Implicit Deny)', requestId };
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
loadPolicies() {
|
|
60
|
+
if (!fs.existsSync(this.policiesDir)) return [];
|
|
61
|
+
|
|
62
|
+
return fs.readdirSync(this.policiesDir)
|
|
63
|
+
.filter(f => f.endsWith('.json'))
|
|
64
|
+
.map(f => {
|
|
65
|
+
try {
|
|
66
|
+
const content = fs.readFileSync(path.join(this.policiesDir, f), 'utf8');
|
|
67
|
+
return JSON.parse(content);
|
|
68
|
+
} catch (err) {
|
|
69
|
+
console.error(`[APO-ERROR] Failed to parse policy ${f}:`, err.message);
|
|
70
|
+
return null;
|
|
71
|
+
}
|
|
72
|
+
})
|
|
73
|
+
.filter(Boolean);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Simple rule matcher (simulated OPA/Rego logic).
|
|
78
|
+
*/
|
|
79
|
+
matches(policy, intent) {
|
|
80
|
+
const { conditions } = policy;
|
|
81
|
+
if (!conditions) return true;
|
|
82
|
+
|
|
83
|
+
// Check DID match (supports wildcards)
|
|
84
|
+
if (conditions.did && !this.globMatch(conditions.did, intent.did)) return false;
|
|
85
|
+
|
|
86
|
+
// Check Action match
|
|
87
|
+
if (conditions.action && !this.globMatch(conditions.action, intent.action)) return false;
|
|
88
|
+
|
|
89
|
+
// Check Resource match
|
|
90
|
+
if (conditions.resource && !this.globMatch(conditions.resource, intent.resource)) return false;
|
|
91
|
+
|
|
92
|
+
// Check Tier match
|
|
93
|
+
if (conditions.min_tier && intent.tier < conditions.min_tier) return false;
|
|
94
|
+
|
|
95
|
+
return true;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
globMatch(pattern, text) {
|
|
99
|
+
if (pattern === '*') return true;
|
|
100
|
+
if (pattern === text) return true;
|
|
101
|
+
const regex = new RegExp('^' + pattern.replace(/\*/g, '.*') + '$');
|
|
102
|
+
return regex.test(text);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
module.exports = PolicyEngine;
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MindForge v5 — Agentic RBAC Manager
|
|
3
|
+
* Maps Agent DIDs to specific project roles and granular permissions.
|
|
4
|
+
*/
|
|
5
|
+
'use strict';
|
|
6
|
+
|
|
7
|
+
const fs = require('node:fs');
|
|
8
|
+
const path = require('node:path');
|
|
9
|
+
const ztai = require('./ztai-manager');
|
|
10
|
+
|
|
11
|
+
class RBACManager {
|
|
12
|
+
constructor(config = {}) {
|
|
13
|
+
this.rolesPath = config.rolesPath || path.join(process.cwd(), '.planning/AGENT-ROLES.json');
|
|
14
|
+
this.defaultRoles = {
|
|
15
|
+
'did:mindforge:planner': ['lead-architect', 'resource-optimizer'],
|
|
16
|
+
'did:mindforge:executor': ['developer', 'test-automator'],
|
|
17
|
+
'did:mindforge:reviewer': ['security-auditor', 'compliance-checker'],
|
|
18
|
+
'did:mindforge:researcher': ['knowledge-detective'],
|
|
19
|
+
'did:mindforge:tool': ['system-operator']
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Gets the roles assigned to a specific agent DID.
|
|
25
|
+
* @param {string} did
|
|
26
|
+
*/
|
|
27
|
+
getRoles(did) {
|
|
28
|
+
const roles = this.loadRoles();
|
|
29
|
+
// Return explicit roles OR default roles based on persona-matched DIDs
|
|
30
|
+
const explicit = roles[did];
|
|
31
|
+
if (explicit) return explicit;
|
|
32
|
+
|
|
33
|
+
// Default mapping (regex for persona-based DIDs)
|
|
34
|
+
for (const [pattern, defaultRoles] of Object.entries(this.defaultRoles)) {
|
|
35
|
+
if (did.includes(pattern)) return defaultRoles;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
return ['guest-agent'];
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* [HARDEN] Dynamically binds roles based on ZTAI trust tiers if no explicit role exists.
|
|
43
|
+
* Ensures high-trust agents automatically get architect-level visibility.
|
|
44
|
+
*/
|
|
45
|
+
async getRolesByTier(did) {
|
|
46
|
+
const manager = new ztai();
|
|
47
|
+
const identity = await manager.getIdentity();
|
|
48
|
+
const explicit = this.getRoles(did);
|
|
49
|
+
|
|
50
|
+
if (identity.tier >= 3) {
|
|
51
|
+
return [...new Set([...explicit, 'lead-architect'])];
|
|
52
|
+
}
|
|
53
|
+
if (identity.tier >= 2) {
|
|
54
|
+
return [...new Set([...explicit, 'developer'])];
|
|
55
|
+
}
|
|
56
|
+
return explicit;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
loadRoles() {
|
|
60
|
+
if (!fs.existsSync(this.rolesPath)) return {};
|
|
61
|
+
try {
|
|
62
|
+
return JSON.parse(fs.readFileSync(this.rolesPath, 'utf8'));
|
|
63
|
+
} catch {
|
|
64
|
+
return {};
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Assigns a role to an agent.
|
|
70
|
+
*/
|
|
71
|
+
assignRole(did, roles) {
|
|
72
|
+
const current = this.loadRoles();
|
|
73
|
+
current[did] = Array.isArray(roles) ? roles : [roles];
|
|
74
|
+
fs.writeFileSync(this.rolesPath, JSON.stringify(current, null, 2));
|
|
75
|
+
console.log(`[RBAC] Assigned roles [${roles}] to agent ${did}`);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Revokes all roles for an agent.
|
|
80
|
+
*/
|
|
81
|
+
revokeRoles(did) {
|
|
82
|
+
const current = this.loadRoles();
|
|
83
|
+
delete current[did];
|
|
84
|
+
fs.writeFileSync(this.rolesPath, JSON.stringify(current, null, 2));
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Checks if an agent has a specific permission based on their roles.
|
|
89
|
+
* @param {string} did
|
|
90
|
+
* @param {string} permission
|
|
91
|
+
*/
|
|
92
|
+
hasPermission(did, permission) {
|
|
93
|
+
const roles = this.getRoles(did);
|
|
94
|
+
const PERMISSION_MAP = {
|
|
95
|
+
'lead-architect': ['write_architecture', 'approve_adr', 'global_sync_push'],
|
|
96
|
+
'developer': ['write_src', 'read_src', 'execute_tests'],
|
|
97
|
+
'security-auditor': ['read_security', 'write_audit_log', 'block_execution'],
|
|
98
|
+
'system-operator': ['write_bin', 'modify_infrastructure'],
|
|
99
|
+
'guest-agent': ['read_src']
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
for (const role of roles) {
|
|
103
|
+
if (PERMISSION_MAP[role]?.includes(permission)) return true;
|
|
104
|
+
}
|
|
105
|
+
return false;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
module.exports = RBACManager;
|