@lapxo/obligations 0.3.5 → 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.
Files changed (45) hide show
  1. package/README.md +8 -143
  2. package/TARGET.bound +574 -507
  3. package/dist/measures/error-events.d.ts +27 -0
  4. package/dist/measures/error-events.js +43 -0
  5. package/dist/measures/experiments.d.ts +15 -0
  6. package/dist/measures/experiments.js +53 -0
  7. package/dist/measures/fitting.d.ts +243 -0
  8. package/dist/measures/fitting.js +115 -0
  9. package/dist/measures/identification.d.ts +156 -0
  10. package/dist/measures/identification.js +107 -0
  11. package/dist/measures/index.d.ts +18 -0
  12. package/dist/measures/index.js +9 -0
  13. package/dist/measures/m3-experiment.d.ts +69 -0
  14. package/dist/measures/m3-experiment.js +70 -0
  15. package/dist/measures/m3.d.ts +139 -0
  16. package/dist/measures/m3.js +181 -0
  17. package/dist/measures/model.d.ts +14 -0
  18. package/dist/measures/model.js +67 -0
  19. package/dist/measures/rational.d.ts +19 -0
  20. package/dist/measures/rational.js +53 -0
  21. package/dist/measures/spectrum.d.ts +22 -0
  22. package/dist/measures/spectrum.js +84 -0
  23. package/docs/measures.md +149 -0
  24. package/package.json +1 -93
  25. package/receipts.bound +75 -0
  26. package/samples/measures/descent.json +92 -0
  27. package/samples/measures/m3-reader.mjs +732 -0
  28. package/samples/measures/m3.json +3126 -0
  29. package/samples/measures/observations.json +212 -0
  30. package/samples/measures/reader.mjs +424 -0
  31. package/samples/measures/spectrum.json +6530 -0
  32. package/samples/measures/unanimity.json +76 -0
  33. package/samples/no/installed-artifact.json +302 -0
  34. package/samples/yes/algebra-is-closed.json +17 -0
  35. package/samples/yes/field-uses-price-and-debit.json +9 -0
  36. package/samples/yes/installed-artifact.json +397 -0
  37. package/samples/yes/three-theories-one-algebra.json +5 -0
  38. package/src/field/motion.ts +59 -0
  39. package/src/lattice/index.ts +79 -0
  40. package/vectors/measures/descent.cli.json +148 -0
  41. package/vectors/measures/installed-artifact.cli.json +43 -0
  42. package/vectors/measures/m3.cli.json +148 -0
  43. package/vectors/measures/observations.cli.json +148 -0
  44. package/vectors/measures/spectrum.cli.json +148 -0
  45. package/vectors/measures/unanimity.cli.json +148 -0
@@ -0,0 +1,67 @@
1
+ function valid({ c, p, n }) {
2
+ if (!Number.isFinite(c) || c < 0 || c > 1 || !Number.isFinite(p) || p < 0 || p > 1 || !Number.isSafeInteger(n) || n < 2)
3
+ throw new Error('REFUSE·measure invalid unanimity model');
4
+ }
5
+ function logSum(a, b) { const high = Math.max(a, b); return high === -Infinity ? high : high + Math.log(Math.exp(a - high) + Math.exp(b - high)); }
6
+ export function unanimityFloor(model, k) {
7
+ valid(model);
8
+ if (!Number.isSafeInteger(k) || k < 1)
9
+ throw new Error('REFUSE·measure invalid witness count');
10
+ const { c, p, n } = model;
11
+ if (c === 1 || p === 1)
12
+ return { status: 'measured', value: 1 };
13
+ if (p === 0)
14
+ return { status: 'measured', value: c };
15
+ const logPrivate = Math.log1p(-c) + k * Math.log(p) + (1 - k) * Math.log(n - 1);
16
+ const logA = logSum(c === 0 ? -Infinity : Math.log(c), logPrivate), logB = Math.log1p(-c) + k * Math.log1p(-p);
17
+ const odds = logA - logB;
18
+ const value = odds >= 0 ? 1 / (1 + Math.exp(-odds)) : Math.exp(odds) / (1 + Math.exp(odds));
19
+ return { status: 'measured', value };
20
+ }
21
+ export function unanimityThreshold(model, searchLimit) {
22
+ valid(model);
23
+ if (!Number.isSafeInteger(searchLimit) || searchLimit < 1)
24
+ throw new Error('REFUSE·measure invalid search budget');
25
+ const { c, p, n } = model, q = p / (n - 1), coefficient = 1 - p - q;
26
+ if (c === 1 || p === 0 || p === 1 || coefficient <= 0)
27
+ return { status: 'measured', value: 1 };
28
+ if (c === 0)
29
+ return { status: 'unmeasured', cause: 'no finite nondecreasing threshold for this model' };
30
+ const right = Math.log(p) + Math.log(c), base = Math.log(coefficient) + Math.log1p(-c) + Math.log(n - 1);
31
+ for (let k = 1; k <= searchLimit; k++)
32
+ if (base + k * Math.log(q) <= right)
33
+ return { status: 'measured', value: k };
34
+ return { status: 'unmeasured', cause: 'threshold outside declared search budget' };
35
+ }
36
+ export function descentCount(graph, cell) {
37
+ const nodes = new Map();
38
+ for (const node of graph) {
39
+ if (!node.scope || nodes.has(node.scope))
40
+ throw new Error('REFUSE·measure duplicate or absent graph scope');
41
+ nodes.set(node.scope, [...new Set(node.restsOn)]);
42
+ }
43
+ if (!nodes.has(cell) || [...nodes.values()].some(parents => parents.some(parent => !nodes.has(parent))))
44
+ return { status: 'unmeasured', cause: 'incomplete declared descent graph' };
45
+ const seen = new Map(), visiting = new Set();
46
+ function reaches(scope) {
47
+ if (visiting.has(scope))
48
+ throw new Error('REFUSE·measure cyclic descent at ' + scope);
49
+ if (seen.has(scope))
50
+ return seen.get(scope);
51
+ visiting.add(scope);
52
+ let result = false;
53
+ for (const parent of nodes.get(scope)) {
54
+ const nested = reaches(parent);
55
+ result = result || parent === cell || nested;
56
+ }
57
+ visiting.delete(scope);
58
+ seen.set(scope, result);
59
+ return result;
60
+ }
61
+ let count = 0;
62
+ for (const scope of nodes.keys())
63
+ if (reaches(scope) && scope !== cell)
64
+ count++;
65
+ return { status: 'measured', value: count };
66
+ }
67
+ export const modelRequired = (measure) => ({ status: 'unmeasured', cause: 'declared model required for ' + measure });
@@ -0,0 +1,19 @@
1
+ export type Rational = Readonly<{
2
+ numerator: string;
3
+ denominator: string;
4
+ }>;
5
+ export type RationalInput = string | Rational;
6
+ export type Q = readonly [bigint, bigint];
7
+ export declare const zero: Q, one: Q;
8
+ export declare const refuse: (cause: string) => never;
9
+ export declare function q(a: bigint, b?: bigint): Q;
10
+ export declare function rational(input: RationalInput): Q;
11
+ export declare const add: (a: Q, b: Q) => Q;
12
+ export declare const sub: (a: Q, b: Q) => Q;
13
+ export declare const mul: (a: Q, b: Q) => Q;
14
+ export declare const div: (a: Q, b: Q) => Q;
15
+ export declare const pow: (a: Q, n: number) => Q;
16
+ export declare const equal: (a: Q, b: Q) => boolean;
17
+ export declare const pack: (a: Q) => Rational;
18
+ export declare function probability(input: RationalInput): Q;
19
+ export declare function roundHalfEven(input: RationalInput, digits: number): string;
@@ -0,0 +1,53 @@
1
+ export const zero = [0n, 1n], one = [1n, 1n];
2
+ export const refuse = (cause) => { throw new Error('REFUSE·model/M3 ' + cause); };
3
+ const gcd = (a, b) => { a = a < 0n ? -a : a; while (b) {
4
+ const r = a % b;
5
+ a = b;
6
+ b = r;
7
+ } return a; };
8
+ export function q(a, b = 1n) {
9
+ if (b === 0n)
10
+ refuse('zero rational denominator');
11
+ if (b < 0n) {
12
+ a = -a;
13
+ b = -b;
14
+ }
15
+ const d = gcd(a, b);
16
+ return [a / d, b / d];
17
+ }
18
+ export function rational(input) {
19
+ if (typeof input === 'string') {
20
+ if (/^-?\d+\/\d+$/.test(input)) {
21
+ const [a, b] = input.split('/');
22
+ return q(BigInt(a), BigInt(b));
23
+ }
24
+ if (!/^-?\d+(\.\d+)?$/.test(input))
25
+ refuse('invalid exact probability');
26
+ const sign = input.startsWith('-') ? -1n : 1n, text = input.replace(/^-/, '');
27
+ const [whole, part = ''] = text.split('.');
28
+ return q(sign * BigInt(whole + part), 10n ** BigInt(part.length));
29
+ }
30
+ if (!input || typeof input.numerator !== 'string' || typeof input.denominator !== 'string' || !/^[-]?\d+$/.test(input.numerator) || !/^\d+$/.test(input.denominator))
31
+ refuse('invalid rational');
32
+ return q(BigInt(input.numerator), BigInt(input.denominator));
33
+ }
34
+ export const add = (a, b) => q(a[0] * b[1] + b[0] * a[1], a[1] * b[1]);
35
+ export const sub = (a, b) => q(a[0] * b[1] - b[0] * a[1], a[1] * b[1]);
36
+ export const mul = (a, b) => q(a[0] * b[0], a[1] * b[1]);
37
+ export const div = (a, b) => q(a[0] * b[1], a[1] * b[0]);
38
+ export const pow = (a, n) => q(a[0] ** BigInt(n), a[1] ** BigInt(n));
39
+ export const equal = (a, b) => a[0] === b[0] && a[1] === b[1];
40
+ export const pack = (a) => ({ numerator: String(a[0]), denominator: String(a[1]) });
41
+ export function probability(input) { const a = rational(input); if (a[0] < 0n || a[0] > a[1])
42
+ refuse('probability outside 0..1'); return a; }
43
+ export function roundHalfEven(input, digits) {
44
+ if (!Number.isSafeInteger(digits) || digits < 0)
45
+ refuse('invalid decimal digits');
46
+ const [a, b] = rational(input), scale = 10n ** BigInt(digits), absolute = a < 0n ? -a : a;
47
+ let integer = absolute * scale / b;
48
+ const remainder = absolute * scale % b;
49
+ if (2n * remainder > b || (2n * remainder === b && integer % 2n === 1n))
50
+ integer++;
51
+ const text = String(integer).padStart(digits + 1, '0'), prefix = a < 0n && integer !== 0n ? '-' : '';
52
+ return prefix + (digits ? text.slice(0, -digits) + '.' + text.slice(-digits) : text);
53
+ }
@@ -0,0 +1,22 @@
1
+ import type { Covariance, Scalar, Unmeasured } from './error-events.ts';
2
+ export type NumericalPolicy = Readonly<{
3
+ absolute: number;
4
+ relative: number;
5
+ maxRotations: number;
6
+ }>;
7
+ export type Spectrum = Readonly<{
8
+ status: 'measured';
9
+ origins: readonly string[];
10
+ values: readonly number[];
11
+ vectors: readonly (readonly number[])[];
12
+ tolerance: number;
13
+ residual: number;
14
+ }>;
15
+ export declare function spectrum(reading: Covariance | Unmeasured, policy: NumericalPolicy): Spectrum | Unmeasured;
16
+ export declare function commonMass(reading: Spectrum | Unmeasured): Scalar;
17
+ export declare function loadings(reading: Spectrum | Unmeasured): Readonly<{
18
+ status: 'measured';
19
+ origins: readonly string[];
20
+ values: readonly number[];
21
+ }> | Unmeasured;
22
+ export declare function commonMassOf(reading: Spectrum | Unmeasured, origins: readonly string[], tau: number): Scalar;
@@ -0,0 +1,84 @@
1
+ const refuse = (cause) => { throw new Error('REFUSE·measure ' + cause); };
2
+ export function spectrum(reading, policy) {
3
+ if (reading.status === 'unmeasured')
4
+ return reading;
5
+ if (!Number.isFinite(policy.absolute) || policy.absolute <= 0 || !Number.isFinite(policy.relative) || policy.relative < 0 || !Number.isSafeInteger(policy.maxRotations) || policy.maxRotations < 1)
6
+ refuse('invalid numerical policy');
7
+ const n = reading.origins.length, original = reading.matrix;
8
+ if (!n || original.length !== n || original.some(row => row.length !== n || row.some(x => !Number.isFinite(x))))
9
+ refuse('invalid covariance matrix');
10
+ const scale = Math.max(...original.flat().map(Math.abs)), tolerance = policy.absolute + policy.relative * scale;
11
+ for (let i = 0; i < n; i++)
12
+ for (let j = 0; j < n; j++)
13
+ if (original[i][j] !== original[j][i])
14
+ refuse('nonsymmetric covariance');
15
+ const a = original.map(row => [...row]), v = Array.from({ length: n }, (_, i) => Array.from({ length: n }, (_, j) => i === j ? 1 : 0));
16
+ for (let step = 0; step < policy.maxRotations; step++) {
17
+ let p = 0, q = 0, largest = 0;
18
+ for (let i = 0; i < n; i++)
19
+ for (let j = i + 1; j < n; j++)
20
+ if (Math.abs(a[i][j]) > largest) {
21
+ largest = Math.abs(a[i][j]);
22
+ p = i;
23
+ q = j;
24
+ }
25
+ if (largest <= tolerance)
26
+ break;
27
+ const theta = .5 * Math.atan2(2 * a[p][q], a[q][q] - a[p][p]), c = Math.cos(theta), s = Math.sin(theta);
28
+ const pp = a[p][p], qq = a[q][q], pq = a[p][q];
29
+ for (let k = 0; k < n; k++)
30
+ if (k !== p && k !== q) {
31
+ const x = a[k][p], y = a[k][q];
32
+ a[k][p] = a[p][k] = c * x - s * y;
33
+ a[k][q] = a[q][k] = s * x + c * y;
34
+ }
35
+ a[p][p] = c * c * pp - 2 * s * c * pq + s * s * qq;
36
+ a[q][q] = s * s * pp + 2 * s * c * pq + c * c * qq;
37
+ a[p][q] = a[q][p] = 0;
38
+ for (let k = 0; k < n; k++) {
39
+ const x = v[k][p], y = v[k][q];
40
+ v[k][p] = c * x - s * y;
41
+ v[k][q] = s * x + c * y;
42
+ }
43
+ }
44
+ const order = Array.from({ length: n }, (_, i) => i).sort((i, j) => a[j][j] - a[i][i] || i - j);
45
+ const raw = order.map(i => a[i][i]);
46
+ if (raw.some(x => x < -tolerance))
47
+ refuse('covariance is not positive semidefinite');
48
+ const values = raw.map(x => Math.max(0, x)), vectors = order.map(i => v.map(row => row[i]));
49
+ const residual = Math.max(...vectors.map((vector, i) => Math.hypot(...original.map((row, j) => row.reduce((sum, x, k) => sum + x * vector[k], 0) - values[i] * vector[j]))));
50
+ if (residual > n * tolerance)
51
+ return { status: 'unmeasured', cause: 'eigensolver did not converge within declared budget' };
52
+ return { status: 'measured', origins: reading.origins, values, vectors, tolerance, residual };
53
+ }
54
+ export function commonMass(reading) {
55
+ if (reading.status === 'unmeasured')
56
+ return reading;
57
+ const total = reading.values.reduce((sum, x) => sum + x, 0);
58
+ return total <= reading.tolerance ? { status: 'unmeasured', cause: 'no resolved variation' } : { status: 'measured', value: reading.values[0] / total };
59
+ }
60
+ export function loadings(reading) {
61
+ if (reading.status === 'unmeasured')
62
+ return reading;
63
+ if (reading.values[0] <= reading.tolerance || (reading.values.length > 1 && reading.values[0] - reading.values[1] <= 2 * reading.tolerance))
64
+ return { status: 'unmeasured', cause: 'top eigenspace is unresolved or repeated' };
65
+ return { status: 'measured', origins: reading.origins, values: reading.vectors[0].map(Math.abs) };
66
+ }
67
+ export function commonMassOf(reading, origins, tau) {
68
+ if (reading.status === 'unmeasured')
69
+ return reading;
70
+ if (!Number.isFinite(tau) || tau <= 0 || tau > 1)
71
+ refuse('invalid spectral threshold');
72
+ const selected = [...new Set(origins)].map(origin => reading.origins.indexOf(origin));
73
+ if (!selected.length || selected.some(i => i < 0))
74
+ return { status: 'unmeasured', cause: 'subset not observed' };
75
+ const energy = reading.values.map((value, k) => value * selected.reduce((sum, i) => sum + reading.vectors[k][i] ** 2, 0));
76
+ const total = energy.reduce((sum, x) => sum + x, 0);
77
+ if (total <= reading.tolerance)
78
+ return { status: 'unmeasured', cause: 'no resolved subset variation' };
79
+ const cutoff = tau * reading.values[0];
80
+ if (reading.values.some(value => Math.abs(value - cutoff) <= 2 * reading.tolerance) && tau !== 1)
81
+ return { status: 'unmeasured', cause: 'spectral threshold unresolved at tolerance' };
82
+ const common = energy.reduce((sum, x, k) => sum + (reading.values[k] >= cutoff - 2 * reading.tolerance ? x : 0), 0);
83
+ return { status: 'measured', value: common / total };
84
+ }
@@ -0,0 +1,149 @@
1
+ # Measures beside the states
2
+
3
+ The pure API @lapxo/obligations/measures does not change FREE, REQUIRED, FORBIDDEN or CONFLICT. Observed association never establishes independence.
4
+
5
+ ## Descriptive contract
6
+ errorMatrix takes explicit binary event/origin/error rows and minCells >= 2. Identical redelivery is idempotent; conflicting observations refuse; incomplete shared events are unmeasured. covariance is population covariance of the handed rows, divided by their event count. participationRatio describes effective rank; zero variation is unmeasured.
7
+
8
+ spectrum requires absolute, relative and maxRotations. Asymmetric or materially non-PSD matrices refuse. commonMass is the largest observed variance fraction, not a probability of false agreement. loadings require an isolated top eigenvalue; repeated eigenspaces have no unique top loading. commonMassOf requires an explicit cutoff and whole eigenspaces. The unanimity no-sample prints observed commonMass >= 0.5 beside FREE, without claiming strength.
9
+
10
+ descentCount counts distinct proper descendants in a declared restsOn graph. Identical edges add nothing. Missing declarations remain unmeasured; duplicate node declarations and cycles refuse. Declared descent is not observed activity or independence.
11
+
12
+ ## Controlled procedures
13
+ unanimityFloor and unanimityThreshold implement the declared T1 special case. With P_k=(1-c)p^k(n-1)^(1-k), F_k=(c+P_k)/(c+P_k+(1-c)(1-p)^k). For nondegenerate parameters, F_(k+1) >= F_k iff p*c >= (1-p-p/(n-1))*P_k. The c=.01,p=.1,n=2 no-sample decreases before k=3; its threshold is 3. dissentExperiment and interestExperiment report conditional counts under explicitly handed generators: xorshift32, nonzero seed and trial count. Their denominators are events and falseEvents, and zero events are unmeasured. Interest is an explicitly handed bias toward one wrong value, not inferred from a missing observation. E3: a school answers truth with probability q, otherwise its own wrong value. These are controlled procedures, never laws or state changes.
14
+
15
+ ## Native publication evidence
16
+ observations, spectrum, unanimity and descent each have yes/no cases in samples/measures/<group>.json and installed-instrument captures in vectors/measures/<group>.cli.json. M/3 has samples/measures/m3.json and vectors/measures/m3.cli.json. Each vector ran on two independent places, repeated the positive reading byte-for-byte and refused its negative by name. State-preservation tests compare all four actual algebraic states before and after measurements.
17
+
18
+ ## Model boundary
19
+ M/3 below is the only reference model. The older descriptive D/commonMass and independence claims are superseded. modelRequired returns unmeasured for an absent model; no measurement silently supplies a causal model. Factor attribution, dissent and probe results are conditional on M/3's handed parameters, not empirical independence certificates.
20
+
21
+ # obligations 0.4.0 — model M/3 (authoritative contract)
22
+
23
+ M/3 is the reference conditional model shipped beside the descriptive measures. Every M/3
24
+ result carries `model=M/3`, its handed parameters and its conditions. The descriptive
25
+ measures are independent of M/3. Nothing changes a state. This document supersedes all
26
+ earlier M/1, M/2 and amendment texts.
27
+
28
+ ## 1. Definition
29
+ Witnesses W (unique identifiers); cells with truth t and integer cardinality n ≥ 2;
30
+ factors F, each with unique identifier, sharing set a_f ⊆ W, firing probability c_f and a
31
+ unique declared index (total order); private error probability p_w for every witness
32
+ involved. Per cell, independently:
33
+ 1. each factor fires independently with probability c_f;
34
+ 2. a witness is governed by the fired factor containing it with the lowest index, if
35
+ any; otherwise its private error fires with probability p_w;
36
+ 3. labels: each fired governing factor is a factor label; each privately erring witness
37
+ is a private label (namespaces are distinct: a factor label and a private label can
38
+ never merge even with identical identifier strings); every label draws one wrong
39
+ value uniformly from the n−1 wrong values; draws of distinct labels are mutually
40
+ independent and independent of all firing and private indicators; everyone else says t.
41
+ Singleton factors (|a_f| = 1) are retained in declared order; the generator is never
42
+ normalized.
43
+
44
+ ## 2. Validation (refuse by name)
45
+ S ⊆ W and S nonempty; every a_f ⊆ W; unique witness and factor identifiers; unique factor
46
+ indices; c_f, p_w ∈ [0,1]; n integer ≥ 2; an explicitly handed p_w for every witness in
47
+ S and in every sharing set touching S; a sharing set with duplicate members is refused.
48
+
49
+ ## 3. Exact evaluator
50
+ Enumerate fired subsets of the factors touching S (2^|touching|) and private patterns of
51
+ ungoverned members of S (2^|free|). In each configuration, erring witnesses are grouped by
52
+ label; L = number of labels; weights = witnesses per label. Collisions of wrong values
53
+ follow set partitions π of the labels with
54
+ P(π) = (n−1)^{↓|π|} / (n−1)^L (falling factorial), and P(π) = 0 when |π| > n−1.
55
+ Each partition yields block totals; unanimity ⇔ no correct witness and one block;
56
+ majority = strictly more than |S|/2 witnesses on one value; ties and pluralities ≤ half
57
+ are "no majority".
58
+ Exactness: all c_f, p_w are handed as rationals (or decimal strings converted exactly);
59
+ accumulation is in rational arithmetic; displayed decimals are rounded half-even to a
60
+ declared number of digits. Budget: before any work, compute
61
+ work = Σ_configurations Bell(L) ≤ `evaluator/budget` (declared); if exceeded, return
62
+ `unmeasured` with cause `evaluator/budget` and no partial accumulation.
63
+ Outputs per (S, x): P_true, P_false (false unanimity), P_fired (false unanimity with some
64
+ touching factor fired), P_dissent = 1 − P_true − P_false (identity, asserted),
65
+ maj_true∧dissent, maj_false∧dissent, maj_none∧dissent (exclusive, sum = P_dissent).
66
+ Closed form admitted only for P_true = Π_{f touches S}(1−c_f) · Π_{w∈S}(1−p_w).
67
+
68
+ ## 4. Quantities and denominators
69
+ ```
70
+ Φ = P_false / (P_true + P_false) false-unanimity share
71
+ D = P_fired / (P_true + P_false) factor-attribution share
72
+ reliability = 1 − Φ, labelled "P(correct | unanimous) under M/3 with handed parameters"
73
+ P(false maj | dissent) = maj_false∧dissent / P_dissent
74
+ P(false maj | any maj ∧ dissent) = maj_false∧dissent / (maj_true∧dissent + maj_false∧dissent)
75
+ ```
76
+ A ratio with zero denominator is `unmeasured` with cause; a zero numerator over a positive
77
+ denominator is a measured 0. Φ − D is private coincidence; 1 − D is never reliability.
78
+
79
+ ## 5. Dissent
80
+ Theorem: if a factor covering S fires and no fired factor of lower index touches S
81
+ partially, S is unanimous; disagreement inside S certifies this configuration did not
82
+ occur — nothing more. False majorities under dissent remain possible through partial
83
+ factors and are reported through the two conditionals above. T1 and T5 stay controlled
84
+ experiments with declared PRNG, seed, trials and denominators (T5 uses the second
85
+ conditional).
86
+
87
+ ## 6. Probe update
88
+ For a witness u private-only and independent of every factor touching S (or, with its
89
+ total marginal error probability, labelled so):
90
+ ```
91
+ a = Φ · p_u/(n−1); b = (1−Φ)·(1−p_u); Φ′ = a/(a+b); unmeasured iff a+b = 0
92
+ ```
93
+ Strict improvement Φ′ < Φ holds for 0 < Φ < 1 iff p_u < (n−1)/n; boundary cases are
94
+ valid (Φ=0, p_u=0.2 → 0; Φ=1, p_u=0.2 → 1; p_u=1 → 1).
95
+
96
+ ## 7. Identification and fitting
97
+ Let, for each witness w,
98
+ ```
99
+ r_w = (1−p_w) · Π_{singleton f ∋ w} (1−c_f) unresolved singleton/private survival
100
+ s_w = r_w · Π_{shared f ∋ w} (1−c_f) total correctness probability
101
+ s_uv = P(e_u = 0 ∧ e_v = 0)
102
+ ```
103
+ Population identification (declared sharing sets, s_u > 0 for every involved witness):
104
+ log(s_uv/(s_u·s_v)) = Σ_{shared f ∋ u,v} −log(1−c_f) is linear in −log(1−c_f); if the
105
+ pair × shared-factor system has full column rank, every shared c_f is identified, and then
106
+ r_w from s_w; r_w's decomposition into p_w and singleton c_f is unresolved by error data.
107
+ Structure is never discovered by a measure. Finite-data fitting is a separate declared
108
+ procedure: constrained least squares on the log system, declared budget, residual
109
+ diagnostics against a declared tolerance, bootstrap uncertainty with declared B/seed/PRNG,
110
+ pooling only under declared parameter compatibility; no pseudocounts, no clamping, no
111
+ promotion of fitted structure; zero joint-correct counts or incompatible moments →
112
+ `model/M misfit`, no c_f reported. Φ and D are reported only with handed parameters and
113
+ labelled `handed`, never `fitted`.
114
+
115
+ ## 8. Time, stake, commonMass
116
+ Freshness and interest enter only as hypothetical factors with declared firing
117
+ probabilities; otherwise annotations and `unmeasured`. Descriptive commonMass is read as
118
+ excess over 1/|S| only as deviation from the equal-variance independent reference; it
119
+ never identifies dependence.
120
+
121
+ ## 9. Captured vectors (exact; rational reference; decimals rounded half-even, 8 digits)
122
+ - two witnesses, covering c=1/20, p=1/5, n=64: P_true 0.608, P_false 0.05060317,
123
+ P_fired 0.05, P_dissent 0.34139683, Φ 0.07683409, D 0.07591825.
124
+ - impossible conditioning (no factors, p_A=0, p_B=1): P_true = P_false = 0, P_dissent 1,
125
+ Φ, D unmeasured (cause: no unanimity mass).
126
+ - three witnesses, covering {A,B,C} c=1/5 idx 0, partial {A,B} c=3/10 idx 1, p=0:
127
+ P_true 0.56, P_false 0.2, P_dissent 0.24, maj_false∧dissent 0.24, Φ = D = 0.26315789,
128
+ P(false maj | dissent) = 1, P(false maj | any maj ∧ dissent) = 1.
129
+ - earlier singleton {A} c=3/10 idx 0, covering {A,B} c=1/5 idx 1, p=1/5: Φ 0.28387293,
130
+ D 0.28316249, P_dissent 0.49953016; merged-singleton no-sample Φ 0.35944805.
131
+ - four witnesses, factors {0,1} and {2,3} each c=1/2, p=0: P_dissent 47/63 = 0.74603175,
132
+ maj_none∧dissent 47/63, P(false maj | dissent) = 0 (measured), P(false maj | any maj ∧
133
+ dissent) unmeasured (no majority mass), Φ = D = 1/64.
134
+ - probe (Φ 0.07683409, n=64): p_u=0.2 → 0.00033; 0.98 → 0.06080; 0.99 → 0.11566; 1 → 1;
135
+ Φ=0,p_u=0.2 → 0; Φ=1,p_u=0.2 → 1.
136
+ - identification: c=1/5, p_A=1/2, p_B=3/8 → c recovered exactly 1/5; (c=1/5,p_A=1,
137
+ p_B=3/8) vs (c=2/5,p_A=1,p_B=1/6) have identical moments → s_A = 0 → unidentified.
138
+ - identity 1 − P_true − P_false = P_dissent holds in every case.
139
+
140
+ ## 10. Open, by name
141
+ Partial value sharing (a factor firing without forcing one value) — a future model;
142
+ probe usefulness beyond the private-only case; discovery of sharing structure (never by a
143
+ measure); adequacy policies (min cells, interval widths, budgets) as declared lines.
144
+
145
+ ## 11. Acceptance
146
+ TypeScript implementation reproduces every captured vector exactly in rational
147
+ arithmetic; validation refuses by name; budget is computed before work; every result
148
+ carries model, handed parameters and conditions; states identical before and after;
149
+ the descriptive 0.4.0 measures and all algebra hashes unchanged.
package/package.json CHANGED
@@ -1,93 +1 @@
1
- {
2
- "name": "@lapxo/obligations",
3
- "version": "0.3.5",
4
- "description": "The algebra of a cell: two poles, origins with phase, eight acts.",
5
- "type": "module",
6
- "license": "MIT",
7
- "author": "Lapxo",
8
- "repository": {
9
- "type": "git",
10
- "url": "git+https://github.com/Lapxo/obligations.git"
11
- },
12
- "keywords": [
13
- "obligations",
14
- "lattice",
15
- "provenance"
16
- ],
17
- "sideEffects": false,
18
- "engines": {
19
- "node": ">=22.12"
20
- },
21
- "exports": {
22
- ".": {
23
- "types": "./dist/lattice/index.d.ts",
24
- "default": "./dist/lattice/index.js"
25
- },
26
- "./debit": {
27
- "types": "./dist/debit/debit.d.ts",
28
- "default": "./dist/debit/debit.js"
29
- },
30
- "./encounter": {
31
- "types": "./dist/field/encounter.d.ts",
32
- "default": "./dist/field/encounter.js"
33
- },
34
- "./field": {
35
- "types": "./dist/field/field.d.ts",
36
- "default": "./dist/field/field.js"
37
- },
38
- "./forms": {
39
- "types": "./dist/lattice/forms.d.ts",
40
- "default": "./dist/lattice/forms.js"
41
- },
42
- "./lattice": {
43
- "types": "./dist/lattice/lattice.d.ts",
44
- "default": "./dist/lattice/lattice.js"
45
- },
46
- "./packed": {
47
- "types": "./dist/debit/packed.d.ts",
48
- "default": "./dist/debit/packed.js"
49
- },
50
- "./present": {
51
- "types": "./dist/field/present.d.ts",
52
- "default": "./dist/field/present.js"
53
- },
54
- "./price": {
55
- "types": "./dist/lattice/price/index.d.ts",
56
- "default": "./dist/lattice/price/index.js"
57
- },
58
- "./replay": {
59
- "types": "./dist/replay.d.ts",
60
- "default": "./dist/replay.js"
61
- },
62
- "./shuffle": {
63
- "types": "./dist/debit/shuffle.d.ts",
64
- "default": "./dist/debit/shuffle.js"
65
- },
66
- "./signatures": {
67
- "types": "./dist/field/signatures.d.ts",
68
- "default": "./dist/field/signatures.js"
69
- },
70
- "./views/field": {
71
- "types": "./dist/views/field.d.ts",
72
- "default": "./dist/views/field.js"
73
- },
74
- "./views/product": {
75
- "types": "./dist/views/product.d.ts",
76
- "default": "./dist/views/product.js"
77
- },
78
- "./package.json": "./package.json"
79
- },
80
- "files": [
81
- "dist",
82
- "README.md",
83
- "LICENSE",
84
- "TARGET.bound"
85
- ],
86
- "scripts": {
87
- "build": "tsc --build"
88
- },
89
- "devDependencies": {
90
- "@types/node": "^22",
91
- "typescript": "^5.9.3"
92
- }
93
- }
1
+ {"name":"@lapxo/obligations","version":"0.4.0","description":"The algebra of a cell: two poles, origins with phase, eight acts.","type":"module","license":"MIT","author":"Lapxo","repository":{"type":"git","url":"git+https://github.com/Lapxo/obligations.git"},"keywords":["obligations","lattice","provenance"],"sideEffects":false,"engines":{"node":">=22.12"},"exports":{".":{"types":"./dist/lattice/index.d.ts","default":"./dist/lattice/index.js"},"./debit":{"types":"./dist/debit/debit.d.ts","default":"./dist/debit/debit.js"},"./encounter":{"types":"./dist/field/encounter.d.ts","default":"./dist/field/encounter.js"},"./field":{"types":"./dist/field/field.d.ts","default":"./dist/field/field.js"},"./forms":{"types":"./dist/lattice/forms.d.ts","default":"./dist/lattice/forms.js"},"./lattice":{"types":"./dist/lattice/lattice.d.ts","default":"./dist/lattice/lattice.js"},"./measures":{"types":"./dist/measures/index.d.ts","default":"./dist/measures/index.js"},"./packed":{"types":"./dist/debit/packed.d.ts","default":"./dist/debit/packed.js"},"./present":{"types":"./dist/field/present.d.ts","default":"./dist/field/present.js"},"./price":{"types":"./dist/lattice/price/index.d.ts","default":"./dist/lattice/price/index.js"},"./replay":{"types":"./dist/replay.d.ts","default":"./dist/replay.js"},"./shuffle":{"types":"./dist/debit/shuffle.d.ts","default":"./dist/debit/shuffle.js"},"./signatures":{"types":"./dist/field/signatures.d.ts","default":"./dist/field/signatures.js"},"./views/field":{"types":"./dist/views/field.d.ts","default":"./dist/views/field.js"},"./views/product":{"types":"./dist/views/product.d.ts","default":"./dist/views/product.js"},"./package.json":"./package.json"},"files":["dist","README.md","LICENSE","TARGET.bound","receipts.bound","docs/measures.md","samples/measures","vectors/measures","samples/yes/algebra-is-closed.json","samples/yes/field-uses-price-and-debit.json","samples/yes/three-theories-one-algebra.json","src/lattice/index.ts","src/field/motion.ts","samples/yes/installed-artifact.json","samples/no/installed-artifact.json","vectors/measures/installed-artifact.cli.json"],"scripts":{"build":"tsc --build","test":"node --import ./test/setup.ts --test --test-concurrency=2 test/*.test.ts test/measures/*.test.ts"},"devDependencies":{"@types/node":"^22","typescript":"^5.9.3"}}