mcprigor 1.0.0-rc.1

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.
Files changed (164) hide show
  1. package/LICENSE +17 -0
  2. package/README.md +233 -0
  3. package/dist/assertions.d.ts +4 -0
  4. package/dist/assertions.d.ts.map +1 -0
  5. package/dist/assertions.js +101 -0
  6. package/dist/assertions.js.map +1 -0
  7. package/dist/author.d.ts +57 -0
  8. package/dist/author.d.ts.map +1 -0
  9. package/dist/author.js +134 -0
  10. package/dist/author.js.map +1 -0
  11. package/dist/canonical.d.ts +4 -0
  12. package/dist/canonical.d.ts.map +1 -0
  13. package/dist/canonical.js +17 -0
  14. package/dist/canonical.js.map +1 -0
  15. package/dist/cli.d.ts +3 -0
  16. package/dist/cli.d.ts.map +1 -0
  17. package/dist/cli.js +265 -0
  18. package/dist/cli.js.map +1 -0
  19. package/dist/contract.d.ts +28 -0
  20. package/dist/contract.d.ts.map +1 -0
  21. package/dist/contract.js +138 -0
  22. package/dist/contract.js.map +1 -0
  23. package/dist/data.d.ts +24 -0
  24. package/dist/data.d.ts.map +1 -0
  25. package/dist/data.js +367 -0
  26. package/dist/data.js.map +1 -0
  27. package/dist/discovery.d.ts +6 -0
  28. package/dist/discovery.d.ts.map +1 -0
  29. package/dist/discovery.js +82 -0
  30. package/dist/discovery.js.map +1 -0
  31. package/dist/errors.d.ts +19 -0
  32. package/dist/errors.d.ts.map +1 -0
  33. package/dist/errors.js +40 -0
  34. package/dist/errors.js.map +1 -0
  35. package/dist/extension-host.d.ts +20 -0
  36. package/dist/extension-host.d.ts.map +1 -0
  37. package/dist/extension-host.js +52 -0
  38. package/dist/extension-host.js.map +1 -0
  39. package/dist/extension-sdk.d.ts +22 -0
  40. package/dist/extension-sdk.d.ts.map +1 -0
  41. package/dist/extension-sdk.js +3 -0
  42. package/dist/extension-sdk.js.map +1 -0
  43. package/dist/extension-worker.d.ts +2 -0
  44. package/dist/extension-worker.d.ts.map +1 -0
  45. package/dist/extension-worker.js +27 -0
  46. package/dist/extension-worker.js.map +1 -0
  47. package/dist/extensions.d.ts +15 -0
  48. package/dist/extensions.d.ts.map +1 -0
  49. package/dist/extensions.js +60 -0
  50. package/dist/extensions.js.map +1 -0
  51. package/dist/imports.d.ts +7 -0
  52. package/dist/imports.d.ts.map +1 -0
  53. package/dist/imports.js +41 -0
  54. package/dist/imports.js.map +1 -0
  55. package/dist/index.d.ts +29 -0
  56. package/dist/index.d.ts.map +1 -0
  57. package/dist/index.js +28 -0
  58. package/dist/index.js.map +1 -0
  59. package/dist/language.d.ts +34 -0
  60. package/dist/language.d.ts.map +1 -0
  61. package/dist/language.js +102 -0
  62. package/dist/language.js.map +1 -0
  63. package/dist/loader.d.ts +4 -0
  64. package/dist/loader.d.ts.map +1 -0
  65. package/dist/loader.js +51 -0
  66. package/dist/loader.js.map +1 -0
  67. package/dist/parity.d.ts +23 -0
  68. package/dist/parity.d.ts.map +1 -0
  69. package/dist/parity.js +77 -0
  70. package/dist/parity.js.map +1 -0
  71. package/dist/path.d.ts +3 -0
  72. package/dist/path.d.ts.map +1 -0
  73. package/dist/path.js +71 -0
  74. package/dist/path.js.map +1 -0
  75. package/dist/qa-advanced.d.ts +8 -0
  76. package/dist/qa-advanced.d.ts.map +1 -0
  77. package/dist/qa-advanced.js +239 -0
  78. package/dist/qa-advanced.js.map +1 -0
  79. package/dist/qa-language.d.ts +4 -0
  80. package/dist/qa-language.d.ts.map +1 -0
  81. package/dist/qa-language.js +385 -0
  82. package/dist/qa-language.js.map +1 -0
  83. package/dist/qa-loader.d.ts +4 -0
  84. package/dist/qa-loader.d.ts.map +1 -0
  85. package/dist/qa-loader.js +22 -0
  86. package/dist/qa-loader.js.map +1 -0
  87. package/dist/redact.d.ts +7 -0
  88. package/dist/redact.d.ts.map +1 -0
  89. package/dist/redact.js +63 -0
  90. package/dist/redact.js.map +1 -0
  91. package/dist/replay.d.ts +17 -0
  92. package/dist/replay.d.ts.map +1 -0
  93. package/dist/replay.js +48 -0
  94. package/dist/replay.js.map +1 -0
  95. package/dist/reporters.d.ts +6 -0
  96. package/dist/reporters.d.ts.map +1 -0
  97. package/dist/reporters.js +52 -0
  98. package/dist/reporters.js.map +1 -0
  99. package/dist/runner.d.ts +16 -0
  100. package/dist/runner.d.ts.map +1 -0
  101. package/dist/runner.js +304 -0
  102. package/dist/runner.js.map +1 -0
  103. package/dist/schema.d.ts +446 -0
  104. package/dist/schema.d.ts.map +1 -0
  105. package/dist/schema.js +117 -0
  106. package/dist/schema.js.map +1 -0
  107. package/dist/session.d.ts +5 -0
  108. package/dist/session.d.ts.map +1 -0
  109. package/dist/session.js +111 -0
  110. package/dist/session.js.map +1 -0
  111. package/dist/snapshots.d.ts +28 -0
  112. package/dist/snapshots.d.ts.map +1 -0
  113. package/dist/snapshots.js +87 -0
  114. package/dist/snapshots.js.map +1 -0
  115. package/dist/starter.d.ts +3 -0
  116. package/dist/starter.d.ts.map +1 -0
  117. package/dist/starter.js +34 -0
  118. package/dist/starter.js.map +1 -0
  119. package/dist/state.d.ts +13 -0
  120. package/dist/state.d.ts.map +1 -0
  121. package/dist/state.js +29 -0
  122. package/dist/state.js.map +1 -0
  123. package/dist/trace.d.ts +57 -0
  124. package/dist/trace.d.ts.map +1 -0
  125. package/dist/trace.js +94 -0
  126. package/dist/trace.js.map +1 -0
  127. package/dist/types.d.ts +245 -0
  128. package/dist/types.d.ts.map +1 -0
  129. package/dist/types.js +2 -0
  130. package/dist/types.js.map +1 -0
  131. package/dist/workspace.d.ts +10 -0
  132. package/dist/workspace.d.ts.map +1 -0
  133. package/dist/workspace.js +144 -0
  134. package/dist/workspace.js.map +1 -0
  135. package/docs/CLI-REFERENCE.md +167 -0
  136. package/docs/COMPATIBILITY.md +42 -0
  137. package/docs/CONTRACT-DRIFT.md +42 -0
  138. package/docs/DATA-AND-REUSE.md +213 -0
  139. package/docs/DATA-ENGINEERING.md +96 -0
  140. package/docs/ENGINEER-SETUP.md +176 -0
  141. package/docs/ERROR-MODEL.md +24 -0
  142. package/docs/EVIDENCE.md +58 -0
  143. package/docs/EXTENSION-SDK.md +76 -0
  144. package/docs/FILE-EXTENSION.md +52 -0
  145. package/docs/GETTING-STARTED.md +126 -0
  146. package/docs/GUIDED-AUTHORING.md +80 -0
  147. package/docs/LANDSCAPE.md +81 -0
  148. package/docs/LANGUAGE-SPEC.md +317 -0
  149. package/docs/MCP-NATIVE.md +111 -0
  150. package/docs/PLAIN-LANGUAGE-COOKBOOK.md +219 -0
  151. package/docs/QA-GUIDE.md +128 -0
  152. package/docs/QA-WORKSPACE.md +78 -0
  153. package/docs/README.md +55 -0
  154. package/docs/SECURITY-AND-RETENTION.md +37 -0
  155. package/docs/SNAPSHOTS-AND-REPLAY.md +85 -0
  156. package/docs/SPECIFICATION.md +178 -0
  157. package/docs/STATE-AND-DEPENDENCIES.md +106 -0
  158. package/docs/TRANSPORT-PARITY.md +98 -0
  159. package/docs/TROUBLESHOOTING.md +199 -0
  160. package/editors/mcpr-language.json +16 -0
  161. package/package.json +70 -0
  162. package/workspace-assets/app.js +1 -0
  163. package/workspace-assets/index.html +1 -0
  164. package/workspace-assets/style.css +1 -0
@@ -0,0 +1,111 @@
1
+ import { Client } from "@modelcontextprotocol/sdk/client/index.js";
2
+ import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js";
3
+ import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
4
+ import { CreateMessageRequestSchema, ElicitRequestSchema, ListRootsRequestSchema, LoggingMessageNotificationSchema, ProgressNotificationSchema, PromptListChangedNotificationSchema, ResourceListChangedNotificationSchema, ResourceUpdatedNotificationSchema, ResultSchema, TaskStatusNotificationSchema, ToolListChangedNotificationSchema, } from "@modelcontextprotocol/sdk/types.js";
5
+ import { RigorError } from "./errors.js";
6
+ const activeSessions = new Set();
7
+ export function createSession(target) { const session = new SdkSession(target, () => activeSessions.delete(session)); activeSessions.add(session); return session; }
8
+ export async function shutdownSessions() { await Promise.allSettled([...activeSessions].map((session) => session.close())); activeSessions.clear(); }
9
+ export function installSignalCleanup() { const handler = () => { void shutdownSessions().finally(() => { process.exitCode = 130; }); }; process.once("SIGINT", handler); process.once("SIGTERM", handler); return () => { process.off("SIGINT", handler); process.off("SIGTERM", handler); }; }
10
+ class SdkSession {
11
+ target;
12
+ disposed;
13
+ client = new Client({ name: "mcprigor", version: "1.0.0-rc.1" }, { capabilities: { roots: { listChanged: true }, sampling: {}, elicitation: { form: {}, url: {} } } });
14
+ messages = [];
15
+ diagnosticBytes = 0;
16
+ nativeEvents = [];
17
+ sequence = 0;
18
+ behavior = {};
19
+ transport;
20
+ waiters = [];
21
+ constructor(target, disposed) {
22
+ this.target = target;
23
+ this.disposed = disposed;
24
+ this.installHandlers();
25
+ }
26
+ configureClient(behavior) { this.behavior = behavior; }
27
+ async connect() {
28
+ if (this.target.transport === "stdio") {
29
+ const env = this.target.env ? { ...process.env, ...this.target.env } : undefined;
30
+ this.transport = new StdioClientTransport({ command: this.target.command, args: this.target.args, cwd: this.target.cwd, env, stderr: "pipe" });
31
+ this.transport.stderr?.on("data", (chunk) => { if (this.diagnosticBytes >= 64 * 1024)
32
+ return; const text = String(chunk).slice(0, 16 * 1024).trimEnd(); this.diagnosticBytes += Buffer.byteLength(text); this.messages.push(text); });
33
+ }
34
+ else
35
+ this.transport = new StreamableHTTPClientTransport(new URL(this.target.url), { requestInit: { headers: this.target.headers } });
36
+ try {
37
+ await this.client.connect(this.transport, { timeout: 10_000 });
38
+ }
39
+ catch (error) {
40
+ await this.client.close().catch(() => { });
41
+ this.disposed();
42
+ const message = error instanceof Error ? error.message : String(error);
43
+ if (/ENOENT|spawn/i.test(message))
44
+ throw new RigorError("server-spawn", "MCP-SPAWN-001", message, undefined, error);
45
+ throw new RigorError(/timeout/i.test(message) ? "timeout" : "initialization", /timeout/i.test(message) ? "MCP-TIMEOUT-001" : "MCP-INIT-001", message, undefined, error);
46
+ }
47
+ const server = this.client.getServerVersion();
48
+ return { protocolVersion: this.transport instanceof StreamableHTTPClientTransport ? this.transport.protocolVersion : undefined, serverName: server?.name, serverVersion: server?.version, capabilities: this.client.getServerCapabilities() };
49
+ }
50
+ async request(method, params, timeoutMs = 10_000) { return this.client.request({ method, params: params }, ResultSchema, { timeout: timeoutMs }); }
51
+ async nativeRequest(method, params, options = {}) {
52
+ const progress = [];
53
+ const taskEvents = [];
54
+ const controller = new AbortController();
55
+ const timer = options.cancelAfterMs ? setTimeout(() => controller.abort(new Error("MCP request cancelled by test")), options.cancelAfterMs) : undefined;
56
+ try {
57
+ if (options.task && method === "tools/call") {
58
+ for await (const event of this.client.experimental.tasks.callToolStream(params, undefined, { timeout: options.timeoutMs, signal: controller.signal })) {
59
+ taskEvents.push(event);
60
+ if (event.type === "result")
61
+ return { result: event.result, progress, taskEvents };
62
+ if (event.type === "error")
63
+ throw event.error;
64
+ }
65
+ throw new Error("MCP-TASK-001 Task stream ended without a result");
66
+ }
67
+ const result = await this.client.request({ method, params: params }, ResultSchema, { timeout: options.timeoutMs, signal: controller.signal, onprogress: options.progress ? (event) => progress.push(event) : undefined });
68
+ return { result, progress, taskEvents };
69
+ }
70
+ finally {
71
+ if (timer)
72
+ clearTimeout(timer);
73
+ }
74
+ }
75
+ events() { return structuredClone(this.nativeEvents); }
76
+ awaitEvent(method, timeoutMs = 5_000) {
77
+ const existing = this.nativeEvents.find((event) => event.method === method);
78
+ if (existing)
79
+ return Promise.resolve(structuredClone(existing));
80
+ return new Promise((resolve, reject) => { const timer = setTimeout(() => { this.waiters = this.waiters.filter((item) => item.timer !== timer); reject(new Error(`MCP-EVENT-001 Timed out waiting for ${method}`)); }, timeoutMs); this.waiters.push({ method, resolve, reject, timer }); });
81
+ }
82
+ async subscribe(uri) { return this.client.subscribeResource({ uri }); }
83
+ async unsubscribe(uri) { return this.client.unsubscribeResource({ uri }); }
84
+ async setLoggingLevel(level) { return this.client.setLoggingLevel(level); }
85
+ async close() { for (const waiter of this.waiters) {
86
+ clearTimeout(waiter.timer);
87
+ waiter.reject(new RigorError("cancellation", "MCP-CANCEL-001", "Session closed while waiting for an event"));
88
+ } this.waiters = []; try {
89
+ await this.client.close();
90
+ }
91
+ catch (error) {
92
+ throw new RigorError("cleanup", "MCP-CLEANUP-002", error instanceof Error ? error.message : String(error), undefined, error);
93
+ }
94
+ finally {
95
+ this.disposed();
96
+ } }
97
+ diagnostics() { return [...this.messages]; }
98
+ installHandlers() {
99
+ const notificationSchemas = [ProgressNotificationSchema, LoggingMessageNotificationSchema, ResourceUpdatedNotificationSchema, ResourceListChangedNotificationSchema, ToolListChangedNotificationSchema, PromptListChangedNotificationSchema, TaskStatusNotificationSchema];
100
+ for (const schema of notificationSchemas)
101
+ this.client.setNotificationHandler(schema, (notification) => this.pushEvent(notification.method, notification.params));
102
+ this.client.setRequestHandler(ListRootsRequestSchema, async () => ({ roots: this.behavior.roots ?? [] }));
103
+ this.client.setRequestHandler(CreateMessageRequestSchema, async () => ({ model: this.behavior.sampling?.model ?? "mcprigor-fixture", role: "assistant", content: { type: "text", text: this.behavior.sampling?.text ?? "deterministic response" }, stopReason: "endTurn" }));
104
+ this.client.setRequestHandler(ElicitRequestSchema, async () => ({ action: this.behavior.elicitation?.action ?? "decline", ...(this.behavior.elicitation?.content ? { content: this.behavior.elicitation.content } : {}) }));
105
+ }
106
+ pushEvent(method, params) { const event = { method, params, sequence: ++this.sequence }; this.nativeEvents.push(event); for (const waiter of this.waiters.filter((item) => item.method === method)) {
107
+ clearTimeout(waiter.timer);
108
+ waiter.resolve(structuredClone(event));
109
+ } this.waiters = this.waiters.filter((item) => item.method !== method); }
110
+ }
111
+ //# sourceMappingURL=session.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session.js","sourceRoot":"","sources":["../src/session.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,28 @@
1
+ export interface SnapshotFile {
2
+ schemaVersion: 1;
3
+ snapshots: Record<string, unknown>;
4
+ }
5
+ export interface SnapshotOptions {
6
+ file: string;
7
+ update?: boolean;
8
+ ignore?: string[];
9
+ }
10
+ export declare class SnapshotStore {
11
+ private readonly options;
12
+ private data;
13
+ private dirty;
14
+ constructor(options: SnapshotOptions);
15
+ load(): Promise<void>;
16
+ match(name: string, actual: unknown, ignore?: string[]): void;
17
+ save(): Promise<void>;
18
+ }
19
+ export interface SemanticChange {
20
+ path: string;
21
+ kind: "added" | "removed" | "changed";
22
+ before?: unknown;
23
+ after?: unknown;
24
+ }
25
+ export declare function semanticDiff(before: unknown, after: unknown, path?: string, changes?: SemanticChange[]): SemanticChange[];
26
+ export declare function renderSemanticDiff(changes: SemanticChange[]): string;
27
+ export declare function normalizeSnapshot(value: unknown, ignore: string[]): unknown;
28
+ //# sourceMappingURL=snapshots.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"snapshots.d.ts","sourceRoot":"","sources":["../src/snapshots.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,YAAY;IAAG,aAAa,EAAE,CAAC,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAAE;AACtF,MAAM,WAAW,eAAe;IAAG,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,OAAO,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,EAAE,CAAA;CAAE;AAEtF,qBAAa,aAAa;IAEZ,OAAO,CAAC,QAAQ,CAAC,OAAO;IADpC,OAAO,CAAC,IAAI,CAAqD;IAAC,OAAO,CAAC,KAAK,CAAS;gBAC3D,OAAO,EAAE,eAAe;IAC/C,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAC3B,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAE,MAAM,EAAO,GAAG,IAAI;IAM3D,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;CAC5B;AAED,MAAM,WAAW,cAAc;IAAG,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,OAAO,GAAG,SAAS,GAAG,SAAS,CAAC;IAAC,MAAM,CAAC,EAAE,OAAO,CAAC;IAAC,KAAK,CAAC,EAAE,OAAO,CAAA;CAAE;AAC1H,wBAAgB,YAAY,CAAC,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,SAAM,EAAE,OAAO,GAAE,cAAc,EAAO,GAAG,cAAc,EAAE,CAK1H;AACD,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,cAAc,EAAE,GAAG,MAAM,CAAqS;AAC1W,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,OAAO,CAA0H"}
@@ -0,0 +1,87 @@
1
+ import { mkdir, readFile, writeFile } from "node:fs/promises";
2
+ import { dirname, resolve } from "node:path";
3
+ import { canonicalize } from "./canonical.js";
4
+ export class SnapshotStore {
5
+ options;
6
+ data = { schemaVersion: 1, snapshots: {} };
7
+ dirty = false;
8
+ constructor(options) {
9
+ this.options = options;
10
+ }
11
+ async load() { try {
12
+ const value = JSON.parse(await readFile(resolve(this.options.file), "utf8"));
13
+ if (value.schemaVersion !== 1 || !value.snapshots)
14
+ throw new Error("invalid format");
15
+ this.data = value;
16
+ }
17
+ catch (error) {
18
+ if (error.code !== "ENOENT")
19
+ throw new Error(`MCP-SNAPSHOT-001 Cannot load snapshot: ${error instanceof Error ? error.message : String(error)}`);
20
+ } }
21
+ match(name, actual, ignore = []) {
22
+ const normalized = normalizeSnapshot(actual, [...(this.options.ignore ?? []), ...ignore]);
23
+ if (!(name in this.data.snapshots)) {
24
+ if (!this.options.update)
25
+ throw new Error(`MCP-SNAPSHOT-002 Snapshot “${name}” does not exist. Re-run with --update-snapshots.`);
26
+ this.data.snapshots[name] = normalized;
27
+ this.dirty = true;
28
+ return;
29
+ }
30
+ const expected = this.data.snapshots[name];
31
+ const changes = semanticDiff(expected, normalized);
32
+ if (changes.length) {
33
+ if (this.options.update) {
34
+ this.data.snapshots[name] = normalized;
35
+ this.dirty = true;
36
+ return;
37
+ }
38
+ throw new Error(`MCP-SNAPSHOT-003 Snapshot “${name}” changed:\n${renderSemanticDiff(changes)}`);
39
+ }
40
+ }
41
+ async save() { if (!this.dirty)
42
+ return; const file = resolve(this.options.file); await mkdir(dirname(file), { recursive: true }); await writeFile(file, JSON.stringify(canonicalize(this.data), null, 2) + "\n", "utf8"); }
43
+ }
44
+ export function semanticDiff(before, after, path = "$", changes = []) {
45
+ if (Object.is(before, after))
46
+ return changes;
47
+ if (Array.isArray(before) && Array.isArray(after)) {
48
+ const length = Math.max(before.length, after.length);
49
+ for (let i = 0; i < length; i++) {
50
+ if (i >= before.length)
51
+ changes.push({ path: `${path}[${i}]`, kind: "added", after: after[i] });
52
+ else if (i >= after.length)
53
+ changes.push({ path: `${path}[${i}]`, kind: "removed", before: before[i] });
54
+ else
55
+ semanticDiff(before[i], after[i], `${path}[${i}]`, changes);
56
+ }
57
+ return changes;
58
+ }
59
+ if (record(before) && record(after)) {
60
+ const keys = [...new Set([...Object.keys(before), ...Object.keys(after)])].sort();
61
+ for (const key of keys) {
62
+ if (!(key in before))
63
+ changes.push({ path: `${path}.${key}`, kind: "added", after: after[key] });
64
+ else if (!(key in after))
65
+ changes.push({ path: `${path}.${key}`, kind: "removed", before: before[key] });
66
+ else
67
+ semanticDiff(before[key], after[key], `${path}.${key}`, changes);
68
+ }
69
+ return changes;
70
+ }
71
+ changes.push({ path, kind: "changed", before, after });
72
+ return changes;
73
+ }
74
+ export function renderSemanticDiff(changes) { return changes.map((item) => item.kind === "added" ? `+ ${item.path}: ${JSON.stringify(item.after)}` : item.kind === "removed" ? `- ${item.path}: ${JSON.stringify(item.before)}` : `- ${item.path}: ${JSON.stringify(item.before)}\n+ ${item.path}: ${JSON.stringify(item.after)}`).join("\n"); }
75
+ export function normalizeSnapshot(value, ignore) { const clone = structuredClone(value); for (const path of ignore)
76
+ removePath(clone, path); return canonicalize(clone); }
77
+ function removePath(value, path) { if (!path.startsWith("$.") || !record(value))
78
+ return; const parts = path.slice(2).replace(/\[(\d+)\]/g, ".$1").split("."); let current = value; for (let i = 0; i < parts.length - 1; i++) {
79
+ current = current?.[parts[i]];
80
+ if (current == null)
81
+ return;
82
+ } if (Array.isArray(current))
83
+ current.splice(Number(parts.at(-1)), 1);
84
+ else if (record(current))
85
+ delete current[parts.at(-1)]; }
86
+ function record(value) { return typeof value === "object" && value !== null && !Array.isArray(value); }
87
+ //# sourceMappingURL=snapshots.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"snapshots.js","sourceRoot":"","sources":["../src/snapshots.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ export declare const starterTemplate = "# MCP Rigor \u2014 plain-language acceptance tests\nSuite: \"My MCP server\"\n\n# For a local server:\nServer: node dist/server.js\n\n# Or replace the line above with:\n# MCP URL: http://localhost:3000/mcp\n\nTest: \"The calculator adds two numbers\"\n Require: tools\n\n Call tool \"add\" with:\n a: 2\n b: 3\n\n Expect \"structuredContent.sum\" equals 5\n Save \"structuredContent.sum\" as \"answer\"\n";
2
+ export declare function writeStarter(file: string, force?: boolean): Promise<void>;
3
+ //# sourceMappingURL=starter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"starter.d.ts","sourceRoot":"","sources":["../src/starter.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,eAAe,maAkB3B,CAAC;AAEF,wBAAsB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,UAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,CAQ7E"}
@@ -0,0 +1,34 @@
1
+ import { access, writeFile } from "node:fs/promises";
2
+ export const starterTemplate = `# MCP Rigor — plain-language acceptance tests
3
+ Suite: "My MCP server"
4
+
5
+ # For a local server:
6
+ Server: node dist/server.js
7
+
8
+ # Or replace the line above with:
9
+ # MCP URL: http://localhost:3000/mcp
10
+
11
+ Test: "The calculator adds two numbers"
12
+ Require: tools
13
+
14
+ Call tool "add" with:
15
+ a: 2
16
+ b: 3
17
+
18
+ Expect "structuredContent.sum" equals 5
19
+ Save "structuredContent.sum" as "answer"
20
+ `;
21
+ export async function writeStarter(file, force = false) {
22
+ if (!force) {
23
+ try {
24
+ await access(file);
25
+ throw new Error(`QA-INIT-001 ${file} already exists. Choose another name or add --force.`);
26
+ }
27
+ catch (error) {
28
+ if (error instanceof Error && error.message.startsWith("QA-INIT-001"))
29
+ throw error;
30
+ }
31
+ }
32
+ await writeFile(file, starterTemplate, "utf8");
33
+ }
34
+ //# sourceMappingURL=starter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"starter.js","sourceRoot":"","sources":["../src/starter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAErD,MAAM,CAAC,MAAM,eAAe,GAAG;;;;;;;;;;;;;;;;;;CAkB9B,CAAC;AAEF,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,IAAY,EAAE,KAAK,GAAG,KAAK;IAC5D,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,IAAI,CAAC;YAAC,MAAM,MAAM,CAAC,IAAI,CAAC,CAAC;YAAC,MAAM,IAAI,KAAK,CAAC,eAAe,IAAI,sDAAsD,CAAC,CAAC;QAAC,CAAC;QACvH,OAAO,KAAK,EAAE,CAAC;YACb,IAAI,KAAK,YAAY,KAAK,IAAI,KAAK,CAAC,OAAO,CAAC,UAAU,CAAC,aAAa,CAAC;gBAAE,MAAM,KAAK,CAAC;QACrF,CAAC;IACH,CAAC;IACD,MAAM,SAAS,CAAC,IAAI,EAAE,eAAe,EAAE,MAAM,CAAC,CAAC;AACjD,CAAC"}
@@ -0,0 +1,13 @@
1
+ import type { Target } from "./types.js";
2
+ export interface PersistedState {
3
+ formatVersion: 1;
4
+ createdAt: string;
5
+ targetFingerprint: string;
6
+ suiteFingerprint: string;
7
+ outputs: Record<string, unknown>;
8
+ integrity: string;
9
+ }
10
+ export declare function targetFingerprint(target: Target): string;
11
+ export declare function readState(file: string, target: Target, allowTargetMismatch?: boolean): Promise<PersistedState>;
12
+ export declare function writeState(file: string, target: Target, suite: unknown, outputs: Record<string, unknown>): Promise<void>;
13
+ //# sourceMappingURL=state.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"state.d.ts","sourceRoot":"","sources":["../src/state.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AAEzC,MAAM,WAAW,cAAc;IAC7B,aAAa,EAAE,CAAC,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,gBAAgB,EAAE,MAAM,CAAC;IACzB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACjC,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAGxD;AAED,wBAAsB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,mBAAmB,UAAQ,GAAG,OAAO,CAAC,cAAc,CAAC,CAQlH;AAED,wBAAsB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAO9H"}
package/dist/state.js ADDED
@@ -0,0 +1,29 @@
1
+ import { chmod, readFile, rename, writeFile } from "node:fs/promises";
2
+ import { dirname, basename, join } from "node:path";
3
+ import { fingerprint } from "./canonical.js";
4
+ export function targetFingerprint(target) {
5
+ if (target.transport === "stdio")
6
+ return fingerprint({ transport: target.transport, command: target.command, args: target.args ?? [], cwd: target.cwd });
7
+ return fingerprint({ transport: target.transport, url: target.url });
8
+ }
9
+ export async function readState(file, target, allowTargetMismatch = false) {
10
+ const value = JSON.parse(await readFile(file, "utf8"));
11
+ if (value.formatVersion !== 1 || typeof value.outputs !== "object" || !value.outputs)
12
+ throw new Error("MCP-STATE-001 State file format is invalid");
13
+ const expectedIntegrity = fingerprint({ ...value, integrity: undefined });
14
+ if (value.integrity !== expectedIntegrity)
15
+ throw new Error("MCP-STATE-002 State file integrity check failed");
16
+ const current = targetFingerprint(target);
17
+ if (!allowTargetMismatch && value.targetFingerprint !== current)
18
+ throw new Error("MCP-STATE-003 State file belongs to a different MCP target. Use --allow-state-target-mismatch only after reviewing it.");
19
+ return value;
20
+ }
21
+ export async function writeState(file, target, suite, outputs) {
22
+ const core = { formatVersion: 1, createdAt: new Date().toISOString(), targetFingerprint: targetFingerprint(target), suiteFingerprint: fingerprint(suite), outputs };
23
+ const value = { ...core, integrity: fingerprint({ ...core, integrity: undefined }) };
24
+ const temporary = join(dirname(file), `.${basename(file)}.${process.pid}.tmp`);
25
+ await writeFile(temporary, `${JSON.stringify(value, null, 2)}\n`, { encoding: "utf8", mode: 0o600 });
26
+ await chmod(temporary, 0o600);
27
+ await rename(temporary, file);
28
+ }
29
+ //# sourceMappingURL=state.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"state.js","sourceRoot":"","sources":["../src/state.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AACtE,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACpD,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAY7C,MAAM,UAAU,iBAAiB,CAAC,MAAc;IAC9C,IAAI,MAAM,CAAC,SAAS,KAAK,OAAO;QAAE,OAAO,WAAW,CAAC,EAAE,SAAS,EAAE,MAAM,CAAC,SAAS,EAAE,OAAO,EAAE,MAAM,CAAC,OAAO,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,IAAI,EAAE,EAAE,GAAG,EAAE,MAAM,CAAC,GAAG,EAAE,CAAC,CAAC;IACzJ,OAAO,WAAW,CAAC,EAAE,SAAS,EAAE,MAAM,CAAC,SAAS,EAAE,GAAG,EAAE,MAAM,CAAC,GAAG,EAAE,CAAC,CAAC;AACvE,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,IAAY,EAAE,MAAc,EAAE,mBAAmB,GAAG,KAAK;IACvF,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,CAAmB,CAAC;IACzE,IAAI,KAAK,CAAC,aAAa,KAAK,CAAC,IAAI,OAAO,KAAK,CAAC,OAAO,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,OAAO;QAAE,MAAM,IAAI,KAAK,CAAC,4CAA4C,CAAC,CAAC;IACpJ,MAAM,iBAAiB,GAAG,WAAW,CAAC,EAAE,GAAG,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,CAAC,CAAC;IAC1E,IAAI,KAAK,CAAC,SAAS,KAAK,iBAAiB;QAAE,MAAM,IAAI,KAAK,CAAC,iDAAiD,CAAC,CAAC;IAC9G,MAAM,OAAO,GAAG,iBAAiB,CAAC,MAAM,CAAC,CAAC;IAC1C,IAAI,CAAC,mBAAmB,IAAI,KAAK,CAAC,iBAAiB,KAAK,OAAO;QAAE,MAAM,IAAI,KAAK,CAAC,wHAAwH,CAAC,CAAC;IAC3M,OAAO,KAAK,CAAC;AACf,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,IAAY,EAAE,MAAc,EAAE,KAAc,EAAE,OAAgC;IAC7G,MAAM,IAAI,GAAG,EAAE,aAAa,EAAE,CAAU,EAAE,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,EAAE,iBAAiB,EAAE,iBAAiB,CAAC,MAAM,CAAC,EAAE,gBAAgB,EAAE,WAAW,CAAC,KAAK,CAAC,EAAE,OAAO,EAAE,CAAC;IAC7K,MAAM,KAAK,GAAmB,EAAE,GAAG,IAAI,EAAE,SAAS,EAAE,WAAW,CAAC,EAAE,GAAG,IAAI,EAAE,SAAS,EAAE,SAAS,EAAE,CAAC,EAAE,CAAC;IACrG,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,IAAI,QAAQ,CAAC,IAAI,CAAC,IAAI,OAAO,CAAC,GAAG,MAAM,CAAC,CAAC;IAC/E,MAAM,SAAS,CAAC,SAAS,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;IACrG,MAAM,KAAK,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;IAC9B,MAAM,MAAM,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;AAChC,CAAC"}
@@ -0,0 +1,57 @@
1
+ import { type Redactor } from "./redact.js";
2
+ import type { RunResult, Target, TestSession } from "./types.js";
3
+ export type TraceEventType = "session.connect.start" | "session.connect.success" | "request" | "response" | "error" | "session.close" | "diagnostic";
4
+ export interface TraceEvent {
5
+ schemaVersion: 1;
6
+ sequence: number;
7
+ elapsedMs: number;
8
+ type: TraceEventType;
9
+ testId?: string;
10
+ step?: string;
11
+ requestId?: string;
12
+ method?: string;
13
+ data?: unknown;
14
+ }
15
+ export interface NormalizedTraceEvent {
16
+ schemaVersion: 1;
17
+ sequence: number;
18
+ type: TraceEventType;
19
+ testId?: string;
20
+ step?: string;
21
+ requestId?: string;
22
+ method?: string;
23
+ data?: unknown;
24
+ }
25
+ export interface EvidenceManifest {
26
+ schemaVersion: 1;
27
+ frameworkVersion: string;
28
+ createdAt: string;
29
+ suiteName: string;
30
+ status: RunResult["status"];
31
+ resultHash: string;
32
+ traceHash: string;
33
+ normalizedTraceHash: string;
34
+ files: Record<string, string>;
35
+ target: {
36
+ transport: Target["transport"];
37
+ };
38
+ }
39
+ export declare class TraceRecorder {
40
+ private readonly redactor;
41
+ private readonly started;
42
+ private sequence;
43
+ private request;
44
+ readonly events: TraceEvent[];
45
+ constructor(redactor?: Redactor);
46
+ record(type: TraceEventType, fields?: Omit<TraceEvent, "schemaVersion" | "sequence" | "elapsedMs" | "type">): TraceEvent;
47
+ nextRequestId(): string;
48
+ normalized(): NormalizedTraceEvent[];
49
+ }
50
+ export declare function traceSession(session: TestSession, recorder: TraceRecorder, context: () => {
51
+ testId?: string;
52
+ step?: string;
53
+ }): TestSession;
54
+ export declare function writeEvidenceBundle(directory: string, result: RunResult, target: Target, recorder: TraceRecorder): Promise<EvidenceManifest>;
55
+ export declare function showEvidence(directory: string): Promise<string>;
56
+ export declare function compareEvidence(first: string, second: string): Promise<string>;
57
+ //# sourceMappingURL=trace.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"trace.d.ts","sourceRoot":"","sources":["../src/trace.ts"],"names":[],"mappings":"AAGA,OAAO,EAAkB,KAAK,QAAQ,EAAE,MAAM,aAAa,CAAC;AAC5D,OAAO,KAAK,EAAE,SAAS,EAAe,MAAM,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAE9E,MAAM,MAAM,cAAc,GAAG,uBAAuB,GAAG,yBAAyB,GAAG,SAAS,GAAG,UAAU,GAAG,OAAO,GAAG,eAAe,GAAG,YAAY,CAAC;AACrJ,MAAM,WAAW,UAAU;IAAG,aAAa,EAAE,CAAC,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,cAAc,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,OAAO,CAAA;CAAE;AAChM,MAAM,WAAW,oBAAoB;IAAG,aAAa,EAAE,CAAC,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,cAAc,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,OAAO,CAAA;CAAE;AACvL,MAAM,WAAW,gBAAgB;IAAG,aAAa,EAAE,CAAC,CAAC;IAAC,gBAAgB,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,SAAS,CAAC,QAAQ,CAAC,CAAC;IAAC,UAAU,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC;IAAC,mBAAmB,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAAC,MAAM,EAAE;QAAE,SAAS,EAAE,MAAM,CAAC,WAAW,CAAC,CAAA;KAAE,CAAA;CAAE;AAElS,qBAAa,aAAa;IAGZ,OAAO,CAAC,QAAQ,CAAC,QAAQ;IAFrC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAc;IAAC,OAAO,CAAC,QAAQ,CAAK;IAAC,OAAO,CAAC,OAAO,CAAK;IACjF,QAAQ,CAAC,MAAM,EAAE,UAAU,EAAE,CAAM;gBACN,QAAQ,GAAE,QAA2B;IAClE,MAAM,CAAC,IAAI,EAAE,cAAc,EAAE,MAAM,GAAE,IAAI,CAAC,UAAU,EAAE,eAAe,GAAG,UAAU,GAAG,WAAW,GAAG,MAAM,CAAM,GAAG,UAAU;IAG5H,aAAa,IAAI,MAAM;IACvB,UAAU,IAAI,oBAAoB,EAAE;CACrC;AAED,wBAAgB,YAAY,CAAC,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,aAAa,EAAE,OAAO,EAAE,MAAM;IAAE,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,WAAW,CAc1I;AAED,wBAAsB,mBAAmB,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,aAAa,GAAG,OAAO,CAAC,gBAAgB,CAAC,CASlJ;AAED,wBAAsB,YAAY,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAIrE;AACD,wBAAsB,eAAe,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAIpF"}
package/dist/trace.js ADDED
@@ -0,0 +1,94 @@
1
+ import { mkdir, readFile, writeFile } from "node:fs/promises";
2
+ import { basename, join, resolve } from "node:path";
3
+ import { canonicalize, fingerprint } from "./canonical.js";
4
+ import { createRedactor } from "./redact.js";
5
+ export class TraceRecorder {
6
+ redactor;
7
+ started = Date.now();
8
+ sequence = 0;
9
+ request = 0;
10
+ events = [];
11
+ constructor(redactor = createRedactor()) {
12
+ this.redactor = redactor;
13
+ }
14
+ record(type, fields = {}) {
15
+ const event = this.redactor.value({ schemaVersion: 1, sequence: ++this.sequence, elapsedMs: Date.now() - this.started, type, ...fields });
16
+ this.events.push(event);
17
+ return event;
18
+ }
19
+ nextRequestId() { return `request-${++this.request}`; }
20
+ normalized() { return this.events.map(({ elapsedMs: _elapsed, ...event }) => canonicalize(normalizeVolatile(event))); }
21
+ }
22
+ export function traceSession(session, recorder, context) {
23
+ return {
24
+ async connect() { recorder.record("session.connect.start", context()); try {
25
+ const info = await session.connect();
26
+ recorder.record("session.connect.success", { ...context(), data: info });
27
+ return info;
28
+ }
29
+ catch (error) {
30
+ recorder.record("error", { ...context(), data: safeError(error) });
31
+ throw error;
32
+ } },
33
+ async request(method, params, timeoutMs) { const requestId = recorder.nextRequestId(); recorder.record("request", { ...context(), requestId, method, data: { params, timeoutMs } }); try {
34
+ const response = await session.request(method, params, timeoutMs);
35
+ recorder.record("response", { ...context(), requestId, method, data: response });
36
+ return response;
37
+ }
38
+ catch (error) {
39
+ recorder.record("error", { ...context(), requestId, method, data: safeError(error) });
40
+ throw error;
41
+ } },
42
+ async close() { try {
43
+ await session.close();
44
+ }
45
+ finally {
46
+ recorder.record("session.close", context());
47
+ for (const message of session.diagnostics())
48
+ recorder.record("diagnostic", { ...context(), data: message });
49
+ } },
50
+ nativeRequest: session.nativeRequest ? (method, params, options) => session.nativeRequest(method, params, options) : undefined,
51
+ events: session.events ? () => session.events() : undefined,
52
+ awaitEvent: session.awaitEvent ? (method, timeoutMs) => session.awaitEvent(method, timeoutMs) : undefined,
53
+ subscribe: session.subscribe ? (uri) => session.subscribe(uri) : undefined,
54
+ unsubscribe: session.unsubscribe ? (uri) => session.unsubscribe(uri) : undefined,
55
+ setLoggingLevel: session.setLoggingLevel ? (level) => session.setLoggingLevel(level) : undefined,
56
+ configureClient: session.configureClient ? (behavior) => session.configureClient(behavior) : undefined,
57
+ diagnostics: () => session.diagnostics(),
58
+ };
59
+ }
60
+ export async function writeEvidenceBundle(directory, result, target, recorder) {
61
+ const root = resolve(directory);
62
+ await mkdir(root, { recursive: true });
63
+ const raw = recorder.events.map((event) => JSON.stringify(event)).join("\n") + "\n";
64
+ const normalizedEvents = recorder.normalized();
65
+ const normalized = normalizedEvents.map((event) => JSON.stringify(event)).join("\n") + "\n";
66
+ const files = { result: "result.json", trace: "trace.jsonl", normalizedTrace: "trace.normalized.jsonl", manifest: "manifest.json" };
67
+ const manifestCore = { schemaVersion: 1, frameworkVersion: "1.0.0-rc.1", createdAt: new Date().toISOString(), suiteName: result.suiteName, status: result.status, resultHash: result.evidenceHash, traceHash: fingerprint(recorder.events), normalizedTraceHash: fingerprint(normalizedEvents), files, target: { transport: target.transport } };
68
+ const manifest = manifestCore;
69
+ await Promise.all([writeFile(join(root, files.result), JSON.stringify(result, null, 2) + "\n"), writeFile(join(root, files.trace), raw), writeFile(join(root, files.normalizedTrace), normalized), writeFile(join(root, files.manifest), JSON.stringify(manifest, null, 2) + "\n")]);
70
+ return manifest;
71
+ }
72
+ export async function showEvidence(directory) {
73
+ const manifest = JSON.parse(await readFile(join(resolve(directory), "manifest.json"), "utf8"));
74
+ const result = JSON.parse(await readFile(join(resolve(directory), manifest.files.result), "utf8"));
75
+ return [`Evidence: ${basename(resolve(directory))}`, `Suite: ${manifest.suiteName}`, `Status: ${manifest.status}`, `Tests: ${result.summary.passed} passed, ${result.summary.failed} failed, ${result.summary.blocked} blocked`, `Result: ${manifest.resultHash}`, `Normalized trace: ${manifest.normalizedTraceHash}`].join("\n");
76
+ }
77
+ export async function compareEvidence(first, second) {
78
+ const a = JSON.parse(await readFile(join(resolve(first), "manifest.json"), "utf8"));
79
+ const b = JSON.parse(await readFile(join(resolve(second), "manifest.json"), "utf8"));
80
+ if (a.normalizedTraceHash === b.normalizedTraceHash && a.resultHash === b.resultHash)
81
+ return "Evidence bundles are semantically identical.";
82
+ const lines = ["Evidence bundles differ:"];
83
+ if (a.resultHash !== b.resultHash)
84
+ lines.push(`- Result hash: ${a.resultHash} → ${b.resultHash}`);
85
+ if (a.normalizedTraceHash !== b.normalizedTraceHash)
86
+ lines.push(`- Trace hash: ${a.normalizedTraceHash} → ${b.normalizedTraceHash}`);
87
+ return lines.join("\n");
88
+ }
89
+ function normalizeVolatile(value) { if (Array.isArray(value))
90
+ return value.map(normalizeVolatile); if (!value || typeof value !== "object")
91
+ return typeof value === "string" ? value.replace(/\/var\/folders\/[^\s"']+/g, "<temp-path>").replace(/\/tmp\/[^\s"']+/g, "<temp-path>") : value; return Object.fromEntries(Object.entries(value).filter(([key]) => !/timestamp|createdAt|sessionId/i.test(key)).map(([key, item]) => [key, normalizeVolatile(item)])); }
92
+ function safeError(error) { if (!(error instanceof Error))
93
+ return { message: String(error) }; const candidate = error; return { name: error.name, message: error.message, code: candidate.code, data: candidate.data }; }
94
+ //# sourceMappingURL=trace.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"trace.js","sourceRoot":"","sources":["../src/trace.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC9D,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpD,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAC3D,OAAO,EAAE,cAAc,EAAiB,MAAM,aAAa,CAAC;AAQ5D,MAAM,OAAO,aAAa;IAGK;IAFZ,OAAO,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IAAS,QAAQ,GAAG,CAAC,CAAC;IAAS,OAAO,GAAG,CAAC,CAAC;IACxE,MAAM,GAAiB,EAAE,CAAC;IACnC,YAA6B,WAAqB,cAAc,EAAE;QAArC,aAAQ,GAAR,QAAQ,CAA6B;IAAG,CAAC;IACtE,MAAM,CAAC,IAAoB,EAAE,SAAgF,EAAE;QAC7G,MAAM,KAAK,GAAe,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,aAAa,EAAE,CAAC,EAAE,QAAQ,EAAE,EAAE,IAAI,CAAC,QAAQ,EAAE,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,OAAO,EAAE,IAAI,EAAE,GAAG,MAAM,EAAE,CAAC,CAAC;QAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAAC,OAAO,KAAK,CAAC;IAC/L,CAAC;IACD,aAAa,KAAa,OAAO,WAAW,EAAE,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;IAC/D,UAAU,KAA6B,OAAO,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,EAAE,SAAS,EAAE,QAAQ,EAAE,GAAG,KAAK,EAAE,EAAE,EAAE,CAAC,YAAY,CAAC,iBAAiB,CAAC,KAAK,CAAC,CAAyB,CAAC,CAAC,CAAC,CAAC;CACxK;AAED,MAAM,UAAU,YAAY,CAAC,OAAoB,EAAE,QAAuB,EAAE,OAAiD;IAC3H,OAAO;QACL,KAAK,CAAC,OAAO,KAA2B,QAAQ,CAAC,MAAM,CAAC,uBAAuB,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;YAAC,MAAM,IAAI,GAAG,MAAM,OAAO,CAAC,OAAO,EAAE,CAAC;YAAC,QAAQ,CAAC,MAAM,CAAC,yBAAyB,EAAE,EAAE,GAAG,OAAO,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;YAAC,OAAO,IAAI,CAAC;QAAC,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YAAC,QAAQ,CAAC,MAAM,CAAC,OAAO,EAAE,EAAE,GAAG,OAAO,EAAE,EAAE,IAAI,EAAE,SAAS,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;YAAC,MAAM,KAAK,CAAC;QAAC,CAAC,CAAC,CAAC;QACtU,KAAK,CAAC,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,IAAI,MAAM,SAAS,GAAG,QAAQ,CAAC,aAAa,EAAE,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,SAAS,EAAE,EAAE,GAAG,OAAO,EAAE,EAAE,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,EAAE,MAAM,EAAE,SAAS,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;YAAC,MAAM,QAAQ,GAAG,MAAM,OAAO,CAAC,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,CAAC,CAAC;YAAC,QAAQ,CAAC,MAAM,CAAC,UAAU,EAAE,EAAE,GAAG,OAAO,EAAE,EAAE,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,CAAC;YAAC,OAAO,QAAQ,CAAC;QAAC,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YAAC,QAAQ,CAAC,MAAM,CAAC,OAAO,EAAE,EAAE,GAAG,OAAO,EAAE,EAAE,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;YAAC,MAAM,KAAK,CAAC;QAAC,CAAC,CAAC,CAAC;QAC1d,KAAK,CAAC,KAAK,KAAK,IAAI,CAAC;YAAC,MAAM,OAAO,CAAC,KAAK,EAAE,CAAC;QAAC,CAAC;gBAAS,CAAC;YAAC,QAAQ,CAAC,MAAM,CAAC,eAAe,EAAE,OAAO,EAAE,CAAC,CAAC;YAAC,KAAK,MAAM,OAAO,IAAI,OAAO,CAAC,WAAW,EAAE;gBAAE,QAAQ,CAAC,MAAM,CAAC,YAAY,EAAE,EAAE,GAAG,OAAO,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,CAAC;QAAC,CAAC,CAAC,CAAC;QACtN,aAAa,EAAE,OAAO,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,aAAc,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,SAAS;QAC/H,MAAM,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,MAAO,EAAE,CAAC,CAAC,CAAC,SAAS;QAC5D,UAAU,EAAE,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,MAAM,EAAE,SAAS,EAAE,EAAE,CAAC,OAAO,CAAC,UAAW,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC,CAAC,CAAC,SAAS;QAC1G,SAAS,EAAE,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,OAAO,CAAC,SAAU,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS;QAC3E,WAAW,EAAE,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,OAAO,CAAC,WAAY,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS;QACjF,eAAe,EAAE,OAAO,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,OAAO,CAAC,eAAgB,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,SAAS;QACjG,eAAe,EAAE,OAAO,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,OAAO,CAAC,eAAgB,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,SAAS;QACvG,WAAW,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,WAAW,EAAE;KACzC,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,mBAAmB,CAAC,SAAiB,EAAE,MAAiB,EAAE,MAAc,EAAE,QAAuB;IACrH,MAAM,IAAI,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC;IAAC,MAAM,KAAK,CAAC,IAAI,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACxE,MAAM,GAAG,GAAG,QAAQ,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;IACpF,MAAM,gBAAgB,GAAG,QAAQ,CAAC,UAAU,EAAE,CAAC;IAAC,MAAM,UAAU,GAAG,gBAAgB,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;IAC5I,MAAM,KAAK,GAAG,EAAE,MAAM,EAAE,aAAa,EAAE,KAAK,EAAE,aAAa,EAAE,eAAe,EAAE,wBAAwB,EAAE,QAAQ,EAAE,eAAe,EAAE,CAAC;IACpI,MAAM,YAAY,GAAG,EAAE,aAAa,EAAE,CAAU,EAAE,gBAAgB,EAAE,YAAY,EAAE,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,EAAE,SAAS,EAAE,MAAM,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,UAAU,EAAE,MAAM,CAAC,YAAY,EAAE,SAAS,EAAE,WAAW,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,mBAAmB,EAAE,WAAW,CAAC,gBAAgB,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,SAAS,EAAE,MAAM,CAAC,SAAS,EAAE,EAAE,CAAC;IAC1V,MAAM,QAAQ,GAAqB,YAAY,CAAC;IAChD,MAAM,OAAO,CAAC,GAAG,CAAC,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,CAAC,MAAM,CAAC,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC,EAAE,SAAS,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,CAAC,KAAK,CAAC,EAAE,GAAG,CAAC,EAAE,SAAS,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,CAAC,eAAe,CAAC,EAAE,UAAU,CAAC,EAAE,SAAS,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,CAAC,QAAQ,CAAC,EAAE,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;IACrR,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,SAAiB;IAClD,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,EAAE,eAAe,CAAC,EAAE,MAAM,CAAC,CAAqB,CAAC;IACnH,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,EAAE,QAAQ,CAAC,KAAK,CAAC,MAAO,CAAC,EAAE,MAAM,CAAC,CAAc,CAAC;IACjH,OAAO,CAAC,aAAa,QAAQ,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,EAAE,EAAE,UAAU,QAAQ,CAAC,SAAS,EAAE,EAAE,WAAW,QAAQ,CAAC,MAAM,EAAE,EAAE,UAAU,MAAM,CAAC,OAAO,CAAC,MAAM,YAAY,MAAM,CAAC,OAAO,CAAC,MAAM,YAAY,MAAM,CAAC,OAAO,CAAC,OAAO,UAAU,EAAE,WAAW,QAAQ,CAAC,UAAU,EAAE,EAAE,qBAAqB,QAAQ,CAAC,mBAAmB,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACrU,CAAC;AACD,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,KAAa,EAAE,MAAc;IACjE,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,eAAe,CAAC,EAAE,MAAM,CAAC,CAAqB,CAAC;IAAC,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,eAAe,CAAC,EAAE,MAAM,CAAC,CAAqB,CAAC;IAClN,IAAI,CAAC,CAAC,mBAAmB,KAAK,CAAC,CAAC,mBAAmB,IAAI,CAAC,CAAC,UAAU,KAAK,CAAC,CAAC,UAAU;QAAE,OAAO,8CAA8C,CAAC;IAC5I,MAAM,KAAK,GAAG,CAAC,0BAA0B,CAAC,CAAC;IAAC,IAAI,CAAC,CAAC,UAAU,KAAK,CAAC,CAAC,UAAU;QAAE,KAAK,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC,UAAU,MAAM,CAAC,CAAC,UAAU,EAAE,CAAC,CAAC;IAAC,IAAI,CAAC,CAAC,mBAAmB,KAAK,CAAC,CAAC,mBAAmB;QAAE,KAAK,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC,mBAAmB,MAAM,CAAC,CAAC,mBAAmB,EAAE,CAAC,CAAC;IAAC,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC/S,CAAC;AACD,SAAS,iBAAiB,CAAC,KAAc,IAAa,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;IAAE,OAAO,KAAK,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ;IAAE,OAAO,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,2BAA2B,EAAE,aAAa,CAAC,CAAC,OAAO,CAAC,kBAAkB,EAAE,aAAa,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,OAAO,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC,CAAC,gCAAgC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,IAAI,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,EAAE,iBAAiB,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AACtd,SAAS,SAAS,CAAC,KAAc,IAAa,IAAI,CAAC,CAAC,KAAK,YAAY,KAAK,CAAC;IAAE,OAAO,EAAE,OAAO,EAAE,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,MAAM,SAAS,GAAG,KAAmD,CAAC,CAAC,OAAO,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,IAAI,EAAE,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,SAAS,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC"}