@mneme-ai/core 2.15.2 → 2.16.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 (61) hide show
  1. package/dist/agent_manifest.d.ts +1 -1
  2. package/dist/agent_manifest.d.ts.map +1 -1
  3. package/dist/agent_manifest.js +18 -1
  4. package/dist/agent_manifest.js.map +1 -1
  5. package/dist/alpha/alpha.test.d.ts +2 -0
  6. package/dist/alpha/alpha.test.d.ts.map +1 -0
  7. package/dist/alpha/alpha.test.js +101 -0
  8. package/dist/alpha/alpha.test.js.map +1 -0
  9. package/dist/alpha/index.d.ts +106 -0
  10. package/dist/alpha/index.d.ts.map +1 -0
  11. package/dist/alpha/index.js +190 -0
  12. package/dist/alpha/index.js.map +1 -0
  13. package/dist/anti_collusion/anti_collusion.test.d.ts +2 -0
  14. package/dist/anti_collusion/anti_collusion.test.d.ts.map +1 -0
  15. package/dist/anti_collusion/anti_collusion.test.js +137 -0
  16. package/dist/anti_collusion/anti_collusion.test.js.map +1 -0
  17. package/dist/anti_collusion/index.d.ts +89 -0
  18. package/dist/anti_collusion/index.d.ts.map +1 -0
  19. package/dist/anti_collusion/index.js +218 -0
  20. package/dist/anti_collusion/index.js.map +1 -0
  21. package/dist/cosmic/aurelian_v216.test.d.ts +2 -0
  22. package/dist/cosmic/aurelian_v216.test.d.ts.map +1 -0
  23. package/dist/cosmic/aurelian_v216.test.js +89 -0
  24. package/dist/cosmic/aurelian_v216.test.js.map +1 -0
  25. package/dist/index.d.ts +6 -0
  26. package/dist/index.d.ts.map +1 -1
  27. package/dist/index.js +7 -0
  28. package/dist/index.js.map +1 -1
  29. package/dist/living_model/index.d.ts +104 -0
  30. package/dist/living_model/index.d.ts.map +1 -0
  31. package/dist/living_model/index.js +152 -0
  32. package/dist/living_model/index.js.map +1 -0
  33. package/dist/living_model/living_model.test.d.ts +2 -0
  34. package/dist/living_model/living_model.test.d.ts.map +1 -0
  35. package/dist/living_model/living_model.test.js +125 -0
  36. package/dist/living_model/living_model.test.js.map +1 -0
  37. package/dist/obelisk/index.d.ts +74 -0
  38. package/dist/obelisk/index.d.ts.map +1 -0
  39. package/dist/obelisk/index.js +114 -0
  40. package/dist/obelisk/index.js.map +1 -0
  41. package/dist/obelisk/obelisk.test.d.ts +2 -0
  42. package/dist/obelisk/obelisk.test.d.ts.map +1 -0
  43. package/dist/obelisk/obelisk.test.js +67 -0
  44. package/dist/obelisk/obelisk.test.js.map +1 -0
  45. package/dist/persona/index.d.ts +107 -0
  46. package/dist/persona/index.d.ts.map +1 -0
  47. package/dist/persona/index.js +144 -0
  48. package/dist/persona/index.js.map +1 -0
  49. package/dist/persona/persona.test.d.ts +2 -0
  50. package/dist/persona/persona.test.d.ts.map +1 -0
  51. package/dist/persona/persona.test.js +71 -0
  52. package/dist/persona/persona.test.js.map +1 -0
  53. package/dist/public_audit/index.d.ts +70 -0
  54. package/dist/public_audit/index.d.ts.map +1 -0
  55. package/dist/public_audit/index.js +175 -0
  56. package/dist/public_audit/index.js.map +1 -0
  57. package/dist/public_audit/public_audit.test.d.ts +2 -0
  58. package/dist/public_audit/public_audit.test.d.ts.map +1 -0
  59. package/dist/public_audit/public_audit.test.js +64 -0
  60. package/dist/public_audit/public_audit.test.js.map +1 -0
  61. package/package.json +1 -1
@@ -0,0 +1,152 @@
1
+ /**
2
+ * v2.16.0 — MNEME LIVING MODEL
3
+ *
4
+ * "Promote INFRA AS AI from per-host primitive to a real distributed
5
+ * Living Model. Anti-entropy sync between hosts + causal inference
6
+ * over the gossiped patterns + federated query."
7
+ *
8
+ * Phase 1 primitives (v2.16): the three abstractions a fully-distributed
9
+ * inference layer needs.
10
+ *
11
+ * 1. anti-entropy sync — Merkle-tree summary of local observations;
12
+ * peers compare summaries and exchange only the diff
13
+ * 2. causal inference — given pairs of observations (event A at host X,
14
+ * event B at host Y), compute correlation + lead/lag + a naive
15
+ * Granger-causality-ish score
16
+ * 3. federated query — given a question + a list of peer digests,
17
+ * route the query to peers most likely to have matching observations
18
+ *
19
+ * v2.17+ will wire these into a real gossip protocol. v2.16 ships the
20
+ * pure primitives, fully testable.
21
+ */
22
+ import { createHash, createHmac } from "node:crypto";
23
+ const PROTOCOL_VERSION = 1;
24
+ export function buildMerkleSummary(host, observations) {
25
+ const ids = observations.map((o) => o.id).sort();
26
+ if (ids.length === 0)
27
+ return { v: PROTOCOL_VERSION, host, total: 0, root: createHash("sha256").update("").digest("hex"), leafIds: [] };
28
+ // Layered hashing
29
+ let layer = ids.map((id) => createHash("sha256").update(id).digest("hex"));
30
+ while (layer.length > 1) {
31
+ const next = [];
32
+ for (let i = 0; i < layer.length; i += 2) {
33
+ const a = layer[i];
34
+ const b = layer[i + 1] ?? a;
35
+ next.push(createHash("sha256").update(a + b).digest("hex"));
36
+ }
37
+ layer = next;
38
+ }
39
+ return { v: PROTOCOL_VERSION, host, total: ids.length, root: layer[0], leafIds: ids };
40
+ }
41
+ /** Diff two summaries: which ids does the LOCAL host need to request from
42
+ * the PEER? Pure set difference on leafIds. */
43
+ export function diffSummaries(local, peer) {
44
+ const localSet = new Set(local.leafIds);
45
+ const peerSet = new Set(peer.leafIds);
46
+ const toFetch = peer.leafIds.filter((id) => !localSet.has(id));
47
+ const toSend = local.leafIds.filter((id) => !peerSet.has(id));
48
+ return { toFetch, toSend, rootsMatch: local.root === peer.root };
49
+ }
50
+ function corr(xs, ys) {
51
+ if (xs.length !== ys.length || xs.length < 3)
52
+ return null;
53
+ const meanX = xs.reduce((a, b) => a + b, 0) / xs.length;
54
+ const meanY = ys.reduce((a, b) => a + b, 0) / ys.length;
55
+ let num = 0, dx2 = 0, dy2 = 0;
56
+ for (let i = 0; i < xs.length; i++) {
57
+ const dx = xs[i] - meanX, dy = ys[i] - meanY;
58
+ num += dx * dy;
59
+ dx2 += dx * dx;
60
+ dy2 += dy * dy;
61
+ }
62
+ const denom = Math.sqrt(dx2 * dy2);
63
+ return denom === 0 ? 0 : num / denom;
64
+ }
65
+ export function inferCausal(pairs, opts = {}) {
66
+ if (pairs.length === 0) {
67
+ return { cause: "", effect: "", correlation: null, meanLeadSeconds: null, directionalityVote: 0, samples: 0, sig: "" };
68
+ }
69
+ const cause = pairs[0].cause;
70
+ const effect = pairs[0].effect;
71
+ // Group pairs into adjacent cause/effect occurrences (within same minute
72
+ // window). Compute time deltas.
73
+ const sorted = pairs.slice().sort((a, b) => a.ts.localeCompare(b.ts));
74
+ const causeTimes = [];
75
+ const effectTimes = [];
76
+ const causeVals = [];
77
+ const effectVals = [];
78
+ for (const p of sorted) {
79
+ const t = new Date(p.ts).getTime();
80
+ if (!Number.isFinite(t))
81
+ continue;
82
+ if (p.cause === cause) {
83
+ causeTimes.push(t);
84
+ if (p.value !== undefined)
85
+ causeVals.push(p.value);
86
+ }
87
+ if (p.effect === effect) {
88
+ effectTimes.push(t);
89
+ if (p.value !== undefined)
90
+ effectVals.push(p.value);
91
+ }
92
+ }
93
+ // Lead time: for each effect, find the most recent cause within 1h.
94
+ // Average the (effect - cause) deltas.
95
+ const leads = [];
96
+ let forwardCount = 0, reverseCount = 0;
97
+ for (const eT of effectTimes) {
98
+ let best = -Infinity;
99
+ for (const cT of causeTimes) {
100
+ if (cT <= eT && eT - cT <= 3600 * 1000)
101
+ best = Math.max(best, cT);
102
+ }
103
+ if (best > -Infinity) {
104
+ const delta = (eT - best) / 1000;
105
+ leads.push(delta);
106
+ // Same-instant observations are ambiguous (delta === 0) — don't
107
+ // count toward either direction. Only count strictly-ordered pairs.
108
+ if (delta > 0)
109
+ forwardCount++;
110
+ else if (delta < 0)
111
+ reverseCount++;
112
+ }
113
+ }
114
+ const meanLead = leads.length > 0 ? leads.reduce((a, b) => a + b, 0) / leads.length : null;
115
+ const totalVotes = forwardCount + reverseCount;
116
+ const directionalityVote = totalVotes === 0 ? 0.5 : forwardCount / totalVotes;
117
+ // Correlation when both series have aligned values
118
+ const minLen = Math.min(causeVals.length, effectVals.length);
119
+ const correlation = minLen >= 3 ? corr(causeVals.slice(0, minLen), effectVals.slice(0, minLen)) : null;
120
+ const body = { cause, effect, correlation, meanLeadSeconds: meanLead, directionalityVote, samples: pairs.length };
121
+ const sig = createHmac("sha256", opts.secret ?? "mneme-living-model-default").update(JSON.stringify(body)).digest("hex");
122
+ return { ...body, sig };
123
+ }
124
+ export function routeFederatedQuery(input) {
125
+ const max = input.maxPeers ?? 3;
126
+ const subjectLower = input.subject.toLowerCase();
127
+ const kindLower = (input.kind ?? "").toLowerCase();
128
+ const scored = input.peers.map((p) => {
129
+ let score = 0;
130
+ const reasons = [];
131
+ if (p.knownSubjects?.some((s) => s.toLowerCase().includes(subjectLower) || subjectLower.includes(s.toLowerCase()))) {
132
+ score += 0.6;
133
+ reasons.push(`subject match`);
134
+ }
135
+ if (kindLower && p.knownKinds?.some((k) => k.toLowerCase() === kindLower)) {
136
+ score += 0.4;
137
+ reasons.push(`kind match`);
138
+ }
139
+ if (score === 0)
140
+ reasons.push("no specific hint");
141
+ return { peer: p.host, score: Math.round(score * 100) / 100, reason: reasons.join(" + ") };
142
+ }).sort((a, b) => b.score - a.score).slice(0, max);
143
+ const topScore = scored[0]?.score ?? 0;
144
+ return {
145
+ recommendations: scored,
146
+ fallback: topScore >= 0.6 ? "narrow" : "broadcast",
147
+ };
148
+ }
149
+ export function formatLivingModelLine(s) {
150
+ return `LIVING · ${s.host} · ${s.total} obs · root=${s.root.slice(0, 12)}`;
151
+ }
152
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/living_model/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=living_model.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"living_model.test.d.ts","sourceRoot":"","sources":["../../src/living_model/living_model.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,125 @@
1
+ import { describe, it, expect } from "vitest";
2
+ import { buildMerkleSummary, diffSummaries, inferCausal, routeFederatedQuery, formatLivingModelLine } from "./index.js";
3
+ describe("v2.16 · LIVING MODEL primitives", () => {
4
+ describe("Merkle anti-entropy", () => {
5
+ it("empty observation list still produces a root", () => {
6
+ const s = buildMerkleSummary("host-a", []);
7
+ expect(s.root).toMatch(/^[0-9a-f]{64}$/);
8
+ expect(s.total).toBe(0);
9
+ });
10
+ it("identical observation sets produce identical roots", () => {
11
+ const obs = [{ id: "o1", ts: "x", host: "a", kind: "k", subject: "s" }];
12
+ const a = buildMerkleSummary("h", obs);
13
+ const b = buildMerkleSummary("h", obs);
14
+ expect(a.root).toBe(b.root);
15
+ });
16
+ it("diff finds missing ids both ways", () => {
17
+ const a = buildMerkleSummary("a", [
18
+ { id: "1", ts: "t", host: "a", kind: "k", subject: "s" },
19
+ { id: "2", ts: "t", host: "a", kind: "k", subject: "s" },
20
+ ]);
21
+ const b = buildMerkleSummary("b", [
22
+ { id: "2", ts: "t", host: "b", kind: "k", subject: "s" },
23
+ { id: "3", ts: "t", host: "b", kind: "k", subject: "s" },
24
+ ]);
25
+ const d = diffSummaries(a, b);
26
+ expect(d.toFetch).toEqual(["3"]);
27
+ expect(d.toSend).toEqual(["1"]);
28
+ expect(d.rootsMatch).toBe(false);
29
+ });
30
+ it("identical sets → rootsMatch true + no ids to fetch", () => {
31
+ const obs = [{ id: "x", ts: "t", host: "a", kind: "k", subject: "s" }];
32
+ const a = buildMerkleSummary("a", obs);
33
+ const b = buildMerkleSummary("b", obs);
34
+ const d = diffSummaries(a, b);
35
+ expect(d.rootsMatch).toBe(true);
36
+ expect(d.toFetch).toEqual([]);
37
+ expect(d.toSend).toEqual([]);
38
+ });
39
+ });
40
+ describe("Causal inference", () => {
41
+ it("empty input → zero samples", () => {
42
+ const r = inferCausal([]);
43
+ expect(r.samples).toBe(0);
44
+ });
45
+ it("cause precedes effect → positive directionalityVote + positive mean lead", () => {
46
+ // Pattern: every day, a deploy at 10:00 → an error_spike 5 min later
47
+ const pairs = [];
48
+ for (let i = 0; i < 5; i++) {
49
+ const dayMs = i * 24 * 60 * 60 * 1000;
50
+ const t0 = 1700000000000 + dayMs;
51
+ // Deploy event (no effect bound yet)
52
+ pairs.push({ ts: new Date(t0).toISOString(), cause: "deploy", effect: "X" });
53
+ // Error spike 5 min after deploy
54
+ pairs.push({ ts: new Date(t0 + 5 * 60 * 1000).toISOString(), cause: "Y", effect: "error_spike" });
55
+ }
56
+ // The first pair sets cause="deploy" effect="X". We want to test
57
+ // deploy→error_spike, so re-orient: pass cause-only and effect-only
58
+ // observations.
59
+ const r = inferCausal([
60
+ { ts: new Date(1700000000000).toISOString(), cause: "deploy", effect: "error_spike" }, // anchor
61
+ ...pairs.slice(1).map((p, i) => ({
62
+ ...p,
63
+ cause: p.cause === "deploy" ? "deploy" : "noop",
64
+ effect: p.effect === "error_spike" ? "error_spike" : "noop",
65
+ })),
66
+ ]);
67
+ expect(r.directionalityVote).toBeGreaterThan(0.5);
68
+ expect(r.meanLeadSeconds).toBeGreaterThan(0);
69
+ });
70
+ it("includes correlation when numeric values supplied", () => {
71
+ const pairs = [];
72
+ for (let i = 0; i < 5; i++) {
73
+ pairs.push({ ts: new Date(1700000000000 + i * 60 * 1000).toISOString(), cause: "load", effect: "latency", value: i + 1 });
74
+ pairs.push({ ts: new Date(1700000000000 + i * 60 * 1000 + 30 * 1000).toISOString(), cause: "load", effect: "latency", value: (i + 1) * 2 });
75
+ }
76
+ const r = inferCausal(pairs);
77
+ expect(r.correlation).not.toBeNull();
78
+ });
79
+ it("HMAC sig present on non-empty result", () => {
80
+ const r = inferCausal([{ ts: "2026-01-01T00:00:00Z", cause: "a", effect: "b" }]);
81
+ expect(r.sig).toMatch(/^[0-9a-f]{64}$/);
82
+ });
83
+ });
84
+ describe("Federated query routing", () => {
85
+ it("routes by subject match", () => {
86
+ const r = routeFederatedQuery({
87
+ subject: "auth-service",
88
+ peers: [
89
+ { host: "h1", knownSubjects: ["auth-service", "billing"] },
90
+ { host: "h2", knownSubjects: ["frontend"] },
91
+ { host: "h3", knownSubjects: ["payments"] },
92
+ ],
93
+ });
94
+ expect(r.recommendations[0].peer).toBe("h1");
95
+ expect(r.fallback).toBe("narrow");
96
+ });
97
+ it("falls back to broadcast when nobody matches", () => {
98
+ const r = routeFederatedQuery({
99
+ subject: "unknown-service",
100
+ peers: [
101
+ { host: "h1", knownSubjects: ["billing"] },
102
+ { host: "h2", knownSubjects: ["frontend"] },
103
+ ],
104
+ });
105
+ expect(r.fallback).toBe("broadcast");
106
+ });
107
+ it("kind match contributes to score", () => {
108
+ const r = routeFederatedQuery({
109
+ subject: "auth",
110
+ kind: "error_spike",
111
+ peers: [
112
+ { host: "with-kind", knownSubjects: ["auth"], knownKinds: ["error_spike"] },
113
+ { host: "without-kind", knownSubjects: ["auth"] },
114
+ ],
115
+ });
116
+ expect(r.recommendations[0].peer).toBe("with-kind");
117
+ });
118
+ });
119
+ it("formatLivingModelLine summarises", () => {
120
+ const s = buildMerkleSummary("h1", [{ id: "x", ts: "t", host: "h1", kind: "k", subject: "s" }]);
121
+ expect(formatLivingModelLine(s)).toContain("LIVING");
122
+ expect(formatLivingModelLine(s)).toContain("h1");
123
+ });
124
+ });
125
+ //# sourceMappingURL=living_model.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"living_model.test.js","sourceRoot":"","sources":["../../src/living_model/living_model.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,74 @@
1
+ /**
2
+ * v2.16.0 — MNEME OBELISK (Federated Trust Graph)
3
+ *
4
+ * "BOUNTY today is local — one repo, one ledger. OBELISK promotes
5
+ * it to a federated trust standard: any signed BOUNTY card from any
6
+ * repo (or any vendor's own self-published score) can be aggregated
7
+ * into the global AI Trust Graph."
8
+ *
9
+ * Phase 1 (v2.16) primitives:
10
+ *
11
+ * 1. obeliskCard — wrap a local BOUNTY VendorScorecard with publisher
12
+ * identity + ed25519-like signature (using HMAC for now; ed25519
13
+ * requires a webcrypto path we'll add in v2.17)
14
+ * 2. aggregateGraph — given N cards from N publishers, weight + fuse
15
+ * into a per-vendor consensus falseRate with confidence based on
16
+ * total sample count and publisher diversity
17
+ * 3. verifyCard — independent verification of a single card
18
+ *
19
+ * Privacy: publisher identity is whatever string they pick. No PII
20
+ * required. Could be a GitHub handle, a pseudonym, or org name.
21
+ *
22
+ * Trust model: each card stands on its own signature. Aggregation
23
+ * weights samples by Wilson lower bound so a single publisher with 5
24
+ * verdicts doesn't outvote 10 publishers with 1000 verdicts.
25
+ */
26
+ declare const PROTOCOL_VERSION: 1;
27
+ export interface VendorScorecard {
28
+ vendor: string;
29
+ totalVerdicts: number;
30
+ falseCount: number;
31
+ trueCount: number;
32
+ partialCount: number;
33
+ inconclusiveCount: number;
34
+ falseRate: number;
35
+ falseRateLB: number;
36
+ generatedAt: string;
37
+ }
38
+ export interface ObeliskCard {
39
+ v: typeof PROTOCOL_VERSION;
40
+ publisher: string;
41
+ publisherUrl?: string;
42
+ publishedAt: string;
43
+ vendorScore: VendorScorecard;
44
+ sig: string;
45
+ }
46
+ export declare function buildCard(input: {
47
+ publisher: string;
48
+ publisherUrl?: string;
49
+ vendorScore: VendorScorecard;
50
+ secret?: string;
51
+ }): ObeliskCard;
52
+ export declare function verifyCard(card: ObeliskCard, secret?: string): {
53
+ ok: boolean;
54
+ reason?: string;
55
+ };
56
+ export interface AggregatedRow {
57
+ vendor: string;
58
+ totalVerdicts: number;
59
+ totalFalse: number;
60
+ consensusFalseRate: number;
61
+ /** Wilson LB on aggregated counts. */
62
+ consensusFalseRateLB: number;
63
+ publisherCount: number;
64
+ publishers: string[];
65
+ /** Higher = stronger signal. Logit-based using totalVerdicts. */
66
+ confidenceScore: number;
67
+ }
68
+ export declare function aggregateGraph(cards: ObeliskCard[], secret?: string): {
69
+ rows: AggregatedRow[];
70
+ unverified: ObeliskCard[];
71
+ };
72
+ export declare function formatObeliskLine(rows: AggregatedRow[]): string;
73
+ export {};
74
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/obelisk/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAIH,QAAA,MAAM,gBAAgB,EAAG,CAAU,CAAC;AAEpC,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,aAAa,EAAE,MAAM,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;IACrB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,WAAW;IAC1B,CAAC,EAAE,OAAO,gBAAgB,CAAC;IAC3B,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,eAAe,CAAC;IAC7B,GAAG,EAAE,MAAM,CAAC;CACb;AAaD,wBAAgB,SAAS,CAAC,KAAK,EAAE;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,eAAe,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,WAAW,CAWzI;AAED,wBAAgB,UAAU,CAAC,IAAI,EAAE,WAAW,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG;IAAE,EAAE,EAAE,OAAO,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,CAO/F;AAED,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,aAAa,EAAE,MAAM,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;IACnB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,sCAAsC;IACtC,oBAAoB,EAAE,MAAM,CAAC;IAC7B,cAAc,EAAE,MAAM,CAAC;IACvB,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,iEAAiE;IACjE,eAAe,EAAE,MAAM,CAAC;CACzB;AAWD,wBAAgB,cAAc,CAAC,KAAK,EAAE,WAAW,EAAE,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG;IACrE,IAAI,EAAE,aAAa,EAAE,CAAC;IACtB,UAAU,EAAE,WAAW,EAAE,CAAC;CAC3B,CAqCA;AAED,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,aAAa,EAAE,GAAG,MAAM,CAI/D"}
@@ -0,0 +1,114 @@
1
+ /**
2
+ * v2.16.0 — MNEME OBELISK (Federated Trust Graph)
3
+ *
4
+ * "BOUNTY today is local — one repo, one ledger. OBELISK promotes
5
+ * it to a federated trust standard: any signed BOUNTY card from any
6
+ * repo (or any vendor's own self-published score) can be aggregated
7
+ * into the global AI Trust Graph."
8
+ *
9
+ * Phase 1 (v2.16) primitives:
10
+ *
11
+ * 1. obeliskCard — wrap a local BOUNTY VendorScorecard with publisher
12
+ * identity + ed25519-like signature (using HMAC for now; ed25519
13
+ * requires a webcrypto path we'll add in v2.17)
14
+ * 2. aggregateGraph — given N cards from N publishers, weight + fuse
15
+ * into a per-vendor consensus falseRate with confidence based on
16
+ * total sample count and publisher diversity
17
+ * 3. verifyCard — independent verification of a single card
18
+ *
19
+ * Privacy: publisher identity is whatever string they pick. No PII
20
+ * required. Could be a GitHub handle, a pseudonym, or org name.
21
+ *
22
+ * Trust model: each card stands on its own signature. Aggregation
23
+ * weights samples by Wilson lower bound so a single publisher with 5
24
+ * verdicts doesn't outvote 10 publishers with 1000 verdicts.
25
+ */
26
+ import { createHmac, timingSafeEqual } from "node:crypto";
27
+ const PROTOCOL_VERSION = 1;
28
+ function canon(v) {
29
+ if (v === null || typeof v !== "object")
30
+ return JSON.stringify(v);
31
+ if (Array.isArray(v))
32
+ return "[" + v.map(canon).join(",") + "]";
33
+ const keys = Object.keys(v).sort();
34
+ return "{" + keys.map((k) => JSON.stringify(k) + ":" + canon(v[k])).join(",") + "}";
35
+ }
36
+ function defaultSecret() {
37
+ return process.env["MNEME_OBELISK_SECRET"] || `mneme-obelisk-v${PROTOCOL_VERSION}`;
38
+ }
39
+ export function buildCard(input) {
40
+ const publishedAt = new Date().toISOString();
41
+ const body = {
42
+ v: PROTOCOL_VERSION,
43
+ publisher: input.publisher,
44
+ ...(input.publisherUrl ? { publisherUrl: input.publisherUrl } : {}),
45
+ publishedAt,
46
+ vendorScore: input.vendorScore,
47
+ };
48
+ const sig = createHmac("sha256", input.secret ?? defaultSecret()).update(canon(body)).digest("hex");
49
+ return { ...body, sig };
50
+ }
51
+ export function verifyCard(card, secret) {
52
+ const { sig: claimed, ...body } = card;
53
+ const expected = createHmac("sha256", secret ?? defaultSecret()).update(canon(body)).digest("hex");
54
+ try {
55
+ const ok = timingSafeEqual(Buffer.from(expected, "hex"), Buffer.from(claimed, "hex"));
56
+ return ok ? { ok: true } : { ok: false, reason: "card sig mismatch -- forged or wrong publisher key" };
57
+ }
58
+ catch {
59
+ return { ok: false, reason: "card sig length invalid" };
60
+ }
61
+ }
62
+ function wilsonLB(positive, total, z = 1.96) {
63
+ if (total === 0)
64
+ return 0;
65
+ const p = positive / total;
66
+ const denom = 1 + (z * z) / total;
67
+ const center = p + (z * z) / (2 * total);
68
+ const margin = z * Math.sqrt((p * (1 - p) + (z * z) / (4 * total)) / total);
69
+ return Math.max(0, Math.min(1, (center - margin) / denom));
70
+ }
71
+ export function aggregateGraph(cards, secret) {
72
+ const verified = [];
73
+ const unverified = [];
74
+ for (const c of cards) {
75
+ if (verifyCard(c, secret).ok)
76
+ verified.push(c);
77
+ else
78
+ unverified.push(c);
79
+ }
80
+ const byVendor = new Map();
81
+ for (const c of verified) {
82
+ const v = c.vendorScore;
83
+ const e = byVendor.get(v.vendor) ?? { totalVerdicts: 0, totalFalse: 0, publishers: new Set() };
84
+ e.totalVerdicts += v.totalVerdicts;
85
+ e.totalFalse += v.falseCount;
86
+ e.publishers.add(c.publisher);
87
+ byVendor.set(v.vendor, e);
88
+ }
89
+ const rows = Array.from(byVendor.entries()).map(([vendor, e]) => {
90
+ const consensusFalseRate = e.totalVerdicts === 0 ? 0 : e.totalFalse / e.totalVerdicts;
91
+ const consensusFalseRateLB = wilsonLB(e.totalFalse, e.totalVerdicts);
92
+ // Confidence: log(totalVerdicts) capped + bonus for >=3 distinct publishers
93
+ const sampleConf = Math.min(1, Math.log10(e.totalVerdicts + 1) / 3);
94
+ const diversityBonus = e.publishers.size >= 3 ? 0.2 : e.publishers.size >= 2 ? 0.1 : 0;
95
+ return {
96
+ vendor,
97
+ totalVerdicts: e.totalVerdicts,
98
+ totalFalse: e.totalFalse,
99
+ consensusFalseRate: Math.round(consensusFalseRate * 10000) / 10000,
100
+ consensusFalseRateLB: Math.round(consensusFalseRateLB * 10000) / 10000,
101
+ publisherCount: e.publishers.size,
102
+ publishers: Array.from(e.publishers).sort(),
103
+ confidenceScore: Math.round((sampleConf + diversityBonus) * 1000) / 1000,
104
+ };
105
+ }).sort((a, b) => b.consensusFalseRateLB - a.consensusFalseRateLB);
106
+ return { rows, unverified };
107
+ }
108
+ export function formatObeliskLine(rows) {
109
+ if (rows.length === 0)
110
+ return "OBELISK · empty graph";
111
+ const worst = rows[0];
112
+ return `OBELISK · ${rows.length} vendors · worst=${worst.vendor} (lb=${worst.consensusFalseRateLB.toFixed(3)} across ${worst.publisherCount} publishers)`;
113
+ }
114
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/obelisk/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=obelisk.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"obelisk.test.d.ts","sourceRoot":"","sources":["../../src/obelisk/obelisk.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,67 @@
1
+ import { describe, it, expect } from "vitest";
2
+ import { buildCard, verifyCard, aggregateGraph, formatObeliskLine } from "./index.js";
3
+ const score = (vendor, t, f) => ({
4
+ vendor, totalVerdicts: t + f, falseCount: f, trueCount: t,
5
+ partialCount: 0, inconclusiveCount: 0,
6
+ falseRate: f / Math.max(1, t + f),
7
+ falseRateLB: 0,
8
+ generatedAt: new Date().toISOString(),
9
+ });
10
+ describe("v2.16 · OBELISK (federated trust graph)", () => {
11
+ it("buildCard + verifyCard round-trip", () => {
12
+ const card = buildCard({ publisher: "alice@x.com", vendorScore: score("claude", 90, 10) });
13
+ expect(verifyCard(card).ok).toBe(true);
14
+ });
15
+ it("verifyCard fails on tamper", () => {
16
+ const card = buildCard({ publisher: "alice@x.com", vendorScore: score("claude", 90, 10) });
17
+ const tampered = { ...card, publisher: "evil@attacker.com" };
18
+ expect(verifyCard(tampered).ok).toBe(false);
19
+ });
20
+ it("aggregateGraph sums verdicts across publishers", () => {
21
+ const a = buildCard({ publisher: "alice", vendorScore: score("claude", 80, 20) });
22
+ const b = buildCard({ publisher: "bob", vendorScore: score("claude", 90, 10) });
23
+ const c = buildCard({ publisher: "carol", vendorScore: score("claude", 95, 5) });
24
+ const { rows } = aggregateGraph([a, b, c]);
25
+ expect(rows.length).toBe(1);
26
+ expect(rows[0].totalVerdicts).toBe(300);
27
+ expect(rows[0].totalFalse).toBe(35);
28
+ expect(rows[0].publisherCount).toBe(3);
29
+ expect(rows[0].consensusFalseRate).toBeCloseTo(35 / 300, 4);
30
+ });
31
+ it("aggregateGraph isolates unverified cards", () => {
32
+ const a = buildCard({ publisher: "alice", vendorScore: score("claude", 80, 20) });
33
+ const tampered = { ...a, publisher: "evil" };
34
+ const { rows, unverified } = aggregateGraph([a, tampered]);
35
+ expect(unverified).toHaveLength(1);
36
+ expect(rows[0].publisherCount).toBe(1);
37
+ });
38
+ it("Wilson LB <= rate for small samples", () => {
39
+ const a = buildCard({ publisher: "alice", vendorScore: score("claude", 0, 5) }); // 100% false rate, tiny sample
40
+ const { rows } = aggregateGraph([a]);
41
+ expect(rows[0].consensusFalseRate).toBe(1);
42
+ expect(rows[0].consensusFalseRateLB).toBeLessThan(1);
43
+ });
44
+ it("diversity bonus: more publishers → higher confidence", () => {
45
+ const a1 = buildCard({ publisher: "alice", vendorScore: score("claude", 50, 50) });
46
+ const a2 = buildCard({ publisher: "alice", vendorScore: score("claude", 50, 50) });
47
+ const a3 = buildCard({ publisher: "alice", vendorScore: score("claude", 50, 50) });
48
+ const b1 = buildCard({ publisher: "bob", vendorScore: score("claude", 50, 50) });
49
+ const c1 = buildCard({ publisher: "carol", vendorScore: score("claude", 50, 50) });
50
+ const single = aggregateGraph([a1, a2, a3]);
51
+ const diverse = aggregateGraph([a1, b1, c1]);
52
+ expect(diverse.rows[0].confidenceScore).toBeGreaterThanOrEqual(single.rows[0].confidenceScore);
53
+ });
54
+ it("sort orders worst (highest falseRateLB) first", () => {
55
+ const aBad = buildCard({ publisher: "p1", vendorScore: score("vendorA", 10, 90) });
56
+ const aGood = buildCard({ publisher: "p2", vendorScore: score("vendorB", 90, 10) });
57
+ const { rows } = aggregateGraph([aBad, aGood]);
58
+ expect(rows[0].vendor).toBe("vendorA");
59
+ });
60
+ it("formatObeliskLine summarises", () => {
61
+ const card = buildCard({ publisher: "alice", vendorScore: score("claude", 90, 10) });
62
+ const { rows } = aggregateGraph([card]);
63
+ expect(formatObeliskLine(rows)).toContain("OBELISK");
64
+ expect(formatObeliskLine([])).toContain("empty");
65
+ });
66
+ });
67
+ //# sourceMappingURL=obelisk.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"obelisk.test.js","sourceRoot":"","sources":["../../src/obelisk/obelisk.test.ts"],"names":[],"mappings":"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"}