@mneme-ai/core 2.5.0 → 2.7.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/dist/index.d.ts +6 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +22 -0
- package/dist/index.js.map +1 -1
- package/dist/metron/code_audit.d.ts +55 -0
- package/dist/metron/code_audit.d.ts.map +1 -0
- package/dist/metron/code_audit.js +132 -0
- package/dist/metron/code_audit.js.map +1 -0
- package/dist/metron/code_audit.test.d.ts +2 -0
- package/dist/metron/code_audit.test.d.ts.map +1 -0
- package/dist/metron/code_audit.test.js +81 -0
- package/dist/metron/code_audit.test.js.map +1 -0
- package/dist/metron/index.d.ts +95 -0
- package/dist/metron/index.d.ts.map +1 -0
- package/dist/metron/index.js +393 -0
- package/dist/metron/index.js.map +1 -0
- package/dist/metron/metron.test.d.ts +2 -0
- package/dist/metron/metron.test.d.ts.map +1 -0
- package/dist/metron/metron.test.js +123 -0
- package/dist/metron/metron.test.js.map +1 -0
- package/dist/metron/update_notifier.d.ts +56 -0
- package/dist/metron/update_notifier.d.ts.map +1 -0
- package/dist/metron/update_notifier.js +143 -0
- package/dist/metron/update_notifier.js.map +1 -0
- package/dist/truth_kernel/index.d.ts +92 -0
- package/dist/truth_kernel/index.d.ts.map +1 -0
- package/dist/truth_kernel/index.js +203 -0
- package/dist/truth_kernel/index.js.map +1 -0
- package/dist/truth_kernel/truth_kernel.test.d.ts +2 -0
- package/dist/truth_kernel/truth_kernel.test.d.ts.map +1 -0
- package/dist/truth_kernel/truth_kernel.test.js +126 -0
- package/dist/truth_kernel/truth_kernel.test.js.map +1 -0
- package/dist/wormhole/auto_wire.d.ts +68 -0
- package/dist/wormhole/auto_wire.d.ts.map +1 -0
- package/dist/wormhole/auto_wire.js +186 -0
- package/dist/wormhole/auto_wire.js.map +1 -0
- package/dist/wormhole/index.d.ts +112 -0
- package/dist/wormhole/index.d.ts.map +1 -0
- package/dist/wormhole/index.js +151 -0
- package/dist/wormhole/index.js.map +1 -0
- package/dist/wormhole/wormhole.test.d.ts +2 -0
- package/dist/wormhole/wormhole.test.d.ts.map +1 -0
- package/dist/wormhole/wormhole.test.js +154 -0
- package/dist/wormhole/wormhole.test.js.map +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* v2.7.0 -- UPDATE NOTIFIER.
|
|
3
|
+
*
|
|
4
|
+
* "When Mneme upgrades, every AI agent in the user's editor must
|
|
5
|
+
* know — within one prompt — what changed and what they can call now."
|
|
6
|
+
*
|
|
7
|
+
* The pattern v2.5 introduced: when Mneme bumps version, the daemon
|
|
8
|
+
* sync'd CLAUDE.md / AGENTS.md / .cursor/rules with the FULL command
|
|
9
|
+
* manifest. Good, but verbose. Half of that block is unchanged across
|
|
10
|
+
* versions; AI agents already know.
|
|
11
|
+
*
|
|
12
|
+
* This module renders a [NEW SINCE vX.Y] block — a tight, version-
|
|
13
|
+
* scoped delta listing only the tools / behaviour changes added since
|
|
14
|
+
* the last seen version. Daemon writes the delta block above the
|
|
15
|
+
* full-manifest block; AI agents scan the delta first and ignore the
|
|
16
|
+
* rest until something cross-references it.
|
|
17
|
+
*
|
|
18
|
+
* Wild move: the delta block is HMAC-signed and timestamped, so an AI
|
|
19
|
+
* agent that hallucinates an old block (or a stale CLAUDE.md from a
|
|
20
|
+
* branch) can detect the staleness by checking the signature against
|
|
21
|
+
* the live Mneme version.
|
|
22
|
+
*/
|
|
23
|
+
import { createHmac } from "node:crypto";
|
|
24
|
+
/** The canonical changelog Mneme ships. Add new entries at the TOP. */
|
|
25
|
+
export const VERSION_DELTAS = [
|
|
26
|
+
{
|
|
27
|
+
version: "2.7.0",
|
|
28
|
+
releasedAt: "2026-05-13",
|
|
29
|
+
headline: "METRON verifiable scorecard (HMAC-signed evidence per axis), WORMHOLE auto-wire (daemon discovers + persists EWMA stats), CATCH AUDITOR + ANY DENSITY auditors feed real-time numbers into METRON.",
|
|
30
|
+
newTools: [
|
|
31
|
+
"mneme.metron.score",
|
|
32
|
+
"mneme.metron.verify",
|
|
33
|
+
"mneme.metron.audit",
|
|
34
|
+
"mneme.wormhole.auto_send",
|
|
35
|
+
],
|
|
36
|
+
changedBehaviors: [
|
|
37
|
+
"mneme.wormhole.status now reads .mneme/wormhole-stats.json automatically — no caller-supplied stats needed.",
|
|
38
|
+
"Pulse now embeds the METRON one-liner so AI agents see overall world-class score every turn.",
|
|
39
|
+
],
|
|
40
|
+
removed: [],
|
|
41
|
+
recommendedAction: "Call mneme.metron.score once at session start to learn the repo's current 8-axis scorecard. Treat any axis <70 as 'do not promise world-class' until improved.",
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
version: "2.6.0",
|
|
45
|
+
releasedAt: "2026-05-13",
|
|
46
|
+
headline: "TRUTH KERNEL (weighted-Bayesian fusion of every hallucination gate) + WORMHOLE (channel auto-negotiation for cross-device sync).",
|
|
47
|
+
newTools: ["mneme.truth.check_multi", "mneme.wormhole.status"],
|
|
48
|
+
changedBehaviors: [
|
|
49
|
+
"When you would have called flash / apoptosis / xray individually, call mneme.truth.check_multi instead — it fuses verdicts via weighted log-odds and surfaces disagreement as a separate signal.",
|
|
50
|
+
],
|
|
51
|
+
removed: [],
|
|
52
|
+
recommendedAction: "Replace per-gate hallucination checks with mneme.truth.check_multi for tighter verdicts.",
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
version: "2.5.0",
|
|
56
|
+
releasedAt: "2026-05-13",
|
|
57
|
+
headline: "12 v2.0/v2.1 wild-idea modules now have MCP surface (mutiny / prophet / prophecy / dream / wisdom_shards / necromancy / interstellar / twins / living_will / timeriver / recursive_soul / holy).",
|
|
58
|
+
newTools: [
|
|
59
|
+
"mneme.mutiny.check", "mneme.prophet.predict", "mneme.prophecy.read", "mneme.dream.run",
|
|
60
|
+
"mneme.wisdom_shards.append", "mneme.necromancy.fingerprint", "mneme.interstellar.compress",
|
|
61
|
+
"mneme.adversarial_twins.debate", "mneme.living_will.create", "mneme.timeriver.counterfactual",
|
|
62
|
+
"mneme.recursive_soul.list_reviews", "mneme.holy.heartbeat",
|
|
63
|
+
],
|
|
64
|
+
changedBehaviors: [],
|
|
65
|
+
removed: [],
|
|
66
|
+
recommendedAction: "These 12 tools were previously library-only; now they're first-class MCP calls.",
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
version: "2.4.0",
|
|
70
|
+
releasedAt: "2026-05-13",
|
|
71
|
+
headline: "Security hardening (4 root-cause class fixes: safe_exec / secret_store / hmac_compare / prompt_sanitize) + SYMBIOSIS per-vendor fusion + LEXICON writer-routing.",
|
|
72
|
+
newTools: [],
|
|
73
|
+
changedBehaviors: [
|
|
74
|
+
"Soul prompt + pulse + parasite-bridge are now sanitized + lexicon-tuned at render time. Vendor classifiers no longer see internal demonic vocabulary.",
|
|
75
|
+
"All execSync template strings replaced with spawnSync argv-array via util/safe_exec.",
|
|
76
|
+
],
|
|
77
|
+
removed: [],
|
|
78
|
+
recommendedAction: "Behind-the-scenes — no AI-side change required.",
|
|
79
|
+
},
|
|
80
|
+
];
|
|
81
|
+
const SENTINEL_BEGIN = "<!-- MNEME UPDATE NOTIFIER START -->";
|
|
82
|
+
const SENTINEL_END = "<!-- MNEME UPDATE NOTIFIER END -->";
|
|
83
|
+
/** Pick all deltas STRICTLY newer than lastSeenVersion (semver-lex order). */
|
|
84
|
+
function pickDeltas(input) {
|
|
85
|
+
const last = input.lastSeenVersion;
|
|
86
|
+
if (!last)
|
|
87
|
+
return VERSION_DELTAS;
|
|
88
|
+
const lastIdx = VERSION_DELTAS.findIndex((d) => d.version === last);
|
|
89
|
+
// VERSION_DELTAS is in DESCENDING order — newer entries come first.
|
|
90
|
+
// Slice up to (but not including) the lastSeen entry.
|
|
91
|
+
if (lastIdx === -1)
|
|
92
|
+
return VERSION_DELTAS;
|
|
93
|
+
return VERSION_DELTAS.slice(0, lastIdx);
|
|
94
|
+
}
|
|
95
|
+
/** Render a Markdown block AI agents should embed in their context. */
|
|
96
|
+
export function renderUpdateBlock(input) {
|
|
97
|
+
const deltas = pickDeltas(input);
|
|
98
|
+
if (deltas.length === 0)
|
|
99
|
+
return "";
|
|
100
|
+
const secret = input.secret ?? "metron-default";
|
|
101
|
+
const lines = [];
|
|
102
|
+
lines.push(SENTINEL_BEGIN);
|
|
103
|
+
lines.push(`## 📣 What's NEW in Mneme (since ${input.lastSeenVersion ?? "your first session"})`);
|
|
104
|
+
lines.push("");
|
|
105
|
+
lines.push(`AI agent: read this once per session. The list below is everything that CHANGED since the version you last saw — focus your attention here.`);
|
|
106
|
+
lines.push("");
|
|
107
|
+
for (const d of deltas) {
|
|
108
|
+
lines.push(`### v${d.version} — ${d.releasedAt}`);
|
|
109
|
+
lines.push(`${d.headline}`);
|
|
110
|
+
lines.push("");
|
|
111
|
+
if (d.newTools.length > 0) {
|
|
112
|
+
lines.push(`**New MCP tools:** ${d.newTools.map((t) => `\`${t}\``).join(", ")}`);
|
|
113
|
+
}
|
|
114
|
+
if (d.changedBehaviors.length > 0) {
|
|
115
|
+
lines.push(`**Changed behaviour:**`);
|
|
116
|
+
for (const c of d.changedBehaviors)
|
|
117
|
+
lines.push(`- ${c}`);
|
|
118
|
+
}
|
|
119
|
+
if (d.removed.length > 0) {
|
|
120
|
+
lines.push(`**Removed:** ${d.removed.map((t) => `\`${t}\``).join(", ")}`);
|
|
121
|
+
}
|
|
122
|
+
if (d.recommendedAction) {
|
|
123
|
+
lines.push(`**Do this:** ${d.recommendedAction}`);
|
|
124
|
+
}
|
|
125
|
+
lines.push("");
|
|
126
|
+
}
|
|
127
|
+
// HMAC + version footer so a stale block is detectable
|
|
128
|
+
const stamp = `[mneme-update-block | current=${input.currentVersion} | since=${input.lastSeenVersion ?? "?"} | at=${new Date().toISOString()}]`;
|
|
129
|
+
const sig = createHmac("sha256", secret).update(stamp).digest("hex").slice(0, 16);
|
|
130
|
+
lines.push(`> ${stamp} · sig=${sig}`);
|
|
131
|
+
lines.push(SENTINEL_END);
|
|
132
|
+
return lines.join("\n");
|
|
133
|
+
}
|
|
134
|
+
/** Verify the HMAC footer of a previously-rendered block. */
|
|
135
|
+
export function verifyUpdateBlock(block, secret = "metron-default") {
|
|
136
|
+
const m = block.match(/\[mneme-update-block \| current=([^|]+) \| since=([^|]+) \| at=([^\]]+)\] · sig=([0-9a-f]{16})/);
|
|
137
|
+
if (!m)
|
|
138
|
+
return { ok: false, reason: "no signed footer" };
|
|
139
|
+
const stamp = `[mneme-update-block | current=${m[1].trim()} | since=${m[2].trim()} | at=${m[3].trim()}]`;
|
|
140
|
+
const expected = createHmac("sha256", secret).update(stamp).digest("hex").slice(0, 16);
|
|
141
|
+
return expected === m[4] ? { ok: true } : { ok: false, reason: "signature mismatch" };
|
|
142
|
+
}
|
|
143
|
+
//# sourceMappingURL=update_notifier.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"update_notifier.js","sourceRoot":"","sources":["../../src/metron/update_notifier.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* v2.6.0 -- TRUTH KERNEL.
|
|
3
|
+
*
|
|
4
|
+
* "Many gates · one verdict · disagreement is signal, not noise."
|
|
5
|
+
*
|
|
6
|
+
* The pattern Mneme accumulated by v2.5: more than ten folders all
|
|
7
|
+
* answering the same family of question — "is this AI claim true?".
|
|
8
|
+
* Each carries a different sensor:
|
|
9
|
+
* FLASH — Veracity-Velocity Singularity over evidence weights
|
|
10
|
+
* APOPTOSIS — 7-witness fusion (file ∧ symbol ∧ type ∧ git ∧ test ∧ ...)
|
|
11
|
+
* X-RAY — surface-text hedging vs. absolutism
|
|
12
|
+
* TWINS — opposing-prior debate disagreement
|
|
13
|
+
* (additional sensors can be added — the kernel is sensor-agnostic.)
|
|
14
|
+
*
|
|
15
|
+
* Until now AI agents had to PICK which sensor to call. That's the
|
|
16
|
+
* wrong mental model. A truthful claim should look truthful to every
|
|
17
|
+
* sensor; a false claim is detected EARLIER when multiple sensors are
|
|
18
|
+
* fused. Mneme should ask the AI for a claim and run every sensor in
|
|
19
|
+
* parallel, then BAYESIAN-FUSE the verdicts into a single probability
|
|
20
|
+
* with calibrated weights.
|
|
21
|
+
*
|
|
22
|
+
* Wild move: DISAGREEMENT is itself the most valuable output. When
|
|
23
|
+
* apoptosis says HEALTHY and x-ray says LOW-CONFIDENCE, that conflict
|
|
24
|
+
* is a louder signal than either verdict alone. The kernel surfaces
|
|
25
|
+
* the disagreement, not just the fused score.
|
|
26
|
+
*
|
|
27
|
+
* Sensors stay independently callable (no breaking change). Kernel
|
|
28
|
+
* is a NEW SURFACE that composes them.
|
|
29
|
+
*/
|
|
30
|
+
export type SensorVerdict = "TRUE" | "FALSE" | "UNCERTAIN" | "INAPPLICABLE";
|
|
31
|
+
export interface SensorOutput {
|
|
32
|
+
/** Stable sensor id ("flash" / "apoptosis" / etc). */
|
|
33
|
+
sensor: string;
|
|
34
|
+
/** This sensor's verdict on the claim. */
|
|
35
|
+
verdict: SensorVerdict;
|
|
36
|
+
/** Sensor's confidence in its own verdict, 0..1. */
|
|
37
|
+
confidence: number;
|
|
38
|
+
/** Free-form rationale a human can read. */
|
|
39
|
+
rationale?: string;
|
|
40
|
+
/** Wall-clock ms the sensor took. */
|
|
41
|
+
ms?: number;
|
|
42
|
+
}
|
|
43
|
+
export interface SensorAdapter {
|
|
44
|
+
/** Stable id used in fusion + reporting. */
|
|
45
|
+
id: string;
|
|
46
|
+
/** Optional prior weight 0..1 — calibrated from historical accuracy.
|
|
47
|
+
* Default 1.0 (treat as fully reliable until measured otherwise). */
|
|
48
|
+
weight?: number;
|
|
49
|
+
/** Run the sensor. Must never throw — return a degraded verdict instead. */
|
|
50
|
+
run: (claim: string, ctx?: Record<string, unknown>) => Promise<SensorOutput> | SensorOutput;
|
|
51
|
+
}
|
|
52
|
+
export interface TruthKernelInput {
|
|
53
|
+
/** The claim under test. */
|
|
54
|
+
claim: string;
|
|
55
|
+
/** Sensors to fan out to. Must be ≥ 1. */
|
|
56
|
+
sensors: readonly SensorAdapter[];
|
|
57
|
+
/** Optional context passed verbatim to every sensor. */
|
|
58
|
+
ctx?: Record<string, unknown>;
|
|
59
|
+
/** Hard timeout per sensor in ms. Default 5000. */
|
|
60
|
+
perSensorTimeoutMs?: number;
|
|
61
|
+
}
|
|
62
|
+
export interface TruthVerdict {
|
|
63
|
+
/** Fused probability the claim is true, 0..1. */
|
|
64
|
+
pTrue: number;
|
|
65
|
+
/** Convenience label derived from pTrue + disagreement. */
|
|
66
|
+
verdict: "ACCEPTED" | "DISPUTED" | "REJECTED" | "INCONCLUSIVE";
|
|
67
|
+
/** 0..1 — how much sensors disagree. High disagreement = uncertain. */
|
|
68
|
+
disagreement: number;
|
|
69
|
+
/** Each sensor's raw verdict. */
|
|
70
|
+
sensorOutputs: SensorOutput[];
|
|
71
|
+
/** When applicable, the sensor that most-strongly drove the fused score. */
|
|
72
|
+
dominantSensor?: string;
|
|
73
|
+
/** When applicable, the sensor whose verdict is the outlier. */
|
|
74
|
+
outlierSensor?: string;
|
|
75
|
+
/** Total wall-clock ms. */
|
|
76
|
+
totalMs: number;
|
|
77
|
+
}
|
|
78
|
+
/** Run the kernel: fan out → fuse → label. */
|
|
79
|
+
export declare function checkTruth(input: TruthKernelInput): Promise<TruthVerdict>;
|
|
80
|
+
/** Compact one-line pulse summary. */
|
|
81
|
+
export declare function formatTruthKernelPulseLine(v: TruthVerdict): string;
|
|
82
|
+
/** Calibrate sensor weights from historical (sensorOutput, groundTruth) pairs.
|
|
83
|
+
* Returns a new weight map; higher weight = sensor was more often right.
|
|
84
|
+
*
|
|
85
|
+
* Simple algorithm: weight = max(0.1, accuracy * 2) so a 50% sensor → 1.0,
|
|
86
|
+
* a perfect sensor → 2.0, a random sensor → 1.0. Caps at 2.0 to avoid
|
|
87
|
+
* any single sensor dominating the log-odds sum. */
|
|
88
|
+
export declare function calibrateWeights(history: ReadonlyArray<{
|
|
89
|
+
sensor: string;
|
|
90
|
+
verdictWasCorrect: boolean;
|
|
91
|
+
}>): Map<string, number>;
|
|
92
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/truth_kernel/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAEH,MAAM,MAAM,aAAa,GAAG,MAAM,GAAG,OAAO,GAAG,WAAW,GAAG,cAAc,CAAC;AAE5E,MAAM,WAAW,YAAY;IAC3B,sDAAsD;IACtD,MAAM,EAAE,MAAM,CAAC;IACf,0CAA0C;IAC1C,OAAO,EAAE,aAAa,CAAC;IACvB,oDAAoD;IACpD,UAAU,EAAE,MAAM,CAAC;IACnB,4CAA4C;IAC5C,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,qCAAqC;IACrC,EAAE,CAAC,EAAE,MAAM,CAAC;CACb;AAED,MAAM,WAAW,aAAa;IAC5B,4CAA4C;IAC5C,EAAE,EAAE,MAAM,CAAC;IACX;0EACsE;IACtE,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,4EAA4E;IAC5E,GAAG,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,OAAO,CAAC,YAAY,CAAC,GAAG,YAAY,CAAC;CAC7F;AAED,MAAM,WAAW,gBAAgB;IAC/B,4BAA4B;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,0CAA0C;IAC1C,OAAO,EAAE,SAAS,aAAa,EAAE,CAAC;IAClC,wDAAwD;IACxD,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC9B,mDAAmD;IACnD,kBAAkB,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED,MAAM,WAAW,YAAY;IAC3B,iDAAiD;IACjD,KAAK,EAAE,MAAM,CAAC;IACd,2DAA2D;IAC3D,OAAO,EAAE,UAAU,GAAG,UAAU,GAAG,UAAU,GAAG,cAAc,CAAC;IAC/D,uEAAuE;IACvE,YAAY,EAAE,MAAM,CAAC;IACrB,iCAAiC;IACjC,aAAa,EAAE,YAAY,EAAE,CAAC;IAC9B,4EAA4E;IAC5E,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,gEAAgE;IAChE,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,2BAA2B;IAC3B,OAAO,EAAE,MAAM,CAAC;CACjB;AAiGD,8CAA8C;AAC9C,wBAAsB,UAAU,CAAC,KAAK,EAAE,gBAAgB,GAAG,OAAO,CAAC,YAAY,CAAC,CAiC/E;AAED,sCAAsC;AACtC,wBAAgB,0BAA0B,CAAC,CAAC,EAAE,YAAY,GAAG,MAAM,CAElE;AAED;;;;;qDAKqD;AACrD,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,aAAa,CAAC;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,iBAAiB,EAAE,OAAO,CAAA;CAAE,CAAC,GAAG,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAgB5H"}
|
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* v2.6.0 -- TRUTH KERNEL.
|
|
3
|
+
*
|
|
4
|
+
* "Many gates · one verdict · disagreement is signal, not noise."
|
|
5
|
+
*
|
|
6
|
+
* The pattern Mneme accumulated by v2.5: more than ten folders all
|
|
7
|
+
* answering the same family of question — "is this AI claim true?".
|
|
8
|
+
* Each carries a different sensor:
|
|
9
|
+
* FLASH — Veracity-Velocity Singularity over evidence weights
|
|
10
|
+
* APOPTOSIS — 7-witness fusion (file ∧ symbol ∧ type ∧ git ∧ test ∧ ...)
|
|
11
|
+
* X-RAY — surface-text hedging vs. absolutism
|
|
12
|
+
* TWINS — opposing-prior debate disagreement
|
|
13
|
+
* (additional sensors can be added — the kernel is sensor-agnostic.)
|
|
14
|
+
*
|
|
15
|
+
* Until now AI agents had to PICK which sensor to call. That's the
|
|
16
|
+
* wrong mental model. A truthful claim should look truthful to every
|
|
17
|
+
* sensor; a false claim is detected EARLIER when multiple sensors are
|
|
18
|
+
* fused. Mneme should ask the AI for a claim and run every sensor in
|
|
19
|
+
* parallel, then BAYESIAN-FUSE the verdicts into a single probability
|
|
20
|
+
* with calibrated weights.
|
|
21
|
+
*
|
|
22
|
+
* Wild move: DISAGREEMENT is itself the most valuable output. When
|
|
23
|
+
* apoptosis says HEALTHY and x-ray says LOW-CONFIDENCE, that conflict
|
|
24
|
+
* is a louder signal than either verdict alone. The kernel surfaces
|
|
25
|
+
* the disagreement, not just the fused score.
|
|
26
|
+
*
|
|
27
|
+
* Sensors stay independently callable (no breaking change). Kernel
|
|
28
|
+
* is a NEW SURFACE that composes them.
|
|
29
|
+
*/
|
|
30
|
+
/** Convert a sensor verdict into a probability that the claim is true.
|
|
31
|
+
* TRUE → confidence (clamp 0.5..1)
|
|
32
|
+
* FALSE → 1 - confidence (clamp 0..0.5)
|
|
33
|
+
* UNCERTAIN → 0.5 (no information)
|
|
34
|
+
* INAPPLICABLE → 0.5 with weight 0 (effectively removed) */
|
|
35
|
+
function verdictToProb(o) {
|
|
36
|
+
const c = Math.max(0, Math.min(1, o.confidence ?? 0));
|
|
37
|
+
switch (o.verdict) {
|
|
38
|
+
case "TRUE": return { p: 0.5 + 0.5 * c, informational: true };
|
|
39
|
+
case "FALSE": return { p: 0.5 - 0.5 * c, informational: true };
|
|
40
|
+
case "UNCERTAIN": return { p: 0.5, informational: false };
|
|
41
|
+
case "INAPPLICABLE": return { p: 0.5, informational: false };
|
|
42
|
+
default: return { p: 0.5, informational: false };
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
/** Run one sensor with a hard timeout. Always returns a verdict — on
|
|
46
|
+
* timeout / throw, returns an UNCERTAIN sensor output so the kernel
|
|
47
|
+
* stays robust. */
|
|
48
|
+
async function runSensorSafe(s, claim, ctx, timeoutMs) {
|
|
49
|
+
const t0 = Date.now();
|
|
50
|
+
try {
|
|
51
|
+
const result = await Promise.race([
|
|
52
|
+
Promise.resolve(s.run(claim, ctx)),
|
|
53
|
+
new Promise((_resolve, reject) => setTimeout(() => reject(new Error("timeout")), timeoutMs)),
|
|
54
|
+
]);
|
|
55
|
+
return { ...result, ms: result.ms ?? Date.now() - t0 };
|
|
56
|
+
}
|
|
57
|
+
catch (e) {
|
|
58
|
+
return { sensor: s.id, verdict: "UNCERTAIN", confidence: 0, rationale: `sensor failed: ${e.message?.slice(0, 80) ?? "unknown"}`, ms: Date.now() - t0 };
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
/** Weighted log-odds fusion with calibrated weights.
|
|
62
|
+
* Each informational sensor contributes log(p/(1-p)) * weight; the sum
|
|
63
|
+
* becomes the fused log-odds. Convert back with sigmoid. */
|
|
64
|
+
function fuse(sensorOutputs, adapters) {
|
|
65
|
+
let logOdds = 0;
|
|
66
|
+
let informational = 0;
|
|
67
|
+
for (const o of sensorOutputs) {
|
|
68
|
+
const { p, informational: inf } = verdictToProb(o);
|
|
69
|
+
if (!inf)
|
|
70
|
+
continue;
|
|
71
|
+
const a = adapters.get(o.sensor);
|
|
72
|
+
const w = a?.weight ?? 1.0;
|
|
73
|
+
// Clamp p away from {0,1} to keep log-odds finite.
|
|
74
|
+
const pSafe = Math.min(0.999, Math.max(0.001, p));
|
|
75
|
+
logOdds += Math.log(pSafe / (1 - pSafe)) * w;
|
|
76
|
+
informational++;
|
|
77
|
+
}
|
|
78
|
+
if (informational === 0)
|
|
79
|
+
return { pTrue: 0.5, informationalCount: 0 };
|
|
80
|
+
const pTrue = 1 / (1 + Math.exp(-logOdds));
|
|
81
|
+
return { pTrue, informationalCount: informational };
|
|
82
|
+
}
|
|
83
|
+
/** Disagreement = WEIGHTED variance of per-sensor pTrue across informational
|
|
84
|
+
* sensors, normalized to 0..1 (max weighted-variance is 0.25 when sensors
|
|
85
|
+
* split evenly). Weighting matters: a low-weight outlier shouldn't
|
|
86
|
+
* trigger DISPUTED when the high-weight sensors agree. */
|
|
87
|
+
function disagreementScore(sensorOutputs, adapters) {
|
|
88
|
+
const ps = [];
|
|
89
|
+
for (const o of sensorOutputs) {
|
|
90
|
+
const { p, informational } = verdictToProb(o);
|
|
91
|
+
if (!informational)
|
|
92
|
+
continue;
|
|
93
|
+
const w = adapters.get(o.sensor)?.weight ?? 1;
|
|
94
|
+
if (w <= 0)
|
|
95
|
+
continue;
|
|
96
|
+
ps.push({ p, w });
|
|
97
|
+
}
|
|
98
|
+
if (ps.length < 2)
|
|
99
|
+
return 0;
|
|
100
|
+
const totalW = ps.reduce((acc, x) => acc + x.w, 0);
|
|
101
|
+
if (totalW <= 0)
|
|
102
|
+
return 0;
|
|
103
|
+
const mean = ps.reduce((acc, x) => acc + x.p * x.w, 0) / totalW;
|
|
104
|
+
const variance = ps.reduce((acc, x) => acc + x.w * (x.p - mean) ** 2, 0) / totalW;
|
|
105
|
+
return Math.min(1, variance / 0.25);
|
|
106
|
+
}
|
|
107
|
+
/** Pick the dominant / outlier sensors from the informational set. */
|
|
108
|
+
function pickRoleSensors(sensorOutputs, adapters, pTrue) {
|
|
109
|
+
let dominantId;
|
|
110
|
+
let dominantPull = -Infinity;
|
|
111
|
+
let outlierId;
|
|
112
|
+
let outlierDist = -1;
|
|
113
|
+
for (const o of sensorOutputs) {
|
|
114
|
+
const { p, informational } = verdictToProb(o);
|
|
115
|
+
if (!informational)
|
|
116
|
+
continue;
|
|
117
|
+
const w = adapters.get(o.sensor)?.weight ?? 1;
|
|
118
|
+
// Dominant = strongest weighted log-odds contribution aligned with consensus.
|
|
119
|
+
const pSafe = Math.min(0.999, Math.max(0.001, p));
|
|
120
|
+
const contribution = (pTrue > 0.5 ? Math.log(pSafe / (1 - pSafe)) : -Math.log(pSafe / (1 - pSafe))) * w;
|
|
121
|
+
if (contribution > dominantPull) {
|
|
122
|
+
dominantPull = contribution;
|
|
123
|
+
dominantId = o.sensor;
|
|
124
|
+
}
|
|
125
|
+
// Outlier = furthest from consensus.
|
|
126
|
+
const dist = Math.abs(p - pTrue);
|
|
127
|
+
if (dist > outlierDist) {
|
|
128
|
+
outlierDist = dist;
|
|
129
|
+
outlierId = o.sensor;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
return { dominant: dominantId, outlier: outlierId };
|
|
133
|
+
}
|
|
134
|
+
/** Run the kernel: fan out → fuse → label. */
|
|
135
|
+
export async function checkTruth(input) {
|
|
136
|
+
if (input.sensors.length === 0) {
|
|
137
|
+
return { pTrue: 0.5, verdict: "INCONCLUSIVE", disagreement: 0, sensorOutputs: [], totalMs: 0 };
|
|
138
|
+
}
|
|
139
|
+
const t0 = Date.now();
|
|
140
|
+
const timeout = input.perSensorTimeoutMs ?? 5000;
|
|
141
|
+
const adapterMap = new Map();
|
|
142
|
+
for (const s of input.sensors)
|
|
143
|
+
adapterMap.set(s.id, s);
|
|
144
|
+
const sensorOutputs = await Promise.all(input.sensors.map((s) => runSensorSafe(s, input.claim, input.ctx, timeout)));
|
|
145
|
+
const { pTrue, informationalCount } = fuse(sensorOutputs, adapterMap);
|
|
146
|
+
const disagreement = disagreementScore(sensorOutputs, adapterMap);
|
|
147
|
+
const { dominant, outlier } = pickRoleSensors(sensorOutputs, adapterMap, pTrue);
|
|
148
|
+
let verdict;
|
|
149
|
+
if (informationalCount === 0) {
|
|
150
|
+
verdict = "INCONCLUSIVE";
|
|
151
|
+
}
|
|
152
|
+
else if (disagreement >= 0.5 && informationalCount >= 2) {
|
|
153
|
+
verdict = "DISPUTED";
|
|
154
|
+
}
|
|
155
|
+
else if (pTrue >= 0.75) {
|
|
156
|
+
verdict = "ACCEPTED";
|
|
157
|
+
}
|
|
158
|
+
else if (pTrue <= 0.25) {
|
|
159
|
+
verdict = "REJECTED";
|
|
160
|
+
}
|
|
161
|
+
else {
|
|
162
|
+
verdict = "INCONCLUSIVE";
|
|
163
|
+
}
|
|
164
|
+
return {
|
|
165
|
+
pTrue,
|
|
166
|
+
verdict,
|
|
167
|
+
disagreement,
|
|
168
|
+
sensorOutputs,
|
|
169
|
+
dominantSensor: dominant,
|
|
170
|
+
outlierSensor: outlier,
|
|
171
|
+
totalMs: Date.now() - t0,
|
|
172
|
+
};
|
|
173
|
+
}
|
|
174
|
+
/** Compact one-line pulse summary. */
|
|
175
|
+
export function formatTruthKernelPulseLine(v) {
|
|
176
|
+
return `TRUTH-KERNEL · ${v.verdict} · pTrue=${v.pTrue.toFixed(2)} · disagree=${v.disagreement.toFixed(2)} · sensors=${v.sensorOutputs.length} · ${v.totalMs}ms`;
|
|
177
|
+
}
|
|
178
|
+
/** Calibrate sensor weights from historical (sensorOutput, groundTruth) pairs.
|
|
179
|
+
* Returns a new weight map; higher weight = sensor was more often right.
|
|
180
|
+
*
|
|
181
|
+
* Simple algorithm: weight = max(0.1, accuracy * 2) so a 50% sensor → 1.0,
|
|
182
|
+
* a perfect sensor → 2.0, a random sensor → 1.0. Caps at 2.0 to avoid
|
|
183
|
+
* any single sensor dominating the log-odds sum. */
|
|
184
|
+
export function calibrateWeights(history) {
|
|
185
|
+
const tallies = new Map();
|
|
186
|
+
for (const h of history) {
|
|
187
|
+
const t = tallies.get(h.sensor) ?? { right: 0, total: 0 };
|
|
188
|
+
t.total++;
|
|
189
|
+
if (h.verdictWasCorrect)
|
|
190
|
+
t.right++;
|
|
191
|
+
tallies.set(h.sensor, t);
|
|
192
|
+
}
|
|
193
|
+
const weights = new Map();
|
|
194
|
+
for (const [sensor, t] of tallies) {
|
|
195
|
+
if (t.total === 0)
|
|
196
|
+
continue;
|
|
197
|
+
const acc = t.right / t.total;
|
|
198
|
+
const w = Math.max(0.1, Math.min(2.0, acc * 2));
|
|
199
|
+
weights.set(sensor, w);
|
|
200
|
+
}
|
|
201
|
+
return weights;
|
|
202
|
+
}
|
|
203
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/truth_kernel/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"truth_kernel.test.d.ts","sourceRoot":"","sources":["../../src/truth_kernel/truth_kernel.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import { describe, it, expect } from "vitest";
|
|
2
|
+
import { checkTruth, calibrateWeights, formatTruthKernelPulseLine } from "./index.js";
|
|
3
|
+
function makeSensor(id, verdict, confidence, weight = 1) {
|
|
4
|
+
return { id, weight, run: () => ({ sensor: id, verdict, confidence }) };
|
|
5
|
+
}
|
|
6
|
+
describe("v2.6 TRUTH KERNEL · fusion", () => {
|
|
7
|
+
it("two confident TRUE sensors → ACCEPTED with high pTrue", async () => {
|
|
8
|
+
const r = await checkTruth({
|
|
9
|
+
claim: "the sky is blue",
|
|
10
|
+
sensors: [makeSensor("flash", "TRUE", 0.9), makeSensor("apoptosis", "TRUE", 0.85)],
|
|
11
|
+
});
|
|
12
|
+
expect(r.verdict).toBe("ACCEPTED");
|
|
13
|
+
expect(r.pTrue).toBeGreaterThan(0.9);
|
|
14
|
+
expect(r.disagreement).toBeLessThan(0.05);
|
|
15
|
+
});
|
|
16
|
+
it("two confident FALSE sensors → REJECTED with low pTrue", async () => {
|
|
17
|
+
const r = await checkTruth({
|
|
18
|
+
claim: "the sky is green",
|
|
19
|
+
sensors: [makeSensor("flash", "FALSE", 0.9), makeSensor("apoptosis", "FALSE", 0.9)],
|
|
20
|
+
});
|
|
21
|
+
expect(r.verdict).toBe("REJECTED");
|
|
22
|
+
expect(r.pTrue).toBeLessThan(0.1);
|
|
23
|
+
});
|
|
24
|
+
it("conflicting sensors → DISPUTED with high disagreement", async () => {
|
|
25
|
+
const r = await checkTruth({
|
|
26
|
+
claim: "ambiguous claim",
|
|
27
|
+
sensors: [makeSensor("flash", "TRUE", 0.9), makeSensor("apoptosis", "FALSE", 0.9)],
|
|
28
|
+
});
|
|
29
|
+
expect(r.verdict).toBe("DISPUTED");
|
|
30
|
+
expect(r.disagreement).toBeGreaterThan(0.5);
|
|
31
|
+
expect(r.outlierSensor).toBeDefined();
|
|
32
|
+
});
|
|
33
|
+
it("all UNCERTAIN sensors → INCONCLUSIVE", async () => {
|
|
34
|
+
const r = await checkTruth({
|
|
35
|
+
claim: "x",
|
|
36
|
+
sensors: [makeSensor("a", "UNCERTAIN", 0), makeSensor("b", "UNCERTAIN", 0)],
|
|
37
|
+
});
|
|
38
|
+
expect(r.verdict).toBe("INCONCLUSIVE");
|
|
39
|
+
expect(r.pTrue).toBeCloseTo(0.5, 2);
|
|
40
|
+
});
|
|
41
|
+
it("INAPPLICABLE sensors are excluded from fusion", async () => {
|
|
42
|
+
const r = await checkTruth({
|
|
43
|
+
claim: "x",
|
|
44
|
+
sensors: [makeSensor("a", "TRUE", 0.95), makeSensor("b", "INAPPLICABLE", 0)],
|
|
45
|
+
});
|
|
46
|
+
expect(r.verdict).toBe("ACCEPTED");
|
|
47
|
+
expect(r.pTrue).toBeGreaterThan(0.9);
|
|
48
|
+
});
|
|
49
|
+
it("higher-weight sensor dominates the fused verdict", async () => {
|
|
50
|
+
const r = await checkTruth({
|
|
51
|
+
claim: "tie-breaker test",
|
|
52
|
+
sensors: [makeSensor("trustworthy", "TRUE", 0.9, 2.0), makeSensor("flaky", "FALSE", 0.9, 0.2)],
|
|
53
|
+
});
|
|
54
|
+
expect(r.verdict).toBe("ACCEPTED");
|
|
55
|
+
expect(r.pTrue).toBeGreaterThan(0.5);
|
|
56
|
+
expect(r.dominantSensor).toBe("trustworthy");
|
|
57
|
+
});
|
|
58
|
+
it("empty sensor list → INCONCLUSIVE", async () => {
|
|
59
|
+
const r = await checkTruth({ claim: "x", sensors: [] });
|
|
60
|
+
expect(r.verdict).toBe("INCONCLUSIVE");
|
|
61
|
+
});
|
|
62
|
+
it("crashing sensor degrades to UNCERTAIN gracefully", async () => {
|
|
63
|
+
const crashy = {
|
|
64
|
+
id: "crashy",
|
|
65
|
+
run: () => { throw new Error("kaboom"); },
|
|
66
|
+
};
|
|
67
|
+
const r = await checkTruth({
|
|
68
|
+
claim: "x",
|
|
69
|
+
sensors: [makeSensor("ok", "TRUE", 0.9), crashy],
|
|
70
|
+
});
|
|
71
|
+
// Crashy sensor is non-informational → ok sensor drives the verdict.
|
|
72
|
+
expect(r.verdict).toBe("ACCEPTED");
|
|
73
|
+
const crashOut = r.sensorOutputs.find((o) => o.sensor === "crashy");
|
|
74
|
+
expect(crashOut?.verdict).toBe("UNCERTAIN");
|
|
75
|
+
});
|
|
76
|
+
it("slow sensor times out without blocking the kernel", async () => {
|
|
77
|
+
const slow = {
|
|
78
|
+
id: "slow",
|
|
79
|
+
run: () => new Promise((resolve) => setTimeout(() => resolve({ sensor: "slow", verdict: "TRUE", confidence: 1 }), 200)),
|
|
80
|
+
};
|
|
81
|
+
const r = await checkTruth({
|
|
82
|
+
claim: "x",
|
|
83
|
+
sensors: [makeSensor("fast", "TRUE", 0.9), slow],
|
|
84
|
+
perSensorTimeoutMs: 50,
|
|
85
|
+
});
|
|
86
|
+
const slowOut = r.sensorOutputs.find((o) => o.sensor === "slow");
|
|
87
|
+
expect(slowOut?.verdict).toBe("UNCERTAIN");
|
|
88
|
+
expect(r.verdict).toBe("ACCEPTED"); // fast sensor still drives the verdict
|
|
89
|
+
});
|
|
90
|
+
});
|
|
91
|
+
describe("v2.6 TRUTH KERNEL · calibration", () => {
|
|
92
|
+
it("perfectly-accurate sensor gets weight 2.0", () => {
|
|
93
|
+
const history = Array.from({ length: 10 }, () => ({ sensor: "perfect", verdictWasCorrect: true }));
|
|
94
|
+
const w = calibrateWeights(history);
|
|
95
|
+
expect(w.get("perfect")).toBe(2.0);
|
|
96
|
+
});
|
|
97
|
+
it("50%-accurate sensor gets weight 1.0", () => {
|
|
98
|
+
const history = [
|
|
99
|
+
...Array.from({ length: 5 }, () => ({ sensor: "average", verdictWasCorrect: true })),
|
|
100
|
+
...Array.from({ length: 5 }, () => ({ sensor: "average", verdictWasCorrect: false })),
|
|
101
|
+
];
|
|
102
|
+
const w = calibrateWeights(history);
|
|
103
|
+
expect(w.get("average")).toBeCloseTo(1.0, 2);
|
|
104
|
+
});
|
|
105
|
+
it("always-wrong sensor gets weight floor 0.1", () => {
|
|
106
|
+
const history = Array.from({ length: 10 }, () => ({ sensor: "wrong", verdictWasCorrect: false }));
|
|
107
|
+
const w = calibrateWeights(history);
|
|
108
|
+
expect(w.get("wrong")).toBe(0.1);
|
|
109
|
+
});
|
|
110
|
+
it("empty history → empty weight map", () => {
|
|
111
|
+
expect(calibrateWeights([]).size).toBe(0);
|
|
112
|
+
});
|
|
113
|
+
});
|
|
114
|
+
describe("v2.6 TRUTH KERNEL · pulse", () => {
|
|
115
|
+
it("formatTruthKernelPulseLine produces a compact summary", async () => {
|
|
116
|
+
const r = await checkTruth({
|
|
117
|
+
claim: "x",
|
|
118
|
+
sensors: [makeSensor("a", "TRUE", 0.9)],
|
|
119
|
+
});
|
|
120
|
+
const line = formatTruthKernelPulseLine(r);
|
|
121
|
+
expect(line).toContain("TRUTH-KERNEL");
|
|
122
|
+
expect(line).toContain("ACCEPTED");
|
|
123
|
+
expect(line).toContain("pTrue=");
|
|
124
|
+
});
|
|
125
|
+
});
|
|
126
|
+
//# sourceMappingURL=truth_kernel.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"truth_kernel.test.js","sourceRoot":"","sources":["../../src/truth_kernel/truth_kernel.test.ts"],"names":[],"mappings":"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"}
|