@mneme-ai/core 1.81.0 → 1.83.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/agent_manifest.d.ts +1 -1
- package/dist/agent_manifest.d.ts.map +1 -1
- package/dist/agent_manifest.js +9 -1
- package/dist/agent_manifest.js.map +1 -1
- package/dist/aura/aura.test.d.ts +2 -0
- package/dist/aura/aura.test.d.ts.map +1 -0
- package/dist/aura/aura.test.js +107 -0
- package/dist/aura/aura.test.js.map +1 -0
- package/dist/aura/auto_discovery.d.ts +25 -0
- package/dist/aura/auto_discovery.d.ts.map +1 -0
- package/dist/aura/auto_discovery.js +51 -0
- package/dist/aura/auto_discovery.js.map +1 -0
- package/dist/aura/index.d.ts +13 -0
- package/dist/aura/index.d.ts.map +1 -0
- package/dist/aura/index.js +13 -0
- package/dist/aura/index.js.map +1 -0
- package/dist/aura/pair_payload.d.ts +60 -0
- package/dist/aura/pair_payload.d.ts.map +1 -0
- package/dist/aura/pair_payload.js +73 -0
- package/dist/aura/pair_payload.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +9 -0
- package/dist/index.js.map +1 -1
- package/dist/lattice/intent_atoms.d.ts.map +1 -1
- package/dist/lattice/intent_atoms.js +105 -0
- package/dist/lattice/intent_atoms.js.map +1 -1
- package/dist/lattice/lattice.test.js +26 -0
- package/dist/lattice/lattice.test.js.map +1 -1
- package/dist/lineage/spore.d.ts.map +1 -1
- package/dist/lineage/spore.js +22 -3
- package/dist/lineage/spore.js.map +1 -1
- package/dist/osmosis/harvest.d.ts +75 -0
- package/dist/osmosis/harvest.d.ts.map +1 -0
- package/dist/osmosis/harvest.js +178 -0
- package/dist/osmosis/harvest.js.map +1 -0
- package/dist/osmosis/index.d.ts +10 -0
- package/dist/osmosis/index.d.ts.map +1 -0
- package/dist/osmosis/index.js +10 -0
- package/dist/osmosis/index.js.map +1 -0
- package/dist/osmosis/osmosis.test.d.ts +2 -0
- package/dist/osmosis/osmosis.test.d.ts.map +1 -0
- package/dist/osmosis/osmosis.test.js +114 -0
- package/dist/osmosis/osmosis.test.js.map +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* v1.82.0 -- OSMOSIS: 24/7 second-brain expansion.
|
|
3
|
+
*
|
|
4
|
+
* Wild premise: Mneme's second brain should keep growing even while
|
|
5
|
+
* the user sleeps. Every AI agent the user touches (Claude / Cursor /
|
|
6
|
+
* Codex / Gemini / Cline / Aider / Copilot / web AIs) leaks usable
|
|
7
|
+
* knowledge through:
|
|
8
|
+
* - Their replies (decisions, reasoning, verdicts)
|
|
9
|
+
* - Their tool calls (what they tried, what worked)
|
|
10
|
+
* - Their refusals (boundaries the user cares about)
|
|
11
|
+
*
|
|
12
|
+
* OSMOSIS harvests those leaks WITH USER CONSENT, distills them into
|
|
13
|
+
* compact "wisdom shards", and merges into the local genome. The user
|
|
14
|
+
* never trains anything; they just keep working, and the brain grows.
|
|
15
|
+
*
|
|
16
|
+
* Storage:
|
|
17
|
+
* .mneme/osmosis/shards/<id>.json -- raw harvested observations
|
|
18
|
+
* .mneme/osmosis/wisdom.jsonl -- distilled wisdom rules (signed)
|
|
19
|
+
* .mneme/osmosis/consent.json -- per-vendor opt-in record
|
|
20
|
+
*
|
|
21
|
+
* Privacy: opt-in per vendor. Never harvests without explicit consent.
|
|
22
|
+
* No content leaves your machine. Everything stored locally.
|
|
23
|
+
*/
|
|
24
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync, appendFileSync, readdirSync } from "node:fs";
|
|
25
|
+
import { join } from "node:path";
|
|
26
|
+
import { createHash } from "node:crypto";
|
|
27
|
+
const OSMOSIS_DIR = ".mneme/osmosis";
|
|
28
|
+
const SHARDS_DIR = ".mneme/osmosis/shards";
|
|
29
|
+
const WISDOM_LOG = ".mneme/osmosis/wisdom.jsonl";
|
|
30
|
+
const CONSENT_FILE = ".mneme/osmosis/consent.json";
|
|
31
|
+
function ensureDirs(repoRoot) {
|
|
32
|
+
const dir = join(repoRoot, OSMOSIS_DIR);
|
|
33
|
+
const shardsDir = join(repoRoot, SHARDS_DIR);
|
|
34
|
+
if (!existsSync(dir))
|
|
35
|
+
mkdirSync(dir, { recursive: true });
|
|
36
|
+
if (!existsSync(shardsDir))
|
|
37
|
+
mkdirSync(shardsDir, { recursive: true });
|
|
38
|
+
return { dir, shardsDir };
|
|
39
|
+
}
|
|
40
|
+
export function readConsent(repoRoot) {
|
|
41
|
+
const path = join(repoRoot, CONSENT_FILE);
|
|
42
|
+
if (!existsSync(path)) {
|
|
43
|
+
return { vendors: {}, dailyCap: 100, updatedAt: new Date(0).toISOString() };
|
|
44
|
+
}
|
|
45
|
+
try {
|
|
46
|
+
let raw = readFileSync(path, "utf8");
|
|
47
|
+
if (raw.charCodeAt(0) === 0xfeff)
|
|
48
|
+
raw = raw.slice(1);
|
|
49
|
+
return JSON.parse(raw.trim());
|
|
50
|
+
}
|
|
51
|
+
catch {
|
|
52
|
+
return { vendors: {}, dailyCap: 100, updatedAt: new Date(0).toISOString() };
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
export function setConsent(repoRoot, vendor, enabled) {
|
|
56
|
+
ensureDirs(repoRoot);
|
|
57
|
+
const current = readConsent(repoRoot);
|
|
58
|
+
current.vendors[vendor] = enabled;
|
|
59
|
+
current.updatedAt = new Date().toISOString();
|
|
60
|
+
writeFileSync(join(repoRoot, CONSENT_FILE), JSON.stringify(current, null, 2), "utf8");
|
|
61
|
+
return current;
|
|
62
|
+
}
|
|
63
|
+
function shardId(observations) {
|
|
64
|
+
const concat = observations.map((o) => `${o.vendor}|${o.kind}|${o.text}`).join("\n");
|
|
65
|
+
return createHash("sha256").update(concat).digest("hex").slice(0, 16);
|
|
66
|
+
}
|
|
67
|
+
function lastWisdomHash(repoRoot) {
|
|
68
|
+
const path = join(repoRoot, WISDOM_LOG);
|
|
69
|
+
if (!existsSync(path))
|
|
70
|
+
return null;
|
|
71
|
+
const raw = readFileSync(path, "utf8").trim();
|
|
72
|
+
if (!raw)
|
|
73
|
+
return null;
|
|
74
|
+
const lines = raw.split("\n");
|
|
75
|
+
try {
|
|
76
|
+
const last = JSON.parse(lines[lines.length - 1]);
|
|
77
|
+
return last.hash;
|
|
78
|
+
}
|
|
79
|
+
catch {
|
|
80
|
+
return null;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
/** Record an observation iff consent is granted for the vendor. */
|
|
84
|
+
export function harvest(repoRoot, obs) {
|
|
85
|
+
const consent = readConsent(repoRoot);
|
|
86
|
+
if (consent.vendors[obs.vendor] !== true) {
|
|
87
|
+
return { recorded: false, reason: `vendor ${obs.vendor} not opted-in` };
|
|
88
|
+
}
|
|
89
|
+
ensureDirs(repoRoot);
|
|
90
|
+
const id = shardId([obs]);
|
|
91
|
+
const path = join(repoRoot, SHARDS_DIR, `${id}.json`);
|
|
92
|
+
if (existsSync(path)) {
|
|
93
|
+
return { recorded: false, reason: "duplicate observation (same hash)" };
|
|
94
|
+
}
|
|
95
|
+
writeFileSync(path, JSON.stringify(obs, null, 2), "utf8");
|
|
96
|
+
return { recorded: true };
|
|
97
|
+
}
|
|
98
|
+
/** Distill a batch of observations into a signed wisdom shard. */
|
|
99
|
+
export function distill(repoRoot, observations, rule) {
|
|
100
|
+
ensureDirs(repoRoot);
|
|
101
|
+
const id = shardId(observations);
|
|
102
|
+
const createdAt = new Date().toISOString();
|
|
103
|
+
const prev = lastWisdomHash(repoRoot);
|
|
104
|
+
const body = `${id}|${createdAt}|${observations.length}|${rule ?? ""}|${prev ?? ""}`;
|
|
105
|
+
const hash = createHash("sha256").update(body).digest("hex");
|
|
106
|
+
const confidence = Math.min(1, observations.length / 5);
|
|
107
|
+
const shard = {
|
|
108
|
+
id,
|
|
109
|
+
observations: [...observations],
|
|
110
|
+
createdAt,
|
|
111
|
+
rule,
|
|
112
|
+
confidence,
|
|
113
|
+
prevHash: prev,
|
|
114
|
+
hash,
|
|
115
|
+
};
|
|
116
|
+
appendFileSync(join(repoRoot, WISDOM_LOG), JSON.stringify(shard) + "\n", "utf8");
|
|
117
|
+
return shard;
|
|
118
|
+
}
|
|
119
|
+
/** Read all wisdom shards. Returns newest-first. */
|
|
120
|
+
export function listWisdom(repoRoot) {
|
|
121
|
+
const path = join(repoRoot, WISDOM_LOG);
|
|
122
|
+
if (!existsSync(path))
|
|
123
|
+
return [];
|
|
124
|
+
const lines = readFileSync(path, "utf8").split("\n").filter(Boolean);
|
|
125
|
+
const out = [];
|
|
126
|
+
for (const l of lines) {
|
|
127
|
+
try {
|
|
128
|
+
out.push(JSON.parse(l));
|
|
129
|
+
}
|
|
130
|
+
catch {
|
|
131
|
+
// skip
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
return out.reverse();
|
|
135
|
+
}
|
|
136
|
+
/** Verify the wisdom hash-chain. Returns the first index where the
|
|
137
|
+
* prevHash pointer breaks, or null if the entire chain is valid. */
|
|
138
|
+
export function verifyChain(repoRoot) {
|
|
139
|
+
const path = join(repoRoot, WISDOM_LOG);
|
|
140
|
+
if (!existsSync(path))
|
|
141
|
+
return { valid: true, brokenAtIndex: null };
|
|
142
|
+
const lines = readFileSync(path, "utf8").split("\n").filter(Boolean);
|
|
143
|
+
let prev = null;
|
|
144
|
+
for (let i = 0; i < lines.length; i++) {
|
|
145
|
+
try {
|
|
146
|
+
const shard = JSON.parse(lines[i]);
|
|
147
|
+
if (shard.prevHash !== prev)
|
|
148
|
+
return { valid: false, brokenAtIndex: i };
|
|
149
|
+
prev = shard.hash;
|
|
150
|
+
}
|
|
151
|
+
catch {
|
|
152
|
+
return { valid: false, brokenAtIndex: i };
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
return { valid: true, brokenAtIndex: null };
|
|
156
|
+
}
|
|
157
|
+
/** Count shards collected today (UTC). Used by the daily-cap guard. */
|
|
158
|
+
export function todayShardCount(repoRoot) {
|
|
159
|
+
const dir = join(repoRoot, SHARDS_DIR);
|
|
160
|
+
if (!existsSync(dir))
|
|
161
|
+
return 0;
|
|
162
|
+
const today = new Date().toISOString().slice(0, 10);
|
|
163
|
+
let n = 0;
|
|
164
|
+
for (const f of readdirSync(dir)) {
|
|
165
|
+
if (!f.endsWith(".json"))
|
|
166
|
+
continue;
|
|
167
|
+
try {
|
|
168
|
+
const obs = JSON.parse(readFileSync(join(dir, f), "utf8"));
|
|
169
|
+
if (obs.observedAt.slice(0, 10) === today)
|
|
170
|
+
n++;
|
|
171
|
+
}
|
|
172
|
+
catch {
|
|
173
|
+
// skip
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
return n;
|
|
177
|
+
}
|
|
178
|
+
//# sourceMappingURL=harvest.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"harvest.js","sourceRoot":"","sources":["../../src/osmosis/harvest.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* v1.82.0 -- OSMOSIS: 24/7 second-brain expansion.
|
|
3
|
+
*
|
|
4
|
+
* Mneme's second brain grows continuously by harvesting (with consent)
|
|
5
|
+
* observations from every AI agent the user works with. No training,
|
|
6
|
+
* no API calls, no cloud uploads — just local distillation into a
|
|
7
|
+
* hash-chained wisdom ledger.
|
|
8
|
+
*/
|
|
9
|
+
export * from "./harvest.js";
|
|
10
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/osmosis/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,cAAc,cAAc,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* v1.82.0 -- OSMOSIS: 24/7 second-brain expansion.
|
|
3
|
+
*
|
|
4
|
+
* Mneme's second brain grows continuously by harvesting (with consent)
|
|
5
|
+
* observations from every AI agent the user works with. No training,
|
|
6
|
+
* no API calls, no cloud uploads — just local distillation into a
|
|
7
|
+
* hash-chained wisdom ledger.
|
|
8
|
+
*/
|
|
9
|
+
export * from "./harvest.js";
|
|
10
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/osmosis/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,cAAc,cAAc,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"osmosis.test.d.ts","sourceRoot":"","sources":["../../src/osmosis/osmosis.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import { describe, it, expect, beforeEach } from "vitest";
|
|
2
|
+
import { mkdtempSync, readFileSync } from "node:fs";
|
|
3
|
+
import { tmpdir } from "node:os";
|
|
4
|
+
import { join } from "node:path";
|
|
5
|
+
import { readConsent, setConsent, harvest, distill, listWisdom, verifyChain, todayShardCount, } from "./harvest.js";
|
|
6
|
+
function tmpRepo() {
|
|
7
|
+
return mkdtempSync(join(tmpdir(), "mneme-osmosis-"));
|
|
8
|
+
}
|
|
9
|
+
const claudeObs = {
|
|
10
|
+
vendor: "claude-opus-4-7",
|
|
11
|
+
kind: "decision",
|
|
12
|
+
text: "prefer Gist over clipboard for cross-machine",
|
|
13
|
+
observedAt: "2026-05-13T10:00:00.000Z",
|
|
14
|
+
};
|
|
15
|
+
describe("v1.82 OSMOSIS · consent", () => {
|
|
16
|
+
it("defaults to no opt-in, dailyCap 100", () => {
|
|
17
|
+
const repo = tmpRepo();
|
|
18
|
+
const c = readConsent(repo);
|
|
19
|
+
expect(c.vendors).toEqual({});
|
|
20
|
+
expect(c.dailyCap).toBe(100);
|
|
21
|
+
});
|
|
22
|
+
it("setConsent persists opt-in state", () => {
|
|
23
|
+
const repo = tmpRepo();
|
|
24
|
+
setConsent(repo, "claude-opus-4-7", true);
|
|
25
|
+
const c = readConsent(repo);
|
|
26
|
+
expect(c.vendors["claude-opus-4-7"]).toBe(true);
|
|
27
|
+
});
|
|
28
|
+
it("setConsent can revoke", () => {
|
|
29
|
+
const repo = tmpRepo();
|
|
30
|
+
setConsent(repo, "claude", true);
|
|
31
|
+
setConsent(repo, "claude", false);
|
|
32
|
+
expect(readConsent(repo).vendors["claude"]).toBe(false);
|
|
33
|
+
});
|
|
34
|
+
});
|
|
35
|
+
describe("v1.82 OSMOSIS · harvest gate", () => {
|
|
36
|
+
let repo;
|
|
37
|
+
beforeEach(() => {
|
|
38
|
+
repo = tmpRepo();
|
|
39
|
+
});
|
|
40
|
+
it("refuses to harvest without consent", () => {
|
|
41
|
+
const r = harvest(repo, claudeObs);
|
|
42
|
+
expect(r.recorded).toBe(false);
|
|
43
|
+
expect(r.reason).toContain("not opted-in");
|
|
44
|
+
});
|
|
45
|
+
it("harvests after opt-in", () => {
|
|
46
|
+
setConsent(repo, "claude-opus-4-7", true);
|
|
47
|
+
const r = harvest(repo, claudeObs);
|
|
48
|
+
expect(r.recorded).toBe(true);
|
|
49
|
+
});
|
|
50
|
+
it("rejects duplicate observation", () => {
|
|
51
|
+
setConsent(repo, "claude-opus-4-7", true);
|
|
52
|
+
expect(harvest(repo, claudeObs).recorded).toBe(true);
|
|
53
|
+
expect(harvest(repo, claudeObs).recorded).toBe(false);
|
|
54
|
+
});
|
|
55
|
+
});
|
|
56
|
+
describe("v1.82 OSMOSIS · distill + hash chain", () => {
|
|
57
|
+
let repo;
|
|
58
|
+
beforeEach(() => {
|
|
59
|
+
repo = tmpRepo();
|
|
60
|
+
});
|
|
61
|
+
it("distill writes a signed shard with id + hash", () => {
|
|
62
|
+
const s = distill(repo, [claudeObs], "prefer Gist over clipboard");
|
|
63
|
+
expect(s.id).toMatch(/^[a-f0-9]{16}$/);
|
|
64
|
+
expect(s.hash).toMatch(/^[a-f0-9]{64}$/);
|
|
65
|
+
expect(s.confidence).toBeGreaterThan(0);
|
|
66
|
+
expect(s.rule).toBe("prefer Gist over clipboard");
|
|
67
|
+
});
|
|
68
|
+
it("two consecutive shards form a hash chain", () => {
|
|
69
|
+
const a = distill(repo, [claudeObs]);
|
|
70
|
+
const b = distill(repo, [{ ...claudeObs, text: "second observation" }]);
|
|
71
|
+
expect(b.prevHash).toBe(a.hash);
|
|
72
|
+
});
|
|
73
|
+
it("listWisdom returns newest-first", () => {
|
|
74
|
+
distill(repo, [claudeObs]);
|
|
75
|
+
distill(repo, [{ ...claudeObs, text: "newer" }]);
|
|
76
|
+
const list = listWisdom(repo);
|
|
77
|
+
expect(list.length).toBe(2);
|
|
78
|
+
expect(list[0].observations[0].text).toBe("newer");
|
|
79
|
+
});
|
|
80
|
+
it("verifyChain returns valid on a clean log", () => {
|
|
81
|
+
distill(repo, [claudeObs]);
|
|
82
|
+
distill(repo, [{ ...claudeObs, text: "two" }]);
|
|
83
|
+
distill(repo, [{ ...claudeObs, text: "three" }]);
|
|
84
|
+
const r = verifyChain(repo);
|
|
85
|
+
expect(r.valid).toBe(true);
|
|
86
|
+
expect(r.brokenAtIndex).toBeNull();
|
|
87
|
+
});
|
|
88
|
+
it("verifyChain catches a tampered prevHash", () => {
|
|
89
|
+
distill(repo, [claudeObs]);
|
|
90
|
+
distill(repo, [{ ...claudeObs, text: "two" }]);
|
|
91
|
+
// Tamper with line 2 by rewriting log directly.
|
|
92
|
+
const path = join(repo, ".mneme/osmosis/wisdom.jsonl");
|
|
93
|
+
const raw = readFileSync(path, "utf8");
|
|
94
|
+
const lines = raw.split("\n").filter(Boolean);
|
|
95
|
+
const tampered = JSON.parse(lines[1]);
|
|
96
|
+
tampered.prevHash = "deadbeef";
|
|
97
|
+
lines[1] = JSON.stringify(tampered);
|
|
98
|
+
require("node:fs").writeFileSync(path, lines.join("\n") + "\n");
|
|
99
|
+
const r = verifyChain(repo);
|
|
100
|
+
expect(r.valid).toBe(false);
|
|
101
|
+
expect(r.brokenAtIndex).toBe(1);
|
|
102
|
+
});
|
|
103
|
+
});
|
|
104
|
+
describe("v1.82 OSMOSIS · todayShardCount", () => {
|
|
105
|
+
it("counts only observations from today (UTC)", () => {
|
|
106
|
+
const repo = tmpRepo();
|
|
107
|
+
setConsent(repo, "claude", true);
|
|
108
|
+
const today = new Date().toISOString();
|
|
109
|
+
harvest(repo, { ...claudeObs, vendor: "claude", observedAt: today });
|
|
110
|
+
harvest(repo, { vendor: "claude", kind: "reply", text: "x", observedAt: "2020-01-01T00:00:00Z" });
|
|
111
|
+
expect(todayShardCount(repo)).toBe(1);
|
|
112
|
+
});
|
|
113
|
+
});
|
|
114
|
+
//# sourceMappingURL=osmosis.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"osmosis.test.js","sourceRoot":"","sources":["../../src/osmosis/osmosis.test.ts"],"names":[],"mappings":"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"}
|