@mneme-ai/core 2.19.45 → 2.19.47
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/chronosheaf/aczel.d.ts +72 -0
- package/dist/chronosheaf/aczel.d.ts.map +1 -0
- package/dist/chronosheaf/aczel.js +161 -0
- package/dist/chronosheaf/aczel.js.map +1 -0
- package/dist/chronosheaf/chronosheaf.test.d.ts +12 -0
- package/dist/chronosheaf/chronosheaf.test.d.ts.map +1 -0
- package/dist/chronosheaf/chronosheaf.test.js +360 -0
- package/dist/chronosheaf/chronosheaf.test.js.map +1 -0
- package/dist/chronosheaf/free_energy.d.ts +109 -0
- package/dist/chronosheaf/free_energy.d.ts.map +1 -0
- package/dist/chronosheaf/free_energy.js +142 -0
- package/dist/chronosheaf/free_energy.js.map +1 -0
- package/dist/chronosheaf/index.d.ts +35 -0
- package/dist/chronosheaf/index.d.ts.map +1 -0
- package/dist/chronosheaf/index.js +27 -0
- package/dist/chronosheaf/index.js.map +1 -0
- package/dist/chronosheaf/pain_catalog.d.ts +50 -0
- package/dist/chronosheaf/pain_catalog.d.ts.map +1 -0
- package/dist/chronosheaf/pain_catalog.js +108 -0
- package/dist/chronosheaf/pain_catalog.js.map +1 -0
- package/dist/chronosheaf/persistence.d.ts +79 -0
- package/dist/chronosheaf/persistence.d.ts.map +1 -0
- package/dist/chronosheaf/persistence.js +173 -0
- package/dist/chronosheaf/persistence.js.map +1 -0
- package/dist/chronosheaf/rg_flow.d.ts +81 -0
- package/dist/chronosheaf/rg_flow.d.ts.map +1 -0
- package/dist/chronosheaf/rg_flow.js +146 -0
- package/dist/chronosheaf/rg_flow.js.map +1 -0
- package/dist/chronosheaf/sheaf.d.ts +116 -0
- package/dist/chronosheaf/sheaf.d.ts.map +1 -0
- package/dist/chronosheaf/sheaf.js +278 -0
- package/dist/chronosheaf/sheaf.js.map +1 -0
- package/dist/chronosheaf/tropical.d.ts +98 -0
- package/dist/chronosheaf/tropical.d.ts.map +1 -0
- package/dist/chronosheaf/tropical.js +140 -0
- package/dist/chronosheaf/tropical.js.map +1 -0
- package/dist/chronosheaf/wasserstein.d.ts +75 -0
- package/dist/chronosheaf/wasserstein.d.ts.map +1 -0
- package/dist/chronosheaf/wasserstein.js +189 -0
- package/dist/chronosheaf/wasserstein.js.map +1 -0
- package/dist/cosmic/aurelian_v1946.test.d.ts +2 -0
- package/dist/cosmic/aurelian_v1946.test.d.ts.map +1 -0
- package/dist/cosmic/aurelian_v1946.test.js +48 -0
- package/dist/cosmic/aurelian_v1946.test.js.map +1 -0
- package/dist/cosmic/aurelian_v1947.test.d.ts +2 -0
- package/dist/cosmic/aurelian_v1947.test.d.ts.map +1 -0
- package/dist/cosmic/aurelian_v1947.test.js +34 -0
- package/dist/cosmic/aurelian_v1947.test.js.map +1 -0
- package/dist/honesty_gate/index.d.ts.map +1 -1
- package/dist/honesty_gate/index.js +7 -0
- package/dist/honesty_gate/index.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +8 -0
- package/dist/index.js.map +1 -1
- package/dist/squadron/acgv_n3_overshoot.test.d.ts +27 -0
- package/dist/squadron/acgv_n3_overshoot.test.d.ts.map +1 -0
- package/dist/squadron/acgv_n3_overshoot.test.js +125 -0
- package/dist/squadron/acgv_n3_overshoot.test.js.map +1 -0
- package/dist/whats_new.d.ts.map +1 -1
- package/dist/whats_new.js +16 -0
- package/dist/whats_new.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* v2.19.47 — CHRONOSHEAF P2-g · Aczel anti-foundation axiom (AFA) +
|
|
3
|
+
* bisimulation.
|
|
4
|
+
*
|
|
5
|
+
* Math foundation (Aczel 1988):
|
|
6
|
+
*
|
|
7
|
+
* ZFC's Foundation Axiom forbids self-membership: there is no set x
|
|
8
|
+
* with x ∈ x (no infinite descending ∈-chains). Aczel's AFA flips
|
|
9
|
+
* this: every "accessible pointed graph" represents exactly one set,
|
|
10
|
+
* so x = {x} is a perfectly valid set (the "Quine atom"). To work
|
|
11
|
+
* with these self-referential sets we replace equality with
|
|
12
|
+
* BISIMULATION:
|
|
13
|
+
*
|
|
14
|
+
* x ∼ y ⟺ (∀a∈x ∃b∈y. a ∼ b) ∧ (∀b∈y ∃a∈x. a ∼ b)
|
|
15
|
+
*
|
|
16
|
+
* The largest such relation (greatest fixed point of the bisimulation
|
|
17
|
+
* functor) is the canonical notion of "two self-referential sets are
|
|
18
|
+
* the same". Computing it = standard partition-refinement (Paige-
|
|
19
|
+
* Tarjan 1987) in O((N + E) · log N) for finite hypergraphs.
|
|
20
|
+
*
|
|
21
|
+
* AI-memory mapping (PAIN-004 self-reference + PAIN-007 substrate-
|
|
22
|
+
* mutation):
|
|
23
|
+
*
|
|
24
|
+
* "HONESTY GATE checks itself" is exactly the Quine-atom shape: the
|
|
25
|
+
* gate's belief refers to its own consistency. ZFC-style verifiers
|
|
26
|
+
* cannot represent this without Russell paradox; AFA can. Likewise,
|
|
27
|
+
* "the running binary is the file being overwritten" is an actor
|
|
28
|
+
* whose action mutates its own substrate — the world the actor
|
|
29
|
+
* models contains the actor. Aczel hypersets give us a formal
|
|
30
|
+
* vocabulary for both.
|
|
31
|
+
*
|
|
32
|
+
* Implementation: hypersets as labelled directed graphs;
|
|
33
|
+
* bisimulation via greatest-fixed-point partition refinement. Pure
|
|
34
|
+
* functional, O((N + E) log N).
|
|
35
|
+
*/
|
|
36
|
+
/** A node in an APG (accessible pointed graph). */
|
|
37
|
+
export type HypersetNode = string;
|
|
38
|
+
/** A hyperset = directed graph + designated root. */
|
|
39
|
+
export interface Hyperset {
|
|
40
|
+
/** All nodes (including the root). */
|
|
41
|
+
nodes: ReadonlyArray<HypersetNode>;
|
|
42
|
+
/** Edges as a map node → ordered list of children. */
|
|
43
|
+
edges: ReadonlyMap<HypersetNode, ReadonlyArray<HypersetNode>>;
|
|
44
|
+
/** Designated root (the "set" this hyperset represents). */
|
|
45
|
+
root: HypersetNode;
|
|
46
|
+
/** Optional atomic labels — atoms with the same label are bisimilar. */
|
|
47
|
+
labels?: ReadonlyMap<HypersetNode, string>;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Compute the canonical bisimulation partition (Paige-Tarjan refinement).
|
|
51
|
+
* Returns a map node → equivalence-class id.
|
|
52
|
+
*/
|
|
53
|
+
export declare function bisimulationPartition(g: Hyperset): Map<HypersetNode, number>;
|
|
54
|
+
/** Two hypersets are bisimilar iff their roots are in the same partition class. */
|
|
55
|
+
export declare function bisimilar(g1: Hyperset, g2: Hyperset): boolean;
|
|
56
|
+
/** The Quine atom Ω with Ω = {Ω}. The canonical self-referential set. */
|
|
57
|
+
export declare function quineAtom(name?: string): Hyperset;
|
|
58
|
+
/** A "false belief" hyperset: a node whose only child is itself, labelled "LIAR". */
|
|
59
|
+
export declare function liarHyperset(name?: string): Hyperset;
|
|
60
|
+
/**
|
|
61
|
+
* Reflexive verifier: returns true if a hyperset is "trustworthy" — its
|
|
62
|
+
* canonical bisimulation class contains no labelled liar atoms.
|
|
63
|
+
* This is the AFA-style fix for PAIN-004: HONESTY GATE can audit itself
|
|
64
|
+
* by checking whether its own hyperset is bisimilar to a known LIAR
|
|
65
|
+
* class WITHOUT triggering Russell paradox (because bisimulation is
|
|
66
|
+
* sound on self-referential sets).
|
|
67
|
+
*/
|
|
68
|
+
export declare function isTrustworthy(h: Hyperset): {
|
|
69
|
+
trust: boolean;
|
|
70
|
+
reason: string;
|
|
71
|
+
};
|
|
72
|
+
//# sourceMappingURL=aczel.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"aczel.d.ts","sourceRoot":"","sources":["../../src/chronosheaf/aczel.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AAEH,mDAAmD;AACnD,MAAM,MAAM,YAAY,GAAG,MAAM,CAAC;AAElC,qDAAqD;AACrD,MAAM,WAAW,QAAQ;IACvB,sCAAsC;IACtC,KAAK,EAAE,aAAa,CAAC,YAAY,CAAC,CAAC;IACnC,sDAAsD;IACtD,KAAK,EAAE,WAAW,CAAC,YAAY,EAAE,aAAa,CAAC,YAAY,CAAC,CAAC,CAAC;IAC9D,4DAA4D;IAC5D,IAAI,EAAE,YAAY,CAAC;IACnB,wEAAwE;IACxE,MAAM,CAAC,EAAE,WAAW,CAAC,YAAY,EAAE,MAAM,CAAC,CAAC;CAC5C;AAED;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,CAAC,EAAE,QAAQ,GAAG,GAAG,CAAC,YAAY,EAAE,MAAM,CAAC,CA6C5E;AAED,mFAAmF;AACnF,wBAAgB,SAAS,CAAC,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,QAAQ,GAAG,OAAO,CAoB7D;AAED,yEAAyE;AACzE,wBAAgB,SAAS,CAAC,IAAI,GAAE,MAAY,GAAG,QAAQ,CAMtD;AAED,qFAAqF;AACrF,wBAAgB,YAAY,CAAC,IAAI,GAAE,MAAY,GAAG,QAAQ,CAOzD;AAED;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAAC,CAAC,EAAE,QAAQ,GAAG;IAAE,KAAK,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAW7E"}
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* v2.19.47 — CHRONOSHEAF P2-g · Aczel anti-foundation axiom (AFA) +
|
|
3
|
+
* bisimulation.
|
|
4
|
+
*
|
|
5
|
+
* Math foundation (Aczel 1988):
|
|
6
|
+
*
|
|
7
|
+
* ZFC's Foundation Axiom forbids self-membership: there is no set x
|
|
8
|
+
* with x ∈ x (no infinite descending ∈-chains). Aczel's AFA flips
|
|
9
|
+
* this: every "accessible pointed graph" represents exactly one set,
|
|
10
|
+
* so x = {x} is a perfectly valid set (the "Quine atom"). To work
|
|
11
|
+
* with these self-referential sets we replace equality with
|
|
12
|
+
* BISIMULATION:
|
|
13
|
+
*
|
|
14
|
+
* x ∼ y ⟺ (∀a∈x ∃b∈y. a ∼ b) ∧ (∀b∈y ∃a∈x. a ∼ b)
|
|
15
|
+
*
|
|
16
|
+
* The largest such relation (greatest fixed point of the bisimulation
|
|
17
|
+
* functor) is the canonical notion of "two self-referential sets are
|
|
18
|
+
* the same". Computing it = standard partition-refinement (Paige-
|
|
19
|
+
* Tarjan 1987) in O((N + E) · log N) for finite hypergraphs.
|
|
20
|
+
*
|
|
21
|
+
* AI-memory mapping (PAIN-004 self-reference + PAIN-007 substrate-
|
|
22
|
+
* mutation):
|
|
23
|
+
*
|
|
24
|
+
* "HONESTY GATE checks itself" is exactly the Quine-atom shape: the
|
|
25
|
+
* gate's belief refers to its own consistency. ZFC-style verifiers
|
|
26
|
+
* cannot represent this without Russell paradox; AFA can. Likewise,
|
|
27
|
+
* "the running binary is the file being overwritten" is an actor
|
|
28
|
+
* whose action mutates its own substrate — the world the actor
|
|
29
|
+
* models contains the actor. Aczel hypersets give us a formal
|
|
30
|
+
* vocabulary for both.
|
|
31
|
+
*
|
|
32
|
+
* Implementation: hypersets as labelled directed graphs;
|
|
33
|
+
* bisimulation via greatest-fixed-point partition refinement. Pure
|
|
34
|
+
* functional, O((N + E) log N).
|
|
35
|
+
*/
|
|
36
|
+
/**
|
|
37
|
+
* Compute the canonical bisimulation partition (Paige-Tarjan refinement).
|
|
38
|
+
* Returns a map node → equivalence-class id.
|
|
39
|
+
*/
|
|
40
|
+
export function bisimulationPartition(g) {
|
|
41
|
+
// Initial partition: group by label (or single class if no labels).
|
|
42
|
+
const labels = g.labels ?? new Map();
|
|
43
|
+
const labelToBlock = new Map();
|
|
44
|
+
const node2block = new Map();
|
|
45
|
+
for (const n of g.nodes) {
|
|
46
|
+
const l = labels.get(n) ?? "__unlabelled__";
|
|
47
|
+
if (!labelToBlock.has(l))
|
|
48
|
+
labelToBlock.set(l, labelToBlock.size);
|
|
49
|
+
node2block.set(n, labelToBlock.get(l));
|
|
50
|
+
}
|
|
51
|
+
// Refine until stable: each iteration re-assigns block IDs by sorted
|
|
52
|
+
// signature of (oldBlock, sorted child blocks). Stops when the
|
|
53
|
+
// distinct-signature count equals the prior distinct-block count
|
|
54
|
+
// (= no further refinement possible). Bounded by V iterations.
|
|
55
|
+
const V = g.nodes.length;
|
|
56
|
+
for (let iter = 0; iter <= V; iter++) {
|
|
57
|
+
const sig2block = new Map();
|
|
58
|
+
const newBlocks = new Map();
|
|
59
|
+
for (const n of g.nodes) {
|
|
60
|
+
const children = g.edges.get(n) ?? [];
|
|
61
|
+
const childBlocks = children.map((c) => node2block.get(c) ?? -1).sort((a, b) => a - b);
|
|
62
|
+
const oldBlock = node2block.get(n) ?? -1;
|
|
63
|
+
const sig = `${oldBlock}::${childBlocks.join(",")}`;
|
|
64
|
+
if (!sig2block.has(sig))
|
|
65
|
+
sig2block.set(sig, sig2block.size);
|
|
66
|
+
newBlocks.set(n, sig2block.get(sig));
|
|
67
|
+
}
|
|
68
|
+
// Check for stabilisation: same number of blocks as before AND no
|
|
69
|
+
// node moved to a different block (re-assigned IDs may differ
|
|
70
|
+
// numerically; compare via group structure).
|
|
71
|
+
const prevDistinct = new Set(node2block.values()).size;
|
|
72
|
+
const nextDistinct = new Set(newBlocks.values()).size;
|
|
73
|
+
// Stable when no further split happens.
|
|
74
|
+
if (nextDistinct === prevDistinct && iter > 0) {
|
|
75
|
+
// Confirm structural equality via canonical comparison.
|
|
76
|
+
let stable = true;
|
|
77
|
+
const repToOld = new Map();
|
|
78
|
+
for (const [n, b] of newBlocks)
|
|
79
|
+
repToOld.set(b, node2block.get(n));
|
|
80
|
+
for (const [n, b] of newBlocks) {
|
|
81
|
+
if (repToOld.get(b) !== node2block.get(n)) {
|
|
82
|
+
stable = false;
|
|
83
|
+
break;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
if (stable) {
|
|
87
|
+
for (const [n, b] of newBlocks)
|
|
88
|
+
node2block.set(n, b);
|
|
89
|
+
break;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
for (const [n, b] of newBlocks)
|
|
93
|
+
node2block.set(n, b);
|
|
94
|
+
}
|
|
95
|
+
return node2block;
|
|
96
|
+
}
|
|
97
|
+
/** Two hypersets are bisimilar iff their roots are in the same partition class. */
|
|
98
|
+
export function bisimilar(g1, g2) {
|
|
99
|
+
// Build a combined graph with disjoint node-name spaces.
|
|
100
|
+
const tag1 = (n) => `A::${n}`;
|
|
101
|
+
const tag2 = (n) => `B::${n}`;
|
|
102
|
+
const nodes = [...g1.nodes.map(tag1), ...g2.nodes.map(tag2)];
|
|
103
|
+
const edges = new Map();
|
|
104
|
+
const labels = new Map();
|
|
105
|
+
for (const n of g1.nodes) {
|
|
106
|
+
const children = (g1.edges.get(n) ?? []).map(tag1);
|
|
107
|
+
edges.set(tag1(n), children);
|
|
108
|
+
const l = g1.labels?.get(n);
|
|
109
|
+
if (l !== undefined)
|
|
110
|
+
labels.set(tag1(n), l);
|
|
111
|
+
}
|
|
112
|
+
for (const n of g2.nodes) {
|
|
113
|
+
const children = (g2.edges.get(n) ?? []).map(tag2);
|
|
114
|
+
edges.set(tag2(n), children);
|
|
115
|
+
const l = g2.labels?.get(n);
|
|
116
|
+
if (l !== undefined)
|
|
117
|
+
labels.set(tag2(n), l);
|
|
118
|
+
}
|
|
119
|
+
const combined = { nodes, edges, root: tag1(g1.root), labels };
|
|
120
|
+
const part = bisimulationPartition(combined);
|
|
121
|
+
return part.get(tag1(g1.root)) === part.get(tag2(g2.root));
|
|
122
|
+
}
|
|
123
|
+
/** The Quine atom Ω with Ω = {Ω}. The canonical self-referential set. */
|
|
124
|
+
export function quineAtom(name = "Ω") {
|
|
125
|
+
return {
|
|
126
|
+
nodes: [name],
|
|
127
|
+
edges: new Map([[name, [name]]]),
|
|
128
|
+
root: name,
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
/** A "false belief" hyperset: a node whose only child is itself, labelled "LIAR". */
|
|
132
|
+
export function liarHyperset(name = "L") {
|
|
133
|
+
return {
|
|
134
|
+
nodes: [name],
|
|
135
|
+
edges: new Map([[name, [name]]]),
|
|
136
|
+
root: name,
|
|
137
|
+
labels: new Map([[name, "LIAR"]]),
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* Reflexive verifier: returns true if a hyperset is "trustworthy" — its
|
|
142
|
+
* canonical bisimulation class contains no labelled liar atoms.
|
|
143
|
+
* This is the AFA-style fix for PAIN-004: HONESTY GATE can audit itself
|
|
144
|
+
* by checking whether its own hyperset is bisimilar to a known LIAR
|
|
145
|
+
* class WITHOUT triggering Russell paradox (because bisimulation is
|
|
146
|
+
* sound on self-referential sets).
|
|
147
|
+
*/
|
|
148
|
+
export function isTrustworthy(h) {
|
|
149
|
+
const part = bisimulationPartition(h);
|
|
150
|
+
const rootBlock = part.get(h.root);
|
|
151
|
+
if (rootBlock === undefined)
|
|
152
|
+
return { trust: false, reason: "root not in partition" };
|
|
153
|
+
// Liar atoms have label "LIAR" by convention.
|
|
154
|
+
for (const [node, block] of part) {
|
|
155
|
+
if (block === rootBlock && h.labels?.get(node) === "LIAR") {
|
|
156
|
+
return { trust: false, reason: `root bisimilar to LIAR atom '${node}'` };
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
return { trust: true, reason: "no LIAR atom in root's bisimulation class" };
|
|
160
|
+
}
|
|
161
|
+
//# sourceMappingURL=aczel.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"aczel.js","sourceRoot":"","sources":["../../src/chronosheaf/aczel.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* v2.19.47 — CHRONOSHEAF P1 + P2 test suite.
|
|
3
|
+
*
|
|
4
|
+
* Every primitive gets:
|
|
5
|
+
* - canonical examples with hand-computed expected values
|
|
6
|
+
* - cross-vector invariants (algebraic identities the math demands)
|
|
7
|
+
* - 1000-iter fuzz where the primitive is randomised
|
|
8
|
+
*
|
|
9
|
+
* Total target: 60+ tests across 8 modules.
|
|
10
|
+
*/
|
|
11
|
+
export {};
|
|
12
|
+
//# sourceMappingURL=chronosheaf.test.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chronosheaf.test.d.ts","sourceRoot":"","sources":["../../src/chronosheaf/chronosheaf.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG"}
|
|
@@ -0,0 +1,360 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* v2.19.47 — CHRONOSHEAF P1 + P2 test suite.
|
|
3
|
+
*
|
|
4
|
+
* Every primitive gets:
|
|
5
|
+
* - canonical examples with hand-computed expected values
|
|
6
|
+
* - cross-vector invariants (algebraic identities the math demands)
|
|
7
|
+
* - 1000-iter fuzz where the primitive is randomised
|
|
8
|
+
*
|
|
9
|
+
* Total target: 60+ tests across 8 modules.
|
|
10
|
+
*/
|
|
11
|
+
import { describe, it, expect } from "vitest";
|
|
12
|
+
// ─── P1 pain_catalog ───────────────────────────────────────────────────
|
|
13
|
+
import { PAIN_CATALOG, catalogStats, painsForPrimitive, primitivesForPain } from "./pain_catalog.js";
|
|
14
|
+
describe("v2.19.47 CHRONOSHEAF P1 · pain_catalog", () => {
|
|
15
|
+
it("contains exactly 7 user-reported pains", () => {
|
|
16
|
+
expect(PAIN_CATALOG.length).toBe(7);
|
|
17
|
+
});
|
|
18
|
+
it("every pain has all required fields", () => {
|
|
19
|
+
for (const e of PAIN_CATALOG) {
|
|
20
|
+
expect(e.painId).toMatch(/^PAIN-\d{3}$/);
|
|
21
|
+
expect(typeof e.pain).toBe("string");
|
|
22
|
+
expect(typeof e.currentToolsSee).toBe("string");
|
|
23
|
+
expect(typeof e.whatTheyMiss).toBe("string");
|
|
24
|
+
expect(typeof e.topology).toBe("string");
|
|
25
|
+
expect(Array.isArray(e.primitives)).toBe(true);
|
|
26
|
+
expect(e.primitives.length).toBeGreaterThan(0);
|
|
27
|
+
}
|
|
28
|
+
});
|
|
29
|
+
it("painsForPrimitive returns every pain the primitive addresses", () => {
|
|
30
|
+
const sheafPains = painsForPrimitive("sheaf");
|
|
31
|
+
expect(sheafPains.length).toBeGreaterThan(0);
|
|
32
|
+
for (const p of sheafPains)
|
|
33
|
+
expect(p.primitives).toContain("sheaf");
|
|
34
|
+
});
|
|
35
|
+
it("primitivesForPain inverts correctly", () => {
|
|
36
|
+
expect(primitivesForPain("PAIN-001")).toContain("sheaf");
|
|
37
|
+
expect(primitivesForPain("NONEXISTENT")).toEqual([]);
|
|
38
|
+
});
|
|
39
|
+
it("catalogStats counts everything correctly", () => {
|
|
40
|
+
const s = catalogStats();
|
|
41
|
+
expect(s.totalPains).toBe(7);
|
|
42
|
+
expect(Object.keys(s.byTopology).length).toBeGreaterThan(0);
|
|
43
|
+
expect(s.primitiveLoad.length).toBeGreaterThan(0);
|
|
44
|
+
const total = s.primitiveLoad.reduce((acc, x) => acc + x.pains, 0);
|
|
45
|
+
let expected = 0;
|
|
46
|
+
for (const e of PAIN_CATALOG)
|
|
47
|
+
expected += e.primitives.length;
|
|
48
|
+
expect(total).toBe(expected);
|
|
49
|
+
});
|
|
50
|
+
});
|
|
51
|
+
// ─── P2-a sheaf cohomology ─────────────────────────────────────────────
|
|
52
|
+
import { delta0, delta1, isCocycle, cohomologyH1, gluingDiagnostic, } from "./sheaf.js";
|
|
53
|
+
describe("v2.19.47 CHRONOSHEAF P2-a · sheaf cohomology", () => {
|
|
54
|
+
it("tree cover (no cycle): H¹ = 0", () => {
|
|
55
|
+
const cover = {
|
|
56
|
+
sites: ["A", "B", "C"],
|
|
57
|
+
overlaps: [["A", "B"], ["B", "C"]],
|
|
58
|
+
};
|
|
59
|
+
const r = cohomologyH1(cover);
|
|
60
|
+
expect(r.h1).toBe(0);
|
|
61
|
+
expect(r.hasObstruction).toBe(false);
|
|
62
|
+
});
|
|
63
|
+
it("3-cycle without triple overlap: H¹ = 1 (the canonical obstruction)", () => {
|
|
64
|
+
const cover = {
|
|
65
|
+
sites: ["A", "B", "C"],
|
|
66
|
+
overlaps: [["A", "B"], ["B", "C"], ["A", "C"]],
|
|
67
|
+
};
|
|
68
|
+
const r = cohomologyH1(cover);
|
|
69
|
+
expect(r.h1).toBe(1);
|
|
70
|
+
expect(r.hasObstruction).toBe(true);
|
|
71
|
+
expect(r.obstructions.length).toBe(1);
|
|
72
|
+
});
|
|
73
|
+
it("3-cycle WITH triple overlap: H¹ = 0 (the triangle kills it)", () => {
|
|
74
|
+
const cover = {
|
|
75
|
+
sites: ["A", "B", "C"],
|
|
76
|
+
overlaps: [["A", "B"], ["B", "C"], ["A", "C"]],
|
|
77
|
+
triples: [["A", "B", "C"]],
|
|
78
|
+
};
|
|
79
|
+
const r = cohomologyH1(cover);
|
|
80
|
+
expect(r.h1).toBe(0);
|
|
81
|
+
});
|
|
82
|
+
it("delta0 of consistent claim values is zero everywhere", () => {
|
|
83
|
+
const cover = {
|
|
84
|
+
sites: ["A", "B", "C"],
|
|
85
|
+
overlaps: [["A", "B"], ["B", "C"]],
|
|
86
|
+
};
|
|
87
|
+
const sigma0 = new Map([["A", 5], ["B", 5], ["C", 5]]);
|
|
88
|
+
const d = delta0(cover, sigma0);
|
|
89
|
+
for (const v of d.values())
|
|
90
|
+
expect(v).toBe(0);
|
|
91
|
+
});
|
|
92
|
+
it("delta0 of inconsistent claim values is non-zero on the discordant pair", () => {
|
|
93
|
+
const cover = {
|
|
94
|
+
sites: ["A", "B"],
|
|
95
|
+
overlaps: [["A", "B"]],
|
|
96
|
+
};
|
|
97
|
+
const sigma0 = new Map([["A", 1], ["B", 3]]);
|
|
98
|
+
const d = delta0(cover, sigma0);
|
|
99
|
+
// Pair key is sorted lex: "A" + "B" → "AB". Value = b_B − b_A = 3 − 1 = 2.
|
|
100
|
+
const v = d.get("AB") ?? d.get("BA");
|
|
101
|
+
expect(v).toBe(2);
|
|
102
|
+
});
|
|
103
|
+
it("isCocycle returns true on tree cover with no triples", () => {
|
|
104
|
+
const cover = { sites: ["A", "B"], overlaps: [["A", "B"]] };
|
|
105
|
+
const sigma1 = new Map([["AB", 7]]);
|
|
106
|
+
expect(isCocycle(cover, sigma1)).toBe(true);
|
|
107
|
+
});
|
|
108
|
+
it("gluingDiagnostic reports H¹ and residual together", () => {
|
|
109
|
+
const cover = {
|
|
110
|
+
sites: ["A", "B", "C"],
|
|
111
|
+
overlaps: [["A", "B"], ["B", "C"], ["A", "C"]],
|
|
112
|
+
};
|
|
113
|
+
const claim = new Map([["A", 711], ["B", 711], ["C", 712]]);
|
|
114
|
+
const r = gluingDiagnostic(cover, claim);
|
|
115
|
+
expect(r.h1).toBe(1);
|
|
116
|
+
expect(r.residual.size).toBe(3);
|
|
117
|
+
});
|
|
118
|
+
it("delta1 on a triangle is the alternating sum", () => {
|
|
119
|
+
const cover = {
|
|
120
|
+
sites: ["A", "B", "C"],
|
|
121
|
+
overlaps: [["A", "B"], ["B", "C"], ["A", "C"]],
|
|
122
|
+
triples: [["A", "B", "C"]],
|
|
123
|
+
};
|
|
124
|
+
const sigma1 = new Map([["AB", 1], ["BC", 1], ["AC", 2]]);
|
|
125
|
+
const d = delta1(cover, sigma1);
|
|
126
|
+
expect(d.size).toBe(1);
|
|
127
|
+
const v = Array.from(d.values())[0];
|
|
128
|
+
expect(v).toBe(0); // 1 + 1 - 2 = 0
|
|
129
|
+
});
|
|
130
|
+
});
|
|
131
|
+
// ─── P2-b rg_flow ──────────────────────────────────────────────────────
|
|
132
|
+
import { rgStep, rgFixedPoint, classifyRelevance, smallestScaleForBudget } from "./rg_flow.js";
|
|
133
|
+
describe("v2.19.47 CHRONOSHEAF P2-b · RG flow", () => {
|
|
134
|
+
it("rgStep mean aggregator halves length and averages", () => {
|
|
135
|
+
const s = rgStep({ vector: [1, 3, 5, 7], scale: 0 }, { factor: 2, aggregator: "mean" });
|
|
136
|
+
expect(s.vector).toEqual([2, 6]);
|
|
137
|
+
expect(s.scale).toBe(1);
|
|
138
|
+
});
|
|
139
|
+
it("rgFixedPoint reaches scalar state in finite iterations", () => {
|
|
140
|
+
const r = rgFixedPoint({ vector: [1, 2, 3, 4, 5, 6, 7, 8], scale: 0 }, { factor: 2, aggregator: "sum" });
|
|
141
|
+
expect(r.reachedFixedPoint).toBe(true);
|
|
142
|
+
expect(r.state.vector.length).toBeLessThanOrEqual(1);
|
|
143
|
+
});
|
|
144
|
+
it("classifyRelevance labels constant vector — mean shrinks L2 norm → irrelevant", () => {
|
|
145
|
+
const r = classifyRelevance({ vector: [1, 1, 1, 1], scale: 0 }, { factor: 2, aggregator: "mean" }, [1, 1, 1, 1]);
|
|
146
|
+
// [1,1,1,1] mean → [1,1] mean → [1]. L2 norms: 2 → √2 → 1 → ratio < 1 → irrelevant.
|
|
147
|
+
expect(["irrelevant", "marginal"]).toContain(r.class);
|
|
148
|
+
});
|
|
149
|
+
it("classifyRelevance labels constant vector under SUM → relevant (L2 grows)", () => {
|
|
150
|
+
const r = classifyRelevance({ vector: [1, 1, 1, 1], scale: 0 }, { factor: 2, aggregator: "sum" }, [1, 1, 1, 1]);
|
|
151
|
+
// sum: [1,1,1,1] → [2,2] → [4]. L2 norms: 2 → 2√2 → 4 → growth ratio > 1 → relevant.
|
|
152
|
+
expect(["relevant", "marginal"]).toContain(r.class);
|
|
153
|
+
});
|
|
154
|
+
it("smallestScaleForBudget returns state with size ≤ target", () => {
|
|
155
|
+
const r = smallestScaleForBudget({ vector: [1, 2, 3, 4, 5, 6, 7, 8], scale: 0 }, { factor: 2, aggregator: "mean" }, 2);
|
|
156
|
+
expect(r.state.vector.length).toBeLessThanOrEqual(2);
|
|
157
|
+
});
|
|
158
|
+
});
|
|
159
|
+
// ─── P2-c persistence ──────────────────────────────────────────────────
|
|
160
|
+
import { persistentHomology0, bottleneckDistance } from "./persistence.js";
|
|
161
|
+
describe("v2.19.47 CHRONOSHEAF P2-c · persistent homology", () => {
|
|
162
|
+
it("two isolated vertices → 2 essential 0-classes", () => {
|
|
163
|
+
const filt = [{ value: 0, add: [["x"], ["y"]] }];
|
|
164
|
+
const pd = persistentHomology0(filt);
|
|
165
|
+
expect(pd.essentialByDim[0]).toBe(2);
|
|
166
|
+
});
|
|
167
|
+
it("vertices then edge → 1 essential, 1 finite-persistence pair", () => {
|
|
168
|
+
const filt = [
|
|
169
|
+
{ value: 0, add: [["x"], ["y"]] },
|
|
170
|
+
{ value: 1, add: [["x", "y"]] },
|
|
171
|
+
];
|
|
172
|
+
const pd = persistentHomology0(filt);
|
|
173
|
+
expect(pd.essentialByDim[0]).toBe(1);
|
|
174
|
+
const finite = pd.pairs.filter((p) => isFinite(p.persistence));
|
|
175
|
+
expect(finite.length).toBe(1);
|
|
176
|
+
expect(finite[0].persistence).toBe(1);
|
|
177
|
+
});
|
|
178
|
+
it("bottleneckDistance is 0 between identical diagrams", () => {
|
|
179
|
+
const filt = [
|
|
180
|
+
{ value: 0, add: [["a"], ["b"]] },
|
|
181
|
+
{ value: 1, add: [["a", "b"]] },
|
|
182
|
+
];
|
|
183
|
+
const a = persistentHomology0(filt);
|
|
184
|
+
const b = persistentHomology0(filt);
|
|
185
|
+
expect(bottleneckDistance(a, b)).toBe(0);
|
|
186
|
+
});
|
|
187
|
+
});
|
|
188
|
+
// ─── P2-d free_energy ──────────────────────────────────────────────────
|
|
189
|
+
import { klDivergence, entropy, variationalFreeEnergy, selectAction, confidenceToPosterior, normalise, } from "./free_energy.js";
|
|
190
|
+
describe("v2.19.47 CHRONOSHEAF P2-d · free energy", () => {
|
|
191
|
+
it("KL(p ‖ p) = 0", () => {
|
|
192
|
+
const p = normalise([1, 2, 3]);
|
|
193
|
+
expect(klDivergence(p, p)).toBeCloseTo(0, 9);
|
|
194
|
+
});
|
|
195
|
+
it("entropy of uniform = log(n)", () => {
|
|
196
|
+
const p = normalise([1, 1, 1, 1]);
|
|
197
|
+
expect(entropy(p)).toBeCloseTo(Math.log(4), 9);
|
|
198
|
+
});
|
|
199
|
+
it("variational F is finite for valid inputs", () => {
|
|
200
|
+
const q = normalise([0.7, 0.3]);
|
|
201
|
+
const prior = normalise([0.5, 0.5]);
|
|
202
|
+
const logLik = [Math.log(0.9), Math.log(0.1)];
|
|
203
|
+
const F = variationalFreeEnergy(q, prior, logLik);
|
|
204
|
+
expect(Number.isFinite(F)).toBe(true);
|
|
205
|
+
});
|
|
206
|
+
it("selectAction picks the candidate with minimal G", () => {
|
|
207
|
+
const scoring = { preferredObs: normalise([0.9, 0.1]), priorZ: normalise([0.5, 0.5]) };
|
|
208
|
+
const candidates = [
|
|
209
|
+
{ id: "good", predictedObs: normalise([0.85, 0.15]), predictedQz: normalise([0.7, 0.3]) },
|
|
210
|
+
{ id: "bad", predictedObs: normalise([0.1, 0.9]), predictedQz: normalise([0.5, 0.5]) },
|
|
211
|
+
];
|
|
212
|
+
const r = selectAction(candidates, scoring);
|
|
213
|
+
expect(r.winner.id).toBe("good");
|
|
214
|
+
});
|
|
215
|
+
it("confidenceToPosterior turns 0.6 into a Beta posterior mean near 0.6", () => {
|
|
216
|
+
const r = confidenceToPosterior(0.6, 100);
|
|
217
|
+
expect(r.posterior[0]).toBeGreaterThan(0.55);
|
|
218
|
+
expect(r.posterior[0]).toBeLessThan(0.65);
|
|
219
|
+
expect(r.entropyBits).toBeGreaterThan(0);
|
|
220
|
+
});
|
|
221
|
+
});
|
|
222
|
+
// ─── P2-e wasserstein ──────────────────────────────────────────────────
|
|
223
|
+
import { wasserstein1D, sinkhorn, catalogDrift } from "./wasserstein.js";
|
|
224
|
+
describe("v2.19.47 CHRONOSHEAF P2-e · wasserstein", () => {
|
|
225
|
+
it("W_1 between identical distributions = 0", () => {
|
|
226
|
+
const mu = new Map([["0", 0.5], ["1", 0.5]]);
|
|
227
|
+
expect(wasserstein1D(mu, mu)).toBe(0);
|
|
228
|
+
});
|
|
229
|
+
it("W_1 between point masses at 0 and 1 = 1", () => {
|
|
230
|
+
const mu = new Map([["0", 1]]);
|
|
231
|
+
const nu = new Map([["1", 1]]);
|
|
232
|
+
expect(wasserstein1D(mu, nu)).toBeCloseTo(1, 9);
|
|
233
|
+
});
|
|
234
|
+
it("sinkhorn returns a coupling with given marginals (approximately)", () => {
|
|
235
|
+
const mu = [0.5, 0.5];
|
|
236
|
+
const nu = [0.5, 0.5];
|
|
237
|
+
const C = [[0, 1], [1, 0]];
|
|
238
|
+
const r = sinkhorn(mu, nu, C, { epsilon: 0.1, maxIter: 200 });
|
|
239
|
+
expect(r.iterations).toBeGreaterThan(0);
|
|
240
|
+
// Row sums approximately match mu.
|
|
241
|
+
for (let i = 0; i < mu.length; i++) {
|
|
242
|
+
const rowSum = r.coupling[i].reduce((a, x) => a + x, 0);
|
|
243
|
+
expect(Math.abs(rowSum - mu[i])).toBeLessThan(0.01);
|
|
244
|
+
}
|
|
245
|
+
});
|
|
246
|
+
it("catalogDrift = 0 between identical snapshots", () => {
|
|
247
|
+
const snap = ["mneme.x.y", "mneme.a.b"];
|
|
248
|
+
expect(catalogDrift(snap, snap)).toBe(0);
|
|
249
|
+
});
|
|
250
|
+
it("catalogDrift > 0 between disjoint family snapshots", () => {
|
|
251
|
+
const a = ["mneme.x.y"];
|
|
252
|
+
const b = ["mneme.z.w"];
|
|
253
|
+
expect(catalogDrift(a, b)).toBeGreaterThan(0);
|
|
254
|
+
});
|
|
255
|
+
});
|
|
256
|
+
// ─── P2-f tropical ─────────────────────────────────────────────────────
|
|
257
|
+
import { tropicalAdd, tropicalMul, tropicalLongestPath, verifierChainConfidence, } from "./tropical.js";
|
|
258
|
+
describe("v2.19.47 CHRONOSHEAF P2-f · tropical semiring", () => {
|
|
259
|
+
it("tropical add = max, mul = sum", () => {
|
|
260
|
+
expect(tropicalAdd(3, 5)).toBe(5);
|
|
261
|
+
expect(tropicalMul(3, 5)).toBe(8);
|
|
262
|
+
});
|
|
263
|
+
it("longest path through a 3-node chain returns sum of edge weights", () => {
|
|
264
|
+
const g = {
|
|
265
|
+
nodes: ["A", "B", "C"],
|
|
266
|
+
edges: new Map([
|
|
267
|
+
["A", [{ to: "B", weight: 2, label: "AB" }]],
|
|
268
|
+
["B", [{ to: "C", weight: 3, label: "BC" }]],
|
|
269
|
+
]),
|
|
270
|
+
};
|
|
271
|
+
const r = tropicalLongestPath(g, "A", "C");
|
|
272
|
+
expect(r).toBeTruthy();
|
|
273
|
+
expect(r.value).toBe(5);
|
|
274
|
+
expect(r.path).toEqual(["A", "B", "C"]);
|
|
275
|
+
expect(r.criticalEdge?.label).toBe("AB"); // smaller weight
|
|
276
|
+
});
|
|
277
|
+
it("verifierChainConfidence is the min + identifies critical verifier", () => {
|
|
278
|
+
const r = verifierChainConfidence([
|
|
279
|
+
{ id: "a", confidence: 0.9 },
|
|
280
|
+
{ id: "b", confidence: 0.6 },
|
|
281
|
+
{ id: "c", confidence: 0.95 },
|
|
282
|
+
]);
|
|
283
|
+
expect(r.chainConfidence).toBe(0.6);
|
|
284
|
+
expect(r.criticalVerifier?.id).toBe("b");
|
|
285
|
+
});
|
|
286
|
+
it("empty chain returns confidence 1 + null critical", () => {
|
|
287
|
+
const r = verifierChainConfidence([]);
|
|
288
|
+
expect(r.chainConfidence).toBe(1);
|
|
289
|
+
expect(r.criticalVerifier).toBeNull();
|
|
290
|
+
});
|
|
291
|
+
});
|
|
292
|
+
// ─── P2-g aczel ────────────────────────────────────────────────────────
|
|
293
|
+
import { bisimulationPartition, bisimilar, quineAtom, liarHyperset, isTrustworthy } from "./aczel.js";
|
|
294
|
+
describe("v2.19.47 CHRONOSHEAF P2-g · Aczel anti-foundation", () => {
|
|
295
|
+
it("two Quine atoms are bisimilar", () => {
|
|
296
|
+
const a = quineAtom("X");
|
|
297
|
+
const b = quineAtom("Y");
|
|
298
|
+
expect(bisimilar(a, b)).toBe(true);
|
|
299
|
+
});
|
|
300
|
+
it("Quine atom ≠ labelled LIAR atom (different labels disambiguate)", () => {
|
|
301
|
+
const q = quineAtom("Q");
|
|
302
|
+
const l = liarHyperset("L");
|
|
303
|
+
expect(bisimilar(q, l)).toBe(false);
|
|
304
|
+
});
|
|
305
|
+
it("isTrustworthy returns true for an unlabelled Quine atom", () => {
|
|
306
|
+
const q = quineAtom();
|
|
307
|
+
const r = isTrustworthy(q);
|
|
308
|
+
expect(r.trust).toBe(true);
|
|
309
|
+
});
|
|
310
|
+
it("isTrustworthy returns false for a LIAR hyperset", () => {
|
|
311
|
+
const l = liarHyperset();
|
|
312
|
+
const r = isTrustworthy(l);
|
|
313
|
+
expect(r.trust).toBe(false);
|
|
314
|
+
expect(r.reason).toContain("LIAR");
|
|
315
|
+
});
|
|
316
|
+
it("bisimulationPartition on a singleton labelled graph yields 1 class", () => {
|
|
317
|
+
const h = quineAtom();
|
|
318
|
+
const p = bisimulationPartition(h);
|
|
319
|
+
expect(new Set(p.values()).size).toBe(1);
|
|
320
|
+
});
|
|
321
|
+
});
|
|
322
|
+
// ─── 1000-iter fuzz ────────────────────────────────────────────────────
|
|
323
|
+
describe("v2.19.47 CHRONOSHEAF · 1000-iter cross-primitive fuzz", () => {
|
|
324
|
+
it("sheaf cohomologyH1 never throws on random small covers", () => {
|
|
325
|
+
for (let i = 0; i < 1000; i++) {
|
|
326
|
+
const n = 3 + (i % 5);
|
|
327
|
+
const sites = [];
|
|
328
|
+
for (let k = 0; k < n; k++)
|
|
329
|
+
sites.push(`S${k}`);
|
|
330
|
+
const overlaps = [];
|
|
331
|
+
for (let a = 0; a < n; a++)
|
|
332
|
+
for (let b = a + 1; b < n; b++) {
|
|
333
|
+
if (Math.random() < 0.5)
|
|
334
|
+
overlaps.push([sites[a], sites[b]]);
|
|
335
|
+
}
|
|
336
|
+
expect(() => cohomologyH1({ sites, overlaps })).not.toThrow();
|
|
337
|
+
}
|
|
338
|
+
});
|
|
339
|
+
it("RG flow never throws on random vectors", () => {
|
|
340
|
+
for (let i = 0; i < 200; i++) {
|
|
341
|
+
const len = 1 + (i % 32);
|
|
342
|
+
const vector = Array.from({ length: len }, () => Math.random() * 100);
|
|
343
|
+
expect(() => rgFixedPoint({ vector, scale: 0 }, { factor: 2, aggregator: "mean" }, 20)).not.toThrow();
|
|
344
|
+
}
|
|
345
|
+
});
|
|
346
|
+
it("free_energy.selectAction never throws on random candidate sets", () => {
|
|
347
|
+
for (let i = 0; i < 200; i++) {
|
|
348
|
+
const supportSize = 2 + (i % 4);
|
|
349
|
+
const rand = () => Array.from({ length: supportSize }, () => Math.random());
|
|
350
|
+
const cands = Array.from({ length: 3 }, (_, k) => ({
|
|
351
|
+
id: `c${k}`,
|
|
352
|
+
predictedObs: normalise(rand()),
|
|
353
|
+
predictedQz: normalise(rand()),
|
|
354
|
+
}));
|
|
355
|
+
const scoring = { preferredObs: normalise(rand()), priorZ: normalise(rand()) };
|
|
356
|
+
expect(() => selectAction(cands, scoring)).not.toThrow();
|
|
357
|
+
}
|
|
358
|
+
});
|
|
359
|
+
});
|
|
360
|
+
//# sourceMappingURL=chronosheaf.test.js.map
|