@superinstance/live-canon 0.2.0 → 0.4.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/index.js +145 -186
- package/package.json +3 -3
package/index.js
CHANGED
|
@@ -1,168 +1,66 @@
|
|
|
1
|
-
// index.js — Live Canon
|
|
2
|
-
//
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
// 4. GHOST - find paper that should exist by shape proximity
|
|
9
|
-
// 5. TICK - re-balance the canon
|
|
10
|
-
//
|
|
11
|
-
// Polyformal: byte-exact with Python, C99, Rust, Verilog, VHDL.
|
|
12
|
-
// State hash = 0xbf27a3631cdee337 for the 9 bundled papers.
|
|
13
|
-
//
|
|
14
|
-
// Phase 251 of the polyformalism canon.
|
|
15
|
-
|
|
16
|
-
'use strict';
|
|
17
|
-
|
|
18
|
-
// ===== FNV-1a 64-bit hash (UTF-8 byte-exact with Python) =====
|
|
1
|
+
// index.js — Live Canon: AI-Writings as a navigable cell fabric
|
|
2
|
+
// 14 papers, byte-exact with Python, C, Rust, Verilog, VHDL, JavaScript
|
|
3
|
+
|
|
4
|
+
const FNV_OFFSET = 0xCBF29CE484222325n;
|
|
5
|
+
const FNV_PRIME = 0x00000100000001B3n;
|
|
6
|
+
const MASK = 0xFFFFFFFFFFFFFFFFn;
|
|
7
|
+
|
|
19
8
|
function fnv1a_64(s) {
|
|
20
|
-
let h =
|
|
21
|
-
const
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
h
|
|
9
|
+
let h = FNV_OFFSET;
|
|
10
|
+
const enc = new TextEncoder();
|
|
11
|
+
const bytes = enc.encode(s);
|
|
12
|
+
for (const b of bytes) {
|
|
13
|
+
h ^= BigInt(b);
|
|
14
|
+
h = (h * FNV_PRIME) & MASK;
|
|
25
15
|
}
|
|
26
16
|
return h;
|
|
27
17
|
}
|
|
28
18
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
const
|
|
32
|
-
const
|
|
33
|
-
const
|
|
34
|
-
const
|
|
35
|
-
const
|
|
36
|
-
const
|
|
37
|
-
const
|
|
38
|
-
const
|
|
39
|
-
const
|
|
40
|
-
const
|
|
41
|
-
|
|
42
|
-
return [num_q, title_lo, f_q, phase_q, year_q, n_refs_q, title_hi, 0,
|
|
43
|
-
0, 0, 0, 0, 0, 0, 0, 0];
|
|
19
|
+
function cellToDials(p) {
|
|
20
|
+
const year = parseInt((p.date || '1970-01-01').slice(0, 4)) || 1970;
|
|
21
|
+
const yearQ = (year - 1970) * 546;
|
|
22
|
+
const phaseQ = (p.phase || 0) * 218;
|
|
23
|
+
const fQ = (p.f_number || 0) * 218;
|
|
24
|
+
const nRefs = (p.ref_papers || []).length + (p.ref_f_numbers || []).length;
|
|
25
|
+
const nRefsQ = Math.min(0x7FFF, nRefs * 256);
|
|
26
|
+
const th = fnv1a_64(p.title || '');
|
|
27
|
+
const titleLo = Number(th & 0xFFFFn);
|
|
28
|
+
const titleHi = Number((th >> 16n) & 0xFFFFn);
|
|
29
|
+
const num = Math.min(p.number || 0, 500);
|
|
30
|
+
const numQ = num * 131;
|
|
31
|
+
return [numQ, titleLo, fQ, phaseQ, yearQ, nRefsQ, titleHi, 0, 0, 0, 0, 0, 0, 0, 0, 0];
|
|
44
32
|
}
|
|
45
33
|
|
|
46
|
-
// ===== Cosine similarity =====
|
|
47
|
-
function cosineSim(a, b) {
|
|
48
|
-
let dot = 0, na = 0, nb = 0;
|
|
49
|
-
for (let i = 0; i < 16; i++) {
|
|
50
|
-
dot += a[i] * b[i];
|
|
51
|
-
na += a[i] * a[i];
|
|
52
|
-
nb += b[i] * b[i];
|
|
53
|
-
}
|
|
54
|
-
na = Math.sqrt(na);
|
|
55
|
-
nb = Math.sqrt(nb);
|
|
56
|
-
if (na === 0 || nb === 0) return 0;
|
|
57
|
-
return dot / (na * nb);
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
// ===== State hash (FNV-1a over sorted dials) =====
|
|
61
34
|
function stateHash(papers) {
|
|
62
|
-
const
|
|
63
|
-
|
|
64
|
-
let h =
|
|
65
|
-
for (const d of
|
|
35
|
+
const dials = Object.values(papers).map(cellToDials);
|
|
36
|
+
dials.sort((a, b) => a[0] - b[0]);
|
|
37
|
+
let h = FNV_OFFSET;
|
|
38
|
+
for (const d of dials) {
|
|
66
39
|
for (const v of d) {
|
|
67
40
|
const lo = v & 0xFF;
|
|
68
41
|
const hi = (v >> 8) & 0xFF;
|
|
69
42
|
h ^= BigInt(lo);
|
|
70
|
-
h = (h *
|
|
43
|
+
h = (h * FNV_PRIME) & MASK;
|
|
71
44
|
h ^= BigInt(hi);
|
|
72
|
-
h = (h *
|
|
45
|
+
h = (h * FNV_PRIME) & MASK;
|
|
73
46
|
}
|
|
74
47
|
}
|
|
75
48
|
return h;
|
|
76
49
|
}
|
|
77
50
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
const [num, d] = queue.shift();
|
|
85
|
-
const paper = canon[num];
|
|
86
|
-
if (paper) {
|
|
87
|
-
result.push({ depth: d, paper });
|
|
88
|
-
if (d < depth) {
|
|
89
|
-
for (const ref of (paper.ref_papers || [])) {
|
|
90
|
-
if (canon[ref] && !visited.has(ref)) {
|
|
91
|
-
visited.add(ref);
|
|
92
|
-
queue.push([ref, d + 1]);
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
return result;
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
function confluence(canon, paper_nums) {
|
|
102
|
-
if (!paper_nums || paper_nums.length === 0) return { error: "no papers" };
|
|
103
|
-
let sharedRefs = null, sharedF = null;
|
|
104
|
-
const titles = [];
|
|
105
|
-
for (const num of paper_nums) {
|
|
106
|
-
const p = canon[num];
|
|
107
|
-
if (!p) continue;
|
|
108
|
-
titles.push(p.title);
|
|
109
|
-
const refs = new Set(p.ref_papers || []);
|
|
110
|
-
sharedRefs = sharedRefs === null
|
|
111
|
-
? new Set(refs)
|
|
112
|
-
: new Set([...sharedRefs].filter(x => refs.has(x)));
|
|
113
|
-
const fs = new Set(p.ref_f_numbers || []);
|
|
114
|
-
sharedF = sharedF === null
|
|
115
|
-
? new Set(fs)
|
|
116
|
-
: new Set([...sharedF].filter(x => fs.has(x)));
|
|
117
|
-
}
|
|
118
|
-
let suggested = `Composition of ${paper_nums.length} papers`;
|
|
119
|
-
if (sharedF && sharedF.size > 0) {
|
|
120
|
-
const first = [...sharedF].sort((a, b) => a - b)[0];
|
|
121
|
-
suggested = `F${first} Synthesis: ${titles.join(", ")}`;
|
|
122
|
-
}
|
|
123
|
-
const maxN = Math.max(...Object.keys(canon).map(Number));
|
|
124
|
-
return {
|
|
125
|
-
input_papers: paper_nums,
|
|
126
|
-
input_titles: titles,
|
|
127
|
-
shared_refs: sharedRefs ? [...sharedRefs].sort((a, b) => a - b) : [],
|
|
128
|
-
shared_f_numbers: sharedF ? [...sharedF].sort((a, b) => a - b) : [],
|
|
129
|
-
suggested_title: suggested,
|
|
130
|
-
ghost_paper: `paper-${maxN + 1}.md`,
|
|
131
|
-
};
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
function lineage(canon, f_number) {
|
|
135
|
-
const result = [];
|
|
136
|
-
for (const p of Object.values(canon)) {
|
|
137
|
-
if ((p.ref_f_numbers || []).includes(f_number)) result.push(p);
|
|
138
|
-
}
|
|
139
|
-
result.sort((a, b) => (a.phase - b.phase) || (a.number - b.number));
|
|
140
|
-
return result;
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
function ghost(canon, paper_num, k) {
|
|
144
|
-
const target = canon[paper_num];
|
|
145
|
-
if (!target) return { error: "missing paper" };
|
|
146
|
-
const targetDials = cellToDials(target);
|
|
147
|
-
const scored = [];
|
|
148
|
-
for (const [n, p] of Object.entries(canon)) {
|
|
149
|
-
if (Number(n) === paper_num) continue;
|
|
150
|
-
const score = cosineSim(targetDials, cellToDials(p));
|
|
151
|
-
scored.push({ id: `p${String(n).padStart(4, "0")}`, score: Math.round(score * 10000) / 10000 });
|
|
51
|
+
function cosine(a, b) {
|
|
52
|
+
let dot = 0, na = 0, nb = 0;
|
|
53
|
+
for (let i = 0; i < 16; i++) {
|
|
54
|
+
dot += a[i] * b[i];
|
|
55
|
+
na += a[i] * a[i];
|
|
56
|
+
nb += b[i] * b[i];
|
|
152
57
|
}
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
neighbors: scored.slice(0, k),
|
|
157
|
-
suggested_title: `A Bridge between F${target.f_number} and its neighbors`,
|
|
158
|
-
};
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
function tick(canon) {
|
|
162
|
-
return { ticked_cells: Object.keys(canon).length };
|
|
58
|
+
na = Math.sqrt(na);
|
|
59
|
+
nb = Math.sqrt(nb);
|
|
60
|
+
return na && nb ? dot / (na * nb) : 0;
|
|
163
61
|
}
|
|
164
62
|
|
|
165
|
-
//
|
|
63
|
+
// Default 14-paper canon (F115-F135)
|
|
166
64
|
const DEFAULT_CANON = {
|
|
167
65
|
425: { number: 425, title: "F115 — The Logical Routes: VHDL × Verilog × the QUF bit-exactness", f_number: 115, phase: 237, date: "2026-09-03", ref_papers: [426, 427], ref_f_numbers: [] },
|
|
168
66
|
426: { number: 426, title: "F116 — The 5+1+1+1+1+1+1+1+1+1+1 Opcodes in 5 Substrates: A Polyformalism Atlas", f_number: 116, phase: 238, date: "2026-09-03", ref_papers: [], ref_f_numbers: [115] },
|
|
@@ -173,54 +71,115 @@ const DEFAULT_CANON = {
|
|
|
173
71
|
433: { number: 433, title: "F123 — The Composer Agent: 5 Cells, 80 Parameters", f_number: 123, phase: 245, date: "2026-09-03", ref_papers: [], ref_f_numbers: [120, 122] },
|
|
174
72
|
439: { number: 439, title: "F129 — The Live Canon: Papers as Cells, Reading as Navigation", f_number: 129, phase: 251, date: "2026-09-03", ref_papers: [], ref_f_numbers: [115, 120, 122, 125] },
|
|
175
73
|
440: { number: 440, title: "F130 — The Polyformal Live Canon: One Cell, Five Substrates", f_number: 130, phase: 251, date: "2026-09-03", ref_papers: [], ref_f_numbers: [115, 129] },
|
|
74
|
+
441: { number: 441, title: "F131 — The 3-Package Polyformalism: One Cell, Three Registries", f_number: 131, phase: 252, date: "2026-09-03", ref_papers: [], ref_f_numbers: [115, 130] },
|
|
75
|
+
442: { number: 442, title: "F132 — Operational Fictions as Concrete System-Prompt Noun-Phrases", f_number: 132, phase: 253, date: "2026-09-03", ref_papers: [], ref_f_numbers: [] },
|
|
76
|
+
443: { number: 443, title: "F133 — Operational Fictions as Falsifiable Claims (avg divergence 0.861)", f_number: 133, phase: 254, date: "2026-09-03", ref_papers: [], ref_f_numbers: [132] },
|
|
77
|
+
444: { number: 444, title: "F134 — The Quilt Cowboy: Orchestrator Over 12 Cheap Voices", f_number: 134, phase: 254, date: "2026-09-03", ref_papers: [], ref_f_numbers: [132, 133] },
|
|
78
|
+
445: { number: 445, title: "F135 — The Wheelhouse Test: Scoring Fictions for 0300-in-a-Gale Tolerability", f_number: 135, phase: 254, date: "2026-09-03", ref_papers: [], ref_f_numbers: [132, 133] },
|
|
79
|
+
446: { number: 446, title: "F136 — The Edge of the Doctrine — 6 Experiments", f_number: 136, phase: 254, date: "2026-09-03", ref_papers: [], ref_f_numbers: [132, 133, 134, 135] },
|
|
80
|
+
447: { number: 447, title: "F137 — The Word-Level Metric is Broken (semantic divergence is real)", f_number: 137, phase: 254, date: "2026-09-03", ref_papers: [], ref_f_numbers: [133, 136] },
|
|
81
|
+
448: { number: 448, title: "F138 — The Real Numbers — 12 Pairs with Semantic Divergence (0.231 vs 0.171)", f_number: 138, phase: 254, date: "2026-09-03", ref_papers: [], ref_f_numbers: [133, 137] },
|
|
82
|
+
449: { number: 449, title: "F139 — Wearable Neural Devices + Quilt — The Synergy of Signaling-as-Play", f_number: 139, phase: 256, date: "2026-09-03", ref_papers: [], ref_f_numbers: [129, 130, 131] },
|
|
83
|
+
450: { number: 450, title: "F140 — The Negative Space: Decomposition × Composition × Double-Entry Bookkeeping of the Self", f_number: 140, phase: 257, date: "2026-09-03", ref_papers: [], ref_f_numbers: [129, 133, 137, 138, 139] },
|
|
176
84
|
};
|
|
177
85
|
|
|
178
|
-
// ===== LiveCanon class =====
|
|
179
86
|
class LiveCanon {
|
|
180
|
-
constructor(canon =
|
|
181
|
-
this.canon = canon;
|
|
87
|
+
constructor(canon = null) {
|
|
88
|
+
this.canon = canon || { ...DEFAULT_CANON };
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
get stateHashBigInt() {
|
|
92
|
+
return stateHash(this.canon);
|
|
182
93
|
}
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
get
|
|
189
|
-
|
|
190
|
-
|
|
94
|
+
|
|
95
|
+
get stateHashString() {
|
|
96
|
+
return '0x' + this.stateHashBigInt.toString(16).padStart(16, '0');
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
get paperCount() {
|
|
100
|
+
return Object.keys(this.canon).length;
|
|
101
|
+
}
|
|
102
|
+
|
|
191
103
|
papers() { return Object.values(this.canon); }
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
const
|
|
196
|
-
const
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
104
|
+
|
|
105
|
+
navigate(start, depth = 2) {
|
|
106
|
+
const visited = new Set([start]);
|
|
107
|
+
const result = [];
|
|
108
|
+
const queue = [[start, 0]];
|
|
109
|
+
while (queue.length) {
|
|
110
|
+
const [num, d] = queue.shift();
|
|
111
|
+
const paper = this.canon[num];
|
|
112
|
+
if (paper) {
|
|
113
|
+
result.push({ depth: d, paper });
|
|
114
|
+
if (d < depth) {
|
|
115
|
+
for (const ref of paper.ref_papers || []) {
|
|
116
|
+
if (this.canon[ref] && !visited.has(ref)) {
|
|
117
|
+
visited.add(ref);
|
|
118
|
+
queue.push([ref, d + 1]);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
return result;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
confluence(paperNums) {
|
|
128
|
+
if (!paperNums || !paperNums.length) return { error: "no papers" };
|
|
129
|
+
let sharedRefs = null, sharedF = null;
|
|
130
|
+
const titles = [];
|
|
131
|
+
for (const num of paperNums) {
|
|
132
|
+
const p = this.canon[num];
|
|
133
|
+
if (!p) continue;
|
|
134
|
+
titles.push(p.title);
|
|
135
|
+
const refs = new Set(p.ref_papers || []);
|
|
136
|
+
sharedRefs = sharedRefs === null ? new Set(refs) : new Set([...sharedRefs].filter(x => refs.has(x)));
|
|
137
|
+
const fs = new Set(p.ref_f_numbers || []);
|
|
138
|
+
sharedF = sharedF === null ? new Set(fs) : new Set([...sharedF].filter(x => fs.has(x)));
|
|
139
|
+
}
|
|
140
|
+
let suggested = `Composition of ${paperNums.length} papers`;
|
|
141
|
+
if (sharedF && sharedF.size) {
|
|
142
|
+
const first = Math.min(...sharedF);
|
|
143
|
+
suggested = `F${first} Synthesis: ${titles.join(', ')}`;
|
|
144
|
+
}
|
|
145
|
+
const maxN = Math.max(...Object.keys(this.canon).map(Number));
|
|
146
|
+
return {
|
|
147
|
+
input_papers: paperNums,
|
|
148
|
+
input_titles: titles,
|
|
149
|
+
shared_refs: sharedRefs ? [...sharedRefs].sort() : [],
|
|
150
|
+
shared_f_numbers: sharedF ? [...sharedF].sort() : [],
|
|
151
|
+
suggested_title: suggested,
|
|
152
|
+
ghost_paper: `paper-${maxN + 1}.md`,
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
lineage(fNumber) {
|
|
157
|
+
return this.papers()
|
|
158
|
+
.filter(p => (p.ref_f_numbers || []).includes(fNumber))
|
|
159
|
+
.sort((a, b) => (a.phase || 0) - (b.phase || 0));
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
ghost(paperNum, k = 5) {
|
|
163
|
+
const target = this.canon[paperNum];
|
|
164
|
+
if (!target) return { error: "missing paper" };
|
|
165
|
+
const targetDials = cellToDials(target);
|
|
166
|
+
const scored = [];
|
|
167
|
+
for (const [n, p] of Object.entries(this.canon)) {
|
|
168
|
+
if (n == paperNum) continue;
|
|
169
|
+
const score = cosine(targetDials, cellToDials(p));
|
|
170
|
+
scored.push({ id: `p${String(n).padStart(4, '0')}`, score: Math.round(score * 10000) / 10000 });
|
|
209
171
|
}
|
|
210
|
-
|
|
172
|
+
scored.sort((a, b) => b.score - a.score);
|
|
173
|
+
return {
|
|
174
|
+
source_paper: `paper-${paperNum}.md`,
|
|
175
|
+
neighbors: scored.slice(0, k),
|
|
176
|
+
suggested_title: `A Bridge between F${target.f_number || 0} and its neighbors`,
|
|
177
|
+
};
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
tick() {
|
|
181
|
+
return { ticked_cells: this.paperCount };
|
|
211
182
|
}
|
|
212
183
|
}
|
|
213
184
|
|
|
214
|
-
module.exports = {
|
|
215
|
-
LiveCanon,
|
|
216
|
-
DEFAULT_CANON,
|
|
217
|
-
fnv1a_64,
|
|
218
|
-
cellToDials,
|
|
219
|
-
cosineSim,
|
|
220
|
-
stateHash,
|
|
221
|
-
navigate,
|
|
222
|
-
confluence,
|
|
223
|
-
lineage,
|
|
224
|
-
ghost,
|
|
225
|
-
tick,
|
|
226
|
-
};
|
|
185
|
+
module.exports = { LiveCanon, fnv1a_64, stateHash, cellToDials, DEFAULT_CANON };
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@superinstance/live-canon",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "Live Canon
|
|
3
|
+
"version": "0.4.0",
|
|
4
|
+
"description": "Live Canon \u2014 read the AI-Writings canon as a navigable cell fabric, with 5 novel operations: NAVIGATE, CONFLUENCE, LINEAGE, GHOST, TICK.",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"scripts": {
|
|
7
7
|
"test": "node test/test.js"
|
|
@@ -24,4 +24,4 @@
|
|
|
24
24
|
"engines": {
|
|
25
25
|
"node": ">=18.0.0"
|
|
26
26
|
}
|
|
27
|
-
}
|
|
27
|
+
}
|