crbro-memory 1.6.1 → 1.8.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/README.md +260 -174
- package/dist/engine/brain.d.ts +2 -0
- package/dist/engine/brain.d.ts.map +1 -1
- package/dist/engine/brain.js +4 -0
- package/dist/engine/brain.js.map +1 -1
- package/dist/engine/cortex.d.ts +37 -0
- package/dist/engine/cortex.d.ts.map +1 -1
- package/dist/engine/cortex.js +61 -2
- package/dist/engine/cortex.js.map +1 -1
- package/dist/engine/keychain.d.ts +32 -0
- package/dist/engine/keychain.d.ts.map +1 -0
- package/dist/engine/keychain.js +329 -0
- package/dist/engine/keychain.js.map +1 -0
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +271 -6
- package/dist/server.js.map +1 -1
- package/dist/sync/git.d.ts +36 -0
- package/dist/sync/git.d.ts.map +1 -0
- package/dist/sync/git.js +178 -0
- package/dist/sync/git.js.map +1 -0
- package/dist/sync/materialize.d.ts +26 -0
- package/dist/sync/materialize.d.ts.map +1 -0
- package/dist/sync/materialize.js +192 -0
- package/dist/sync/materialize.js.map +1 -0
- package/dist/sync/ops.d.ts +76 -0
- package/dist/sync/ops.d.ts.map +1 -0
- package/dist/sync/ops.js +75 -0
- package/dist/sync/ops.js.map +1 -0
- package/dist/sync/space.d.ts +89 -0
- package/dist/sync/space.d.ts.map +1 -0
- package/dist/sync/space.js +363 -0
- package/dist/sync/space.js.map +1 -0
- package/dist/types/index.d.ts +4 -0
- package/dist/types/index.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/sync/git.js
ADDED
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// ─── CRBRO Shared Memory: the git transport ──────────────────────
|
|
3
|
+
//
|
|
4
|
+
// Git is the whole backend. No service to run, no account to create, no bill:
|
|
5
|
+
// a private repository is already storage, history, access control and a merge
|
|
6
|
+
// engine, and the user picks where it lives.
|
|
7
|
+
//
|
|
8
|
+
// Two things about running git from inside an MCP server matter more than the
|
|
9
|
+
// commands themselves. It must never wait for a human — there is no terminal
|
|
10
|
+
// on the other end of stdio, so a credential prompt would hang the assistant
|
|
11
|
+
// forever. And it must never rewrite what it stores: git on Windows converts
|
|
12
|
+
// line endings by default, which turns one appended line into two different
|
|
13
|
+
// lines on two machines, and the logs here are append-only.
|
|
14
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
15
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
16
|
+
};
|
|
17
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18
|
+
exports.GITIGNORE = exports.GITATTRIBUTES = void 0;
|
|
19
|
+
exports.git = git;
|
|
20
|
+
exports.gitAvailable = gitAvailable;
|
|
21
|
+
exports.hardenRepo = hardenRepo;
|
|
22
|
+
exports.initSpace = initSpace;
|
|
23
|
+
exports.cloneSpace = cloneSpace;
|
|
24
|
+
exports.syncSpace = syncSpace;
|
|
25
|
+
const node_child_process_1 = require("node:child_process");
|
|
26
|
+
const node_fs_1 = require("node:fs");
|
|
27
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
28
|
+
/**
|
|
29
|
+
* Everything that could make git stop and ask a person something, turned off.
|
|
30
|
+
* Without this the server hangs on the first private repository it meets.
|
|
31
|
+
*/
|
|
32
|
+
const SILENT_ENV = {
|
|
33
|
+
GIT_TERMINAL_PROMPT: '0',
|
|
34
|
+
GIT_ASKPASS: '',
|
|
35
|
+
SSH_ASKPASS: '',
|
|
36
|
+
GIT_SSH_COMMAND: 'ssh -o BatchMode=yes -o StrictHostKeyChecking=accept-new',
|
|
37
|
+
GCM_INTERACTIVE: 'never',
|
|
38
|
+
};
|
|
39
|
+
function classify(stderr) {
|
|
40
|
+
const s = stderr.toLowerCase();
|
|
41
|
+
if (s.includes('could not resolve host') || s.includes('unable to access') ||
|
|
42
|
+
s.includes('network is unreachable') || s.includes('operation timed out'))
|
|
43
|
+
return 'offline';
|
|
44
|
+
if (s.includes('authentication failed') || s.includes('permission denied') ||
|
|
45
|
+
s.includes('could not read username') || s.includes('terminal prompts disabled'))
|
|
46
|
+
return 'auth';
|
|
47
|
+
if (s.includes('conflict'))
|
|
48
|
+
return 'conflict';
|
|
49
|
+
return undefined;
|
|
50
|
+
}
|
|
51
|
+
function git(args, cwd, timeoutMs = 20_000) {
|
|
52
|
+
const r = (0, node_child_process_1.spawnSync)('git', args, {
|
|
53
|
+
cwd,
|
|
54
|
+
encoding: 'utf-8',
|
|
55
|
+
timeout: timeoutMs,
|
|
56
|
+
windowsHide: true,
|
|
57
|
+
env: { ...process.env, ...SILENT_ENV },
|
|
58
|
+
});
|
|
59
|
+
if (r.error) {
|
|
60
|
+
const code = r.error.code;
|
|
61
|
+
return {
|
|
62
|
+
ok: false,
|
|
63
|
+
stdout: '',
|
|
64
|
+
stderr: String(r.error.message || ''),
|
|
65
|
+
reason: code === 'ENOENT' ? 'no_git' : 'timeout',
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
if (r.signal) {
|
|
69
|
+
return { ok: false, stdout: r.stdout || '', stderr: r.stderr || '', reason: 'timeout' };
|
|
70
|
+
}
|
|
71
|
+
const stderr = r.stderr || '';
|
|
72
|
+
return {
|
|
73
|
+
ok: r.status === 0,
|
|
74
|
+
stdout: r.stdout || '',
|
|
75
|
+
stderr,
|
|
76
|
+
reason: r.status === 0 ? undefined : classify(stderr),
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
/** Is git installed at all? */
|
|
80
|
+
function gitAvailable() {
|
|
81
|
+
return git(['--version'], process.cwd(), 5_000).ok;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Settings that have to be on the repository itself, not on the machine.
|
|
85
|
+
*
|
|
86
|
+
* `core.autocrlf` ships enabled on Windows — verified true at system level on
|
|
87
|
+
* the machine this was built on — and it rewrites files on checkout. With
|
|
88
|
+
* append-only logs merged by union, the same line with two different endings
|
|
89
|
+
* becomes two lines, and the memory quietly duplicates itself. `* -text` in
|
|
90
|
+
* .gitattributes plus this setting stops it at both ends.
|
|
91
|
+
*/
|
|
92
|
+
function hardenRepo(dir) {
|
|
93
|
+
git(['config', 'core.autocrlf', 'false'], dir);
|
|
94
|
+
git(['config', 'core.safecrlf', 'false'], dir);
|
|
95
|
+
git(['config', 'merge.ours.driver', 'true'], dir);
|
|
96
|
+
// Identity, so committing works on a machine with no global git config.
|
|
97
|
+
if (!git(['config', 'user.email'], dir).stdout.trim()) {
|
|
98
|
+
git(['config', 'user.email', 'crbro@localhost'], dir);
|
|
99
|
+
}
|
|
100
|
+
if (!git(['config', 'user.name'], dir).stdout.trim()) {
|
|
101
|
+
git(['config', 'user.name', 'CRBRO'], dir);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
exports.GITATTRIBUTES = '# CRBRO shared memory. Do not edit.\n' +
|
|
105
|
+
'# -text keeps git from rewriting line endings: these logs are append-only\n' +
|
|
106
|
+
'# and a rewritten ending turns one line into two on the next merge.\n' +
|
|
107
|
+
'* -text\n' +
|
|
108
|
+
'*.jsonl merge=union\n';
|
|
109
|
+
exports.GITIGNORE = '# Local bookkeeping. Never shared.\n' +
|
|
110
|
+
'.local/\n';
|
|
111
|
+
/** Prepare a brand-new space so the first person to clone finds real history. */
|
|
112
|
+
async function initSpace(dir, remote, branch = 'main') {
|
|
113
|
+
await node_fs_1.promises.mkdir(dir, { recursive: true });
|
|
114
|
+
const init = git(['init', '-b', branch], dir);
|
|
115
|
+
if (!init.ok && !init.stdout.includes('Reinitialized')) {
|
|
116
|
+
const legacy = git(['init'], dir);
|
|
117
|
+
if (!legacy.ok)
|
|
118
|
+
return legacy;
|
|
119
|
+
git(['checkout', '-b', branch], dir);
|
|
120
|
+
}
|
|
121
|
+
hardenRepo(dir);
|
|
122
|
+
await node_fs_1.promises.writeFile(node_path_1.default.join(dir, '.gitattributes'), exports.GITATTRIBUTES, 'utf-8');
|
|
123
|
+
await node_fs_1.promises.writeFile(node_path_1.default.join(dir, '.gitignore'), exports.GITIGNORE, 'utf-8');
|
|
124
|
+
git(['remote', 'remove', 'origin'], dir);
|
|
125
|
+
const add = git(['remote', 'add', 'origin', remote], dir);
|
|
126
|
+
if (!add.ok)
|
|
127
|
+
return add;
|
|
128
|
+
git(['add', '-A', '.'], dir);
|
|
129
|
+
git(['commit', '-q', '-m', 'CRBRO shared space'], dir);
|
|
130
|
+
// Push the first commit before anyone clones. Skipping this is how two
|
|
131
|
+
// people end up with unrelated histories and a merge that refuses to run —
|
|
132
|
+
// each of them keeping their own half of the memory without noticing.
|
|
133
|
+
return git(['push', '-u', 'origin', `HEAD:${branch}`], dir, 30_000);
|
|
134
|
+
}
|
|
135
|
+
/** Clone an existing space. */
|
|
136
|
+
function cloneSpace(dir, remote, branch = 'main') {
|
|
137
|
+
const parent = node_path_1.default.dirname(dir);
|
|
138
|
+
const name = node_path_1.default.basename(dir);
|
|
139
|
+
const r = git(['clone', '--branch', branch, remote, name], parent, 60_000);
|
|
140
|
+
if (r.ok)
|
|
141
|
+
hardenRepo(dir);
|
|
142
|
+
return r;
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Bring in everyone else's notes and send ours.
|
|
146
|
+
* Offline is a normal outcome, not an error: the work stays local and goes out
|
|
147
|
+
* next time. Nothing here can lose a note, because nobody edits anyone's file.
|
|
148
|
+
*/
|
|
149
|
+
function syncSpace(dir, author, branch = 'main', timeoutMs = 30_000) {
|
|
150
|
+
git(['add', '-A', '.'], dir);
|
|
151
|
+
const hayCambios = !git(['diff', '--cached', '--quiet'], dir).ok;
|
|
152
|
+
if (hayCambios) {
|
|
153
|
+
git(['commit', '-q', '-m', `crbro ${author} ${new Date().toISOString()}`], dir);
|
|
154
|
+
}
|
|
155
|
+
const fetched = git(['fetch', 'origin', branch], dir, timeoutMs);
|
|
156
|
+
if (!fetched.ok)
|
|
157
|
+
return { pulled: fetched, pushed: null };
|
|
158
|
+
const merged = git(['merge', '--no-edit', '--allow-unrelated-histories', `origin/${branch}`], dir, timeoutMs);
|
|
159
|
+
if (!merged.ok) {
|
|
160
|
+
// Union merging makes this rare, but a hand-edited file could still clash.
|
|
161
|
+
// Keeping both sides and stopping beats guessing.
|
|
162
|
+
git(['merge', '--abort'], dir);
|
|
163
|
+
return { pulled: { ...merged, reason: 'conflict' }, pushed: null };
|
|
164
|
+
}
|
|
165
|
+
// Push, and if someone landed first, take their work and try once more.
|
|
166
|
+
let pushed = git(['push', 'origin', `HEAD:${branch}`], dir, timeoutMs);
|
|
167
|
+
for (let intento = 0; intento < 2 && !pushed.ok && pushed.reason !== 'auth'; intento++) {
|
|
168
|
+
if (!git(['fetch', 'origin', branch], dir, timeoutMs).ok)
|
|
169
|
+
break;
|
|
170
|
+
if (!git(['merge', '--no-edit', `origin/${branch}`], dir, timeoutMs).ok) {
|
|
171
|
+
git(['merge', '--abort'], dir);
|
|
172
|
+
break;
|
|
173
|
+
}
|
|
174
|
+
pushed = git(['push', 'origin', `HEAD:${branch}`], dir, timeoutMs);
|
|
175
|
+
}
|
|
176
|
+
return { pulled: merged, pushed };
|
|
177
|
+
}
|
|
178
|
+
//# sourceMappingURL=git.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"git.js","sourceRoot":"","sources":["../../src/sync/git.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { Neuron } from '../types/index.js';
|
|
2
|
+
import type { Op } from './ops.js';
|
|
3
|
+
/** Fields that disagreed and were left alone, so a human can look. */
|
|
4
|
+
export interface Divergence {
|
|
5
|
+
field: string;
|
|
6
|
+
mine: string;
|
|
7
|
+
theirs: string;
|
|
8
|
+
from: string;
|
|
9
|
+
}
|
|
10
|
+
export interface MergeReport {
|
|
11
|
+
facts_added: number;
|
|
12
|
+
facts_retracted: number;
|
|
13
|
+
facts_superseded: number;
|
|
14
|
+
decisions_added: number;
|
|
15
|
+
patterns_added: number;
|
|
16
|
+
tags_added: number;
|
|
17
|
+
authors: string[];
|
|
18
|
+
divergence: Divergence[];
|
|
19
|
+
}
|
|
20
|
+
export declare function applyOps(base: Neuron | null, ops: Op[], fallback?: {
|
|
21
|
+
id: string;
|
|
22
|
+
}): {
|
|
23
|
+
neuron: Neuron;
|
|
24
|
+
report: MergeReport;
|
|
25
|
+
};
|
|
26
|
+
//# sourceMappingURL=materialize.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"materialize.d.ts","sourceRoot":"","sources":["../../src/sync/materialize.ts"],"names":[],"mappings":"AAeA,OAAO,KAAK,EAAE,MAAM,EAA8B,MAAM,mBAAmB,CAAC;AAC5E,OAAO,KAAK,EAAE,EAAE,EAAgC,MAAM,UAAU,CAAC;AAGjE,sEAAsE;AACtE,MAAM,WAAW,UAAU;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,WAAW;IAC1B,WAAW,EAAE,MAAM,CAAC;IACpB,eAAe,EAAE,MAAM,CAAC;IACxB,gBAAgB,EAAE,MAAM,CAAC;IACzB,eAAe,EAAE,MAAM,CAAC;IACxB,cAAc,EAAE,MAAM,CAAC;IACvB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,UAAU,EAAE,UAAU,EAAE,CAAC;CAC1B;AAqBD,wBAAgB,QAAQ,CACtB,IAAI,EAAE,MAAM,GAAG,IAAI,EACnB,GAAG,EAAE,EAAE,EAAE,EACT,QAAQ,CAAC,EAAE;IAAE,EAAE,EAAE,MAAM,CAAA;CAAE,GACxB;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,WAAW,CAAA;CAAE,CA6JzC"}
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// ─── CRBRO Shared Memory: rebuilding a neuron from the logs ──────
|
|
3
|
+
//
|
|
4
|
+
// Everything hard about sharing memory lives in this file, and it is one pure
|
|
5
|
+
// function. Given whatever the neuron looks like locally plus every note
|
|
6
|
+
// anyone has written, produce the neuron. No disk, no network, no git.
|
|
7
|
+
//
|
|
8
|
+
// Three properties make the merge automatic, and every rule below is chosen to
|
|
9
|
+
// preserve them:
|
|
10
|
+
// - order does not matter,
|
|
11
|
+
// - applying the same note twice changes nothing,
|
|
12
|
+
// - applying half the notes now and the rest later ends up the same.
|
|
13
|
+
// Anything that needed a clock, a "latest wins", or a tie-break on wall time
|
|
14
|
+
// would break them, which is why none of that is here.
|
|
15
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
16
|
+
exports.applyOps = applyOps;
|
|
17
|
+
const fs_js_1 = require("../utils/fs.js");
|
|
18
|
+
const ops_js_1 = require("./ops.js");
|
|
19
|
+
/**
|
|
20
|
+
* How far along a fact's life it is. Merging takes the maximum, so a fact
|
|
21
|
+
* someone retracted can never come back to life because a stale log still
|
|
22
|
+
* calls it active. Truth about what is no longer true only moves one way.
|
|
23
|
+
*/
|
|
24
|
+
const RANK = { active: 0, superseded: 1, retracted: 2 };
|
|
25
|
+
const BY_RANK = ['active', 'superseded', 'retracted'];
|
|
26
|
+
function rankOf(s) {
|
|
27
|
+
return RANK[s || 'active'] ?? 0;
|
|
28
|
+
}
|
|
29
|
+
/** The earlier of two ISO dates. Empty strings lose. */
|
|
30
|
+
function earliest(a, b) {
|
|
31
|
+
if (!a)
|
|
32
|
+
return b;
|
|
33
|
+
if (!b)
|
|
34
|
+
return a;
|
|
35
|
+
return a < b ? a : b;
|
|
36
|
+
}
|
|
37
|
+
function applyOps(base, ops, fallback) {
|
|
38
|
+
const report = {
|
|
39
|
+
facts_added: 0,
|
|
40
|
+
facts_retracted: 0,
|
|
41
|
+
facts_superseded: 0,
|
|
42
|
+
decisions_added: 0,
|
|
43
|
+
patterns_added: 0,
|
|
44
|
+
tags_added: 0,
|
|
45
|
+
authors: [],
|
|
46
|
+
divergence: [],
|
|
47
|
+
};
|
|
48
|
+
const neuronOp = ops.find(o => o.op === 'neuron');
|
|
49
|
+
const id = base?.id || neuronOp?.nid || fallback?.id || '';
|
|
50
|
+
// Start from what we already have. If we have nothing, the announcement
|
|
51
|
+
// gives us a name; if we do have it, ours stands and any disagreement is
|
|
52
|
+
// reported rather than resolved. Overwriting someone's local name because a
|
|
53
|
+
// teammate spelled it differently is not a merge, it is a stomp.
|
|
54
|
+
const neuron = base
|
|
55
|
+
? { ...base, facts: [...base.facts], decisions: [...base.decisions], patterns: [...base.patterns], preferences: [...base.preferences], tags: [...base.tags], connections: [...base.connections] }
|
|
56
|
+
: {
|
|
57
|
+
id,
|
|
58
|
+
name: neuronOp && neuronOp.op === 'neuron' ? neuronOp.name : id,
|
|
59
|
+
domain: neuronOp && neuronOp.op === 'neuron' ? neuronOp.domain : 'general',
|
|
60
|
+
type: (neuronOp && neuronOp.op === 'neuron' ? neuronOp.ntype : 'project'),
|
|
61
|
+
created: (0, fs_js_1.now)(),
|
|
62
|
+
last_accessed: (0, fs_js_1.now)(),
|
|
63
|
+
access_count: 0,
|
|
64
|
+
heat: 0.5,
|
|
65
|
+
summary: '',
|
|
66
|
+
facts: [],
|
|
67
|
+
decisions: [],
|
|
68
|
+
patterns: [],
|
|
69
|
+
preferences: [],
|
|
70
|
+
connections: [],
|
|
71
|
+
tags: [],
|
|
72
|
+
};
|
|
73
|
+
if (base && neuronOp && neuronOp.op === 'neuron') {
|
|
74
|
+
if (neuronOp.name && base.name && (0, ops_js_1.normalizeText)(neuronOp.name) !== (0, ops_js_1.normalizeText)(base.name)) {
|
|
75
|
+
report.divergence.push({ field: 'name', mine: base.name, theirs: neuronOp.name, from: neuronOp.by });
|
|
76
|
+
}
|
|
77
|
+
if (neuronOp.domain && base.domain && neuronOp.domain !== base.domain && base.domain !== 'general') {
|
|
78
|
+
report.divergence.push({ field: 'domain', mine: base.domain, theirs: neuronOp.domain, from: neuronOp.by });
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
// ─── Facts: union by id, then the furthest-along status ───────
|
|
82
|
+
const byFid = new Map();
|
|
83
|
+
for (const f of neuron.facts) {
|
|
84
|
+
byFid.set(f.id || '', f);
|
|
85
|
+
}
|
|
86
|
+
// Facts stored before ids existed: index them by their text so an incoming
|
|
87
|
+
// note about the same sentence lands on the same fact instead of duplicating.
|
|
88
|
+
const byText = new Map();
|
|
89
|
+
for (const f of neuron.facts) {
|
|
90
|
+
byText.set((0, ops_js_1.normalizeText)(f.text), f);
|
|
91
|
+
}
|
|
92
|
+
const statusOps = [];
|
|
93
|
+
for (const op of ops) {
|
|
94
|
+
if (op.op === 'fact') {
|
|
95
|
+
const fo = op;
|
|
96
|
+
const existing = byFid.get(fo.fid) || byText.get((0, ops_js_1.normalizeText)(fo.text));
|
|
97
|
+
if (existing) {
|
|
98
|
+
// Same fact from two people. Keep the earliest date so provenance
|
|
99
|
+
// reflects who knew it first, and the higher confidence.
|
|
100
|
+
existing.id = existing.id || fo.fid;
|
|
101
|
+
existing.added = earliest(existing.added, fo.at);
|
|
102
|
+
existing.confidence = Math.max(existing.confidence ?? 1, fo.conf ?? 1);
|
|
103
|
+
continue;
|
|
104
|
+
}
|
|
105
|
+
const fact = {
|
|
106
|
+
text: fo.text,
|
|
107
|
+
confidence: fo.conf ?? 1,
|
|
108
|
+
added: fo.at,
|
|
109
|
+
source: `team:${fo.by}`,
|
|
110
|
+
id: fo.fid,
|
|
111
|
+
status: 'active',
|
|
112
|
+
};
|
|
113
|
+
neuron.facts.push(fact);
|
|
114
|
+
byFid.set(fo.fid, fact);
|
|
115
|
+
byText.set((0, ops_js_1.normalizeText)(fo.text), fact);
|
|
116
|
+
report.facts_added++;
|
|
117
|
+
}
|
|
118
|
+
else if (op.op === 'status') {
|
|
119
|
+
statusOps.push(op);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
// Status is applied after every fact exists, so a note retracting a fact
|
|
123
|
+
// works no matter which log it arrived in or in what order.
|
|
124
|
+
for (const so of statusOps) {
|
|
125
|
+
const target = byFid.get(so.fid);
|
|
126
|
+
if (!target)
|
|
127
|
+
continue;
|
|
128
|
+
const antes = rankOf(target.status);
|
|
129
|
+
const despues = Math.max(antes, rankOf(so.to));
|
|
130
|
+
if (despues === antes)
|
|
131
|
+
continue;
|
|
132
|
+
target.status = BY_RANK[despues];
|
|
133
|
+
target.revised = so.at;
|
|
134
|
+
if (so.why)
|
|
135
|
+
target.revision_note = so.why;
|
|
136
|
+
if (target.status === 'retracted')
|
|
137
|
+
report.facts_retracted++;
|
|
138
|
+
else
|
|
139
|
+
report.facts_superseded++;
|
|
140
|
+
}
|
|
141
|
+
// ─── Decisions: union by (id, author) ────────────────────────
|
|
142
|
+
// Two people can reach the same decision for different reasons, and both
|
|
143
|
+
// reasons are worth keeping. Keying on the pair means neither is lost.
|
|
144
|
+
const seenDecision = new Set();
|
|
145
|
+
for (const d of neuron.decisions) {
|
|
146
|
+
seenDecision.add(`${d.id || (0, ops_js_1.normalizeText)(d.text)}|${d.by || ''}`);
|
|
147
|
+
}
|
|
148
|
+
for (const op of ops) {
|
|
149
|
+
if (op.op !== 'decision')
|
|
150
|
+
continue;
|
|
151
|
+
const dop = op;
|
|
152
|
+
const key = `${dop.did}|${dop.by}`;
|
|
153
|
+
if (seenDecision.has(key))
|
|
154
|
+
continue;
|
|
155
|
+
seenDecision.add(key);
|
|
156
|
+
neuron.decisions.push({
|
|
157
|
+
text: dop.text,
|
|
158
|
+
date: dop.at,
|
|
159
|
+
rationale: dop.why || '',
|
|
160
|
+
id: dop.did,
|
|
161
|
+
by: dop.by,
|
|
162
|
+
});
|
|
163
|
+
report.decisions_added++;
|
|
164
|
+
}
|
|
165
|
+
// ─── Patterns and tags: plain set union ──────────────────────
|
|
166
|
+
for (const op of ops) {
|
|
167
|
+
if (op.op === 'pattern') {
|
|
168
|
+
if (!neuron.patterns.some(p => (0, ops_js_1.normalizeText)(p) === (0, ops_js_1.normalizeText)(op.text))) {
|
|
169
|
+
neuron.patterns.push(op.text);
|
|
170
|
+
report.patterns_added++;
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
else if (op.op === 'tag') {
|
|
174
|
+
if (!neuron.tags.some(t => (0, ops_js_1.normalizeText)(t) === (0, ops_js_1.normalizeText)(op.text))) {
|
|
175
|
+
neuron.tags.push(op.text);
|
|
176
|
+
report.tags_added++;
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
// Deterministic order, so two machines holding the same knowledge produce
|
|
181
|
+
// byte-identical files. Without this, every sync would look like a change.
|
|
182
|
+
neuron.facts.sort((a, b) => {
|
|
183
|
+
const d = String(a.added || '').localeCompare(String(b.added || ''));
|
|
184
|
+
return d !== 0 ? d : String(a.id || '').localeCompare(String(b.id || ''));
|
|
185
|
+
});
|
|
186
|
+
neuron.decisions.sort((a, b) => String(a.date || '').localeCompare(String(b.date || '')));
|
|
187
|
+
neuron.patterns.sort();
|
|
188
|
+
neuron.tags.sort();
|
|
189
|
+
report.authors = [...new Set(ops.map(o => o.by).filter(Boolean))].sort();
|
|
190
|
+
return { neuron, report };
|
|
191
|
+
}
|
|
192
|
+
//# sourceMappingURL=materialize.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"materialize.js","sourceRoot":"","sources":["../../src/sync/materialize.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
/** Bumped only if the shape changes in a way older clients cannot read. */
|
|
2
|
+
export declare const OPS_VERSION = 1;
|
|
3
|
+
export type OpKind = 'neuron' | 'fact' | 'status' | 'decision' | 'pattern' | 'tag';
|
|
4
|
+
interface OpBase {
|
|
5
|
+
v: number;
|
|
6
|
+
op: OpKind;
|
|
7
|
+
/** Neuron this applies to. */
|
|
8
|
+
nid: string;
|
|
9
|
+
/** Who wrote it. Not a security claim — anyone with push access can write any name. */
|
|
10
|
+
by: string;
|
|
11
|
+
/** ISO timestamp. Used for display and for keeping the earliest date, never to decide a winner. */
|
|
12
|
+
at: string;
|
|
13
|
+
}
|
|
14
|
+
/** Announces a neuron. Its name/type/domain are only used if the receiver has no such neuron. */
|
|
15
|
+
export interface NeuronOp extends OpBase {
|
|
16
|
+
op: 'neuron';
|
|
17
|
+
name: string;
|
|
18
|
+
ntype: string;
|
|
19
|
+
domain: string;
|
|
20
|
+
}
|
|
21
|
+
export interface FactOp extends OpBase {
|
|
22
|
+
op: 'fact';
|
|
23
|
+
fid: string;
|
|
24
|
+
text: string;
|
|
25
|
+
conf: number;
|
|
26
|
+
src?: string;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* A fact stopped being current. Only ever moves forward:
|
|
30
|
+
* active → superseded → retracted, never back.
|
|
31
|
+
*/
|
|
32
|
+
export interface StatusOp extends OpBase {
|
|
33
|
+
op: 'status';
|
|
34
|
+
fid: string;
|
|
35
|
+
to: 'superseded' | 'retracted';
|
|
36
|
+
why?: string;
|
|
37
|
+
}
|
|
38
|
+
export interface DecisionOp extends OpBase {
|
|
39
|
+
op: 'decision';
|
|
40
|
+
did: string;
|
|
41
|
+
text: string;
|
|
42
|
+
why?: string;
|
|
43
|
+
}
|
|
44
|
+
export interface PatternOp extends OpBase {
|
|
45
|
+
op: 'pattern';
|
|
46
|
+
text: string;
|
|
47
|
+
}
|
|
48
|
+
export interface TagOp extends OpBase {
|
|
49
|
+
op: 'tag';
|
|
50
|
+
text: string;
|
|
51
|
+
}
|
|
52
|
+
export type Op = NeuronOp | FactOp | StatusOp | DecisionOp | PatternOp | TagOp;
|
|
53
|
+
/**
|
|
54
|
+
* Same wording, same id, on every machine.
|
|
55
|
+
*
|
|
56
|
+
* Normalising first matters: one person's copy of a sentence may differ from
|
|
57
|
+
* another's by a stray double space or a different Unicode composition, and
|
|
58
|
+
* without this they would become two facts saying the same thing.
|
|
59
|
+
*/
|
|
60
|
+
export declare function normalizeText(text: string): string;
|
|
61
|
+
export declare function entryId(text: string): string;
|
|
62
|
+
/** Serialise one operation as a single line. */
|
|
63
|
+
export declare function encodeOp(op: Op): string;
|
|
64
|
+
/**
|
|
65
|
+
* Parse a log. Unreadable lines are skipped rather than thrown, because a log
|
|
66
|
+
* can be cut in half by a process dying mid-append or by a merge landing while
|
|
67
|
+
* we read. One bad line must never cost the other nine hundred.
|
|
68
|
+
*/
|
|
69
|
+
export declare function decodeOps(content: string): {
|
|
70
|
+
ops: Op[];
|
|
71
|
+
skipped: number;
|
|
72
|
+
};
|
|
73
|
+
/** Where a person's log for a neuron lives inside the space. */
|
|
74
|
+
export declare function opsRelPath(neuronId: string, author: string, device: string): string;
|
|
75
|
+
export {};
|
|
76
|
+
//# sourceMappingURL=ops.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ops.d.ts","sourceRoot":"","sources":["../../src/sync/ops.ts"],"names":[],"mappings":"AAcA,2EAA2E;AAC3E,eAAO,MAAM,WAAW,IAAI,CAAC;AAE7B,MAAM,MAAM,MAAM,GAAG,QAAQ,GAAG,MAAM,GAAG,QAAQ,GAAG,UAAU,GAAG,SAAS,GAAG,KAAK,CAAC;AAEnF,UAAU,MAAM;IACd,CAAC,EAAE,MAAM,CAAC;IACV,EAAE,EAAE,MAAM,CAAC;IACX,8BAA8B;IAC9B,GAAG,EAAE,MAAM,CAAC;IACZ,uFAAuF;IACvF,EAAE,EAAE,MAAM,CAAC;IACX,mGAAmG;IACnG,EAAE,EAAE,MAAM,CAAC;CACZ;AAED,iGAAiG;AACjG,MAAM,WAAW,QAAS,SAAQ,MAAM;IACtC,EAAE,EAAE,QAAQ,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,MAAO,SAAQ,MAAM;IACpC,EAAE,EAAE,MAAM,CAAC;IACX,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED;;;GAGG;AACH,MAAM,WAAW,QAAS,SAAQ,MAAM;IACtC,EAAE,EAAE,QAAQ,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,EAAE,EAAE,YAAY,GAAG,WAAW,CAAC;IAC/B,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,UAAW,SAAQ,MAAM;IACxC,EAAE,EAAE,UAAU,CAAC;IACf,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,SAAU,SAAQ,MAAM;IACvC,EAAE,EAAE,SAAS,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,KAAM,SAAQ,MAAM;IACnC,EAAE,EAAE,KAAK,CAAC;IACV,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,MAAM,EAAE,GAAG,QAAQ,GAAG,MAAM,GAAG,QAAQ,GAAG,UAAU,GAAG,SAAS,GAAG,KAAK,CAAC;AAE/E;;;;;;GAMG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAElD;AAED,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAE5C;AAED,gDAAgD;AAChD,wBAAgB,QAAQ,CAAC,EAAE,EAAE,EAAE,GAAG,MAAM,CAEvC;AAED;;;;GAIG;AACH,wBAAgB,SAAS,CAAC,OAAO,EAAE,MAAM,GAAG;IAAE,GAAG,EAAE,EAAE,EAAE,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAyBzE;AAED,gEAAgE;AAChE,wBAAgB,UAAU,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAEnF"}
|
package/dist/sync/ops.js
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// ─── CRBRO Shared Memory: the operation log ──────────────────────
|
|
3
|
+
//
|
|
4
|
+
// Two people cannot share a neuron by copying the file back and forth: the
|
|
5
|
+
// last save wins and the other person's work vanishes. So nobody ever shares
|
|
6
|
+
// the neuron. Each person appends notes to their own log — "I added this
|
|
7
|
+
// fact", "I retracted that one" — and every machine rebuilds the neuron from
|
|
8
|
+
// all the logs it has.
|
|
9
|
+
//
|
|
10
|
+
// Nobody writes to anybody else's file, so there is nothing to collide. That
|
|
11
|
+
// is the whole trick, and it is what makes the merge automatic: no conflict
|
|
12
|
+
// can arise if no two writers touch the same bytes.
|
|
13
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
14
|
+
exports.OPS_VERSION = void 0;
|
|
15
|
+
exports.normalizeText = normalizeText;
|
|
16
|
+
exports.entryId = entryId;
|
|
17
|
+
exports.encodeOp = encodeOp;
|
|
18
|
+
exports.decodeOps = decodeOps;
|
|
19
|
+
exports.opsRelPath = opsRelPath;
|
|
20
|
+
const hash_js_1 = require("../utils/hash.js");
|
|
21
|
+
/** Bumped only if the shape changes in a way older clients cannot read. */
|
|
22
|
+
exports.OPS_VERSION = 1;
|
|
23
|
+
/**
|
|
24
|
+
* Same wording, same id, on every machine.
|
|
25
|
+
*
|
|
26
|
+
* Normalising first matters: one person's copy of a sentence may differ from
|
|
27
|
+
* another's by a stray double space or a different Unicode composition, and
|
|
28
|
+
* without this they would become two facts saying the same thing.
|
|
29
|
+
*/
|
|
30
|
+
function normalizeText(text) {
|
|
31
|
+
return (text || '').normalize('NFC').replace(/\s+/g, ' ').trim();
|
|
32
|
+
}
|
|
33
|
+
function entryId(text) {
|
|
34
|
+
return (0, hash_js_1.contentHash)(normalizeText(text));
|
|
35
|
+
}
|
|
36
|
+
/** Serialise one operation as a single line. */
|
|
37
|
+
function encodeOp(op) {
|
|
38
|
+
return JSON.stringify(op);
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Parse a log. Unreadable lines are skipped rather than thrown, because a log
|
|
42
|
+
* can be cut in half by a process dying mid-append or by a merge landing while
|
|
43
|
+
* we read. One bad line must never cost the other nine hundred.
|
|
44
|
+
*/
|
|
45
|
+
function decodeOps(content) {
|
|
46
|
+
const ops = [];
|
|
47
|
+
let skipped = 0;
|
|
48
|
+
for (const line of (content || '').split('\n')) {
|
|
49
|
+
const t = line.trim();
|
|
50
|
+
if (!t)
|
|
51
|
+
continue;
|
|
52
|
+
try {
|
|
53
|
+
const parsed = JSON.parse(t);
|
|
54
|
+
if (!parsed || typeof parsed !== 'object' || !parsed.op || !parsed.nid) {
|
|
55
|
+
skipped++;
|
|
56
|
+
continue;
|
|
57
|
+
}
|
|
58
|
+
if (parsed.v > exports.OPS_VERSION) {
|
|
59
|
+
// Written by a newer CRBRO. Skipping is safer than half-understanding it.
|
|
60
|
+
skipped++;
|
|
61
|
+
continue;
|
|
62
|
+
}
|
|
63
|
+
ops.push(parsed);
|
|
64
|
+
}
|
|
65
|
+
catch {
|
|
66
|
+
skipped++;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
return { ops, skipped };
|
|
70
|
+
}
|
|
71
|
+
/** Where a person's log for a neuron lives inside the space. */
|
|
72
|
+
function opsRelPath(neuronId, author, device) {
|
|
73
|
+
return `neurons/${neuronId}/ops/${author}.${device}.jsonl`;
|
|
74
|
+
}
|
|
75
|
+
//# sourceMappingURL=ops.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ops.js","sourceRoot":"","sources":["../../src/sync/ops.ts"],"names":[],"mappings":";AAAA,oEAAoE;AACpE,EAAE;AACF,2EAA2E;AAC3E,6EAA6E;AAC7E,yEAAyE;AACzE,6EAA6E;AAC7E,uBAAuB;AACvB,EAAE;AACF,6EAA6E;AAC7E,4EAA4E;AAC5E,oDAAoD;;;AAyEpD,sCAEC;AAED,0BAEC;AAGD,4BAEC;AAOD,8BAyBC;AAGD,gCAEC;AAvHD,8CAA+C;AAE/C,2EAA2E;AAC9D,QAAA,WAAW,GAAG,CAAC,CAAC;AA6D7B;;;;;;GAMG;AACH,SAAgB,aAAa,CAAC,IAAY;IACxC,OAAO,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;AACnE,CAAC;AAED,SAAgB,OAAO,CAAC,IAAY;IAClC,OAAO,IAAA,qBAAW,EAAC,aAAa,CAAC,IAAI,CAAC,CAAC,CAAC;AAC1C,CAAC;AAED,gDAAgD;AAChD,SAAgB,QAAQ,CAAC,EAAM;IAC7B,OAAO,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC;AAC5B,CAAC;AAED;;;;GAIG;AACH,SAAgB,SAAS,CAAC,OAAe;IACvC,MAAM,GAAG,GAAS,EAAE,CAAC;IACrB,IAAI,OAAO,GAAG,CAAC,CAAC;IAEhB,KAAK,MAAM,IAAI,IAAI,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;QAC/C,MAAM,CAAC,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;QACtB,IAAI,CAAC,CAAC;YAAE,SAAS;QACjB,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAO,CAAC;YACnC,IAAI,CAAC,MAAM,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,CAAC,MAAM,CAAC,EAAE,IAAI,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC;gBACvE,OAAO,EAAE,CAAC;gBACV,SAAS;YACX,CAAC;YACD,IAAI,MAAM,CAAC,CAAC,GAAG,mBAAW,EAAE,CAAC;gBAC3B,0EAA0E;gBAC1E,OAAO,EAAE,CAAC;gBACV,SAAS;YACX,CAAC;YACD,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACnB,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,EAAE,CAAC;QACZ,CAAC;IACH,CAAC;IAED,OAAO,EAAE,GAAG,EAAE,OAAO,EAAE,CAAC;AAC1B,CAAC;AAED,gEAAgE;AAChE,SAAgB,UAAU,CAAC,QAAgB,EAAE,MAAc,EAAE,MAAc;IACzE,OAAO,WAAW,QAAQ,QAAQ,MAAM,IAAI,MAAM,QAAQ,CAAC;AAC7D,CAAC"}
|