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.
@@ -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.2.0",
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, multimodal VLM image captioning, pluggable LLM providers (OpenAI/Anthropic/Gemini/Ollama), OpenTelemetry distributed tracing, GDPR export, multi-agent Hivemind sync, time travel, visual Mind Palace dashboard. Zero-config local mode.",
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
  }