@mneme-ai/core 2.7.0 → 2.8.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.
- package/dist/ai_handshake.d.ts.map +1 -1
- package/dist/ai_handshake.js +9 -11
- package/dist/ai_handshake.js.map +1 -1
- package/dist/antivirus/vaccines.js +8 -8
- package/dist/antivirus/vaccines.js.map +1 -1
- package/dist/birthright/birthright.test.d.ts +2 -0
- package/dist/birthright/birthright.test.d.ts.map +1 -0
- package/dist/birthright/birthright.test.js +102 -0
- package/dist/birthright/birthright.test.js.map +1 -0
- package/dist/birthright/index.d.ts +85 -0
- package/dist/birthright/index.d.ts.map +1 -0
- package/dist/birthright/index.js +132 -0
- package/dist/birthright/index.js.map +1 -0
- package/dist/evolve/evolve.js +7 -7
- package/dist/evolve/evolve.js.map +1 -1
- package/dist/exodus/quantum_cache.js +7 -7
- package/dist/exodus/quantum_cache.js.map +1 -1
- package/dist/forensics/stack-priors.d.ts.map +1 -1
- package/dist/forensics/stack-priors.js +6 -8
- package/dist/forensics/stack-priors.js.map +1 -1
- package/dist/handoff/handoff.test.d.ts +2 -0
- package/dist/handoff/handoff.test.d.ts.map +1 -0
- package/dist/handoff/handoff.test.js +67 -0
- package/dist/handoff/handoff.test.js.map +1 -0
- package/dist/handoff/index.d.ts +86 -0
- package/dist/handoff/index.d.ts.map +1 -0
- package/dist/handoff/index.js +168 -0
- package/dist/handoff/index.js.map +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +16 -0
- package/dist/index.js.map +1 -1
- package/dist/metron/code_audit.d.ts.map +1 -1
- package/dist/metron/code_audit.js +9 -1
- package/dist/metron/code_audit.js.map +1 -1
- package/dist/metron/update_notifier.d.ts.map +1 -1
- package/dist/metron/update_notifier.js +19 -0
- package/dist/metron/update_notifier.js.map +1 -1
- package/dist/nucleus_daemon.d.ts.map +1 -1
- package/dist/nucleus_daemon.js +14 -14
- package/dist/nucleus_daemon.js.map +1 -1
- package/dist/pulse.js +13 -13
- package/dist/pulse.js.map +1 -1
- package/dist/shadow_consensus/index.d.ts +117 -0
- package/dist/shadow_consensus/index.d.ts.map +1 -0
- package/dist/shadow_consensus/index.js +132 -0
- package/dist/shadow_consensus/index.js.map +1 -0
- package/dist/shadow_consensus/shadow_consensus.test.d.ts +2 -0
- package/dist/shadow_consensus/shadow_consensus.test.d.ts.map +1 -0
- package/dist/shadow_consensus/shadow_consensus.test.js +84 -0
- package/dist/shadow_consensus/shadow_consensus.test.js.map +1 -0
- package/dist/util/best_effort.d.ts +32 -0
- package/dist/util/best_effort.d.ts.map +1 -0
- package/dist/util/best_effort.js +58 -0
- package/dist/util/best_effort.js.map +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* v2.8.0 -- SHADOW CONSENSUS.
|
|
3
|
+
*
|
|
4
|
+
* "N vendors silently vote on a claim · winner is the fused verdict."
|
|
5
|
+
*
|
|
6
|
+
* The wild move: Mneme can already PREPARE a question + soul-prompt
|
|
7
|
+
* context. It can already FUSE multiple sensor verdicts via the v2.6
|
|
8
|
+
* TRUTH KERNEL. SHADOW CONSENSUS composes these two:
|
|
9
|
+
*
|
|
10
|
+
* 1. User asks Mneme a high-stakes question.
|
|
11
|
+
* 2. Mneme generates a soul prompt + question payload tagged with
|
|
12
|
+
* a "ballot id".
|
|
13
|
+
* 3. Mneme writes the ballot to N vendor inboxes (Claude / GPT /
|
|
14
|
+
* Gemini / Cursor / etc) via the existing handoff paths — the
|
|
15
|
+
* user (or AI orchestrator) pastes to each vendor.
|
|
16
|
+
* 4. Each vendor's reply lands back as a sensor output (caller calls
|
|
17
|
+
* `recordVendorReply(ballotId, vendor, answer)`).
|
|
18
|
+
* 5. When ≥ M replies arrive, SHADOW CONSENSUS fuses them via the
|
|
19
|
+
* v2.6 TRUTH KERNEL and emits a verdict + per-vendor breakdown.
|
|
20
|
+
*
|
|
21
|
+
* Mneme becomes a META-LLM that you don't pay for: it asks every
|
|
22
|
+
* vendor, fuses the answers, surfaces the disagreement. The user paid
|
|
23
|
+
* for the actual vendor seats; Mneme adds the consensus layer.
|
|
24
|
+
*
|
|
25
|
+
* Nobel-tier move: each ballot is HMAC-chained — sending the same
|
|
26
|
+
* question to Claude twice doesn't fool the consensus (Mneme detects
|
|
27
|
+
* the duplicate signature). Tampering with one vendor's reply also
|
|
28
|
+
* fails verification. The consensus IS the proof.
|
|
29
|
+
*
|
|
30
|
+
* Privacy: ballots are NEVER persisted off-disk by default. The caller
|
|
31
|
+
* decides if + where to store them.
|
|
32
|
+
*/
|
|
33
|
+
import { createHash, createHmac, randomBytes } from "node:crypto";
|
|
34
|
+
import { checkTruth } from "../truth_kernel/index.js";
|
|
35
|
+
import { safeHmacEqual } from "../util/hmac_compare.js";
|
|
36
|
+
function canonicalBallot(b) {
|
|
37
|
+
return JSON.stringify({ id: b.id, question: b.question, context: b.context ?? "", vendors: [...b.vendors].sort(), openedAt: b.openedAt });
|
|
38
|
+
}
|
|
39
|
+
function canonicalReply(r) {
|
|
40
|
+
return JSON.stringify({ ballotId: r.ballotId, vendor: r.vendor, verdict: r.verdict, confidence: r.confidence, rationale: r.rationale ?? "", receivedAt: r.receivedAt });
|
|
41
|
+
}
|
|
42
|
+
/** Open a new ballot. The HMAC is computed over the canonical body so
|
|
43
|
+
* duplicates with a different timestamp don't match. */
|
|
44
|
+
export function openBallot(input) {
|
|
45
|
+
if (input.vendors.length === 0)
|
|
46
|
+
throw new Error("openBallot: at least one vendor required");
|
|
47
|
+
if (input.question.length === 0)
|
|
48
|
+
throw new Error("openBallot: question must be non-empty");
|
|
49
|
+
const id = createHash("sha256").update(randomBytes(16)).digest("hex").slice(0, 16);
|
|
50
|
+
const body = {
|
|
51
|
+
id,
|
|
52
|
+
question: input.question,
|
|
53
|
+
context: input.context,
|
|
54
|
+
vendors: input.vendors,
|
|
55
|
+
openedAt: new Date().toISOString(),
|
|
56
|
+
};
|
|
57
|
+
const sig = createHmac("sha256", input.secret).update(canonicalBallot(body)).digest("hex");
|
|
58
|
+
return { ...body, sig };
|
|
59
|
+
}
|
|
60
|
+
/** Verify a ballot's HMAC matches the secret. */
|
|
61
|
+
export function verifyBallot(ballot, secret) {
|
|
62
|
+
const expected = createHmac("sha256", secret).update(canonicalBallot(ballot)).digest("hex");
|
|
63
|
+
return safeHmacEqual(expected, ballot.sig);
|
|
64
|
+
}
|
|
65
|
+
/** Record a vendor's reply against a ballot. Fails if the vendor wasn't
|
|
66
|
+
* invited or the ballot signature is bad. */
|
|
67
|
+
export function recordReply(input) {
|
|
68
|
+
if (!verifyBallot(input.ballot, input.secret))
|
|
69
|
+
return { ok: false, reason: "ballot signature invalid" };
|
|
70
|
+
if (!input.ballot.vendors.includes(input.vendor))
|
|
71
|
+
return { ok: false, reason: `vendor ${input.vendor} not invited` };
|
|
72
|
+
const body = {
|
|
73
|
+
ballotId: input.ballot.id,
|
|
74
|
+
vendor: input.vendor,
|
|
75
|
+
verdict: input.verdict,
|
|
76
|
+
confidence: Math.max(0, Math.min(1, input.confidence)),
|
|
77
|
+
rationale: input.rationale,
|
|
78
|
+
receivedAt: new Date().toISOString(),
|
|
79
|
+
};
|
|
80
|
+
const sig = createHmac("sha256", input.secret).update(canonicalReply(body)).digest("hex");
|
|
81
|
+
return { ok: true, reply: { ...body, sig } };
|
|
82
|
+
}
|
|
83
|
+
/** Verify a vendor reply's HMAC. */
|
|
84
|
+
export function verifyReply(reply, secret) {
|
|
85
|
+
const expected = createHmac("sha256", secret).update(canonicalReply(reply)).digest("hex");
|
|
86
|
+
return safeHmacEqual(expected, reply.sig);
|
|
87
|
+
}
|
|
88
|
+
/** Close the ballot and compute the fused consensus.
|
|
89
|
+
* Replies that fail HMAC verification are silently dropped + reported
|
|
90
|
+
* via `replies.length`. */
|
|
91
|
+
export async function closeConsensus(input) {
|
|
92
|
+
if (!verifyBallot(input.ballot, input.secret)) {
|
|
93
|
+
throw new Error("closeConsensus: ballot signature invalid");
|
|
94
|
+
}
|
|
95
|
+
const valid = [];
|
|
96
|
+
const seenVendors = new Set();
|
|
97
|
+
for (const r of input.replies) {
|
|
98
|
+
if (r.ballotId !== input.ballot.id)
|
|
99
|
+
continue;
|
|
100
|
+
if (!input.ballot.vendors.includes(r.vendor))
|
|
101
|
+
continue;
|
|
102
|
+
if (seenVendors.has(r.vendor))
|
|
103
|
+
continue; // one vote per vendor
|
|
104
|
+
if (!verifyReply(r, input.secret))
|
|
105
|
+
continue;
|
|
106
|
+
valid.push(r);
|
|
107
|
+
seenVendors.add(r.vendor);
|
|
108
|
+
}
|
|
109
|
+
const minQuorum = input.quorumOverride ?? Math.floor(input.ballot.vendors.length / 2) + 1;
|
|
110
|
+
const quorate = valid.length >= minQuorum;
|
|
111
|
+
// Wrap each reply as a TRUTH KERNEL sensor adapter.
|
|
112
|
+
const sensors = valid.map((r) => ({
|
|
113
|
+
id: r.vendor,
|
|
114
|
+
weight: 1,
|
|
115
|
+
run: () => ({ sensor: r.vendor, verdict: r.verdict, confidence: r.confidence, rationale: r.rationale }),
|
|
116
|
+
}));
|
|
117
|
+
const truth = await checkTruth({ claim: input.ballot.question, sensors });
|
|
118
|
+
const coverage = input.ballot.vendors.length > 0 ? valid.length / input.ballot.vendors.length : 0;
|
|
119
|
+
return {
|
|
120
|
+
ballot: input.ballot,
|
|
121
|
+
replies: valid,
|
|
122
|
+
truth,
|
|
123
|
+
coverage,
|
|
124
|
+
quorate,
|
|
125
|
+
closedAt: new Date().toISOString(),
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
/** Compact pulse summary. */
|
|
129
|
+
export function formatConsensusPulseLine(c) {
|
|
130
|
+
return `SHADOW-CONSENSUS · ${c.truth.verdict} · pTrue=${c.truth.pTrue.toFixed(2)} · coverage=${(c.coverage * 100).toFixed(0)}% · quorate=${c.quorate} · ballot=${c.ballot.id.slice(0, 8)}`;
|
|
131
|
+
}
|
|
132
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/shadow_consensus/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shadow_consensus.test.d.ts","sourceRoot":"","sources":["../../src/shadow_consensus/shadow_consensus.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { describe, it, expect } from "vitest";
|
|
2
|
+
import { openBallot, recordReply, closeConsensus, verifyBallot, verifyReply, formatConsensusPulseLine } from "./index.js";
|
|
3
|
+
describe("v2.8 SHADOW CONSENSUS", () => {
|
|
4
|
+
const secret = "test-secret";
|
|
5
|
+
it("openBallot mints a signed ballot", () => {
|
|
6
|
+
const b = openBallot({ question: "is X true?", vendors: ["claude", "gpt", "gemini"], secret });
|
|
7
|
+
expect(b.id).toMatch(/^[0-9a-f]{16}$/);
|
|
8
|
+
expect(b.sig.length).toBe(64);
|
|
9
|
+
expect(verifyBallot(b, secret)).toBe(true);
|
|
10
|
+
});
|
|
11
|
+
it("openBallot rejects empty inputs", () => {
|
|
12
|
+
expect(() => openBallot({ question: "", vendors: ["claude"], secret })).toThrow();
|
|
13
|
+
expect(() => openBallot({ question: "?", vendors: [], secret })).toThrow();
|
|
14
|
+
});
|
|
15
|
+
it("verifyBallot detects tampering", () => {
|
|
16
|
+
const b = openBallot({ question: "q", vendors: ["claude", "gpt"], secret });
|
|
17
|
+
const tampered = { ...b, question: "different" };
|
|
18
|
+
expect(verifyBallot(tampered, secret)).toBe(false);
|
|
19
|
+
});
|
|
20
|
+
it("recordReply succeeds for invited vendor", () => {
|
|
21
|
+
const b = openBallot({ question: "q", vendors: ["claude", "gpt"], secret });
|
|
22
|
+
const r = recordReply({ ballot: b, vendor: "claude", verdict: "TRUE", confidence: 0.9, secret });
|
|
23
|
+
expect(r.ok).toBe(true);
|
|
24
|
+
if (r.ok)
|
|
25
|
+
expect(verifyReply(r.reply, secret)).toBe(true);
|
|
26
|
+
});
|
|
27
|
+
it("recordReply rejects un-invited vendor", () => {
|
|
28
|
+
const b = openBallot({ question: "q", vendors: ["claude"], secret });
|
|
29
|
+
const r = recordReply({ ballot: b, vendor: "stranger", verdict: "TRUE", confidence: 1, secret });
|
|
30
|
+
expect(r.ok).toBe(false);
|
|
31
|
+
if (!r.ok)
|
|
32
|
+
expect(r.reason).toContain("not invited");
|
|
33
|
+
});
|
|
34
|
+
it("recordReply rejects with wrong secret", () => {
|
|
35
|
+
const b = openBallot({ question: "q", vendors: ["claude"], secret });
|
|
36
|
+
const r = recordReply({ ballot: b, vendor: "claude", verdict: "TRUE", confidence: 1, secret: "wrong" });
|
|
37
|
+
expect(r.ok).toBe(false);
|
|
38
|
+
});
|
|
39
|
+
it("closeConsensus fuses N replies via TRUTH KERNEL", async () => {
|
|
40
|
+
const b = openBallot({ question: "is X true?", vendors: ["claude", "gpt", "gemini"], secret });
|
|
41
|
+
const claudeR = recordReply({ ballot: b, vendor: "claude", verdict: "TRUE", confidence: 0.9, secret });
|
|
42
|
+
const gptR = recordReply({ ballot: b, vendor: "gpt", verdict: "TRUE", confidence: 0.85, secret });
|
|
43
|
+
expect(claudeR.ok && gptR.ok).toBe(true);
|
|
44
|
+
const replies = [
|
|
45
|
+
claudeR.reply,
|
|
46
|
+
gptR.reply,
|
|
47
|
+
];
|
|
48
|
+
const c = await closeConsensus({ ballot: b, replies, secret });
|
|
49
|
+
expect(c.truth.verdict).toBe("ACCEPTED");
|
|
50
|
+
expect(c.quorate).toBe(true); // 2 of 3 ≥ floor(3/2)+1 = 2
|
|
51
|
+
expect(c.coverage).toBeCloseTo(2 / 3, 2);
|
|
52
|
+
});
|
|
53
|
+
it("closeConsensus drops replies with tampered HMAC", async () => {
|
|
54
|
+
const b = openBallot({ question: "q", vendors: ["claude", "gpt"], secret });
|
|
55
|
+
const r1 = recordReply({ ballot: b, vendor: "claude", verdict: "TRUE", confidence: 0.9, secret });
|
|
56
|
+
const replyOk = r1.reply;
|
|
57
|
+
const tampered = { ...replyOk, verdict: "FALSE" };
|
|
58
|
+
const c = await closeConsensus({ ballot: b, replies: [replyOk, tampered], secret });
|
|
59
|
+
expect(c.replies.length).toBe(1); // tampered dropped
|
|
60
|
+
});
|
|
61
|
+
it("closeConsensus enforces one-vote-per-vendor", async () => {
|
|
62
|
+
const b = openBallot({ question: "q", vendors: ["claude"], secret });
|
|
63
|
+
const r1 = recordReply({ ballot: b, vendor: "claude", verdict: "TRUE", confidence: 0.9, secret });
|
|
64
|
+
const r2 = recordReply({ ballot: b, vendor: "claude", verdict: "FALSE", confidence: 0.9, secret });
|
|
65
|
+
const replies = [r1.reply, r2.reply];
|
|
66
|
+
const c = await closeConsensus({ ballot: b, replies, secret });
|
|
67
|
+
expect(c.replies.length).toBe(1); // duplicate dropped
|
|
68
|
+
});
|
|
69
|
+
it("closeConsensus not quorate when too few replies", async () => {
|
|
70
|
+
const b = openBallot({ question: "q", vendors: ["a", "b", "c", "d", "e"], secret });
|
|
71
|
+
const r = recordReply({ ballot: b, vendor: "a", verdict: "TRUE", confidence: 1, secret });
|
|
72
|
+
const reply = r.reply;
|
|
73
|
+
const c = await closeConsensus({ ballot: b, replies: [reply], secret });
|
|
74
|
+
expect(c.quorate).toBe(false); // 1 of 5 < floor(5/2)+1 = 3
|
|
75
|
+
});
|
|
76
|
+
it("formatConsensusPulseLine emits a compact summary", async () => {
|
|
77
|
+
const b = openBallot({ question: "q", vendors: ["a"], secret });
|
|
78
|
+
const r = recordReply({ ballot: b, vendor: "a", verdict: "TRUE", confidence: 1, secret });
|
|
79
|
+
const reply = r.reply;
|
|
80
|
+
const c = await closeConsensus({ ballot: b, replies: [reply], secret });
|
|
81
|
+
expect(formatConsensusPulseLine(c)).toContain("SHADOW-CONSENSUS");
|
|
82
|
+
});
|
|
83
|
+
});
|
|
84
|
+
//# sourceMappingURL=shadow_consensus.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shadow_consensus.test.js","sourceRoot":"","sources":["../../src/shadow_consensus/shadow_consensus.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* v2.8.0 -- BEST EFFORT marker.
|
|
3
|
+
*
|
|
4
|
+
* "Distinguish deliberate silent catches from accidental bug-swallowers."
|
|
5
|
+
*
|
|
6
|
+
* METRON v2.7 counted every `catch {}` as a Reliability penalty. That's
|
|
7
|
+
* unfair: some catches are intentionally silent (best-effort writes,
|
|
8
|
+
* optional probes, cleanup paths). The fix is structural — wrap
|
|
9
|
+
* deliberate silent catches in `bestEffort()` so:
|
|
10
|
+
*
|
|
11
|
+
* 1. The intent is documented at the call site (a comment with the
|
|
12
|
+
* reason instead of an opaque `catch {}`).
|
|
13
|
+
* 2. The auditor in METRON can recognise the marker and exclude it
|
|
14
|
+
* from the silent-catch penalty.
|
|
15
|
+
* 3. Optional `onError` callback lets callers log to a structured
|
|
16
|
+
* channel without changing the catch shape.
|
|
17
|
+
*
|
|
18
|
+
* Nobel-tier move: the marker IS the audit gate. Mneme refuses to ship
|
|
19
|
+
* Reliability score > 90 unless every catch{} is either WRAPPED in
|
|
20
|
+
* bestEffort() or REMEDIATED to a real handler. No more silent decay.
|
|
21
|
+
*/
|
|
22
|
+
/** Sentinel string embedded in the call site so METRON's audit can
|
|
23
|
+
* recognise a deliberate silent catch. */
|
|
24
|
+
export declare const BEST_EFFORT_MARKER = "BE:silent-by-design";
|
|
25
|
+
/** Synchronous best-effort wrapper. Runs the body, swallows errors,
|
|
26
|
+
* optionally invokes onError for telemetry. NEVER throws. */
|
|
27
|
+
export declare function bestEffort<T>(body: () => T, onError?: (e: unknown) => void): T | undefined;
|
|
28
|
+
/** Async best-effort wrapper. */
|
|
29
|
+
export declare function bestEffortAsync<T>(body: () => Promise<T> | T, onError?: (e: unknown) => void): Promise<T | undefined>;
|
|
30
|
+
/** Match catch-block bodies that are documented as best-effort. */
|
|
31
|
+
export declare const BEST_EFFORT_REGEX: RegExp;
|
|
32
|
+
//# sourceMappingURL=best_effort.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"best_effort.d.ts","sourceRoot":"","sources":["../../src/util/best_effort.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH;2CAC2C;AAC3C,eAAO,MAAM,kBAAkB,wBAAwB,CAAC;AAExD;8DAC8D;AAC9D,wBAAgB,UAAU,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,CAAC,EAAE,OAAO,CAAC,EAAE,CAAC,CAAC,EAAE,OAAO,KAAK,IAAI,GAAG,CAAC,GAAG,SAAS,CAS1F;AAED,iCAAiC;AACjC,wBAAsB,eAAe,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,OAAO,CAAC,EAAE,CAAC,CAAC,EAAE,OAAO,KAAK,IAAI,GAAG,OAAO,CAAC,CAAC,GAAG,SAAS,CAAC,CAS3H;AAED,mEAAmE;AACnE,eAAO,MAAM,iBAAiB,QAA8E,CAAC"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* v2.8.0 -- BEST EFFORT marker.
|
|
3
|
+
*
|
|
4
|
+
* "Distinguish deliberate silent catches from accidental bug-swallowers."
|
|
5
|
+
*
|
|
6
|
+
* METRON v2.7 counted every `catch {}` as a Reliability penalty. That's
|
|
7
|
+
* unfair: some catches are intentionally silent (best-effort writes,
|
|
8
|
+
* optional probes, cleanup paths). The fix is structural — wrap
|
|
9
|
+
* deliberate silent catches in `bestEffort()` so:
|
|
10
|
+
*
|
|
11
|
+
* 1. The intent is documented at the call site (a comment with the
|
|
12
|
+
* reason instead of an opaque `catch {}`).
|
|
13
|
+
* 2. The auditor in METRON can recognise the marker and exclude it
|
|
14
|
+
* from the silent-catch penalty.
|
|
15
|
+
* 3. Optional `onError` callback lets callers log to a structured
|
|
16
|
+
* channel without changing the catch shape.
|
|
17
|
+
*
|
|
18
|
+
* Nobel-tier move: the marker IS the audit gate. Mneme refuses to ship
|
|
19
|
+
* Reliability score > 90 unless every catch{} is either WRAPPED in
|
|
20
|
+
* bestEffort() or REMEDIATED to a real handler. No more silent decay.
|
|
21
|
+
*/
|
|
22
|
+
/** Sentinel string embedded in the call site so METRON's audit can
|
|
23
|
+
* recognise a deliberate silent catch. */
|
|
24
|
+
export const BEST_EFFORT_MARKER = "BE:silent-by-design";
|
|
25
|
+
/** Synchronous best-effort wrapper. Runs the body, swallows errors,
|
|
26
|
+
* optionally invokes onError for telemetry. NEVER throws. */
|
|
27
|
+
export function bestEffort(body, onError) {
|
|
28
|
+
try {
|
|
29
|
+
return body();
|
|
30
|
+
}
|
|
31
|
+
catch (e) {
|
|
32
|
+
if (onError) {
|
|
33
|
+
try {
|
|
34
|
+
onError(e);
|
|
35
|
+
}
|
|
36
|
+
catch { /* BE:silent-by-design (telemetry must not throw) */ }
|
|
37
|
+
}
|
|
38
|
+
return undefined;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
/** Async best-effort wrapper. */
|
|
42
|
+
export async function bestEffortAsync(body, onError) {
|
|
43
|
+
try {
|
|
44
|
+
return await body();
|
|
45
|
+
}
|
|
46
|
+
catch (e) {
|
|
47
|
+
if (onError) {
|
|
48
|
+
try {
|
|
49
|
+
onError(e);
|
|
50
|
+
}
|
|
51
|
+
catch { /* BE:silent-by-design (telemetry must not throw) */ }
|
|
52
|
+
}
|
|
53
|
+
return undefined;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
/** Match catch-block bodies that are documented as best-effort. */
|
|
57
|
+
export const BEST_EFFORT_REGEX = /catch\s*(?:\([^)]*\))?\s*\{\s*\/\*\s*(?:BE:silent-by-design|best-effort)/i;
|
|
58
|
+
//# sourceMappingURL=best_effort.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"best_effort.js","sourceRoot":"","sources":["../../src/util/best_effort.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH;2CAC2C;AAC3C,MAAM,CAAC,MAAM,kBAAkB,GAAG,qBAAqB,CAAC;AAExD;8DAC8D;AAC9D,MAAM,UAAU,UAAU,CAAI,IAAa,EAAE,OAA8B;IACzE,IAAI,CAAC;QACH,OAAO,IAAI,EAAE,CAAC;IAChB,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,IAAI,OAAO,EAAE,CAAC;YACZ,IAAI,CAAC;gBAAC,OAAO,CAAC,CAAC,CAAC,CAAC;YAAC,CAAC;YAAC,MAAM,CAAC,CAAC,oDAAoD,CAAC,CAAC;QACpF,CAAC;QACD,OAAO,SAAS,CAAC;IACnB,CAAC;AACH,CAAC;AAED,iCAAiC;AACjC,MAAM,CAAC,KAAK,UAAU,eAAe,CAAI,IAA0B,EAAE,OAA8B;IACjG,IAAI,CAAC;QACH,OAAO,MAAM,IAAI,EAAE,CAAC;IACtB,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,IAAI,OAAO,EAAE,CAAC;YACZ,IAAI,CAAC;gBAAC,OAAO,CAAC,CAAC,CAAC,CAAC;YAAC,CAAC;YAAC,MAAM,CAAC,CAAC,oDAAoD,CAAC,CAAC;QACpF,CAAC;QACD,OAAO,SAAS,CAAC;IACnB,CAAC;AACH,CAAC;AAED,mEAAmE;AACnE,MAAM,CAAC,MAAM,iBAAiB,GAAG,2EAA2E,CAAC"}
|