secufusion-mcp 2.5.1 → 3.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/README.md +12 -11
- package/agents/planner.md +128 -119
- package/agents/reviewer.md +123 -0
- package/mcp/dist/benchmark_fixture.js +46 -0
- package/mcp/dist/benchmark_phase4.js +135 -0
- package/mcp/dist/benchmark_phase5.js +121 -0
- package/mcp/dist/benchmark_phase6.js +83 -0
- package/mcp/dist/benchmark_phase7.js +106 -0
- package/mcp/dist/benchmark_phase8.js +75 -0
- package/mcp/dist/benchmark_runner.js +130 -0
- package/mcp/dist/benchmark_traceability.js +74 -0
- package/mcp/dist/experience_manager.js +226 -0
- package/mcp/dist/graph_builder.js +148 -0
- package/mcp/dist/implementation_plan.js +92 -0
- package/mcp/dist/investigation_engine.js +59 -0
- package/mcp/dist/regression_engine.js +196 -0
- package/mcp/dist/requirement_manager.js +84 -0
- package/mcp/dist/run_benchmarks.js +62 -0
- package/mcp/dist/server.js +727 -144
- package/mcp/dist/test_engine.js +113 -0
- package/mcp/dist/test_graph.js +60 -0
- package/mcp/dist/traceability_engine.js +106 -0
- package/mcp/dist/trigger_extraction.js +4 -0
- package/mcp/dist/ui_intelligence.js +74 -0
- package/mcp/dist/validation_engine.js +69 -0
- package/package.json +1 -1
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import { savePlan, validatePlan } from "./implementation_plan.js";
|
|
4
|
+
import { generateTestObligations, aggregateValidation } from "./validation_engine.js";
|
|
5
|
+
import { executeTests, ingestTestResults, loadTestResults, correlateTestFailure } from "./test_engine.js";
|
|
6
|
+
import { saveRequirement } from "./requirement_manager.js";
|
|
7
|
+
import { saveTraceability } from "./traceability_engine.js";
|
|
8
|
+
import { performFullExtraction } from "./server.js";
|
|
9
|
+
const ecosystemRoot = "c:\\Users\\Yash\\Desktop\\mcp";
|
|
10
|
+
function setupRequirement(id, title, status, decisions = []) {
|
|
11
|
+
const req = {
|
|
12
|
+
id,
|
|
13
|
+
title,
|
|
14
|
+
status,
|
|
15
|
+
raw_request: title,
|
|
16
|
+
clarification_questions: [],
|
|
17
|
+
decisions
|
|
18
|
+
};
|
|
19
|
+
saveRequirement(ecosystemRoot, req);
|
|
20
|
+
}
|
|
21
|
+
function runPhase5Benchmark() {
|
|
22
|
+
console.log("=== RUNNING PHASE 5 TESTING INTELLIGENCE BENCHMARK ===");
|
|
23
|
+
// Initial Setup
|
|
24
|
+
const stats = performFullExtraction(ecosystemRoot);
|
|
25
|
+
const dnaPath = path.join(ecosystemRoot, ".secufusion", "dna.json");
|
|
26
|
+
const dna = JSON.parse(fs.readFileSync(dnaPath, "utf-8"));
|
|
27
|
+
const graph = dna.graph;
|
|
28
|
+
saveTraceability(ecosystemRoot, []);
|
|
29
|
+
fs.writeFileSync(path.join(ecosystemRoot, '.secufusion', 'tests', 'results.json'), '[]'); // Clear tests
|
|
30
|
+
console.log("\\n--- 1. TEST DISCOVERY & INGESTION (User Deletion) ---");
|
|
31
|
+
setupRequirement("REQ-DEL-5", "User Deletion Tests", "CONFIRMED", ["Authorized to delete user"]);
|
|
32
|
+
// Create Plan
|
|
33
|
+
let planDel = {
|
|
34
|
+
id: "PLAN-DEL-5",
|
|
35
|
+
requirement_id: "REQ-DEL-5",
|
|
36
|
+
status: "DRAFT",
|
|
37
|
+
summary: "Delete user test execution",
|
|
38
|
+
affected_services: ["sfn-iam-api"],
|
|
39
|
+
affected_files: [],
|
|
40
|
+
api_changes: ["DELETE /users/{id}"],
|
|
41
|
+
database_changes: ["DELETE cascade on users table"],
|
|
42
|
+
event_changes: [],
|
|
43
|
+
frontend_changes: [],
|
|
44
|
+
extension_changes: [],
|
|
45
|
+
security_implications: [],
|
|
46
|
+
implementation_steps: ["Perform deletion"],
|
|
47
|
+
test_obligations: ["Test deletion limits"],
|
|
48
|
+
validation_requirements: [],
|
|
49
|
+
traceability_requirements: [],
|
|
50
|
+
risks: [],
|
|
51
|
+
assumptions: [],
|
|
52
|
+
unknowns: [],
|
|
53
|
+
blockers: [],
|
|
54
|
+
created_at: new Date().toISOString(),
|
|
55
|
+
updated_at: new Date().toISOString(),
|
|
56
|
+
snapshot_id: "LATEST"
|
|
57
|
+
};
|
|
58
|
+
const obligations = generateTestObligations(planDel);
|
|
59
|
+
planDel.test_obligations = obligations;
|
|
60
|
+
savePlan(ecosystemRoot, planDel);
|
|
61
|
+
// Missing test execution -> Should be UNKNOWN
|
|
62
|
+
let errors = validatePlan(ecosystemRoot, planDel);
|
|
63
|
+
console.log("Validation Errors:", errors);
|
|
64
|
+
let tests = loadTestResults(ecosystemRoot);
|
|
65
|
+
let validation = aggregateValidation("CONFIRMED", errors, planDel.test_obligations, tests, [], false);
|
|
66
|
+
console.log("Validation State with MISSING test executions:", validation.overall); // Should be UNKNOWN
|
|
67
|
+
// Ingest PASS results
|
|
68
|
+
const passResult = {
|
|
69
|
+
id: "TR-1",
|
|
70
|
+
test_name: "testUserDeletionCascade",
|
|
71
|
+
suite_name: "UserDeletionTest",
|
|
72
|
+
repository: "sfn-iam-api",
|
|
73
|
+
file_path: "UNKNOWN",
|
|
74
|
+
status: "PASS",
|
|
75
|
+
duration_ms: 150,
|
|
76
|
+
exit_code: 0,
|
|
77
|
+
timestamp: new Date().toISOString(),
|
|
78
|
+
execution_identity: "EXEC-1"
|
|
79
|
+
};
|
|
80
|
+
ingestTestResults(ecosystemRoot, [passResult]);
|
|
81
|
+
tests = loadTestResults(ecosystemRoot);
|
|
82
|
+
validation = aggregateValidation("CONFIRMED", errors, planDel.test_obligations, tests, [], false);
|
|
83
|
+
console.log("Validation State with PASS tests:", validation.overall, "(tests=", validation.tests, ", planErrors=", errors, ", testResults=", tests, ")"); // Should be PASS
|
|
84
|
+
console.log("\\n--- 2. FAIL NORMALIZATION & CORRELATION (Retention) ---");
|
|
85
|
+
// Ingest FAIL results
|
|
86
|
+
const failResult = {
|
|
87
|
+
id: "TR-2",
|
|
88
|
+
test_name: "testRetentionPolicyCleanup",
|
|
89
|
+
suite_name: "RetentionJobTest",
|
|
90
|
+
repository: "sfn-events-api",
|
|
91
|
+
file_path: "UNKNOWN",
|
|
92
|
+
status: "FAIL",
|
|
93
|
+
duration_ms: 1200,
|
|
94
|
+
exit_code: 1,
|
|
95
|
+
failure_message: "Expected 0 events, found 5",
|
|
96
|
+
failure_type: "ASSERTION_FAILURE",
|
|
97
|
+
timestamp: new Date().toISOString(),
|
|
98
|
+
execution_identity: "EXEC-2"
|
|
99
|
+
};
|
|
100
|
+
// Map traceability to a fake RetentionJob node
|
|
101
|
+
graph.nodes.push({ id: "CLASS:RetentionJob", type: "CLASS", name: "RetentionJob", repository: "sfn-events-api" });
|
|
102
|
+
const edges = [{ source: "TEST:testRetentionPolicyCleanup", target: "CLASS:RetentionJob", relation: "TESTS", confidence: "DIRECT", extractionMethod: "STATIC" }];
|
|
103
|
+
const correlated = correlateTestFailure(graph, edges, failResult);
|
|
104
|
+
console.log("Failure Correlated Artifacts:", correlated);
|
|
105
|
+
ingestTestResults(ecosystemRoot, [failResult]);
|
|
106
|
+
tests = loadTestResults(ecosystemRoot);
|
|
107
|
+
validation = aggregateValidation("CONFIRMED", errors, planDel.test_obligations, tests, [], false);
|
|
108
|
+
console.log("Validation State with FAIL test:", validation.overall); // Should be FAIL
|
|
109
|
+
console.log("\\n--- 3. TEST EXECUTION (Controlled BOUNDARY) ---");
|
|
110
|
+
// Run an echo command
|
|
111
|
+
const execResults = executeTests(ecosystemRoot, "echo 'Testing controlled execution'", ".");
|
|
112
|
+
console.log("Execution Result Status:", execResults[0].status);
|
|
113
|
+
console.log("Execution Output Captured:", execResults.length);
|
|
114
|
+
}
|
|
115
|
+
try {
|
|
116
|
+
runPhase5Benchmark();
|
|
117
|
+
}
|
|
118
|
+
catch (e) {
|
|
119
|
+
console.error("Benchmark failed:", e);
|
|
120
|
+
process.exit(1);
|
|
121
|
+
}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import fs from "fs";
|
|
2
|
+
import path from "path";
|
|
3
|
+
import { recordExperience, getEngineeringExperience, validateExperience, markExperienceStale, linkExperience, findExperienceConflicts } from "./experience_manager.js";
|
|
4
|
+
function resetExperience(ecosystemRoot) {
|
|
5
|
+
const expPath = path.join(ecosystemRoot, '.secufusion', 'experience.json');
|
|
6
|
+
if (fs.existsSync(expPath))
|
|
7
|
+
fs.unlinkSync(expPath);
|
|
8
|
+
}
|
|
9
|
+
function runBenchmark() {
|
|
10
|
+
console.log("=== RUNNING PHASE 6 ENGINEERING KNOWLEDGE BENCHMARK ===\n");
|
|
11
|
+
// Use a temp workspace to avoid polluting real .secufusion
|
|
12
|
+
const ecosystemRoot = path.join(process.cwd(), '.benchmark_tmp_ph6');
|
|
13
|
+
if (!fs.existsSync(ecosystemRoot))
|
|
14
|
+
fs.mkdirSync(ecosystemRoot, { recursive: true });
|
|
15
|
+
resetExperience(ecosystemRoot);
|
|
16
|
+
try {
|
|
17
|
+
console.log("--- 1. RECORDING PROPOSED EXPERIENCE ---");
|
|
18
|
+
const exp1 = recordExperience(ecosystemRoot, {
|
|
19
|
+
id: "EXP-RETENTION",
|
|
20
|
+
title: "Retention Cleanup Idempotency",
|
|
21
|
+
summary: "Previous retention cleanup required idempotent execution due to retries.",
|
|
22
|
+
category: "SCHEDULING",
|
|
23
|
+
lesson: "Always use idempotent queries for cleanup jobs in RetentionPolicy.",
|
|
24
|
+
outcome: "FAILURE",
|
|
25
|
+
affected_components: ["CLASS:RetentionJob", "CLASS:Scheduler"],
|
|
26
|
+
status: "PROPOSED",
|
|
27
|
+
evidence: "Run failures in Phase 3"
|
|
28
|
+
});
|
|
29
|
+
console.log(`Recorded: ${exp1.id} with status ${exp1.status}`);
|
|
30
|
+
console.log("\n--- 2. VALIDATING EXPERIENCE WITH EVIDENCE ---");
|
|
31
|
+
const validatedExp = validateExperience(ecosystemRoot, exp1.id, "TEST-RESULT: PASS for idempotent query");
|
|
32
|
+
console.log(`Validated: ${validatedExp.id}, Status: ${validatedExp.status}, Evidence: ${validatedExp.evidence}`);
|
|
33
|
+
console.log("\n--- 3. TRACEABILITY INTEGRATION (LINKING) ---");
|
|
34
|
+
const linkedExp = linkExperience(ecosystemRoot, exp1.id, {
|
|
35
|
+
source_requirement_id: "REQ-101",
|
|
36
|
+
source_traceability_ids: ["TR-99"]
|
|
37
|
+
});
|
|
38
|
+
console.log(`Linked: ${linkedExp.id}, Source Req: ${linkedExp.source_requirement_id}`);
|
|
39
|
+
console.log("\n--- 4. RETENTION BENCHMARK (STALENESS) ---");
|
|
40
|
+
// Simulated: We discover that the current repository scheduler implementation has changed
|
|
41
|
+
console.log("Simulating repository evidence check: Scheduler has been replaced with Quartz.");
|
|
42
|
+
const staleExp = markExperienceStale(ecosystemRoot, exp1.id, "Scheduler implementation replaced by Quartz, making old idempotency logic obsolete.");
|
|
43
|
+
console.log(`Stale State: ${staleExp.status}`);
|
|
44
|
+
console.log(`Stale Reason in context: ${staleExp.context}`);
|
|
45
|
+
console.log("\n--- 5. USER DELETION BENCHMARK (CONFLICTS) ---");
|
|
46
|
+
recordExperience(ecosystemRoot, {
|
|
47
|
+
id: "EXP-DEL-1",
|
|
48
|
+
title: "Hard delete user events",
|
|
49
|
+
summary: "User deletion must cascade to events.",
|
|
50
|
+
category: "DELETION",
|
|
51
|
+
lesson: "Use cascade delete.",
|
|
52
|
+
outcome: "SUCCESS",
|
|
53
|
+
affected_components: ["CLASS:UserDeletionService"],
|
|
54
|
+
status: "VALIDATED"
|
|
55
|
+
});
|
|
56
|
+
recordExperience(ecosystemRoot, {
|
|
57
|
+
id: "EXP-DEL-2",
|
|
58
|
+
title: "Anonymize user events",
|
|
59
|
+
summary: "User deletion must anonymize events.",
|
|
60
|
+
category: "DELETION",
|
|
61
|
+
lesson: "Use anonymization strategy.",
|
|
62
|
+
outcome: "SUCCESS",
|
|
63
|
+
affected_components: ["CLASS:UserDeletionService"],
|
|
64
|
+
status: "VALIDATED"
|
|
65
|
+
});
|
|
66
|
+
const conflicts = findExperienceConflicts(ecosystemRoot);
|
|
67
|
+
console.log(`Conflicts Detected: ${conflicts.length} records on shared component.`);
|
|
68
|
+
conflicts.forEach(c => console.log(` - ${c.id}: ${c.title} (Outcome: ${c.outcome})`));
|
|
69
|
+
console.log("\n--- 6. BOUNDED RETRIEVAL ---");
|
|
70
|
+
const retrieved = getEngineeringExperience(ecosystemRoot, "", { affected_components: ["CLASS:RetentionJob"] });
|
|
71
|
+
console.log(`Retrieved ${retrieved.length} records for CLASS:RetentionJob`);
|
|
72
|
+
console.log(`Retrieved Record Status: ${retrieved[0].status}`);
|
|
73
|
+
console.log("\n=== BENCHMARK COMPLETE (ALL PASS) ===");
|
|
74
|
+
}
|
|
75
|
+
catch (e) {
|
|
76
|
+
console.error("Benchmark Failed:", e.message);
|
|
77
|
+
process.exit(1);
|
|
78
|
+
}
|
|
79
|
+
finally {
|
|
80
|
+
fs.rmSync(ecosystemRoot, { recursive: true, force: true });
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
runBenchmark();
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import fs from "fs";
|
|
2
|
+
import path from "path";
|
|
3
|
+
import { compareRepositorySnapshots, detectArchitectureDrift, detectRequirementDrift, detectTraceabilityDrift, getRegressionContext } from "./regression_engine.js";
|
|
4
|
+
import { recordExperience } from "./experience_manager.js";
|
|
5
|
+
function reset(ecosystemRoot) {
|
|
6
|
+
if (fs.existsSync(ecosystemRoot)) {
|
|
7
|
+
fs.rmSync(ecosystemRoot, { recursive: true, force: true });
|
|
8
|
+
}
|
|
9
|
+
fs.mkdirSync(ecosystemRoot, { recursive: true });
|
|
10
|
+
}
|
|
11
|
+
function runBenchmark() {
|
|
12
|
+
console.log("=== RUNNING PHASE 7 CONTINUOUS INTELLIGENCE BENCHMARK ===\n");
|
|
13
|
+
const ecosystemRoot = path.join(process.cwd(), '.benchmark_tmp_ph7');
|
|
14
|
+
reset(ecosystemRoot);
|
|
15
|
+
try {
|
|
16
|
+
// --- Setup Data ---
|
|
17
|
+
const baseSnapshot = {
|
|
18
|
+
schema_version: "1.0",
|
|
19
|
+
nodes: [
|
|
20
|
+
{ id: "SERVICE:sfn-iam-api", type: "SERVICE", name: "sfn-iam-api", repository: "sfn-iam-api" },
|
|
21
|
+
{ id: "SERVICE:sfn-tenants-api", type: "SERVICE", name: "sfn-tenants-api", repository: "sfn-tenants-api" },
|
|
22
|
+
{ id: "CLASS:UserDeletionService", type: "CLASS", name: "UserDeletionService", repository: "sfn-iam-api" },
|
|
23
|
+
{ id: "CLASS:RetentionJob", type: "CLASS", name: "RetentionJob", repository: "sfn-tenants-api" },
|
|
24
|
+
{ id: "API:GET:/api/tenants", type: "API", name: "GET /api/tenants", repository: "sfn-tenants-api" },
|
|
25
|
+
{ id: "TOPIC:user-deleted", type: "TOPIC", name: "user-deleted" }
|
|
26
|
+
],
|
|
27
|
+
edges: [
|
|
28
|
+
{ id: "E1", source: "CLASS:UserDeletionService", target: "TOPIC:user-deleted", type: "PRODUCES" },
|
|
29
|
+
{ id: "E2", source: "SERVICE:sfn-iam-api", target: "SERVICE:sfn-tenants-api", type: "CALLS" }
|
|
30
|
+
]
|
|
31
|
+
};
|
|
32
|
+
const currentSnapshot = {
|
|
33
|
+
schema_version: "1.0",
|
|
34
|
+
nodes: [
|
|
35
|
+
{ id: "SERVICE:sfn-iam-api", type: "SERVICE", name: "sfn-iam-api", repository: "sfn-iam-api" },
|
|
36
|
+
{ id: "SERVICE:sfn-tenants-api", type: "SERVICE", name: "sfn-tenants-api", repository: "sfn-tenants-api" },
|
|
37
|
+
// UserDeletionService still exists but metadata/logic changed (represented via snapshot diff)
|
|
38
|
+
{ id: "CLASS:UserDeletionService", type: "CLASS", name: "UserDeletionService", repository: "sfn-iam-api", metadata: { updated: true } },
|
|
39
|
+
{ id: "CLASS:RetentionJob", type: "CLASS", name: "RetentionJob", repository: "sfn-tenants-api" },
|
|
40
|
+
// API GET /api/tenants is REMOVED
|
|
41
|
+
{ id: "TOPIC:user-deleted", type: "TOPIC", name: "user-deleted" }
|
|
42
|
+
],
|
|
43
|
+
edges: [
|
|
44
|
+
// Produces edge E1 is REMOVED (Architecture drift)
|
|
45
|
+
// Calls edge E2 is REMOVED
|
|
46
|
+
]
|
|
47
|
+
};
|
|
48
|
+
const reqs = [
|
|
49
|
+
{
|
|
50
|
+
id: "REQ-1", status: "CONFIRMED",
|
|
51
|
+
apis: ["GET:/api/tenants"]
|
|
52
|
+
}
|
|
53
|
+
];
|
|
54
|
+
const links = [
|
|
55
|
+
{ id: "L1", source: "REQ-1", target: "API:GET:/api/tenants", type: "IMPLEMENTS", provenance: "USER_CONFIRMED", confidence: "CONFIRMED" }
|
|
56
|
+
];
|
|
57
|
+
const allTests = [
|
|
58
|
+
{ id: "TEST-1", name: "testUserDeletionCascade", target_components: ["CLASS:UserDeletionService"] }
|
|
59
|
+
];
|
|
60
|
+
recordExperience(ecosystemRoot, {
|
|
61
|
+
id: "EXP-1", title: "Orphaned Events", summary: "User deletion left event references orphaned.",
|
|
62
|
+
category: "DELETION", lesson: "Validate cascade deletion.", outcome: "FAILURE",
|
|
63
|
+
affected_components: ["CLASS:UserDeletionService"], status: "VALIDATED"
|
|
64
|
+
});
|
|
65
|
+
// --- Benchmark 1: Snapshot Comparison ---
|
|
66
|
+
console.log("--- 1. SNAPSHOT COMPARISON ---");
|
|
67
|
+
const changes = compareRepositorySnapshots(baseSnapshot, currentSnapshot);
|
|
68
|
+
console.log(`Changes detected: ${changes.length}`);
|
|
69
|
+
changes.forEach(c => console.log(` - ${c.category}: ${c.artifact_id}`));
|
|
70
|
+
// --- Benchmark 2: Architecture Drift ---
|
|
71
|
+
console.log("\n--- 2. ARCHITECTURE DRIFT (BENCHMARK #26) ---");
|
|
72
|
+
const archDrift = detectArchitectureDrift(baseSnapshot, currentSnapshot);
|
|
73
|
+
console.log(`Drifts detected: ${archDrift.length}`);
|
|
74
|
+
archDrift.forEach(d => console.log(` - ${d.category} on ${d.affected_component} (Status: ${d.status})`));
|
|
75
|
+
// --- Benchmark 3: Requirement Drift ---
|
|
76
|
+
console.log("\n--- 3. REQUIREMENT DRIFT (BENCHMARK #27) ---");
|
|
77
|
+
const reqDrift = detectRequirementDrift(reqs, currentSnapshot);
|
|
78
|
+
console.log(`Requirement Drifts: ${reqDrift.length}`);
|
|
79
|
+
reqDrift.forEach(d => console.log(` - ${d.condition}: ${d.expected_artifact} for ${d.requirement_id}`));
|
|
80
|
+
// --- Benchmark 4: Traceability Drift ---
|
|
81
|
+
console.log("\n--- 4. TRACEABILITY DRIFT ---");
|
|
82
|
+
const traceDrift = detectTraceabilityDrift(links, currentSnapshot);
|
|
83
|
+
console.log(`Traceability Drifts: ${traceDrift.length}`);
|
|
84
|
+
traceDrift.forEach(d => console.log(` - ${d.condition}: ${d.target_id}`));
|
|
85
|
+
// --- Benchmark 5: Regression Tests & Context ---
|
|
86
|
+
console.log("\n--- 5. USER DELETION REGRESSION (BENCHMARK #25) & COVERAGE (BENCHMARK #28) ---");
|
|
87
|
+
const context = getRegressionContext(ecosystemRoot, baseSnapshot, currentSnapshot, reqs, links, allTests);
|
|
88
|
+
console.log(`Historical Failures matching changes: ${context.historical_failures.length}`);
|
|
89
|
+
console.log(`Regression Tests found: ${context.regression_tests.length}`);
|
|
90
|
+
console.log("\n--- 6. RISK INDICATORS (BENCHMARK #29 CROSS-SERVICE) ---");
|
|
91
|
+
context.risk_indicators.forEach(r => {
|
|
92
|
+
console.log(` - ${r.indicator} (${r.risk_level})`);
|
|
93
|
+
if (r.indicator === "CROSS_SERVICE_CHANGE")
|
|
94
|
+
console.log(` Services: ${r.evidence.services.join(", ")}`);
|
|
95
|
+
});
|
|
96
|
+
console.log("\n=== BENCHMARK COMPLETE (ALL PASS) ===");
|
|
97
|
+
}
|
|
98
|
+
catch (e) {
|
|
99
|
+
console.error("Benchmark Failed:", e.message);
|
|
100
|
+
process.exit(1);
|
|
101
|
+
}
|
|
102
|
+
finally {
|
|
103
|
+
fs.rmSync(ecosystemRoot, { recursive: true, force: true });
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
runBenchmark();
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import fs from "fs";
|
|
2
|
+
import path from "path";
|
|
3
|
+
import { discoverUIPatterns, generateStaticUIReference, getDesignContext } from "./ui_intelligence.js";
|
|
4
|
+
function reset(ecosystemRoot) {
|
|
5
|
+
if (fs.existsSync(ecosystemRoot)) {
|
|
6
|
+
fs.rmSync(ecosystemRoot, { recursive: true, force: true });
|
|
7
|
+
}
|
|
8
|
+
fs.mkdirSync(ecosystemRoot, { recursive: true });
|
|
9
|
+
}
|
|
10
|
+
function runBenchmark() {
|
|
11
|
+
console.log("=== RUNNING PHASE 8 UX & UI DESIGN BENCHMARK ===\n");
|
|
12
|
+
const ecosystemRoot = path.join(process.cwd(), '.benchmark_tmp_ph8');
|
|
13
|
+
reset(ecosystemRoot);
|
|
14
|
+
try {
|
|
15
|
+
// --- Setup Mock State ---
|
|
16
|
+
const snapshot = {
|
|
17
|
+
schema_version: "1.0",
|
|
18
|
+
nodes: [
|
|
19
|
+
{ id: "FRONTEND_APP:sfn-web-ui", type: "FRONTEND_APP", name: "sfn-web-ui" },
|
|
20
|
+
{ id: "UI_PATTERN:TenantSelector", type: "UI_PATTERN", name: "TenantSelector", repository: "sfn-web-ui", evidence: { filePath: "src/components/TenantSelector.tsx" }, metadata: { type: "React", description: "Standard tenant dropdown" } },
|
|
21
|
+
{ id: "UI_PATTERN:ConfirmationModal", type: "UI_PATTERN", name: "ConfirmationModal", repository: "sfn-web-ui", evidence: { filePath: "src/components/ConfirmationModal.tsx" }, metadata: { type: "React", description: "Destructive confirmation dialog" } },
|
|
22
|
+
{ id: "FRONTEND_COMPONENT:RetentionSettings", type: "FRONTEND_COMPONENT", name: "RetentionSettings", repository: "sfn-web-ui", evidence: { filePath: "src/pages/RetentionSettings.tsx" }, metadata: { type: "React" } },
|
|
23
|
+
{ id: "API:DELETE:/api/users", type: "API", name: "DELETE /api/users", repository: "sfn-iam-api" }
|
|
24
|
+
],
|
|
25
|
+
edges: []
|
|
26
|
+
};
|
|
27
|
+
fs.mkdirSync(path.join(ecosystemRoot, ".secufusion", "requirements"), { recursive: true });
|
|
28
|
+
const retentionReq = { id: "REQ-RETENTION", status: "CONFIRMED" };
|
|
29
|
+
const deletionReq = { id: "REQ-DELETE-USER", status: "CONFIRMED", apis: ["DELETE:/api/users"] };
|
|
30
|
+
fs.writeFileSync(path.join(ecosystemRoot, ".secufusion", "requirements", "REQ-RETENTION.json"), JSON.stringify(retentionReq));
|
|
31
|
+
fs.writeFileSync(path.join(ecosystemRoot, ".secufusion", "requirements", "REQ-DELETE-USER.json"), JSON.stringify(deletionReq));
|
|
32
|
+
// --- Benchmark 1: Retention Policy (New Feature) ---
|
|
33
|
+
console.log("--- 1. RETENTION POLICY BENCHMARK ---");
|
|
34
|
+
const retentionContext = getDesignContext(ecosystemRoot, "REQ-RETENTION", snapshot);
|
|
35
|
+
console.log(`Context status: ${retentionContext.status}`);
|
|
36
|
+
const tenantPatterns = discoverUIPatterns(ecosystemRoot, "tenant selector", snapshot);
|
|
37
|
+
console.log(`Discovered Tenant Patterns: ${tenantPatterns.length}`);
|
|
38
|
+
tenantPatterns.forEach(p => console.log(` - ${p.name} (Source: ${p.evidence.location.filePath})`));
|
|
39
|
+
const retentionHtml = `<html><body><h1>Retention Policy</h1><p>Set retention here</p></body></html>`;
|
|
40
|
+
const retentionPath = generateStaticUIReference(ecosystemRoot, "DESIGN-RETENTION", retentionHtml, { status: "DRAFT" });
|
|
41
|
+
console.log(`Generated HTML at: ${retentionPath}`);
|
|
42
|
+
const retentionContent = fs.readFileSync(retentionPath, "utf-8");
|
|
43
|
+
if (retentionContent.includes("REFERENCE_ONLY"))
|
|
44
|
+
console.log("SUCCESS: Retention HTML contains REFERENCE_ONLY marker.");
|
|
45
|
+
// --- Benchmark 2: User Deletion (Destructive Operation) ---
|
|
46
|
+
console.log("\n--- 2. USER DELETION BENCHMARK ---");
|
|
47
|
+
const deletionContext = getDesignContext(ecosystemRoot, "REQ-DELETE-USER", snapshot);
|
|
48
|
+
console.log(`Architecture Context Nodes: ${deletionContext.architecture_context.length}`);
|
|
49
|
+
deletionContext.architecture_context.forEach((n) => console.log(` - Affected: ${n.id}`));
|
|
50
|
+
const deletePatterns = discoverUIPatterns(ecosystemRoot, "confirmation destructive", snapshot);
|
|
51
|
+
console.log(`Discovered Confirmation Patterns: ${deletePatterns.length}`);
|
|
52
|
+
deletePatterns.forEach(p => console.log(` - ${p.name} (Source: ${p.evidence.location.filePath})`));
|
|
53
|
+
const deletionHtml = `<html><body><h1>Delete User</h1></body></html>`;
|
|
54
|
+
const deletionPath = generateStaticUIReference(ecosystemRoot, "DESIGN-DELETE-USER", deletionHtml, { status: "USER_REVIEW_REQUIRED" });
|
|
55
|
+
console.log(`Generated HTML at: ${deletionPath}`);
|
|
56
|
+
const deletionContent = fs.readFileSync(deletionPath, "utf-8");
|
|
57
|
+
if (deletionContent.includes("REFERENCE_ONLY"))
|
|
58
|
+
console.log("SUCCESS: Deletion HTML contains REFERENCE_ONLY marker.");
|
|
59
|
+
// --- Benchmark 3: Validate Metadata ---
|
|
60
|
+
console.log("\n--- 3. DESIGN METADATA VALIDATION ---");
|
|
61
|
+
const metaPath = path.join(ecosystemRoot, ".secufusion", "designs", "DESIGN-DELETE-USER", "design.json");
|
|
62
|
+
const meta = JSON.parse(fs.readFileSync(metaPath, "utf-8"));
|
|
63
|
+
console.log(`Design Status: ${meta.status}`);
|
|
64
|
+
console.log(`Design ID: ${meta.design_id}`);
|
|
65
|
+
console.log("\n=== BENCHMARK COMPLETE (ALL PASS) ===");
|
|
66
|
+
}
|
|
67
|
+
catch (e) {
|
|
68
|
+
console.error("Benchmark Failed:", e.message);
|
|
69
|
+
process.exit(1);
|
|
70
|
+
}
|
|
71
|
+
finally {
|
|
72
|
+
fs.rmSync(ecosystemRoot, { recursive: true, force: true });
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
runBenchmark();
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import { investigateEntity, investigateRelationship } from "./investigation_engine.js";
|
|
2
|
+
import { saveRequirement, generateConfirmedSpecification } from "./requirement_manager.js";
|
|
3
|
+
import fs from 'fs';
|
|
4
|
+
import path from 'path';
|
|
5
|
+
const ecosystemRoot = "c:\\Users\\Yash\\Desktop\\mcp";
|
|
6
|
+
function getGraph() {
|
|
7
|
+
const dnaPath = path.join(ecosystemRoot, ".secufusion", "dna.json");
|
|
8
|
+
return JSON.parse(fs.readFileSync(dnaPath, "utf-8")).graph;
|
|
9
|
+
}
|
|
10
|
+
function runRetentionBenchmark() {
|
|
11
|
+
console.log("=== RUNNING RETENTION BENCHMARK ===");
|
|
12
|
+
const reqId = "BM-RET-1";
|
|
13
|
+
let req = {
|
|
14
|
+
id: reqId,
|
|
15
|
+
title: "Retention Policy Setup",
|
|
16
|
+
status: "RAW",
|
|
17
|
+
clarification_questions: [],
|
|
18
|
+
raw_request: "The feature is available only to Master MSSP/MSSP users. Any tenant can configure retention. After span, events are cleaned using dynamic scheduling."
|
|
19
|
+
};
|
|
20
|
+
saveRequirement(ecosystemRoot, req);
|
|
21
|
+
req.status = "UNDERSTOOD";
|
|
22
|
+
// 1. Investigation Phase
|
|
23
|
+
req.status = "INVESTIGATING";
|
|
24
|
+
const graph = getGraph();
|
|
25
|
+
const retRes = investigateEntity(graph, "Retention");
|
|
26
|
+
const tenantRes = investigateEntity(graph, "Tenant");
|
|
27
|
+
const eventRes = investigateEntity(graph, "Event");
|
|
28
|
+
const relRes = investigateRelationship(graph, "Retention", "Event");
|
|
29
|
+
req.facts = [
|
|
30
|
+
retRes.summary,
|
|
31
|
+
tenantRes.summary,
|
|
32
|
+
eventRes.summary,
|
|
33
|
+
relRes.summary
|
|
34
|
+
];
|
|
35
|
+
// 2. Unknown / Conflict Detection
|
|
36
|
+
req.unknowns = [
|
|
37
|
+
"Which timestamp governs retention on Event?",
|
|
38
|
+
"Are all event types covered?",
|
|
39
|
+
"What happens when retention changes?",
|
|
40
|
+
"Is deletion hard delete, soft delete?",
|
|
41
|
+
"What authorization applies to parent/child access?"
|
|
42
|
+
];
|
|
43
|
+
req.blockers = ["Missing explicit deletion semantics", "Missing authorization logic"];
|
|
44
|
+
saveRequirement(ecosystemRoot, req);
|
|
45
|
+
// 3. Clarification Required
|
|
46
|
+
req.status = "CLARIFICATION_REQUIRED";
|
|
47
|
+
req.clarification_questions.push({
|
|
48
|
+
id: "CQ-RET-1",
|
|
49
|
+
topic: "Deletion Semantics",
|
|
50
|
+
issue: "Deletion is destructive and type is unknown.",
|
|
51
|
+
state: "OPEN",
|
|
52
|
+
severity: "CRITICAL",
|
|
53
|
+
blocking: true,
|
|
54
|
+
question: "Is the cleanup a hard delete or soft delete? Which timestamp governs it?",
|
|
55
|
+
evidence: retRes.evidence,
|
|
56
|
+
created_at: new Date().toISOString()
|
|
57
|
+
});
|
|
58
|
+
saveRequirement(ecosystemRoot, req);
|
|
59
|
+
// 4. Resolve and Confirm
|
|
60
|
+
req.clarification_questions[0].state = "RESOLVED";
|
|
61
|
+
req.clarification_questions[0].answer = "Hard delete governed by created_at.";
|
|
62
|
+
req.clarification_questions[0].decision = "Retention cleanup will hard delete based on created_at.";
|
|
63
|
+
req.decisions = [req.clarification_questions[0].decision];
|
|
64
|
+
req.blockers = [];
|
|
65
|
+
req.status = "CONFIRMED";
|
|
66
|
+
req.tenancy = "Parent reads/writes child policy";
|
|
67
|
+
req.authorization = "Master MSSP only";
|
|
68
|
+
req.data_lifecycle = "Hard delete after N days based on created_at";
|
|
69
|
+
saveRequirement(ecosystemRoot, req);
|
|
70
|
+
console.log(generateConfirmedSpecification(req));
|
|
71
|
+
}
|
|
72
|
+
function runUserDeletionBenchmark() {
|
|
73
|
+
console.log("=== RUNNING USER DELETION BENCHMARK ===");
|
|
74
|
+
const reqId = "BM-DEL-1";
|
|
75
|
+
let req = {
|
|
76
|
+
id: reqId,
|
|
77
|
+
title: "User Deletion",
|
|
78
|
+
status: "RAW",
|
|
79
|
+
clarification_questions: [],
|
|
80
|
+
raw_request: "End-to-end functionality for deleting a selected user from the UI across all services."
|
|
81
|
+
};
|
|
82
|
+
saveRequirement(ecosystemRoot, req);
|
|
83
|
+
req.status = "UNDERSTOOD";
|
|
84
|
+
req.status = "INVESTIGATING";
|
|
85
|
+
const graph = getGraph();
|
|
86
|
+
const userRes = investigateEntity(graph, "User");
|
|
87
|
+
const eventRes = investigateEntity(graph, "Event");
|
|
88
|
+
const userEventRel = investigateRelationship(graph, "User", "Event");
|
|
89
|
+
req.facts = [
|
|
90
|
+
userRes.summary,
|
|
91
|
+
userEventRel.summary
|
|
92
|
+
];
|
|
93
|
+
req.unknowns = [
|
|
94
|
+
"What happens to events generated by the user?",
|
|
95
|
+
"Are there audit records that must be retained?"
|
|
96
|
+
];
|
|
97
|
+
req.blockers = ["Unspecified retention of related audit events"];
|
|
98
|
+
saveRequirement(ecosystemRoot, req);
|
|
99
|
+
req.status = "CLARIFICATION_REQUIRED";
|
|
100
|
+
req.clarification_questions.push({
|
|
101
|
+
id: "CQ-DEL-1",
|
|
102
|
+
topic: "Orphan Data",
|
|
103
|
+
issue: "Events associated with the user exist.",
|
|
104
|
+
state: "OPEN",
|
|
105
|
+
severity: "CRITICAL",
|
|
106
|
+
blocking: true,
|
|
107
|
+
question: "Should events created by the user be deleted, anonymized, or retained?",
|
|
108
|
+
evidence: userEventRel.evidence,
|
|
109
|
+
created_at: new Date().toISOString()
|
|
110
|
+
});
|
|
111
|
+
saveRequirement(ecosystemRoot, req);
|
|
112
|
+
req.clarification_questions[0].state = "RESOLVED";
|
|
113
|
+
req.clarification_questions[0].answer = "Anonymize events, retain audit records.";
|
|
114
|
+
req.clarification_questions[0].decision = "Events will be anonymized instead of deleted.";
|
|
115
|
+
req.decisions = [req.clarification_questions[0].decision];
|
|
116
|
+
req.blockers = [];
|
|
117
|
+
req.status = "CONFIRMED";
|
|
118
|
+
req.data_lifecycle = "Hard delete user metadata, anonymize associated events, retain audit records.";
|
|
119
|
+
saveRequirement(ecosystemRoot, req);
|
|
120
|
+
console.log(generateConfirmedSpecification(req));
|
|
121
|
+
}
|
|
122
|
+
try {
|
|
123
|
+
runRetentionBenchmark();
|
|
124
|
+
console.log("\\n");
|
|
125
|
+
runUserDeletionBenchmark();
|
|
126
|
+
}
|
|
127
|
+
catch (e) {
|
|
128
|
+
console.error("Benchmark failed:", e);
|
|
129
|
+
process.exit(1);
|
|
130
|
+
}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import { performFullExtraction } from "./server.js";
|
|
4
|
+
import { addTraceabilityLink, traceForward, findTraceabilityGaps, loadTraceability, saveTraceability } from "./traceability_engine.js";
|
|
5
|
+
import { saveRequirement } from "./requirement_manager.js";
|
|
6
|
+
const ecosystemRoot = "c:\\Users\\Yash\\Desktop\\mcp";
|
|
7
|
+
function setupRequirement(id, title) {
|
|
8
|
+
const req = {
|
|
9
|
+
id,
|
|
10
|
+
title,
|
|
11
|
+
status: "CONFIRMED",
|
|
12
|
+
raw_request: title,
|
|
13
|
+
clarification_questions: []
|
|
14
|
+
};
|
|
15
|
+
saveRequirement(ecosystemRoot, req);
|
|
16
|
+
}
|
|
17
|
+
function runRealBenchmark() {
|
|
18
|
+
console.log("=== RUNNING REAL REPOSITORY TRACEABILITY BENCHMARK ===");
|
|
19
|
+
// 1. Extract Real Repository
|
|
20
|
+
console.log("Extracting actual repository...");
|
|
21
|
+
const stats = performFullExtraction(ecosystemRoot);
|
|
22
|
+
console.log("Extraction stats:", JSON.stringify(stats));
|
|
23
|
+
const dnaPath = path.join(ecosystemRoot, ".secufusion", "dna.json");
|
|
24
|
+
const dna = JSON.parse(fs.readFileSync(dnaPath, "utf-8"));
|
|
25
|
+
const graph = dna.graph;
|
|
26
|
+
// Clear previous traceability
|
|
27
|
+
saveTraceability(ecosystemRoot, []);
|
|
28
|
+
// --- Retention Benchmark ---
|
|
29
|
+
console.log("\\n--- RETENTION BENCHMARK (REAL REPO) ---");
|
|
30
|
+
setupRequirement("REQ-RET-1", "Retention Policy");
|
|
31
|
+
const retentionNodes = graph.nodes.filter((n) => (n.name || "").toLowerCase().includes("retention"));
|
|
32
|
+
for (const node of retentionNodes) {
|
|
33
|
+
addTraceabilityLink(ecosystemRoot, "REQUIREMENT:REQ-RET-1", node.id, "IMPLEMENTED_BY", "INFERRED", "SUPPORTED");
|
|
34
|
+
}
|
|
35
|
+
const edges1 = loadTraceability(ecosystemRoot);
|
|
36
|
+
const traceRet = traceForward(graph, edges1, "REQUIREMENT:REQ-RET-1", 3);
|
|
37
|
+
const gapsRet = findTraceabilityGaps(ecosystemRoot, graph, edges1);
|
|
38
|
+
console.log("Traced Artifacts:", traceRet.nodes.length - 1);
|
|
39
|
+
console.log("Evidence Found:", traceRet.nodes.filter((n) => n.type !== "UNKNOWN" && !n.id.startsWith("REQUIREMENT:")).length);
|
|
40
|
+
console.log("Traceability Gaps (Retention):", gapsRet.filter((g) => g.id === "REQUIREMENT:REQ-RET-1").length > 0 ? "YES (REQUIREMENT_WITHOUT_IMPLEMENTATION)" : "NO");
|
|
41
|
+
console.log("Affected Services:", traceRet.nodes.filter((n) => n.type === "SERVICE").map((n) => n.name));
|
|
42
|
+
console.log("Affected APIs:", traceRet.nodes.filter((n) => n.type === "API").map((n) => n.name));
|
|
43
|
+
console.log("Affected DBs:", traceRet.nodes.filter((n) => n.type === "DATABASE_TABLE").map((n) => n.name));
|
|
44
|
+
// --- User Deletion Benchmark ---
|
|
45
|
+
console.log("\\n--- USER DELETION BENCHMARK (REAL REPO) ---");
|
|
46
|
+
setupRequirement("REQ-DEL-1", "User Deletion");
|
|
47
|
+
const userNodes = graph.nodes.filter((n) => (n.name || "").toLowerCase().includes("user"));
|
|
48
|
+
for (const node of userNodes) {
|
|
49
|
+
addTraceabilityLink(ecosystemRoot, "REQUIREMENT:REQ-DEL-1", node.id, "IMPLEMENTED_BY", "INFERRED", "SUPPORTED");
|
|
50
|
+
}
|
|
51
|
+
const edges2 = loadTraceability(ecosystemRoot);
|
|
52
|
+
const traceDel = traceForward(graph, edges2, "REQUIREMENT:REQ-DEL-1", 3);
|
|
53
|
+
const gapsDel = findTraceabilityGaps(ecosystemRoot, graph, edges2);
|
|
54
|
+
console.log("Traced Artifacts:", traceDel.nodes.length - 1);
|
|
55
|
+
console.log("Evidence Found:", traceDel.nodes.filter((n) => n.type !== "UNKNOWN" && !n.id.startsWith("REQUIREMENT:")).length);
|
|
56
|
+
console.log("Traceability Gaps (User Deletion):", gapsDel.filter((g) => g.id === "REQUIREMENT:REQ-DEL-1").length > 0 ? "YES (REQUIREMENT_WITHOUT_IMPLEMENTATION)" : "NO");
|
|
57
|
+
console.log("Affected Services:", traceDel.nodes.filter((n) => n.type === "SERVICE").map((n) => n.name));
|
|
58
|
+
console.log("Affected APIs:", traceDel.nodes.filter((n) => n.type === "API").map((n) => n.name));
|
|
59
|
+
console.log("\\n=== VALIDATION SUMMARY ===");
|
|
60
|
+
console.log("Did the MCP discover the actual SecuFusion implementation surface of a feature?");
|
|
61
|
+
if (retentionNodes.length === 0 && userNodes.length === 0) {
|
|
62
|
+
console.log("No. The actual SecuFusion backend repository (Java/Spring) is missing from this workspace. The extraction correctly resulted in 0 mappings without fabricating evidence. This correctly triggered the TRACEABILITY_GAP behavior.");
|
|
63
|
+
}
|
|
64
|
+
else {
|
|
65
|
+
console.log("Yes. Discovered actual implementation surface.");
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
try {
|
|
69
|
+
runRealBenchmark();
|
|
70
|
+
}
|
|
71
|
+
catch (e) {
|
|
72
|
+
console.error("Benchmark failed:", e);
|
|
73
|
+
process.exit(1);
|
|
74
|
+
}
|