prism-mcp-server 7.2.0 → 7.3.3
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 +102 -19
- package/dist/cli.js +50 -0
- package/dist/config.js +16 -0
- package/dist/darkfactory/clawInvocation.js +77 -0
- package/dist/darkfactory/runner.js +683 -0
- package/dist/darkfactory/safetyController.js +197 -0
- package/dist/darkfactory/schema.js +4 -0
- package/dist/dashboard/server.js +103 -0
- package/dist/dashboard/ui.js +2668 -1990
- package/dist/dashboard/ui.tmp.js +3475 -0
- package/dist/errors.js +29 -0
- package/dist/hivemindWatchdog.js +197 -4
- package/dist/lifecycle.js +9 -1
- package/dist/server.js +41 -3
- package/dist/storage/sqlite.js +243 -0
- package/dist/storage/supabase.js +195 -3
- package/dist/storage/supabaseMigrations.js +52 -0
- package/dist/tools/index.js +5 -0
- package/dist/tools/pipelineDefinitions.js +131 -0
- package/dist/tools/pipelineHandlers.js +214 -0
- package/dist/tools/routerExperience.js +14 -0
- package/dist/tools/sessionMemoryDefinitions.js +5 -3
- package/dist/verification/clawValidator.js +229 -0
- package/dist/verification/cliHandler.js +325 -0
- package/dist/verification/gatekeeper.js +39 -0
- package/dist/verification/renameDetector.js +170 -0
- package/dist/verification/runner.js +501 -0
- package/dist/verification/schema.js +64 -0
- package/dist/verification/severityPolicy.js +98 -0
- package/package.json +13 -5
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { createHash } from "crypto";
|
|
3
|
+
// ─── v7.2.0: Severity Levels ────────────────────────────────
|
|
4
|
+
// warn → log and continue
|
|
5
|
+
// gate → block progression until resolved
|
|
6
|
+
// abort → rollback (fail the pipeline)
|
|
7
|
+
export const SeverityLevel = z.enum(["warn", "gate", "abort"]).default("warn");
|
|
8
|
+
// Base for all assertions
|
|
9
|
+
const BaseAssertion = z.object({
|
|
10
|
+
target: z.string().describe("The SQL query, URL, or file path"),
|
|
11
|
+
expected: z.any().describe("The expected outcome to match against"),
|
|
12
|
+
});
|
|
13
|
+
// 1. Declarative Assertions (Split for better type inference)
|
|
14
|
+
export const SqliteAssertionSchema = BaseAssertion.extend({ type: z.literal("sqlite_query") });
|
|
15
|
+
export const HttpStatusAssertionSchema = BaseAssertion.extend({ type: z.literal("http_status") });
|
|
16
|
+
export const FileExistsAssertionSchema = BaseAssertion.extend({ type: z.literal("file_exists") });
|
|
17
|
+
export const FileContainsAssertionSchema = BaseAssertion.extend({ type: z.literal("file_contains") });
|
|
18
|
+
// 2. Sandboxed JS Assertion
|
|
19
|
+
export const SandboxedJsAssertionSchema = z.object({
|
|
20
|
+
type: z.literal("quickjs_eval"),
|
|
21
|
+
code: z.string().describe("JS code to run in QuickJS. Must return a boolean."),
|
|
22
|
+
inputs: z.record(z.string(), z.any()).optional().describe("Data to inject as globals into the sandbox"),
|
|
23
|
+
});
|
|
24
|
+
// 3. Main Schema Wrapper (v7.2.0 enhanced)
|
|
25
|
+
export const TestAssertionSchema = z.object({
|
|
26
|
+
id: z.string(),
|
|
27
|
+
layer: z.enum(["data", "agent", "pipeline"]),
|
|
28
|
+
description: z.string(),
|
|
29
|
+
severity: SeverityLevel,
|
|
30
|
+
// v7.2.0: per-assertion timeout in ms
|
|
31
|
+
timeout_ms: z.number().int().min(50).max(120_000).optional().describe("Per-assertion timeout in milliseconds"),
|
|
32
|
+
// v7.2.0: retry on transient failures (e.g. http_status)
|
|
33
|
+
retry_count: z.number().int().min(0).max(5).optional().describe("Number of retries on transient failures"),
|
|
34
|
+
// v7.2.0: assertion dependency chain
|
|
35
|
+
depends_on: z.string().optional().describe("ID of assertion that must pass first"),
|
|
36
|
+
// Discriminated union gives pinpoint accuracy on parsing errors
|
|
37
|
+
assertion: z.discriminatedUnion("type", [
|
|
38
|
+
SqliteAssertionSchema,
|
|
39
|
+
HttpStatusAssertionSchema,
|
|
40
|
+
FileExistsAssertionSchema,
|
|
41
|
+
FileContainsAssertionSchema,
|
|
42
|
+
SandboxedJsAssertionSchema
|
|
43
|
+
])
|
|
44
|
+
});
|
|
45
|
+
export const TestSuiteSchema = z.object({
|
|
46
|
+
tests: z.array(TestAssertionSchema)
|
|
47
|
+
});
|
|
48
|
+
// ─── v7.2.0: Rubric Hash Utility ─────────────────────────────
|
|
49
|
+
/**
|
|
50
|
+
* Compute a deterministic SHA-256 hash over the test assertions.
|
|
51
|
+
*
|
|
52
|
+
* Sorts by `id` before hashing so that insertion order does NOT affect
|
|
53
|
+
* the result. This ensures the hash is stable across environments
|
|
54
|
+
* even when tests are stored in different orders.
|
|
55
|
+
*
|
|
56
|
+
* @param tests - The array of TestAssertion to hash
|
|
57
|
+
* @returns Lowercase hex SHA-256 digest
|
|
58
|
+
*/
|
|
59
|
+
export function computeRubricHash(tests) {
|
|
60
|
+
const sorted = [...tests].sort((a, b) => a.id.localeCompare(b.id));
|
|
61
|
+
return createHash("sha256")
|
|
62
|
+
.update(JSON.stringify(sorted))
|
|
63
|
+
.digest("hex");
|
|
64
|
+
}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
// ─── v7.2.0: Severity Gate Enforcement ──────────────────────
|
|
2
|
+
// Separated from the runner for testability.
|
|
3
|
+
//
|
|
4
|
+
// Rules:
|
|
5
|
+
// - "warn" failures → logged, always continue
|
|
6
|
+
// - "gate" failures → block. Return "block" action with failed assertions list
|
|
7
|
+
// - "abort" failures → immediate abort. Return "abort" action
|
|
8
|
+
//
|
|
9
|
+
// When PRISM_VERIFICATION_DEFAULT_SEVERITY is set, it overrides
|
|
10
|
+
// individual assertion severity levels (acts as a floor).
|
|
11
|
+
/**
|
|
12
|
+
* Map severity string to numeric rank for comparison.
|
|
13
|
+
* Higher = more severe.
|
|
14
|
+
*/
|
|
15
|
+
function severityRank(s) {
|
|
16
|
+
switch (s) {
|
|
17
|
+
case "warn": return 0;
|
|
18
|
+
case "gate": return 1;
|
|
19
|
+
case "abort": return 2;
|
|
20
|
+
default: {
|
|
21
|
+
// M4 fix: Exhaustive check — future SeverityLevel additions will cause a compile error
|
|
22
|
+
const _exhaustive = s;
|
|
23
|
+
return _exhaustive;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Resolve the effective severity for an assertion, considering
|
|
29
|
+
* the global default severity override (acts as a floor).
|
|
30
|
+
*/
|
|
31
|
+
export function resolveEffectiveSeverity(assertionSeverity, defaultSeverity) {
|
|
32
|
+
const assertRank = severityRank(assertionSeverity);
|
|
33
|
+
const defaultRank = severityRank(defaultSeverity);
|
|
34
|
+
// Use whichever is more severe (floor behavior)
|
|
35
|
+
return assertRank >= defaultRank ? assertionSeverity : defaultSeverity;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Evaluate all assertion results against severity gates.
|
|
39
|
+
*
|
|
40
|
+
* Returns a SeverityGateResult indicating the overall action:
|
|
41
|
+
* - "continue" → all clear, or only "warn"-level failures
|
|
42
|
+
* - "block" → at least one "gate"-level failure (no "abort")
|
|
43
|
+
* - "abort" → at least one "abort"-level failure
|
|
44
|
+
*/
|
|
45
|
+
export function evaluateSeverityGates(results, config) {
|
|
46
|
+
const failures = results.filter(r => !r.passed && !r.skipped);
|
|
47
|
+
if (failures.length === 0) {
|
|
48
|
+
return {
|
|
49
|
+
action: "continue",
|
|
50
|
+
failed_assertions: [],
|
|
51
|
+
summary: "All assertions passed."
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
// Resolve effective severities and categorize failures
|
|
55
|
+
const abortFailures = [];
|
|
56
|
+
const gateFailures = [];
|
|
57
|
+
const warnFailures = [];
|
|
58
|
+
for (const f of failures) {
|
|
59
|
+
const effective = resolveEffectiveSeverity(f.severity, config.default_severity);
|
|
60
|
+
switch (effective) {
|
|
61
|
+
case "abort":
|
|
62
|
+
abortFailures.push(f);
|
|
63
|
+
break;
|
|
64
|
+
case "gate":
|
|
65
|
+
gateFailures.push(f);
|
|
66
|
+
break;
|
|
67
|
+
case "warn":
|
|
68
|
+
default:
|
|
69
|
+
warnFailures.push(f);
|
|
70
|
+
break;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
// Abort takes precedence over gate
|
|
74
|
+
if (abortFailures.length > 0) {
|
|
75
|
+
const ids = abortFailures.map(a => a.id).join(", ");
|
|
76
|
+
return {
|
|
77
|
+
action: "abort",
|
|
78
|
+
failed_assertions: [...abortFailures, ...gateFailures, ...warnFailures],
|
|
79
|
+
summary: `ABORT: ${abortFailures.length} abort-level failure(s) [${ids}]. ` +
|
|
80
|
+
`${gateFailures.length} gate, ${warnFailures.length} warn failures also present.`
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
if (gateFailures.length > 0) {
|
|
84
|
+
const ids = gateFailures.map(a => a.id).join(", ");
|
|
85
|
+
return {
|
|
86
|
+
action: "block",
|
|
87
|
+
failed_assertions: [...gateFailures, ...warnFailures],
|
|
88
|
+
summary: `BLOCKED: ${gateFailures.length} gate-level failure(s) [${ids}]. ` +
|
|
89
|
+
`${warnFailures.length} warn-level failures also present.`
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
// Only warn-level failures → continue
|
|
93
|
+
return {
|
|
94
|
+
action: "continue",
|
|
95
|
+
failed_assertions: warnFailures,
|
|
96
|
+
summary: `CONTINUE: ${warnFailures.length} warn-level failure(s) logged, no blocking issues.`
|
|
97
|
+
};
|
|
98
|
+
}
|
package/package.json
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "prism-mcp-server",
|
|
3
|
-
"version": "7.
|
|
3
|
+
"version": "7.3.3",
|
|
4
4
|
"mcpName": "io.github.dcostenco/prism-mcp",
|
|
5
|
-
"description": "The Mind Palace for AI Agents — persistent memory (SQLite/Supabase), behavioral learning & IDE rules sync,
|
|
5
|
+
"description": "The Mind Palace for AI Agents — fail-closed Dark Factory autonomous pipelines (3-gate parse→type→scope validation), persistent memory (SQLite/Supabase), ACT-R cognitive retrieval, behavioral learning & IDE rules sync, multi-agent Hivemind, time travel, visual dashboard. Zero-config local mode.",
|
|
6
6
|
"module": "index.ts",
|
|
7
7
|
"type": "module",
|
|
8
8
|
"main": "dist/server.js",
|
|
9
9
|
"bin": {
|
|
10
|
+
"prism": "dist/cli.js",
|
|
10
11
|
"prism-mcp-server": "dist/server.js",
|
|
11
12
|
"prism-import": "dist/utils/universalImporter.js"
|
|
12
13
|
},
|
|
@@ -15,6 +16,7 @@
|
|
|
15
16
|
],
|
|
16
17
|
"scripts": {
|
|
17
18
|
"build": "tsc",
|
|
19
|
+
"lint:dashboard": "node scripts/lint-dashboard-es5.cjs",
|
|
18
20
|
"start": "node dist/server.js",
|
|
19
21
|
"test": "vitest run",
|
|
20
22
|
"test:watch": "vitest",
|
|
@@ -68,7 +70,11 @@
|
|
|
68
70
|
"dashboard",
|
|
69
71
|
"actr",
|
|
70
72
|
"cognitive-memory",
|
|
71
|
-
"activation-memory"
|
|
73
|
+
"activation-memory",
|
|
74
|
+
"dark-factory",
|
|
75
|
+
"autonomous-pipeline",
|
|
76
|
+
"fail-closed",
|
|
77
|
+
"path-traversal-prevention"
|
|
72
78
|
],
|
|
73
79
|
"homepage": "https://github.com/dcostenco/prism-mcp",
|
|
74
80
|
"repository": {
|
|
@@ -90,7 +96,6 @@
|
|
|
90
96
|
},
|
|
91
97
|
"dependencies": {
|
|
92
98
|
"@anthropic-ai/sdk": "^0.80.0",
|
|
93
|
-
"@tavily/core": "^0.6.0",
|
|
94
99
|
"@google-cloud/discoveryengine": "^2.5.3",
|
|
95
100
|
"@google/generative-ai": "^0.24.1",
|
|
96
101
|
"@libsql/client": "^0.17.2",
|
|
@@ -102,7 +107,9 @@
|
|
|
102
107
|
"@opentelemetry/sdk-trace-node": "^2.6.1",
|
|
103
108
|
"@opentelemetry/semantic-conventions": "^1.40.0",
|
|
104
109
|
"@supabase/supabase-js": "^2.99.3",
|
|
110
|
+
"@tavily/core": "^0.6.0",
|
|
105
111
|
"cheerio": "^1.2.0",
|
|
112
|
+
"commander": "^14.0.3",
|
|
106
113
|
"dotenv": "^16.5.0",
|
|
107
114
|
"fflate": "^0.8.2",
|
|
108
115
|
"jsdom": "^29.0.1",
|
|
@@ -110,6 +117,7 @@
|
|
|
110
117
|
"p-limit": "^7.3.0",
|
|
111
118
|
"quickjs-emscripten": "^0.32.0",
|
|
112
119
|
"stream-json": "^2.0.0",
|
|
113
|
-
"turndown": "^7.2.2"
|
|
120
|
+
"turndown": "^7.2.2",
|
|
121
|
+
"zod": "^4.3.6"
|
|
114
122
|
}
|
|
115
123
|
}
|